Files
itgmania212121/stepmania/src/Model.cpp
T
2003-05-09 04:42:04 +00:00

974 lines
28 KiB
C++

#include "global.h"
/*
-----------------------------------------------------------------------------
Class: Milkshape
Desc: Types defined in msLib.h.
Copyright (c) 2001-2002 by the person(s) listed below. All rights reserved.
Chris Danford
-----------------------------------------------------------------------------
*/
#include "Model.h"
#include "Milkshape.h"
#include "mathlib.h"
#include "RageDisplay.h"
#include "RageUtil.h"
#include "RageTextureManager.h"
const float FRAMES_PER_SECOND = 30;
Model::Model ()
{
m_pModel = NULL;
m_pBones = NULL;
}
Model::~Model ()
{
Clear ();
}
void Model::Clear ()
{
delete[] m_pBones;
m_pBones = NULL;
delete m_pModel;
m_pModel = NULL;
}
bool Model::LoadMilkshapeAscii( CString sPath )
{
CString sDir, sThrowAway;
splitrelpath( sPath, sDir, sThrowAway, sThrowAway );
FILE *file = fopen (sPath, "rt");
if (!file)
RageException::Throw( "Model:: Could not open '%s'.", sPath.c_str() );
Clear ();
m_pModel = new msModel;
// Never zero out a non-POD data type.
// memset (m_pModel, 0, sizeof (msModel));
bool bError = false;
char szLine[256];
char szName[MS_MAX_NAME];
int nFlags, nIndex, i, j;
ClearBounds (m_vMins, m_vMaxs);
while (fgets (szLine, 256, file) != NULL && !bError)
{
if (!strncmp (szLine, "//", 2))
continue;
int nFrame;
if (sscanf (szLine, "Frames: %d", &nFrame) == 1)
{
m_pModel->nTotalFrames = nFrame;
}
if (sscanf (szLine, "Frame: %d", &nFrame) == 1)
{
m_pModel->nFrame = nFrame;
}
int nNumMeshes = 0;
if (sscanf (szLine, "Meshes: %d", &nNumMeshes) == 1)
{
m_pModel->Meshes.resize( nNumMeshes );
for (i = 0; i < nNumMeshes && !bError; i++)
{
msMesh& mesh = m_pModel->Meshes[i];
if (!fgets (szLine, 256, file))
{
bError = true;
break;
}
// mesh: name, flags, material index
if (sscanf (szLine, "\"%[^\"]\" %d %d",szName, &nFlags, &nIndex) != 3)
{
bError = true;
break;
}
strcpy( mesh.szName, szName );
// mesh.nFlags = nFlags;
mesh.nMaterialIndex = nIndex;
//
// vertices
//
if (!fgets (szLine, 256, file))
{
bError = true;
break;
}
int nNumVertices = 0;
if (sscanf (szLine, "%d", &nNumVertices) != 1)
{
bError = true;
break;
}
mesh.Vertices.resize( nNumVertices );
for (j = 0; j < nNumVertices; j++)
{
if (!fgets (szLine, 256, file))
{
bError = true;
break;
}
msVec3 Vertex;
msVec2 uv;
if (sscanf (szLine, "%d %f %f %f %f %f %d",
&nFlags,
&Vertex[0], &Vertex[1], &Vertex[2],
&uv[0], &uv[1],
&nIndex
) != 7)
{
bError = true;
break;
}
msVertex& vertex = mesh.Vertices[j];
// vertex.nFlags = nFlags;
memcpy( vertex.Vertex, Vertex, sizeof(vertex.Vertex) );
memcpy( vertex.uv, uv, sizeof(vertex.uv) );
vertex.nBoneIndex = nIndex;
AddPointToBounds (Vertex, m_vMins, m_vMaxs);
}
//
// normals
//
if (!fgets (szLine, 256, file))
{
bError = true;
break;
}
int nNumNormals = 0;
if (sscanf (szLine, "%d", &nNumNormals) != 1)
{
bError = true;
break;
}
vector<msVec3> Normals;
Normals.resize( nNumNormals );
for (j = 0; j < nNumNormals; j++)
{
if (!fgets (szLine, 256, file))
{
bError = true;
break;
}
msVec3 Normal;
if (sscanf (szLine, "%f %f %f", &Normal[0], &Normal[1], &Normal[2]) != 3)
{
bError = true;
break;
}
VectorNormalize (Normal);
Normals[j] = Normal;
}
//
// triangles
//
if (!fgets (szLine, 256, file))
{
bError = true;
break;
}
int nNumTriangles = 0;
if (sscanf (szLine, "%d", &nNumTriangles) != 1)
{
bError = true;
break;
}
mesh.Triangles.resize( nNumTriangles );
for (j = 0; j < nNumTriangles; j++)
{
if (!fgets (szLine, 256, file))
{
bError = true;
break;
}
word nIndices[3];
word nNormalIndices[3];
if (sscanf (szLine, "%d %hd %hd %hd %hd %hd %hd %d",
&nFlags,
&nIndices[0], &nIndices[1], &nIndices[2],
&nNormalIndices[0], &nNormalIndices[1], &nNormalIndices[2],
&nIndex
) != 8)
{
bError = true;
break;
}
// deflate the normals into vertices
for( int k=0; k<3; k++ )
{
msVertex& Vertex = mesh.Vertices[ nIndices[k] ];
msVec3& Normal = Normals[ nNormalIndices[k] ];
Vertex.Normal = Normal;
}
msTriangle& Triangle = mesh.Triangles[j];
// Triangle.nFlags = nFlags;
memcpy( &Triangle.nVertexIndices, nIndices, sizeof(Triangle.nVertexIndices) );
// Triangle.nSmoothingGroup = nIndex;
}
}
}
//
// materials
//
int nNumMaterials = 0;
if (sscanf (szLine, "Materials: %d", &nNumMaterials) == 1)
{
m_pModel->Materials.resize( nNumMaterials );
int i;
char szName[MS_MAX_NAME];
for (i = 0; i < nNumMaterials && !bError; i++)
{
msMaterial& Material = m_pModel->Materials[i];
// name
if (!fgets (szLine, 256, file))
{
bError = true;
break;
}
if (sscanf (szLine, "\"%[^\"]\"", szName) != 1)
{
bError = true;
break;
}
strcpy( Material.szName, szName );
// ambient
if (!fgets (szLine, 256, file))
{
bError = true;
break;
}
msVec4 Ambient;
if (sscanf (szLine, "%f %f %f %f", &Ambient.v[0], &Ambient.v[1], &Ambient.v[2], &Ambient.v[3]) != 4)
{
bError = true;
break;
}
memcpy( &Material.Ambient, &Ambient, sizeof(Material.Ambient) );
// diffuse
if (!fgets (szLine, 256, file))
{
bError = true;
break;
}
msVec4 Diffuse;
if (sscanf (szLine, "%f %f %f %f", &Diffuse.v[0], &Diffuse.v[1], &Diffuse.v[2], &Diffuse.v[3]) != 4)
{
bError = true;
break;
}
memcpy( &Material.Diffuse, &Diffuse, sizeof(Material.Diffuse) );
// specular
if (!fgets (szLine, 256, file))
{
bError = true;
break;
}
msVec4 Specular;
if (sscanf (szLine, "%f %f %f %f", &Specular.v[0], &Specular.v[1], &Specular.v[2], &Specular.v[3]) != 4)
{
bError = true;
break;
}
memcpy( &Material.Specular, &Specular, sizeof(Material.Specular) );
// emissive
if (!fgets (szLine, 256, file))
{
bError = true;
break;
}
msVec4 Emissive;
if (sscanf (szLine, "%f %f %f %f", &Emissive.v[0], &Emissive.v[1], &Emissive.v[2], &Emissive.v[3]) != 4)
{
bError = true;
break;
}
memcpy( &Material.Emissive, &Emissive, sizeof(Material.Emissive) );
// shininess
if (!fgets (szLine, 256, file))
{
bError = true;
break;
}
float fShininess;
if (sscanf (szLine, "%f", &fShininess) != 1)
{
bError = true;
break;
}
Material.fShininess = fShininess;
// transparency
if (!fgets (szLine, 256, file))
{
bError = true;
break;
}
float fTransparency;
if (sscanf (szLine, "%f", &fTransparency) != 1)
{
bError = true;
break;
}
Material.fTransparency = fTransparency;
// diffuse texture
if (!fgets (szLine, 256, file))
{
bError = true;
break;
}
strcpy (szName, "");
sscanf (szLine, "\"%[^\"]\"", szName);
strcpy( Material.szDiffuseTexture, szName );
// alpha texture
if (!fgets (szLine, 256, file))
{
bError = true;
break;
}
strcpy (szName, "");
sscanf (szLine, "\"%[^\"]\"", szName);
strcpy( Material.szAlphaTexture, szName );
Material.pTexture = NULL;
if( strcmp(Material.szDiffuseTexture, "")!=0 )
{
RageTextureID ID;
ID.filename = sDir+Material.szDiffuseTexture;
ID.bStretch = true;
if( DoesFileExist(ID.filename) )
Material.pTexture = TEXTUREMAN->LoadTexture( ID );
}
}
}
//
// bones
//
int nNumBones = 0;
if (sscanf (szLine, "Bones: %d", &nNumBones) == 1)
{
int i;
char szName[MS_MAX_NAME];
m_pModel->Bones.resize( nNumBones );
for (i = 0; i < nNumBones && !bError; i++)
{
msBone& Bone = m_pModel->Bones[i];
// name
if (!fgets (szLine, 256, file))
{
bError = true;
break;
}
if (sscanf (szLine, "\"%[^\"]\"", szName) != 1)
{
bError = true;
break;
}
strcpy( Bone.szName, szName );
// parent
if (!fgets (szLine, 256, file))
{
bError = true;
break;
}
strcpy (szName, "");
sscanf (szLine, "\"%[^\"]\"", szName);
strcpy( Bone.szParentName, szName );
// flags, position, rotation
msVec3 Position, Rotation;
if (!fgets (szLine, 256, file))
{
bError = true;
break;
}
if (sscanf (szLine, "%d %f %f %f %f %f %f",
&nFlags,
&Position.v[0], &Position.v[1], &Position.v[2],
&Rotation.v[0], &Rotation.v[1], &Rotation.v[2]) != 7)
{
bError = true;
break;
}
Bone.nFlags = nFlags;
memcpy( &Bone.Position, &Position, sizeof(Bone.Position) );
memcpy( &Bone.Rotation, &Rotation, sizeof(Bone.Rotation) );
float fTime;
// position key count
if (!fgets (szLine, 256, file))
{
bError = true;
break;
}
int nNumPositionKeys = 0;
if (sscanf (szLine, "%d", &nNumPositionKeys) != 1)
{
bError = true;
break;
}
Bone.PositionKeys.resize( nNumPositionKeys );
for (j = 0; j < nNumPositionKeys; j++)
{
if (!fgets (szLine, 256, file))
{
bError = true;
break;
}
if (sscanf (szLine, "%f %f %f %f", &fTime, &Position[0], &Position[1], &Position[2]) != 4)
{
bError = true;
break;
}
msPositionKey key = { fTime, { Position[0], Position[1], Position[2] } };
Bone.PositionKeys[j] = key;
}
// rotation key count
if (!fgets (szLine, 256, file))
{
bError = true;
break;
}
int nNumRotationKeys = 0;
if (sscanf (szLine, "%d", &nNumRotationKeys) != 1)
{
bError = true;
break;
}
Bone.RotationKeys.resize( nNumRotationKeys );
for (j = 0; j < nNumRotationKeys; j++)
{
if (!fgets (szLine, 256, file))
{
bError = true;
break;
}
if (sscanf (szLine, "%f %f %f %f", &fTime, &Rotation[0], &Rotation[1], &Rotation[2]) != 4)
{
bError = true;
break;
}
msRotationKey key = { fTime, { Rotation[0], Rotation[1], Rotation[2] } };
Bone.RotationKeys[j] = key;
}
}
}
}
fclose (file);
LoadMilkshapeAsciiBones( sPath );
// Setup temp vertices
m_vTempVerticesByBone.resize( m_pModel->Meshes.size() );
for (i = 0; i < m_pModel->Meshes.size(); i++)
{
msMesh& Mesh = m_pModel->Meshes[i];
m_vTempVerticesByBone[i].resize( Mesh.Vertices.size() );
}
return true;
}
bool Model::LoadMilkshapeAsciiBones( CString sPath )
{
CString sDir, sThrowAway;
splitrelpath( sPath, sDir, sThrowAway, sThrowAway );
FILE *file = fopen (sPath, "rt");
if (!file)
RageException::Throw( "Model:: Could not open '%s'.", sPath.c_str() );
bool bError = false;
char szLine[256];
int nFlags, j;
while (fgets (szLine, 256, file) != NULL && !bError)
{
if (!strncmp (szLine, "//", 2))
continue;
//
// bones
//
int nNumBones = 0;
if (sscanf (szLine, "Bones: %d", &nNumBones) == 1)
{
int i;
char szName[MS_MAX_NAME];
m_pModel->Bones.resize( nNumBones );
for (i = 0; i < nNumBones && !bError; i++)
{
msBone& Bone = m_pModel->Bones[i];
// name
if (!fgets (szLine, 256, file))
{
bError = true;
break;
}
if (sscanf (szLine, "\"%[^\"]\"", szName) != 1)
{
bError = true;
break;
}
strcpy( Bone.szName, szName );
// parent
if (!fgets (szLine, 256, file))
{
bError = true;
break;
}
strcpy (szName, "");
sscanf (szLine, "\"%[^\"]\"", szName);
strcpy( Bone.szParentName, szName );
// flags, position, rotation
msVec3 Position, Rotation;
if (!fgets (szLine, 256, file))
{
bError = true;
break;
}
if (sscanf (szLine, "%d %f %f %f %f %f %f",
&nFlags,
&Position.v[0], &Position.v[1], &Position.v[2],
&Rotation.v[0], &Rotation.v[1], &Rotation.v[2]) != 7)
{
bError = true;
break;
}
Bone.nFlags = nFlags;
memcpy( &Bone.Position, &Position, sizeof(Bone.Position) );
memcpy( &Bone.Rotation, &Rotation, sizeof(Bone.Rotation) );
float fTime;
// position key count
if (!fgets (szLine, 256, file))
{
bError = true;
break;
}
int nNumPositionKeys = 0;
if (sscanf (szLine, "%d", &nNumPositionKeys) != 1)
{
bError = true;
break;
}
Bone.PositionKeys.resize( nNumPositionKeys );
for (j = 0; j < nNumPositionKeys; j++)
{
if (!fgets (szLine, 256, file))
{
bError = true;
break;
}
if (sscanf (szLine, "%f %f %f %f", &fTime, &Position[0], &Position[1], &Position[2]) != 4)
{
bError = true;
break;
}
msPositionKey key = { fTime, { Position[0], Position[1], Position[2] } };
Bone.PositionKeys[j] = key;
}
// rotation key count
if (!fgets (szLine, 256, file))
{
bError = true;
break;
}
int nNumRotationKeys = 0;
if (sscanf (szLine, "%d", &nNumRotationKeys) != 1)
{
bError = true;
break;
}
Bone.RotationKeys.resize( nNumRotationKeys );
for (j = 0; j < nNumRotationKeys; j++)
{
if (!fgets (szLine, 256, file))
{
bError = true;
break;
}
if (sscanf (szLine, "%f %f %f %f", &fTime, &Rotation[0], &Rotation[1], &Rotation[2]) != 4)
{
bError = true;
break;
}
msRotationKey key = { fTime, { Rotation[0], Rotation[1], Rotation[2] } };
Bone.RotationKeys[j] = key;
}
}
}
}
// ignore "Frames:" in file
m_pModel->nTotalFrames = 0;
for (int i = 0; i < m_pModel->Bones.size(); i++)
{
msBone& Bone = m_pModel->Bones[i];
for( int j=0; j<Bone.PositionKeys.size(); j++ )
{
m_pModel->nTotalFrames = max( m_pModel->nTotalFrames, Bone.PositionKeys[j].fTime );
m_pModel->nTotalFrames = max( m_pModel->nTotalFrames, Bone.RotationKeys[j].fTime );
}
}
SetupBones ();
return true;
}
#include "SDL_opengl.h"
#include "RageTimer.h"
void Model::DrawPrimitives()
{
if (!m_pModel)
return;
DISPLAY->Scale( 0, -1, 0 ); // flip so positive Y is up
DISPLAY->SetBlendModeNormal();
DISPLAY->EnableZBuffer();
for (int i = 0; i < (int)m_pModel->Meshes.size(); i++)
{
msMesh *pMesh = &m_pModel->Meshes[i];
RageVertexVector& TempVertices = m_vTempVerticesByBone[i];
// apply material
if( pMesh->nMaterialIndex != -1 )
{
msMaterial& mat = m_pModel->Materials[ pMesh->nMaterialIndex ];
DISPLAY->SetMaterial(
mat.Emissive,
mat.Ambient,
mat.Diffuse,
mat.Specular,
mat.fShininess );
DISPLAY->SetTexture( mat.pTexture );
}
else
{
float emissive[4] = {0,0,0,0};
float ambient[4] = {0.2f,0.2f,0.2f,1};
float diffuse[4] = {0.7f,0.7f,0.7f,1};
float specular[4] = {0.2f,0.2f,0.2f,1};
float shininess = 1;
DISPLAY->SetMaterial(
emissive,
ambient,
diffuse,
specular,
shininess );
DISPLAY->SetTexture( NULL );
}
// process vertices
for (int j = 0; j < (int)pMesh->Vertices.size(); j++)
{
RageVertex& tempVert = TempVertices[j];
msVertex& originalVert = pMesh->Vertices[j];
tempVert.c = RageColor(1,1,1,1);
memcpy( &tempVert.t, originalVert.uv, sizeof(originalVert.uv) );
if( originalVert.nBoneIndex == -1 )
{
memcpy( &tempVert.n, originalVert.Normal, sizeof(originalVert.Normal) );
memcpy( &tempVert.p, originalVert.Vertex, sizeof(originalVert.Vertex) );
}
else
{
VectorRotate (originalVert.Normal, m_pBones[originalVert.nBoneIndex].mFinal, tempVert.n);
int bone = originalVert.nBoneIndex;
VectorRotate (originalVert.Vertex, m_pBones[originalVert.nBoneIndex].mFinal, tempVert.p);
tempVert.p[0] += m_pBones[bone].mFinal[0][3];
tempVert.p[1] += m_pBones[bone].mFinal[1][3];
tempVert.p[2] += m_pBones[bone].mFinal[2][3];
}
}
DISPLAY->DrawIndexedTriangles( &TempVertices[0], (Uint16*)&pMesh->Triangles[0], pMesh->Triangles.size()*3 );
}
DISPLAY->DisableZBuffer();
}
float
Model::CalcDistance () const
{
float dx = m_vMaxs[0] - m_vMins[0];
float dy = m_vMaxs[1] - m_vMins[1];
float dz = m_vMaxs[2] - m_vMins[2];
float d = dx;
if (dy > d)
d = dy;
if (dz > d)
d = dz;
return d;
}
void
Model::SetupBones ()
{
int nBoneCount = (int)m_pModel->Bones.size();
if (!m_pBones)
{
m_pBones = new myBone_t[nBoneCount];
}
int i, j;
for (i = 0; i < nBoneCount; i++)
{
msBone *pBone = &m_pModel->Bones[i];
msVec3 vRot;
vRot[0] = pBone->Rotation[0] * 180 / (float) Q_PI;
vRot[1] = pBone->Rotation[1] * 180 / (float) Q_PI;
vRot[2] = pBone->Rotation[2] * 180 / (float) Q_PI;
AngleMatrix (vRot, m_pBones[i].mRelative);
m_pBones[i].mRelative[0][3] = pBone->Position[0];
m_pBones[i].mRelative[1][3] = pBone->Position[1];
m_pBones[i].mRelative[2][3] = pBone->Position[2];
int nParentBone = m_pModel->FindBoneByName( pBone->szParentName );
if (nParentBone != -1)
{
R_ConcatTransforms (m_pBones[nParentBone].mAbsolute, m_pBones[i].mRelative, m_pBones[i].mAbsolute);
memcpy (m_pBones[i].mFinal, m_pBones[i].mAbsolute, sizeof (matrix_t));
}
else
{
memcpy (m_pBones[i].mAbsolute, m_pBones[i].mRelative, sizeof (matrix_t));
memcpy (m_pBones[i].mFinal, m_pBones[i].mRelative, sizeof (matrix_t));
}
}
for (i = 0; i < m_pModel->Meshes.size(); i++)
{
msMesh *pMesh = &m_pModel->Meshes[i];
for (j = 0; j < (int)pMesh->Vertices.size(); j++)
{
msVertex *pVertex = &pMesh->Vertices[j];
if (pVertex->nBoneIndex != -1)
{
pVertex->Vertex[0] -= m_pBones[pVertex->nBoneIndex].mAbsolute[0][3];
pVertex->Vertex[1] -= m_pBones[pVertex->nBoneIndex].mAbsolute[1][3];
pVertex->Vertex[2] -= m_pBones[pVertex->nBoneIndex].mAbsolute[2][3];
msVec3 vTmp;
VectorIRotate (pVertex->Vertex, m_pBones[pVertex->nBoneIndex].mAbsolute, vTmp);
VectorCopy (vTmp, pVertex->Vertex);
}
}
}
m_fCurrFrame = (float) m_pModel->nFrame;
}
void
Model::AdvanceFrame (float dt)
{
if (!m_pModel)
return;
m_fCurrFrame += FRAMES_PER_SECOND * dt;
if (m_fCurrFrame > (float) m_pModel->nTotalFrames)
m_fCurrFrame = 0.0f;
int nBoneCount = (int)m_pModel->Bones.size();
int i, j;
for (i = 0; i < nBoneCount; i++)
{
msBone *pBone = &m_pModel->Bones[i];
int nPositionKeyCount = pBone->PositionKeys.size();
int nRotationKeyCount = pBone->RotationKeys.size();
if (nPositionKeyCount == 0 && nRotationKeyCount == 0)
{
memcpy (m_pBones[i].mFinal, m_pBones[i].mAbsolute, sizeof (matrix_t));
}
else
{
msVec3 vPos;
msVec4 vRot;
//
// search for the adjaced position keys
//
msPositionKey *pLastPositionKey = 0, *pThisPositionKey = 0;
for (j = 0; j < nPositionKeyCount; j++)
{
msPositionKey *pPositionKey = &pBone->PositionKeys[j];
if (pPositionKey->fTime >= m_fCurrFrame)
{
pThisPositionKey = pPositionKey;
break;
}
pLastPositionKey = pPositionKey;
}
if (pLastPositionKey != 0 && pThisPositionKey != 0)
{
float d = pThisPositionKey->fTime - pLastPositionKey->fTime;
float s = (m_fCurrFrame - pLastPositionKey->fTime) / d;
vPos[0] = pLastPositionKey->Position[0] + (pThisPositionKey->Position[0] - pLastPositionKey->Position[0]) * s;
vPos[1] = pLastPositionKey->Position[1] + (pThisPositionKey->Position[1] - pLastPositionKey->Position[1]) * s;
vPos[2] = pLastPositionKey->Position[2] + (pThisPositionKey->Position[2] - pLastPositionKey->Position[2]) * s;
}
else if (pLastPositionKey == 0)
{
VectorCopy (pThisPositionKey->Position, vPos);
}
else if (pThisPositionKey == 0)
{
VectorCopy (pLastPositionKey->Position, vPos);
}
//
// search for the adjaced rotation keys
//
matrix_t m;
msRotationKey *pLastRotationKey = 0, *pThisRotationKey = 0;
for (j = 0; j < nRotationKeyCount; j++)
{
msRotationKey *pRotationKey = &pBone->RotationKeys[j];
if (pRotationKey->fTime >= m_fCurrFrame)
{
pThisRotationKey = pRotationKey;
break;
}
pLastRotationKey = pRotationKey;
}
if (pLastRotationKey != 0 && pThisRotationKey != 0)
{
float d = pThisRotationKey->fTime - pLastRotationKey->fTime;
float s = (m_fCurrFrame - pLastRotationKey->fTime) / d;
#if 1
msVec4 q1, q2, q;
AngleQuaternion (pLastRotationKey->Rotation, q1);
AngleQuaternion (pThisRotationKey->Rotation, q2);
QuaternionSlerp (q1, q2, s, q);
QuaternionMatrix (q, m);
#else
vRot[0] = pLastRotationKey->Rotation[0] + (pThisRotationKey->Rotation[0] - pLastRotationKey->Rotation[0]) * s;
vRot[1] = pLastRotationKey->Rotation[1] + (pThisRotationKey->Rotation[1] - pLastRotationKey->Rotation[1]) * s;
vRot[2] = pLastRotationKey->Rotation[2] + (pThisRotationKey->Rotation[2] - pLastRotationKey->Rotation[2]) * s;
vRot[0] *= 180 / (float) Q_PI;
vRot[1] *= 180 / (float) Q_PI;
vRot[2] *= 180 / (float) Q_PI;
AngleMatrix (vRot, m);
#endif
}
else if (pLastRotationKey == 0)
{
vRot[0] = pThisRotationKey->Rotation[0] * 180 / (float) Q_PI;
vRot[1] = pThisRotationKey->Rotation[1] * 180 / (float) Q_PI;
vRot[2] = pThisRotationKey->Rotation[2] * 180 / (float) Q_PI;
AngleMatrix (vRot, m);
}
else if (pThisRotationKey == 0)
{
vRot[0] = pLastRotationKey->Rotation[0] * 180 / (float) Q_PI;
vRot[1] = pLastRotationKey->Rotation[1] * 180 / (float) Q_PI;
vRot[2] = pLastRotationKey->Rotation[2] * 180 / (float) Q_PI;
AngleMatrix (vRot, m);
}
m[0][3] = vPos[0];
m[1][3] = vPos[1];
m[2][3] = vPos[2];
R_ConcatTransforms (m_pBones[i].mRelative, m, m_pBones[i].mRelativeFinal);
int nParentBone = m_pModel->FindBoneByName( pBone->szParentName );
if (nParentBone == -1)
{
memcpy (m_pBones[i].mFinal, m_pBones[i].mRelativeFinal, sizeof (matrix_t));
}
else
{
R_ConcatTransforms (m_pBones[nParentBone].mFinal, m_pBones[i].mRelativeFinal, m_pBones[i].mFinal);
}
}
}
}
void Model::Update( float fDelta )
{
Actor::Update( fDelta );
AdvanceFrame( fDelta );
}