From 739cc6d38babc5b739726d745d6da14c4d2f10db Mon Sep 17 00:00:00 2001 From: Chris Danford Date: Sat, 7 Jun 2003 18:09:20 +0000 Subject: [PATCH] support loading of multiple animations in a Model --- stepmania/src/DancingCharacters.cpp | 15 +- stepmania/src/Model.cpp | 269 +++++++--------------------- stepmania/src/Model.h | 35 ++-- stepmania/src/ModelTypes.h | 8 +- 4 files changed, 107 insertions(+), 220 deletions(-) diff --git a/stepmania/src/DancingCharacters.cpp b/stepmania/src/DancingCharacters.cpp index c2bc47e241..d5b185f15b 100644 --- a/stepmania/src/DancingCharacters.cpp +++ b/stepmania/src/DancingCharacters.cpp @@ -34,12 +34,18 @@ DancingCharacters::DancingCharacters() { m_Character[PLAYER_1].SetX( MODEL_X[PLAYER_1] ); m_Character[PLAYER_1].LoadMilkshapeAscii( "C:\\My Documents\\Dev\\ddrpc char hacking\\DDRPCRip\\models\\char0000\\model.txt" ); - m_Character[PLAYER_1].LoadMilkshapeAsciiBones( "C:\\My Documents\\Dev\\ddrpc char hacking\\DDRPCRip\\models\\dance0001.bones.txt" ); + m_Character[PLAYER_1].LoadMilkshapeAsciiBones( "rest", "C:\\My Documents\\Dev\\ddrpc char hacking\\DDRPCRip\\models\\rest.bones.txt" ); + m_Character[PLAYER_1].LoadMilkshapeAsciiBones( "warmup", "C:\\My Documents\\Dev\\ddrpc char hacking\\DDRPCRip\\models\\warmup.bones.txt" ); + m_Character[PLAYER_1].LoadMilkshapeAsciiBones( "default", "C:\\My Documents\\Dev\\ddrpc char hacking\\DDRPCRip\\models\\dance0001.bones.txt" ); + m_Character[PLAYER_1].PlayAnimation( "rest" ); this->AddChild( &m_Character[PLAYER_1] ); m_Character[PLAYER_2].SetX( MODEL_X[PLAYER_2] ); m_Character[PLAYER_2].LoadMilkshapeAscii( "C:\\My Documents\\Dev\\ddrpc char hacking\\DDRPCRip\\models\\char0011\\model.txt" ); - m_Character[PLAYER_2].LoadMilkshapeAsciiBones( "C:\\My Documents\\Dev\\ddrpc char hacking\\DDRPCRip\\models\\dance0002.bones.txt" ); + m_Character[PLAYER_2].LoadMilkshapeAsciiBones( "rest", "C:\\My Documents\\Dev\\ddrpc char hacking\\DDRPCRip\\models\\rest.bones.txt" ); + m_Character[PLAYER_2].LoadMilkshapeAsciiBones( "warmup", "C:\\My Documents\\Dev\\ddrpc char hacking\\DDRPCRip\\models\\warmup.bones.txt" ); + m_Character[PLAYER_2].LoadMilkshapeAsciiBones( "default", "C:\\My Documents\\Dev\\ddrpc char hacking\\DDRPCRip\\models\\dance0001.bones.txt" ); + m_Character[PLAYER_2].PlayAnimation( "rest" ); this->AddChild( &m_Character[PLAYER_2] ); StartCameraSweep(); @@ -49,6 +55,11 @@ DancingCharacters::DancingCharacters() void DancingCharacters::Update( float fDelta ) { ActorFrame::Update( fDelta ); + + if( PREFSMAN->m_bShowDancingCharacters ) + { + + } // update camera sweep m_fSecsIntoSweep += fDelta; diff --git a/stepmania/src/Model.cpp b/stepmania/src/Model.cpp index cd4237da67..c1e770eaed 100644 --- a/stepmania/src/Model.cpp +++ b/stepmania/src/Model.cpp @@ -19,13 +19,14 @@ const float FRAMES_PER_SECOND = 30; +const CString DEFAULT_ANIMATION_NAME = "default"; Model::Model () { - m_pModel = NULL; m_pBones = NULL; m_bTextureWrapping = true; m_bUseZBuffer = true; + m_pCurAnimation = NULL; } Model::~Model () @@ -38,8 +39,10 @@ void Model::Clear () delete[] m_pBones; m_pBones = NULL; - delete m_pModel; - m_pModel = NULL; + m_Meshes.clear(); + m_Materials.clear(); + m_mapNameToAnimation.clear(); + m_pCurAnimation = NULL; } bool Model::LoadFromModelFile( CString sPath ) @@ -80,10 +83,6 @@ bool Model::LoadMilkshapeAscii( CString sPath ) 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]; @@ -99,21 +98,23 @@ bool Model::LoadMilkshapeAscii( CString sPath ) int nFrame; if (sscanf (szLine, "Frames: %d", &nFrame) == 1) { - m_pModel->nTotalFrames = nFrame; + // ignore + // m_pModel->nTotalFrames = nFrame; } if (sscanf (szLine, "Frame: %d", &nFrame) == 1) { - m_pModel->nFrame = nFrame; + // ignore + // m_pModel->nFrame = nFrame; } int nNumMeshes = 0; if (sscanf (szLine, "Meshes: %d", &nNumMeshes) == 1) { - m_pModel->Meshes.resize( nNumMeshes ); + m_Meshes.resize( nNumMeshes ); for (i = 0; i < nNumMeshes && !bError; i++) { - msMesh& mesh = m_pModel->Meshes[i]; + msMesh& mesh = m_Meshes[i]; if (!fgets (szLine, 256, file)) { @@ -282,14 +283,14 @@ bool Model::LoadMilkshapeAscii( CString sPath ) int nNumMaterials = 0; if (sscanf (szLine, "Materials: %d", &nNumMaterials) == 1) { - m_pModel->Materials.resize( nNumMaterials ); + m_Materials.resize( nNumMaterials ); int i; char szName[MS_MAX_NAME]; for (i = 0; i < nNumMaterials && !bError; i++) { - msMaterial& Material = m_pModel->Materials[i]; + msMaterial& Material = m_Materials[i]; // name if (!fgets (szLine, 256, file)) @@ -415,150 +416,24 @@ bool Model::LoadMilkshapeAscii( CString sPath ) } } } - - // - // 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 ); + LoadMilkshapeAsciiBones( DEFAULT_ANIMATION_NAME, sPath ); // Setup temp vertices - m_vTempVerticesByBone.resize( m_pModel->Meshes.size() ); - for (i = 0; i < (int)m_pModel->Meshes.size(); i++) + m_vTempVerticesByBone.resize( m_Meshes.size() ); + for (i = 0; i < (int)m_Meshes.size(); i++) { - msMesh& Mesh = m_pModel->Meshes[i]; + msMesh& Mesh = m_Meshes[i]; m_vTempVerticesByBone[i].resize( Mesh.Vertices.size() ); } return true; } -bool Model::LoadMilkshapeAsciiBones( CString sPath ) +bool Model::LoadMilkshapeAsciiBones( CString sAniName, CString sPath ) { CString sDir, sThrowAway; splitrelpath( sPath, sDir, sThrowAway, sThrowAway ); @@ -582,14 +457,17 @@ bool Model::LoadMilkshapeAsciiBones( CString sPath ) int nNumBones = 0; if (sscanf (szLine, "Bones: %d", &nNumBones) == 1) { + m_mapNameToAnimation[sAniName] = msAnimation(); + msAnimation &Animation = m_mapNameToAnimation[sAniName]; + int i; char szName[MS_MAX_NAME]; - m_pModel->Bones.resize( nNumBones ); + Animation.Bones.resize( nNumBones ); for (i = 0; i < nNumBones && !bError; i++) { - msBone& Bone = m_pModel->Bones[i]; + msBone& Bone = Animation.Bones[i]; // name if (!fgets (szLine, 256, file)) @@ -700,22 +578,23 @@ bool Model::LoadMilkshapeAsciiBones( CString sPath ) Bone.RotationKeys[j] = key; } } + + // Ignore "Frames:" in file. Calculate it ourself + Animation.nTotalFrames = 0; + for ( i = 0; i < (int)Animation.Bones.size(); i++) + { + msBone& Bone = Animation.Bones[i]; + for( int j=0; j<(int)Bone.PositionKeys.size(); j++ ) + { + Animation.nTotalFrames = max( Animation.nTotalFrames, (int)Bone.PositionKeys[j].fTime+1 ); + Animation.nTotalFrames = max( Animation.nTotalFrames, (int)Bone.RotationKeys[j].fTime+1 ); + } + } + + PlayAnimation( sAniName ); } } - // ignore "Frames:" in file - m_pModel->nTotalFrames = 0; - for (int i = 0; i < (int)m_pModel->Bones.size(); i++) - { - msBone& Bone = m_pModel->Bones[i]; - for( int j=0; j<(int)Bone.PositionKeys.size(); j++ ) - { - m_pModel->nTotalFrames = max( m_pModel->nTotalFrames, (int)Bone.PositionKeys[j].fTime+1 ); - m_pModel->nTotalFrames = max( m_pModel->nTotalFrames, (int)Bone.RotationKeys[j].fTime+1 ); - } - } - - SetupBones (); return true; } @@ -725,22 +604,22 @@ bool Model::LoadMilkshapeAsciiBones( CString sPath ) void Model::DrawPrimitives() { - if (!m_pModel) - return; + if(m_Meshes.empty()) + return; // bail early Actor::SetRenderStates(); // set Actor-specified render states DISPLAY->Scale( 1, -1, 1 ); // flip Y so positive is up - for (int i = 0; i < (int)m_pModel->Meshes.size(); i++) + for (int i = 0; i < (int)m_Meshes.size(); i++) { - msMesh *pMesh = &m_pModel->Meshes[i]; + msMesh *pMesh = &m_Meshes[i]; RageVertexVector& TempVertices = m_vTempVerticesByBone[i]; // apply material if( pMesh->nMaterialIndex != -1 ) { - msMaterial& mat = m_pModel->Materials[ pMesh->nMaterialIndex ]; + msMaterial& mat = m_Materials[ pMesh->nMaterialIndex ]; DISPLAY->SetMaterial( mat.Emissive, mat.Ambient, @@ -801,25 +680,16 @@ void Model::DrawPrimitives() } -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 () +void Model::PlayAnimation( CString sAniName ) { - int nBoneCount = (int)m_pModel->Bones.size(); + if( m_mapNameToAnimation.find(sAniName) == m_mapNameToAnimation.end() ) + return; + else + m_pCurAnimation = &m_mapNameToAnimation[sAniName]; + + // setup bones + int nBoneCount = (int)m_pCurAnimation->Bones.size(); if (!m_pBones) { m_pBones = new myBone_t[nBoneCount]; @@ -828,7 +698,7 @@ Model::SetupBones () int i, j; for (i = 0; i < nBoneCount; i++) { - msBone *pBone = &m_pModel->Bones[i]; + msBone *pBone = &m_pCurAnimation->Bones[i]; msVec3 vRot; vRot[0] = pBone->Rotation[0] * 180 / (float) Q_PI; vRot[1] = pBone->Rotation[1] * 180 / (float) Q_PI; @@ -838,7 +708,7 @@ Model::SetupBones () 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 ); + int nParentBone = m_pCurAnimation->FindBoneByName( pBone->szParentName ); if (nParentBone != -1) { R_ConcatTransforms (m_pBones[nParentBone].mAbsolute, m_pBones[i].mRelative, m_pBones[i].mAbsolute); @@ -851,9 +721,9 @@ Model::SetupBones () } } - for (i = 0; i < (int)m_pModel->Meshes.size(); i++) + for (i = 0; i < (int)m_Meshes.size(); i++) { - msMesh *pMesh = &m_pModel->Meshes[i]; + msMesh *pMesh = &m_Meshes[i]; for (j = 0; j < (int)pMesh->Vertices.size(); j++) { msVertex *pVertex = &pMesh->Vertices[j]; @@ -869,24 +739,24 @@ Model::SetupBones () } } - m_fCurrFrame = (float) m_pModel->nFrame; + m_fCurrFrame = 0; } void Model::AdvanceFrame (float dt) { - if (!m_pModel) - return; + if( m_Meshes.empty() || !m_pCurAnimation ) + return; // bail early m_fCurrFrame += FRAMES_PER_SECOND * dt; - if (m_fCurrFrame > (float) m_pModel->nTotalFrames) + if (m_fCurrFrame > (float) m_pCurAnimation->nTotalFrames) m_fCurrFrame = 0.0f; - int nBoneCount = (int)m_pModel->Bones.size(); + int nBoneCount = (int)m_pCurAnimation->Bones.size(); int i, j; for (i = 0; i < nBoneCount; i++) { - msBone *pBone = &m_pModel->Bones[i]; + msBone *pBone = &m_pCurAnimation->Bones[i]; int nPositionKeyCount = pBone->PositionKeys.size(); int nRotationKeyCount = pBone->RotationKeys.size(); if (nPositionKeyCount == 0 && nRotationKeyCount == 0) @@ -980,7 +850,7 @@ Model::AdvanceFrame (float dt) 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 ); + int nParentBone = m_pCurAnimation->FindBoneByName( pBone->szParentName ); if (nParentBone == -1) { memcpy (m_pBones[i].mFinal, m_pBones[i].mRelativeFinal, sizeof (matrix_t)); @@ -997,23 +867,20 @@ void Model::Update( float fDelta ) { Actor::Update( fDelta ); AdvanceFrame( fDelta ); - if( m_pModel ) - for( int i=0; i<(int)m_pModel->Materials.size(); i++ ) - m_pModel->Materials[i].aniTexture.Update( fDelta ); + for( int i=0; i<(int)m_Materials.size(); i++ ) + m_Materials[i].aniTexture.Update( fDelta ); } void Model::SetState( int iNewState ) { - if( m_pModel ) - for( int i=0; i<(int)m_pModel->Materials.size(); i++ ) - m_pModel->Materials[i].aniTexture.SetState( iNewState ); + for( int i=0; i<(int)m_Materials.size(); i++ ) + m_Materials[i].aniTexture.SetState( iNewState ); } int Model::GetNumStates() { int iMaxStates = 0; - if( m_pModel ) - for( int i=0; i<(int)m_pModel->Materials.size(); i++ ) - iMaxStates = max( iMaxStates, m_pModel->Materials[i].aniTexture.GetNumStates() ); + for( int i=0; i<(int)m_Materials.size(); i++ ) + iMaxStates = max( iMaxStates, m_Materials[i].aniTexture.GetNumStates() ); return iMaxStates; } diff --git a/stepmania/src/Model.h b/stepmania/src/Model.h index c42d599048..1b2d41775a 100644 --- a/stepmania/src/Model.h +++ b/stepmania/src/Model.h @@ -13,7 +13,9 @@ #include "Actor.h" #include "RageTypes.h" +#include "ModelTypes.h" #include +#include struct msModel; @@ -35,24 +37,23 @@ public: public: void Clear (); - void Load( CString sPath ) + void Load( CString sFile ) { - if( sPath == "" ) return; - if( sPath.Right(6) == ".model" ) - LoadFromModelFile( sPath ); + if( sFile == "" ) return; + if( sFile.Right(6) == ".model" ) + LoadFromModelFile( sFile ); else - LoadMilkshapeAscii( sPath ); + LoadMilkshapeAscii( sFile ); }; - bool LoadFromModelFile( CString sPath ); - bool LoadMilkshapeAscii( CString sPath ); - bool LoadMilkshapeAsciiBones( CString sPath ); + bool LoadFromModelFile( CString sFile ); + bool LoadMilkshapeAscii( CString sFile ); + bool LoadMilkshapeAsciiBones( CString sAniName, CString sFile ); + void PlayAnimation( CString sAniName ); virtual void Update( float fDelta ); virtual void DrawPrimitives(); - float CalcDistance () const; - void SetupBones (); void AdvanceFrame (float dt); virtual void SetState( int iNewState ); @@ -60,12 +61,16 @@ public: private: - msModel *m_pModel; - RageVector3 m_vMins, m_vMaxs; - myBone_t *m_pBones; - typedef vector RageVertexVector; + vector m_Meshes; + vector m_Materials; + map m_mapNameToAnimation; + msAnimation* m_pCurAnimation; + + RageVector3 m_vMins, m_vMaxs; + myBone_t *m_pBones; + typedef vector RageVertexVector; vector m_vTempVerticesByBone; - float m_fCurrFrame; + float m_fCurrFrame; }; diff --git a/stepmania/src/ModelTypes.h b/stepmania/src/ModelTypes.h index e2d3682567..6494694625 100644 --- a/stepmania/src/ModelTypes.h +++ b/stepmania/src/ModelTypes.h @@ -170,7 +170,10 @@ typedef struct msModel vector Meshes; vector Materials; +} msModel; +struct msAnimation +{ vector Bones; int FindBoneByName( const char* szName ) @@ -181,11 +184,12 @@ typedef struct msModel return -1; } - int nFrame; + // not used +// int nFrame; int nTotalFrames; msVec3 Position; msVec3 Rotation; -} msModel; +}; #endif