bool FArchiveXML::LoadPASCylinder(FCDObject* object, xmlNode* node)
{
	FCDPASCylinder* pASCylinder = (FCDPASCylinder*)object;

	bool status = true;

	if (!IsEquivalent(node->name, DAE_CYLINDER_ELEMENT))
	{
		FUError::Error(FUError::WARNING_LEVEL, FUError::WARNING_INVALID_SPHERE_TYPE, node->line);
		return status;
	}

	for (xmlNode* child = node->children; child != NULL; child = child->next)
	{
		if (child->type != XML_ELEMENT_NODE) continue;

		if (IsEquivalent(child->name, DAE_HEIGHT_ELEMENT))
		{
			pASCylinder->height = FUStringConversion::ToFloat(ReadNodeContentDirect(child));
		}
		else if (IsEquivalent(child->name, DAE_RADIUS_ELEMENT))
		{
			const char* stringRadius = ReadNodeContentDirect(child);
			pASCylinder->radius.x = FUStringConversion::ToFloat(&stringRadius);
			pASCylinder->radius.y = FUStringConversion::ToFloat(&stringRadius);
		}
	}

	pASCylinder->SetDirtyFlag();
	return status;
}
bool FArchiveXML::LoadPhysicsScene(FCDObject* object, xmlNode* sceneNode)
{
	if (!FArchiveXML::LoadEntity(object, sceneNode)) return false;

	bool status = true;
	FCDPhysicsScene* physicsScene = (FCDPhysicsScene*)object;
	if (IsEquivalent(sceneNode->name, DAE_PHYSICS_SCENE_ELEMENT))
	{
		for (xmlNode* child = sceneNode->children; child != NULL; child = child->next)
		{
			if (child->type != XML_ELEMENT_NODE) continue;

			// Look for instantiation elements
			if (IsEquivalent(child->name, DAE_INSTANCE_PHYSICS_MODEL_ELEMENT)) 
			{
				FCDPhysicsModelInstance* instance = physicsScene->AddPhysicsModelInstance(NULL);
				status &= (FArchiveXML::LoadPhysicsModelInstance(instance, child));
				continue; 
			}
			else if (IsEquivalent(child->name, DAE_TECHNIQUE_COMMON_ELEMENT))
			{
				xmlNode* gravityNode = FindChildByType(child, DAE_GRAVITY_ATTRIBUTE);
				if (gravityNode)
				{
					const char* gravityVal = ReadNodeContentDirect(gravityNode);
					FMVector3 gravity;
					gravity.x = FUStringConversion::ToFloat(&gravityVal);
					gravity.y = FUStringConversion::ToFloat(&gravityVal);
					gravity.z = FUStringConversion::ToFloat(&gravityVal);
					physicsScene->SetGravity(gravity);
				}
				xmlNode* timestepNode = FindChildByType(child, DAE_TIME_STEP_ATTRIBUTE);
				if (timestepNode)
				{
					physicsScene->SetTimestep(FUStringConversion::ToFloat(ReadNodeContentDirect(timestepNode)));
				}
			}
			else if (IsEquivalent(child->name, 
					DAE_INSTANCE_FORCE_FIELD_ELEMENT))
			{
				FCDPhysicsForceFieldInstance* instance = physicsScene->AddForceFieldInstance(NULL);
				status &= (FArchiveXML::LoadPhysicsForceFieldInstance(instance, child));
			}
			else if (IsEquivalent(child->name, DAE_EXTRA_ELEMENT))
			{
				// The extra information is loaded by the FCDEntity class.
			}
		}
	}

	physicsScene->SetDirtyFlag();
	return status;
}
bool FArchiveXML::LoadPASPlane(FCDObject* object, xmlNode* node)
{
	FCDPASPlane* pASPlane = (FCDPASPlane*)object;

	bool status = true;

	if (!IsEquivalent(node->name, DAE_PLANE_ELEMENT))
	{
		FUError::Error(FUError::WARNING_LEVEL, FUError::WARNING_INVALID_PLANE_TYPE, node->line);
		return status;
	}

	for (xmlNode* child = node->children; child != NULL; child = child->next)
	{
		if (child->type != XML_ELEMENT_NODE) continue;

		if (IsEquivalent(child->name, DAE_EQUATION_ELEMENT))
		{
			const char* eq = ReadNodeContentDirect(child);
			pASPlane->normal.x = FUStringConversion::ToFloat(&eq);
			pASPlane->normal.y = FUStringConversion::ToFloat(&eq);
			pASPlane->normal.z = FUStringConversion::ToFloat(&eq);
			pASPlane->d = FUStringConversion::ToFloat(&eq);
		}
	}

	pASPlane->SetDirtyFlag();
	return status;
}
bool FArchiveXML::LoadPASSphere(FCDObject* object, xmlNode* node)
{
	FCDPASSphere* pASSphere = (FCDPASSphere*)object;

	bool status = true;

	if (!IsEquivalent(node->name, DAE_SPHERE_ELEMENT))
	{
		FUError::Error(FUError::WARNING_LEVEL, FUError::WARNING_INVALID_SPHERE_TYPE, node->line);
		return status;
	}

	for (xmlNode* child = node->children; child != NULL; child = child->next)
	{
		if (child->type != XML_ELEMENT_NODE) continue;

		if (IsEquivalent(child->name, DAE_RADIUS_ELEMENT))
		{
			pASSphere->radius = FUStringConversion::ToFloat(ReadNodeContentDirect(child));
		}
	}

	pASSphere->SetDirtyFlag();
	return status;
}
bool FArchiveXML::LoadPASBox(FCDObject* object, xmlNode* node)
{
	FCDPASBox* pASBox = (FCDPASBox*)object;

	bool status = true;

	if (!IsEquivalent(node->name, DAE_BOX_ELEMENT))
	{
		FUError::Error(FUError::WARNING_LEVEL, FUError::WARNING_INVALID_BOX_TYPE, node->line);
		return status;
	}

	for (xmlNode* child = node->children; child != NULL; child = child->next)
	{
		if (child->type != XML_ELEMENT_NODE) continue;

		if (IsEquivalent(child->name, DAE_HALF_EXTENTS_ELEMENT))
		{
			const char* halfExt = ReadNodeContentDirect(child);
			pASBox->halfExtents.x = FUStringConversion::ToFloat(&halfExt);
			pASBox->halfExtents.y = FUStringConversion::ToFloat(&halfExt);
			pASBox->halfExtents.z = FUStringConversion::ToFloat(&halfExt);
		}
	}

	pASBox->SetDirtyFlag();
	return status;
}
bool FArchiveXML::LoadPhysicsMaterial(FCDObject* object, xmlNode* physicsMaterialNode)
{
	if (!FArchiveXML::LoadEntity(object, physicsMaterialNode)) return false;

	bool status = true;
	FCDPhysicsMaterial* physicsMaterial = (FCDPhysicsMaterial*)object;
	if (!IsEquivalent(physicsMaterialNode->name, DAE_PHYSICS_MATERIAL_ELEMENT))
	{
		FUError::Error(FUError::WARNING_LEVEL, FUError::WARNING_UNKNOWN_PHYS_MAT_LIB_ELEMENT, physicsMaterialNode->line);
		return status;
	}

	// Read in the <technique_common> element
	xmlNode* commonTechniqueNode = FindChildByType(physicsMaterialNode, DAE_TECHNIQUE_COMMON_ELEMENT);
	if (commonTechniqueNode == NULL)
	{
		FUError::Error(FUError::ERROR_LEVEL, FUError::ERROR_COMMON_TECHNIQUE_MISSING, physicsMaterialNode->line);
	}

	xmlNode* paramNode = FindChildByType(commonTechniqueNode, DAE_PHYSICS_STATIC_FRICTION);
	if (paramNode != NULL) 
	{
		const char* content = ReadNodeContentDirect(paramNode);
		physicsMaterial->SetStaticFriction(FUStringConversion::ToFloat(content));
	}

	paramNode = FindChildByType(commonTechniqueNode, DAE_PHYSICS_DYNAMIC_FRICTION);
	if (paramNode != NULL) 
	{
		const char* content = ReadNodeContentDirect(paramNode);
		physicsMaterial->SetDynamicFriction(FUStringConversion::ToFloat(content));
	}

	paramNode = FindChildByType(commonTechniqueNode, DAE_PHYSICS_RESTITUTION);
	if (paramNode != NULL)
	{
		const char* content = ReadNodeContentDirect(paramNode);
		physicsMaterial->SetRestitution(FUStringConversion::ToFloat(content));
	}

	physicsMaterial->SetDirtyFlag(); 
	return status;
}
Exemple #7
0
	// Retrieves a list of matrices from a source node
	void ReadSource(xmlNode* sourceNode, FMMatrix44List& array)
	{
		if (sourceNode != NULL)
		{
			// Get the accessor's count
			xmlNode* accessorNode = FindTechniqueAccessor(sourceNode);
			array.resize(ReadNodeCount(accessorNode));

			xmlNode* arrayNode = FindChildByType(sourceNode, DAE_FLOAT_ARRAY_ELEMENT);
			const char* arrayContent = ReadNodeContentDirect(arrayNode);
			FUStringConversion::ToMatrixList(arrayContent, array);
		}
	}
