//----------------------------- void PostProcessor::createMissingAnimationList( const Loader::AnimationSidAddressBinding& binding ) { const SidTreeNode* sidTreeNode = resolveSid( binding.sidAddress); if ( sidTreeNode ) { if ( sidTreeNode->getTargetType() == SidTreeNode::TARGETTYPECLASS_ANIMATABLE ) { COLLADAFW::Animatable* animatable = sidTreeNode->getAnimatableTarget(); COLLADAFW::UniqueId animationListUniqueId = animatable->getAnimationList(); if ( !animationListUniqueId.isValid() ) { animationListUniqueId = createUniqueId( COLLADAFW::AnimationList::ID() ); animatable->setAnimationList( animationListUniqueId ); } COLLADAFW::AnimationList*& animationList = getAnimationListByUniqueId(animationListUniqueId); if ( !animationList ) { animationList = new COLLADAFW::AnimationList( animationListUniqueId ); } // TODO handle this for arrays COLLADAFW::AnimationList::AnimationBinding animationBinding; animationBinding.animation = binding.animationInfo.uniqueId; animationBinding.animationClass = binding.animationInfo.animationClass; switch ( binding.sidAddress.getMemberSelection() ) { case SidAddress::MEMBER_SELECTION_ONE_INDEX: animationBinding.firstIndex = binding.sidAddress.getFirstIndex(); animationBinding.secondIndex = 0; animationBinding.animationClass = COLLADAFW::AnimationList::ARRAY_ELEMENT_1D; break; case SidAddress::MEMBER_SELECTION_TWO_INDICES: animationBinding.firstIndex = binding.sidAddress.getFirstIndex(); animationBinding.secondIndex = binding.sidAddress.getSecondIndex(); animationBinding.animationClass = COLLADAFW::AnimationList::ARRAY_ELEMENT_2D; break; default: animationBinding.firstIndex = 0; animationBinding.secondIndex = 0; } animationList->getAnimationBindings().append( animationBinding ); } } }
//------------------------------ const COLLADAFW::AnimationList* ImporterBase::getAnimationList( const COLLADAFW::Animatable* animatable ) { if ( !animatable ) { return 0; } const COLLADAFW::UniqueId& referencedAnimationListUniqueId = animatable->getAnimationList(); if ( !referencedAnimationListUniqueId.isValid() ) { return 0; } return getAnimationListByUniqueId( referencedAnimationListUniqueId ); }
//------------------------------ bool MorphControllerCreator::createMorphController( const COLLADAFW::MorphController* morphController, INode* referencingINode ) { Object* sourceObject = getObjectByUniqueId( morphController->getSource() ); if ( !sourceObject ) { // TODO handle error // morph source object not present return true; } mMorphModifier = (MorphR3*) createMaxObject(OSM_CLASS_ID, MORPHER_CLASS_ID); if ( !mMorphModifier ) { // TODO handle error // morph controller could not be created return true; } if ( (sourceObject->ClassID() == derivObjClassID) || (sourceObject->ClassID() == WSMDerivObjClassID) ) { // Object is a derived object, just attach ourselves to it mDerivedObject = (IDerivedObject*) sourceObject; } else { // Create the derived object for the target and the modifier mDerivedObject = CreateDerivedObject(sourceObject); } mDerivedObject->AddModifier(mMorphModifier); mMorphModifier->cache.MakeCache(sourceObject); const COLLADAFW::FloatOrDoubleArray& morphWeights = morphController->getMorphWeights(); const COLLADAFW::UniqueIdArray& morphTargets = morphController->getMorphTargets(); // There is a maximum number of channels supported by the 3dsMax morpher: // Calculate the number of channels to process size_t colladaTargetCount = morphTargets.getCount(); int channelCount = (int) min(colladaTargetCount, mMorphModifier->chanBank.size()); const COLLADAFW::UniqueId& morphWeightsAnimationListId = morphWeights.getAnimationList(); const COLLADAFW::AnimationList* morphWeightsAnimationList = getAnimationListByUniqueId( morphWeightsAnimationListId ); for (int i = 0; i < channelCount; ++i) { const COLLADAFW::UniqueId& targetUniqueId = morphTargets[i]; Object* targetObject = getObjectByUniqueId( targetUniqueId ); if ( !targetObject ) { // TODO handle error // the target has not been created, might be missing in dae file return true; } INodeList targetINodes; getObjectINodesByUniqueId( targetUniqueId, targetINodes ); INode* targetINode = 0; if ( !targetINodes.empty() ) { // it does not seem to make a difference which INode we use, as long as it references the correct geometry targetINode = targetINodes[0]; } morphChannel* channel = &mMorphModifier->chanBank[i]; if ( targetINode ) { channel->buildFromNode(targetINode); channel->mConnection = targetINode; } else { // Manually initializes this channel initializeChannelGeometry(channel, targetObject); } if ( !morphWeightsAnimationList ) { float weight = 0; if ( morphWeights.getType() == COLLADAFW::FloatOrDoubleArray::DATA_TYPE_FLOAT ) { weight = (*morphWeights.getFloatValues())[i]; } else if ( morphWeights.getType() == COLLADAFW::FloatOrDoubleArray::DATA_TYPE_DOUBLE ) { weight = (float)(*morphWeights.getDoubleValues())[i]; } channel->cblock->SetValue(0, 0, weight * 100); } } if ( morphWeightsAnimationList ) { const COLLADAFW::AnimationList::AnimationBindings& animationBindings = morphWeightsAnimationList->getAnimationBindings(); for ( size_t i = 0, count = animationBindings.getCount(); i < count; ++i) { const COLLADAFW::AnimationList::AnimationBinding& animationBinding = animationBindings[i]; if ( animationBinding.animationClass != COLLADAFW::AnimationList::ARRAY_ELEMENT_1D) { // this animation does not animate one element of a one dimensional array continue; } const DocumentImporter::MaxControllerList& maxControllerList = getMaxControllerListByAnimationUniqueId( animationBinding.animation ); assert(maxControllerList.size()==1); if ( maxControllerList.size() < 1 ) { // this animation does not animate one element of a one dimensional array continue; } Control* weightController = maxControllerList[0]; size_t channelNumber = animationBinding.firstIndex; if ( (int)channelNumber >= channelCount ) { // invalid channel continue; } morphChannel* channel = &mMorphModifier->chanBank[channelNumber]; if ( !channel ) { continue; } Control* scaledWeightController = cloneController( weightController, &ConversionFunctors::toPercent); //Control* scaledWeightController = cloneController( weightController); //channel->cblock->SetController(0, weightController); channel->cblock->SetController(0, scaledWeightController); } } //assign the morph controller to all INodes referencing it INodeList referencingINodes; getObjectINodesByUniqueId( morphController->getUniqueId(), referencingINodes ); for ( size_t i = 0, count = referencingINodes.size(); i < count; ++i) { INode* referencingINode = referencingINodes[i]; referencingINode->SetObjectRef(mDerivedObject); } addUniqueIdObjectPair( morphController->getUniqueId(), mDerivedObject ); return true; }