void Array::Load( lpxmlnode pNode) { m_id = GetAttributeStringValue("id", pNode); m_count = GetAttributeIntegerValue("count", pNode); printf("Loading %s\n", m_id.c_str()); std::string type = pNode->name(); if(type == "float_array") { GetFloatArray(m_floats, GetSubnodeStringValue("float_array", pNode)); } else if(type == "Name_array") { GetNameArray(m_names, GetSubnodeStringValue("Name_array", pNode)); } }
const char *ParseFrame(const char *pText, const MFMatrix &mat, int parentID) { char frameName[64]; const char *pName = GetNextToken(pText, &pText, frameName); MFMatrix worldMatrix = mat; F3DBone *pBone = NULL; if(!MFString_CaseCmpN(pName, "bn_", 3) || !MFString_CaseCmpN(pName, "z_", 2)) { int boneID = pModel->GetSkeletonChunk()->bones.size(); pBone = &pModel->GetSkeletonChunk()->bones[boneID]; F3DBone *pParent = parentID == -1 ? NULL : &pModel->GetSkeletonChunk()->bones[parentID]; parentID = boneID; MFString_Copy(pBone->name, pName); MFString_Copy(pBone->parentName, pParent ? pParent->name : ""); pBone->worldMatrix = mat; } if(MFString_Compare(pName, "{")) SkipToken(pText, "{"); const char *pTok = GetNextToken(pText, &pText); while(MFString_Compare(pTok, "}")) { if(!MFString_Compare(pTok, "Frame")) { pText = ParseFrame(pText, worldMatrix, parentID); } else if(!MFString_Compare(pTok, "FrameTransformMatrix")) { SkipToken(pText, "{"); MFMatrix localMatrix; GetFloatArray(pText, (float*)&localMatrix, 16, &pText); worldMatrix.Multiply(localMatrix, worldMatrix); if(pBone) { pBone->boneMatrix = localMatrix; pBone->worldMatrix = worldMatrix; } SkipToken(pText, ";"); SkipToken(pText, "}"); } else if(!MFString_Compare(pTok, "Mesh")) { gMeshChunks.push(XMeshChunk::Create(worldMatrix, pText, pName)); SkipSection(pText); } else { MFDebug_Warn(4, MFStr("Unexpected token '%s'\n", pTok)); SkipSection(pText); } pTok = GetNextToken(pText, &pText); } return pText; }
const char *ParseAnimation(const char *pText) { const char *pAnimName = GetNextToken(pText, &pText); if(MFString_Compare(pAnimName, "{")) SkipToken(pText, "{"); char bone[64]; int numFrames = 0; float *pFrameTimes = NULL; MFQuaternion *pQuats = NULL; MFVector *pScale = NULL; MFVector *pTrans = NULL; MFMatrix *pMats = NULL; MFVector tQuat; const char *pTok = GetNextToken(pText, &pText); while(MFString_Compare(pTok, "}")) { if(!MFString_Compare(pTok, "AnimationKey")) { SkipToken(pText, "{"); int type = GetInt(pText, &pText); numFrames = GetInt(pText, &pText); pFrameTimes = (float*)MFHeap_Alloc(sizeof(float)*numFrames); switch(type) { case KT_Quat: pQuats = (MFQuaternion*)MFHeap_Alloc(sizeof(MFQuaternion)*numFrames); break; case KT_Scale: pScale = (MFVector*)MFHeap_Alloc(sizeof(MFVector)*numFrames); break; case KT_Translation: pTrans = (MFVector*)MFHeap_Alloc(sizeof(MFVector)*numFrames); break; case KT_Matrix: pMats = (MFMatrix*)MFHeap_Alloc(sizeof(MFMatrix)*numFrames); break; } // read data for(int a=0; a<numFrames; a++) { int frame = GetInt(pText, &pText); pFrameTimes[a] = (float)frame; int numComponents = GetInt(pText, &pText); switch(type) { case KT_Quat: MFDebug_Assert(numComponents == 4, "Required 4 components for a quaternion."); GetFloatArray(pText, tQuat, numComponents, &pText); ((MFVector&)pQuats[a]).Swizzle(tQuat, SW_Y|SW_NEG, SW_Z|SW_NEG, SW_W|SW_NEG, SW_X|SW_NEG); break; case KT_Scale: MFDebug_Assert(numComponents == 3, "Required 3 components for a scale."); GetFloatArray(pText, (float*)&pScale[a], numComponents, &pText); break; case KT_Translation: MFDebug_Assert(numComponents == 3, "Required 3 components for a translation."); GetFloatArray(pText, (float*)&pTrans[a], numComponents, &pText); break; case KT_Matrix: MFDebug_Assert(numComponents == 16, "Required 16 components for a matrix."); GetFloatArray(pText, (float*)&pMats[a], numComponents, &pText); break; } SkipToken(pText, ";"); if(a < numFrames-1) SkipToken(pText, ","); } SkipToken(pText, ";"); SkipToken(pText, "}"); } else if(!MFString_Compare(pTok, "{")) { GetNextToken(pText, &pText, bone); SkipToken(pText, "}"); } else { MFDebug_Warn(4, MFStr("Unexpected token '%s'\n", pTok)); SkipSection(pText); } pTok = GetNextToken(pText, &pText); } if(!MFString_CaseCmpN(bone, "bn_", 3) || !MFString_CaseCmpN(bone, "z_", 2)) { // copy data to bone F3DAnimation &anim = pModel->GetAnimationChunk()->anims.push(); anim.boneID = pModel->GetSkeletonChunk()->FindBone(bone); if(anim.boneID == -1) { MFDebug_Warn(4, MFStr("Bone '%s' not found..\n", bone)); return pText; } anim.minTime = pFrameTimes[0]; anim.maxTime = pFrameTimes[numFrames-1]; for(int a=0; a<numFrames; a++) { anim.keyframes[a].time = pFrameTimes[a]; if(pMats) { anim.keyframes[a].key = pMats[a]; // anim.keyframes[a].scale = MakeVector(pMats[a].GetXAxis().Magnitude3(), pMats[a].GetYAxis().Magnitude3(), pMats[a].GetZAxis().Magnitude3(), 1.0f); // pMats[a].Normalise(); // anim.keyframes[a].rotation = pMats[a].GetRotationQ(); // anim.keyframes[a].translation = pMats[a].GetTrans(); } else { anim.keyframes[a].key.SetRotationQ(pQuats ? pQuats[a] : MFQuaternion::identity); if(pScale) anim.keyframes[a].key.Scale(pScale[a]); anim.keyframes[a].key.SetTrans3(pTrans ? pTrans[a] : MFVector::identity); // anim.keyframes[a].rotation = pQuats ? pQuats[a] : MFQuaternion::identity; // anim.keyframes[a].scale = pScale ? pScale[a] : MFVector::one; // anim.keyframes[a].translation = pTrans ? pTrans[a] : MFVector::identity; } } } return pText; }
const char *ParseSkinWeights(const char *pText, F3DSubObject &sub, int numPositions) { SkipToken(pText, "{"); const char *pName = GetString(pText, &pText); // get num weights int numWeights = GetInt(pText, &pText); if(numWeights > 0) MFDebug_Assert(numWeights == numPositions, "Number of weights's does not match the number of verts in the mesh."); int *pIndices = numWeights > 0 ? (int*)MFHeap_Alloc(sizeof(int) * numWeights) : NULL; GetIntArray(pText, pIndices, numWeights, &pText); float *pWeights = numWeights > 0 ? (float*)MFHeap_Alloc(sizeof(float) * numWeights) : NULL; GetFloatArray(pText, pWeights, numWeights, &pText); MFMatrix matrixOffset; GetFloatArray(pText, (float*)&matrixOffset, 16, &pText); SkipToken(pText, ";"); SkipToken(pText, "}"); if(numWeights > 0) { // now we want to do something with all this data... F3DSkeletonChunk *pSC = pModel->GetSkeletonChunk(); int boneID = pSC->FindBone(pName); // if boneID == -1 we dont want to process this data if(boneID == -1) return pText; // check weights are sequential for(int a=0; a<numWeights; a++) MFDebug_Assert(a == pIndices[a], "Weight array is not sequential!"); for(int a=0; a<sub.matSubobjects.size(); a++) ++sub.matSubobjects[a].numBones; // map to faces for(int m=0; m<sub.matSubobjects.size(); m++) { int totalVerts = sub.matSubobjects[m].vertices.size(); for(int a=0; a<totalVerts; a++) { F3DVertex &v = sub.matSubobjects[m].vertices[a]; int i = v.position; const int numBones = sizeof(v.bone)/sizeof(v.bone[0]); if(pWeights[i] != 0.0f) { for(int b=0; b<numBones; b++) { if(v.bone[b] == -1) { v.weight[b] = pWeights[i]; v.bone[b] = boneID; pSC->bones[boneID].bIsSkinned = true; sub.matSubobjects[m].maxWeights = MFMax(sub.matSubobjects[m].maxWeights, b+1); break; } } } } } } return pText; }