bool FArchiveXML::LoadPASTaperedCapsule(FCDObject* object, xmlNode* node)
{
	FCDPASTaperedCapsule* pASTaperedCapsule = (FCDPASTaperedCapsule*)object;

	bool status = true;

	if (!IsEquivalent(node->name, DAE_TAPERED_CAPSULE_ELEMENT))
	{
		FUError::Error(FUError::WARNING_LEVEL, FUError::WARNING_INVALID_TCAPSULE_TYPE, node->line);
		return status;
	}

	for (xmlNode* child = node->children; child != NULL; child = child->next)
	{
		if (child->type != XML_ELEMENT_NODE) continue;

		if (IsEquivalent(child->name, DAE_HEIGHT_ELEMENT))
		{
			const char* h = ReadNodeContentDirect(child);
			pASTaperedCapsule->height = FUStringConversion::ToFloat(&h);
		}
		else if (IsEquivalent(child->name, DAE_RADIUS1_ELEMENT))
		{
			const char* stringRadius = ReadNodeContentDirect(child);
			pASTaperedCapsule->radius.x = FUStringConversion::ToFloat(&stringRadius);
			pASTaperedCapsule->radius.y = FUStringConversion::ToFloat(&stringRadius);
		}
		else if (IsEquivalent(child->name, DAE_RADIUS2_ELEMENT))
		{
			const char* stringRadius = ReadNodeContentDirect(child);
			pASTaperedCapsule->radius2.x = FUStringConversion::ToFloat(&stringRadius);
			pASTaperedCapsule->radius2.y = FUStringConversion::ToFloat(&stringRadius);
		}
	}

	pASTaperedCapsule->SetDirtyFlag();
	return status;
}
Exemple #9
0
	// Retrieves a list of floats from a source node
	// Returns the data's stride.
	uint32 ReadSource(xmlNode* sourceNode, FloatList& array)
	{
		uint32 stride = 0;
		if (sourceNode != NULL)
		{
			// Get the accessor's count
			xmlNode* accessorNode = FindTechniqueAccessor(sourceNode);
			stride = ReadNodeStride(accessorNode);
			array.resize(ReadNodeCount(accessorNode) * stride);

			xmlNode* arrayNode = FindChildByType(sourceNode, DAE_FLOAT_ARRAY_ELEMENT);
			const char* arrayContent = ReadNodeContentDirect(arrayNode);
			FUStringConversion::ToFloatList(arrayContent, array);
		}
		return stride;
	}
Exemple #10
0
	// Retrieves a series of interpolation values from a source node
	void ReadSourceInterpolation(xmlNode* sourceNode, UInt32List& array)
	{
		if (sourceNode != NULL)
		{
			// Get the accessor's count
			xmlNode* accessorNode = FindTechniqueAccessor(sourceNode);
			uint32 count = ReadNodeCount(accessorNode);
			array.resize(count);

			// Backward compatibility: drop the unwanted interpolation values.
			// Before, we exported one interpolation token for each dimension of a merged curve.
			// Now, we export one interpolation token for each key of a merged curve.
			uint32 stride = ReadNodeStride(accessorNode);
			StringList stringArray(count * stride);
			xmlNode* arrayNode = FindChildByType(sourceNode, DAE_NAME_ARRAY_ELEMENT);
			const char* arrayContent = ReadNodeContentDirect(arrayNode);
			FUStringConversion::ToStringList(arrayContent, stringArray);
			for (uint32 i = 0; i < count; ++i)
			{
				array[i] = (uint32) FUDaeInterpolation::FromString(stringArray[i * stride]);
			}
		}
	}
Exemple #11
0
	// Retrieves a series of interleaved floats from a source node
	void ReadSourceInterleaved(xmlNode* sourceNode, fm::pvector<FloatList>& arrays)
	{
		if (sourceNode != NULL)
		{
			// Get the accessor's count
			xmlNode* accessorNode = FindTechniqueAccessor(sourceNode);
			uint32 count = ReadNodeCount(accessorNode);
			for (fm::pvector<FloatList>::iterator it = arrays.begin(); it != arrays.end(); ++it)
			{
				(*it)->resize(count);
			}

			// Use the stride to pad the interleaved float lists or remove extra elements
			uint32 stride = ReadNodeStride(accessorNode);
			while (stride < arrays.size()) arrays.pop_back();
			while (stride > arrays.size()) arrays.push_back(NULL);

			// Read and parse the float array
   			xmlNode* arrayNode = FindChildByType(sourceNode, DAE_FLOAT_ARRAY_ELEMENT);
			const char* arrayContent = ReadNodeContentDirect(arrayNode);
			FUStringConversion::ToInterleavedFloatList(arrayContent, arrays);
		}
	}
