bool FArchiveXML::LoadTransformSkew(FCDObject* object, xmlNode* skewNode) { FCDTSkew* tSkew = (FCDTSkew*)object; const char* content = FUDaeParser::ReadNodeContentDirect(skewNode); FloatList factors; factors.reserve(7); FUStringConversion::ToFloatList(content, factors); if (factors.size() != 7) return false; tSkew->SetAngle(factors[0]); tSkew->SetRotateAxis(FMVector3(factors[1], factors[2], factors[3])); tSkew->SetAroundAxis(FMVector3(factors[4], factors[5], factors[6])); // Check and pre-process the axises if (IsEquivalent(tSkew->GetRotateAxis(), FMVector3::Origin) || IsEquivalent(tSkew->GetAroundAxis(), FMVector3::Origin)) return false; tSkew->SetRotateAxis(tSkew->GetRotateAxis().Normalize()); tSkew->SetAroundAxis(tSkew->GetAroundAxis().Normalize()); // Register the animated values FArchiveXML::LoadAnimatable(&tSkew->GetSkew(), skewNode); tSkew->SetDirtyFlag(); return true; }
bool FArchiveXML::LoadTransformTranslation(FCDObject* object, xmlNode* node) { FCDTTranslation* tTranslation = (FCDTTranslation*)object; const char* content = FUDaeParser::ReadNodeContentDirect(node); FloatList factors; factors.reserve(3); FUStringConversion::ToFloatList(content, factors); if (factors.size() != 3) return false; tTranslation->SetTranslation(factors[0], factors[1], factors[2]); FArchiveXML::LoadAnimatable(&tTranslation->GetTranslation(), node); tTranslation->SetDirtyFlag(); return true; }
bool FArchiveXML::LoadTransformScale(FCDObject* object, xmlNode* node) { FCDTScale* tScale = (FCDTScale*)object; const char* content = FUDaeParser::ReadNodeContentDirect(node); FloatList factors; factors.reserve(3); FUStringConversion::ToFloatList(content, factors); if (factors.size() != 3) return false; tScale->SetScale(factors[0], factors[1], factors[2]); // Register the animated values FArchiveXML::LoadAnimatable(&tScale->GetScale(), node); tScale->SetDirtyFlag(); return true; }
bool FArchiveXML::LoadTransformLookAt(FCDObject* object, xmlNode* lookAtNode) { FCDTLookAt* tLookAt = (FCDTLookAt*)object; const char* content = FUDaeParser::ReadNodeContentDirect(lookAtNode); FloatList factors; factors.reserve(9); FUStringConversion::ToFloatList(content, factors); if (factors.size() != 9) return false; tLookAt->GetPosition().Set(factors[0], factors[1], factors[2]); tLookAt->GetTarget().Set(factors[3], factors[4], factors[5]); tLookAt->GetUp().Set(factors[6], factors[7], factors[8]); // Register the animated values FArchiveXML::LoadAnimatable(&tLookAt->GetLookAt(), lookAtNode); tLookAt->SetDirtyFlag(); return true; }
xmlNode* FArchiveXML::WriteAnimationChannel(FCDObject* object, xmlNode* parentNode) { FCDAnimationChannel* animationChannel = (FCDAnimationChannel*)object; FCDAnimationChannelData& data = FArchiveXML::documentLinkDataMap[animationChannel->GetDocument()].animationChannelData[animationChannel]; //FUAssert(!data.targetPointer.empty(), NULL); fm::string baseId = FCDObjectWithId::CleanId(animationChannel->GetParent()->GetDaeId() + "_" + data.targetPointer); // Check for curve merging uint32 realCurveCount = 0; const FCDAnimationCurve* masterCurve = NULL; FCDAnimationCurveList mergingCurves; mergingCurves.resize(data.defaultValues.size()); bool mergeCurves = true; size_t curveCount = animationChannel->GetCurveCount(); for (size_t i = 0; i < curveCount; ++i) { const FCDAnimationCurve* curve = animationChannel->GetCurve(i); if (curve != NULL) { // Check that we have a default placement for this curve in the default value listing size_t dv; for (dv = 0; dv < data.defaultValues.size(); ++dv) { if (data.defaultValues[dv].curve == curve) { mergingCurves[dv] = const_cast<FCDAnimationCurve*>(curve); break; } } mergeCurves &= dv != data.defaultValues.size(); // Check that the curves can be merged correctly. ++realCurveCount; if (masterCurve == NULL) { masterCurve = curve; } else { // Check the infinity types, the keys and the interpolations. size_t curveKeyCount = curve->GetKeyCount(); size_t masterKeyCount = masterCurve->GetKeyCount(); mergeCurves &= masterKeyCount == curveKeyCount; if (!mergeCurves) break; for (size_t j = 0; j < curveKeyCount && mergeCurves; ++j) { const FCDAnimationKey* curveKey = curve->GetKey(j); const FCDAnimationKey* masterKey = masterCurve->GetKey(j); mergeCurves &= IsEquivalent(curveKey->input, masterKey->input); mergeCurves &= curveKey->interpolation == masterKey->interpolation; // Prevent curve having TCB interpolation from merging mergeCurves &= curveKey->interpolation != FUDaeInterpolation::TCB; mergeCurves &= masterKey->interpolation != FUDaeInterpolation::TCB; } if (!mergeCurves) break; mergeCurves &= curve->GetPostInfinity() == masterCurve->GetPostInfinity(); mergeCurves &= curve->GetPreInfinity() == masterCurve->GetPreInfinity(); } // Disallow the merging of any curves with a driver. mergeCurves &= !curve->HasDriver(); } } if (mergeCurves && realCurveCount > 1) { // Prepare the list of default values FloatList values; values.reserve(data.defaultValues.size()); for (FAXAnimationChannelDefaultValueList::iterator itDV = data.defaultValues.begin(); itDV != data.defaultValues.end(); ++itDV) { values.push_back((*itDV).defaultValue); } FUAssert(data.animatedValue != NULL, return parentNode); const char** qualifiers = new const char*[values.size()]; memset(qualifiers, 0, sizeof(char*) * values.size()); for (size_t i = 0; i < values.size() && i < data.animatedValue->GetValueCount(); ++i) { qualifiers[i] = data.animatedValue->GetQualifier(i); } // Merge and export the curves FCDAnimationMultiCurve* multiCurve = FCDAnimationCurveTools::MergeCurves(mergingCurves, values); FArchiveXML::WriteSourceFCDAnimationMultiCurve(multiCurve, parentNode, qualifiers, baseId); FArchiveXML::WriteSamplerFCDAnimationMultiCurve(multiCurve, parentNode, baseId); FArchiveXML::WriteChannelFCDAnimationMultiCurve(multiCurve, parentNode, baseId, data.targetPointer); SAFE_RELEASE(multiCurve); }