From 781e630b2ccd31a7e93d27e1bb68a85af8e28a64 Mon Sep 17 00:00:00 2001 From: Ykkrosh Date: Fri, 9 Mar 2007 13:40:28 +0000 Subject: [PATCH] # Incomplete improved support for XSI models/animations This was SVN commit r4946. --- source/collada/CommonConvert.cpp | 132 ++++++++++++++++- source/collada/CommonConvert.h | 52 +++++-- source/collada/PMDConvert.cpp | 78 +++++++--- source/collada/PSAConvert.cpp | 235 +++++++++++++++++++------------ source/collada/StdSkeletons.cpp | 65 ++++++++- source/collada/precompiled.h | 4 + 6 files changed, 432 insertions(+), 134 deletions(-) diff --git a/source/collada/CommonConvert.cpp b/source/collada/CommonConvert.cpp index 3bbff9c9a1..e856074776 100644 --- a/source/collada/CommonConvert.cpp +++ b/source/collada/CommonConvert.cpp @@ -5,6 +5,9 @@ #include "FCollada.h" #include "FCDocument/FCDSceneNode.h" #include "FCDocument/FCDSkinController.h" +#include "FUtils/FUDaeSyntax.h" +#include "FUtils/FUFileManager.h" +#include "FUtils/FUXmlParser.h" #include @@ -64,11 +67,76 @@ void FColladaErrorHandler::OnError(FUError::Level errorLevel, uint32 errorCode, } +////////////////////////////////////////////////////////////////////////// + +void FColladaDocument::LoadFromText(const char *text) +{ + document.reset(FCollada::NewTopDocument()); + + FUFileManager* fileManager = document->GetFileManager(); + const char* basePath = ""; + + // Mostly copied from FCDocument::LoadFromText + + bool status = true; + + // Push the given path unto the file manager's stack + fileManager->PushRootPath(basePath); + + // Parse the document into a XML tree + xmlDoc* daeDocument = xmlParseDoc((const xmlChar*)text); + if (daeDocument != NULL) + { + xmlNode *rootNode = xmlDocGetRootElement(daeDocument); + + // Read in the whole document from the root node + status &= (document->LoadDocumentFromXML(rootNode)); + + // HACK (sort of): read in from the root, because FCollada + // doesn't let us do that + ReadExtras(rootNode); + + // Free the XML document + xmlFreeDoc(daeDocument); + } + else + { + FUError::Error(FUError::ERROR, FUError::ERROR_MALFORMED_XML); + status = false; + } + + // Clean-up the XML reader + xmlCleanupParser(); + + // Restore the original OS current folder + fileManager->PopRootPath(); + + if (status) + FUError::Error(FUError::DEBUG, FUError::DEBUG_LOAD_SUCCESSFUL); + + REQUIRE_SUCCESS(status); +} + +void FColladaDocument::ReadExtras(xmlNode* colladaNode) +{ + if (! IsEquivalent(colladaNode->name, DAE_COLLADA_ELEMENT)) + return; + + extra.reset(new FCDExtra(document.get())); + + xmlNodeList extraNodes; + FUXmlParser::FindChildrenByType(colladaNode, DAE_EXTRA_ELEMENT, extraNodes); + for (xmlNodeList::iterator it = extraNodes.begin(); it != extraNodes.end(); ++it) + { + xmlNode* extraNode = (*it); + extra->LoadFromXML(extraNode); + } +} ////////////////////////////////////////////////////////////////////////// -// These don't get exported properly from FCollada (3.02, DLL), so define them -// here instead of fixing it correctly. +// HACK: These don't get exported properly from FCollada (3.02, DLL), so define +// them here instead of fixing it correctly. const FMVector3 FMVector3::XAxis(1.0f, 0.0f, 0.0f); static float identity[] = { 1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1 }; FMMatrix44 FMMatrix44::Identity(identity); @@ -79,6 +147,45 @@ struct FoundInstance FMMatrix44 transform; }; +static bool IsVisible_XSI(FCDSceneNode* node, bool& visible) +{ + // Look for + + FCDExtra* extra = node->GetExtra(); + if (! extra) return false; + + FCDEType* type = extra->GetDefaultType(); + if (! type) return false; + + FCDETechnique* technique = type->FindTechnique("XSI"); + if (! technique) return false; + + FCDENode* visibility1 = technique->FindChildNode("SI_Visibility"); + if (! visibility1) return false; + + FCDENode* visibility2 = visibility1->FindChildNode("xsi_param"); + if (! visibility2) return false; + + if (IsEquivalent(visibility2->GetContent(), "TRUE")) + visible = true; + else if (IsEquivalent(visibility2->GetContent(), "FALSE")) + visible = false; + return true; +} + +static bool IsVisible(FCDSceneNode* node) +{ + bool visible; + + // Try the XSI visibility property + if (IsVisible_XSI(node, visible)) + return visible; + + // Else fall back to the FCollada-specific setting + visible = (node->GetVisibility() != 0.0); + return visible; +} + /** * Recursively finds all entities under the current node. If onlyMarked is * set, only matches entities where the user-defined property was set to @@ -110,10 +217,15 @@ static void FindInstances(FCDSceneNode* node, std::vector& instan if (! (type == FCDEntity::GEOMETRY || type == FCDEntity::CONTROLLER)) continue; + // Ignore invisible objects, because presumably nobody wanted to export them + if (! IsVisible(node)) + continue; + FoundInstance f; f.transform = transform * node->ToMatrix(); f.instance = node->GetInstance(i); instances.push_back(f); + Log(LOG_INFO, "Found convertible object '%s'", node->GetName().c_str()); } } @@ -209,3 +321,19 @@ void SkinReduceInfluences(FCDSkinController* skin, size_t maxInfluenceCount, flo skin->SetDirtyFlag(); } + + +void FixSkeletonRoots(FCDControllerInstance* controllerInstance) +{ + // HACK: The XSI exporter doesn't do a and FCollada doesn't + // seem to know where else to look, so just guess that it's somewhere + // under Scene_Root + if (controllerInstance->GetSkeletonRoots().empty()) + { + // HACK (evil): SetSkeletonRoot is declared but not defined, and there's + // no other proper way to modify the skeleton-roots list, so cheat horribly + FUUriList& uriList = const_cast(controllerInstance->GetSkeletonRoots()); + uriList.push_back(FUUri("Scene_Root")); + controllerInstance->LinkImport(); + } +} diff --git a/source/collada/CommonConvert.h b/source/collada/CommonConvert.h index cb2b16eb74..e3f5eb5807 100644 --- a/source/collada/CommonConvert.h +++ b/source/collada/CommonConvert.h @@ -13,19 +13,9 @@ class FCDSkinController; class ColladaException : public std::exception { public: - ColladaException(const std::string& msg) - : msg(msg) - { - } - - ~ColladaException() throw() - { - } - - virtual const char* what() const throw() - { - return msg.c_str(); - } + ColladaException(const std::string& msg) : msg(msg) { } + ~ColladaException() throw() { } + virtual const char* what() const throw() { return msg.c_str(); } private: std::string msg; }; @@ -35,6 +25,10 @@ struct OutputCB virtual void operator() (const char* data, unsigned int length)=0; }; +/** + * Standard error handler - logs FCollada messages using Log(), and also + * maintains a list of XML parser errors. + */ class FColladaErrorHandler { public: @@ -48,6 +42,31 @@ private: void operator=(FColladaErrorHandler); }; +/** + * Standard document loader. Based on FCDocument::LoadFromText, but allows + * access to nodes at the document level (i.e. directly in ). + */ +class FColladaDocument +{ +public: + /** Loads the document from the given XML string. Should be the first function + * called on this object, and should only be called once. + * @throws ColladaException if unable to load. + */ + void LoadFromText(const char* text); + + /** Returns the FCDocument that was loaded. */ + FCDocument* GetDocument() const { return document.get(); } + + /** Returns the data from the element. */ + FCDExtra* GetExtra() const { return extra.get(); } + +private: + void ReadExtras(xmlNode* colladaNode); + std::auto_ptr document; + std::auto_ptr extra; +}; + /** Throws a ColladaException unless the value is true. */ #define REQUIRE(value, message) require_(__LINE__, value, "Assertion not satisfied", message) @@ -87,4 +106,11 @@ bool FindSingleInstance(FCDSceneNode* node, FCDEntityInstance*& instance, FMMatr */ void SkinReduceInfluences(FCDSkinController* skin, size_t maxInfluenceCount, float minimumWeight); +/** + * Fixes some occasional problems with the skeleton root definitions in a + * controller. (In particular, it's needed for models exported from XSI.) + * Should be called before extracting any joint information from the controller. + */ +void FixSkeletonRoots(FCDControllerInstance* controllerInstance); + #endif // COMMONCONVERT_H__ diff --git a/source/collada/PMDConvert.cpp b/source/collada/PMDConvert.cpp index e74878c1b4..526ddfbf28 100644 --- a/source/collada/PMDConvert.cpp +++ b/source/collada/PMDConvert.cpp @@ -6,6 +6,7 @@ #include "FCollada.h" #include "FCDocument/FCDAsset.h" #include "FCDocument/FCDocument.h" +#include "FCDocument/FCDocumentTools.h" #include "FCDocument/FCDController.h" #include "FCDocument/FCDControllerInstance.h" #include "FCDocument/FCDGeometry.h" @@ -62,10 +63,10 @@ public: { FColladaErrorHandler err (xmlErrors); - std::auto_ptr doc (FCollada::NewTopDocument()); - REQUIRE_SUCCESS(doc->LoadFromText("", input)); + FColladaDocument doc; + doc.LoadFromText(input); - FCDSceneNode* root = doc->GetVisualSceneRoot(); + FCDSceneNode* root = doc.GetDocument()->GetVisualSceneRoot(); REQUIRE(root != NULL, "has root object"); // Find the instance to convert @@ -77,7 +78,8 @@ public: assert(instance); Log(LOG_INFO, "Converting '%s'", instance->GetEntity()->GetName().c_str()); - FMVector3 upAxis = doc->GetAsset()->GetUpAxis(); + // StandardizeUpAxisAndLength completely mangles the skeletons, so don't use it + FMVector3 upAxis = doc.GetDocument()->GetAsset()->GetUpAxis(); bool yUp = (upAxis.y != 0); // assume either Y_UP or Z_UP (TODO: does anyone ever do X_UP?) if (instance->GetEntity()->GetType() == FCDEntity::GEOMETRY) @@ -127,12 +129,14 @@ public: FCDSkinController* skin = controller->GetSkinController(); REQUIRE(skin != NULL, "is skin controller"); + FixSkeletonRoots(controllerInstance); + // Data for joints is stored in two places - avoid overflows by limiting // to the minimum of the two sizes, and warn if they're different (which // happens in practice for slightly-broken meshes) size_t jointCount = std::min(skin->GetJointCount(), controllerInstance->GetJointCount()); if (skin->GetJointCount() != controllerInstance->GetJointCount()) - Log(LOG_WARNING, "Mismatched bone counts"); + Log(LOG_WARNING, "Mismatched bone counts (skin has %d, skeleton has %d)", skin->GetJointCount(), controllerInstance->GetJointCount()); // Get the skinned mesh for this entity FCDEntity* baseTarget = controller->GetBaseTarget(); @@ -295,7 +299,7 @@ public: FloatList& dataNormal = sourceNormal ->GetSourceData(); FloatList& dataTexcoord = sourceTexcoord->GetSourceData(); - TransformVertices(dataPosition, dataNormal, boneTransforms, propPoints, transform); + TransformVertices(dataPosition, dataNormal, boneTransforms, propPoints, transform, yUp); WritePMD(output, *indicesCombined, dataPosition, dataNormal, dataTexcoord, boneWeights, boneTransforms, propPoints); } @@ -440,7 +444,7 @@ public: static void TransformVertices(FloatList& position, FloatList& normal, std::vector& bones, std::vector& propPoints, - const FMMatrix44& transform) + const FMMatrix44& transform, bool yUp) { // Update the vertex positions and normals assert(position.size() == normal.size()); @@ -453,11 +457,18 @@ public: pos = transform.TransformCoordinate(pos); norm = transform.TransformVector(norm).Normalize(); - // Switch from Max's coordinate system into the game's: - // (TODO: handle Y_UP mode too) + // Convert from Y_UP or Z_UP to the game's coordinate system - std::swap(pos.y, pos.z); - std::swap(norm.y, norm.z); + if (yUp) + { + pos.x = -pos.x; + norm.x = -norm.x; + } + else + { + std::swap(pos.y, pos.z); + std::swap(norm.y, norm.z); + } // and copy back into the original array @@ -475,24 +486,45 @@ public: // applied to the skeleton. for (size_t i = 0; i < bones.size(); ++i) { - // Convert bone translations from xyz into xzy axes: - std::swap(bones[i].translation[1], bones[i].translation[2]); + if (yUp) + { + // TODO: this is all just guesses which seem to work for data + // exported from XSI, rather than having been properly thought + // through + bones[i].translation[0] = -bones[i].translation[0]; + bones[i].orientation[0] = -bones[i].orientation[0]; + bones[i].orientation[3] = -bones[i].orientation[3]; + } + else + { + // Convert bone translations from xyz into xzy axes: + std::swap(bones[i].translation[1], bones[i].translation[2]); - // To convert the quaternions: imagine you're using the axis/angle - // representation, then swap the y,z basis vectors and change the - // direction of rotation by negating the angle ( => negating sin(angle) - // => negating x,y,z => changing (x,y,z,w) to (-x,-z,-y,w) - // but then (-x,-z,-y,w) == (x,z,y,-w) so do that instead) - std::swap(bones[i].orientation[1], bones[i].orientation[2]); - bones[i].orientation[3] = -bones[i].orientation[3]; + // To convert the quaternions: imagine you're using the axis/angle + // representation, then swap the y,z basis vectors and change the + // direction of rotation by negating the angle ( => negating sin(angle) + // => negating x,y,z => changing (x,y,z,w) to (-x,-z,-y,w) + // but then (-x,-z,-y,w) == (x,z,y,-w) so do that instead) + std::swap(bones[i].orientation[1], bones[i].orientation[2]); + bones[i].orientation[3] = -bones[i].orientation[3]; + } } // And do the same for prop points for (size_t i = 0; i < propPoints.size(); ++i) { - std::swap(propPoints[i].translation[1], propPoints[i].translation[2]); - std::swap(propPoints[i].orientation[1], propPoints[i].orientation[2]); - propPoints[i].orientation[3] = -propPoints[i].orientation[3]; + if (yUp) + { + propPoints[i].translation[0] = -propPoints[i].translation[0]; + propPoints[i].orientation[0] = -propPoints[i].orientation[0]; + propPoints[i].orientation[3] = -propPoints[i].orientation[3]; + } + else + { + std::swap(propPoints[i].translation[1], propPoints[i].translation[2]); + std::swap(propPoints[i].orientation[1], propPoints[i].orientation[2]); + propPoints[i].orientation[3] = -propPoints[i].orientation[3]; + } } } diff --git a/source/collada/PSAConvert.cpp b/source/collada/PSAConvert.cpp index 319748f368..dbac019115 100644 --- a/source/collada/PSAConvert.cpp +++ b/source/collada/PSAConvert.cpp @@ -5,6 +5,7 @@ #include "FCollada.h" #include "FCDocument/FCDocument.h" +#include "FCDocument/FCDocumentTools.h" #include "FCDocument/FCDAnimated.h" #include "FCDocument/FCDAnimationCurve.h" #include "FCDocument/FCDController.h" @@ -47,10 +48,10 @@ public: { FColladaErrorHandler err (xmlErrors); - std::auto_ptr doc (FCollada::NewTopDocument()); - REQUIRE_SUCCESS(doc->LoadFromText("", input)); + FColladaDocument doc; + doc.LoadFromText(input); - FCDSceneNode* root = doc->GetVisualSceneRoot(); + FCDSceneNode* root = doc.GetDocument()->GetVisualSceneRoot(); REQUIRE(root != NULL, "has root object"); // Find the instance to convert @@ -62,69 +63,21 @@ public: assert(instance); Log(LOG_INFO, "Converting '%s'", instance->GetEntity()->GetName().c_str()); + FMVector3 upAxis = doc.GetDocument()->GetAsset()->GetUpAxis(); + bool yUp = (upAxis.y != 0); // assume either Y_UP or Z_UP (TODO: does anyone ever do X_UP?) + if (instance->GetType() == FCDEntityInstance::CONTROLLER) { FCDControllerInstance* controllerInstance = (FCDControllerInstance*)instance; + FixSkeletonRoots(controllerInstance); + float frameLength = 1.f / 30.f; // currently we always want to create PMDs at fixed 30fps // Find the extents of the animation: float timeStart, timeEnd; - - // FCollada tools export info in the scene to specify the start - // and end times. - // If that isn't available, we have to search for the earliest and latest - // keyframes on any of the bones. - if (doc->HasStartTime() && doc->HasEndTime()) - { - timeStart = doc->GetStartTime(); - timeEnd = doc->GetEndTime(); - } - else - { - timeStart = std::numeric_limits::max(); - timeEnd = -std::numeric_limits::max(); - for (size_t i = 0; i < controllerInstance->GetJointCount(); ++i) - { - FCDSceneNode* joint = controllerInstance->GetJoint(i); - REQUIRE(joint != NULL, "joint exists"); - - int boneId = StdSkeletons::FindStandardBoneID(joint->GetName()); - if (boneId < 0) - { - // unrecognised joint - it's probably just a prop point - // or something, so ignore it - continue; - } - - // Skip unanimated joints - if (joint->GetTransformCount() == 0) - continue; - - REQUIRE(joint->GetTransformCount() == 1, "joint has single transform"); - - FCDTransform* transform = joint->GetTransform(0); - - // Skip unanimated joints (TODO: Which of these happens in practice?) - if (! transform->IsAnimated()) - continue; - - // Iterate over all curves - FCDAnimated* anim = transform->GetAnimated(); - FCDAnimationCurveListList& curvesList = anim->GetCurves(); - for (size_t j = 0; j < curvesList.size(); ++j) - { - FCDAnimationCurveList& curves = curvesList[j]; - for (size_t k = 0; k < curves.size(); ++k) - { - FCDAnimationCurve* curve = curves[k]; - timeStart = std::min(timeStart, curve->GetKeys().front()); - timeEnd = std::max(timeEnd, curve->GetKeys().back()); - } - } - } - } + GetAnimationRange(doc, controllerInstance, timeStart, timeEnd); // Count frames; don't include the last keyframe size_t frameCount = (size_t)((timeEnd - timeStart) / frameLength - 0.5f); @@ -142,36 +95,9 @@ public: std::vector frameBoneTransforms (boneCount, boneDefault); // Move the model into the new animated pose - for (size_t i = 0; i < controllerInstance->GetJointCount(); ++i) - { - FCDSceneNode* joint = controllerInstance->GetJoint(i); - - int boneId = StdSkeletons::FindStandardBoneID(joint->GetName()); - if (boneId < 0) - continue; // not a recognised bone - ignore it, same as before - - FCDTransform* transform = joint->GetTransform(0); - FCDAnimated* anim = transform->GetAnimated(); - anim->Evaluate(time); - } - // As well as the joints, we need to update all the ancestors - // of the skeleton (e.g. the Bip01 node, since the skeleton is - // hanging off Bip01-Pelvis instead). - // So choose an arbitrary joint, which is hopefully actually the - // top-most joint but it doesn't really matter, and evaluate all - // its ancestors; - if (controllerInstance->GetJointCount() >= 1) - { - FCDSceneNode* node = controllerInstance->GetJoint(0); - while (node->GetParentCount() == 1) // (I guess this should be true in sensible models) - { - node = node->GetParent(); - if (node->IsJoint() && node->GetTransformCount() == 1) - node->GetTransform(0)->GetAnimated()->Evaluate(time); - else - break; - } - } + // (We can't tell exactly which nodes should be animated, so + // just update the entire world recursively) + EvaluateAnimations(root, time); // Convert the pose into the form require by the game for (size_t i = 0; i < controllerInstance->GetJointCount(); ++i) @@ -204,7 +130,7 @@ public: } // Convert into game's coordinate space - TransformVertices(boneTransforms); + TransformVertices(boneTransforms, yUp); // Write out the file WritePSA(output, frameCount, boneCount, boneTransforms); @@ -244,16 +170,141 @@ public: } } - static void TransformVertices(std::vector& bones) + static void TransformVertices(std::vector& bones, bool yUp) { // (See PMDConvert.cpp for explanatory comments) for (size_t i = 0; i < bones.size(); ++i) { - std::swap(bones[i].translation[1], bones[i].translation[2]); - std::swap(bones[i].orientation[1], bones[i].orientation[2]); - bones[i].orientation[3] = -bones[i].orientation[3]; + if (yUp) + { + bones[i].translation[0] = -bones[i].translation[0]; + bones[i].orientation[0] = -bones[i].orientation[0]; + bones[i].orientation[3] = -bones[i].orientation[3]; + } + else + { + std::swap(bones[i].translation[1], bones[i].translation[2]); + std::swap(bones[i].orientation[1], bones[i].orientation[2]); + bones[i].orientation[3] = -bones[i].orientation[3]; + } } } + + static void GetAnimationRange(FColladaDocument& doc, FCDControllerInstance* controllerInstance, + float& timeStart, float& timeEnd) + { + // FCollada tools export info in the scene to specify the start + // and end times. + // If that isn't available, we have to search for the earliest and latest + // keyframes on any of the bones. + if (doc.GetDocument()->HasStartTime() && doc.GetDocument()->HasEndTime()) + { + timeStart = doc.GetDocument()->GetStartTime(); + timeEnd = doc.GetDocument()->GetEndTime(); + return; + } + + // XSI exports relevant information in + // + // (and 'end' and 'frameRate') so use those + if (GetAnimationRange_XSI(doc, timeStart, timeEnd)) + return; + + timeStart = std::numeric_limits::max(); + timeEnd = -std::numeric_limits::max(); + for (size_t i = 0; i < controllerInstance->GetJointCount(); ++i) + { + FCDSceneNode* joint = controllerInstance->GetJoint(i); + REQUIRE(joint != NULL, "joint exists"); + + int boneId = StdSkeletons::FindStandardBoneID(joint->GetName()); + if (boneId < 0) + { + // unrecognised joint - it's probably just a prop point + // or something, so ignore it + continue; + } + + // Skip unanimated joints + if (joint->GetTransformCount() == 0) + continue; + + for (size_t j = 0; j < joint->GetTransformCount(); ++j) + { + FCDTransform* transform = joint->GetTransform(j); + + if (! transform->IsAnimated()) + continue; + + // Iterate over all curves + FCDAnimated* anim = transform->GetAnimated(); + FCDAnimationCurveListList& curvesList = anim->GetCurves(); + for (size_t j = 0; j < curvesList.size(); ++j) + { + FCDAnimationCurveList& curves = curvesList[j]; + for (size_t k = 0; k < curves.size(); ++k) + { + FCDAnimationCurve* curve = curves[k]; + timeStart = std::min(timeStart, curve->GetKeys().front()); + timeEnd = std::max(timeEnd, curve->GetKeys().back()); + } + } + } + } + } + + static bool GetAnimationRange_XSI(FColladaDocument& doc, float& timeStart, float& timeEnd) + { + FCDExtra* extra = doc.GetExtra(); + if (! extra) return false; + + FCDEType* type = extra->GetDefaultType(); + if (! type) return false; + + FCDETechnique* technique = type->FindTechnique("XSI"); + if (! technique) return false; + + FCDENode* scene = technique->FindChildNode("SI_Scene"); + if (! scene) return false; + + float start = FLT_MAX, end = -FLT_MAX, framerate = 0.f; + + FCDENodeList paramNodes; + scene->FindChildrenNodes("xsi_param", paramNodes); + for (FCDENodeList::iterator it = paramNodes.begin(); it != paramNodes.end(); ++it) + { + if ((*it)->ReadAttribute("sid") == "start") + start = FUStringConversion::ToFloat((*it)->GetContent()); + else if ((*it)->ReadAttribute("sid") == "end") + end = FUStringConversion::ToFloat((*it)->GetContent()); + else if ((*it)->ReadAttribute("sid") == "frameRate") + framerate = FUStringConversion::ToFloat((*it)->GetContent()); + } + + if (framerate != 0.f && start != FLT_MAX && end != -FLT_MAX) + { + timeStart = start / framerate; + timeEnd = end / framerate; + return true; + } + + return false; + } + + static void EvaluateAnimations(FCDSceneNode* node, float time) + { + for (size_t i = 0; i < node->GetTransformCount(); ++i) + { + FCDTransform* transform = node->GetTransform(i); + FCDAnimated* anim = transform->GetAnimated(); + if (anim) + anim->Evaluate(time); + } + + for (size_t i = 0; i < node->GetChildrenCount(); ++i) + EvaluateAnimations(node->GetChild(i), time); + } + }; diff --git a/source/collada/StdSkeletons.cpp b/source/collada/StdSkeletons.cpp index 97aeee5bdf..71963cf948 100644 --- a/source/collada/StdSkeletons.cpp +++ b/source/collada/StdSkeletons.cpp @@ -4,7 +4,7 @@ namespace { - const char* standardBoneNames[] = { + const char* standardBoneNames0[] = { /* */ "Bip01", /* */ "Bip01_Pelvis", /* */ "Bip01_Spine", @@ -36,8 +36,65 @@ namespace /* */ "Bip01_R_Toe0Nub", // (the above comments just stop the indentation being dropped by // automatic code-formatting things...) +// NULL +// }; +// (TODO (important): do this stuff properly) +// const char* standardBoneNames1[] = { + /* */ "Biped_GlobalSRT", + /* */ "Biped_Spineroot", + /* */ "Biped_Spine01", + /* */ "Biped_Spine02", + /* */ "Biped_Spine03", + /* */ "Biped_Spineeffector", + /* */ "Biped_Lshoulderroot", + /* */ "Biped_Lshoulder", + /* */ "Biped_Lshouldereffector", + /* */ "Biped_Larmroot", + /* */ "Biped_Lbicept", + /* */ "Biped_Lforearm", + /* */ "Biped_Larmupvector", + /* */ "Biped_Rshoulderroot", + /* */ "Biped_Rshoulder", + /* */ "Biped_Rshouldereffector", + /* */ "Biped_Rarmroot", + /* */ "Biped_Rbicept", + /* */ "Biped_Rforearm", + /* */ "Biped_Rarmupvector", + /* */ "Biped_neckroot", + /* */ "Biped_neck", + /* */ "Biped_head", + /* */ "Biped_headeffector", + /* */ "Biped_Llegroot", + /* */ "Biped_Lthigh", + /* */ "Biped_Lshin", + /* */ "Biped_Rlegroot", + /* */ "Biped_Rthigh", + /* */ "Biped_Rshin", + /* */ "Biped_Llegupvector", + /* */ "Biped_Rlegupvector", + /* */ "Biped_Larmeffector", + /* */ "Biped_Lhandroot", + /* */ "Biped_Lhand", + /* */ "Biped_Lfingers", + /* */ "Biped_Lhandeffector", + /* */ "Biped_Llegeffector", + /* */ "Biped_Lfooteffector", + /* */ "Biped_Lfoot", + /* */ "Biped_Ltoe", + /* */ "Biped_Ltoeeffector", + /* */ "Biped_Rarmeffector", + /* */ "Biped_Rhandroot", + /* */ "Biped_Rhand", + /* */ "Biped_Rfingers", + /* */ "Biped_Rhandeffector", + /* */ "Biped_Rlegeffector", + /* */ "Biped_Rfootroot", + /* */ "Biped_Rfoot", + /* */ "Biped_Rtoe", + /* */ "Biped_Rtoeeffector", NULL }; + } namespace StdSkeletons @@ -45,15 +102,15 @@ namespace StdSkeletons int GetBoneCount() { int i = 0; - while (standardBoneNames[i] != NULL) + while (standardBoneNames0[i] != NULL) ++i; return i; } int FindStandardBoneID(const std::string& name) { - for (int i = 0; standardBoneNames[i] != NULL; ++i) - if (standardBoneNames[i] == name) + for (int i = 0; standardBoneNames0[i] != NULL; ++i) + if (standardBoneNames0[i] == name) return i; return -1; } diff --git a/source/collada/precompiled.h b/source/collada/precompiled.h index 9b2ab329b9..57e1ab02ff 100644 --- a/source/collada/precompiled.h +++ b/source/collada/precompiled.h @@ -15,6 +15,7 @@ extern void Log(int severity, const char* fmt, ...); #include "FCollada.h" #include "FCDocument/FCDAsset.h" #include "FCDocument/FCDocument.h" +#include "FCDocument/FCDocumentTools.h" #include "FCDocument/FCDAnimated.h" #include "FCDocument/FCDAnimationCurve.h" #include "FCDocument/FCDController.h" @@ -27,6 +28,9 @@ extern void Log(int severity, const char* fmt, ...); #include "FCDocument/FCDGeometrySource.h" #include "FCDocument/FCDSceneNode.h" #include "FCDocument/FCDSkinController.h" +#include "FUtils/FUDaeSyntax.h" +#include "FUtils/FUFileManager.h" +#include "FUtils/FUXmlParser.h" #include #include