Search Home Members Contacts
About Us
Products
Downloads
Community
Support
Pages: [1]
  Print  
Author Topic: Moving Sun + Dynamic Water  (Read 3225 times)
RiddleMaster
Community Member
*
Posts: 14


« on: April 20, 2004, 11:45:47 AM »

Hi,

I am new to TV, but by no means a new programmer.

I have been working for the past three days on a game and got a good start on it, but like everything in life there are a couple problems.

1)I have made the sun moving, so that it crosses the sky like a real sun would, but I was wondering if anyone figured out how to have the sun drop down?  Like for sun sets/rises!

Right now it goes across the sky till it hits a point then resets at the other side of the sky.

2)I am having alot of trouble with the dynamic water.  I made a height map that has a lake in it, but I cannot get the water to work right.  I have been looking around for an example of how to do dynamic water but havent found anything yet.  Any help on this would be appreciated.

I am using TV with VB6.

Thanks
Logged
CIRCUIT
Customers
Community Member
*****
Posts: 221


« Reply #1 on: April 20, 2004, 02:10:16 PM »

just have the sun revolve around a point. you will have to use TV.TimeElapsed to increment an angle that the sun is currently at and multiplied by the speed of the sun.  As for the water, make sure your card supports it, and check out the "Complete Landscape" tutorial.
Logged
RiddleMaster
Community Member
*
Posts: 14


« Reply #2 on: April 21, 2004, 10:40:31 AM »

I looked at the complete landscape example, but I don't like the results of it, I am looking for the dynamic water, with waves and possibly rain drops effects in it.

I got one going but it doesnt look right, instead of filling in my lake it looks like a line.

Should I use texturemapping(i think thats whut it is) on it??
Logged
regress
Customers
Community Member
*****
Posts: 241


« Reply #3 on: April 21, 2004, 12:09:26 PM »

Sunset and sunrise can be tricky if done right, e.g. if you want the flexibility to change the set/rise times and "move" the sun a bit closer to the scene. Below is an [admittedly somewhat odd] approach I took a few months ago.

Cheers,
Ben
 
Code:

Option Explicit

' ======= Enums ======= '
Public Enum BODY_STYLE
   PLANET_TYPE = 0
   SUN_TYPE = 1
   MOON_TYPE = 2
End Enum

' ======= Internal Constants ======= '
Private Const PI = 3.14159265358979
Private Const PI2 = PI * 2
Private Const PI_2 = PI / 2

' ======= Read-Write ======= '
'Number of seconds in a day
Private m_SecondsPerDay As Long

'Center position from which the orbital path will be calculated
Private m_Origin        As D3DVECTOR

'Starting radius, which is the radius of the orbital path
'at a rise of 25% of seconds per day and a set of 75% of
'seconds per day (level with the horizon on both ends).
'For example, with a rise of .25 and a set of .75,
'the ending radius (m_SkyRadius) calculated in Change()
'would be the same as the StartSkyRadius here; any variance
'from those percentages, and m_SkyRadius changes
Private m_StartSkyRadius   As Single
Private m_StartEarthRadius As Single

'Rise time, expressed as a % of seconds per day
Private m_RiseTime      As Single

'Set time, expressed as a % of seconds per day
Private m_SetTime       As Single

'Name for this astronomical body
Private m_Name          As String

'Description for this astronomical body
Private m_Description   As String

'Useful for for a tool/gui
Private m_Style         As BODY_STYLE

' ======= Read-Only ======= '

'Current orbital position after Change()
Private m_Position As D3DVECTOR

'Current light direction after Change()
Private m_LightDirection As D3DVECTOR

'Current Rotation (on either x or z axis)
Private m_Rotation As D3DVECTOR

'Current light value after Change()- useful for color calculations
Private m_LightValue    As Single

'Span between rise and set, expressed as a % of seconds per day
Private m_TimeSpan      As Single

'Adjusted sky radius after ComputeOffsets()
Private m_SkyRadius     As Single

'Adjusted earth radius after ComputeOffsets()
Private m_EarthRadius   As Single

'Angular velocity offset after ComputeOffsets()
Private m_Offset        As Single

'Height offset after ComputeOffsets()
Private m_HeightOffset  As Single

'Angular velocity
Private m_AngVel        As Single

'Flag for whether or not the current second is between rise and set times, after Change()
Private m_IsDayLight    As Boolean

'Flag for whether or not the current second is in rising range, after Change()
Private m_IsRising      As Boolean

'Flag for whether or not the current second is in setting range, after Change()
Private m_IsSetting     As Boolean

