26 #include "FCDocument/FCDSceneNode.h"
27 #include "FCDocument/FCDSkinController.h"
28 #include "FUtils/FUDaeSyntax.h"
29 #include "FUtils/FUFileManager.h"
34 void require_(
int line,
bool value,
const char* type,
const char* message)
38 sprintf(linestr,
"%d", line);
39 throw ColladaException(std::string(type) +
" (line " + linestr +
"): " + message);
48 vsnprintf(buffer,
sizeof(buffer), msg, ap);
49 buffer[
sizeof(buffer)-1] =
'\0';
52 *((std::string*)ctx) += buffer;
56 : xmlErrors(xmlErrors_)
68 xmlSetGenericErrorFunc(NULL, NULL);
78 if (errorCode == FUError::WARNING_INVALID_POLYGON_MAT_SYMBOL)
83 errorString =
"Unknown error code";
85 if (errorLevel == FUError::DEBUG_LEVEL)
86 Log(
LOG_INFO,
"FCollada %d: %s", errorCode, errorString);
87 else if (errorLevel == FUError::WARNING_LEVEL)
98 document.reset(FCollada::NewTopDocument());
100 const char* newText = NULL;
101 size_t newTextSize = 0;
105 bool status = FCollada::LoadDocumentFromMemory(
"unknown.dae",
document.get(), (
void*)newText, newTextSize);
108 xmlFree((
void*)newText);
143 REQUIRE(root != NULL,
"has root object");
154 if (asset && asset->GetContributorCount() >= 1)
156 std::string tool (asset->GetContributor(0)->GetAuthoringTool());
157 if (tool.find(
"XSI") != tool.npos)
162 m_YUp = (upAxis.y != 0);
174 static float identity[] = { 1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1 };
187 FCDExtra* extra = node->GetExtra();
188 if (! extra)
return false;
190 FCDEType* type = extra->GetDefaultType();
191 if (! type)
return false;
193 FCDETechnique* technique = type->FindTechnique(
"XSI");
194 if (! technique)
return false;
196 FCDENode* visibility1 = technique->FindChildNode(
"SI_Visibility");
197 if (! visibility1)
return false;
199 FCDENode* visibility2 = visibility1->FindChildNode(
"xsi_param");
200 if (! visibility2)
return false;
202 if (IsEquivalent(visibility2->GetContent(),
"TRUE"))
204 else if (IsEquivalent(visibility2->GetContent(),
"FALSE"))
211 bool visible =
false;
218 visible = (node->GetVisibility() != 0.0);
232 static void FindInstances(FCDSceneNode* node, std::vector<FoundInstance>& instances,
const FMMatrix44& transform,
bool onlyMarked)
234 for (
size_t i = 0; i < node->GetChildrenCount(); ++i)
236 FCDSceneNode* child = node->GetChild(i);
237 FindInstances(child, instances, transform * node->ToMatrix(), onlyMarked);
240 for (
size_t i = 0; i < node->GetInstanceCount(); ++i)
244 if (node->GetNote() !=
"export")
249 FCDEntity::Type type = node->GetInstance(i)->GetEntityType();
250 if (! (type == FCDEntity::GEOMETRY || type == FCDEntity::CONTROLLER))
258 f.
transform = transform * node->ToMatrix();
260 instances.push_back(f);
261 Log(
LOG_INFO,
"Found convertible object '%s'", node->GetName().c_str());
267 std::vector<FoundInstance> instances;
270 if (instances.size() > 1)
275 if (instances.empty())
278 if (instances.size() > 1)
280 Log(
LOG_ERROR,
"Found too many possible objects to convert - try adding the 'export' property to disambiguate one");
283 if (instances.empty())
290 assert(instances.size() == 1);
291 instance = instances[0].instance;
292 transform = instances[0].transform;
300 return (a.weight > b.weight);
309 for (
size_t i = 0; i < skin->GetInfluenceCount(); ++i)
311 FCDSkinControllerVertex& influence = *skin->GetVertexInfluence(i);
313 std::vector<FCDJointWeightPair> newWeights;
314 for (
size_t i = 0; i < influence.GetPairCount(); ++i)
316 FCDJointWeightPair* weight = influence.GetPair(i);
318 for (
size_t j = 0; j < newWeights.size(); ++j)
320 FCDJointWeightPair& newWeight = newWeights[j];
321 if (weight->jointIndex == newWeight.jointIndex)
323 newWeight.weight += weight->weight;
328 newWeights.push_back(*weight);
336 if (newWeights.size() > maxInfluenceCount)
337 newWeights.resize(maxInfluenceCount);
343 while (!newWeights.empty() && newWeights.back().weight < minimumWeight)
344 newWeights.pop_back();
347 float totalWeight = 0;
348 for (std::vector<FCDJointWeightPair>::iterator itNW = newWeights.begin(); itNW != newWeights.end(); ++itNW)
349 totalWeight += itNW->weight;
350 for (std::vector<FCDJointWeightPair>::iterator itNW = newWeights.begin(); itNW != newWeights.end(); ++itNW)
351 itNW->weight /= totalWeight;
354 influence.SetPairCount(0);
355 for (std::vector<FCDJointWeightPair>::iterator itNW = newWeights.begin(); itNW != newWeights.end(); ++itNW)
356 influence.AddPair(itNW->jointIndex, itNW->weight);
359 skin->SetDirtyFlag();
370 if (controllerInstance.GetSkeletonRoots().empty())
374 FUUriList& uriList =
const_cast<FUUriList&
>(controllerInstance.GetSkeletonRoots());
375 uriList.push_back(FUUri(
"Scene_Root"));
376 controllerInstance.LinkImport();
388 const FCDSceneNode* joint = controllerInstance.GetJoint(0);
391 joint = joint->GetParent();
393 REQUIRE(skeleton != NULL,
"recognised skeleton structure");
397 void TransformBones(std::vector<BoneTransform>& bones,
const FMMatrix44& scaleTransform,
bool yUp)
399 for (
size_t i = 0; i < bones.size(); ++i)
402 FMVector3 trans(bones[i].translation, 0);
403 trans = scaleTransform.TransformCoordinate(trans);
404 bones[i].translation[0] = trans.x;
405 bones[i].translation[1] = trans.y;
406 bones[i].translation[2] = trans.z;
432 bones[i].translation[2] = -bones[i].translation[2];
433 bones[i].orientation[2] = -bones[i].orientation[2];
434 bones[i].orientation[3] = -bones[i].orientation[3];
439 std::swap(bones[i].translation[1], bones[i].translation[2]);
446 std::swap(bones[i].orientation[1], bones[i].orientation[2]);
447 bones[i].orientation[3] = -bones[i].orientation[3];
FMMatrix44 m_EntityTransform
void require_(int line, bool value, const char *type, const char *message)
static const Skeleton * FindSkeleton(const std::string &rootBoneName)
Tries to find a skeleton that matches the given root bone name.
#define UNUSED(param)
mark a function parameter as unused and avoid the corresponding compiler warning. ...
#define REQUIRE(value, message)
Throws a ColladaException unless the value is true.
void ReadExtras(xmlNode *colladaNode)
static bool IsVisible(FCDSceneNode *node)
static bool IsVisible_XSI(FCDSceneNode *node, bool &visible)
FCDEntityInstance * m_Instance
FCDocument * GetDocument() const
Returns the FCDocument that was loaded.
void SkinReduceInfluences(FCDSkinController *skin, size_t maxInfluenceCount, float minimumWeight)
Like FCDSkinController::ReduceInfluences but works correctly.
static void swap(UniqueRange &p1, UniqueRange &p2)
CommonConvert(const char *text, std::string &xmlErrors)
bool FindSingleInstance(FCDSceneNode *node, FCDEntityInstance *&instance, FMMatrix44 &transform)
Tries to find a single suitable entity instance in the scene.
FMMatrix44 FMMatrix44_Identity
std::auto_ptr< FCDocument > document
void FixSkeletonRoots(FCDControllerInstance &controllerInstance)
Fixes some occasional problems with the skeleton root definitions in a controller.
const Skeleton & FindSkeleton(const FCDControllerInstance &controllerInstance)
Finds the skeleton definition which best matches the given controller.
static void FindInstances(FCDSceneNode *node, std::vector< FoundInstance > &instances, const FMMatrix44 &transform, bool onlyMarked)
Recursively finds all entities under the current node.
void TransformBones(std::vector< BoneTransform > &bones, const FMMatrix44 &scaleTransform, bool yUp)
Performs the standard transformations on bones, applying a scale matrix and moving them into the game...
FColladaErrorHandler(std::string &xmlErrors)
void OnError(FUError::Level errorLevel, uint32 errorCode, uint32 lineNumber)
const char * GetErrorString(PSRETURN code)
void LoadFromText(const char *text)
Loads the document from the given XML string.
void FixBrokenXML(const char *text, const char **out, size_t *outSize)
Fixes some errors in COLLADA XML files that would otherwise prevent FCollada from loading them succes...
#define REQUIRE_SUCCESS(status)
Throws a ColladaException unless the status is successful.
void errorHandler(void *ctx, const char *msg,...)
Error handler for libxml2.
FCDEntityInstance * instance
static bool ReverseSortWeight(const FCDJointWeightPair &a, const FCDJointWeightPair &b)
void Log(int severity, const char *msg,...)
const FMVector3 FMVector3_XAxis(1.0f, 0.0f, 0.0f)