Exemplo n.º 1
0
bool ColladaSceneNode::IsAnimated(FCDSceneNode * originalNode)
{
	for (int t = 0; t < (int)originalNode->GetTransformCount(); ++t)
	{
		FCDTransform * transform = originalNode->GetTransform(t);
		if (transform->IsAnimated()) // process all animations to make CalculateWorldTransform work
		{
			return true;
		}
		if (transform->GetType() == FCDTransform::TRANSLATION)
		{
			FCDTTranslation * translation = dynamic_cast<FCDTTranslation*>(transform);
			if (translation->IsAnimated()) 
			{
				return true;
			}
		}else if (transform->GetType() == FCDTransform::ROTATION)
		{
			FCDTRotation * rotation = dynamic_cast<FCDTRotation*>(transform);
			if (rotation->IsAnimated()) 
			{
				return true;
			}
		}
	}
	return false;
}
Exemplo n.º 2
0
void CModelConverter::ReadDAESceneTree(FCDSceneNode* pNode, CConversionSceneNode* pScene)
{
	size_t iTransforms = pNode->GetTransformCount();

	Matrix4x4 mTransformations;

	for (size_t t = 0; t < iTransforms; t++)
	{
		FCDTransform* pTransform = pNode->GetTransform(t);
		FMMatrix44 m = pTransform->ToMatrix();
		mTransformations *= Matrix4x4(m);
	}

	pScene->SetTransformations(mTransformations);

	size_t iInstances = pNode->GetInstanceCount();

	for (size_t i = 0; i < iInstances; i++)
	{
		FCDEntityInstance* pInstance = pNode->GetInstance(i);

		switch (pInstance->GetType())
		{
		case FCDEntityInstance::GEOMETRY:
		{
			FCDGeometryInstance* pGeometryInstance = dynamic_cast<FCDGeometryInstance*>(pInstance);
			FCDEntity* pEntity = pGeometryInstance->GetEntity();
			size_t iMesh = pScene->m_pScene->FindMesh(convert_from_fstring(pEntity->GetName()));
			size_t iMeshInstance = pScene->AddMeshInstance(iMesh);

			size_t iMaterialInstances = pGeometryInstance->GetMaterialInstanceCount();
			for (size_t m = 0; m < iMaterialInstances; m++)
			{
				FCDMaterialInstance* pMaterialInstance = pGeometryInstance->GetMaterialInstance(m);
				FCDMaterial* pMaterial = pMaterialInstance->GetMaterial();
				tstring sMaterial = pMaterial?convert_from_fstring(pMaterialInstance->GetMaterial()->GetName()):"";
				tstring sMaterialStub = convert_from_fstring(pMaterialInstance->GetSemantic());

				size_t iMaterial = pScene->m_pScene->FindMaterial(sMaterial);
				size_t iMaterialStub = pScene->m_pScene->GetMesh(iMesh)->FindMaterialStub(sMaterialStub);

				pScene->GetMeshInstance(iMeshInstance)->AddMappedMaterial(iMaterialStub, iMaterial);
			}
		}
		}
	}

	size_t iChildren = pNode->GetChildrenCount();
	for (size_t j = 0; j < iChildren; j++)
	{
		FCDSceneNode* pChildNode = pNode->GetChild(j);
		size_t iNode = pScene->AddChild(convert_from_fstring(pChildNode->GetName()));
		ReadDAESceneTree(pChildNode, pScene->GetChild(iNode));
	}
}
Exemplo n.º 3
0
	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());
		}
	}