'The "range" in which rising takes place
Private m_RiseRange     As Single

'The "range" in which setting takes place
Private m_SetRange      As Single

'Value of where we're at either during a rise or a set, expressed in a % of the
'total rise or set range; this % will increase from the beginning of the range until
'actual rise or set, and will decrease afterwards to 0. Other than during rise or set
'ranges, the value hence always return 0.
Private m_RangeProgress As Single

'One light per orbital body
Private m_Light         As D3DLIGHT8

' ======= Internal ======= '
Private m_PIPos         As Single
Private m_RiseSecond    As Single
Private m_SetSecond     As Single
Private m_RiseBound(1)  As Long
Private m_SetBound(1)   As Long
Private m_RiseHalf      As Long
Private m_SetHalf       As Long

Private m_RotateOrbit   As Single
Private m_MatRotate     As D3DMATRIX

' ======= Pubic Procedures ======= '

'Required - once called, you can change the storage varibles with property calls
Public Sub Init(SecondsPerDay As Long, Origin As D3DVECTOR, StartingSkyRadius As Single, _
                StartingEarthRadius As Single, RiseTime As Single, SetTime As Single, _
                Optional RotateInDegrees As Single = 0, Optional RiseRange As Single = 0.2, _
                Optional SetRange As Single = 0.2)
               
'Orbit Rotation. By default (with a value of 0) the orbit rotates down the middle of the x-axis (E-W)
m_RotateOrbit = Deg2Rad(RotateInDegrees)
D3DXMatrixIdentity m_MatRotate
               
'Total number of seconds in one day
m_SecondsPerDay = SecondsPerDay

'Angular velocity
m_AngVel = (PI2 / m_SecondsPerDay)

'Center origin coords
m_Origin = Origin

'Rise and set times, expressed as a % of seconds per day
m_RiseTime = RiseTime: m_SetTime = SetTime

'Rise and set times, expressed as number of seconds
m_RiseSecond = m_SecondsPerDay * m_RiseTime
m_SetSecond = m_SecondsPerDay * m_SetTime

'Rise and set ranges, expressed as a % of seconds per day - clamped at .5
m_RiseRange = RiseRange
m_SetRange = SetRange
If m_RiseRange > 0.5 Then m_RiseRange = 0.5
If m_SetRange > 0.5 Then m_SetRange = 0.5
If m_RiseRange < 0.001 Then m_RiseRange = 0.001
If m_SetRange < 0.001 Then m_SetRange = 0.001

'Starting radius - this will be adjusted to a new radius depending on the rise/set times
m_StartSkyRadius = StartingSkyRadius
m_StartEarthRadius = StartingEarthRadius

'Call the procedure to calculate offsets
ComputeOffsets

End Sub

'Computes a new orbital position, light position and light value for current second
Public Sub Change(Second As Long)

'Get the current angular position
m_PIPos = PI2 * (Second / m_SecondsPerDay)

'Store the rotation angle
m_Rotation.x = Cos(m_PIPos - m_Offset)
m_Rotation.y = Sin(m_PIPos - m_Offset)
m_Rotation.z = 0

'Calculate orbit position
With m_Position
   .x = m_Origin.x + m_Rotation.x * m_EarthRadius
   .y = m_Origin.y + m_HeightOffset + m_Rotation.y * m_SkyRadius
   .z = m_Origin.z + m_Rotation.z
End With

'Adjust the rotation of the orbit on the y-axis to your desire
D3DXMatrixRotationY m_MatRotate, m_RotateOrbit
D3DXVec3TransformCoord m_Position, m_Position, m_MatRotate


D3DXVec3Normalize m_Rotation, m_Position
D3DXVec3TransformCoord m_Rotation, m_Rotation, m_MatRotate

'Calcultate lighting direction
D3DXVec3Scale m_LightDirection, m_Position, -1
D3DXVec3Normalize m_LightDirection, m_LightDirection
m_Light.Direction = m_LightDirection
'Calculate appropriate light values for color - the light value is offset
'to push the values closer to 1 (maximum value) between rise and set
'
'The curve is something like:
'
'    ''''''''''''''''''''
'   '                    '
'  '                      '
'
'Whereas, the actual positioning of the
'astronomical body (and light direction) is a circle,
'adjusted for rise and set times, e.g. with an adjusted
'radius and moved up or down
m_LightValue = -Cos(m_PIPos) * 0.5 + 0.5

If Second > m_RiseSecond And Second < m_SetSecond Then
   m_LightValue = m_LightValue + 0.1
   m_IsDayLight = True
Else
   m_IsDayLight = False
End If

