/* Copyright (C) 2005-2007 Feeling Software Inc. Portions of the code are: Copyright (C) 2005-2007 Sony Computer Entertainment America MIT License: http://www.opensource.org/licenses/mit-license.php */ #include "StdAfx.h" #include "FArchiveXML.h" #include "FCDocument/FCDocument.h" #include "FCDocument/FCDSceneNode.h" #include "FCDocument/FCDEntityInstance.h" #include "FCDocument/FCDPhysicsForceFieldInstance.h" #include "FCDocument/FCDGeometryInstance.h" #include "FCDocument/FCDPhysicsModelInstance.h" #include "FCDocument/FCDPhysicsRigidBodyInstance.h" #include "FCDocument/FCDPhysicsRigidBodyParameters.h" #include "FCDocument/FCDPhysicsAnalyticalGeometry.h" #include "FCDocument/FCDPhysicsMaterial.h" #include "FCDocument/FCDPhysicsModel.h" #include "FCDocument/FCDPhysicsRigidBody.h" #include "FCDocument/FCDPhysicsRigidConstraint.h" #include "FCDocument/FCDPhysicsScene.h" #include "FCDocument/FCDPhysicsShape.h" xmlNode* FArchiveXML::WritePhysicsShape(FCDObject* object, xmlNode* parentNode) { FCDPhysicsShape* physicsShape = (FCDPhysicsShape*)object; xmlNode* physicsShapeNode = AddChild(parentNode, DAE_SHAPE_ELEMENT); AddChild(physicsShapeNode, DAE_HOLLOW_ELEMENT, physicsShape->IsHollow()?"true":"false"); if (physicsShape->GetMass() && !physicsShape->IsDensityMoreAccurate()) AddChild(physicsShapeNode, DAE_MASS_ELEMENT, FUStringConversion::ToString(physicsShape->GetMass())); if (physicsShape->GetDensity()) AddChild(physicsShapeNode, DAE_DENSITY_ELEMENT, FUStringConversion::ToString(physicsShape->GetDensity())); if (physicsShape->OwnsPhysicsMaterial() && physicsShape->GetPhysicsMaterial()) { xmlNode* materialNode = AddChild(physicsShapeNode, DAE_PHYSICS_MATERIAL_ELEMENT); FArchiveXML::LetWriteObject(physicsShape->GetPhysicsMaterial(), materialNode); } else if (physicsShape->GetInstanceMaterial()) { FArchiveXML::LetWriteObject(physicsShape->GetInstanceMaterial(), physicsShapeNode); } if (physicsShape->GetGeometryInstance()) FArchiveXML::LetWriteObject(physicsShape->GetGeometryInstance(), physicsShapeNode); if (physicsShape->GetAnalyticalGeometry()) FArchiveXML::LetWriteObject(physicsShape->GetAnalyticalGeometry(), physicsShapeNode); for (size_t i = 0; i < physicsShape->GetTransforms().size(); ++i) { FArchiveXML::LetWriteObject(physicsShape->GetTransforms()[i], physicsShapeNode); } return physicsShapeNode; } xmlNode* FArchiveXML::WritePhysicsAnalyticalGeometry(FCDObject* object, xmlNode* UNUSED(parentNode)) { FCDPhysicsAnalyticalGeometry* physicsAnalyticalGeometry = (FCDPhysicsAnalyticalGeometry*)object; (void) physicsAnalyticalGeometry; // // Currently not reachable // FUBreak; return NULL; } xmlNode* FArchiveXML::WritePASBox(FCDObject* object, xmlNode* node) { FCDPASBox* pASBox = (FCDPASBox*)object; xmlNode* geomNode = AddChild(node, DAE_BOX_ELEMENT); fm::string s = FUStringConversion::ToString(pASBox->halfExtents); AddChild(geomNode, DAE_HALF_EXTENTS_ELEMENT, s); return geomNode; } xmlNode* FArchiveXML::WritePASCapsule(FCDObject* object, xmlNode* node) { FCDPASCapsule* pASCapsule = (FCDPASCapsule*)object; xmlNode* geomNode = AddChild(node, DAE_CAPSULE_ELEMENT); AddChild(geomNode, DAE_HEIGHT_ELEMENT, pASCapsule->height); AddChild(geomNode, DAE_RADIUS_ELEMENT, FUStringConversion::ToString(pASCapsule->radius)); return geomNode; } xmlNode* FArchiveXML::WritePASTaperedCapsule(FCDObject* object, xmlNode* node) { FCDPASTaperedCapsule* pASTaperedCapsule = (FCDPASTaperedCapsule*)object; xmlNode* geomNode = AddChild(node, DAE_TAPERED_CAPSULE_ELEMENT); AddChild(geomNode, DAE_HEIGHT_ELEMENT, pASTaperedCapsule->height); AddChild(geomNode, DAE_RADIUS1_ELEMENT, FUStringConversion::ToString(pASTaperedCapsule->radius)); AddChild(geomNode, DAE_RADIUS2_ELEMENT, FUStringConversion::ToString(pASTaperedCapsule->radius2)); return geomNode; } xmlNode* FArchiveXML::WritePASCylinder(FCDObject* object, xmlNode* node) { FCDPASCylinder* pASCylinder = (FCDPASCylinder*)object; xmlNode* geomNode = AddChild(node, DAE_CYLINDER_ELEMENT); AddChild(geomNode, DAE_HEIGHT_ELEMENT, pASCylinder->height); AddChild(geomNode, DAE_RADIUS_ELEMENT, FUStringConversion::ToString(pASCylinder->radius)); return geomNode; } xmlNode* FArchiveXML::WritePASTaperedCylinder(FCDObject* object, xmlNode* node) { FCDPASTaperedCylinder* pASTaperedCylinder = (FCDPASTaperedCylinder*)object; xmlNode* geomNode = AddChild(node, DAE_TAPERED_CYLINDER_ELEMENT); AddChild(geomNode, DAE_HEIGHT_ELEMENT, pASTaperedCylinder->height); AddChild(geomNode, DAE_RADIUS1_ELEMENT, FUStringConversion::ToString(pASTaperedCylinder->radius)); AddChild(geomNode, DAE_RADIUS2_ELEMENT, FUStringConversion::ToString(pASTaperedCylinder->radius2)); return geomNode; } xmlNode* FArchiveXML::WritePASPlane(FCDObject* object, xmlNode* node) { FCDPASPlane* pASPlane = (FCDPASPlane*)object; xmlNode* geomNode = AddChild(node, DAE_PLANE_ELEMENT); FMVector4 equation; equation.w = pASPlane->normal.x; equation.x = pASPlane->normal.y; equation.y = pASPlane->normal.z; equation.z = pASPlane->d; fm::string s = FUStringConversion::ToString(equation); AddChild(geomNode, DAE_EQUATION_ELEMENT, s); return geomNode; } xmlNode* FArchiveXML::WritePASSphere(FCDObject* object, xmlNode* node) { FCDPASSphere* pASSphere = (FCDPASSphere*)object; xmlNode* geomNode = AddChild(node, DAE_SPHERE_ELEMENT); AddChild(geomNode, DAE_RADIUS_ELEMENT, pASSphere->radius); return geomNode; } xmlNode* FArchiveXML::WritePhysicsMaterial(FCDObject* object, xmlNode* parentNode) { FCDPhysicsMaterial* physicsMaterial = (FCDPhysicsMaterial*)object; xmlNode* physicsMaterialNode = FArchiveXML::WriteToEntityXMLFCDEntity(physicsMaterial, parentNode, DAE_PHYSICS_MATERIAL_ELEMENT); xmlNode* commonTechniqueNode = AddChild(physicsMaterialNode, DAE_TECHNIQUE_COMMON_ELEMENT); AddChild(commonTechniqueNode, DAE_PHYSICS_DYNAMIC_FRICTION, physicsMaterial->GetDynamicFriction()); AddChild(commonTechniqueNode, DAE_PHYSICS_RESTITUTION, physicsMaterial->GetRestitution()); AddChild(commonTechniqueNode, DAE_PHYSICS_STATIC_FRICTION, physicsMaterial->GetStaticFriction()); FArchiveXML::WriteEntityExtra(physicsMaterial, physicsMaterialNode); return physicsMaterialNode; } xmlNode* FArchiveXML::WritePhysicsModel(FCDObject* object, xmlNode* parentNode) { FCDPhysicsModel* physicsModel = (FCDPhysicsModel*)object; xmlNode* physicsModelNode = FArchiveXML::WriteToEntityXMLFCDEntity(physicsModel, parentNode, DAE_PHYSICS_MODEL_ELEMENT); for (size_t i = 0; i < physicsModel->GetInstanceCount(); ++i) { FArchiveXML::LetWriteObject(physicsModel->GetInstance(i), physicsModelNode); } for (size_t i = 0; i < physicsModel->GetRigidBodyCount(); ++i) { FArchiveXML::LetWriteObject(physicsModel->GetRigidBody(i), physicsModelNode); } for (size_t i = 0; i < physicsModel->GetRigidConstraintCount(); i++) { FArchiveXML::LetWriteObject(physicsModel->GetRigidConstraint(i), physicsModelNode); } FArchiveXML::WriteEntityExtra(physicsModel, physicsModelNode); return physicsModelNode; } xmlNode* FArchiveXML::WritePhysicsRigidBody(FCDObject* object, xmlNode* parentNode) { FCDPhysicsRigidBody* physicsRigidBody = (FCDPhysicsRigidBody*)object; xmlNode* physicsRigidBodyNode = FArchiveXML::WriteToEntityXMLFCDEntity(physicsRigidBody, parentNode, DAE_RIGID_BODY_ELEMENT, false); physicsRigidBody->SetSubId(AddNodeSid(physicsRigidBodyNode, physicsRigidBody->GetSubId().c_str())); xmlNode* baseNode = AddChild(physicsRigidBodyNode, DAE_TECHNIQUE_COMMON_ELEMENT); FArchiveXML::WritePhysicsRigidBodyParameters(physicsRigidBody->GetParameters(), baseNode); FArchiveXML::WriteEntityExtra(physicsRigidBody, physicsRigidBodyNode); return physicsRigidBodyNode; } xmlNode* FArchiveXML::WritePhysicsRigidConstraint(FCDObject* object, xmlNode* parentNode) { FCDPhysicsRigidConstraint* physicsRigidConstraint = (FCDPhysicsRigidConstraint*)object; xmlNode* physicsRigidConstraintNode = FArchiveXML::WriteToEntityXMLFCDEntity(physicsRigidConstraint, parentNode, DAE_RIGID_CONSTRAINT_ELEMENT, false); physicsRigidConstraint->SetSubId(AddNodeSid(physicsRigidConstraintNode, physicsRigidConstraint->GetSubId().c_str())); xmlNode* refNode = AddChild(physicsRigidConstraintNode, DAE_REF_ATTACHMENT_ELEMENT); fm::string referenceId = (physicsRigidConstraint->GetReferenceRigidBody() != NULL) ? physicsRigidConstraint->GetReferenceRigidBody()->GetSubId() : (physicsRigidConstraint->GetReferenceNode() != NULL) ? physicsRigidConstraint->GetReferenceNode()->GetDaeId() : ""; AddAttribute(refNode, DAE_RIGID_BODY_ELEMENT, referenceId); for (FCDTransformContainer::iterator itT = physicsRigidConstraint->GetTransformsRef().begin(); itT != physicsRigidConstraint->GetTransformsRef().end(); ++itT) { FArchiveXML::LetWriteObject((*itT), refNode); } xmlNode* tarNode = AddChild(physicsRigidConstraintNode, DAE_ATTACHMENT_ELEMENT); fm::string targetId = (physicsRigidConstraint->GetTargetRigidBody() != NULL) ? physicsRigidConstraint->GetTargetRigidBody()->GetSubId() : (physicsRigidConstraint->GetTargetNode() != NULL) ? physicsRigidConstraint->GetTargetNode()->GetDaeId() : ""; AddAttribute(tarNode, DAE_RIGID_BODY_ELEMENT, targetId); for (FCDTransformContainer::iterator itT = physicsRigidConstraint->GetTransformsTar().begin(); itT != physicsRigidConstraint->GetTransformsTar().end(); ++itT) { FArchiveXML::LetWriteObject((*itT), tarNode); } xmlNode* baseNode = AddChild(physicsRigidConstraintNode, DAE_TECHNIQUE_COMMON_ELEMENT); xmlNode* enabledNode = AddChild(baseNode, DAE_ENABLED_ELEMENT, physicsRigidConstraint->GetEnabled()); if (physicsRigidConstraint->GetEnabled().IsAnimated()) { FArchiveXML::WriteAnimatedValue(&physicsRigidConstraint->GetEnabled(), enabledNode, !physicsRigidConstraint->GetSubId().empty() ? physicsRigidConstraint->GetSubId().c_str() : "constrain"); } xmlNode* interpenetrateNode = AddChild(baseNode, DAE_INTERPENETRATE_ELEMENT, physicsRigidConstraint->GetInterpenetrate()); if (physicsRigidConstraint->GetInterpenetrate().IsAnimated()) { FArchiveXML::WriteAnimatedValue(&physicsRigidConstraint->GetInterpenetrate(), interpenetrateNode, !physicsRigidConstraint->GetSubId().empty() ? physicsRigidConstraint->GetSubId().c_str() : "interpenetrate"); } xmlNode* limitsNode = AddChild(baseNode, DAE_LIMITS_ELEMENT); xmlNode* sctNode = AddChild(limitsNode, DAE_SWING_CONE_AND_TWIST_ELEMENT); AddChild(sctNode, DAE_MIN_ELEMENT, (const FMVector3&) physicsRigidConstraint->GetLimitsSCTMin()); AddChild(sctNode, DAE_MAX_ELEMENT, (const FMVector3&) physicsRigidConstraint->GetLimitsSCTMax()); xmlNode* linearNode = AddChild(limitsNode, DAE_LINEAR_ELEMENT); AddChild(linearNode, DAE_MIN_ELEMENT, (FMVector3&) physicsRigidConstraint->GetLimitsLinearMin()); AddChild(linearNode, DAE_MAX_ELEMENT, (FMVector3&) physicsRigidConstraint->GetLimitsLinearMax()); xmlNode* springNode = AddChild(baseNode, DAE_SPRING_ELEMENT); xmlNode* sAngularNode = AddChild(springNode, DAE_ANGULAR_ELEMENT); AddChild(sAngularNode, DAE_STIFFNESS_ELEMENT, physicsRigidConstraint->GetSpringAngularStiffness()); AddChild(sAngularNode, DAE_DAMPING_ELEMENT, physicsRigidConstraint->GetSpringAngularDamping()); AddChild(sAngularNode, DAE_TARGET_VALUE_ELEMENT, physicsRigidConstraint->GetSpringAngularTargetValue()); xmlNode* sLinearNode = AddChild(springNode, DAE_LINEAR_ELEMENT); AddChild(sLinearNode, DAE_STIFFNESS_ELEMENT, physicsRigidConstraint->GetSpringLinearStiffness()); AddChild(sLinearNode, DAE_DAMPING_ELEMENT, physicsRigidConstraint->GetSpringLinearDamping()); AddChild(sLinearNode, DAE_TARGET_VALUE_ELEMENT, physicsRigidConstraint->GetSpringLinearTargetValue()); //FIXME: what about and ? FArchiveXML::WriteEntityExtra(physicsRigidConstraint, physicsRigidConstraintNode); return physicsRigidConstraintNode; } xmlNode* FArchiveXML::WritePhysicsScene(FCDObject* object, xmlNode* parentNode) { FCDPhysicsScene* physicsScene = (FCDPhysicsScene*)object; xmlNode* physicsSceneNode = FArchiveXML::WriteToEntityXMLFCDEntity(physicsScene, parentNode, DAE_PHYSICS_SCENE_ELEMENT); if (physicsSceneNode == NULL) return physicsSceneNode; // Write out the instantiation: force fields, then physics models for (size_t i = 0; i < physicsScene->GetForceFieldInstancesCount(); ++i) { FCDEntityInstance* instance = physicsScene->GetForceFieldInstance(i); FArchiveXML::LetWriteObject(instance, physicsSceneNode); } for (size_t i = 0; i < physicsScene->GetPhysicsModelInstancesCount(); ++i) { FCDEntityInstance* instance = physicsScene->GetPhysicsModelInstance(i); FArchiveXML::LetWriteObject(instance, physicsSceneNode); } // Add COMMON technique. xmlNode* techniqueNode = AddChild(physicsSceneNode, DAE_TECHNIQUE_COMMON_ELEMENT); AddChild(techniqueNode, DAE_GRAVITY_ATTRIBUTE, TO_STRING(physicsScene->GetGravity())); AddChild(techniqueNode, DAE_TIME_STEP_ATTRIBUTE, physicsScene->GetTimestep()); // Write out the extra information FArchiveXML::WriteEntityExtra(physicsScene, physicsSceneNode); return physicsSceneNode; } void FArchiveXML::WritePhysicsRigidBodyParameters(FCDPhysicsRigidBodyParameters* physicsRigidBodyParameters, xmlNode* techniqueNode) { FArchiveXML::AddPhysicsParameter(techniqueNode, DAE_DYNAMIC_ELEMENT, physicsRigidBodyParameters->GetDynamic()); FArchiveXML::AddPhysicsParameter(techniqueNode, DAE_MASS_ELEMENT, physicsRigidBodyParameters->GetMass()); xmlNode* massFrameNode = AddChild(techniqueNode, DAE_MASS_FRAME_ELEMENT); FArchiveXML::AddPhysicsParameter(massFrameNode, DAE_TRANSLATE_ELEMENT, physicsRigidBodyParameters->GetMassFrameTranslate()); FMVector4 massFrameRotate(physicsRigidBodyParameters->GetMassFrameRotateAxis(), physicsRigidBodyParameters->GetMassFrameRotateAngle()); AddChild(massFrameNode, DAE_ROTATE_ELEMENT, massFrameRotate); if (physicsRigidBodyParameters->IsInertiaAccurate()) { FArchiveXML::AddPhysicsParameter(techniqueNode, DAE_INERTIA_ELEMENT, physicsRigidBodyParameters->GetInertia()); } if (physicsRigidBodyParameters->GetPhysicsMaterial() != NULL) { if (physicsRigidBodyParameters->OwnsPhysicsMaterial()) { FArchiveXML::LetWriteObject(physicsRigidBodyParameters->GetPhysicsMaterial(), techniqueNode); } else if (physicsRigidBodyParameters->GetInstanceMaterial() != NULL) { FArchiveXML::LetWriteObject(physicsRigidBodyParameters->GetInstanceMaterial(), techniqueNode); } else { xmlNode* instanceNode = AddChild(techniqueNode, DAE_INSTANCE_PHYSICS_MATERIAL_ELEMENT); AddAttribute(instanceNode, DAE_URL_ATTRIBUTE, fm::string("#") + physicsRigidBodyParameters->GetPhysicsMaterial()->GetDaeId()); } } for (size_t i = 0; i < physicsRigidBodyParameters->GetPhysicsShapeCount(); ++i) { FArchiveXML::LetWriteObject(physicsRigidBodyParameters->GetPhysicsShape(i), techniqueNode); } } template xmlNode* FArchiveXML::AddPhysicsParameter(xmlNode* parentNode, const char* name, FCDParameterAnimatableT& value) { xmlNode* paramNode = AddChild(parentNode, name); AddContent(paramNode, FUStringConversion::ToString((TYPE&) value)); if (value.IsAnimated()) { const FCDAnimated* animated = value.GetAnimated(); FArchiveXML::WriteAnimatedValue(animated, paramNode, name); } return paramNode; }