Exemplo n.º 4
0
FMMatrix44 ColladaSceneNode::CalculateTransformForTime(FCDSceneNode * originalNode, float32 time)
{
	FMMatrix44 colladaLocalMatrix;
	colladaLocalMatrix = FMMatrix44::Identity;// = FMMatrix44::Identity(); 
	
	for (int t = 0; t < (int)originalNode->GetTransformCount(); ++t)
	{
		FCDTransform * transform = originalNode->GetTransform(t);
		if (transform->IsAnimated()) // process all animations to make CalculateWorldTransform work
		{
			FCDAnimated * animated = transform->GetAnimated();
			animated->Evaluate(time);
		}
		
		if (transform->GetType() == FCDTransform::TRANSLATION)
		{
			FCDTTranslation * translation = dynamic_cast<FCDTTranslation*>(transform);
			FMVector3 point = FMVector3(0.0f, 0.0f, 0.0f);
			point = translation->GetTranslation();
			if (transform->IsAnimated()) 
			{
				FCDAnimationCurve* curve;
				
				// look for x animation
				curve = transform->GetAnimated()->FindCurve(".X");
				if (curve != 0) 
					point.x = curve->Evaluate(time);
					
				// look for y animation
				curve = transform->GetAnimated()->FindCurve(".Y");
				if (curve != 0) 
					point.y = curve->Evaluate(time);
						
				// look for z animation
				curve = transform->GetAnimated()->FindCurve(".Z");
				if (curve != 0) 
					point.z = curve->Evaluate(time);
			}
			colladaLocalMatrix = colladaLocalMatrix * FMMatrix44::TranslationMatrix(point);
		}else if (transform->GetType() == FCDTransform::ROTATION)
		{
			FCDTRotation * rotation = dynamic_cast<FCDTRotation*>(transform);
			FMVector3 axis = FMVector3(0.0f, 0.0f, 0.0f);
			float angle = 0;
			axis = rotation->GetAxis();
			angle = rotation->GetAngle();
			
			if (rotation->IsAnimated()) 
			{
				FCDAnimationCurve* curve;
				
				// look for x animation
				curve = rotation->GetAnimated()->FindCurve(".X");
				if (curve != 0) 
					axis.x = curve->Evaluate(time);
					
				// look for y animation
				curve = rotation->GetAnimated()->FindCurve(".Y");
				if (curve != 0) 
					axis.y = curve->Evaluate(time);
						
				// look for z animation
				curve = rotation->GetAnimated()->FindCurve(".Z");
				if (curve != 0) 
					axis.z = curve->Evaluate(time);
							
							// look for z animation
				curve = rotation->GetAnimated()->FindCurve(".ANGLE");
				if (curve != 0) 
					angle = curve->Evaluate(time);
			}
			colladaLocalMatrix = colladaLocalMatrix * FMMatrix44::AxisRotationMatrix(axis, angle * PI / 180.0f);
		}else
		{
			colladaLocalMatrix = colladaLocalMatrix * transform->ToMatrix();
		}
		
	}
	return colladaLocalMatrix;
}
Exemplo n.º 5
0
bool FArchiveXML::LoadPhysicsShape(FCDObject* object, xmlNode* physicsShapeNode)
{ 
	FCDPhysicsShape* physicsShape = (FCDPhysicsShape*)object;

	bool status = true;
	if (!IsEquivalent(physicsShapeNode->name, DAE_SHAPE_ELEMENT))
	{
		FUError::Error(FUError::WARNING_LEVEL, FUError::WARNING_UNKNOW_PS_LIB_ELEMENT, physicsShapeNode->line);
		return status;
	}

	// Read in the first valid child element found
	for (xmlNode* child = physicsShapeNode->children; child != NULL; child = child->next)
	{
		if (child->type != XML_ELEMENT_NODE) continue;

		if (IsEquivalent(child->name, DAE_HOLLOW_ELEMENT))
		{
			physicsShape->SetHollow(FUStringConversion::ToBoolean(ReadNodeContentDirect(child)));
		}
		else if (IsEquivalent(child->name, DAE_MASS_ELEMENT))
		{
			physicsShape->SetMass(FUStringConversion::ToFloat(ReadNodeContentDirect(child)));
			physicsShape->SetDensityMoreAccurate(false);
		}
		else if (IsEquivalent(child->name, DAE_DENSITY_ELEMENT))
		{
			physicsShape->SetDensity(FUStringConversion::ToFloat(ReadNodeContentDirect(child)));
			physicsShape->SetDensityMoreAccurate(physicsShape->GetMassPointer() == NULL); // mass before density in COLLADA 1.4.1
		}
		else if (IsEquivalent(child->name, DAE_PHYSICS_MATERIAL_ELEMENT))
		{
			FCDPhysicsMaterial* material = physicsShape->AddOwnPhysicsMaterial();
			FArchiveXML::LoadPhysicsMaterial(material, child);
		}
		else if (IsEquivalent(child->name, 
				DAE_INSTANCE_PHYSICS_MATERIAL_ELEMENT))
		{
			physicsShape->SetInstanceMaterial(FCDEntityInstanceFactory::CreateInstance(physicsShape->GetDocument(), NULL, FCDEntity::PHYSICS_MATERIAL));
			FArchiveXML::LoadSwitch(physicsShape->GetInstanceMaterial(),
										&physicsShape->GetInstanceMaterial()->GetObjectType(),
										child);

			if (!HasNodeProperty(child, DAE_URL_ATTRIBUTE))
			{
				//inline definition of physics_material
				FCDPhysicsMaterial* material = physicsShape->AddOwnPhysicsMaterial();
				FArchiveXML::LoadPhysicsMaterial(material, child);
				physicsShape->GetInstanceMaterial()->SetEntity(material);
			}
		}
		else if (IsEquivalent(child->name, DAE_INSTANCE_GEOMETRY_ELEMENT))
		{
			FUUri url = ReadNodeUrl(child);
			if (!url.IsFile())
			{
				FCDGeometry* entity = physicsShape->GetDocument()->FindGeometry(TO_STRING(url.GetFragment()));
				if (entity != NULL)
				{
					physicsShape->SetAnalyticalGeometry(NULL);
					physicsShape->SetGeometryInstance((FCDGeometryInstance*)FCDEntityInstanceFactory::CreateInstance(physicsShape->GetDocument(), NULL, FCDEntity::GEOMETRY));
					physicsShape->GetGeometryInstance()->SetEntity((FCDEntity*)entity);
					status &= (FArchiveXML::LoadGeometryInstance(physicsShape->GetGeometryInstance(), child));
					continue; 
				}
			}
			FUError::Error(FUError::WARNING_LEVEL, FUError::WARNING_FCDGEOMETRY_INST_MISSING, child->line);
		}

#define PARSE_ANALYTICAL_SHAPE(type, nodeName) \
		else if (IsEquivalent(child->name, nodeName)) { \
		FCDPhysicsAnalyticalGeometry* analytical = physicsShape->CreateAnalyticalGeometry(FCDPhysicsAnalyticalGeometry::type); \
		status = FArchiveXML::LoadPhysicsAnalyticalGeometry(analytical, child); \
			if (!status) { \
				FUError::Error(FUError::WARNING_LEVEL, FUError::WARNING_INVALID_SHAPE_NODE, child->line); break; \
			} }

		PARSE_ANALYTICAL_SHAPE(BOX, DAE_BOX_ELEMENT)
		PARSE_ANALYTICAL_SHAPE(PLANE, DAE_PLANE_ELEMENT)
		PARSE_ANALYTICAL_SHAPE(SPHERE, DAE_SPHERE_ELEMENT)
		PARSE_ANALYTICAL_SHAPE(CYLINDER, DAE_CYLINDER_ELEMENT)
		PARSE_ANALYTICAL_SHAPE(CAPSULE, DAE_CAPSULE_ELEMENT)
		PARSE_ANALYTICAL_SHAPE(TAPERED_CAPSULE, DAE_TAPERED_CAPSULE_ELEMENT)
		PARSE_ANALYTICAL_SHAPE(TAPERED_CYLINDER, DAE_TAPERED_CYLINDER_ELEMENT)
#undef PARSE_ANALYTICAL_SHAPE


		// Parse the physics shape transforms <rotate>, <translate> are supported.
		else if (IsEquivalent(child->name, DAE_ASSET_ELEMENT)) {}
		else if (IsEquivalent(child->name, DAE_EXTRA_ELEMENT)) {}
		else
		{
			uint32 transformType = FArchiveXML::GetTransformType(child);
			if (transformType == FCDTransform::TRANSLATION || transformType == FCDTransform::ROTATION)
			{
				FCDTransform* transform = physicsShape->AddTransform((FCDTransform::Type) transformType);
				status &= (FArchiveXML::LoadSwitch(transform, &transform->GetObjectType(), child));
			}
		}
	}

	if ((physicsShape->GetMassPointer() == NULL) && (physicsShape->GetDensityPointer() == NULL))
	{
		physicsShape->SetDensity(1.0f);
		physicsShape->SetDensityMoreAccurate(true);
	}

	// default value if only one is defined.
	if ((physicsShape->GetMassPointer() == NULL) && (physicsShape->GetDensityPointer() != NULL))
	{
		physicsShape->SetMass(physicsShape->GetDensity() * physicsShape->CalculateVolume());
	}
	else if ((physicsShape->GetMassPointer() != NULL) && (physicsShape->GetDensityPointer() == NULL))
	{
		physicsShape->SetDensity(physicsShape->GetMass() / physicsShape->CalculateVolume());
	}

	physicsShape->SetDirtyFlag();
	return status;
}		
Exemplo n.º 6
0
bool FArchiveXML::LoadSceneNode(FCDObject* object, xmlNode* node)
{ 
	if (!FArchiveXML::LoadEntity(object, node)) return false;

	bool status = true;
	FCDSceneNode* sceneNode = (FCDSceneNode*)object;
	if (!IsEquivalent(node->name, DAE_VSCENE_ELEMENT) && !IsEquivalent(node->name, DAE_NODE_ELEMENT))
	{
		FUError::Error(FUError::ERROR_LEVEL, FUError::ERROR_UNKNOWN_ELEMENT, node->line);
	}

	// Read a subid if we gots one
	fm::string nodeSubId = ReadNodeProperty(node, DAE_SID_ATTRIBUTE);
	sceneNode->SetSubId(nodeSubId);

	// Read in the <node> element's type
	fm::string nodeType = ReadNodeProperty(node, DAE_TYPE_ATTRIBUTE);
	if (nodeType == DAE_JOINT_NODE_TYPE) sceneNode->SetJointFlag(true);
	else if (nodeType.length() == 0 || nodeType == DAE_NODE_NODE_TYPE) {} // No special consideration
	else
	{
		FUError::Error(FUError::WARNING_LEVEL, FUError::WARNING_UNKNOW_NODE_ELEMENT_TYPE, node->line);
	}

	// The scene node has ordered elements, so process them directly and in order.
	for (xmlNode* child = node->children; child != NULL; child = child->next)
	{
		if (child->type != XML_ELEMENT_NODE) continue;

		if (IsEquivalent(child->name, DAE_NODE_ELEMENT))
		{
			// Load the child scene node
			FCDSceneNode* node = sceneNode->AddChildNode();
			status = FArchiveXML::LoadSceneNode(node, child);
			if (!status) break;
		}
		// Although this case can be handled by FCDEntityInstanceFactory,
		// we can do some special case handling here.
		else if (IsEquivalent(child->name, DAE_INSTANCE_NODE_ELEMENT))
		{
			FUUri url = ReadNodeUrl(child);
			if (!url.IsFile())
			{
				// cannot find the node
				FCDSceneNode* node = sceneNode->GetDocument()->FindSceneNode(TO_STRING(url.GetFragment()));
				if (node != NULL)
				{
					
					if (!sceneNode->AddChildNode(node))
					{
						FUError::Error(FUError::WARNING_LEVEL, FUError::WARNING_CYCLE_DETECTED, child->line);
					}
				}
				else
				{
					FUError::Error(FUError::WARNING_LEVEL, FUError::WARNING_INVALID_NODE_INST, child->line);
				}
			}
			else
			{
				FCDEntityInstance* reference = sceneNode->AddInstance(FCDEntity::SCENE_NODE);
				FArchiveXML::LoadEntityInstance(reference, child);
			}
		}
		else if (IsEquivalent(child->name, DAE_EXTRA_ELEMENT)) {} // Handled by FCDEntity.
		else if (IsEquivalent(child->name, DAE_ASSET_ELEMENT)) {} // Handled by FCDEntity.
		else
		{
			uint32 transformType = FArchiveXML::GetTransformType(child);
			if (transformType != (uint32) ~0)
			{
				FCDTransform* transform = sceneNode->AddTransform((FCDTransform::Type) transformType);
				fm::string childSubId = ReadNodeProperty(child, DAE_SID_ATTRIBUTE);
				transform->SetSubId(childSubId);
				status &= (FArchiveXML::LoadSwitch(transform, &transform->GetObjectType(), child));
			}
			else
			{
				uint32 instanceType = FArchiveXML::GetEntityInstanceType(child);
				if (instanceType != (uint32) ~0)
				{
					FCDEntityInstance* instance = sceneNode->AddInstance((FCDEntity::Type) instanceType);
					status &= (FArchiveXML::LoadSwitch(instance, &instance->GetObjectType(), child));
				}
				else
				{
					FUError::Error(FUError::WARNING_LEVEL, FUError::WARNING_INVALID_TRANSFORM, child->line);
				}
			}
		}
	}

	status &= FArchiveXML::LoadFromExtraSceneNode(sceneNode);
	sceneNode->SetTransformsDirtyFlag();
	sceneNode->SetDirtyFlag();
	return status;
}