//-----------------------------------------------------------------------------
	void XsiSkeletonExporter::buildBoneHierarchy(Skeleton* pSkeleton, 
		DeformerMap& deformers, AnimationList& animList)
	{
		/// Copy all entries from map into a list so iterators won't get invalidated
		std::list<DeformerEntry*> deformerList;
		LogOgreAndXSI(L"-- Bones with vertex assignments:");
		for (DeformerMap::iterator i = deformers.begin(); i != deformers.end(); ++i)
		{
			DeformerEntry* deformer = i->second;
			deformerList.push_back(deformer);
			LogOgreAndXSI(deformer->obj.GetName());
		}

		/* XSI allows you to use any object at all as a bone, not just chain elements.
		   A typical choice is a hierarchy of nulls, for example. In order to 
		   build a skeleton hierarchy which represents the actual one, we need
		   to find the relationships between all the deformers that we found.
		   
		   Well do this by navigating up the scene tree from each bone, looking for
		   a match in the existing bone list or creating a new one where we need it
		   to reach the root. We add bones even if they're not assigned vertices
		   because the animation may depend on them. If the
		   traversal hits the scene root this bone is clearly a root bone 
		   (there may be more than one). 
	   */
		for (std::list<DeformerEntry*>::iterator i = deformerList.begin(); i != deformerList.end(); ++i)
		{
			DeformerEntry* deformer = *i;
			if (deformer->parentName.empty())
			{
				linkBoneWithParent(deformer, deformers, deformerList);
			}
		}

		// Now eliminate all bones without any animated kine parameters
		// Need to do this after we've determined all relationships
		for (std::list<DeformerEntry*>::iterator i = deformerList.begin(); i != deformerList.end(); ++i)
		{
			DeformerEntry* deformer = *i;
			validateAsBone(pSkeleton, deformer, deformers, deformerList, animList);
		}

		// Now link
		for (DeformerMap::iterator i = deformers.begin(); i != deformers.end(); ++i)
		{
			DeformerEntry* deformer = i->second;

			// link to parent
			if (!deformer->parentName.empty())
			{
				DeformerEntry* parent = getDeformer(deformer->parentName, deformers);
				assert (parent && "Parent not found");
				assert (deformer->pBone && "Child bone not created");
				assert(parent->pBone && "Parent bone not created");
				parent->pBone->addChild(deformer->pBone);

			}
		}

	}
예제 #2
0
	//-----------------------------------------------------------------------
	void copyFile(const String& src, const String& dst)
	{
		std::ifstream in(src.c_str(), std::ios::in | std::ios::binary);
		std::ofstream out(dst.c_str(), std::ios::out | std::ios::binary | std::ios::trunc);

		if (!in || !out)
		{
			LogOgreAndXSI("Unable to copy texture '" + src + "' to '" + dst + "'");
			return;
		}

		char tmpBuf[2048];

		while (!in.eof())
		{
			in.read(tmpBuf, 2048);

			std::streamsize c = in.gcount();

			out.write(tmpBuf, c);

		}

		in.close();
		out.close();



	}
	//-----------------------------------------------------------------------------
	void XsiSkeletonExporter::linkBoneWithParent(DeformerEntry* child, 
		DeformerMap& deformers, std::list<DeformerEntry*>& deformerList)
	{
		X3DObject parent(child->obj.GetParent());
		String childName = XSItoOgre(child->obj.GetName());

		if (child->obj == mXsiSceneRoot /* safety check for start node */)
			return;

		// Check for parenting by a chain end effector
		// These are sneaky little buggers - we actually want to attach the
		// child to the end of the final bone in the chain
		if (parent.IsA(XSI::siChainEffectorID))
		{
			ChainEffector effector(parent);
			CRefArray chainBones = effector.GetRoot().GetBones();
			// get the last
			parent = chainBones[chainBones.GetCount()-1];
			child->parentIsChainEndEffector = true;
			
		}
		// is the parent the scene root?
		if (parent == mXsiSceneRoot)
		{
			// we hit the root node
		}
		else
		{

			String parentName = XSItoOgre(parent.GetName());
			// Otherwise, check to see if the parent is in the deformer list
			DeformerEntry* parentDeformer = getDeformer(parentName, deformers);
			if (!parentDeformer)
			{
				// not found, create entry for parent 
				parentDeformer = new DeformerEntry(deformers.size(), parent);
				deformers[parentName] = parentDeformer;
				deformerList.push_back(parentDeformer);
				LogOgreAndXSI(CString(L"Added ") + parent.GetName() + 
					CString(L" as a parent of ") + child->obj.GetName() );
			}

			// Link child entry with parent (not bone yet)
			// link child to parent by name
			child->parentName = parentName;
			parentDeformer->childNames.push_back(childName);




		}

	}
	//-----------------------------------------------------------------------------
	const AxisAlignedBox& XsiSkeletonExporter::exportSkeleton(const String& skeletonFileName, 
		DeformerMap& deformers, float framesPerSecond, AnimationList& animList)
	{
		LogOgreAndXSI(L"** Begin OGRE Skeleton Export **");

		copyDeformerMap(deformers);

		SkeletonPtr skeleton = SkeletonManager::getSingleton().create("export",
			ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
		// construct the hierarchy
		buildBoneHierarchy(skeleton.get(), deformers, animList);

		// progress report
		ProgressManager::getSingleton().progress();

		establishInitialTransforms(deformers);

		// create animations 
		mAABB.setNull();
		createAnimations(skeleton.get(), deformers, framesPerSecond, animList, mAABB);
		// progress report
		ProgressManager::getSingleton().progress();

		// Optimise
		skeleton->optimiseAllAnimations();

		SkeletonSerializer ser;
		ser.exportSkeleton(skeleton.get(), skeletonFileName);
		// progress report
		ProgressManager::getSingleton().progress();

		LogOgreAndXSI(L"** OGRE Skeleton Export Complete **");

		cleanup();

		return mAABB;

	}
	//-----------------------------------------------------------------------------
	void XsiSkeletonExporter::createAnimations(Skeleton* pSkel, 
		DeformerMap& deformers, float fps, AnimationList& animList, AxisAlignedBox& AABBPadding)
	{
		for (AnimationList::iterator ai = animList.begin(); ai != animList.end(); ++ai)
		{
			AnimationEntry& animEntry = *ai;

			// Note that we don't know if this time period includes bone animation
			// but we sample it anyway just in case; animation optimisation will
			// eliminate anything that's redundant
			// A little wasteful perhaps, but it's the only guaranteed way to pick
			// up all the potentially derived effects on deformers

			float animLength = (float)(animEntry.endFrame - animEntry.startFrame) / fps;
			StringUtil::StrStreamType str;
			str << "Creating animation " << animEntry.animationName << 
				" with length " << animLength << " seconds";
			LogOgreAndXSI(str.str());
			Animation* anim = pSkel->createAnimation(animEntry.animationName, animLength);

			createAnimationTracksSampled(anim, animEntry, deformers, fps, AABBPadding);
			
		}
	}