Files
Client/Library/dxx8/samples/Multimedia/VBSamples/Direct3D/PointSprites/D3DParticle.cls
LGram16 e067522598 Initial commit: ROW Client source code
Game client codebase including:
- CharacterActionControl: Character and creature management
- GlobalScript: Network, items, skills, quests, utilities
- RYLClient: Main client application with GUI and event handlers
- Engine: 3D rendering engine (RYLGL)
- MemoryManager: Custom memory allocation
- Library: Third-party dependencies (DirectX, boost, etc.)
- Tools: Development utilities

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-29 16:24:34 +09:00

604 lines
18 KiB
OpenEdge ABL

VERSION 1.0 CLASS
BEGIN
MultiUse = -1 'True
Persistable = 0 'NotPersistable
DataBindingBehavior = 0 'vbNone
DataSourceBehavior = 0 'vbNone
MTSTransactionMode = 0 'NotAnMTSObject
END
Attribute VB_Name = "CParticle"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = True
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Option Explicit
'-----------------------------------------------------------------------------
' Global data for the particles
'-----------------------------------------------------------------------------
Private Type CUSTOMVERTEX
v As D3DVECTOR
color As Long
tu As Single
tv As Single
End Type
Const D3DFVF_COLORVERTEX = (D3DFVF_XYZ Or D3DFVF_DIFFUSE Or D3DFVF_TEX1)
Private Type PARTICLE
m_bSpark As Boolean ' Spark? or real particle?
m_vPos As D3DVECTOR ' Current position
m_vVel As D3DVECTOR ' Current velocity
m_vPos0 As D3DVECTOR ' Initial Position
m_vVel0 As D3DVECTOR ' Initial Velocity
m_fTime0 As Single ' Time of creation
m_clrDiffuse As D3DCOLORVALUE ' Initial diffuse color
m_clrFade As D3DCOLORVALUE ' Faded diffuse color
m_fFade As Single ' Fade progression
iNext As Long ' Next particle in list
End Type
Dim m_Particles() As PARTICLE 'we leave 0 element unused to make code convenient
'so think of this as a 1 based array
Dim m_fRadius As Single
Dim m_MaxParticles As Long
Dim m_NumParticles As Long
Dim m_ParticlesLim As Long
Dim m_iFree As Long 'index of first free particle (0 = empty)
Dim m_iUsed As Long 'index of first particle in list (0 = empty)
Dim m_iLast As Long
'Geometry
Dim m_VertB As Direct3DVertexBuffer8
Dim m_IndxB As Direct3DIndexBuffer8
Dim m_Verts() As CUSTOMVERTEX
Dim m_binit As Boolean
'-----------------------------------------------------------------------------
' Name: Init
' Desc:
'-----------------------------------------------------------------------------
Sub Init(MaxParticles As Long, fRadius As Single)
m_fRadius = fRadius
m_MaxParticles = MaxParticles
m_NumParticles = 0
m_ParticlesLim = 1800
m_iFree = 0
m_iUsed = 0
Set m_VertB = Nothing
Set m_IndxB = Nothing
m_binit = True
ReDim m_Verts(MaxParticles * 6)
ReDim m_Particles(m_ParticlesLim)
End Sub
'-----------------------------------------------------------------------------
' Name: InitDeviceObjects
' Desc:
'-----------------------------------------------------------------------------
Sub InitDeviceObjects(dev As Direct3DDevice8)
Dim v As CUSTOMVERTEX
Dim j As Long, i As Long
Dim indices() As Integer
Dim indxbuffsize As Long
' Create the particle system's vertex buffer and index buffer.
' Each particle requires four vertices and 6 indices
Set m_VertB = dev.CreateVertexBuffer(4 * m_MaxParticles * Len(v), D3DUSAGE_SOFTWAREPROCESSING, D3DFVF_COLORVERTEX, D3DPOOL_MANAGED)
indxbuffsize = 6 * m_MaxParticles * 4 'each entry is 4 bytes (vb integer)
Set m_IndxB = dev.CreateIndexBuffer(indxbuffsize, D3DUSAGE_SOFTWAREPROCESSING, D3DFMT_INDEX16, D3DPOOL_MANAGED)
' Fill the index buffer
ReDim indices(6 * m_MaxParticles) 'we have 2 triangles per particle
j = 0
For i = 0 To m_MaxParticles - 1
indices(j) = 4 * i + 0: j = j + 1
indices(j) = 4 * i + 3: j = j + 1
indices(j) = 4 * i + 1: j = j + 1
indices(j) = 4 * i + 1: j = j + 1
indices(j) = 4 * i + 3: j = j + 1
indices(j) = 4 * i + 2: j = j + 1
Next
' Set the data on the d3d buffer
D3DIndexBuffer8SetData m_IndxB, 0, indxbuffsize, 0, indices(0)
End Sub
'-----------------------------------------------------------------------------
' Name: DeleteDeviceObjects
' Desc:
'-----------------------------------------------------------------------------
Sub DeleteDeviceObjects()
Set m_VertB = Nothing
Set m_IndxB = Nothing
End Sub
'-----------------------------------------------------------------------------
' Name: Class_Terminate
' Desc:
'-----------------------------------------------------------------------------
Private Sub Class_Terminate()
DeleteDeviceObjects
ReDim m_Particles(0)
End Sub
'-----------------------------------------------------------------------------
' Name:
' Desc:
'-----------------------------------------------------------------------------
Sub Update(fSecsPerFrame As Single, NumParticlesToEmit As Long, _
clrEmitColor As D3DCOLORVALUE, _
clrFadeColor As D3DCOLORVALUE, _
fEmitVel As Single, _
vPosition As D3DVECTOR)
If m_binit = False Then Exit Sub
Static fTime As Single
Dim i As Long
Dim iSpark As Long, inew As Long
Dim fRand1 As Single, fRand2 As Single
'advance simulation
fTime = fTime + fSecsPerFrame
Dim iCurrent As Long
Dim iPrevious As Long
iCurrent = m_iUsed
iPrevious = 0
'For each particle in the In Use list ...
'calculate its age and test if the particle is too old
Do While (iCurrent > 0)
With m_Particles(iCurrent)
Dim ft As Single
Dim fGravity As Single
'Calculate current lifetime
ft = fTime - .m_fTime0
'normal particle become sparks at the end of their
'life time and have different behaviour
'that we define here
If .m_bSpark Then
'sparks float higher and fade faster
fGravity = -5#
.m_fFade = .m_fFade - fSecsPerFrame * 2.25
Else
'other particles fall to ground faster but live longer
fGravity = -9.8
End If
'Our newposition computed from velocity and initial position
'pNew=pInit+t*velocity + accl * t * t
'the first terms
.m_vPos.x = .m_vVel0.x * ft + .m_vPos0.x
.m_vPos.y = .m_vVel0.y * ft + .m_vPos0.y
.m_vPos.z = .m_vVel0.z * ft + .m_vPos0.z
'we add gravity in for the accleration terms on y axis
.m_vPos.y = .m_vPos.y + (0.5 * fGravity) * (ft * ft)
'compute new Velocity given acceleartion
'vNew=vInit+t*vCurrent
.m_vVel.y = .m_vVel0.y + fGravity * ft
'clamp fading to zero
If (.m_fFade < 0#) Then .m_fFade = 0
'Normal particles die and turn into 5 sparks when they are
'above a certain height from the ground
'Sparks die when they fall below the surface
'We test here if any particle is dead
If (.m_vPos.y < m_fRadius) Then '
'if we have a normal particle
'lets turn it into 5 sparks
If (Not .m_bSpark) Then
For i = 0 To 4
'If there are particles in the free list, use them
If (m_iFree) Then
iSpark = m_iFree
m_iFree = m_Particles(m_iFree).iNext
'other wise get a new one
Else
If m_iLast >= m_ParticlesLim Then
' 'm_bReset = True
Exit For
End If
m_iLast = m_iLast + 1
iSpark = m_iLast
End If
'put this new particle on the used list
m_Particles(iSpark).iNext = m_iUsed
m_iUsed = iSpark
m_NumParticles = m_NumParticles + 1
'have the spark start out in the same position
'as where the normal particle is now
m_Particles(iSpark).m_bSpark = True
m_Particles(iSpark).m_vPos0 = .m_vPos
m_Particles(iSpark).m_vPos0.y = m_fRadius
fRand1 = Rnd(1) * g_pi * 2
fRand2 = Rnd(1) * g_pi * 0.25
'have the sparks velocity vere off from the normal particle
m_Particles(iSpark).m_vVel0.x = .m_vVel.x * 0.25 + Cos(fRand1) * Sin(fRand2)
m_Particles(iSpark).m_vVel0.z = .m_vVel.z * 0.25 + Sin(fRand1) * Sin(fRand2)
m_Particles(iSpark).m_vVel0.y = Cos(fRand2) * Rnd(1) * 1.5
'set the sparks current position = initial position
'set the sparks current velocitu = initial velocity
m_Particles(iSpark).m_vPos = .m_vPos0
m_Particles(iSpark).m_vVel = .m_vVel0
' set the initial color of the particle to be that of
'what it was as a normal particle
D3DXColorLerp m_Particles(iSpark).m_clrDiffuse, .m_clrFade, .m_clrDiffuse, .m_fFade
'set the spark to fade to blue
m_Particles(iSpark).m_clrFade = ColorValue4(0#, 0#, 0#, 1#)
'set its life time indicator to be newly created
m_Particles(iSpark).m_fFade = 1#
'save the time of creation
m_Particles(iSpark).m_fTime0 = fTime
Next
End If
' Kill the current particle
'remove it form used list
'put it on free list
If iPrevious > 0 Then
m_Particles(iPrevious).iNext = .iNext
Else
m_iUsed = .iNext
End If
Dim iTemp As Long
iTemp = .iNext
.iNext = m_iFree
m_iFree = iCurrent
iCurrent = iTemp
m_NumParticles = m_NumParticles - 1
Else
iPrevious = iCurrent
iCurrent = .iNext
End If
End With
Loop
' Emit new particles
Dim NumParticlesEmit As Long
NumParticlesEmit = m_NumParticles + NumParticlesToEmit
Do While (m_NumParticles < m_ParticlesLim And m_NumParticles < NumParticlesEmit)
' If there is a particle in the free list, use it
If (m_iFree) Then
inew = m_iFree
m_iFree = m_Particles(m_iFree).iNext
'other wise get an new one
Else
If m_iLast >= m_ParticlesLim Then
Exit Do
End If
m_iLast = m_iLast + 1
inew = m_iLast
End If
'put it on the used list
'put this new particle on the used list
m_Particles(inew).iNext = m_iUsed
m_iUsed = inew
m_NumParticles = m_NumParticles + 1
' Emit new particle
fRand1 = Rnd(1) * g_pi * 2
fRand2 = Rnd(1) * g_pi * 0.25
With m_Particles(inew)
.m_bSpark = False
D3DXVec3Add .m_vPos0, vPosition, vec3(0, m_fRadius, 0)
.m_vVel0.x = Cos(fRand1) * Sin(fRand2) * 2.5
.m_vVel0.z = Sin(fRand1) * Sin(fRand2) * 2.5
.m_vVel0.y = Cos(fRand2) * (Rnd(1) * fEmitVel)
.m_vPos = .m_vPos0
.m_vVel = .m_vVel0
.m_clrDiffuse = clrEmitColor
.m_clrFade = clrFadeColor
.m_fFade = 1
.m_fTime0 = fTime
End With
Loop
End Sub
'-----------------------------------------------------------------------------
' Name: Render()
' Desc: Renders the particle system using either pointsprites
'
'-----------------------------------------------------------------------------
Sub Render(dev As Direct3DDevice8)
Dim v As CUSTOMVERTEX
Dim iCurrent As Long, i As Long
With dev
Dim DWFloat0 As Long
Dim DWFloat1 As Long
Dim DWFloatp08 As Long
DWFloat0 = FtoDW(0)
DWFloat1 = FtoDW(1)
DWFloatp08 = FtoDW(0.08)
' Set the render states for using point sprites
.SetRenderState D3DRS_POINTSPRITE_ENABLE, 1 'True
.SetRenderState D3DRS_POINTSCALE_ENABLE, 1 'True
.SetRenderState D3DRS_POINTSIZE, DWFloatp08
.SetRenderState D3DRS_POINTSIZE_MIN, DWFloat0
.SetRenderState D3DRS_POINTSCALE_A, DWFloat0
.SetRenderState D3DRS_POINTSCALE_B, DWFloat0
.SetRenderState D3DRS_POINTSCALE_C, DWFloat1
' Set up the vertex buffer to be rendered
.SetStreamSource 0, m_VertB, Len(v)
.SetVertexShader D3DFVF_COLORVERTEX
End With
Dim NumParticlesToRender As Long
' Render each particle
iCurrent = m_iUsed
Dim vPos As D3DVECTOR, vVel As D3DVECTOR
Dim fLengthSq As Single, steps As Long
Do While (iCurrent <> 0)
With m_Particles(iCurrent)
vPos = .m_vPos
vVel = .m_vVel
fLengthSq = D3DXVec3LengthSq(vVel)
If (fLengthSq < 1#) Then
steps = 2
ElseIf (fLengthSq < 4#) Then
steps = 3
ElseIf (fLengthSq < 9#) Then
steps = 4
ElseIf (fLengthSq < 12.25) Then
steps = 5
ElseIf (fLengthSq < 16#) Then
steps = 6
ElseIf (fLengthSq < 20.25) Then
steps = 7
Else
steps = 8
End If
D3DXVec3Scale vVel, vVel, (-0.04 / steps)
Dim clrDiffuse As D3DCOLORVALUE
D3DXColorLerp clrDiffuse, .m_clrFade, .m_clrDiffuse, .m_fFade
Dim clrDiffuseLong As Long
clrDiffuseLong = D3DCOLORVALUEtoLONG(clrDiffuse)
Dim iVert As Long
' Render each particle a bunch of times to get a blurring effect
For i = 0 To steps - 1
m_Verts(iVert).v = vPos
m_Verts(iVert).color = clrDiffuseLong
NumParticlesToRender = NumParticlesToRender + 1
iVert = iVert + 1
If (NumParticlesToRender = m_MaxParticles) Then
' we have a full Vertex buffer
D3DVertexBuffer8SetData m_VertB, 0, Len(v) * m_MaxParticles, 0, m_Verts(0)
dev.DrawPrimitive D3DPT_POINTLIST, 0, NumParticlesToRender
NumParticlesToRender = 0
iVert = 0
End If
D3DXVec3Add vPos, vPos, vVel
Next
iCurrent = .iNext
End With
Loop
' Render any remaining particles
If (NumParticlesToRender <> 0) Then
D3DVertexBuffer8SetData m_VertB, 0, Len(v) * NumParticlesToRender, 0, m_Verts(0)
g_dev.DrawPrimitive D3DPT_POINTLIST, 0, NumParticlesToRender
End If
' Reset render states
g_dev.SetRenderState D3DRS_POINTSPRITE_ENABLE, 0 'False
g_dev.SetRenderState D3DRS_POINTSCALE_ENABLE, 0 'False
End Sub
'-----------------------------------------------------------------------------
' Name: RenderLights
' Desc:
'-----------------------------------------------------------------------------
Sub RenderLights(dev As Direct3DDevice8)
Dim vTL As D3DVECTOR, vBL As D3DVECTOR, vBR As D3DVECTOR, vTR As D3DVECTOR
Dim v As CUSTOMVERTEX
vTL = vec3(-1, 0, 1): vBL = vec3(-1, 0, -1)
vBR = vec3(1, 0, -1): vTR = vec3(1, 0, 1)
With dev
.SetStreamSource 0, m_VertB, Len(v)
.SetVertexShader D3DFVF_COLORVERTEX
.SetIndices m_IndxB, 0
End With
Dim iCurrent As Long
Dim NumParticlesToRender
Dim fY As Single
Dim fSize As Single
Dim clrDiffuse As D3DCOLORVALUE
Dim clrDiffuseTemp As D3DCOLORVALUE
Dim lngDiffuse As Long
Dim vPos As D3DVECTOR
Dim vTemp As D3DVECTOR
Dim j As Long
iCurrent = m_iUsed
Do While (iCurrent <> 0)
With m_Particles(iCurrent)
fY = .m_vPos.y
'if the particle is close to the ground we will add some lights effects
If (fY < 1) Then
'make sure particle cant go below ground
If (fY < 0) Then fY = 0
fSize = fY * 0.25 + m_fRadius
D3DXColorLerp clrDiffuse, .m_clrFade, .m_clrDiffuse, .m_fFade
D3DXColorScale clrDiffuseTemp, clrDiffuse, (1 - fY) * 0.5
lngDiffuse = D3DCOLORVALUEtoLONG(clrDiffuseTemp)
vPos = vec3(.m_vPos.x, 0#, .m_vPos.z)
D3DXVec3Scale vTemp, vTR, fSize
D3DXVec3Add m_Verts(j).v, vPos, vTemp
m_Verts(j).color = lngDiffuse
m_Verts(j).tu = 0: m_Verts(j).tv = 0
j = j + 1
D3DXVec3Scale vTemp, vBR, fSize
D3DXVec3Add m_Verts(j).v, vPos, vTemp
m_Verts(j).color = lngDiffuse
m_Verts(j).tu = 0: m_Verts(j).tv = 1
j = j + 1
D3DXVec3Scale vTemp, vBL, fSize
D3DXVec3Add m_Verts(j).v, vPos, vTemp
m_Verts(j).color = lngDiffuse
m_Verts(j).tu = 1: m_Verts(j).tv = 1
j = j + 1
D3DXVec3Scale vTemp, vTL, fSize
D3DXVec3Add m_Verts(j).v, vPos, vTemp
m_Verts(j).color = lngDiffuse
m_Verts(j).tu = 1: m_Verts(j).tv = 0
j = j + 1
NumParticlesToRender = NumParticlesToRender + 1
If (NumParticlesToRender = m_MaxParticles) Then
D3DVertexBuffer8SetData m_VertB, 0, Len(v) * 4 * NumParticlesToRender, 0, m_Verts(0)
dev.DrawIndexedPrimitive D3DPT_TRIANGLELIST, _
0, NumParticlesToRender * 4, _
0, NumParticlesToRender * 2
NumParticlesToRender = 0
j = 0
End If
End If
iCurrent = .iNext
End With
Loop
' Render remaining particles
If (NumParticlesToRender <> 0) Then
D3DVertexBuffer8SetData m_VertB, 0, Len(v) * 4 * NumParticlesToRender, 0, m_Verts(0)
dev.DrawIndexedPrimitive D3DPT_TRIANGLELIST, _
0, NumParticlesToRender * 4, _
0, NumParticlesToRender * 2
End If
End Sub