Пример #1
0
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;
			}
		}
	}
}
Пример #2
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;
}
Пример #3
0
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;
}
Пример #4
0
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;
}
Пример #5
0
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 );	
	}
}