Ticket #1012: collada_alternate_fix-01222012.patch
File collada_alternate_fix-01222012.patch, 12.5 KB (added by , 12 years ago) |
---|
-
source/collada/DLL.h
1 /* Copyright (C) 201 1Wildfire Games.1 /* Copyright (C) 2012 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * 4 4 * 0 A.D. is free software: you can redistribute it and/or modify … … 41 41 42 42 /* This version number should be bumped whenever incompatible changes 43 43 * are made, to invalidate old caches. */ 44 #define COLLADA_CONVERTER_VERSION 344 #define COLLADA_CONVERTER_VERSION 4 45 45 46 46 EXPORT void set_logger(LogFn logger, void* cb_data); 47 47 EXPORT int set_skeleton_definitions(const char* xml, int length); -
source/collada/PMDConvert.cpp
1 /* Copyright (C) 201 1Wildfire Games.1 /* Copyright (C) 2012 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * 4 4 * 0 A.D. is free software: you can redistribute it and/or modify … … 252 252 // guaranteed by ReduceInfluences; necessary for avoiding 253 253 // out-of-bounds writes to the VertexBlend 254 254 255 if (vertexInfluences[i].GetPairCount() == 0) 256 { 257 // Blender exports some models with vertices that have no influences, 258 // which I've not found details about in the COLLADA spec, however, 259 // it seems to work OK to treat these vertices the same as if they 260 // were only influenced by the bind-shape matrix (see comment below), 261 // so we use the same special case here. 262 influences.bones[0] = (uint8)jointCount; 263 influences.weights[0] = 1.0f; 264 } 265 255 266 for (size_t j = 0; j < vertexInfluences[i].GetPairCount(); ++j) 256 267 { 257 uint32 jointIdx = vertexInfluences[i].GetPair(j)->jointIndex; 258 REQUIRE(jointIdx <= 0xFF, "sensible number of joints (<256)"); // because we only have a u8 to store them in 268 if (vertexInfluences[i].GetPair(j)->jointIndex == -1) 269 { 270 // This is a special case we must handle, according to the COLLADA spec: 271 // "An index of -1 into the array of joints refers to the bind shape" 272 // which basically means when skinning the vertex it's relative to the 273 // bind-shape transform instead of an animated bone. Since our skinning 274 // is in world space, we will have already applied the bind-shape transform, 275 // so we don't have to worry about that, though we DO have to apply the 276 // world space transform of the model for the indicated vertex. 277 // 278 // To handle this special case, we add a zero translation, identity 279 // rotation bone to all models, with a bone ID equal to the number of 280 // real bones in the COLLADA model. 281 // (see http://trac.wildfiregames.com/ticket/1012) 282 influences.bones[j] = (uint8)jointCount; 283 influences.weights[j] = vertexInfluences[i].GetPair(j)->weight; 284 } 285 else 286 { 287 // Check for less than 255 joints because we store them in a u8 288 // and 0xFF is a reserved value 289 uint32 jointIdx = vertexInfluences[i].GetPair(j)->jointIndex; 290 REQUIRE(jointIdx < 0xFF, "sensible number of joints (<255)"); 259 291 260 // Find the joint on the skeleton, after checking it really exists261 FCDSceneNode* joint = NULL;262 if (jointIdx < controllerInstance.GetJointCount())263 joint = controllerInstance.GetJoint(jointIdx);292 // Find the joint on the skeleton, after checking it really exists 293 FCDSceneNode* joint = NULL; 294 if (jointIdx < controllerInstance.GetJointCount()) 295 joint = controllerInstance.GetJoint(jointIdx); 264 296 265 // Complain on error 266 if (! joint) 267 { 268 if (! hasComplainedAboutNonexistentJoints) 297 // Complain on error 298 if (! joint) 269 299 { 270 Log(LOG_WARNING, "Vertexes influenced by nonexistent joint"); 271 hasComplainedAboutNonexistentJoints = true; 300 if (! hasComplainedAboutNonexistentJoints) 301 { 302 Log(LOG_WARNING, "Vertexes influenced by nonexistent joint"); 303 hasComplainedAboutNonexistentJoints = true; 304 } 305 continue; 272 306 } 273 continue;274 }275 307 276 // Store into the VertexBlend 277 int boneId = skeleton.GetBoneID(joint->GetName().c_str()); 278 if (boneId < 0) 279 { 280 // The relevant joint does exist, but it's not a recognised 281 // bone in our chosen skeleton structure 282 Log(LOG_ERROR, "Vertex influenced by unrecognised bone '%s'", joint->GetName().c_str()); 283 continue; 308 // Store into the VertexBlend 309 int boneId = skeleton.GetBoneID(joint->GetName().c_str()); 310 if (boneId < 0) 311 { 312 // The relevant joint does exist, but it's not a recognised 313 // bone in our chosen skeleton structure 314 Log(LOG_ERROR, "Vertex influenced by unrecognised bone '%s'", joint->GetName().c_str()); 315 continue; 316 } 317 318 influences.bones[j] = (uint8)boneId; 319 influences.weights[j] = vertexInfluences[i].GetPair(j)->weight; 284 320 } 285 286 influences.bones[j] = (uint8)boneId;287 influences.weights[j] = vertexInfluences[i].GetPair(j)->weight;288 321 } 289 322 290 323 boneWeights.push_back(influences); … … 292 325 293 326 // Convert the bind pose into BoneTransform structures for the PMD: 294 327 328 // Add a special zero translation, identity bone (see comments above) 329 295 330 BoneTransform boneDefault = { { 0, 0, 0 }, { 0, 0, 0, 1 } }; // identity transform 296 std::vector<BoneTransform> boneTransforms (skeleton.GetBoneCount() , boneDefault);331 std::vector<BoneTransform> boneTransforms (skeleton.GetBoneCount()+1, boneDefault); 297 332 298 333 for (size_t i = 0; i < jointCount; ++i) 299 334 { … … 454 489 } 455 490 456 491 output("PSMD", 4); // magic number 457 write(output, (uint32) 3); // version number492 write(output, (uint32)4); // version number 458 493 write(output, (uint32)( 459 494 4 + 13*4*vertexCount + // vertices 460 495 4 + 6*faceCount + // faces … … 522 557 /** 523 558 * Applies world-space transform to vertex data and transforms Collada's right-handed 524 559 * Y-up / Z-up coordinates to the game's left-handed Y-up coordinate system 560 * 561 * TODO: Maybe we should use FCDocumentTools::StandardizeUpAxisAndLength in addition 562 * to this, so we'd only have one up-axis case to worry about, but it doesn't seem to 563 * correctly adjust the prop points in Y_UP models. 525 564 */ 526 565 static void TransformStaticModel(float* position, float* normal, size_t vertexCount, 527 566 const FMMatrix44& transform, bool yUp) … … 563 602 /** 564 603 * Applies world-space transform to vertex data and transforms Collada's right-handed 565 604 * Y-up / Z-up coordinates to the game's left-handed Y-up coordinate system 605 * 606 * TODO: Maybe we should use FCDocumentTools::StandardizeUpAxisAndLength in addition 607 * to this, so we'd only have one up-axis case to worry about, but it doesn't seem to 608 * correctly adjust the prop points in Y_UP models. 566 609 */ 567 610 static void TransformSkinnedModel(float* position, float* normal, size_t vertexCount, 568 611 std::vector<BoneTransform>& bones, std::vector<PropPoint>& propPoints, -
source/collada/PSAConvert.cpp
1 /* Copyright (C) 20 09Wildfire Games.1 /* Copyright (C) 2012 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * 4 4 * 0 A.D. is free software: you can redistribute it and/or modify … … 86 86 size_t frameCount = (size_t)((timeEnd - timeStart) / frameLength - 0.5f); 87 87 // (TODO: sort out the timing/looping problems) 88 88 89 size_t boneCount = skeleton.GetBoneCount(); 89 // Add a special zero translation, identity bone state (see comments in PMDConvert.cpp) 90 size_t boneCount = skeleton.GetBoneCount()+1; 90 91 91 92 std::vector<BoneTransform> boneTransforms; 92 93 … … 150 151 static void WritePSA(OutputCB& output, size_t frameCount, size_t boneCount, const std::vector<BoneTransform>& boneTransforms) 151 152 { 152 153 output("PSSA", 4); // magic number 153 write(output, (uint32) 1); // version number154 write(output, (uint32)2); // version number 154 155 write(output, (uint32)( 155 156 4 + 0 + // name 156 157 4 + // frameLength -
source/graphics/ModelDef.cpp
1 /* Copyright (C) 201 1Wildfire Games.1 /* Copyright (C) 2012 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * 4 4 * 0 A.D. is free software: you can redistribute it and/or modify … … 259 259 unpacker.Read(filename,"PSMD"); 260 260 261 261 // check version 262 if (unpacker.GetVersion()<FILE_READ_VERSION) { 262 if (unpacker.GetVersion() < FILE_READ_VERSION) 263 { 263 264 throw PSERROR_File_InvalidVersion(); 264 265 } 265 266 … … 269 270 // now unpack everything 270 271 mdef->m_NumVertices = unpacker.UnpackSize(); 271 272 mdef->m_pVertices=new SModelVertex[mdef->m_NumVertices]; 272 unpacker.UnpackRaw(mdef->m_pVertices, sizeof(SModelVertex)*mdef->m_NumVertices);273 unpacker.UnpackRaw(mdef->m_pVertices, sizeof(SModelVertex)*mdef->m_NumVertices); 273 274 274 275 mdef->m_NumFaces = unpacker.UnpackSize(); 275 276 mdef->m_pFaces=new SModelFace[mdef->m_NumFaces]; 276 unpacker.UnpackRaw(mdef->m_pFaces, sizeof(SModelFace)*mdef->m_NumFaces);277 unpacker.UnpackRaw(mdef->m_pFaces, sizeof(SModelFace)*mdef->m_NumFaces); 277 278 278 279 mdef->m_NumBones = unpacker.UnpackSize(); 279 280 if (mdef->m_NumBones) 280 281 { 282 size_t numPackedBones = mdef->m_NumBones; 283 284 if (unpacker.GetVersion() < 4) 285 { 286 // For older versions we need to add an extra identity bone 287 // (see http://trac.wildfiregames.com/ticket/1012) 288 mdef->m_NumBones++; 289 } 290 281 291 mdef->m_Bones=new CBoneState[mdef->m_NumBones]; 282 unpacker.UnpackRaw(mdef->m_Bones, mdef->m_NumBones*sizeof(CBoneState));292 unpacker.UnpackRaw(mdef->m_Bones, numPackedBones*sizeof(CBoneState)); 283 293 294 if (unpacker.GetVersion() < 4) 295 { 296 // see above comment 297 CBoneState identityBone; 298 identityBone.m_Rotation = CQuaternion(0.0f, 0.0f, 0.0f, 1.0f); 299 identityBone.m_Translation = CVector3D(0.0f, 0.0f, 0.0f); 300 mdef->m_Bones[mdef->m_NumBones - 1] = identityBone; 301 } 302 284 303 mdef->m_pBlendIndices = new size_t[mdef->m_NumVertices]; 285 304 std::vector<SVertexBlend> blends; 286 305 for (size_t i = 0; i < mdef->m_NumVertices; i++) -
source/graphics/SkeletonAnimDef.cpp
1 /* Copyright (C) 20 09Wildfire Games.1 /* Copyright (C) 2012 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * 4 4 * 0 A.D. is free software: you can redistribute it and/or modify … … 93 93 unpacker.Read(filename,"PSSA"); 94 94 95 95 // check version 96 if (unpacker.GetVersion()<FILE_READ_VERSION) { 96 if (unpacker.GetVersion() < FILE_READ_VERSION) 97 { 97 98 throw PSERROR_File_InvalidVersion(); 98 99 } 99 100 100 101 // unpack the data 101 CSkeletonAnimDef* anim=new CSkeletonAnimDef; 102 try { 102 CSkeletonAnimDef* anim = new CSkeletonAnimDef; 103 try 104 { 103 105 CStr name; // unused - just here to maintain compatibility with the animation files 104 106 unpacker.UnpackString(name); 105 unpacker.UnpackRaw(&anim->m_FrameTime, sizeof(anim->m_FrameTime));107 unpacker.UnpackRaw(&anim->m_FrameTime, sizeof(anim->m_FrameTime)); 106 108 anim->m_NumKeys = unpacker.UnpackSize(); 107 109 anim->m_NumFrames = unpacker.UnpackSize(); 108 anim->m_Keys=new Key[anim->m_NumKeys*anim->m_NumFrames]; 109 unpacker.UnpackRaw(anim->m_Keys,anim->m_NumKeys*anim->m_NumFrames*sizeof(Key)); 110 } catch (PSERROR_File&) { 110 111 anim->m_Keys = new Key[anim->m_NumKeys * anim->m_NumFrames]; 112 unpacker.UnpackRaw(anim->m_Keys, anim->m_NumKeys * anim->m_NumFrames * sizeof(Key)); 113 114 if (unpacker.GetVersion() < 2) 115 { 116 // For old versions, we need to add an identity bone state in each frame, 117 // to maintain compatibility with new models 118 // (see http://trac.wildfiregames.com/ticket/1012) 119 120 Key specialKey; 121 specialKey.m_Rotation = CQuaternion(0.0f, 0.0f, 0.0f, 1.0f); 122 specialKey.m_Translation = CVector3D(0.0f, 0.0f, 0.0f); 123 124 size_t oldKeysNum = anim->m_NumKeys; 125 size_t newKeysNum = oldKeysNum + 1; 126 127 Key* newKeys = new Key[newKeysNum * anim->m_NumFrames]; 128 129 for (size_t f = 0; f < anim->m_NumFrames; ++f) 130 { 131 memcpy(&newKeys[f*newKeysNum], &anim->m_Keys[f*oldKeysNum], oldKeysNum*sizeof(Key)); 132 newKeys[f*newKeysNum + oldKeysNum] = specialKey; 133 } 134 135 delete anim->m_Keys; 136 anim->m_NumKeys = newKeysNum; 137 anim->m_Keys = newKeys; 138 } 139 140 } 141 catch (PSERROR_File&) 142 { 111 143 delete anim; 112 144 throw; 113 145 }