Exemple #12
0
bool FArchiveXML::LoadAnimationChannel(FCDObject* object, xmlNode* channelNode)
{ 
	FCDAnimationChannel* animationChannel = (FCDAnimationChannel*)object;
	FCDAnimationChannelData& data = FArchiveXML::documentLinkDataMap[animationChannel->GetDocument()].animationChannelData[animationChannel];

	bool status = true;

	// Read the channel-specific ID
	fm::string daeId = ReadNodeId(channelNode);
	fm::string samplerId = ReadNodeSource(channelNode);
	ReadNodeTargetProperty(channelNode, data.targetPointer, data.targetQualifier);

#ifdef DONT_DEFINE_THIS
	FCDAnimation* anim = animationChannel->GetParent();
	FCDExtra* extra = anim->GetExtra();
	extra->SetTransientFlag(); // Dont save this, its wasted whatever it is.
	FCDEType* type = extra->AddType("AnimTargets");
	FCDETechnique* teq = type->AddTechnique("TEMP");
	teq->AddChildNode("pointer")->SetContent(TO_FSTRING(data.targetPointer));
	teq->AddChildNode("pointer")->SetContent(TO_FSTRING(data.targetQualifier));
#endif
	


	xmlNode* samplerNode = FArchiveXML::FindChildByIdFCDAnimation(animationChannel->GetParent(), samplerId);
	if (samplerNode == NULL || !IsEquivalent(samplerNode->name, DAE_SAMPLER_ELEMENT))
	{
		FUError::Error(FUError::ERROR_LEVEL, FUError::ERROR_MISSING_ELEMENT, channelNode->line);
		return false;
	}

	// Find and process the sources
	xmlNode* inputSource = NULL, * outputSource = NULL, * inTangentSource = NULL, * outTangentSource = NULL, * tcbSource = NULL, * easeSource = NULL, * interpolationSource = NULL;
	xmlNodeList samplerInputNodes;
	fm::string inputDriver;
	FindChildrenByType(samplerNode, DAE_INPUT_ELEMENT, samplerInputNodes);
	for (size_t i = 0; i < samplerInputNodes.size(); ++i) // Don't use iterator here because we are possibly appending source nodes in the loop
	{
		xmlNode* inputNode = samplerInputNodes[i];
		fm::string sourceId = ReadNodeSource(inputNode);
		xmlNode* sourceNode = FArchiveXML::FindChildByIdFCDAnimation(animationChannel->GetParent(), sourceId);
		fm::string sourceSemantic = ReadNodeSemantic(inputNode);

		if (sourceSemantic == DAE_INPUT_ANIMATION_INPUT) inputSource = sourceNode;
		else if (sourceSemantic == DAE_OUTPUT_ANIMATION_INPUT) outputSource = sourceNode;
		else if (sourceSemantic == DAE_INTANGENT_ANIMATION_INPUT) inTangentSource = sourceNode;
		else if (sourceSemantic == DAE_OUTTANGENT_ANIMATION_INPUT) outTangentSource = sourceNode;
		else if (sourceSemantic == DAEFC_TCB_ANIMATION_INPUT) tcbSource = sourceNode;
		else if (sourceSemantic == DAEFC_EASE_INOUT_ANIMATION_INPUT) easeSource = sourceNode;
		else if (sourceSemantic == DAE_INTERPOLATION_ANIMATION_INPUT) interpolationSource = sourceNode;
		else if (sourceSemantic == DAEMAYA_DRIVER_INPUT) inputDriver = sourceId;
	}
	if (inputSource == NULL || outputSource == NULL)
	{
		FUError::Error(FUError::ERROR_LEVEL, FUError::ERROR_MISSING_INPUT, samplerNode->line);
		return false;
	}

	// Calculate the number of curves that in contained by this channel
	xmlNode* outputAccessor = FindTechniqueAccessor(outputSource);
	fm::string accessorStrideString = ReadNodeProperty(outputAccessor, DAE_STRIDE_ATTRIBUTE);
	uint32 curveCount = FUStringConversion::ToUInt32(accessorStrideString);
	if (curveCount == 0) curveCount = 1;

	// Create the animation curves
	for (uint32 i = 0; i < curveCount; ++i)
	{
		animationChannel->AddCurve();
	}

	// Read in the animation curves
	// The input keys and interpolations are shared by all the curves
	FloatList inputs;
    ReadSource(inputSource, inputs);
	size_t keyCount = inputs.size();
	if (keyCount == 0) return true; // Valid although very boring channel.

	UInt32List interpolations; interpolations.reserve(keyCount);
	ReadSourceInterpolation(interpolationSource, interpolations);
	if (interpolations.size() < keyCount)
	{
		// Not enough interpolation types provided, so append BEZIER as many times as needed.
		interpolations.insert(interpolations.end(), keyCount - interpolations.size(), FUDaeInterpolation::FromString(""));
	}

	// Read in the interleaved outputs as floats
	fm::vector<FloatList> tempFloatArrays;
	tempFloatArrays.resize(curveCount);
	fm::pvector<FloatList> outArrays(curveCount);
	for (uint32 i = 0; i < curveCount; ++i) outArrays[i] = &tempFloatArrays[i];
	ReadSourceInterleaved(outputSource, outArrays);
	for (uint32 i = 0; i < curveCount; ++i)
	{
		// Fill in the output array with zeroes, if it was not large enough.
		if (tempFloatArrays[i].size() < keyCount)
		{
			tempFloatArrays[i].insert(tempFloatArrays[i].end(), keyCount - tempFloatArrays[i].size(), 0.0f);
		}

		// Create all the keys, on the curves, according to the interpolation types.
		for (size_t j = 0; j < keyCount; ++j)
		{
			FCDAnimationKey* key = animationChannel->GetCurve(i)->AddKey((FUDaeInterpolation::Interpolation) interpolations[j]);
			key->input = inputs[j];
			key->output = tempFloatArrays[i][j];

			// Set the default values for Bezier/TCB interpolations.
			if (key->interpolation == FUDaeInterpolation::BEZIER)
			{
				FCDAnimationKeyBezier* bkey = (FCDAnimationKeyBezier*) key;
				float previousInput = (j == 0) ? inputs[j] - 1.0f : inputs[j-1];
				float nextInput = (j == keyCount - 1) ? inputs[j] + 1.0f : inputs[j+1];
				bkey->inTangent.x = (previousInput + 2.0f * bkey->input) / 3.0f;
				bkey->outTangent.x = (nextInput + 2.0f * bkey->input) / 3.0f;
				bkey->inTangent.y = bkey->outTangent.y = bkey->output;
			}
			else if (key->interpolation == FUDaeInterpolation::TCB)
			{
				FCDAnimationKeyTCB* tkey = (FCDAnimationKeyTCB*) key;
				tkey->tension = tkey->continuity = tkey->bias = 0.5f;
				tkey->easeIn = tkey->easeOut = 0.0f;
			}
		}
	}
	tempFloatArrays.clear();

	// Read in the interleaved in_tangent source.
	if (inTangentSource != NULL)
	{
		fm::vector<FMVector2List> tempVector2Arrays;
		tempVector2Arrays.resize(curveCount);
		fm::pvector<FMVector2List> arrays(curveCount);
		for (uint32 i = 0; i < curveCount; ++i) arrays[i] = &tempVector2Arrays[i];

		uint32 stride = ReadSourceInterleaved(inTangentSource, arrays);
		if (stride == curveCount)
		{
			// Backward compatibility with 1D tangents.
			// Remove the relativity from the 1D tangents and calculate the second-dimension.
			for (uint32 i = 0; i < curveCount; ++i)
			{
				FMVector2List& inTangents = tempVector2Arrays[i];
				FCDAnimationKey** keys = animationChannel->GetCurve(i)->GetKeys();
				size_t end = min(inTangents.size(), keyCount);
				for (size_t j = 0; j < end; ++j)
				{
					if (keys[j]->interpolation == FUDaeInterpolation::BEZIER)
					{
						FCDAnimationKeyBezier* bkey = (FCDAnimationKeyBezier*) keys[j];
						bkey->inTangent.y = bkey->output - inTangents[j].x;
					}
				}
			}
		}
		else if (stride == curveCount * 2)
		{
			// This is the typical, 2D tangent case.
			for (uint32 i = 0; i < curveCount; ++i)
			{
				FMVector2List& inTangents = tempVector2Arrays[i];
				FCDAnimationKey** keys = animationChannel->GetCurve(i)->GetKeys();
				size_t end = min(inTangents.size(), keyCount);
				for (size_t j = 0; j < end; ++j)
				{
					if (keys[j]->interpolation == FUDaeInterpolation::BEZIER)
					{
						FCDAnimationKeyBezier* bkey = (FCDAnimationKeyBezier*) keys[j];
						bkey->inTangent = inTangents[j];
					}
				}
			}
		}
	}

	// Read in the interleaved out_tangent source.
	if (outTangentSource != NULL)
	{
		fm::vector<FMVector2List> tempVector2Arrays;
		tempVector2Arrays.resize(curveCount);
		fm::pvector<FMVector2List> arrays(curveCount);
		for (uint32 i = 0; i < curveCount; ++i) arrays[i] = &tempVector2Arrays[i];

		uint32 stride = ReadSourceInterleaved(outTangentSource, arrays);
		if (stride == curveCount)
		{
			// Backward compatibility with 1D tangents.
			// Remove the relativity from the 1D tangents and calculate the second-dimension.
			for (uint32 i = 0; i < curveCount; ++i)
			{
				FMVector2List& outTangents = tempVector2Arrays[i];
				FCDAnimationKey** keys = animationChannel->GetCurve(i)->GetKeys();
				size_t end = min(outTangents.size(), keyCount);
				for (size_t j = 0; j < end; ++j)
				{
					if (keys[j]->interpolation == FUDaeInterpolation::BEZIER)
					{
						FCDAnimationKeyBezier* bkey = (FCDAnimationKeyBezier*) keys[j];
						bkey->outTangent.y = bkey->output + outTangents[j].x;
					}
				}
			}
		}
		else if (stride == curveCount * 2)
		{
			// This is the typical, 2D tangent case.
			for (uint32 i = 0; i < curveCount; ++i)
			{
				FMVector2List& outTangents = tempVector2Arrays[i];
				FCDAnimationKey** keys = animationChannel->GetCurve(i)->GetKeys();
				size_t end = min(outTangents.size(), keyCount);
				for (size_t j = 0; j < end; ++j)
				{
					if (keys[j]->interpolation == FUDaeInterpolation::BEZIER)
					{
						FCDAnimationKeyBezier* bkey = (FCDAnimationKeyBezier*) keys[j];
						bkey->outTangent = outTangents[j];
					}
				}
			}
		}
	}

	if (tcbSource != NULL)
	{
		//Process TCB parameters
		fm::vector<FMVector3List> tempVector3Arrays;
		tempVector3Arrays.resize(curveCount);
		fm::pvector<FMVector3List> arrays(curveCount);
		for (uint32 i = 0; i < curveCount; ++i) arrays[i] = &tempVector3Arrays[i];

		ReadSourceInterleaved(tcbSource, arrays);

		for (uint32 i = 0; i < curveCount; ++i)
		{
			FMVector3List& tcbs = tempVector3Arrays[i];
			FCDAnimationKey** keys = animationChannel->GetCurve(i)->GetKeys();
			size_t end = min(tcbs.size(), keyCount);
			for (size_t j = 0; j < end; ++j)
			{
				if (keys[j]->interpolation == FUDaeInterpolation::TCB)
				{
					FCDAnimationKeyTCB* tkey = (FCDAnimationKeyTCB*) keys[j];
					tkey->tension = tcbs[j].x;
					tkey->continuity = tcbs[j].y;
					tkey->bias = tcbs[j].z;
				}
			}
		}
	}

	if (easeSource != NULL)
	{
		//Process Ease-in and ease-out data
		fm::vector<FMVector2List> tempVector2Arrays;
		tempVector2Arrays.resize(curveCount);
		fm::pvector<FMVector2List> arrays(curveCount);
		for (uint32 i = 0; i < curveCount; ++i) arrays[i] = &tempVector2Arrays[i];

		ReadSourceInterleaved(easeSource, arrays);

		for (uint32 i = 0; i < curveCount; ++i)
		{
			FMVector2List& eases = tempVector2Arrays[i];
			FCDAnimationKey** keys = animationChannel->GetCurve(i)->GetKeys();
			size_t end = min(eases.size(), keyCount);
			for (size_t j = 0; j < end; ++j)
			{
				if (keys[j]->interpolation == FUDaeInterpolation::TCB)
				{
					FCDAnimationKeyTCB* tkey = (FCDAnimationKeyTCB*) keys[j];
					tkey->easeIn = eases[j].x;
					tkey->easeOut = eases[j].y;
				}
			}
		}
	}

	// Read in the pre/post-infinity type
	xmlNodeList mayaParameterNodes; StringList mayaParameterNames;
	xmlNode* mayaTechnique = FindTechnique(inputSource, DAEMAYA_MAYA_PROFILE);
	FindParameters(mayaTechnique, mayaParameterNames, mayaParameterNodes);
	size_t parameterCount = mayaParameterNodes.size();
	for (size_t i = 0; i < parameterCount; ++i)
	{
		xmlNode* parameterNode = mayaParameterNodes[i];
		const fm::string& paramName = mayaParameterNames[i];
		const char* content = ReadNodeContentDirect(parameterNode);

		if (paramName == DAEMAYA_PREINFINITY_PARAMETER)
		{
			size_t curveCount = animationChannel->GetCurveCount();
			for (size_t c = 0; c < curveCount; ++c)
			{
				animationChannel->GetCurve(c)->SetPreInfinity(FUDaeInfinity::FromString(content));
			}
		}
		else if (paramName == DAEMAYA_POSTINFINITY_PARAMETER)
		{
			size_t curveCount = animationChannel->GetCurveCount();
			for (size_t c = 0; c < curveCount; ++c)
			{
				animationChannel->GetCurve(c)->SetPostInfinity(FUDaeInfinity::FromString(content));
			}
		}
		else
		{
			// Look for driven-key input target
			if (paramName == DAE_INPUT_ELEMENT)
			{
				fm::string semantic = ReadNodeSemantic(parameterNode);
				if (semantic == DAEMAYA_DRIVER_INPUT)
				{
					inputDriver = ReadNodeSource(parameterNode);
				}
			}
		}
	}

	if (!inputDriver.empty())
	{
		const char* driverTarget = FUDaeParser::SkipPound(inputDriver);
		if (driverTarget != NULL)
		{
			fm::string driverQualifierValue;
			FUStringConversion::SplitTarget(driverTarget, data.driverPointer, driverQualifierValue);
			data.driverQualifier = FUStringConversion::ParseQualifier(driverQualifierValue);
			if (data.driverQualifier < 0) data.driverQualifier = 0;
		}
	}
	animationChannel->SetDirtyFlag();

	return status;
}
bool FArchiveXML::LoadPhysicsRigidConstraint(FCDObject* object, xmlNode* physicsRigidConstraintNode)
{
	if (!FArchiveXML::LoadEntity(object, physicsRigidConstraintNode)) return false;

	bool status = true;
	FCDPhysicsRigidConstraint* physicsRigidConstraint = (FCDPhysicsRigidConstraint*)object;
	if (!IsEquivalent(physicsRigidConstraintNode->name, DAE_RIGID_CONSTRAINT_ELEMENT))
	{
		FUError::Error(FUError::WARNING_LEVEL, FUError::WARNING_UNKNOWN_RGC_LIB_ELEMENT, physicsRigidConstraintNode->line);
		return status;
	}

	physicsRigidConstraint->SetSubId(FUDaeParser::ReadNodeSid(physicsRigidConstraintNode));

#define PARSE_TRANSFORM(node, className, nodeName, transforms) { \
	xmlNodeList transformNodes; \
	FindChildrenByType(node, nodeName, transformNodes); \
	for (xmlNodeList::iterator itT = transformNodes.begin(); itT != transformNodes.end(); ++itT) \
	{ \
		if (IsEquivalent((*itT)->name, nodeName)) { \
			className* transform = new className(physicsRigidConstraint->GetDocument(), NULL); \
			transforms.push_back(transform); \
			status = FArchiveXML::LoadSwitch(transform, &transform->GetObjectType(), *itT); \
			if (!status) { \
				FUError::Error(FUError::WARNING_LEVEL, FUError::WARNING_INVALID_NODE_TRANSFORM, (*itT)->line);} \
		} \
	}  }



	//Reference-frame body
	xmlNode* referenceBodyNode = FindChildByType(physicsRigidConstraintNode, DAE_REF_ATTACHMENT_ELEMENT);
	if (referenceBodyNode == NULL)
	{
		FUError::Error(FUError::WARNING_LEVEL, FUError::WARNING_RF_NODE_MISSING, physicsRigidConstraintNode->line);
	}
	fm::string strRigidBody = ReadNodeProperty(referenceBodyNode, DAE_RIGID_BODY_ELEMENT);
	physicsRigidConstraint->SetReferenceRigidBody(physicsRigidConstraint->GetParent()->FindRigidBodyFromSid(strRigidBody));
	if (physicsRigidConstraint->GetReferenceRigidBody() == NULL)
	{
		physicsRigidConstraint->SetReferenceNode(physicsRigidConstraint->GetDocument()->FindSceneNode(strRigidBody));
		if ((physicsRigidConstraint->GetReferenceNode() == NULL) && (referenceBodyNode != NULL))
		{
			FUError::Error(FUError::WARNING_LEVEL, FUError::WARNING_RF_REF_NODE_MISSING, referenceBodyNode->line);
		}
	}
	// Parse the node's transforms: <rotate>, <translate>
	PARSE_TRANSFORM(referenceBodyNode, FCDTRotation, DAE_ROTATE_ELEMENT, physicsRigidConstraint->GetTransformsRef())
	PARSE_TRANSFORM(referenceBodyNode, FCDTTranslation, DAE_TRANSLATE_ELEMENT, physicsRigidConstraint->GetTransformsRef())

	// target body
	xmlNode* bodyNode = FindChildByType(physicsRigidConstraintNode, DAE_ATTACHMENT_ELEMENT);
	if (bodyNode == NULL)
	{
		FUError::Error(FUError::WARNING_LEVEL, FUError::WARNING_TARGET_BS_NODE_MISSING, physicsRigidConstraintNode->line);
	}
	strRigidBody = ReadNodeProperty(bodyNode, DAE_RIGID_BODY_ELEMENT);
	physicsRigidConstraint->SetTargetRigidBody(physicsRigidConstraint->GetParent()->FindRigidBodyFromSid(strRigidBody));
	if (physicsRigidConstraint->GetTargetRigidBody() == NULL)
	{
		physicsRigidConstraint->SetTargetNode(physicsRigidConstraint->GetDocument()->FindSceneNode(strRigidBody));
		if ((physicsRigidConstraint->GetTargetNode() == NULL) && (bodyNode != NULL))
		{
			FUError::Error(FUError::WARNING_LEVEL, FUError::WARNING_TARGE_BS_REF_NODE_MISSING, bodyNode->line);
		}
	}
	// Parse the node's transforms: <rotate>, <scale>, <translate>
	PARSE_TRANSFORM(bodyNode, FCDTRotation, DAE_ROTATE_ELEMENT, physicsRigidConstraint->GetTransformsTar())
	PARSE_TRANSFORM(bodyNode, FCDTTranslation, DAE_TRANSLATE_ELEMENT, physicsRigidConstraint->GetTransformsTar())

