Cubic Splines for use in Dead Reckoning
Hi,
I''m making a real time 3d (uses only x and z coordinates though) multiplayer hover tank game using C++ and directplay...
I need to know how to IMPLIMENT cubic splines. I''ve read the gamedev article on it, now i just need to know how to code it.
If someone could please show me some code then i would be eternally gratefull...
--m_nPostCount++
Could someone check my code?
The ship jitters and pops when i use it, here it is:
// The actual math, tell me if its wrong
float D3DTankArena::fBuildSpline( float fOld,float fVelOld,float fVelNew,float fNew,float t ) {
float v0= fOld;
float v1= v0 + fVelOld;
float v2= fNew + fVelNew * t + 0.5f * 0.0f * (t*t);
float v3= fNew;
float a1= 3.0f * v2;
float b1= 3.0f * v1;
float c1= 6.0f * v1;
float d1= 3.0f * v0;
float a2 = v3 - a1 + b1 - v0;
float b2 = a1 - c1 + d1;
float c2 = b1 - d1;
float d2 = v0;
return(a2*(t*t*t) + b2*(t*t) + c2*t + d2);
}
// This gets called in the main loop every frame...
HRESULT D3DTankArena::hrUpdateNetwork()
{
void *packet;
int i=0;
for( i=0;i if( m_pPlayerInfo.dpnidPlayer != m_dpnidLocalPlayer )
if( m_pPlayerInfo.bActive ) {<br> break;<br> }<br> }<br><br><br> if( (timeGetTime()-m_dwUpdateTimer)>300 ) <br> {<br> if( m_lNumberOfActivePlayers > 1 ) <br> {<br> m_pPlayerInfo.vOldPos = m_pPlayerInfo.vNewPos;<br> m_pPlayerInfo.fLastVelX = m_pPlayerInfo.fNewVelX;<br> m_pPlayerInfo.fLastVelZ = m_pPlayerInfo.fNewVelZ;<br> m_pPlayerInfo.fLastVelX = m_pPlayerInfo.fNewVelX;<br> m_pPlayerInfo.fLastVelZ = m_pPlayerInfo.fNewVelZ;<br><br> m_pPlayerInfo.vNewPos = m_vNewSyncPos;<br> m_pPlayerInfo.fNewVelX = m_vNewSyncVel.x;<br> m_pPlayerInfo.fNewVelZ = m_vNewSyncVel.y;<br> }<br> m_dwUpdateTimer = timeGetTime();<br> }<br><br> if( timeGetTime() > m_dwUpdateTimer+150 ) { <br> m_pSyncMsg.vPos = D3DXVECTOR2( m_pPlayerInfo[m_iLocalPlayerId].vPosition.x,m_pPlayerInfo[m_iLocalPlayerId].vPosition.z );<br> m_pSyncMsg.vVel = D3DXVECTOR2( m_pPlayerInfo[m_iLocalPlayerId].fVelX,m_pPlayerInfo[m_iLocalPlayerId].fVelZ );<br> m_pSyncMsg.fAngle = m_pPlayerInfo[m_iLocalPlayerId].fRot;<br> packet = (VOID*)&m_pSyncMsg;<br> hrSendPeerMessage( -1,PACKET_TYPE_SYNC,packet );<br> }<br> <br> if( i != MAX_PLAYERS ) {<br> float t=(float)( (float)timeGetTime()-m_dwUpdateTimer )/(float)300.0f;<br> m_pPlayerInfo.vPosition.x = fBuildSpline( m_pPlayerInfo.vOldPos.x,m_pPlayerInfo.fLastVelX,m_pPlayerInfo.fNewVelX,m_pPlayerInfo.vNewPos.x,t );<br> m_pPlayerInfo.vPosition.z = fBuildSpline( m_pPlayerInfo.vOldPos.z,m_pPlayerInfo.fLastVelZ,m_pPlayerInfo.fNewVelZ,m_pPlayerInfo.vNewPos.z,t ); <br> }<br><br> return S_OK;<br>}<br><br>// this code is taken out of the directplay message handler…<br> case PACKET_TYPE_SYNC:<br> {<br> iPlayerId = iGetPlayerId( pReceiveMsg->dpnidSender );<br> pSync = (PacketSync*)pReceiveMsg->pReceiveData;<br> <br> m_vNewSyncPos.x = pSync->vPos.x;<br> m_vNewSyncPos.z = pSync->vPos.y;<br> m_vNewSyncVel = pSync->vVel;<br><br> break;<br> }<br><br>Please help, the ship follows the path, but it jitter back and forth quickly, thanks a ton! </i>
The ship jitters and pops when i use it, here it is:
// The actual math, tell me if its wrong
float D3DTankArena::fBuildSpline( float fOld,float fVelOld,float fVelNew,float fNew,float t ) {
float v0= fOld;
float v1= v0 + fVelOld;
float v2= fNew + fVelNew * t + 0.5f * 0.0f * (t*t);
float v3= fNew;
float a1= 3.0f * v2;
float b1= 3.0f * v1;
float c1= 6.0f * v1;
float d1= 3.0f * v0;
float a2 = v3 - a1 + b1 - v0;
float b2 = a1 - c1 + d1;
float c2 = b1 - d1;
float d2 = v0;
return(a2*(t*t*t) + b2*(t*t) + c2*t + d2);
}
// This gets called in the main loop every frame...
HRESULT D3DTankArena::hrUpdateNetwork()
{
void *packet;
int i=0;
for( i=0;i
if( m_pPlayerInfo.bActive ) {<br> break;<br> }<br> }<br><br><br> if( (timeGetTime()-m_dwUpdateTimer)>300 ) <br> {<br> if( m_lNumberOfActivePlayers > 1 ) <br> {<br> m_pPlayerInfo.vOldPos = m_pPlayerInfo.vNewPos;<br> m_pPlayerInfo.fLastVelX = m_pPlayerInfo.fNewVelX;<br> m_pPlayerInfo.fLastVelZ = m_pPlayerInfo.fNewVelZ;<br> m_pPlayerInfo.fLastVelX = m_pPlayerInfo.fNewVelX;<br> m_pPlayerInfo.fLastVelZ = m_pPlayerInfo.fNewVelZ;<br><br> m_pPlayerInfo.vNewPos = m_vNewSyncPos;<br> m_pPlayerInfo.fNewVelX = m_vNewSyncVel.x;<br> m_pPlayerInfo.fNewVelZ = m_vNewSyncVel.y;<br> }<br> m_dwUpdateTimer = timeGetTime();<br> }<br><br> if( timeGetTime() > m_dwUpdateTimer+150 ) { <br> m_pSyncMsg.vPos = D3DXVECTOR2( m_pPlayerInfo[m_iLocalPlayerId].vPosition.x,m_pPlayerInfo[m_iLocalPlayerId].vPosition.z );<br> m_pSyncMsg.vVel = D3DXVECTOR2( m_pPlayerInfo[m_iLocalPlayerId].fVelX,m_pPlayerInfo[m_iLocalPlayerId].fVelZ );<br> m_pSyncMsg.fAngle = m_pPlayerInfo[m_iLocalPlayerId].fRot;<br> packet = (VOID*)&m_pSyncMsg;<br> hrSendPeerMessage( -1,PACKET_TYPE_SYNC,packet );<br> }<br> <br> if( i != MAX_PLAYERS ) {<br> float t=(float)( (float)timeGetTime()-m_dwUpdateTimer )/(float)300.0f;<br> m_pPlayerInfo.vPosition.x = fBuildSpline( m_pPlayerInfo.vOldPos.x,m_pPlayerInfo.fLastVelX,m_pPlayerInfo.fNewVelX,m_pPlayerInfo.vNewPos.x,t );<br> m_pPlayerInfo.vPosition.z = fBuildSpline( m_pPlayerInfo.vOldPos.z,m_pPlayerInfo.fLastVelZ,m_pPlayerInfo.fNewVelZ,m_pPlayerInfo.vNewPos.z,t ); <br> }<br><br> return S_OK;<br>}<br><br>// this code is taken out of the directplay message handler…<br> case PACKET_TYPE_SYNC:<br> {<br> iPlayerId = iGetPlayerId( pReceiveMsg->dpnidSender );<br> pSync = (PacketSync*)pReceiveMsg->pReceiveData;<br> <br> m_vNewSyncPos.x = pSync->vPos.x;<br> m_vNewSyncPos.z = pSync->vPos.y;<br> m_vNewSyncVel = pSync->vVel;<br><br> break;<br> }<br><br>Please help, the ship follows the path, but it jitter back and forth quickly, thanks a ton! </i>
--m_nPostCount++
Hi!
Sorry, I haven''t check your code.
I had the same problems with the cubic splines and now can tell why.
That article about cubic splines sucks.
You can use cubic splines only for INTERPOLATION, and what you need for network code is EXTRAPOLATION.
When the cubic curve you''ve built may be used only between control points, i.e. only for interpolation. Outside [0,1] region cubic spline behaves very bad -> you feel jitter.
The answer is in quadratic curves. Some easy math and you''re happy:
p = A*t^2 + B*t + C;
v = 2*A*t + B;
t0: p0, v0
t1: p1, v1
exact formulas left as an exercise to the reader
Best regards,
Dmitry S. Baikov
Sorry, I haven''t check your code.
I had the same problems with the cubic splines and now can tell why.
That article about cubic splines sucks.
You can use cubic splines only for INTERPOLATION, and what you need for network code is EXTRAPOLATION.
When the cubic curve you''ve built may be used only between control points, i.e. only for interpolation. Outside [0,1] region cubic spline behaves very bad -> you feel jitter.
The answer is in quadratic curves. Some easy math and you''re happy:
p = A*t^2 + B*t + C;
v = 2*A*t + B;
t0: p0, v0
t1: p1, v1
exact formulas left as an exercise to the reader
Best regards,
Dmitry S. Baikov
Best regards,Dmitry S. Baikov
soooo, p will be the position, and v the velocity?
one other question...
the A, B and C variables are declared like this correct?
A = x3 – 3x2 +3x1 – x0
B = 3x2 – 6x1 + 3x0
C = 3x1 – 3x0
oh and by the way...
what does this mean exactly?
t0: p0, v0
t1: p1, v1
thank you very much
one other question...
the A, B and C variables are declared like this correct?
A = x3 – 3x2 +3x1 – x0
B = 3x2 – 6x1 + 3x0
C = 3x1 – 3x0
oh and by the way...
what does this mean exactly?
t0: p0, v0
t1: p1, v1
thank you very much
--m_nPostCount++
it doesn't work, please check my code....
float D3DTankArena::fBuildSpline( float fOld,float fVelOld,float fVelNew,float fNew,float t ) {
float v0= fOld;
float v1= v0 + fVelOld;
float v2= fNew + (fVelNew * t) + (0.5f * 0.05f) * (t*t);
float v3= fNew;
/*
float a1= 3.0f * v2;
float b1= 3.0f * v1;
float c1= 6.0f * v1;
float d1= 3.0f * v0;
float a2 = v3 - a1 + b1 - v0;
float b2 = a1 - c1 + d1;
float c2 = b1 - d1;
float d2 = v0;
return(a2*(t*t*t) + b2*(t*t) + c2*t + d2);*/
float A = v3 - (3.0f*v2) + (3.0f*v1) - v0;
float B = (3.0f*v2) - (6.0f*v1) + (3.0f*v0);
float C = (3.0f*v1) - (3.0f*v0);
float p = (A*(t*t)) + (B*t) + C;
float v = (2.0f*A*t) + B;
return(p+v);
}
HRESULT D3DTankArena::hrUpdateNetwork()
{
void *packet;
int i=0;
////////////////////////////////////////////////////////////
//
// Dead Reckoning stuff...
//
////////////////////////////////////////////////////////////
for( i=0;i if( m_pPlayerInfo.dpnidPlayer != m_dpnidLocalPlayer )
if( m_pPlayerInfo.bActive ) {<br> break;<br> }<br> }<br><br><br> if( (timeGetTime()-m_dwUpdateTimer)>300 ) <br> {<br> if( m_lNumberOfActivePlayers > 1 ) <br> {<br> m_pPlayerInfo.vOldPos = m_pPlayerInfo.vNewPos;<br> m_pPlayerInfo.fLastVelX = m_pPlayerInfo.fNewVelX;<br> m_pPlayerInfo.fLastVelZ = m_pPlayerInfo.fNewVelZ;<br> m_pPlayerInfo.fLastVelX = m_pPlayerInfo.fNewVelX;<br> m_pPlayerInfo.fLastVelZ = m_pPlayerInfo.fNewVelZ;<br><br> m_pPlayerInfo.vNewPos = m_vNewSyncPos;<br> m_pPlayerInfo.fNewVelX = m_vNewSyncVel.x;<br> m_pPlayerInfo.fNewVelZ = m_vNewSyncVel.y;<br> }<br> m_dwUpdateTimer = timeGetTime();<br> }<br><br> if( timeGetTime() > m_dwUpdateTimer+150 ) { <br> m_pSyncMsg.vPos = D3DXVECTOR2( m_pPlayerInfo[m_iLocalPlayerId].vPosition.x,m_pPlayerInfo[m_iLocalPlayerId].vPosition.z );<br> m_pSyncMsg.vVel = D3DXVECTOR2( m_pPlayerInfo[m_iLocalPlayerId].fVelX,m_pPlayerInfo[m_iLocalPlayerId].fVelZ );<br> m_pSyncMsg.fAngle = m_pPlayerInfo[m_iLocalPlayerId].fRot;<br> packet = (VOID*)&m_pSyncMsg;<br> hrSendPeerMessage( -1,PACKET_TYPE_SYNC,packet );<br> }<br> <br> if( i != MAX_PLAYERS ) {<br> float t=(float)( (float)timeGetTime()-m_dwUpdateTimer )/(float)300.0f;<br> m_pPlayerInfo.vPosition.x = fBuildSpline( m_pPlayerInfo.vOldPos.x,m_pPlayerInfo.fLastVelX,m_pPlayerInfo.fNewVelX,m_pPlayerInfo.vNewPos.x,t );<br> m_pPlayerInfo.vPosition.z = fBuildSpline( m_pPlayerInfo.vOldPos.z,m_pPlayerInfo.fLastVelZ,m_pPlayerInfo.fNewVelZ,m_pPlayerInfo.vNewPos.z,t ); <br> }<br><br> return S_OK;<br>}<br> </i> <br><br>oh, and my ultimate question…<br><br>what do i do with p and v (i assume position and velocity)?<br>add them together and update the players position like this?<br><br>m_pPlayerInfo<i>.vPosition = p+v;<br><br><SPAN CLASS=editedby>[edited by - DirectXFreak on June 18, 2003 7:59:09 PM]</SPAN> </i>
float D3DTankArena::fBuildSpline( float fOld,float fVelOld,float fVelNew,float fNew,float t ) {
float v0= fOld;
float v1= v0 + fVelOld;
float v2= fNew + (fVelNew * t) + (0.5f * 0.05f) * (t*t);
float v3= fNew;
/*
float a1= 3.0f * v2;
float b1= 3.0f * v1;
float c1= 6.0f * v1;
float d1= 3.0f * v0;
float a2 = v3 - a1 + b1 - v0;
float b2 = a1 - c1 + d1;
float c2 = b1 - d1;
float d2 = v0;
return(a2*(t*t*t) + b2*(t*t) + c2*t + d2);*/
float A = v3 - (3.0f*v2) + (3.0f*v1) - v0;
float B = (3.0f*v2) - (6.0f*v1) + (3.0f*v0);
float C = (3.0f*v1) - (3.0f*v0);
float p = (A*(t*t)) + (B*t) + C;
float v = (2.0f*A*t) + B;
return(p+v);
}
HRESULT D3DTankArena::hrUpdateNetwork()
{
void *packet;
int i=0;
////////////////////////////////////////////////////////////
//
// Dead Reckoning stuff...
//
////////////////////////////////////////////////////////////
for( i=0;i
if( m_pPlayerInfo.bActive ) {<br> break;<br> }<br> }<br><br><br> if( (timeGetTime()-m_dwUpdateTimer)>300 ) <br> {<br> if( m_lNumberOfActivePlayers > 1 ) <br> {<br> m_pPlayerInfo.vOldPos = m_pPlayerInfo.vNewPos;<br> m_pPlayerInfo.fLastVelX = m_pPlayerInfo.fNewVelX;<br> m_pPlayerInfo.fLastVelZ = m_pPlayerInfo.fNewVelZ;<br> m_pPlayerInfo.fLastVelX = m_pPlayerInfo.fNewVelX;<br> m_pPlayerInfo.fLastVelZ = m_pPlayerInfo.fNewVelZ;<br><br> m_pPlayerInfo.vNewPos = m_vNewSyncPos;<br> m_pPlayerInfo.fNewVelX = m_vNewSyncVel.x;<br> m_pPlayerInfo.fNewVelZ = m_vNewSyncVel.y;<br> }<br> m_dwUpdateTimer = timeGetTime();<br> }<br><br> if( timeGetTime() > m_dwUpdateTimer+150 ) { <br> m_pSyncMsg.vPos = D3DXVECTOR2( m_pPlayerInfo[m_iLocalPlayerId].vPosition.x,m_pPlayerInfo[m_iLocalPlayerId].vPosition.z );<br> m_pSyncMsg.vVel = D3DXVECTOR2( m_pPlayerInfo[m_iLocalPlayerId].fVelX,m_pPlayerInfo[m_iLocalPlayerId].fVelZ );<br> m_pSyncMsg.fAngle = m_pPlayerInfo[m_iLocalPlayerId].fRot;<br> packet = (VOID*)&m_pSyncMsg;<br> hrSendPeerMessage( -1,PACKET_TYPE_SYNC,packet );<br> }<br> <br> if( i != MAX_PLAYERS ) {<br> float t=(float)( (float)timeGetTime()-m_dwUpdateTimer )/(float)300.0f;<br> m_pPlayerInfo.vPosition.x = fBuildSpline( m_pPlayerInfo.vOldPos.x,m_pPlayerInfo.fLastVelX,m_pPlayerInfo.fNewVelX,m_pPlayerInfo.vNewPos.x,t );<br> m_pPlayerInfo.vPosition.z = fBuildSpline( m_pPlayerInfo.vOldPos.z,m_pPlayerInfo.fLastVelZ,m_pPlayerInfo.fNewVelZ,m_pPlayerInfo.vNewPos.z,t ); <br> }<br><br> return S_OK;<br>}<br> </i> <br><br>oh, and my ultimate question…<br><br>what do i do with p and v (i assume position and velocity)?<br>add them together and update the players position like this?<br><br>m_pPlayerInfo<i>.vPosition = p+v;<br><br><SPAN CLASS=editedby>[edited by - DirectXFreak on June 18, 2003 7:59:09 PM]</SPAN> </i>
--m_nPostCount++
June 25, 2003 08:54 AM
http://www.gamasutra.com/features/19970919/aronson_01.htm
Game Programming Gems II
Game Programming Gems II
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement
Recommended Tutorials
Advertisement