#include "include/Animation/SalmonAnimation.h" #include "include/Utils/Utils.h" #include "include/Engine.h" namespace SE { TAnimSequence::TAnimSequence(const TAnimSequence& animSeq) { BoneCount = animSeq.BoneCount; FrameCount = animSeq.FrameCount; BoneInfoMatrix = animSeq.BoneInfoMatrix; } TAnimSequence::~TAnimSequence() { Clear(); } TAnimSequence& TAnimSequence::operator=(const TAnimSequence& animSeq) { if (this == &animSeq) return *this; Clear(); BoneCount = animSeq.BoneCount; FrameCount = animSeq.FrameCount; BoneInfoMatrix = animSeq.BoneInfoMatrix; return *this; } void TAnimSequence::Clear() { BoneInfoMatrix.clear(); FrameCount = 0; BoneCount = 0; } bool TAnimSequence::LoadFromFileAn1(const std::string& fileName) { Clear(); int i,j; cardinal fSize; boost::shared_array fileData = CreateMemFromFile(fileName, fSize); if ((((char*)&fileData[0])[0] != 'A')|| (((char*)&fileData[0])[1] != 'N')|| (((char*)&fileData[0])[2] != 0)|| (((char*)&fileData[0])[3] != 1)) throw ErrorFileNotCorrect(fileName); if (fSize < 3) throw ErrorFileNotCorrect(fileName); BoneCount = fileData[1]; FrameCount = fileData[2]; BoneInfoMatrix.resize(FrameCount); for (i = 0; i < FrameCount; i++) BoneInfoMatrix[i].resize(BoneCount); //Shift from file pointer cardinal filePointer = 3; for (i=0; ifSize) { throw ErrorFileTooShort(fileName); } BoneInfoMatrix[i][j].Pos.v[0] = ((float*)&fileData[0])[filePointer++]; BoneInfoMatrix[i][j].Pos.v[1] = ((float*)&fileData[0])[filePointer++]; BoneInfoMatrix[i][j].Pos.v[2] = ((float*)&fileData[0])[filePointer++]; BoneInfoMatrix[i][j].Quat.v[0] = ((float*)&fileData[0])[filePointer++]; BoneInfoMatrix[i][j].Quat.v[1] = ((float*)&fileData[0])[filePointer++]; BoneInfoMatrix[i][j].Quat.v[2] = ((float*)&fileData[0])[filePointer++]; BoneInfoMatrix[i][j].Quat.v[3] = ((float*)&fileData[0])[filePointer++]; BoneInfoMatrix[i][j].Len = ((float*)&fileData[0])[filePointer++]; BoneInfoMatrix[i][j].Ancient = 0; //dummy } return true; } void TAnimSequence::ScaleAnimSequence(float s) { for (int i=0; i fileData = CreateMemFromFile(ResourceManager->PathToResources+fileName,fSize); if (fileData == NULL) throw ErrorFileNotLoaded(fileName); if ((((char*)&fileData[0])[0]!='B')|| (((char*)&fileData[0])[1]!='N')|| (((char*)&fileData[0])[2]!=0)|| (((char*)&fileData[0])[3]!=1)) throw ErrorFileNotCorrect(fileName); if (fSize < 3) throw ErrorFileNotCorrect(fileName); int boneCount = fileData[1]; int vertexCount = fileData[2]; //Shift from file pointer cardinal filePointer = 3; //temporary data storage TBoneStruct boneStruct; TVertexWeightStruct vertexWeightStruct; for (i=0; i fSize) throw ErrorFileTooShort(fileName); boneStruct.Pos.v[0] = ((float*)fileData[0])[filePointer++]; boneStruct.Pos.v[1] = ((float*)&fileData[0])[filePointer++]; boneStruct.Pos.v[2] = ((float*)&fileData[0])[filePointer++]; boneStruct.Quat.v[0] = ((float*)&fileData[0])[filePointer++]; boneStruct.Quat.v[1] = ((float*)&fileData[0])[filePointer++]; boneStruct.Quat.v[2] = ((float*)&fileData[0])[filePointer++]; boneStruct.Quat.v[3] = ((float*)&fileData[0])[filePointer++]; boneStruct.Len = ((float*)&fileData[0])[filePointer++]; boneStruct.Ancient = fileData[filePointer++]; BoneList.push_back(boneStruct); } for (i=0; i fSize) throw ErrorFileTooShort(fileName); vertexWeightStruct.WeightCount = fileData[filePointer++]; vertexWeightStruct.VertexBoneInfo.resize(3); vertexWeightStruct.VertexBoneInfo[0].BoneNum = fileData[filePointer++]; vertexWeightStruct.VertexBoneInfo[0].BoneWeight = ((float*)&fileData[0])[filePointer++]; vertexWeightStruct.VertexBoneInfo[1].BoneNum = fileData[filePointer++]; vertexWeightStruct.VertexBoneInfo[1].BoneWeight = ((float*)&fileData[0])[filePointer++]; vertexWeightStruct.VertexBoneInfo[2].BoneNum = fileData[filePointer++]; vertexWeightStruct.VertexBoneInfo[2].BoneWeight = ((float*)&fileData[0])[filePointer++]; VertexWeightList.push_back(vertexWeightStruct); } Ready = true; return true; } bool TAnimList::LoadBoneSystemFromFileBn2(const std::string& fileName) { Clear(); int i; cardinal fSize; boost::shared_array fileData = CreateMemFromFile(ResourceManager->PathToResources+fileName,fSize); if (fileData == NULL) throw ErrorFileNotLoaded(fileName); if (((reinterpret_cast(&fileData[0]))[0]!='B')|| ((reinterpret_cast(&fileData[0]))[1]!='N')|| ((reinterpret_cast(&fileData[0]))[2]!=0)|| ((reinterpret_cast(&fileData[0]))[3]!=2)) throw ErrorFileNotCorrect(fileName); if (fSize < 3) throw ErrorFileNotCorrect(fileName); int boneCount = fileData[1]; int vertexCount = fileData[2]; //Shift from file pointer cardinal filePointer = 3; //temporary data storage TBoneStruct boneStruct; TVertexWeightStruct vertexWeightStruct; for (i=0; i fSize) throw ErrorFileTooShort(fileName); boneStruct.Pos.v[0] = (reinterpret_cast(&fileData[0]))[filePointer++]; boneStruct.Pos.v[1] = (reinterpret_cast(&fileData[0]))[filePointer++]; boneStruct.Pos.v[2] = (reinterpret_cast(&fileData[0]))[filePointer++]; boneStruct.Quat.v[0] = (reinterpret_cast(&fileData[0]))[filePointer++]; boneStruct.Quat.v[1] = (reinterpret_cast(&fileData[0]))[filePointer++]; boneStruct.Quat.v[2] = (reinterpret_cast(&fileData[0]))[filePointer++]; boneStruct.Quat.v[3] = (reinterpret_cast(&fileData[0]))[filePointer++]; boneStruct.Len = (reinterpret_cast(&fileData[0]))[filePointer++]; boneStruct.Ancient = (reinterpret_cast(&fileData[0]))[filePointer++]; BoneList.push_back(boneStruct); } for (i=0; i fSize) throw ErrorFileTooShort(fileName); vertexWeightStruct.WeightCount = fileData[filePointer++]; vertexWeightStruct.VertexBoneInfo.resize(vertexWeightStruct.WeightCount); TBoneWeightStruct boneWeightStructZero; boneWeightStructZero.BoneNum = -1; boneWeightStructZero.BoneWeight = -1; for (cardinal j=0; j(&fileData[0]))[filePointer++]; vertexWeightStruct.VertexBoneInfo[j] = boneWeightStruct; } VertexWeightList.push_back(vertexWeightStruct); } Ready = true; //delete [] fileData; return true; } bool TAnimList::LoadAnimSequenceFromFileAn1(const std::string& fileName) { std::string shortFileName(GetFileName((char*)fileName.c_str())); if (AnimSequenceMap.count(shortFileName) == 0) { TAnimSequence animSeqience; if (animSeqience.LoadFromFileAn1(ResourceManager->PathToResources+fileName)) { AnimSequenceMap[shortFileName] = animSeqience; return true; } else return false; } return false; } void TAnimList::Clear() { BoneList.clear(); VertexWeightList.clear(); AnimSequenceMap.clear(); Ready = false; } void TAnimList::ScaleAnimList(float s) { for (TBoneList::iterator i = BoneList.begin(); i != BoneList.end(); ++i) { i->Pos *= s; i->Len *= s; } for (TAnimSequenceMap::iterator j = AnimSequenceMap.begin(); j != AnimSequenceMap.end(); ++j) { j->second.ScaleAnimSequence(s); } } void TAnimList::MoveAnimList(const vec3& v) { for (TBoneList::iterator i = BoneList.begin(); i != BoneList.end(); ++i) { i->Pos += v; } for (TAnimSequenceMap::iterator j = AnimSequenceMap.begin(); j != AnimSequenceMap.end(); ++j) { j->second.MoveAnimSequence(v); } } void TAnimList::RotateAnimList(const mat3& m) { vec4 q(m); for (TBoneList::iterator i = BoneList.begin(); i != BoneList.end(); ++i) { i->Pos = m * i->Pos; i->Quat = i->Quat * q; } for (TAnimSequenceMap::iterator j = AnimSequenceMap.begin(); j != AnimSequenceMap.end(); ++j) { j->second.RotateAnimSequence(m); } } void TAnimList::DrawBoneSystem() { #ifdef TARGET_WIN32 vec3 startpos, endpos; vec4 vx, q, inv_q; TBoneList::iterator i; for (TBoneList::iterator i = BoneList.begin(); i != BoneList.end(); ++i) { startpos = i->Pos; q = i->Quat; vx = vec4(i->Len, 0.0f, 0.0f, 0.0f); inv_q.v[0] = - q.v[0]; inv_q.v[1] = - q.v[1]; inv_q.v[2] = - q.v[2]; inv_q.v[3] = q.v[3]; vx = q * vx * inv_q; endpos = startpos + vec3(vx); glBegin(GL_LINES); glNormal3f(0.0f, 1.0f, 0.0f); glVertex3fv(startpos.v); glVertex3fv(endpos.v); glEnd(); } #endif } void TAnimList::SaveBoneSystemToBuf() { PrevBoneList.assign(BoneList.begin(),BoneList.end()); } void TAnimList::LoadBoneSystemFromBuf() { BoneList.assign(PrevBoneList.begin(),PrevBoneList.end()); } //===================================================== //=========== TModelAnimManager ======================= //===================================================== TAnimList* TModelAnimManager::operator [] (const std::string& s) { if (AnimListMap.count(s) > 0) { return &AnimListMap[s]; } return NULL; } //NOT SAFE!!! Need to check if model exists in Lite Model Manager and need to check if bone list belongs to this model bool TModelAnimManager::AddAnimationToModel(const std::string& modelName, const std::string& boneListFileName) { if (AnimListMap.count(modelName) == 0) { //TODO: Make switch //if (!AnimListMap[modelName].LoadBoneSystemFromFileBn1(boneListFileName)) if (!AnimListMap[modelName].LoadBoneSystemFromFileBn2(boneListFileName)) { AnimListMap.erase(modelName); return false; } return true; } return false; } void TModelAnimManager::Clear() { AnimListMap.clear(); } //================================================== //=============== ANIM MODEL ======================= //================================================== void TAnimModel::RecalcVertexPos() { int i,j,nBone; mat3 R, R0, dR; vec4 dq,inv_q; vec4 q0; vec4 q; vec4 inv_q0; vec4 inv_dq; //vec3 endbone0; vec3 endbone; vec3 p[20];//TODO: MAKE THIS DYNAMIC!!!! vec3 PrevPos,dbp,px; //float n; int VertexCount = LiteModel.TriangleCount * 3; for (i=0; iVertexWeightList[i].WeightCount; for (j=0; jVertexWeightList[i].VertexBoneInfo[j].BoneNum; q0 = AnimList->PrevBoneList[nBone].Quat; inv_q0 = q0; inv_q0.v[0] = - inv_q0.v[0]; inv_q0.v[1] = - inv_q0.v[1]; inv_q0.v[2] = - inv_q0.v[2]; inv_q0.v[3] = inv_q0.v[3]; q = AnimList->BoneList[nBone].Quat; inv_q = q; inv_q.v[0] = - inv_q.v[0]; inv_q.v[1] = - inv_q.v[1]; inv_q.v[2] = - inv_q.v[2]; inv_q.v[3] = inv_q.v[3]; vec3 prevBonePos = AnimList->PrevBoneList[nBone].Pos; px = PrevPos - prevBonePos; px = inv_q * (q0 * vec4(px) * inv_q0) * q; vec3 bonePos = AnimList->BoneList[nBone].Pos; p[j] = bonePos + px; } px = vec3(0.0f, 0.0f, 0.0f); for (j=0; jVertexWeightList[i].VertexBoneInfo[j].BoneWeight; } //LiteModel.VertexArr[i] = px; //LiteModel.TriangleList.Data.Vec3CoordArr[CONST_STRING_POSITION_ATTRIB][i] = px; /* //Normal px = ((vec3*)(LiteModel.TrianglePointer))[i+VertexCount]; px = dR * px; ((vec3*)(LiteModel.TrianglePointer))[i+VertexCount] = px; //Tangent px = ((vec3*)(LiteModel.TrianglePointer))[i+VertexCount+VertexCount]; px = dR * px; ((vec3*)(LiteModel.TrianglePointer))[i+VertexCount+VertexCount] = px; //Binormal px = ((vec3*)(LiteModel.TrianglePointer))[i+VertexCount+VertexCount+VertexCount]; px = dR * px; ((vec3*)(LiteModel.TrianglePointer))[i+VertexCount+VertexCount+VertexCount] = px;*/ } } void TAnimModel::SaveVertexInfoToBuf() { //CopyVertexArr = LiteModel.TriangleList.Data.Vec3CoordArr[CONST_STRING_POSITION_ATTRIB]; AnimList->SaveBoneSystemToBuf(); } void TAnimModel::LoadVertexInfoFromBuf() { //LiteModel.TriangleList.Data.Vec3CoordArr[CONST_STRING_POSITION_ATTRIB] = CopyVertexArr; AnimList->LoadBoneSystemFromBuf(); } bool TAnimModel::LoadModel(const std::string& modelName) { if (!LiteModel.LoadModel(modelName)) return false; //CopyVertexArr.resize(LiteModel.TriangleList.Data.Vec3CoordArr[CONST_STRING_POSITION_ATTRIB].size()); //CopyVertexArr = LiteModel.TriangleList.Data.Vec3CoordArr[CONST_STRING_POSITION_ATTRIB]; AnimList = ResourceManager->ModelAnimManager[modelName]; if (AnimList == NULL) return false; Ready = true; SaveVertexInfoToBuf(); return true; } void TAnimModel::Clear() { CopyVertexArr.clear(); LiteModel.FreeModel(); AnimList = NULL; Ready = false; } void TAnimModel::ScaleModel(float s) { LiteModel.ScaleModel(s); AnimList->ScaleAnimList(s); SaveVertexInfoToBuf(); } void TAnimModel::MoveModel(const vec3& v) { LiteModel.MoveModel(v); AnimList->MoveAnimList(v); SaveVertexInfoToBuf(); } void TAnimModel::RotateModel(const mat3& r) { LiteModel.RotateModel(r); AnimList->RotateAnimList(r); SaveVertexInfoToBuf(); } void TAnimModel::DrawImmediate() { LiteModel.DrawImmediate(); } void TAnimModel::ApplySequence(const std::string& seq, int n) { int boneCount = AnimList->BoneList.size(); for (int i=0; iBoneList[i].Pos = AnimList->AnimSequenceMap[seq].BoneInfoMatrix[n][i].Pos; AnimList->BoneList[i].Quat = AnimList->AnimSequenceMap[seq].BoneInfoMatrix[n][i].Quat; AnimList->BoneList[i].Len = AnimList->AnimSequenceMap[seq].BoneInfoMatrix[n][i].Len; } RecalcVertexPos(); } } //namespace SE