/* Copyright (C) 2005-2007 Feeling Software Inc. Portions of the code are: Copyright (C) 2005-2007 Sony Computer Entertainment America MIT License: http://www.opensource.org/licenses/mit-license.php */ #include "StdAfx.h" #include "FArchiveXML.h" #include "FCDocument/FCDocument.h" #include "FCDocument/FCDGeometry.h" #include "FCDocument/FCDEntity.h" #include "FCDocument/FCDController.h" #include "FCDocument/FCDSkinController.h" #include "FCDocument/FCDMorphController.h" #include "FCDocument/FCDControllerInstance.h" xmlNode* FArchiveXML::WriteController(FCDObject* object, xmlNode* parentNode) { FCDController* controller = (FCDController*)object; xmlNode* controllerNode = FArchiveXML::WriteToEntityXMLFCDEntity(controller, parentNode, DAE_CONTROLLER_ELEMENT); if (controller->GetSkinController() != NULL) FArchiveXML::LetWriteObject(controller->GetSkinController(), controllerNode); else if (controller->GetMorphController() != NULL) FArchiveXML::LetWriteObject(controller->GetMorphController(), controllerNode); FArchiveXML::WriteEntityExtra(controller, controllerNode); return controllerNode; } xmlNode* FArchiveXML::WriteSkinController(FCDObject* object, xmlNode* parentNode) { FCDSkinController* skinController = (FCDSkinController*)object; // Create the element xmlNode* skinNode = AddChild(parentNode, DAE_CONTROLLER_SKIN_ELEMENT); FUUri targetUri = skinController->GetTargetUri(); fstring targetPath = skinController->GetDocument()->GetFileManager()->CleanUri(targetUri); AddAttribute(skinNode, DAE_SOURCE_ATTRIBUTE, targetPath); // Create the element fm::string bindShapeMatrixString = FUStringConversion::ToString((FMMatrix44&) skinController->GetBindShapeTransform()); AddChild(skinNode, DAE_BINDSHAPEMX_SKIN_PARAMETER, bindShapeMatrixString); // Prepare the joint source information size_t jointCount = skinController->GetJointCount(); StringList jointSubIds; jointSubIds.reserve(jointCount); FMMatrix44List jointBindPoses; jointBindPoses.reserve(jointCount); for (size_t i = 0; i < jointCount; ++i) { FCDSkinControllerJoint* joint = skinController->GetJoint(i); jointSubIds.push_back(joint->GetId()); jointBindPoses.push_back(joint->GetBindPoseInverse()); } // Create the joint source. FUSStringBuilder jointSourceId(skinController->GetParent()->GetDaeId()); jointSourceId += "-joints"; AddSourceString(skinNode, jointSourceId.ToCharPtr(), jointSubIds, DAE_JOINT_SKIN_INPUT); // Create the joint bind matrix source FUSStringBuilder jointBindSourceId(skinController->GetParent()->GetDaeId()); jointBindSourceId += "-bind_poses"; AddSourceMatrix(skinNode, jointBindSourceId.ToCharPtr(), jointBindPoses); // Create the weight source FloatList weights; weights.push_back(1.0f); size_t influenceCount = skinController->GetInfluenceCount(); for (size_t i = 0; i < influenceCount; ++i) { const FCDSkinControllerVertex* vertex = skinController->GetVertexInfluence(i); for (size_t i = 0; i < vertex->GetPairCount(); ++i) { float w = vertex->GetPair(i)->weight; if (!IsEquivalent(w, 1.0f)) weights.push_back(w); } } FUSStringBuilder weightSourceId(skinController->GetParent()->GetDaeId()); weightSourceId += "-weights"; AddSourceFloat(skinNode, weightSourceId.ToCharPtr(), weights, DAE_WEIGHT_SKIN_INPUT); // Create the element xmlNode* jointsNode = AddChild(skinNode, DAE_JOINTS_ELEMENT); AddInput(jointsNode, jointSourceId.ToCharPtr(), DAE_JOINT_SKIN_INPUT); AddInput(jointsNode, jointBindSourceId.ToCharPtr(), DAE_BINDMATRIX_SKIN_INPUT); // Create the element xmlNode* matchesNode = AddChild(skinNode, DAE_WEIGHTS_ELEMENT); AddInput(matchesNode, jointSourceId.ToCharPtr(), DAE_JOINT_SKIN_INPUT, 0); AddInput(matchesNode, weightSourceId.ToCharPtr(), DAE_WEIGHT_SKIN_INPUT, 1); AddAttribute(matchesNode, DAE_COUNT_ATTRIBUTE, skinController->GetInfluenceCount()); // Generate the vertex count and match value strings and export the and elements FUSStringBuilder vertexCounts; vertexCounts.reserve(1024); FUSStringBuilder vertexMatches; vertexMatches.reserve(1024); uint32 weightOffset = 1; for (size_t j = 0; j < influenceCount; ++j) { const FCDSkinControllerVertex* vertex = skinController->GetVertexInfluence(j); vertexCounts.append((uint32) vertex->GetPairCount()); vertexCounts.append(' '); for (size_t i = 0; i < vertex->GetPairCount(); ++i) { const FCDJointWeightPair* pair = vertex->GetPair(i); vertexMatches.append(pair->jointIndex); vertexMatches.append(' '); if (!IsEquivalent(pair->weight, 1.0f)) vertexMatches.append(weightOffset++); else vertexMatches.append('0'); vertexMatches.append(' '); } } if (!vertexMatches.empty()) vertexMatches.pop_back(); AddChild(matchesNode, DAE_VERTEXCOUNT_ELEMENT, vertexCounts); AddChild(matchesNode, DAE_VERTEX_ELEMENT, vertexMatches); return skinNode; } xmlNode* FArchiveXML::WriteMorphController(FCDObject* object, xmlNode* parentNode) { FCDMorphController* morphController = (FCDMorphController*)object; size_t targetCount = morphController->GetTargetCount(); // Create the node and set its attributes xmlNode* morphNode = AddChild(parentNode, DAE_CONTROLLER_MORPH_ELEMENT); AddAttribute(morphNode, DAE_METHOD_ATTRIBUTE, FUDaeMorphMethod::ToString(morphController->GetMethod())); if (morphController->GetBaseTarget() != NULL) { AddAttribute(morphNode, DAE_SOURCE_ATTRIBUTE, fm::string("#") + morphController->GetBaseTarget()->GetDaeId()); } // Gather up the morph target ids and the morphing weights StringList targetIds; targetIds.reserve(targetCount); FloatList weights; weights.reserve(targetCount); for (size_t i = 0 ; i < morphController->GetTargetCount(); ++i) { const FCDMorphTarget* t = morphController->GetTarget(i); targetIds.push_back(t->GetGeometry() != NULL ? t->GetGeometry()->GetDaeId() : DAEERR_UNKNOWN_IDREF); weights.push_back(t->GetWeight()); } // Export the target id source FUSStringBuilder targetSourceId(morphController->GetParent()->GetDaeId()); targetSourceId.append("-targets"); AddSourceIDRef(morphNode, targetSourceId.ToCharPtr(), targetIds, DAE_TARGET_MORPH_INPUT); // Export the weight source FUSStringBuilder weightSourceId(morphController->GetParent()->GetDaeId()); weightSourceId.append("-morph_weights"); xmlNode* weightSourceNode = AddSourceFloat(morphNode, weightSourceId.ToCharPtr(), weights, DAE_WEIGHT_MORPH_INPUT); // Export the elements xmlNode* targetsNode = AddChild(morphNode, DAE_TARGETS_ELEMENT); AddInput(targetsNode, targetSourceId.ToCharPtr(), DAE_TARGET_MORPH_INPUT); AddInput(targetsNode, weightSourceId.ToCharPtr(), DAE_WEIGHT_MORPH_INPUT); // Record the morphing weight animations for (int32 i = 0; i < (int32) targetCount; ++i) { const FCDMorphTarget* t = morphController->GetTarget(i); FArchiveXML::WriteAnimatedValue(&t->GetWeight(), weightSourceNode, "morphing_weights", i); } return morphNode; }