void SimpleSkeletalAnimatedObject_cl::ThinkFunction()
{
  // Check whether the object is active.
  if (GetAnimConfig() == NULL)
    return;

  const float dtime = Vision::GetTimer()->GetTimeDifference();

  // highlight the bone after animation event
  if (m_fBoneHighlightDuration > 0.0f && !m_sHighlightedBoneName.IsEmpty())
  {
    int iColorVal = static_cast<int>(m_fBoneHighlightDuration / BONE_HIGHLIGHT_FADEOUTTIME * 255.0f);
    DrawBoneBoundingBox(m_sHighlightedBoneName, VColorRef(iColorVal,iColorVal, 0), 2.f);
    m_fBoneHighlightDuration -= Vision::GetTimer()->GetTimeDifference();
  }

  // update the LookAt
  if (m_eSampleMode == MODE_LOOKAT)
  {
    VASSERT(m_pLookAtTarget);

    // rotate the object around the character
    m_fLookAtRotationPhase = hkvMath::mod(m_fLookAtRotationPhase + dtime*0.7f, hkvMath::pi() * 2.0f);
    hkvVec3 vNewPos(100.f*hkvMath::sinRad(m_fLookAtRotationPhase), 100.0f*hkvMath::cosRad(m_fLookAtRotationPhase), 160.0f);
    vNewPos += GetPosition();
    m_pLookAtTarget->SetPosition(vNewPos);

    // update the LookAt orientation
    UpdateLookatHeadRotation(dtime);
  }
}
Example #2
0
void SpinningWorldModel::UpdateOn( const LTFLOAT &fCurTime )
{
	LTVector	vNewPos(0.0f, 0.0f, 0.0f);
	LTRotation	rNewRot;
	LTFLOAT		fDeltaTm = fCurTime - m_fLastTime;
	LTFLOAT		fPercent = 0.0f;
	LTVector	vOldAngles( m_fPitch, m_fYaw, m_fRoll );

	m_bUpdateSpin = LTTRUE;

	if( m_vVelocity.x )
	{
		m_fPitch += m_vVelocity.x * fDeltaTm;
	}

	if( m_vVelocity.y )
	{
		m_fYaw += m_vVelocity.y * fDeltaTm;
	}

	if( m_vVelocity.z )
	{
		m_fRoll += m_vVelocity.z * fDeltaTm;
	}

	LTFLOAT	fDifLeft = (m_vOnAngles - LTVector( m_fPitch, m_fYaw, m_fRoll )).Mag();
	LTFLOAT	fFinalDif = (m_vOnAngles - m_vOffAngles).Mag();
		
	// Get the percent of our rotation to use for the light ani...

	fPercent = ( fFinalDif > MATH_EPSILON ? 1 - fDifLeft / fFinalDif : 1.0f );

	if( !CalculateNewPosRot( vNewPos, rNewRot, m_vOnPos, m_fPowerOnTime, fPercent, LTTRUE ) && !(m_dwPropFlags & AWM_PROP_FORCEMOVE) )
	{
		// Restore our angles...

		m_fPitch	= vOldAngles.x;
		m_fYaw		= vOldAngles.y;
		m_fRoll		= vOldAngles.z;

		m_fMoveStartTm	+= g_pLTServer->GetFrameTime();
		m_fLastTime		= fCurTime;
		m_bUpdateSpin	= LTFALSE;

		return;
	}

	g_pLTServer->MoveObject( m_hObject, &vNewPos );

	// Check to see if we actually moved anywhere...

	LTVector	vPos;
	g_pLTServer->GetObjectPos( m_hObject, &vPos );
	if( !vPos.NearlyEquals( vNewPos, MATH_EPSILON ) )
	{
		// Restore our angles...

		m_fPitch	= vOldAngles.x;
		m_fYaw		= vOldAngles.y;
		m_fRoll		= vOldAngles.z;

		m_fMoveStartTm	+= g_pLTServer->GetFrameTime();
		m_fLastTime		= fCurTime;
		m_bUpdateSpin	= LTFALSE;

		return;
	}

	g_pLTServer->RotateObject( m_hObject, &rNewRot );

	// Keep the Pitch, Yaw and Roll within 2PI so they will never over flow...

	if( m_fPitch > MATH_CIRCLE )
	{
		m_fPitch = -(MATH_CIRCLE - m_fPitch);
	}
	else if( m_fPitch < -MATH_CIRCLE )
	{
		m_fPitch += MATH_CIRCLE;
	}

	if( m_fYaw > MATH_CIRCLE )
	{
		m_fYaw = -(MATH_CIRCLE - m_fYaw);
	}
	else if( m_fYaw < -MATH_CIRCLE )
	{
		m_fYaw += MATH_CIRCLE;
	}

	if( m_fRoll > MATH_CIRCLE )
	{
		m_fRoll = -(MATH_CIRCLE - m_fRoll);
	}
	else if( m_fRoll < -MATH_CIRCLE )
	{
		m_fRoll += MATH_CIRCLE;
	}

	m_fLastTime = fCurTime;
}
Example #3
0
void SpinningWorldModel::UpdateOn( const double &fCurTime )
{
	LTVector	vNewPos(0.0f, 0.0f, 0.0f);
	LTRotation	rNewRot;
	float		fDeltaTm = (float)(fCurTime - m_fLastTime);
	float		fPercent = 0.0f;
	LTVector	vOldAngles( m_fPitch, m_fYaw, m_fRoll );

	m_bUpdateSpin = true;

	if( m_vVelocity.x )
	{
		m_fPitch += m_vVelocity.x * fDeltaTm;
	}

	if( m_vVelocity.y )
	{
		m_fYaw += m_vVelocity.y * fDeltaTm;
	}

	if( m_vVelocity.z )
	{
		m_fRoll += m_vVelocity.z * fDeltaTm;
	}

	float	fDifLeft = (m_vInitOnAngles - LTVector( m_fPitch, m_fYaw, m_fRoll )).Mag();
	float	fFinalDif = (m_vInitOnAngles - m_vInitOffAngles).Mag();
		
	// Get the percent of our rotation to use for the light ani...

	fPercent = ( fFinalDif > MATH_EPSILON ? 1 - fDifLeft / fFinalDif : 1.0f );

	uint32 nFlags;
	g_pCommonLT->GetObjectFlags( m_hObject, OFT_Flags, nFlags );
	bool bTestCollisions = !!( nFlags & FLAG_SOLID );

	if( !CalculateNewPosRot( vNewPos, rNewRot, m_vOnPos, m_fPowerOnTime, fPercent, bTestCollisions ) && !(m_dwPropFlags & AWM_PROP_FORCEMOVE) )
	{
		// Restore our angles...

		m_fPitch	= vOldAngles.x;
		m_fYaw		= vOldAngles.y;
		m_fRoll		= vOldAngles.z;

		m_fMoveStartTm	+= g_pLTServer->GetFrameTime();
		m_fLastTime		= fCurTime;
		m_bUpdateSpin	= false;

		return;
	}

	g_pLTServer->Physics()->MoveObject( m_hObject, vNewPos, 0 );

	// Check to see if we actually moved anywhere...

	LTVector	vPos;
	g_pLTServer->GetObjectPos( m_hObject, &vPos );
	if( !vPos.NearlyEquals( vNewPos, MATH_EPSILON ) )
	{
		// Restore our angles...

		m_fPitch	= vOldAngles.x;
		m_fYaw		= vOldAngles.y;
		m_fRoll		= vOldAngles.z;

		m_fMoveStartTm	+= g_pLTServer->GetFrameTime();
		m_fLastTime		= fCurTime;
		m_bUpdateSpin	= false;

		return;
	}

	g_pLTServer->RotateObject( m_hObject, rNewRot );

	// Keep the Pitch, Yaw and Roll within 2PI so they will never over flow...

	if( m_fPitch > MATH_CIRCLE )
	{
		m_fPitch = -(MATH_CIRCLE - m_fPitch);
	}
	else if( m_fPitch < -MATH_CIRCLE )
	{
		m_fPitch += MATH_CIRCLE;
	}

	if( m_fYaw > MATH_CIRCLE )
	{
		m_fYaw = -(MATH_CIRCLE - m_fYaw);
	}
	else if( m_fYaw < -MATH_CIRCLE )
	{
		m_fYaw += MATH_CIRCLE;
	}

	if( m_fRoll > MATH_CIRCLE )
	{
		m_fRoll = -(MATH_CIRCLE - m_fRoll);
	}
	else if( m_fRoll < -MATH_CIRCLE )
	{
		m_fRoll += MATH_CIRCLE;
	}

	m_fLastTime = fCurTime;
}
Example #4
0
void CModelGTF::RenderModel()
{
	// Go through all of the objects stored in this model
	for(int i = 0; i < m_Model.numOfObjects; i++)
	{
		// Get the current object that we are displaying
		t3DObject *pObject = &m_Model.pObject[i];
		
		// Check if there are materials assigned to this object and 
		// enable texture mapping if necessary, otherwise turn it off.
		if(pObject->numOfMaterials >= 1)
			glEnable(GL_TEXTURE_2D);
		else
			glDisable(GL_TEXTURE_2D);

		// Go through all of the faces (polygons) of the object and draw them
		for(int j = 0; j < pObject->numOfFaces; j++)
		{
			// Now let's see if there are any materials that need binding
			if(pObject->numOfMaterials >= 1)
			{
				// Create a static int to hold the last texture ID
				static int lastTexID = -1;

				// Extract the current textureID for this face from our face data
				int textureID = m_Model.pMaterials[pObject->pFaces[j].textureID].texureId;

				// If the current texture ID isn't the same as last time, bind the texture.
				if(textureID != lastTexID && textureID >= 0 && textureID < (int)strTextures.size())
					glBindTexture(GL_TEXTURE_2D, m_Textures[textureID]);

				// Store the current textureID in our static int for next time
				lastTexID = textureID;
			}

			// Start drawing our model triangles
			glBegin(GL_TRIANGLES);

				// Go through each vertex of the triangle and draw it.
				for(int whichVertex = 0; whichVertex < 3; whichVertex++)
				{
					// Make sure there are texture coordinates for this
					if(pObject->pTexVerts) 
					{
						// Here we grab the texture index from our face information
						int texIndex = pObject->pFaces[j].coordIndex[whichVertex];

						// Assign the texture coordinate to this vertex
						glTexCoord2f(pObject->pTexVerts[ texIndex ].x, 
									 pObject->pTexVerts[ texIndex ].y);
					}

					// Grab the current vertex index from our face information
					int vertIndex = pObject->pFaces[j].vertIndex[whichVertex];


//////////// *** NEW *** ////////// *** NEW *** ///////////// *** NEW *** ////////////////////

					// Now we get to the beef of the tutorial.  Below is where we
					// handle the calculations for our animation.  Basically what
					// happens is we grab the current and the next frame of animation
					// data.  With that data (the weights and transformations) we
					// do spherical interpolation (quaternion rotations) and linear
					// interpolation (the translations) to get a smooth transformation
					// between each frame of animation.  There isn't anything to
					// difficult about the concepts, but the math is the challenging
					// part.  The only math that is new to this tutorial is the
					// calculations of multiplying a quaternion by a 3D vector.

					// Extract the current vertex and draw it
					CVector3 vPos = pObject->pVerts[vertIndex];					

					// If there is no animation, just render the original
					// vertex and continue (skip the animation calculations).
					if(!pObject->bAnimated)
					{
						glVertex3f(vPos.x, vPos.y, vPos.z);
						continue;
					}

					// This will be our final vertex position to render
					CVector3 vNewPos(0, 0, 0);

					// Just to specify the index, we store our vertex index as a blendIndex.
					// This will index into our weight list.
					int blendIndex = vertIndex;

					// Now comes the crazy code :)  We now will go through every single
					// weight influence and add up all the influences and transformations
					// to our current vertex.
					for(int b=0; b < pObject->vWeightInfo[blendIndex].numBlendLinks; b++)
					{
						// Grab the current bone index from our weight list.  Remember that
						// the X variable stores the bone index and the Y stores the weight.
						int boneIndex = (int)pObject->vWeightInfo[blendIndex].pWeightInfo[b].x;

						// Make sure that the index we got isn't out of range of our bones
						if(boneIndex > pObject->numBones)
							return;

						// Now we want to grab the translation and rotation data for both the
						// current and the next frame of animation.  That way we can interpolate
						// between the two frames to make the animation look smoother.  So here
						// we grab pointers to the current and next matrix information for the
						// current bone we are working with.
						tBoneMatrix *pBoneMatrix1 = &(pObject->vBoneInfo[m_Model.currentFrame].pBoneMatrices[boneIndex]);
						tBoneMatrix *pBoneMatrix2 = &(pObject->vBoneInfo[m_Model.nextFrame].pBoneMatrices[boneIndex]);

						// First we want to perform the spherical-linear interpolation between
						// the two quaternions (rotations) for the current and next frame.
						CQuaternion	qPos(pBoneMatrix1->qRotation); 
						CQuaternion	qPos2(pBoneMatrix2->qRotation); 
						CQuaternion qNew = qPos.Slerp(qPos, qPos2, m_Model.t);

						// To apply the interpolated rotation we multiply our rotation by
						// the original position of the vertex.  This will then use our
						// function that we created at the top of this file which multiplies a
						// quaternion by a vector.  Once we do that, we store the new 3D vector.
						CVector3 vTempPos = qNew * vPos;

						// Next we grab the translations for the current and next frame
						CVector3 vPosition = pBoneMatrix1->vTranslation;
						CVector3 vNextPosition = pBoneMatrix2->vTranslation;
						
						// Using a simple linear-interpolation equation, we use our time "t"
						// value to interpolate between the current and next translation.  This
						// gives us a smooth transition between each frame of animation.
						vTempPos.x += vPosition.x + m_Model.t * (vNextPosition.x - vPosition.x);
						vTempPos.y += vPosition.y + m_Model.t * (vNextPosition.y - vPosition.y);
						vTempPos.z += vPosition.z + m_Model.t * (vNextPosition.z - vPosition.z);

						// If there is a special weight for this vertex we want to extract
						// that and apply it to our current vertex.  If the model isn't using
						// weighted animation then the weight will just be 1.0, which will do
						// nothing to the vertex when applied.  Remember that the Y value of
						// our weight-info list is the actual weight value to be applied.
						float weight = pObject->vWeightInfo[blendIndex].pWeightInfo[b].y;

						// Apply the weight value to our current vertex and add it to our
						// final transformed vertex position.
						vNewPos += vTempPos * weight;
					}

					// vNewPos has our final position that was transformed, so render it.
					glVertex3f(vNewPos.x, vNewPos.y, vNewPos.z);

//////////// *** NEW *** ////////// *** NEW *** ///////////// *** NEW *** ////////////////////


				}

			// Stop drawing polygons
			glEnd();
		}
	}
}