If m_LightValue > 1 Then m_LightValue = 1

If Second > m_RiseBound(0) And Second <= m_RiseSecond Then
   m_IsRising = True
   m_RangeProgress = 1 - (Second - m_RiseBound(0)) / m_RiseHalf
ElseIf Second > m_RiseSecond And Second < m_RiseBound(1) Then
   m_IsRising = True
   m_RangeProgress = 1 - (m_RiseBound(1) - Second) / m_RiseHalf

ElseIf Second > m_SetBound(0) And Second < m_SetSecond Then
   m_IsSetting = True
   m_RangeProgress = 1 - (Second - m_SetBound(0)) / m_SetHalf
ElseIf Second > m_SetSecond And Second <= m_SetBound(1) Then
   m_IsSetting = True
   m_RangeProgress = 1 - (m_SetBound(1) - Second) / m_SetHalf
Else
   m_RangeProgress = 0
   m_IsRising = False
   m_IsSetting = False
End If

End Sub

' ======= Internal Procedures ======= '

'Computes a new radius, height offset and rise/set time offset
Private Sub ComputeOffsets()
On Error GoTo ExitErr

Dim pSpan As Single, ySign As Integer

'Span in seconds
If m_SetTime > m_RiseTime Then
   m_TimeSpan = m_SetTime - m_RiseTime
Else
   m_TimeSpan = m_SetTime + (1 - m_RiseTime)
End If

'Rise and set lower and upper bounds, expressed as number of seconds
m_RiseHalf = m_SecondsPerDay * (m_RiseRange * 0.5)
m_SetHalf = m_SecondsPerDay * (m_SetRange * 0.5)
m_RiseBound(0) = m_RiseSecond - m_RiseHalf
m_RiseBound(1) = m_RiseSecond + m_RiseHalf
m_SetBound(0) = m_SetSecond - m_SetHalf
m_SetBound(1) = m_SetSecond + m_SetHalf

'Rise time converted to rad
pSpan = (m_SecondsPerDay * m_TimeSpan) * m_AngVel

'This is the offset to make everything work!
m_Offset = ((m_RiseSecond * m_AngVel) + (pSpan / 2)) - PI_2

'Sine rule from basic trig
m_SkyRadius = (m_StartSkyRadius * Sin(PI_2)) / Sin(pSpan / 2)
m_EarthRadius = (m_StartEarthRadius * Sin(PI_2)) / Sin(pSpan / 2)

'Change direction if portion of the circle is larger rather than smaller
If pSpan < PI Then ySign = -1 Else ySign = 1

'Height offset to translate the orbital path along y
m_HeightOffset = (Sqr(m_SkyRadius ^ 2 - m_StartSkyRadius ^ 2) * ySign)

ExitErr:
Exit Sub
End Sub

' ======= Read-Only Functions ======= '

'Returns the current orbital position - should be called AFTER Change()
Public Function Position() As D3DVECTOR
Position = m_Position
End Function

'Returns the current light direction - should be called AFTER Change()
Public Function LightDirection() As D3DVECTOR
LightDirection = m_LightDirection
End Function

'Returns the current orbital rotation - should be called AFTER Change()
Public Function Rotation() As D3DVECTOR
Rotation = m_Rotation
End Function

'Returns the current light value for color calculations - should be called AFTER Change()
Public Function LightValue() As Single
LightValue = m_LightValue
End Function

'Returns the span between rise and set, expressed as a % of seconds per day
Public Function TimeSpan() As Single
TimeSpan = m_TimeSpan
End Function

'Returns the adjusted radius - could be useful for drawing a circular path for a tool
Public Function SkyRadius() As Single
SkyRadius = m_SkyRadius
End Function

'Returns the adjusted radius - could be useful for drawing a circular path for a tool
Public Function EarthRadius() As Single
EarthRadius = m_EarthRadius
End Function

'Returns the height offest - could be useful for drawing a circular path for a tool
Public Function HeightOffset() As Single
HeightOffset = m_HeightOffset
End Function

'Returns the angular velocity - could be useful for other lighting calculations
Public Function AngularVelocity() As Single
AngularVelocity = m_AngVel
End Function

'Returns if we are between rise and set times - useful for knowing when to switch/blend
'textures, for example - should be called AFTER Change()
Public Function IsDayLight() As Boolean
IsDayLight = m_IsDayLight
End Function

' ======= Read/Write Properties ======= '

'Returns/Sets the D3DLight8 structure
Public Property Get Light() As D3DLIGHT8
Light = m_Light
End Property
Public Property Let Light(New_Light As D3DLIGHT8)
m_Light = New_Light
End Property

