I recently began (seriously) working with particle systems and it occured to me that for things like smoke the particles should be allow to swirl and expand. My bright idea to handle this was to use spherical coordinates for their positions and velocities, then translate and stuff them into a VB for D3D. Everything''s working just fine, but then as phi (angle in the xz plane) approaches pi, things begin to go funky, and my particles either collapse in to one point, or just start blinking and spazing. Relevant code:
To convert from spherical to Cartesian:
D3DXVECTOR3 PolarToCartesian(D3DXVECTOR3 polar)
{
D3DXVECTOR3 pt;
pt.x = sinf(polar.z) * cosf(polar.y);
pt.y = sinf(polar.y) * sinf(polar.z);
pt.z = cosf(polar.z);
pt *= polar.x;
return pt;
}
To convert from Cartesian to spherical:
D3DXVECTOR3 CartesianToPolar(D3DXVECTOR3 p)
{
if(p.x == 0.0f)
p.x = 0.001f;
if(p.z == 0.0f)
p.z = 0.001f;
D3DXVECTOR3 r;
r.x = D3DXVec3Length(&p);
r.y = atan2f(p.y, p.x);
r.z = atan2f(sqrtf(p.x*p.x + p.y*p.y), p.z);
if(fabsf(r.x) < 0.01f)
r.x = 0.0f;
if(fabsf(r.y) < 0.01f)
r.y = 0.0f;
if(fabsf(r.z) < 0.01f)
r.z = 0.0f;
return r;
}
And the VB stuffing code:
void PARTICLEEMITTER::Update(float elapsed)
{
for(DWORD i=0;i<m_NumParticles;i++)
{
m_Particles[i].m_Age += elapsed;
if(m_Particles[i].m_PolarUpdate == false)
{
m_Particles[i].m_Position += m_Particles[i].m_PolarVelocity*elapsed;
}
else
{
m_Particles[i].m_Position = PolarToCartesian(CartesianToPolar(m_Particles[i].m_Position) + m_Particles[i].m_PolarVelocity*elapsed);
}
}
PARTICLEVERTEX* pVertices;
HRESULT h = m_pVB->Lock(0, 0, (void**)&pVertices, 0);
for(DWORD i=0; i < m_NumParticles; i++)
{
pVertices[i].diffuse = m_Particles[i].m_Color;
pVertices[i].pos = m_Particles[i].m_Position;
}
m_pVB->Unlock();
}
1) Why exactly would such a thing happen?
2) How could it be corrected?
3) Anything look funny in that code?
Thanks for your time,
ms