#undef PARSE_TRANSFORM

	//technique_common
	xmlNode* techniqueNode = FindChildByType(physicsRigidConstraintNode, DAE_TECHNIQUE_COMMON_ELEMENT);
	if (techniqueNode == NULL)
	{
		//return status.Fail(FS("Technique node not specified in rigid_constraint ") + TO_FSTRING(GetDaeId()), physicsRigidConstraintNode->line);
		FUError::Error(FUError::ERROR_LEVEL, FUError::ERROR_TECHNIQUE_NODE_MISSING, physicsRigidConstraintNode->line);
		return status;
	}

	xmlNode* enabledNode = FindChildByType(techniqueNode, DAE_ENABLED_ELEMENT);
	if (enabledNode != NULL)
	{
		physicsRigidConstraint->SetEnabled(FUStringConversion::ToBoolean(ReadNodeContentDirect(enabledNode)));
		FArchiveXML::LoadAnimatable(&physicsRigidConstraint->GetEnabled(), enabledNode);
	}
	xmlNode* interpenetrateNode = FindChildByType(techniqueNode, DAE_INTERPENETRATE_ELEMENT);
	if (interpenetrateNode != NULL)
	{
		physicsRigidConstraint->SetInterpenetrate(FUStringConversion::ToBoolean(ReadNodeContentDirect(interpenetrateNode)));
		FArchiveXML::LoadAnimatable(&physicsRigidConstraint->GetInterpenetrate(), interpenetrateNode);
	}

	xmlNode* limitsNode = FindChildByType(techniqueNode, DAE_LIMITS_ELEMENT);
	if (limitsNode != NULL)
	{
		xmlNode* linearNode = FindChildByType(limitsNode, DAE_LINEAR_ELEMENT);
		if (linearNode != NULL)
		{
			xmlNode* linearMinNode = FindChildByType(linearNode, DAE_MIN_ELEMENT);
			if (linearMinNode != NULL)
			{
				const char* min = ReadNodeContentDirect(linearMinNode);
				physicsRigidConstraint->SetLimitsLinearMin(FUStringConversion::ToVector3(min));
			}
			xmlNode* linearMaxNode = FindChildByType(linearNode, DAE_MAX_ELEMENT);
			if (linearMaxNode != NULL)
			{
				const char* max = ReadNodeContentDirect(linearMaxNode);
				physicsRigidConstraint->SetLimitsLinearMax(FUStringConversion::ToVector3(max));
			}
		}

		xmlNode* sctNode = FindChildByType(limitsNode, DAE_SWING_CONE_AND_TWIST_ELEMENT);
		if (sctNode != NULL)
		{
			xmlNode* sctMinNode = FindChildByType(sctNode, DAE_MIN_ELEMENT);
			if (sctMinNode != NULL)
			{
				const char* min = ReadNodeContentDirect(sctMinNode);
				physicsRigidConstraint->SetLimitsSCTMin(FUStringConversion::ToVector3(min));
			}
			xmlNode* sctMaxNode = FindChildByType(sctNode, DAE_MAX_ELEMENT);
			if (sctMaxNode != NULL)
			{
				const char* max = ReadNodeContentDirect(sctMaxNode);
				physicsRigidConstraint->SetLimitsSCTMax(FUStringConversion::ToVector3(max));
			}
		}
	}

	xmlNode* spring = FindChildByType(physicsRigidConstraintNode, DAE_SPRING_ELEMENT);
	if (spring)
	{
		xmlNode* linearSpring = FindChildByType(spring, DAE_LINEAR_ELEMENT);
		if (linearSpring)
		{
			xmlNode* param = FindChildByType(linearSpring, DAE_DAMPING_ELEMENT);
			if (param) physicsRigidConstraint->SetSpringLinearDamping(FUStringConversion::ToFloat(ReadNodeContentDirect(param)));
			param = FindChildByType(linearSpring, DAE_STIFFNESS_ELEMENT);
			if (param) physicsRigidConstraint->SetSpringLinearStiffness(FUStringConversion::ToFloat(ReadNodeContentDirect(param)));
			param = FindChildByType(linearSpring, DAE_TARGET_VALUE_ELEMENT);
			if (!param) param = FindChildByType(linearSpring, DAE_REST_LENGTH_ELEMENT1_3); // COLLADA 1.3 backward compatibility
			if (param) physicsRigidConstraint->SetSpringLinearTargetValue(FUStringConversion::ToFloat(ReadNodeContentDirect(param)));
		}

		xmlNode* angularSpring = FindChildByType(spring, DAE_ANGULAR_ELEMENT);
		if (angularSpring)
		{
			xmlNode* param = FindChildByType(angularSpring, DAE_DAMPING_ELEMENT);
			if (param) physicsRigidConstraint->SetSpringAngularDamping(FUStringConversion::ToFloat(ReadNodeContentDirect(param)));
			param = FindChildByType(angularSpring, DAE_STIFFNESS_ELEMENT);
			if (param) physicsRigidConstraint->SetSpringAngularStiffness(FUStringConversion::ToFloat(ReadNodeContentDirect(param)));
			param = FindChildByType(angularSpring, DAE_TARGET_VALUE_ELEMENT);
			if (!param) param = FindChildByType(angularSpring, DAE_REST_LENGTH_ELEMENT1_3); // COLLADA 1.3 backward compatibility
			if (param) physicsRigidConstraint->SetSpringAngularTargetValue(FUStringConversion::ToFloat(ReadNodeContentDirect(param)));
		}
	}

	physicsRigidConstraint->SetDirtyFlag();
	return status;
}
Exemple #14
0
	uint32 ReadSourceInterleaved(xmlNode* sourceNode, fm::pvector<FMVector3List>& arrays)
	{
		uint32 stride = 1;
		if (sourceNode != NULL)
		{
			// Get the accessor's count
			xmlNode* accessorNode = FindTechniqueAccessor(sourceNode);
			uint32 count = ReadNodeCount(accessorNode);
			for (fm::pvector<FMVector3List>::iterator it = arrays.begin(); it != arrays.end(); ++it)
			{
				(*it)->resize(count);
			}

			// Backward Compatibility: if the stride is exactly half the expected value,
			// then we have the old 1D tangents that we need to parse correctly.
			stride = ReadNodeStride(accessorNode);
			if (stride > 0 && stride == arrays.size())
			{
				// Read and parse the float array
				xmlNode* arrayNode = FindChildByType(sourceNode, DAE_FLOAT_ARRAY_ELEMENT);
				const char* value = ReadNodeContentDirect(arrayNode);
				for (size_t i = 0; i < count && *value != 0; ++i)
				{
					for (size_t j = 0; j < stride && *value != 0; ++j)
					{
						arrays[j]->at(i) = FMVector3(FUStringConversion::ToFloat(&value), 0.0f, 0.0f);
					}
				}

				while (*value != 0)
				{
					for (size_t i = 0; i < stride && *value != 0; ++i)
					{
						arrays[i]->push_back(FMVector3(FUStringConversion::ToFloat(&value), 0.0f, 0.0f));
					}
				}
			}
			else
			{
				// Use the stride to pad the interleaved float lists or remove extra elements
				while (stride < arrays.size() * 3) arrays.pop_back();
				while (stride > arrays.size() * 3) arrays.push_back(NULL);

				// Read and parse the float array
				xmlNode* arrayNode = FindChildByType(sourceNode, DAE_FLOAT_ARRAY_ELEMENT);
				const char* value = ReadNodeContentDirect(arrayNode);
				for (size_t i = 0; i < count && *value != 0; ++i)
				{
					for (size_t j = 0; 3 * j < stride && *value != 0; ++j)
					{
						if (arrays[j] != NULL)
						{
							arrays[j]->at(i).x = FUStringConversion::ToFloat(&value);
							arrays[j]->at(i).y = FUStringConversion::ToFloat(&value);
							arrays[j]->at(i).z = FUStringConversion::ToFloat(&value);
						}
						else
						{
							FUStringConversion::ToFloat(&value);
							FUStringConversion::ToFloat(&value);
							FUStringConversion::ToFloat(&value);
						}
					}
				}

				while (*value != 0)
				{
					for (size_t i = 0; 2 * i < stride && *value != 0; ++i)
					{
						if (arrays[i] != NULL)
						{
							FMVector3 v;
							v.x = FUStringConversion::ToFloat(&value);
							v.y = FUStringConversion::ToFloat(&value);
							v.z = FUStringConversion::ToFloat(&value);
							arrays[i]->push_back(v);
						}
						else
						{
							FUStringConversion::ToFloat(&value);
							FUStringConversion::ToFloat(&value);
							FUStringConversion::ToFloat(&value);
						}
					}
				}
			}
		}
		return stride;
	}
