void CVertMeshInstance::UpdateAnimation(float TimeDelta) { if (AnimIndex >= 0) { // update animation time AnimTime += TimeDelta * AnimRate; const FMeshAnimSeq &Seq = pMesh->AnimSeqs[AnimIndex]; if (AnimLooped) { if (AnimTime >= Seq.NumFrames) { // wrap time int numSkip = appFloor(AnimTime / Seq.NumFrames); AnimTime -= numSkip * Seq.NumFrames; } } else { if (AnimTime >= Seq.NumFrames-1) { // clamp time AnimTime = Seq.NumFrames-1; if (AnimTime < 0) AnimTime = 0; } } } }
// not 'static', because used in ExportPsa() void CAnimTrack::GetBonePosition(float Frame, float NumFrames, bool Loop, CVec3 &DstPos, CQuat &DstQuat) const { guard(CAnimTrack::GetBonePosition); // fast case: 1 frame only if (KeyTime.Num() == 1 || NumFrames == 1 || Frame == 0) { if (KeyPos.Num()) DstPos = KeyPos[0]; if (KeyQuat.Num()) DstQuat = KeyQuat[0]; return; } // data for lerping int posX, rotX; // index of previous frame int posY, rotY; // index of next frame float posF, rotF; // fraction between X and Y for lerping int NumTimeKeys = KeyTime.Num(); int NumPosKeys = KeyPos.Num(); int NumRotKeys = KeyQuat.Num(); if (NumTimeKeys) { // here: KeyPos and KeyQuat sizes either equals to 1 or equals to KeyTime size assert(NumPosKeys <= 1 || NumPosKeys == NumTimeKeys); assert(NumRotKeys == 1 || NumRotKeys == NumTimeKeys); GetKeyParams(KeyTime, Frame, NumFrames, Loop, posX, posY, posF); rotX = posX; rotY = posY; rotF = posF; if (NumPosKeys <= 1) { posX = posY = 0; posF = 0; } if (NumRotKeys == 1) { rotX = rotY = 0; rotF = 0; } } else { // empty KeyTime array - keys are evenly spaced on a time line // note: KeyPos and KeyQuat sizes can be different if (KeyPosTime.Num()) { GetKeyParams(KeyPosTime, Frame, NumFrames, Loop, posX, posY, posF); } else if (NumPosKeys > 1) { float Position = Frame / NumFrames * NumPosKeys; posX = appFloor(Position); posF = Position - posX; posY = posX + 1; if (posY >= NumPosKeys) { if (!Loop) { posY = NumPosKeys - 1; posF = 0; } else posY = 0; } } else { posX = posY = 0; posF = 0; } if (KeyQuatTime.Num()) { GetKeyParams(KeyQuatTime, Frame, NumFrames, Loop, rotX, rotY, rotF); } else if (NumRotKeys > 1) { float Position = Frame / NumFrames * NumRotKeys; rotX = appFloor(Position); rotF = Position - rotX; rotY = rotX + 1; if (rotY >= NumRotKeys) { if (!Loop) { rotY = NumRotKeys - 1; rotF = 0; } else rotY = 0; } } else { rotX = rotY = 0; rotF = 0; } } // get position if (posF > 0) Lerp(KeyPos[posX], KeyPos[posY], posF, DstPos); else if (NumPosKeys) // do not change DstPos when no keys DstPos = KeyPos[posX]; // get orientation if (rotF > 0) Slerp(KeyQuat[rotX], KeyQuat[rotY], rotF, DstQuat); else if (NumRotKeys) // do not change DstQuat when no keys DstQuat = KeyQuat[rotX]; unguard; }
void SV_Frame(float msec) { guard(SV_Frame); time_before_game = time_after_game = 0; // if server is not active, do nothing if (!svs.initialized) return; // SV_DrawTextLeft(va("time: %10d rf: %10.5f d: %10.4f ri:%10d", sv.time, svs.realtimef, msec, svs.realtime));//!! svs.realtimef += msec; svs.realtime = appFloor(svs.realtimef); if (!sv.attractloop) { // check timeouts SV_CheckTimeouts(); } // get packets from clients SV_ReadPackets(); if (sv.state == ss_dead) return; // server was killed from one of packet (e.g. "rcon killserver") int frameTime = 100; // (sv_fps->integer > 10) ? (1000 / sv_fps->integer) : 100; // move autonomous things around if enough time has passed if (svs.realtime < sv.time) { // never let the time get too far off if (sv.time - svs.realtime > frameTime) { if (sv_showclamp->integer) appPrintf("sv lowclamp s:%d -- r:%d -> %d\n", sv.time, svs.realtime, sv.time - frameTime); svs.realtime = sv.time - frameTime; svs.realtimef = svs.realtime; } return; } SV_ClearTexts(); if (!sv.attractloop) { // update ping based on the last known frame from all clients SV_CalcPings(); // give the clients some timeslices SV_GiveMsec(); } // let everything in the world think and move /*-------- SV_RunGameFrame() ---------------*/ // we always need to bump framenum, even if we // don't run the world, otherwise the delta // compression can get confused when a client // has the "current" frame sv.framenum++; sv.time += frameTime; // = sv.framenum*100; ?? // don't run if paused if (!sv_paused->integer || sv_maxclients->integer > 1) { time_before_game = appCycles(); guardGame(ge.RunFrame); ge->RunFrame(); unguardGame; // never get more than one tic behind if (sv.time < svs.realtime) { if (sv_showclamp->integer) appPrintf("sv highclamp s:%d r:%d -> %d\n", sv.time, svs.realtime, sv.time); svs.realtime = sv.time; svs.realtimef = sv.time; } time_after_game = appCycles(); } // if extended protocol used, recalculate footstep sounds, mdx/mdl/md3 frames etc. if (sv_extProtocol->integer && !sv.attractloop) SV_PostprocessFrame(); // send messages back to the clients that had packets read this frame SV_SendClientMessages(); // save the entire world state if recording a serverdemo SV_RecordDemoMessage(); // send a heartbeat to the master if needed Master_Heartbeat(); // clear teleport flags, etc for next frame SV_PrepWorldFrame(); unguard; }
void CVertMeshInstance::Draw(unsigned flags) { guard(CVertMeshInstance::Draw); if (!Sections.Num()) return; // empty mesh int i; // get 2 frames for interpolation int FrameNum1, FrameNum2; float frac; if (AnimIndex != INDEX_NONE) { const FMeshAnimSeq &A = pMesh->AnimSeqs[AnimIndex]; FrameNum1 = appFloor(AnimTime); FrameNum2 = FrameNum1 + 1; if (FrameNum2 >= A.NumFrames) FrameNum2 = 0; frac = AnimTime - FrameNum1; FrameNum1 += A.StartFrame; FrameNum2 += A.StartFrame; // clamp frame numbers (has mesh with wrong frame count in last animation: // UT1/BotPack/cdgunmainM; this animation is shown in UnrealEd as lerping to null size) if (FrameNum1 >= pMesh->FrameCount) FrameNum1 = pMesh->FrameCount-1; if (FrameNum2 >= pMesh->FrameCount) FrameNum2 = pMesh->FrameCount-1; } else { FrameNum1 = 0; FrameNum2 = 0; frac = 0; } int base1 = pMesh->VertexCount * FrameNum1; int base2 = pMesh->VertexCount * FrameNum2; float backLerp = 1 - frac; CVec3 Scale1, Scale2; Scale1 = Scale2 = CVT(pMesh->MeshScale); Scale1.Scale(backLerp); Scale2.Scale(frac); // compute deformed mesh const FMeshWedge *W = &pMesh->Wedges[0]; CVec3 *pVec = Verts; CVec3 *pNormal = Normals; for (i = 0; i < pMesh->Wedges.Num(); i++, pVec++, pNormal++, W++) { CVec3 tmp; #if 0 // path with no frame lerp // vertex const FMeshVert &V = pMesh->Verts[base1 + W->iVertex]; tmp[0] = V.X * pMesh->MeshScale.X; tmp[1] = V.Y * pMesh->MeshScale.Y; tmp[2] = V.Z * pMesh->MeshScale.Z; BaseTransform.TransformPoint(tmp, *pVec); // normal const FMeshNorm &N = pMesh->Normals[base1 + W->iVertex]; tmp[0] = (N.X - 512.0f) / 512; tmp[1] = (N.Y - 512.0f) / 512; tmp[2] = (N.Z - 512.0f) / 512; BaseTransform.axis.TransformVector(tmp, *pNormal); #else // vertex const FMeshVert &V1 = pMesh->Verts[base1 + W->iVertex]; const FMeshVert &V2 = pMesh->Verts[base2 + W->iVertex]; tmp[0] = V1.X * Scale1[0] + V2.X * Scale2[0]; tmp[1] = V1.Y * Scale1[1] + V2.Y * Scale2[1]; tmp[2] = V1.Z * Scale1[2] + V2.Z * Scale2[2]; BaseTransform.TransformPoint(tmp, *pVec); // normal const FMeshNorm &N1 = pMesh->Normals[base1 + W->iVertex]; const FMeshNorm &N2 = pMesh->Normals[base2 + W->iVertex]; tmp[0] = (N1.X * backLerp + N2.X * frac - 512.0f) / 512; tmp[1] = (N1.Y * backLerp + N2.Y * frac - 512.0f) / 512; tmp[2] = (N1.Z * backLerp + N2.Z * frac - 512.0f) / 512; BaseTransform.axis.TransformVector(tmp, *pNormal); #endif } #if 0 glBegin(GL_POINTS); for (i = 0; i < pMesh->Wedges.Num(); i++) { glVertex3fv(Verts[i].v); } glEnd(); return; #endif // draw mesh glEnable(GL_LIGHTING); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); glVertexPointer(3, GL_FLOAT, sizeof(CVec3), Verts); glNormalPointer(GL_FLOAT, sizeof(CVec3), Normals); glTexCoordPointer(2, GL_FLOAT, sizeof(FMeshWedge), &pMesh->Wedges[0].TexUV.U); for (i = 0; i < Sections.Num(); i++) { const CMeshSection &Sec = Sections[i]; if (!Sec.NumFaces) continue; SetMaterial(Sec.Material, i); glDrawElements(GL_TRIANGLES, Sec.NumFaces * 3, GL_UNSIGNED_SHORT, &Indices[Sec.FirstIndex]); } glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_NORMAL_ARRAY); glDisable(GL_LIGHTING); BindDefaultMaterial(true); // draw mesh normals if (flags & DF_SHOW_NORMALS) { glBegin(GL_LINES); glColor3f(0.5, 1, 0); for (i = 0; i < pMesh->Wedges.Num(); i++) { glVertex3fv(Verts[i].v); CVec3 tmp; VectorMA(Verts[i], 2, Normals[i], tmp); glVertex3fv(tmp.v); } glEnd(); } unguard; }
void DCameraPathFollower::Tick( float fDeltaSeconds_ ) { Super::Tick( fDeltaSeconds_ ); const dword dwFrameBySecond = 30; if( m_aPathManager.empty() || m_pCurrentPath==NULL ) return; CameraPath *pPath = m_pCurrentPath; // 2004/03/05 by impurity float ftFOV = 1.57f; if( pPath ) { dword iMsg = PmsgNull; // 메세지의 초기화 // 시간이 흐른다. m_fPathTime += (fDeltaSeconds_ * m_fPathPlayRatio); if( m_fPathTime<0.0f ) m_fPathTime = 0.0f; // Tweening if( m_bPathTween ) { if( (m_fPathPlayRatio>=0.0f && m_fPathTime > m_fPathTweenLife) || (m_fPathPlayRatio<0.0f && m_fPathLife-m_fPathTime > m_fPathTweenLife) ) {// end of tweening m_fPathTweenLife = 0.0f; if( m_fPathPlayRatio > 0.0f ) {// Forward playing : m_fPathTime = 0.0f; } else {// Backward playing m_fPathTime = m_fPathLife; } m_bPathTween = false; } else {// Tweening! float fRatio; if( m_fPathPlayRatio > 0.0f ) {// Forward fRatio = m_fPathTime/m_fPathTweenLife; m_lcTarget.Location.Lerp( m_lcPathTweenPrevLocus.Location, pPath->aFrame[0].Location, fRatio ); m_lcTarget.Rotation.Lerp( m_lcPathTweenPrevLocus.Rotation, pPath->aFrame[0].Rotation, fRatio ); } else {// Backward fRatio = (m_fPathLife-m_fPathTime)/m_fPathTweenLife; m_lcTarget.Location.Lerp( m_lcPathTweenPrevLocus.Location, pPath->aFrame[pPath->aFrame.size()-1].Location, fRatio ); m_lcTarget.Rotation.Lerp( m_lcPathTweenPrevLocus.Rotation, pPath->aFrame[pPath->aFrame.size()-1].Rotation, fRatio ); } m_lcTarget.Locate( m_lcTarget.Location+m_vPathTranslation ); m_lcTarget.Rotate( m_lcTarget.Rotation ); m_lcTarget.ScaleUp( SVector( 1.0f, 1.0f, 1.0f ) ); m_lcSavedLocation = m_lcTarget; } } // Non-tweening else { int iLeftFrame = appFloor(m_fPathTime*dwFrameBySecond); if( iLeftFrame < 0 ) { iMsg |= PmsgEnd; iLeftFrame = 0; } else if( iLeftFrame>=(int)pPath->aFrame.size() ) { iLeftFrame = (int)pPath->aFrame.size() - 1; iMsg |= PmsgEnd; if( m_bPathPlayLoop ) { iLeftFrame = 0; m_fPathTime = 0.0f; } } int iRightFrame = iLeftFrame+1; if( iRightFrame >= (int)pPath->aFrame.size() ) { iRightFrame = (int)pPath->aFrame.size() - 1; } //float fRatio = m_fPathTime - (float)iLeftFrame/(float)dwFrameBySecond; float fRatio = (m_fPathTime - (float)iLeftFrame/(float)dwFrameBySecond)/(1.0f/(float)dwFrameBySecond); m_lcTarget.Location.Lerp( pPath->aFrame[iLeftFrame].Location, pPath->aFrame[iRightFrame].Location, fRatio ); m_lcTarget.Rotation.Lerp( pPath->aFrame[iLeftFrame].Rotation, pPath->aFrame[iRightFrame].Rotation, fRatio ); ftFOV = fRatio*pPath->vctFOV[iLeftFrame] + (1.0f-fRatio)*pPath->vctFOV[iRightFrame]; m_lcTarget.Locate( m_lcTarget.Location+m_vPathTranslation ); m_lcTarget.Rotate( m_lcTarget.Rotation ); m_lcTarget.ScaleUp( SVector( 1.0f, 1.0f, 1.0f ) ); m_lcSavedLocation = m_lcTarget; } if( iMsg!=PmsgNull ) SendCallBack( iMsg ); } const static int iRotEpsilon = Rad2Angle(0.01f); const static int AngleHalf = ANGLE_MODULAR/2; const static int iPosEpsilon = Rad2Angle(0.001f); int iDelta = 0; float fProgress = 0.3f + fDeltaSeconds_; if( fProgress > 1.0f ) fProgress = 1.0f; //--------------------------------------------------- // Time Based Interpolation // ::Pos SVector PosTarget = m_lcTarget.Location; SVector PosCurrent = m_lcSavedLocation.Location; // delta(차)값을 조사하여 epsilon보다 클 경우에는 progress하고 // 적으면 고정시킨다. 그리고 각 고정플래그를 ON해서 마지막에 모든 Flag가 ON이면 움직이는 것을 멈춘다. //x { iDelta = PosTarget.X - PosCurrent.X; if( iDelta > iPosEpsilon || iDelta < -iPosEpsilon ) PosCurrent.X += (iDelta)*fProgress; else { PosCurrent.X = PosTarget.X; } //y iDelta = PosTarget.Y - PosCurrent.Y; if( iDelta > iPosEpsilon || iDelta < -iPosEpsilon ) PosCurrent.Y += (iDelta)*fProgress; else { PosCurrent.Y = PosTarget.Y; } //z iDelta = PosTarget.Z - PosCurrent.Z; if( iDelta > iPosEpsilon || iDelta < -iPosEpsilon ) PosCurrent.Z += (iDelta)*fProgress; else { PosCurrent.Z = PosTarget.Z; } } // ::Rot SRotator RotationTarget = m_lcTarget.Rotation; SRotator RotationCurrent = m_lcSavedLocation.Rotation; //yaw RotationCurrent.Yaw = ReduceAngle( RotationCurrent.Yaw ); iDelta = RotationTarget.Yaw - RotationCurrent.Yaw; if( iDelta > iRotEpsilon || iDelta < -iRotEpsilon ) { if( abs(iDelta) > AngleHalf ) { if( iDelta < 0 ) iDelta+=ANGLE_MODULAR; else iDelta-=ANGLE_MODULAR; RotationCurrent.Yaw += (iDelta)*fProgress; } else {// Turn Clockwise! RotationCurrent.Yaw += (iDelta)*fProgress; } RotationCurrent.Yaw = ReduceAngle(RotationCurrent.Yaw); } else { RotationCurrent.Yaw = RotationTarget.Yaw; } //pitch RotationCurrent.Pitch = ReduceAngle( RotationCurrent.Pitch ); iDelta = RotationTarget.Pitch - RotationCurrent.Pitch; if( iDelta > iRotEpsilon || iDelta < -iRotEpsilon ) { if( abs(iDelta) > AngleHalf ) { if( iDelta < 0 ) iDelta+=ANGLE_MODULAR; else iDelta-=ANGLE_MODULAR; RotationCurrent.Pitch += (iDelta)*fProgress; } else {// Turn Clockwise! RotationCurrent.Pitch += (iDelta)*fProgress; } RotationCurrent.Pitch = ReduceAngle(RotationCurrent.Pitch); } else { RotationCurrent.Pitch = RotationTarget.Pitch; } // 2004/03/17 by impurity roll RotationCurrent.Roll = ReduceAngle( RotationCurrent.Roll ); iDelta = RotationTarget.Roll - RotationCurrent.Roll; if( iDelta > iRotEpsilon || iDelta < -iRotEpsilon ) { if( abs(iDelta) > AngleHalf ) { if( iDelta < 0 ) iDelta+=ANGLE_MODULAR; else iDelta-=ANGLE_MODULAR; RotationCurrent.Roll += (iDelta)*fProgress; } else {// Turn Clockwise! RotationCurrent.Roll += (iDelta)*fProgress; } RotationCurrent.Roll = ReduceAngle(RotationCurrent.Roll); } else { RotationCurrent.Roll = RotationTarget.Roll; } // 2004/03/02 by impurity if(m_pParent) { m_CamLocation.Rotate( RotationCurrent + m_pParent->GetLocation()->Rotation ); D3DXVECTOR4 vctPos(PosCurrent.X, 0.0f, PosCurrent.Z,1.0f); D3DXMATRIX matRotation; D3DXMatrixRotationY(&matRotation, m_pParent->GetLocation()->Rotation.Yaw*2.0f*PI/65536); D3DXVec4Transform(&vctPos, &vctPos, &matRotation); PosCurrent.X = vctPos.x; PosCurrent.Z = vctPos.z; m_CamLocation.Locate( PosCurrent + m_pParent->GetLocation()->Location); UpdateMatrixInversed( m_CamLocation.LocalToWorld ); // 2004/03/05 by impurity DProj().ModifyFov( ftFOV ); } else { m_CamLocation.Rotate( RotationCurrent + m_rotYaw ); D3DXVECTOR4 vctPos(PosCurrent.X, 0.0f, PosCurrent.Z,1.0f); D3DXMATRIX matRotation; D3DXMatrixRotationY(&matRotation, m_rotYaw.Yaw*2.0f*PI/65536); D3DXVec4Transform(&vctPos, &vctPos, &matRotation); PosCurrent.X = vctPos.x; PosCurrent.Z = vctPos.z; m_CamLocation.Locate( PosCurrent + m_vctPos); UpdateMatrixInversed( m_CamLocation.LocalToWorld ); // 2004/03/05 by impurity DProj().ModifyFov( ftFOV ); } }