'Returns/Sets the number of seconds in a day
Public Property Get SecondsPerDay() As Long
SecondsPerDay = m_SecondsPerDay
End Property
Public Property Let SecondsPerDay(New_SecondsPerDay As Long)
m_SecondsPerDay = New_SecondsPerDay
If m_SecondsPerDay < 1 Then m_SecondsPerDay = 1
ComputeOffsets
End Property

'Returns/Sets the origin coordinates
Public Property Get Origin() As D3DVECTOR
Origin = m_Origin
End Property
Public Property Let Origin(New_Origin As D3DVECTOR)
m_Origin = New_Origin
ComputeOffsets
End Property

'Returns/Sets a new starting radius, which is the radius of the orbital path
'at a rise of 25% of seconds per day and a set of 75% of seconds per day
'For example, with a rise of .25 and a set of .75, the ending radius (m_SkyRadius)
'calculated in Change() would be the same as the StartSkyRadius here; any variance
'from those percentages, and m_SkyRadius changes
Public Property Get StartSkyRadius() As Single
StartSkyRadius = m_StartSkyRadius
End Property
Public Property Let StartSkyRadius(New_StartSkyRadius As Single)
m_StartSkyRadius = New_StartSkyRadius
ComputeOffsets
End Property
Public Property Get StartEarthRadius() As Single
StartEarthRadius = m_StartEarthRadius
End Property
Public Property Let StartEarthRadius(New_StartEarthRadius As Single)
m_StartEarthRadius = New_StartEarthRadius
ComputeOffsets
End Property

'Returns/Sets the rise time, expressed as a % of seconds per day
Public Property Get RiseTime() As Single
RiseTime = m_RiseTime
End Property
Public Property Let RiseTime(New_RiseTime As Single)
m_RiseTime = New_RiseTime
ComputeOffsets
End Property

'Returns/Sets the set time, expressed as a % of seconds per day
Public Property Get SetTime() As Single
SetTime = m_SetTime
End Property
Public Property Let SetTime(New_SetTime As Single)
m_SetTime = New_SetTime
ComputeOffsets
End Property

'Returns/Sets a name for this astronomical body
Public Property Get Name() As String
Name = m_Name
End Property
Public Property Let Name(New_Name As String)
m_Name = New_Name
End Property

'Returns/Sets a description for this astronomical body
Public Property Get Description() As String
Description = m_Description
End Property
Public Property Let Description(New_Description As String)
m_Description = New_Description
End Property

'Returns/Sets a "style" - useful for for a tool/gui
Public Property Get Style() As BODY_STYLE
Style = m_Style
End Property
Public Property Let Style(New_Style As BODY_STYLE)
m_Style = New_Style
End Property

Private Sub Class_Initialize()
With m_Light
   .Type = D3DLIGHT_DIRECTIONAL
   .Diffuse = DXColor(1, 1, 1, 1)
   .Ambient = DXColor(1, 1, 1, 1)
   .Specular = DXColor(1, 1, 1, 1)
End With
End Sub

'The "range" in which rising takes place
Public Property Get RiseRange() As Single
RiseRange = m_RiseRange
End Property
Public Property Let RiseRange(New_RiseRange As Single)
m_RiseRange = New_RiseRange
If m_RiseRange < 0.001 Then m_RiseRange = 0.001
ComputeOffsets
End Property

'The "range" in which setting takes place
Public Property Get SetRange() As Single
SetRange = m_SetRange
End Property
Public Property Let SetRange(New_SetRange As Single)
m_SetRange = New_SetRange
If m_SetRange < 0.001 Then m_SetRange = 0.001
ComputeOffsets
End Property

'Returns if we are in the rising range - should be called AFTER Change()
Public Function IsRising() As Boolean
IsRising = m_IsRising
End Function

'Returns if we are in the setting range - should be called AFTER Change()
Public Function IsSetting() As Boolean
IsSetting = m_IsSetting
End Function

'Returns the current rise or set range progress - should be called AFTER Change()
Public Function RangeProgress() As Single
RangeProgress = m_RangeProgress
End Function
Logged
regress
Customers
Community Member
*****
Posts: 241


« Reply #4 on: April 30, 2004, 05:58:01 PM »

BTW, if anyone has the time/inclination to try this class above and wants to provide feedback, I'd love to hear it!

Cheers,
Ben
Logged
Pages: [1]
  Print  
 
Jump to:  

Powered by SMF 1.1.3 | SMF © 2006-2007, Simple Machines LLC
Seo4Smf v0.2 © Webmaster's Talks