bool FArchiveXML::LoadPhysicsRigidBodyInstance(FCDObject* object, xmlNode* instanceNode)
{
	if (!FArchiveXML::LoadEntityInstance(object, instanceNode)) return false;

	bool status = true;
	FCDPhysicsRigidBodyInstance* physicsRigidBodyInstance = (FCDPhysicsRigidBodyInstance*)object;

	// Check for the expected instantiation node type
	if (!IsEquivalent(instanceNode->name, DAE_INSTANCE_RIGID_BODY_ELEMENT) || physicsRigidBodyInstance->GetModelParentInstance() == NULL)
	{
		FUError::Error(FUError::ERROR_LEVEL, FUError::ERROR_UNKNOWN_ELEMENT, instanceNode->line);
		status = false;
	}

	// Find the target scene node/rigid body
	fm::string targetNodeId = ReadNodeProperty(instanceNode, DAE_TARGET_ATTRIBUTE);
	physicsRigidBodyInstance->SetTargetNode(physicsRigidBodyInstance->GetDocument()->FindSceneNode(SkipPound(targetNodeId)));
	if (!physicsRigidBodyInstance->GetTargetNode())
	{
		FUError::Error(FUError::ERROR_LEVEL, FUError::WARNING_MISSING_URI_TARGET, instanceNode->line);
	}

	// Find the instantiated rigid body
	FCDPhysicsRigidBody* body = NULL;
	fm::string physicsRigidBodySid = ReadNodeProperty(instanceNode, DAE_BODY_ATTRIBUTE);
	if (physicsRigidBodyInstance->GetModelParentInstance()->GetEntity() != NULL &&  physicsRigidBodyInstance->GetModelParentInstance()->GetEntity()->GetType() == FCDEntity::PHYSICS_MODEL)
	{
		FCDPhysicsModel* model = (FCDPhysicsModel*) physicsRigidBodyInstance->GetModelParentInstance()->GetEntity();
		body = model->FindRigidBodyFromSid(physicsRigidBodySid);
		if (body == NULL)
		{
			FUError::Error(FUError::ERROR_LEVEL, FUError::WARNING_MISSING_URI_TARGET, instanceNode->line);
			return false;
		}
		physicsRigidBodyInstance->SetRigidBody(body);
	}

	//Read in the same children as rigid_body + velocity and angular_velocity
	xmlNode* techniqueNode = FindChildByType(instanceNode, DAE_TECHNIQUE_COMMON_ELEMENT);
	if (techniqueNode == NULL)
	{
		FUError::Error(FUError::ERROR_LEVEL, FUError::ERROR_TECHNIQUE_NODE_MISSING,
				instanceNode->line);
		return false;
	}

	xmlNode* param = 
			FindChildByType(techniqueNode, DAE_ANGULAR_VELOCITY_ELEMENT);
	if (param != NULL)
	{
		physicsRigidBodyInstance->SetAngularVelocity(FUStringConversion::ToVector3(
				ReadNodeContentDirect(param)));
	}
	else
	{
		physicsRigidBodyInstance->SetAngularVelocity(FMVector3::Zero);
	}

	param = FindChildByType(techniqueNode, DAE_VELOCITY_ELEMENT);
	if (param != NULL)
	{
		physicsRigidBodyInstance->SetVelocity(FUStringConversion::ToVector3(ReadNodeContentDirect(param)));
	}
	else
	{
		physicsRigidBodyInstance->SetVelocity(FMVector3::Zero);
	}

	FArchiveXML::LoadPhysicsRigidBodyParameters(physicsRigidBodyInstance->GetParameters(), techniqueNode, body->GetParameters());

	physicsRigidBodyInstance->SetDirtyFlag();
	return status;
}
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;
}		
bool FArchiveXML::LoadPhysicsRigidBodyParameters(FCDPhysicsRigidBodyParameters* parameters, xmlNode* techniqueNode, FCDPhysicsRigidBodyParameters* defaultParameters)
{
	bool status = true;

	xmlNode* param = FindChildByType(techniqueNode, DAE_DYNAMIC_ELEMENT);
	if (param)
	{
		parameters->SetDynamic(FUStringConversion::ToBoolean(ReadNodeContentDirect(param)));
		FArchiveXML::LoadAnimatable(&parameters->GetDynamic(), param);
	}
	else if (defaultParameters != NULL)
	{
		parameters->SetDynamic(defaultParameters->GetDynamic() > 0.5f);
		if (defaultParameters->GetDynamic().IsAnimated())
		{
			defaultParameters->GetDynamic().GetAnimated()->Clone(parameters->GetDynamic().GetAnimated());
		}
	}

	xmlNode* massFrame;
	massFrame = FindChildByType(techniqueNode, DAE_MASS_FRAME_ELEMENT);
	if (massFrame)
	{
		param = FindChildByType(massFrame, DAE_TRANSLATE_ELEMENT);
		if (param)
		{
			parameters->SetMassFrameTranslate(FUStringConversion::ToVector3(ReadNodeContentDirect(param)));
			FArchiveXML::LoadAnimatable(&parameters->GetMassFrameTranslate(), param);
		}
		else if (defaultParameters != NULL)
		{
			parameters->SetMassFrameTranslate(defaultParameters->GetMassFrameTranslate());
			if (defaultParameters->GetMassFrameTranslate().IsAnimated())
			{
				defaultParameters->GetMassFrameTranslate().GetAnimated()->Clone(parameters->GetMassFrameTranslate().GetAnimated());
			}
		}
		else
		{
			// no movement
			parameters->SetMassFrameTranslate(FMVector3::Zero);
		}

		param = FindChildByType(massFrame, DAE_ROTATE_ELEMENT);
		if (param)
		{
			FMVector4 temp = FUStringConversion::ToVector4(ReadNodeContentDirect(param));
			parameters->SetMassFrameOrientation(FMAngleAxis(FMVector3(temp.x, temp.y, temp.z), temp.w));
			LoadAnimatable(&parameters->GetMassFrameOrientation(), param);
		}
		else if (defaultParameters != NULL)
		{
			parameters->SetMassFrameOrientation(defaultParameters->GetMassFrameOrientation());
			if (defaultParameters->GetMassFrameOrientation().IsAnimated())
			{
				defaultParameters->GetMassFrameOrientation().GetAnimated()->Clone(parameters->GetMassFrameOrientation().GetAnimated());
			}
		}
		else
		{
			// no movement
			parameters->SetMassFrameOrientation(FMAngleAxis(FMVector3::XAxis, 0.0f));
		}
	}
	else if (defaultParameters != NULL)
	{
		parameters->SetMassFrameTranslate(defaultParameters->GetMassFrameTranslate());
		parameters->SetMassFrameOrientation(defaultParameters->GetMassFrameOrientation());
		if (defaultParameters->GetMassFrameTranslate().IsAnimated())
		{
			defaultParameters->GetMassFrameTranslate().GetAnimated()->Clone(parameters->GetMassFrameTranslate().GetAnimated());
		}
		if (defaultParameters->GetMassFrameOrientation().IsAnimated())
		{
			defaultParameters->GetMassFrameOrientation().GetAnimated()->Clone(parameters->GetMassFrameOrientation().GetAnimated());
		}
	}
	else
	{
		// no movement
		parameters->SetMassFrameTranslate(FMVector3::Zero);
		parameters->SetMassFrameOrientation(FMAngleAxis(FMVector3::XAxis, 0.0f));
	}

	xmlNodeList shapeNodes;
	FindChildrenByType(techniqueNode, DAE_SHAPE_ELEMENT, shapeNodes);
	if (shapeNodes.empty())
	{
		FUError::Error(FUError::WARNING_LEVEL, FUError::WARNING_SHAPE_NODE_MISSING, techniqueNode->line);
	}
	for (xmlNodeList::iterator itS = shapeNodes.begin(); itS != shapeNodes.end(); ++itS)
	{
		FCDPhysicsShape* shape = parameters->AddPhysicsShape();
		status &= (FArchiveXML::LoadPhysicsShape(shape, *itS));
	}
	// shapes are not taken from the default parameters

	param = FindChildByType(techniqueNode, DAE_PHYSICS_MATERIAL_ELEMENT);
	if (param != NULL) 
	{
		FCDPhysicsMaterial* material = parameters->AddOwnPhysicsMaterial();
		FArchiveXML::LoadPhysicsMaterial(material, param);
	}
	else
	{
		param = FindChildByType(techniqueNode, DAE_INSTANCE_PHYSICS_MATERIAL_ELEMENT);
		if (param != NULL)
		{
			FCDEntityInstance* physicsMaterialInstance = FCDEntityInstanceFactory::CreateInstance(parameters->GetDocument(), NULL, FCDEntity::PHYSICS_MATERIAL);
			parameters->SetInstanceMaterial(physicsMaterialInstance);
			FArchiveXML::LoadSwitch(physicsMaterialInstance, &physicsMaterialInstance->GetObjectType(), param);
			FCDPhysicsMaterial* material = (FCDPhysicsMaterial*) physicsMaterialInstance->GetEntity();
			if (material == NULL)
			{
				FUError::Error(FUError::ERROR_LEVEL, FUError::WARNING_MISSING_URI_TARGET, param->line);
			}
			parameters->SetPhysicsMaterial(material);
		}
		else
		{
			FUError::Error(FUError::WARNING_LEVEL, FUError::WARNING_PHYS_MAT_DEF_MISSING, techniqueNode->line);
		}
	}
	// material is not taken fromt he default parameters

	param = FindChildByType(techniqueNode, DAE_MASS_ELEMENT);
	if (param)
	{
		parameters->SetMass(FUStringConversion::ToFloat(ReadNodeContentDirect(param)));
		parameters->SetDensityMoreAccurate(false);
		parameters->SetDensity(0.0f);
		FArchiveXML::LoadAnimatable(&parameters->GetMass(), param);
	}
	else if (defaultParameters != NULL)
	{
		parameters->SetMass(defaultParameters->GetMass());
		parameters->SetDensity(defaultParameters->GetDensity());
		parameters->SetDensityMoreAccurate(defaultParameters->IsDensityMoreAccurate());
		if (defaultParameters->GetMass().IsAnimated())
		{
			defaultParameters->GetMass().GetAnimated()->Clone(parameters->GetMass().GetAnimated());
		}
	}
	else
	{
		/* Default value for mass is density x total shape volume, but 
		   since our shape's mass is already calculated with respect to the
		   volume, we can just read it from there. If the user specified a 
		   mass, then this overrides the calculation of density x volume, 
		   as expected. */
		parameters->SetMass(0.0f);
		float totalDensity = 0.0f;
		parameters->SetDensityMoreAccurate(false);
		for (size_t i = 0; i < parameters->GetPhysicsShapeCount(); ++i)
		{
			FCDPhysicsShape* shape = parameters->GetPhysicsShape(i);
			parameters->SetMass(parameters->GetMass() + shape->GetMass());
			totalDensity += shape->GetDensity();
			parameters->SetDensityMoreAccurate(parameters->IsDensityMoreAccurate() || shape->IsDensityMoreAccurate()); // common case: 1 shape, density = 1.0f
		}
		parameters->SetDensity(totalDensity / parameters->GetPhysicsShapeCount());
	}
	

	param = FindChildByType(techniqueNode, DAE_INERTIA_ELEMENT);
	if (param) 
	{
		parameters->SetInertia(FUStringConversion::ToVector3(ReadNodeContentDirect(param)));
		parameters->SetInertiaAccurate(true);
		FArchiveXML::LoadAnimatable(&parameters->GetInertia(), param);
	}
	else if (defaultParameters != NULL)
	{
		parameters->SetInertia(defaultParameters->GetInertia());
		parameters->SetInertiaAccurate(defaultParameters->IsInertiaAccurate());
		if (defaultParameters->GetInertia().IsAnimated())
		{
			defaultParameters->GetInertia().GetAnimated()->Clone(parameters->GetInertia().GetAnimated());
		}
	}
	else
	{
		/* FIXME: Approximation: sphere shape, with mass distributed 
		   equally across the volume and center of mass is at the center of
		   the sphere. Real moments of inertia call for complex 
		   integration. Sphere it is simply I = k * m * r^2 on all axes. */
		float volume = 0.0f;
		for (size_t i = 0; i < parameters->GetPhysicsShapeCount(); ++i)
		{
			volume += parameters->GetPhysicsShape(i)->CalculateVolume();
		}

		float radiusCubed = 0.75f * volume / (float)FMath::Pi;
		float I = 0.4f * parameters->GetMass() * pow(radiusCubed, 2.0f / 3.0f);
		parameters->SetInertia(FMVector3(I, I, I));
		parameters->SetInertiaAccurate(false);
	}

	return status;
}