/* 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/FCDExtra.h" #include "FCDocument/FCDMaterial.h" #include "FCDocument/FCDEntityReference.h" #include "FCDocument/FCDEntityInstance.h" #include "FCDocument/FCDEmitterInstance.h" #include "FCDocument/FCDGeometryInstance.h" #include "FCDocument/FCDControllerInstance.h" #include "FCDocument/FCDMaterialInstance.h" #include "FCDocument/FCDPhysicsForceFieldInstance.h" #include "FCDocument/FCDPhysicsModelInstance.h" #include "FCDocument/FCDPhysicsRigidBodyInstance.h" #include "FCDocument/FCDPhysicsRigidConstraintInstance.h" #include "FCDocument/FCDSkinController.h" #include "FCDocument/FCDSceneNode.h" #include "FCDocument/FCDPhysicsModel.h" #include "FCDocument/FCDPhysicsRigidConstraint.h" #include "FCDocument/FCDPhysicsRigidBody.h" #include "FCDocument/FCDPhysicsRigidBodyParameters.h" // // Helpers // static const char* GetInstanceClassTypeFCDEntityInstance(FCDEntity::Type type) { const char* instanceEntityName; switch (type) { case FCDEntity::ANIMATION: instanceEntityName = DAE_INSTANCE_ANIMATION_ELEMENT; break; case FCDEntity::CAMERA: instanceEntityName = DAE_INSTANCE_CAMERA_ELEMENT; break; case FCDEntity::CONTROLLER: instanceEntityName = DAE_INSTANCE_CONTROLLER_ELEMENT; break; case FCDEntity::EMITTER: instanceEntityName = DAE_INSTANCE_EMITTER_ELEMENT; break; case FCDEntity::EFFECT: instanceEntityName = DAE_INSTANCE_EFFECT_ELEMENT; break; case FCDEntity::FORCE_FIELD: instanceEntityName = DAE_INSTANCE_FORCE_FIELD_ELEMENT; break; case FCDEntity::GEOMETRY: instanceEntityName = DAE_INSTANCE_GEOMETRY_ELEMENT; break; case FCDEntity::LIGHT: instanceEntityName = DAE_INSTANCE_LIGHT_ELEMENT; break; case FCDEntity::MATERIAL: instanceEntityName = DAE_INSTANCE_MATERIAL_ELEMENT; break; case FCDEntity::PHYSICS_MATERIAL: instanceEntityName = DAE_INSTANCE_PHYSICS_MATERIAL_ELEMENT; break; case FCDEntity::PHYSICS_MODEL: instanceEntityName = DAE_INSTANCE_PHYSICS_MODEL_ELEMENT; break; case FCDEntity::PHYSICS_RIGID_BODY: instanceEntityName = DAE_INSTANCE_RIGID_BODY_ELEMENT; break; case FCDEntity::PHYSICS_RIGID_CONSTRAINT: instanceEntityName = DAE_INSTANCE_RIGID_CONSTRAINT_ELEMENT; break; case FCDEntity::SCENE_NODE: instanceEntityName = DAE_INSTANCE_NODE_ELEMENT; break; case FCDEntity::ANIMATION_CLIP: case FCDEntity::ENTITY: case FCDEntity::IMAGE: default: FUFail(instanceEntityName = DAEERR_UNKNOWN_ELEMENT); } return instanceEntityName; } // // Instance Export // xmlNode* FArchiveXML::WriteEntityInstance(FCDObject* object, xmlNode* parentNode) { FCDEntityInstance* entityInstance = (FCDEntityInstance*)object; const char* instanceEntityName = GetInstanceClassTypeFCDEntityInstance(entityInstance->GetEntityType()); xmlNode* instanceNode = AddChild(parentNode, instanceEntityName); if (!entityInstance->GetWantedSubId().empty()) { AddAttribute(instanceNode, DAE_SID_ATTRIBUTE, entityInstance->GetWantedSubId()); } if (!entityInstance->GetName().empty()) { AddAttribute(instanceNode, DAE_NAME_ATTRIBUTE, entityInstance->GetName()); } // Only write out our entity if we have one. const FUUri& uri = entityInstance->GetEntityUri(); fstring uriString = entityInstance->GetDocument()->GetFileManager()->CleanUri(uri); AddAttribute(instanceNode, DAE_URL_ATTRIBUTE, uriString); return instanceNode; } xmlNode* FArchiveXML::WriteEmitterInstance(FCDObject* object, xmlNode* parentNode) { FCDEmitterInstance* emitterInstance = (FCDEmitterInstance*)object; xmlNode* instanceNode = FArchiveXML::WriteEntityInstance(emitterInstance, parentNode); FArchiveXML::WriteEntityInstanceExtra(emitterInstance, instanceNode); return instanceNode; } xmlNode* FArchiveXML::WriteSpriteInstance(FCDEntityInstance* object, xmlNode* parentNode) { xmlNode* theRealExport = WriteGeometryInstance(object, parentNode); // Rename from geometry_instance to sprite RenameNode(theRealExport, DAE_INSTANCE_SPRITE_ELEMENT); // The sprite doesnt have a URL RemoveAttribute(theRealExport, DAE_URL_ATTRIBUTE); return theRealExport; } xmlNode* FArchiveXML::WriteGeometryInstance(FCDObject* object, xmlNode* parentNode) { FCDGeometryInstance* geometryInstance = (FCDGeometryInstance*)object; xmlNode* instanceNode = FArchiveXML::WriteEntityInstance(geometryInstance, parentNode); if (!(geometryInstance->GetMaterialInstanceCount() == 0)) { xmlNode* bindMaterialNode = AddChild(instanceNode, DAE_BINDMATERIAL_ELEMENT); size_t parameterCount = geometryInstance->GetEffectParameterCount(); for (size_t p = 0; p < parameterCount; ++p) { FArchiveXML::LetWriteObject(geometryInstance->GetEffectParameter(p), bindMaterialNode); } xmlNode* techniqueCommonNode = AddChild(bindMaterialNode, DAE_TECHNIQUE_COMMON_ELEMENT); for (size_t i = 0; i < geometryInstance->GetMaterialInstanceCount(); ++i) { FArchiveXML::LetWriteObject(geometryInstance->GetMaterialInstance(i), techniqueCommonNode); } } FArchiveXML::WriteEntityInstanceExtra(geometryInstance, instanceNode); return instanceNode; } xmlNode* FArchiveXML::WriteControllerInstance(FCDObject* object, xmlNode* parentNode) { FCDControllerInstance* controllerInstance = (FCDControllerInstance*)object; // Export the geometry instantiation information. xmlNode* instanceNode = FArchiveXML::WriteGeometryInstance(controllerInstance, parentNode); xmlNode* insertBeforeNode = (instanceNode != NULL) ? instanceNode->children : NULL; // Retrieve the parent joints and export the elements. FUUriList& skeletonRoots = controllerInstance->GetSkeletonRoots(); for (FUUriList::iterator itS = skeletonRoots.begin(); itS != skeletonRoots.end(); ++itS) { // TODO: External references (again) fm::string fragment = TO_STRING((*itS).GetFragment()); FUSStringBuilder builder; builder.set('#'); builder.append(fragment); xmlNode* skeletonNode = InsertChild(instanceNode, insertBeforeNode, DAE_SKELETON_ELEMENT); AddContent(skeletonNode, builder); } FArchiveXML::WriteEntityInstanceExtra(controllerInstance, instanceNode); return instanceNode; } xmlNode* FArchiveXML::WriteMaterialInstance(FCDObject* object, xmlNode* parentNode) { FCDMaterialInstance* materialInstance = (FCDMaterialInstance*)object; xmlNode* instanceNode = FArchiveXML::WriteEntityInstance(materialInstance, parentNode); // no url in instance_material RemoveAttribute(instanceNode, DAE_URL_ATTRIBUTE); AddAttribute(instanceNode, DAE_SYMBOL_ATTRIBUTE, materialInstance->GetSemantic()); // Only write out our entity if we have one. const FUUri& uri = materialInstance->GetEntityReference()->GetUri(); fstring uriString = materialInstance->GetDocument()->GetFileManager()->CleanUri(uri); AddAttribute(instanceNode, DAE_TARGET_ATTRIBUTE, uriString); // Write out the bindings. for (size_t i = 0; i < materialInstance->GetBindingCount(); ++i) { const FCDMaterialInstanceBind& bind = *materialInstance->GetBinding(i); xmlNode* bindNode = AddChild(instanceNode, DAE_BIND_ELEMENT); AddAttribute(bindNode, DAE_SEMANTIC_ATTRIBUTE, bind.semantic); AddAttribute(bindNode, DAE_TARGET_ATTRIBUTE, bind.target); } // Write out the vertex input bindings. for (size_t i = 0; i < materialInstance->GetVertexInputBindingCount(); ++i) { const FCDMaterialInstanceBindVertexInput* bind = materialInstance->GetVertexInputBinding(i); xmlNode* bindNode = AddChild(instanceNode, DAE_BIND_VERTEX_INPUT_ELEMENT); AddAttribute(bindNode, DAE_SEMANTIC_ATTRIBUTE, bind->semantic); AddAttribute(bindNode, DAE_INPUT_SEMANTIC_ATTRIBUTE, FUDaeGeometryInput::ToString(bind->GetInputSemantic())); AddAttribute(bindNode, DAE_INPUT_SET_ATTRIBUTE, bind->inputSet); } FArchiveXML::WriteEntityInstanceExtra(materialInstance, instanceNode); return instanceNode; } xmlNode* FArchiveXML::WritePhysicsForceFieldInstance(FCDObject* object, xmlNode* parentNode) { FCDPhysicsForceFieldInstance* physicsForceFieldInstance = (FCDPhysicsForceFieldInstance*)object; xmlNode* instanceNode = FArchiveXML::WriteEntityInstance(physicsForceFieldInstance, parentNode); // nothing interesting in force field instance to write FArchiveXML::WriteEntityInstanceExtra(physicsForceFieldInstance, instanceNode); return instanceNode; } xmlNode* FArchiveXML::WritePhysicsModelInstance(FCDObject* object, xmlNode* parentNode) { FCDPhysicsModelInstance* physicsModelInstance = (FCDPhysicsModelInstance*)object; xmlNode* instanceNode = FArchiveXML::WriteEntityInstance(physicsModelInstance, parentNode); // The sub-instances must be ordered correctly: force fields first, then rigid bodies; rigid constraints are last. for (size_t i = 0; i < physicsModelInstance->GetInstanceCount(); ++i) { if (physicsModelInstance->GetInstance(i)->GetEntityType() == FCDEntity::FORCE_FIELD) { FArchiveXML::LetWriteObject(physicsModelInstance->GetInstance(i), instanceNode); } } for (size_t i = 0; i < physicsModelInstance->GetInstanceCount(); ++i) { if (physicsModelInstance->GetInstance(i)->GetEntityType() == FCDEntity::PHYSICS_RIGID_BODY) { FArchiveXML::LetWriteObject(physicsModelInstance->GetInstance(i), instanceNode); } } for (size_t i = 0; i < physicsModelInstance->GetInstanceCount(); ++i) { if (physicsModelInstance->GetInstance(i)->GetEntityType() == FCDEntity::PHYSICS_RIGID_CONSTRAINT) { FArchiveXML::LetWriteObject(physicsModelInstance->GetInstance(i), instanceNode); } } FArchiveXML::WriteEntityInstanceExtra(physicsModelInstance, instanceNode); return instanceNode; } xmlNode* FArchiveXML::WritePhysicsRigidBodyInstance(FCDObject* object, xmlNode* parentNode) { FCDPhysicsRigidBodyInstance* physicsRigidBodyInstance = (FCDPhysicsRigidBodyInstance*)object; xmlNode* instanceNode = FArchiveXML::WriteEntityInstance(physicsRigidBodyInstance, parentNode); AddAttribute(instanceNode, DAE_TARGET_ATTRIBUTE, fm::string("#") + physicsRigidBodyInstance->GetTargetNode()->GetDaeId()); AddAttribute(instanceNode, DAE_BODY_ATTRIBUTE, physicsRigidBodyInstance->GetEntity()->GetDaeId()); //inconsistency in the spec RemoveAttribute(instanceNode, DAE_URL_ATTRIBUTE); xmlNode* techniqueNode = AddChild(instanceNode, DAE_TECHNIQUE_COMMON_ELEMENT); // almost same as FCDPhysicsRigidBody FArchiveXML::AddPhysicsParameter(techniqueNode, DAE_ANGULAR_VELOCITY_ELEMENT, physicsRigidBodyInstance->GetAngularVelocity()); FArchiveXML::AddPhysicsParameter(techniqueNode, DAE_VELOCITY_ELEMENT, physicsRigidBodyInstance->GetVelocity()); FArchiveXML::WritePhysicsRigidBodyParameters(physicsRigidBodyInstance->GetParameters(), techniqueNode); FArchiveXML::WriteEntityInstanceExtra(physicsRigidBodyInstance, instanceNode); return instanceNode; } xmlNode* FArchiveXML::WritePhysicsRigidConstraintInstance(FCDObject* object, xmlNode* parentNode) { FCDPhysicsRigidConstraintInstance* physicsRigidConstraintInstance = (FCDPhysicsRigidConstraintInstance*)object; xmlNode* instanceNode = FArchiveXML::WriteEntityInstance(physicsRigidConstraintInstance, parentNode); if (physicsRigidConstraintInstance->GetEntity() != NULL && physicsRigidConstraintInstance->GetEntity()->GetObjectType() == FCDPhysicsRigidConstraint::GetClassType()) { FCDPhysicsRigidConstraint* constraint = (FCDPhysicsRigidConstraint*) physicsRigidConstraintInstance->GetEntity(); AddAttribute(instanceNode, DAE_CONSTRAINT_ATTRIBUTE, constraint->GetSubId()); } //inconsistency in the spec RemoveAttribute(instanceNode, DAE_URL_ATTRIBUTE); FArchiveXML::WriteEntityInstanceExtra(physicsRigidConstraintInstance, instanceNode); return instanceNode; }