| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421 |
- #include "Base.h"
- #include "DAEUtil.h"
- #include "StringUtil.h"
- namespace gameplay
- {
- /**
- * Returns the index of the skeleton in skeletonArray that points to the given node.
- *
- * @param skeletonArray The array of skeletons to search.
- * @param node The target node.
- *
- * @return The index in skeletonArray or -1 if not found.
- */
- static int getIndex(const domInstance_controller::domSkeleton_Array& skeletonArray, const domNodeRef& node);
- /**
- * Gets all of the animation channels that target the given node and appends them to the list.
- *
- * @param animationRef The animation to search in.
- * @param nodeIdSlash The node's id with a forward slash appended to it.
- * @param channels The list of channels to append to.
- */
- static void getAnimationChannels(const domAnimationRef& animationRef, const std::string& nodeIdSlash, std::list<domChannelRef>& channels);
- void getAnimationChannels(const domNodeRef& node, std::list<domChannelRef>& channels)
- {
- assert(node->getId());
- std::string nodeIdSlash (node->getId());
- nodeIdSlash.append("/");
- domCOLLADA* root = (domCOLLADA*)node->getDocument()->getDomRoot();
- domLibrary_animations_Array& animationLibrary = root->getLibrary_animations_array();
- size_t animationLibraryCount = animationLibrary.getCount();
- for (size_t i = 0; i < animationLibraryCount; ++i)
- {
- domLibrary_animationsRef& animationsRef = animationLibrary.get(i);
- domAnimation_Array& animationArray = animationsRef->getAnimation_array();
- size_t animationCount = animationArray.getCount();
- for (size_t j = 0; j < animationCount; ++j)
- {
- domAnimationRef& animationRef = animationArray.get(j);
- getAnimationChannels(animationRef, nodeIdSlash, channels);
- }
- }
- // Recursively do the same for all nodes
- daeTArray< daeSmartRef<daeElement> > children;
- node->getChildren(children);
- size_t childCount = children.getCount();
- for (size_t i = 0; i < childCount; ++i)
- {
- daeElementRef childElement = children[i];
- if (childElement->getElementType() == COLLADA_TYPE::NODE)
- {
- domNodeRef childNode = daeSafeCast<domNode>(childElement);
- getAnimationChannels(childNode, channels);
- }
- }
- }
- void getJointNames(const domSourceRef source, std::vector<std::string>& list)
- {
- // BLENDER used name_array
- const domName_arrayRef& nameArray = source->getName_array();
- if (nameArray.cast())
- {
- domListOfNames& ids = nameArray->getValue();
- size_t jointCount = (size_t)nameArray->getCount();
- for (size_t j = 0; j < jointCount; ++j)
- {
- list.push_back(std::string(ids.get(j)));
- }
- }
- else
- {
- // Seymour used IDREF_array
- const domIDREF_arrayRef& idArray = source->getIDREF_array();
- if (idArray.cast())
- {
- xsIDREFS& ids = idArray->getValue();
- size_t jointCount = (size_t)idArray->getCount();
- for (size_t j = 0; j < jointCount; ++j)
- {
- list.push_back(std::string(ids.get(j).getID()));
- }
- }
- }
- }
- void getJointNames(const domSkin* skin, std::vector<std::string>& list)
- {
- const domSkin::domJointsRef& joints = skin->getJoints();
- const domInputLocal_Array& inputArray = joints->getInput_array();
- size_t inputCount = inputArray.getCount();
- for (size_t i = 0; i < inputCount; ++i)
- {
- const domInputLocalRef input = inputArray.get(i);
- const char* semantic = input->getSemantic();
- if (strcmp(semantic, "JOINT") == 0)
- {
- daeElement* sourceElement = input->getSource().getElement();
- if (sourceElement)
- {
- const domSourceRef source = daeSafeCast<domSource>(sourceElement);
- getJointNames(source, list);
- }
- }
- }
- }
- domSource* getInputSource(const domChannelRef& channel)
- {
- daeElement* element = channel->getSource().getElement();
- if (element && element->getElementType() == COLLADA_TYPE::SAMPLER)
- {
- domSampler* sampler = daeSafeCast<domSampler>(element);
- const domInputLocal_Array& inputArray = sampler->getInput_array();
- size_t inputArrayCount = inputArray.getCount();
- for (size_t i = 0; i < inputArrayCount; ++i)
- {
- const domInputLocalRef& input = inputArray.get(i);
- if (strcmp(input->getSemantic(), "INPUT") == 0)
- {
- daeElement* e = input->getSource().getElement();
- if (e && e->getElementType() == COLLADA_TYPE::SOURCE)
- {
- domSource* source = daeSafeCast<domSource>(e);
- assert(source);
- return source;
- }
- }
- }
- }
- return NULL;
- }
- const domSamplerRef getSampler(const domChannelRef& channel)
- {
- const domURIFragmentType& uri = channel->getSource();
- daeElementRef element = uri.getElement();
- if (element && element->getElementType() == COLLADA_TYPE::SAMPLER)
- {
- const domSamplerRef sampler = daeSafeCast<domSampler>(element);
- return sampler;
- }
- // resolve the source manually by searching for the sampler in the animation that the channel is a child of.
- const std::string& id = uri.id();
- const daeElementRef& parent = channel->getParent();
- if (parent && parent->getElementType() == COLLADA_TYPE::ANIMATION)
- {
- const domAnimationRef animation = daeSafeCast<domAnimation>(parent);
-
- const domSampler_Array& samplerArray = animation->getSampler_array();
- size_t count = samplerArray.getCount();
- for (size_t i = 0; i < count; ++i)
- {
- const domSamplerRef& sampler = samplerArray.get(i);
- if (id.compare(sampler->getId()) == 0)
- {
- return sampler;
- }
- }
- }
- return NULL;
- }
- const domSourceRef getSource(const domInputLocalRef& inputLocal, const domAnimationRef& animation)
- {
- const domURIFragmentType& uri = inputLocal->getSource();
- daeElementRef element = uri.getElement();
- if (element && element->getElementType() == COLLADA_TYPE::SAMPLER)
- {
- const domSourceRef source = daeSafeCast<domSource>(element);
- return source;
- }
- // Resolve the URI by searching through the animation's list of sources
- const std::string& id = uri.id();
- const domSource_Array& sourceArray = animation->getSource_array();
- size_t count = sourceArray.getCount();
- for (size_t i = 0; i < count; ++i)
- {
- const domSourceRef source = sourceArray.get(i);
- if (id.compare(source->getId()) == 0)
- {
- return source;
- }
- }
- return NULL;
- }
- const domName_arrayRef getSourceNameArray(const domSourceRef& source)
- {
- const domName_arrayRef& nameArray = source->getName_array();
- if (nameArray)
- {
- return nameArray;
- }
- daeTArray<daeSmartRef<daeElement> > children;
- source->getChildren(children);
- size_t childCount = children.getCount();
- for (size_t i = 0; i < childCount; ++i)
- {
- const daeElementRef element = children.get(i);
- if (element->getElementType() == COLLADA_TYPE::NAME_ARRAY)
- {
- return daeSafeCast<domName_array>(element);
- }
- }
- return NULL;
- }
- const domInstance_controller::domSkeletonRef getSkeleton(const domInstance_controllerRef& instanceController)
- {
- domInstance_controller::domSkeleton_Array& skeletonArray = instanceController->getSkeleton_array();
- size_t count = skeletonArray.getCount();
- if (count == 0)
- {
- return NULL;
- }
- if (count == 1)
- {
- return skeletonArray.get(0);
- }
- // Maya sometimes outputs multiple skeleton elements.
- // Find the skeleton element that points to the root most node.
- const domInstance_controller::domSkeletonRef& currentSkeleton = skeletonArray.get(0);
- const daeElementRef element = currentSkeleton->getValue().getElement();
- if (element && element->getElementType() == COLLADA_TYPE::NODE)
- {
- domNode* node = daeSafeCast<domNode>(element);
- int index = 0;
- bool loop = true;
- do
- {
- daeElementRef parent = node->getParent();
- if (parent && parent->getElementType() == COLLADA_TYPE::NODE)
- {
- domNodeRef parentNode = daeSafeCast<domNode>(parent);
- int result = getIndex(skeletonArray, parentNode);
- if (result >= 0)
- {
- index = result;
- }
- node = parentNode;
- }
- else
- {
- loop = false;
- }
- } while (loop);
- if (index >= 0)
- {
- return skeletonArray.get(index);
- }
- }
- return NULL;
- }
- domNode* getRootJointNode(const domSkin* skin)
- {
- std::vector<std::string> names;
- getJointNames(skin, names);
- daeSIDResolver resolver(const_cast<domSkin*>(skin)->getDocument()->getDomRoot(), names[0].c_str());
- daeElement* element = resolver.getElement();
- if (element && element->getElementType() == COLLADA_TYPE::NODE)
- {
- domNode* node = daeSafeCast<domNode>(resolver.getElement());
- return node;
- }
- return NULL;
- }
- bool equalKeyTimes(const domSource* s1, const domSource* s2)
- {
- // TODO: shouldn't assume that the source has a float array.
- const domFloat_arrayRef& f1 = s1->getFloat_array();
- const domFloat_arrayRef& f2 = s2->getFloat_array();
- if (f1->getCount() == f2->getCount())
- {
- const domListOfFloats& list1 = f1->getValue();
- const domListOfFloats& list2 = f2->getValue();
- size_t count = (size_t)f1->getCount();
- for (size_t i = 0; i < count; ++i)
- {
- if (list1.get(i) != list2.get(i))
- {
- return false;
- }
- }
- return true;
- }
- return false;
- }
- bool equalKeyTimes(const domChannelRef& c1, const domChannelRef& c2)
- {
- domSource* s1 = getInputSource(c1);
- domSource* s2 = getInputSource(c2);
- assert(s1);
- assert(s2);
- return equalKeyTimes(s1, s2);
- }
- void moveChannelAndSouresToAnimation(domChannelRef& channel, domAnimationRef& animation)
- {
- assert(channel);
- assert(animation);
- daeElement::removeFromParent(channel);
- animation->add(channel); // move channel
- daeElementRef element = channel->getSource().getElement();
- if (element)
- {
- domSamplerRef sampler = daeSafeCast<domSampler>(element);
- domInputLocal_Array& inputArray = sampler->getInput_array();
- size_t inputArrayCount = inputArray.getCount();
- for (size_t i = 0; i < inputArrayCount; ++i)
- {
- inputArray = sampler->getInput_array();
- const domInputLocalRef& input = inputArray.get(i);
- daeElementRef element = input->getSource().getElement();
- if (element && element->getElementType() == COLLADA_TYPE::SOURCE)
- {
- domSourceRef source = daeSafeCast<domSource>(element);
- assert(source);
- daeElement::removeFromParent(source);
- animation->add(source); // move source
- }
- }
- daeElement::removeFromParent(sampler);
- animation->add(sampler); // move sampler
- }
- }
- bool isEmptyAnimation(domAnimationRef& animation)
- {
- return animation->getAnimation_array().getCount() == 0 &&
- animation->getChannel_array().getCount() == 0 &&
- animation->getSampler_array().getCount() == 0 &&
- animation->getSource_array().getCount() == 0;
- }
- int getIndex(const domInstance_controller::domSkeleton_Array& skeletonArray, const domNodeRef& node)
- {
- const std::string nodeId = node->getId();
- size_t count = skeletonArray.getCount();
- for (size_t i = 0; i < count; ++i)
- {
- const domInstance_controller::domSkeletonRef& skeleton = skeletonArray.get(i);
- daeElementRef element = skeleton->getValue().getElement();
- if (element->getElementType() == COLLADA_TYPE::NODE)
- {
- domNodeRef targetNode = daeSafeCast<domNode>(element);
- if (nodeId.compare(targetNode->getId()) == 0)
- {
- return i;
- }
- }
- }
- return -1;
- }
- void getAnimationChannels(const domAnimationRef& animationRef, const std::string& nodeIdSlash, std::list<domChannelRef>& channels)
- {
- domChannel_Array& channelArray = animationRef->getChannel_array();
- size_t channelArrayCount = channelArray.getCount();
- for (size_t k = 0; k < channelArrayCount; ++k)
- {
- domChannelRef& channel = channelArray.get(k);
- const char* target = channel->getTarget();
- // TODO: Assumes only one target per channel?
- if (startsWith(target, nodeIdSlash.c_str()))
- {
- channels.push_back(channel);
- }
- }
- // This animation could have child animations.
- const domAnimation_Array& animationArray = animationRef->getAnimation_array();
- unsigned int animationCount = animationArray.getCount();
- for (size_t i = 0; i < animationCount; ++i)
- {
- getAnimationChannels(animationArray[i], nodeIdSlash, channels);
- }
- }
- domVisual_scene* getVisualScene(const domCOLLADA::domSceneRef& domScene)
- {
- daeElement* scene = domScene->getInstance_visual_scene()->getUrl().getElement();
- if (scene->getElementType() == COLLADA_TYPE::VISUAL_SCENE)
- {
- return static_cast<domVisual_scene*>(scene);
- }
- // DAE_FBX sometimes doesn't export an ID. In that case, see if there is only one visual scene and use that.
- // Most of the time there is only one visual scene.
- domCOLLADA* root = (domCOLLADA*)domScene->getDocument()->getDomRoot();
- domLibrary_visual_scenes_Array& visualSceneLibrary = root->getLibrary_visual_scenes_array();
- size_t visualSceneLibraryCount = visualSceneLibrary.getCount();
- for (size_t i = 0; i < visualSceneLibraryCount; ++i)
- {
- domLibrary_visual_scenesRef scenesRef = visualSceneLibrary.get(i);
- domVisual_scene_Array visualScenes = scenesRef->getVisual_scene_array();
- size_t visualSceneCount = visualScenes.getCount();
- for (size_t j = 0; j < visualSceneCount; ++j)
- {
- domVisual_sceneRef visualScene = visualScenes.get(j);
- return visualScene.cast();
- }
- }
- return NULL;
- }
- }
|