void FloatPlacement::initFloatTypeCO(FloatList const & floats) { if (float_list_ == &floats) return; float_list_ = &floats; floatTypeCO->clear(); FloatList::const_iterator it = floats.begin(); FloatList::const_iterator const end = floats.end(); for (; it != end; ++it) { floatTypeCO->addItem(qt_(it->second.name()), toqstr(it->second.floattype())); } }
void GenerateSampledAnimation(FCDSceneNode* node) { sampleKeys.clear(); sampleValues.clear(); FCDAnimatedList animateds; // Special case for rotation angles: need to check for changes that are greater than 180 degrees. Int32List angleIndices; // Collect all the animation curves size_t transformCount = node->GetTransformCount(); for (size_t t = 0; t < transformCount; ++t) { FCDTransform* transform = node->GetTransform(t); FCDAnimated* animated = transform->GetAnimated(); if (animated != NULL) { if (animated->HasCurve()) animateds.push_back(animated); // Figure out whether this is a rotation and then, which animated value contains the angle. if (!transform->HasType(FCDTRotation::GetClassType())) angleIndices.push_back(-1); else angleIndices.push_back((int32) animated->FindQualifier(".ANGLE")); } } if (animateds.empty()) return; // Make a list of the ordered key times to sample size_t animatedsCount = animateds.size(); for (size_t i = 0; i < animatedsCount; ++i) { FCDAnimated* animated = animateds[i]; int32 angleIndex = angleIndices[i]; const FCDAnimationCurveListList& allCurves = animated->GetCurves(); size_t valueCount = allCurves.size(); for (size_t curveIndex = 0; curveIndex < valueCount; ++curveIndex) { const FCDAnimationCurveTrackList& curves = allCurves[curveIndex]; if (curves.empty()) continue; size_t curveKeyCount = curves.front()->GetKeyCount(); const FCDAnimationKey** curveKeys = curves.front()->GetKeys(); size_t sampleKeyCount = sampleKeys.size(); // Merge this curve's keys in with the sample keys // This assumes both key lists are in increasing order size_t s = 0, c = 0; while (s < sampleKeyCount && c < curveKeyCount) { float sampleKey = sampleKeys[s], curveKey = curveKeys[c]->input; if (IsEquivalent(sampleKey, curveKey)) { ++s; ++c; } else if (sampleKey < curveKey) { ++s; } else { // Add this curve key to the sampling key list sampleKeys.insert(sampleKeys.begin() + (s++), curveKeys[c++]->input); sampleKeyCount++; } } // Add all the left-over curve keys to the sampling key list while (c < curveKeyCount) sampleKeys.push_back(curveKeys[c++]->input); // Check for large angular rotations.. if (angleIndex == (intptr_t) curveIndex) { for (size_t c = 1; c < curveKeyCount; ++c) { const FCDAnimationKey* previousKey = curveKeys[c - 1]; const FCDAnimationKey* currentKey = curveKeys[c]; float halfWrapAmount = (currentKey->output - previousKey->output) / 180.0f; halfWrapAmount *= FMath::Sign(halfWrapAmount); if (halfWrapAmount >= 1.0f) { // Need to add sample times. size_t addSampleCount = (size_t) floorf(halfWrapAmount); for (size_t d = 1; d <= addSampleCount; ++d) { float fd = (float) d; float fid = (float) (addSampleCount + 1 - d); float addSampleTime = (currentKey->input * fd + previousKey->input * fid) / (fd + fid); // Sorted insert. float* endIt = sampleKeys.end(); for (float* sampleKeyTime = sampleKeys.begin(); sampleKeyTime != endIt; ++sampleKeyTime) { if (IsEquivalent(*sampleKeyTime, addSampleTime)) break; else if (*sampleKeyTime > addSampleTime) { sampleKeys.insert(sampleKeyTime, addSampleTime); break; } } } } } } } } size_t sampleKeyCount = sampleKeys.size(); if (sampleKeyCount == 0) return; // Pre-allocate the value array; sampleValues.reserve(sampleKeyCount); // Sample the scene node transform for (size_t i = 0; i < sampleKeyCount; ++i) { float sampleTime = sampleKeys[i]; for (FCDAnimatedList::iterator it = animateds.begin(); it != animateds.end(); ++it) { // Sample each animated, which changes the transform values directly (*it)->Evaluate(sampleTime); } // Retrieve the new transform matrix for the COLLADA scene node sampleValues.push_back(node->ToMatrix()); } }
//--------------------------------------------------------------- void ControllerExporter::exportMorphController( ExportNode* exportNode, MorphController* morphController, const String& controllerId, const String& morphSource ) { MorphR3* morpher = morphController->getMorph(); FloatList listOfWeights; StringList listOfTargetIds; String weightsId = controllerId + WEIGHTS_SOURCE_ID_SUFFIX; size_t channelBankCount = morpher->chanBank.size(); for ( size_t i = 0; i<channelBankCount; ++i) { morphChannel& channel = morpher->chanBank[i]; if (!channel.mActive || channel.mNumPoints == 0) continue; INode* targetINode = channel.mConnection; listOfWeights.push_back(ConversionFunctors::fromPercent(channel.cblock->GetFloat(morphChannel::cblock_weight_index, mDocumentExporter->getOptions().getAnimationStart()))); Control* weightController = channel.cblock->GetController(morphChannel::cblock_weight_index); mDocumentExporter->getAnimationExporter()->addAnimatedFloat(weightController, weightsId, EMPTY_STRING, (int)i, true, &ConversionFunctors::fromPercent ); if ( !targetINode ) { MorphControllerHelperGeometry morphControllerHelperGeometry; morphControllerHelperGeometry.exportNode = exportNode; morphControllerHelperGeometry.controllerId = controllerId; morphControllerHelperGeometry.morphController = morphController; morphControllerHelperGeometry.channelBankindex = i; String targetId = ExportSceneGraph::getMorphControllerHelperId(morphControllerHelperGeometry); listOfTargetIds.push_back(targetId); } else { ExportNode* targetExportNode = mExportSceneGraph->getExportNode(targetINode); assert(targetExportNode); ExportNode* geometryExportNode = mDocumentExporter->getExportedObjectExportNode(ObjectIdentifier(targetExportNode->getInitialPose())); assert( geometryExportNode ); // listOfTargetIds.push_back(geometryExportNode); listOfTargetIds.push_back(GeometriesExporter::getGeometryId(*geometryExportNode)); } } openMorph(controllerId, EMPTY_STRING, morphSource); //export weights source String targetId = controllerId + TARGETS_SOURCE_ID_SUFFIX; COLLADASW::IdRefSource targetsSource(mSW); targetsSource.setId(targetId); targetsSource.setArrayId(targetId + ARRAY_ID_SUFFIX); targetsSource.setAccessorStride(1); targetsSource.getParameterNameList().push_back("MORPH_TARGET"); targetsSource.setAccessorCount((unsigned long)listOfTargetIds.size()); targetsSource.prepareToAppendValues(); for ( StringList::const_iterator it = listOfTargetIds.begin(); it != listOfTargetIds.end(); ++it) targetsSource.appendValues(*it); targetsSource.finish(); //export weights source COLLADASW::FloatSource weightsSource(mSW); weightsSource.setId(weightsId); weightsSource.setArrayId(weightsId + ARRAY_ID_SUFFIX); weightsSource.setAccessorStride(1); weightsSource.getParameterNameList().push_back("MORPH_WEIGHT"); weightsSource.setAccessorCount((unsigned long)listOfWeights.size()); weightsSource.prepareToAppendValues(); for ( FloatList::const_iterator it = listOfWeights.begin(); it != listOfWeights.end(); ++it) weightsSource.appendValues(*it); weightsSource.finish(); COLLADASW::TargetsElement targets(mSW); targets.getInputList().push_back(COLLADASW::Input(COLLADASW::InputSemantic::MORPH_TARGET, "#" + targetId)); targets.getInputList().push_back(COLLADASW::Input(COLLADASW::InputSemantic::MORPH_WEIGHT, "#" + weightsId)); targets.add(); closeMorph(); }