diff --git a/lib/irrlicht/CMakeLists.txt b/lib/irrlicht/CMakeLists.txt index 859485a62..5835499ee 100644 --- a/lib/irrlicht/CMakeLists.txt +++ b/lib/irrlicht/CMakeLists.txt @@ -86,7 +86,6 @@ source/Irrlicht/CTriangleBBSelector.cpp source/Irrlicht/CAnimatedMeshMD3.cpp source/Irrlicht/CGUIComboBox.cpp source/Irrlicht/CSceneNodeAnimatorTexture.cpp -source/Irrlicht/CColladaMeshWriter.cpp source/Irrlicht/COpenGLTexture.cpp source/Irrlicht/COctreeSceneNode.cpp source/Irrlicht/CWaterSurfaceSceneNode.cpp @@ -182,7 +181,6 @@ source/Irrlicht/CNullDriver.cpp source/Irrlicht/CCameraSceneNode.cpp source/Irrlicht/CGUISpinBox.cpp source/Irrlicht/CReadFile.cpp -source/Irrlicht/CColladaFileLoader.cpp source/Irrlicht/CParticleRingEmitter.cpp source/Irrlicht/CMetaTriangleSelector.cpp source/Irrlicht/CShadowVolumeSceneNode.cpp @@ -256,7 +254,6 @@ source/Irrlicht/wglext.h source/Irrlicht/CTimer.h source/Irrlicht/CCSMLoader.h source/Irrlicht/CWADReader.h -source/Irrlicht/CColladaMeshWriter.h source/Irrlicht/CSceneNodeAnimatorCameraFPS.h source/Irrlicht/CParticleFadeOutAffector.h source/Irrlicht/COpenGLSLMaterialRenderer.h @@ -322,7 +319,6 @@ source/Irrlicht/CWaterSurfaceSceneNode.h source/Irrlicht/SoftwareDriver2_compile_config.h source/Irrlicht/CSceneNodeAnimatorTexture.h source/Irrlicht/CXMLReader.h -source/Irrlicht/CColladaFileLoader.h source/Irrlicht/CEmptySceneNode.h source/Irrlicht/CCgMaterialRenderer.h source/Irrlicht/CParticleSystemSceneNode.h @@ -434,7 +430,6 @@ include/ITimer.h include/IImage.h include/position2d.h include/IGUIToolbar.h -include/IColladaMeshWriter.h include/IGUISpinBox.h include/IGUITabControl.h include/IBillboardTextSceneNode.h diff --git a/lib/irrlicht/include/IColladaMeshWriter.h b/lib/irrlicht/include/IColladaMeshWriter.h deleted file mode 100644 index 90691f575..000000000 --- a/lib/irrlicht/include/IColladaMeshWriter.h +++ /dev/null @@ -1,404 +0,0 @@ -// Copyright (C) 2002-2012 Nikolaus Gebhardt -// This file is part of the "Irrlicht Engine". -// For conditions of distribution and use, see copyright notice in irrlicht.h - -#ifndef __IRR_I_COLLADA_MESH_WRITER_H_INCLUDED__ -#define __IRR_I_COLLADA_MESH_WRITER_H_INCLUDED__ - -#include "IMeshWriter.h" -#include "ISceneNode.h" -#include "IAnimatedMesh.h" -#include "SMaterial.h" - -namespace irr -{ -namespace io -{ - class IWriteFile; -} // end namespace io - -namespace scene -{ - //! Lighting models - more or less the way Collada categorizes materials - enum E_COLLADA_TECHNIQUE_FX - { - //! Blinn-phong which is default for opengl and dx fixed function pipelines. - //! But several well-known renderers don't support it and prefer phong. - ECTF_BLINN, - //! Phong shading, default in many external renderers. - ECTF_PHONG, - //! diffuse shaded surface that is independent of lighting. - ECTF_LAMBERT, - // constantly shaded surface that is independent of lighting. - ECTF_CONSTANT - }; - - //! How to interpret the opacity in collada - enum E_COLLADA_TRANSPARENT_FX - { - //! default - only alpha channel of color or texture is used. - ECOF_A_ONE = 0, - - //! Alpha values for each RGB channel of color or texture are used. - ECOF_RGB_ZERO = 1 - }; - - //! Color names collada uses in it's color samplers - enum E_COLLADA_COLOR_SAMPLER - { - ECCS_DIFFUSE, - ECCS_AMBIENT, - ECCS_EMISSIVE, - ECCS_SPECULAR, - ECCS_TRANSPARENT, - ECCS_REFLECTIVE - }; - - //! Irrlicht colors which can be mapped to E_COLLADA_COLOR_SAMPLER values - enum E_COLLADA_IRR_COLOR - { - //! Don't write this element at all - ECIC_NONE, - - //! Check IColladaMeshWriterProperties for custom color - ECIC_CUSTOM, - - //! Use SMaterial::DiffuseColor - ECIC_DIFFUSE, - - //! Use SMaterial::AmbientColor - ECIC_AMBIENT, - - //! Use SMaterial::EmissiveColor - ECIC_EMISSIVE, - - //! Use SMaterial::SpecularColor - ECIC_SPECULAR - }; - - //! Control when geometry elements are created - enum E_COLLADA_GEOMETRY_WRITING - { - //! Default - write each mesh exactly once to collada. Optimal but will not work with many tools. - ECGI_PER_MESH, - - //! Write each mesh as often as it's used with different materials-names in the scene. - //! Material names which are used here are created on export, so using the IColladaMeshWriterNames - //! interface you have some control over how many geometries are written. - ECGI_PER_MESH_AND_MATERIAL - }; - - //! Callback interface for properties which can be used to influence collada writing - class IColladaMeshWriterProperties : public virtual IReferenceCounted - { - public: - virtual ~IColladaMeshWriterProperties () {} - - //! Which lighting model should be used in the technique (FX) section when exporting effects (materials) - virtual E_COLLADA_TECHNIQUE_FX getTechniqueFx(const video::SMaterial& material) const = 0; - - //! Which texture index should be used when writing the texture of the given sampler color. - /** \return the index to the texture-layer or -1 if that texture should never be exported - Note: for ECCS_TRANSPARENT by default the alpha channel is used, if you want to use RGB you have to set - also the ECOF_RGB_ZERO flag in getTransparentFx. */ - virtual s32 getTextureIdx(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs) const = 0; - - //! Return which color from Irrlicht should be used for the color requested by collada - /** Note that collada allows exporting either texture or color, not both. - So color mapping is only checked if we have no valid texture already. - By default we try to return best fits when possible. For example ECCS_DIFFUSE is mapped to ECIC_DIFFUSE. - When ECIC_CUSTOM is returned then the result of getCustomColor will be used. */ - virtual E_COLLADA_IRR_COLOR getColorMapping(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs) const = 0; - - //! Return custom colors for certain color types requested by collada. - /** Only used when getColorMapping returns ECIC_CUSTOM for the same paramters. */ - virtual video::SColor getCustomColor(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs) const = 0; - - //! Return the transparence color interpretation. - /** Not this is only about ECCS_TRANSPARENT and does not affect getTransparency. */ - virtual E_COLLADA_TRANSPARENT_FX getTransparentFx(const video::SMaterial& material) const = 0; - - //! Transparency value for that material. - /** This value is additional to transparent settings, if both are set they will be multiplicated. - \return 1.0 for fully transparent, 0.0 for not transparent and not written at all when < 0.f */ - virtual f32 getTransparency(const video::SMaterial& material) const = 0; - - //! Reflectivity value for that material - /** The amount of perfect mirror reflection to be added to the reflected light - \return 0.0 - 1.0 for reflectivity and element is not written at all when < 0.f */ - virtual f32 getReflectivity(const video::SMaterial& material) const = 0; - - //! Return index of refraction for that material - /** By default we don't write that. - \return a value greater equal 0.f to write \ when it is lesser than 0 nothing will be written */ - virtual f32 getIndexOfRefraction(const video::SMaterial& material) const = 0; - - //! Should node be used in scene export? (only needed for scene-writing, ignored in mesh-writing) - //! By default all visible nodes are exported. - virtual bool isExportable(const irr::scene::ISceneNode * node) const = 0; - - //! Return the mesh for the given node. If it has no mesh or shouldn't export it's mesh - //! you can return 0 in which case only the transformation matrix of the node will be used. - // Note: Function is not const because there is no const getMesh() function. - virtual IMesh* getMesh(irr::scene::ISceneNode * node) = 0; - - //! Return if the node has it's own material overwriting the mesh-materials - /** Usually true except for mesh-nodes which have isReadOnlyMaterials set. - This is mostly important for naming (as ISceneNode::getMaterial() already returns the correct material). - You have to override it when exporting custom scenenodes with own materials. - \return true => The node's own material is used, false => ignore node material and use the one from the mesh */ - virtual bool useNodeMaterial(const scene::ISceneNode* node) const = 0; - - }; - - //! Callback interface to use custom names on collada writing. - /** You can either modify names and id's written to collada or you can use - this interface to just find out which names are used on writing. - */ - class IColladaMeshWriterNames : public virtual IReferenceCounted - { - public: - - virtual ~IColladaMeshWriterNames () {} - - //! Return a unique name for the given mesh - /** Note that names really must be unique here per mesh-pointer, so - mostly it's a good idea to return the nameForMesh from - IColladaMeshWriter::getDefaultNameGenerator(). Also names must follow - the xs::NCName standard to be valid, you can run them through - IColladaMeshWriter::toNCName to ensure that. - \param mesh Pointer to the mesh which needs a name - \param instance When E_COLLADA_GEOMETRY_WRITING is not ECGI_PER_MESH then - several instances of the same mesh can be written and this counts them. - */ - virtual irr::core::stringw nameForMesh(const scene::IMesh* mesh, int instance) = 0; - - //! Return a unique name for the given node - /** Note that names really must be unique here per node-pointer, so - mostly it's a good idea to return the nameForNode from - IColladaMeshWriter::getDefaultNameGenerator(). Also names must follow - the xs::NCName standard to be valid, you can run them through - IColladaMeshWriter::toNCName to ensure that. - */ - virtual irr::core::stringw nameForNode(const scene::ISceneNode* node) = 0; - - //! Return a name for the material - /** There is one material created in the writer for each unique name. - So you can use this to control the number of materials which get written. - For example Irrlicht does by default write one material for each material - instanced by a node. So if you know that in your application material - instances per node are identical between different nodes you can reduce - the number of exported materials using that knowledge by using identical - names for such shared materials. - Names must follow the xs::NCName standard to be valid, you can run them - through IColladaMeshWriter::toNCName to ensure that. - */ - virtual irr::core::stringw nameForMaterial(const video::SMaterial & material, int materialId, const scene::IMesh* mesh, const scene::ISceneNode* node) = 0; - }; - - - //! Interface for writing meshes - class IColladaMeshWriter : public IMeshWriter - { - public: - - IColladaMeshWriter() - : Properties(0), DefaultProperties(0), NameGenerator(0), DefaultNameGenerator(0) - , WriteTextures(true), WriteDefaultScene(true), ExportSMaterialOnce(true) - , AmbientLight(0.f, 0.f, 0.f, 1.f) - { - } - - //! Destructor - virtual ~IColladaMeshWriter() - { - if ( Properties ) - Properties->drop(); - if ( DefaultProperties ) - DefaultProperties->drop(); - if ( NameGenerator ) - NameGenerator->drop(); - if ( DefaultNameGenerator ) - DefaultNameGenerator->drop(); - } - - //! writes a scene starting with the given node - virtual bool writeScene(io::IWriteFile* file, scene::ISceneNode* root) = 0; - - - //! Set if texture information should be written - virtual void setWriteTextures(bool write) - { - WriteTextures = write; - } - - //! Get if texture information should be written - virtual bool getWriteTextures() const - { - return WriteTextures; - } - - //! Set if a default scene should be written when writing meshes. - /** Many collada readers fail to read a mesh if the collada files doesn't contain a scene as well. - The scene is doing an instantiation of the mesh. - When using writeScene this flag is ignored (as we have scene there already) - */ - virtual void setWriteDefaultScene(bool write) - { - WriteDefaultScene = write; - } - - //! Get if a default scene should be written - virtual bool getWriteDefaultScene() const - { - return WriteDefaultScene; - } - - //! Sets ambient color of the scene to write - virtual void setAmbientLight(const video::SColorf &ambientColor) - { - AmbientLight = ambientColor; - } - - //! Return ambient light of the scene which is written - virtual video::SColorf getAmbientLight() const - { - return AmbientLight; - } - - //! Control when and how often a mesh is written - /** Optimally ECGI_PER_MESH would be always sufficent - writing geometry once per mesh. - Unfortunately many tools (at the time of writing this nearly all of them) have trouble - on import when different materials are used per node. So when you override materials - per node and importing the resuling collada has materials problems in other tools try - using other values here. - \param writeStyle One of the E_COLLADA_GEOMETRY_WRITING settings. - */ - virtual void setGeometryWriting(E_COLLADA_GEOMETRY_WRITING writeStyle) - { - GeometryWriting = writeStyle; - } - - //! Get the current style of geometry writing. - virtual E_COLLADA_GEOMETRY_WRITING getGeometryWriting() const - { - return GeometryWriting; - } - - //! Make certain there is only one collada material generated per Irrlicht material - /** Checks before creating a collada material-name if an identical - irr:::video::SMaterial has been exported already. If so don't export it with - another name. This is set by default and leads to way smaller .dae files. - Note that if you need to disable this flag for some reason you can still - get a similar effect using the IColladaMeshWriterNames::nameForMaterial - by returning identical names for identical materials there. - */ - virtual void setExportSMaterialsOnlyOnce(bool exportOnce) - { - ExportSMaterialOnce = exportOnce; - } - - virtual bool getExportSMaterialsOnlyOnce() const - { - return ExportSMaterialOnce; - } - - //! Set properties to use by the meshwriter instead of it's default properties. - /** Overloading properties with an own class allows modifying the writing process in certain ways. - By default properties are set to the DefaultProperties. */ - virtual void setProperties(IColladaMeshWriterProperties * p) - { - if ( p == Properties ) - return; - if ( p ) - p->grab(); - if ( Properties ) - Properties->drop(); - Properties = p; - } - - //! Get properties which are currently used. - virtual IColladaMeshWriterProperties * getProperties() const - { - return Properties; - } - - //! Return the original default properties of the writer. - /** You can use this pointer in your own properties to access and return default values. */ - IColladaMeshWriterProperties * getDefaultProperties() const - { - return DefaultProperties; - } - - //! Install a generator to create custom names on export. - virtual void setNameGenerator(IColladaMeshWriterNames * nameGenerator) - { - if ( nameGenerator == NameGenerator ) - return; - if ( nameGenerator ) - nameGenerator->grab(); - if ( NameGenerator ) - NameGenerator->drop(); - NameGenerator = nameGenerator; - } - - //! Get currently used name generator - virtual IColladaMeshWriterNames * getNameGenerator() const - { - return NameGenerator; - } - - //! Return the original default name generator of the writer. - /** You can use this pointer in your own generator to access and return default values. */ - IColladaMeshWriterNames * getDefaultNameGenerator() const - { - return DefaultNameGenerator; - } - - //! Restrict the characters of oldString a set of allowed characters in xs::NCName and add the prefix. - /** A tool function to help when using a custom name generator to generative valid names for collada names and id's. */ - virtual irr::core::stringw toNCName(const irr::core::stringw& oldString, const irr::core::stringw& prefix=irr::core::stringw(L"_NC_")) const = 0; - - - protected: - // NOTE: You usually should also call setProperties with the same paraemter when using setDefaultProperties - virtual void setDefaultProperties(IColladaMeshWriterProperties * p) - { - if ( p == DefaultProperties ) - return; - if ( p ) - p->grab(); - if ( DefaultProperties ) - DefaultProperties->drop(); - DefaultProperties = p; - } - - // NOTE: You usually should also call setNameGenerator with the same paraemter when using setDefaultProperties - virtual void setDefaultNameGenerator(IColladaMeshWriterNames * p) - { - if ( p == DefaultNameGenerator ) - return; - if ( p ) - p->grab(); - if ( DefaultNameGenerator ) - DefaultNameGenerator->drop(); - DefaultNameGenerator = p; - } - - private: - IColladaMeshWriterProperties * Properties; - IColladaMeshWriterProperties * DefaultProperties; - IColladaMeshWriterNames * NameGenerator; - IColladaMeshWriterNames * DefaultNameGenerator; - bool WriteTextures; - bool WriteDefaultScene; - bool ExportSMaterialOnce; - video::SColorf AmbientLight; - E_COLLADA_GEOMETRY_WRITING GeometryWriting; - }; - - -} // end namespace -} // end namespace - -#endif diff --git a/lib/irrlicht/include/IrrCompileConfig.h b/lib/irrlicht/include/IrrCompileConfig.h index 1d1e19a2c..639165a43 100644 --- a/lib/irrlicht/include/IrrCompileConfig.h +++ b/lib/irrlicht/include/IrrCompileConfig.h @@ -317,11 +317,6 @@ B3D, MS3D or X meshes */ #ifdef NO_IRR_COMPILE_WITH_MD3_LOADER_ #undef _IRR_COMPILE_WITH_MD3_LOADER_ #endif -//! Define _IRR_COMPILE_WITH_COLLADA_LOADER_ if you want to load Collada files -#define _IRR_COMPILE_WITH_COLLADA_LOADER_ -#ifdef NO_IRR_COMPILE_WITH_COLLADA_LOADER_ -#undef _IRR_COMPILE_WITH_COLLADA_LOADER_ -#endif //! Define _IRR_COMPILE_WITH_CSM_LOADER_ if you want to load Cartography Shop files #define _IRR_COMPILE_WITH_CSM_LOADER_ #ifdef NO_IRR_COMPILE_WITH_CSM_LOADER_ diff --git a/lib/irrlicht/include/irrlicht.h b/lib/irrlicht/include/irrlicht.h index 78415c6bb..9fb0bfc02 100644 --- a/lib/irrlicht/include/irrlicht.h +++ b/lib/irrlicht/include/irrlicht.h @@ -112,7 +112,6 @@ #include "IMeshManipulator.h" #include "IMeshSceneNode.h" #include "IMeshWriter.h" -#include "IColladaMeshWriter.h" #include "IMetaTriangleSelector.h" #include "IOSOperator.h" #include "IParticleSystemSceneNode.h" // also includes all emitters and attractors diff --git a/lib/irrlicht/source/Irrlicht/CColladaFileLoader.cpp b/lib/irrlicht/source/Irrlicht/CColladaFileLoader.cpp deleted file mode 100644 index 650981218..000000000 --- a/lib/irrlicht/source/Irrlicht/CColladaFileLoader.cpp +++ /dev/null @@ -1,2957 +0,0 @@ -// Copyright (C) 2002-2012 Nikolaus Gebhardt -// This file is part of the "Irrlicht Engine". -// For conditions of distribution and use, see copyright notice in irrlicht.h - -#include "IrrCompileConfig.h" -#ifdef _IRR_COMPILE_WITH_COLLADA_LOADER_ - -#include "CColladaFileLoader.h" -#include "os.h" -#include "IXMLReader.h" -#include "IDummyTransformationSceneNode.h" -#include "SAnimatedMesh.h" -#include "fast_atof.h" -#include "quaternion.h" -#include "ILightSceneNode.h" -#include "ICameraSceneNode.h" -#include "IMeshManipulator.h" -#include "IReadFile.h" -#include "IAttributes.h" -#include "IMeshCache.h" -#include "IMeshSceneNode.h" -#include "SMeshBufferLightMap.h" -#include "irrMap.h" - -#ifdef _DEBUG -#define COLLADA_READER_DEBUG -#endif -namespace irr -{ -namespace scene -{ -namespace -{ - // currently supported COLLADA tag names - const core::stringc colladaSectionName = "COLLADA"; - const core::stringc librarySectionName = "library"; - const core::stringc libraryNodesSectionName = "library_nodes"; - const core::stringc libraryGeometriesSectionName = "library_geometries"; - const core::stringc libraryMaterialsSectionName = "library_materials"; - const core::stringc libraryImagesSectionName = "library_images"; - const core::stringc libraryVisualScenesSectionName = "library_visual_scenes"; - const core::stringc libraryCamerasSectionName = "library_cameras"; - const core::stringc libraryLightsSectionName = "library_lights"; - const core::stringc libraryEffectsSectionName = "library_effects"; - const core::stringc assetSectionName = "asset"; - const core::stringc sceneSectionName = "scene"; - const core::stringc visualSceneSectionName = "visual_scene"; - - const core::stringc lightPrefabName = "light"; - const core::stringc cameraPrefabName = "camera"; - const core::stringc materialSectionName = "material"; - const core::stringc geometrySectionName = "geometry"; - const core::stringc imageSectionName = "image"; - const core::stringc textureSectionName = "texture"; - const core::stringc effectSectionName = "effect"; - - const core::stringc pointSectionName = "point"; - const core::stringc directionalSectionName ="directional"; - const core::stringc spotSectionName = "spot"; - const core::stringc ambientSectionName = "ambient"; - const core::stringc meshSectionName = "mesh"; - const core::stringc sourceSectionName = "source"; - const core::stringc arraySectionName = "array"; - const core::stringc floatArraySectionName ="float_array"; - const core::stringc intArraySectionName = "int_array"; - const core::stringc techniqueCommonSectionName = "technique_common"; - const core::stringc accessorSectionName = "accessor"; - const core::stringc verticesSectionName = "vertices"; - const core::stringc inputTagName = "input"; - const core::stringc polylistSectionName = "polylist"; - const core::stringc trianglesSectionName = "triangles"; - const core::stringc polygonsSectionName = "polygons"; - const core::stringc primitivesName = "p"; - const core::stringc vcountName = "vcount"; - - const core::stringc upAxisNodeName = "up_axis"; - const core::stringc nodeSectionName = "node"; - const core::stringc lookatNodeName = "lookat"; - const core::stringc matrixNodeName = "matrix"; - const core::stringc perspectiveNodeName = "perspective"; - const core::stringc rotateNodeName = "rotate"; - const core::stringc scaleNodeName = "scale"; - const core::stringc translateNodeName = "translate"; - const core::stringc skewNodeName = "skew"; - const core::stringc bboxNodeName = "boundingbox"; - const core::stringc minNodeName = "min"; - const core::stringc maxNodeName = "max"; - const core::stringc instanceName = "instance"; - const core::stringc instanceGeometryName = "instance_geometry"; - const core::stringc instanceSceneName = "instance_visual_scene"; - const core::stringc instanceEffectName = "instance_effect"; - const core::stringc instanceMaterialName = "instance_material"; - const core::stringc instanceLightName = "instance_light"; - const core::stringc instanceNodeName = "instance_node"; - const core::stringc bindMaterialName = "bind_material"; - const core::stringc extraNodeName = "extra"; - const core::stringc techniqueNodeName = "technique"; - const core::stringc colorNodeName = "color"; - const core::stringc floatNodeName = "float"; - const core::stringc float2NodeName = "float2"; - const core::stringc float3NodeName = "float3"; - - const core::stringc newParamName = "newparam"; - const core::stringc paramTagName = "param"; - const core::stringc initFromName = "init_from"; - const core::stringc dataName = "data"; - const core::stringc wrapsName = "wrap_s"; - const core::stringc wraptName = "wrap_t"; - const core::stringc minfilterName = "minfilter"; - const core::stringc magfilterName = "magfilter"; - const core::stringc mipfilterName = "mipfilter"; - - const core::stringc textureNodeName = "texture"; - const core::stringc doubleSidedNodeName = "double_sided"; - const core::stringc constantAttenuationNodeName = "constant_attenuation"; - const core::stringc linearAttenuationNodeName = "linear_attenuation"; - const core::stringc quadraticAttenuationNodeName = "quadratic_attenuation"; - const core::stringc falloffAngleNodeName = "falloff_angle"; - const core::stringc falloffExponentNodeName = "falloff_exponent"; - - const core::stringc profileCOMMONSectionName = "profile_COMMON"; - const core::stringc profileCOMMONAttributeName = "COMMON"; - - const char* const inputSemanticNames[] = {"POSITION", "VERTEX", "NORMAL", "TEXCOORD", - "UV", "TANGENT", "IMAGE", "TEXTURE", 0}; - - // We have to read ambient lights like other light types here, so we need a type for it - const video::E_LIGHT_TYPE ELT_AMBIENT = video::E_LIGHT_TYPE(video::ELT_COUNT+1); -} - - //! following class is for holding and creating instances of library - //! objects, named prefabs in this loader. - class CPrefab : public IColladaPrefab - { - public: - - CPrefab(const core::stringc& id) : Id(id) - { - } - - //! creates an instance of this prefab - virtual scene::ISceneNode* addInstance(scene::ISceneNode* parent, - scene::ISceneManager* mgr) - { - // empty implementation - return 0; - } - - //! returns id of this prefab - virtual const core::stringc& getId() - { - return Id; - } - - protected: - - core::stringc Id; - }; - - - //! prefab for a light scene node - class CLightPrefab : public CPrefab - { - public: - - CLightPrefab(const core::stringc& id) : CPrefab(id) - { - #ifdef COLLADA_READER_DEBUG - os::Printer::log("COLLADA: loaded light prefab", Id.c_str(), ELL_DEBUG); - #endif - } - - video::SLight LightData; // publically accessible - - //! creates an instance of this prefab - virtual scene::ISceneNode* addInstance(scene::ISceneNode* parent, - scene::ISceneManager* mgr) - { - #ifdef COLLADA_READER_DEBUG - os::Printer::log("COLLADA: Constructing light instance", Id.c_str(), ELL_DEBUG); - #endif - - if ( LightData.Type == ELT_AMBIENT ) - { - mgr->setAmbientLight( LightData.DiffuseColor ); - return 0; - } - - scene::ILightSceneNode* l = mgr->addLightSceneNode(parent); - if (l) - { - l->setLightData ( LightData ); - l->setName(getId()); - } - return l; - } - }; - - - //! prefab for a mesh scene node - class CGeometryPrefab : public CPrefab - { - public: - - CGeometryPrefab(const core::stringc& id) : CPrefab(id) - { - } - - scene::IMesh* Mesh; - - //! creates an instance of this prefab - virtual scene::ISceneNode* addInstance(scene::ISceneNode* parent, - scene::ISceneManager* mgr) - { - #ifdef COLLADA_READER_DEBUG - os::Printer::log("COLLADA: Constructing mesh instance", Id.c_str(), ELL_DEBUG); - #endif - - scene::ISceneNode* m = mgr->addMeshSceneNode(Mesh, parent); - if (m) - { - m->setName(getId()); -// m->setMaterialFlag(video::EMF_BACK_FACE_CULLING, false); -// m->setDebugDataVisible(scene::EDS_FULL); - } - return m; - } - }; - - - //! prefab for a camera scene node - class CCameraPrefab : public CPrefab - { - public: - - CCameraPrefab(const core::stringc& id) - : CPrefab(id), YFov(core::PI / 2.5f), ZNear(1.0f), ZFar(3000.0f) - { - #ifdef COLLADA_READER_DEBUG - os::Printer::log("COLLADA: loaded camera prefab", Id.c_str(), ELL_DEBUG); - #endif - } - - // publicly accessible data - f32 YFov; - f32 ZNear; - f32 ZFar; - - //! creates an instance of this prefab - virtual scene::ISceneNode* addInstance(scene::ISceneNode* parent, - scene::ISceneManager* mgr) - { - #ifdef COLLADA_READER_DEBUG - os::Printer::log("COLLADA: Constructing camera instance", Id.c_str(), ELL_DEBUG); - #endif - - scene::ICameraSceneNode* c = mgr->addCameraSceneNode(parent); - if (c) - { - c->setFOV(YFov); - c->setNearValue(ZNear); - c->setFarValue(ZFar); - c->setName(getId()); - } - return c; - } - }; - - - //! prefab for a container scene node - //! Collects other prefabs and instantiates them upon instantiation - //! Uses a dummy scene node to return the children as one scene node - class CScenePrefab : public CPrefab - { - public: - CScenePrefab(const core::stringc& id) : CPrefab(id) - { - #ifdef COLLADA_READER_DEBUG - os::Printer::log("COLLADA: loaded scene prefab", Id.c_str(), ELL_DEBUG); - #endif - } - - //! creates an instance of this prefab - virtual scene::ISceneNode* addInstance(scene::ISceneNode* parent, - scene::ISceneManager* mgr) - { - #ifdef COLLADA_READER_DEBUG - os::Printer::log("COLLADA: Constructing scene instance", Id.c_str(), ELL_DEBUG); - #endif - - if (Children.size()==0) - return 0; - - scene::IDummyTransformationSceneNode* s = mgr->addDummyTransformationSceneNode(parent); - if (s) - { - s->setName(getId()); - s->getRelativeTransformationMatrix() = Transformation; - s->updateAbsolutePosition(); - core::stringc t; - for (u32 i=0; i<16; ++i) - { - t+=core::stringc((double)Transformation[i]); - t+=" "; - } - #ifdef COLLADA_READER_DEBUG - os::Printer::log("COLLADA: Transformation", t.c_str(), ELL_DEBUG); - #endif - - for (u32 i=0; iaddInstance(s, mgr); - } - - return s; - } - - core::array Children; - core::matrix4 Transformation; - }; - - -//! Constructor -CColladaFileLoader::CColladaFileLoader(scene::ISceneManager* smgr, - io::IFileSystem* fs) -: SceneManager(smgr), FileSystem(fs), DummyMesh(0), - FirstLoadedMesh(0), LoadedMeshCount(0), CreateInstances(false) -{ - #ifdef _DEBUG - setDebugName("CColladaFileLoader"); - #endif -} - - -//! destructor -CColladaFileLoader::~CColladaFileLoader() -{ - if (DummyMesh) - DummyMesh->drop(); - - if (FirstLoadedMesh) - FirstLoadedMesh->drop(); -} - - -//! Returns true if the file maybe is able to be loaded by this class. -/** This decision should be based only on the file extension (e.g. ".cob") */ -bool CColladaFileLoader::isALoadableFileExtension(const io::path& filename) const -{ - return core::hasFileExtension ( filename, "xml", "dae" ); -} - - -//! creates/loads an animated mesh from the file. -//! \return Pointer to the created mesh. Returns 0 if loading failed. -//! If you no longer need the mesh, you should call IAnimatedMesh::drop(). -//! See IReferenceCounted::drop() for more information. -IAnimatedMesh* CColladaFileLoader::createMesh(io::IReadFile* file) -{ - io::IXMLReaderUTF8* reader = FileSystem->createXMLReaderUTF8(file); - if (!reader) - return 0; - - CurrentlyLoadingMesh = file->getFileName(); - CreateInstances = SceneManager->getParameters()->getAttributeAsBool( - scene::COLLADA_CREATE_SCENE_INSTANCES); - Version = 0; - FlipAxis = false; - - // read until COLLADA section, skip other parts - - while(reader->read()) - { - if (reader->getNodeType() == io::EXN_ELEMENT) - { - if (colladaSectionName == reader->getNodeName()) - readColladaSection(reader); - else - skipSection(reader, true); // unknown section - } - } - - reader->drop(); - if (!Version) - return 0; - - // because this loader loads and creates a complete scene instead of - // a single mesh, return an empty dummy mesh to make the scene manager - // know that everything went well. - if (!DummyMesh) - DummyMesh = new SAnimatedMesh(); - scene::IAnimatedMesh* returnMesh = DummyMesh; - - if (Version < 10400) - instantiateNode(SceneManager->getRootSceneNode()); - - // add the first loaded mesh into the mesh cache too, if more than one - // meshes have been loaded from the file - if (LoadedMeshCount>1 && FirstLoadedMesh) - { - os::Printer::log("Added COLLADA mesh", FirstLoadedMeshName.c_str()); - SceneManager->getMeshCache()->addMesh(FirstLoadedMeshName.c_str(), FirstLoadedMesh); - } - - // clean up temporary loaded data - clearData(); - - returnMesh->grab(); // store until this loader is destroyed - - DummyMesh->drop(); - DummyMesh = 0; - - if (FirstLoadedMesh) - FirstLoadedMesh->drop(); - FirstLoadedMesh = 0; - LoadedMeshCount = 0; - - return returnMesh; -} - - -//! skips an (unknown) section in the collada document -void CColladaFileLoader::skipSection(io::IXMLReaderUTF8* reader, bool reportSkipping) -{ - #ifndef COLLADA_READER_DEBUG - if (reportSkipping) // always report in COLLADA_READER_DEBUG mode - #endif - os::Printer::log("COLLADA skipping section", core::stringc(reader->getNodeName()).c_str(), ELL_DEBUG); - - // skip if this element is empty anyway. - if (reader->isEmptyElement()) - return; - - // read until we've reached the last element in this section - u32 tagCounter = 1; - - while(tagCounter && reader->read()) - { - if (reader->getNodeType() == io::EXN_ELEMENT && - !reader->isEmptyElement()) - { - #ifdef COLLADA_READER_DEBUG - if (reportSkipping) - os::Printer::log("Skipping COLLADA unknown element", core::stringc(reader->getNodeName()).c_str(), ELL_DEBUG); - #endif - - ++tagCounter; - } - else - if (reader->getNodeType() == io::EXN_ELEMENT_END) - --tagCounter; - } -} - - -//! reads the section and its content -void CColladaFileLoader::readColladaSection(io::IXMLReaderUTF8* reader) -{ - if (reader->isEmptyElement()) - return; - - // todo: patch level needs to be handled - const f32 version = core::fast_atof(core::stringc(reader->getAttributeValue("version")).c_str()); - Version = core::floor32(version)*10000+core::round32(core::fract(version)*1000.0f); - // Version 1.4 can be checked for by if (Version >= 10400) - - while(reader->read()) - if (reader->getNodeType() == io::EXN_ELEMENT) - { - if (assetSectionName == reader->getNodeName()) - readAssetSection(reader); - else - if (librarySectionName == reader->getNodeName()) - readLibrarySection(reader); - else - if (libraryNodesSectionName == reader->getNodeName()) - readLibrarySection(reader); - else - if (libraryGeometriesSectionName == reader->getNodeName()) - readLibrarySection(reader); - else - if (libraryMaterialsSectionName == reader->getNodeName()) - readLibrarySection(reader); - else - if (libraryEffectsSectionName == reader->getNodeName()) - readLibrarySection(reader); - else - if (libraryImagesSectionName == reader->getNodeName()) - readLibrarySection(reader); - else - if (libraryCamerasSectionName == reader->getNodeName()) - readLibrarySection(reader); - else - if (libraryLightsSectionName == reader->getNodeName()) - readLibrarySection(reader); - else - if (libraryVisualScenesSectionName == reader->getNodeName()) - readVisualScene(reader); - else - if (assetSectionName == reader->getNodeName()) - readAssetSection(reader); - else - if (sceneSectionName == reader->getNodeName()) - readSceneSection(reader); - else - { - os::Printer::log("COLLADA loader warning: Wrong tag usage found", reader->getNodeName(), ELL_WARNING); - skipSection(reader, true); // unknown section - } - } -} - - -//! reads a section and its content -void CColladaFileLoader::readLibrarySection(io::IXMLReaderUTF8* reader) -{ - #ifdef COLLADA_READER_DEBUG - os::Printer::log("COLLADA reading library", ELL_DEBUG); - #endif - - if (reader->isEmptyElement()) - return; - - while(reader->read()) - { - if (reader->getNodeType() == io::EXN_ELEMENT) - { - // animation section tbd - if (cameraPrefabName == reader->getNodeName()) - readCameraPrefab(reader); - else - // code section tbd - // controller section tbd - if (geometrySectionName == reader->getNodeName()) - readGeometry(reader); - else - if (imageSectionName == reader->getNodeName()) - readImage(reader); - else - if (lightPrefabName == reader->getNodeName()) - readLightPrefab(reader); - else - if (materialSectionName == reader->getNodeName()) - readMaterial(reader); - else - if (nodeSectionName == reader->getNodeName()) - { - CScenePrefab p(""); - - readNodeSection(reader, SceneManager->getRootSceneNode(), &p); - } - else - if (effectSectionName == reader->getNodeName()) - readEffect(reader); - else - // program section tbd - if (textureSectionName == reader->getNodeName()) - readTexture(reader); - else - skipSection(reader, true); // unknown section, not all allowed supported yet - } - else - if (reader->getNodeType() == io::EXN_ELEMENT_END) - { - if (librarySectionName == reader->getNodeName()) - break; // end reading. - if (libraryNodesSectionName == reader->getNodeName()) - break; // end reading. - if (libraryGeometriesSectionName == reader->getNodeName()) - break; // end reading. - if (libraryMaterialsSectionName == reader->getNodeName()) - break; // end reading. - if (libraryEffectsSectionName == reader->getNodeName()) - break; // end reading. - if (libraryImagesSectionName == reader->getNodeName()) - break; // end reading. - if (libraryLightsSectionName == reader->getNodeName()) - break; // end reading. - if (libraryCamerasSectionName == reader->getNodeName()) - break; // end reading. - } - } -} - - -//! reads a element and stores it as a prefab -void CColladaFileLoader::readVisualScene(io::IXMLReaderUTF8* reader) -{ - CScenePrefab* p = 0; - while(reader->read()) - { - if (reader->getNodeType() == io::EXN_ELEMENT) - { - if (visualSceneSectionName == reader->getNodeName()) - p = new CScenePrefab(readId(reader)); - else - if (p && nodeSectionName == reader->getNodeName()) // as a child of visual_scene - readNodeSection(reader, SceneManager->getRootSceneNode(), p); - else - if (assetSectionName == reader->getNodeName()) - readAssetSection(reader); - else - if (extraNodeName == reader->getNodeName()) - skipSection(reader, false); // ignore all other sections - else - { - os::Printer::log("COLLADA loader warning: Wrong tag usage found", reader->getNodeName(), ELL_WARNING); - skipSection(reader, true); // ignore all other sections - } - } - else - if (reader->getNodeType() == io::EXN_ELEMENT_END) - { - if (libraryVisualScenesSectionName == reader->getNodeName()) - return; - else - if ((visualSceneSectionName == reader->getNodeName()) && p) - { - Prefabs.push_back(p); - p = 0; - } - } - } -} - - -//! reads a section and its content -void CColladaFileLoader::readSceneSection(io::IXMLReaderUTF8* reader) -{ - #ifdef COLLADA_READER_DEBUG - os::Printer::log("COLLADA reading scene", ELL_DEBUG); - #endif - - if (reader->isEmptyElement()) - return; - - // read the scene - - core::matrix4 transform; // transformation of this node - core::aabbox3df bbox; - scene::IDummyTransformationSceneNode* node = 0; - - while(reader->read()) - { - if (reader->getNodeType() == io::EXN_ELEMENT) - { - if (lookatNodeName == reader->getNodeName()) - transform *= readLookAtNode(reader); - else - if (matrixNodeName == reader->getNodeName()) - transform *= readMatrixNode(reader); - else - if (perspectiveNodeName == reader->getNodeName()) - transform *= readPerspectiveNode(reader); - else - if (rotateNodeName == reader->getNodeName()) - transform *= readRotateNode(reader); - else - if (scaleNodeName == reader->getNodeName()) - transform *= readScaleNode(reader); - else - if (skewNodeName == reader->getNodeName()) - transform *= readSkewNode(reader); - else - if (translateNodeName == reader->getNodeName()) - transform *= readTranslateNode(reader); - else - if (bboxNodeName == reader->getNodeName()) - readBboxNode(reader, bbox); - else - if (nodeSectionName == reader->getNodeName()) - { - // create dummy node if there is none yet. - if (!node) - node = SceneManager->addDummyTransformationSceneNode(SceneManager->getRootSceneNode()); - - readNodeSection(reader, node); - } - else - if ((instanceSceneName == reader->getNodeName())) - readInstanceNode(reader, SceneManager->getRootSceneNode(), 0, 0,instanceSceneName); - else - if (extraNodeName == reader->getNodeName()) - skipSection(reader, false); - else - { - os::Printer::log("COLLADA loader warning: Wrong tag usage found", reader->getNodeName(), ELL_WARNING); - skipSection(reader, true); // ignore all other sections - } - } - else - if ((reader->getNodeType() == io::EXN_ELEMENT_END) && - (sceneSectionName == reader->getNodeName())) - return; - } - if (node) - node->getRelativeTransformationMatrix() = transform; -} - - -//! reads a section and its content -void CColladaFileLoader::readAssetSection(io::IXMLReaderUTF8* reader) -{ - #ifdef COLLADA_READER_DEBUG - os::Printer::log("COLLADA reading asset", ELL_DEBUG); - #endif - - if (reader->isEmptyElement()) - return; - - while(reader->read()) - { - if (reader->getNodeType() == io::EXN_ELEMENT) - { - if (upAxisNodeName == reader->getNodeName()) - { - reader->read(); - FlipAxis = (core::stringc("Z_UP") == reader->getNodeData()); - } - } - else - if ((reader->getNodeType() == io::EXN_ELEMENT_END) && - (assetSectionName == reader->getNodeName())) - return; - } -} - - -//! reads a section and its content -void CColladaFileLoader::readNodeSection(io::IXMLReaderUTF8* reader, scene::ISceneNode* parent, CScenePrefab* p) -{ - if (reader->isEmptyElement()) - { - return; - #ifdef COLLADA_READER_DEBUG - os::Printer::log("COLLADA reading empty node", ELL_DEBUG); - #endif - } - - core::stringc name = readId(reader); - #ifdef COLLADA_READER_DEBUG - os::Printer::log("COLLADA reading node", name, ELL_DEBUG); - #endif - - core::matrix4 transform; // transformation of this node - core::aabbox3df bbox; - scene::ISceneNode* node = 0; // instance - CScenePrefab* nodeprefab = 0; // prefab for library_nodes usage - - if (p) - { - nodeprefab = new CScenePrefab(readId(reader)); - p->Children.push_back(nodeprefab); - Prefabs.push_back(nodeprefab); // in order to delete them later on - } - - // read the node - - while(reader->read()) - { - if (reader->getNodeType() == io::EXN_ELEMENT) - { - if (assetSectionName == reader->getNodeName()) - readAssetSection(reader); - else - if (lookatNodeName == reader->getNodeName()) - transform *= readLookAtNode(reader); - else - if (matrixNodeName == reader->getNodeName()) - transform *= readMatrixNode(reader); - else - if (perspectiveNodeName == reader->getNodeName()) - transform *= readPerspectiveNode(reader); - else - if (rotateNodeName == reader->getNodeName()) - transform *= readRotateNode(reader); - else - if (scaleNodeName == reader->getNodeName()) - transform *= readScaleNode(reader); - else - if (skewNodeName == reader->getNodeName()) - transform *= readSkewNode(reader); - else - if (translateNodeName == reader->getNodeName()) - transform *= readTranslateNode(reader); - else - if (bboxNodeName == reader->getNodeName()) - readBboxNode(reader, bbox); - else - if ((instanceName == reader->getNodeName()) || - (instanceNodeName == reader->getNodeName()) || - (instanceGeometryName == reader->getNodeName()) || - (instanceLightName == reader->getNodeName())) - { - scene::ISceneNode* newnode = 0; - readInstanceNode(reader, parent, &newnode, nodeprefab, reader->getNodeName()); - - if (node && newnode) - { - // move children from dummy to new node - ISceneNodeList::ConstIterator it = node->getChildren().begin(); - for (; it != node->getChildren().end(); it = node->getChildren().begin()) - (*it)->setParent(newnode); - - // remove previous dummy node - node->remove(); - node = newnode; - } - } - else - if (nodeSectionName == reader->getNodeName()) - { - // create dummy node if there is none yet. - if (CreateInstances && !node) - { - scene::IDummyTransformationSceneNode* dummy = - SceneManager->addDummyTransformationSceneNode(parent); - dummy->getRelativeTransformationMatrix() = transform; - node = dummy; - } - else - node = parent; - - // read and add child - readNodeSection(reader, node, nodeprefab); - } - else - if (extraNodeName == reader->getNodeName()) - skipSection(reader, false); - else - skipSection(reader, true); // ignore all other sections - - } // end if node - else - if (reader->getNodeType() == io::EXN_ELEMENT_END) - { - if (nodeSectionName == reader->getNodeName()) - break; - } - } - - if (nodeprefab) - nodeprefab->Transformation = transform; - else - if (node) - { - // set transformation correctly into node. - node->setPosition(transform.getTranslation()); - node->setRotation(transform.getRotationDegrees()); - node->setScale(transform.getScale()); - node->updateAbsolutePosition(); - - node->setName(name); - } -} - - -//! reads a element and its content and creates a matrix from it -core::matrix4 CColladaFileLoader::readLookAtNode(io::IXMLReaderUTF8* reader) -{ - core::matrix4 mat; - if (reader->isEmptyElement()) - return mat; - - #ifdef COLLADA_READER_DEBUG - os::Printer::log("COLLADA reading look at node", ELL_DEBUG); - #endif - - f32 floats[9]; - readFloatsInsideElement(reader, floats, 9); - - mat.buildCameraLookAtMatrixLH( - core::vector3df(floats[0], floats[1], floats[2]), - core::vector3df(floats[3], floats[4], floats[5]), - core::vector3df(floats[6], floats[7], floats[8])); - - return mat; -} - - -//! reads a element and its content and creates a matrix from it -core::matrix4 CColladaFileLoader::readSkewNode(io::IXMLReaderUTF8* reader) -{ - #ifdef COLLADA_READER_DEBUG - os::Printer::log("COLLADA reading skew node", ELL_DEBUG); - #endif - - core::matrix4 mat; - if (reader->isEmptyElement()) - return mat; - - f32 floats[7]; // angle rotation-axis translation-axis - readFloatsInsideElement(reader, floats, 7); - - // build skew matrix from these 7 floats - core::quaternion q; - q.fromAngleAxis(floats[0]*core::DEGTORAD, core::vector3df(floats[1], floats[2], floats[3])); - mat = q.getMatrix(); - - if (floats[4]==1.f) // along x-axis - { - mat[4]=0.f; - mat[6]=0.f; - mat[8]=0.f; - mat[9]=0.f; - } - else - if (floats[5]==1.f) // along y-axis - { - mat[1]=0.f; - mat[2]=0.f; - mat[8]=0.f; - mat[9]=0.f; - } - else - if (floats[6]==1.f) // along z-axis - { - mat[1]=0.f; - mat[2]=0.f; - mat[4]=0.f; - mat[6]=0.f; - } - - return mat; -} - - -//! reads a element and its content and stores it in bbox -void CColladaFileLoader::readBboxNode(io::IXMLReaderUTF8* reader, - core::aabbox3df& bbox) -{ - #ifdef COLLADA_READER_DEBUG - os::Printer::log("COLLADA reading boundingbox node", ELL_DEBUG); - #endif - - bbox.reset(core::aabbox3df()); - - if (reader->isEmptyElement()) - return; - - f32 floats[3]; - - while(reader->read()) - { - if (reader->getNodeType() == io::EXN_ELEMENT) - { - if (minNodeName == reader->getNodeName()) - { - readFloatsInsideElement(reader, floats, 3); - bbox.MinEdge.set(floats[0], floats[1], floats[2]); - } - else - if (maxNodeName == reader->getNodeName()) - { - readFloatsInsideElement(reader, floats, 3); - bbox.MaxEdge.set(floats[0], floats[1], floats[2]); - } - else - skipSection(reader, true); // ignore all other sections - } - else - if (reader->getNodeType() == io::EXN_ELEMENT_END) - { - if (bboxNodeName == reader->getNodeName()) - break; - } - } -} - - -//! reads a element and its content and creates a matrix from it -core::matrix4 CColladaFileLoader::readMatrixNode(io::IXMLReaderUTF8* reader) -{ - #ifdef COLLADA_READER_DEBUG - os::Printer::log("COLLADA reading matrix node", ELL_DEBUG); - #endif - - core::matrix4 mat; - if (reader->isEmptyElement()) - return mat; - - readFloatsInsideElement(reader, mat.pointer(), 16); - // put translation into the correct place - if (FlipAxis) - { - core::matrix4 mat2(mat, core::matrix4::EM4CONST_TRANSPOSED); - mat2[1]=mat[8]; - mat2[2]=mat[4]; - mat2[4]=mat[2]; - mat2[5]=mat[10]; - mat2[6]=mat[6]; - mat2[8]=mat[1]; - mat2[9]=mat[9]; - mat2[10]=mat[5]; - mat2[12]=mat[3]; - mat2[13]=mat[11]; - mat2[14]=mat[7]; - return mat2; - } - else - return core::matrix4(mat, core::matrix4::EM4CONST_TRANSPOSED); -} - - -//! reads a element and its content and creates a matrix from it -core::matrix4 CColladaFileLoader::readPerspectiveNode(io::IXMLReaderUTF8* reader) -{ - #ifdef COLLADA_READER_DEBUG - os::Printer::log("COLLADA reading perspective node", ELL_DEBUG); - #endif - - core::matrix4 mat; - if (reader->isEmptyElement()) - return mat; - - f32 floats[1]; - readFloatsInsideElement(reader, floats, 1); - - // TODO: build perspecitve matrix from this float - - os::Printer::log("COLLADA loader warning: not implemented yet.", ELL_WARNING); - - return mat; -} - - -//! reads a element and its content and creates a matrix from it -core::matrix4 CColladaFileLoader::readRotateNode(io::IXMLReaderUTF8* reader) -{ - #ifdef COLLADA_READER_DEBUG - os::Printer::log("COLLADA reading rotate node", ELL_DEBUG); - #endif - - core::matrix4 mat; - if (reader->isEmptyElement()) - return mat; - - f32 floats[4]; - readFloatsInsideElement(reader, floats, 4); - - if (!core::iszero(floats[3])) - { - core::quaternion q; - if (FlipAxis) - q.fromAngleAxis(floats[3]*core::DEGTORAD, core::vector3df(floats[0], floats[2], floats[1])); - else - q.fromAngleAxis(floats[3]*core::DEGTORAD, core::vector3df(floats[0], floats[1], floats[2])); - return q.getMatrix(); - } - else - return core::IdentityMatrix; -} - - -//! reads a element and its content and creates a matrix from it -core::matrix4 CColladaFileLoader::readScaleNode(io::IXMLReaderUTF8* reader) -{ - #ifdef COLLADA_READER_DEBUG - os::Printer::log("COLLADA reading scale node", ELL_DEBUG); - #endif - - core::matrix4 mat; - if (reader->isEmptyElement()) - return mat; - - f32 floats[3]; - readFloatsInsideElement(reader, floats, 3); - - if (FlipAxis) - mat.setScale(core::vector3df(floats[0], floats[2], floats[1])); - else - mat.setScale(core::vector3df(floats[0], floats[1], floats[2])); - - return mat; -} - - -//! reads a element and its content and creates a matrix from it -core::matrix4 CColladaFileLoader::readTranslateNode(io::IXMLReaderUTF8* reader) -{ - #ifdef COLLADA_READER_DEBUG - os::Printer::log("COLLADA reading translate node", ELL_DEBUG); - #endif - - core::matrix4 mat; - if (reader->isEmptyElement()) - return mat; - - f32 floats[3]; - readFloatsInsideElement(reader, floats, 3); - - if (FlipAxis) - mat.setTranslation(core::vector3df(floats[0], floats[2], floats[1])); - else - mat.setTranslation(core::vector3df(floats[0], floats[1], floats[2])); - - return mat; -} - - -//! reads any kind of node -void CColladaFileLoader::readInstanceNode(io::IXMLReaderUTF8* reader, - scene::ISceneNode* parent, scene::ISceneNode** outNode, - CScenePrefab* p, const core::stringc& type) -{ - // find prefab of the specified id - core::stringc url = reader->getAttributeValue("url"); - uriToId(url); - - #ifdef COLLADA_READER_DEBUG - os::Printer::log("COLLADA reading instance", url, ELL_DEBUG); - #endif - - if (!reader->isEmptyElement()) - { - while(reader->read()) - { - if (reader->getNodeType() == io::EXN_ELEMENT) - { - if (bindMaterialName == reader->getNodeName()) - readBindMaterialSection(reader,url); - else - if (extraNodeName == reader->getNodeName()) - skipSection(reader, false); - } - else - if (reader->getNodeType() == io::EXN_ELEMENT_END) - break; - } - } - instantiateNode(parent, outNode, p, url, type); -} - - -void CColladaFileLoader::instantiateNode(scene::ISceneNode* parent, - scene::ISceneNode** outNode, CScenePrefab* p, const core::stringc& url, - const core::stringc& type) -{ - #ifdef COLLADA_READER_DEBUG - os::Printer::log("COLLADA instantiate node", ELL_DEBUG); - #endif - - for (u32 i=0; igetId()) - { - if (p) - p->Children.push_back(Prefabs[i]); - else - if (CreateInstances) - { - scene::ISceneNode * newNode - = Prefabs[i]->addInstance(parent, SceneManager); - if (outNode) - { - *outNode = newNode; - if (*outNode) - (*outNode)->setName(url); - } - } - return; - } - } - if (p) - { - if (instanceGeometryName==type) - { - Prefabs.push_back(new CGeometryPrefab(url)); - p->Children.push_back(Prefabs.getLast()); - } - } -} - - -//! reads a element and stores it as prefab -void CColladaFileLoader::readCameraPrefab(io::IXMLReaderUTF8* reader) -{ - #ifdef COLLADA_READER_DEBUG - os::Printer::log("COLLADA reading camera prefab", ELL_DEBUG); - #endif - - CCameraPrefab* prefab = new CCameraPrefab(readId(reader)); - - if (!reader->isEmptyElement()) - { - // read techniques optics and imager (the latter is completely ignored, though) - readColladaParameters(reader, cameraPrefabName); - - SColladaParam* p; - - // XFOV not yet supported - p = getColladaParameter(ECPN_YFOV); - if (p && p->Type == ECPT_FLOAT) - prefab->YFov = p->Floats[0]; - - p = getColladaParameter(ECPN_ZNEAR); - if (p && p->Type == ECPT_FLOAT) - prefab->ZNear = p->Floats[0]; - - p = getColladaParameter(ECPN_ZFAR); - if (p && p->Type == ECPT_FLOAT) - prefab->ZFar = p->Floats[0]; - // orthographic camera uses LEFT, RIGHT, TOP, and BOTTOM - } - - Prefabs.push_back(prefab); -} - - -//! reads a element and stores it in the image section -void CColladaFileLoader::readImage(io::IXMLReaderUTF8* reader) -{ - // add image to list of loaded images. - Images.push_back(SColladaImage()); - SColladaImage& image=Images.getLast(); - - image.Id = readId(reader); - #ifdef COLLADA_READER_DEBUG - os::Printer::log("COLLADA reading image", core::stringc(image.Id), ELL_DEBUG); - #endif - image.Dimension.Height = (u32)reader->getAttributeValueAsInt("height"); - image.Dimension.Width = (u32)reader->getAttributeValueAsInt("width"); - - if (Version >= 10400) // start with 1.4 - { - while(reader->read()) - { - if (reader->getNodeType() == io::EXN_ELEMENT) - { - if (assetSectionName == reader->getNodeName()) - skipSection(reader, false); - else - if (initFromName == reader->getNodeName()) - { - reader->read(); - image.Source = reader->getNodeData(); - image.Source.trim(); - image.SourceIsFilename=true; - } - else - if (dataName == reader->getNodeName()) - { - reader->read(); - image.Source = reader->getNodeData(); - image.Source.trim(); - image.SourceIsFilename=false; - } - else - if (extraNodeName == reader->getNodeName()) - skipSection(reader, false); - } - else - if (reader->getNodeType() == io::EXN_ELEMENT_END) - { - if (initFromName == reader->getNodeName()) - return; - } - } - } - else - { - image.Source = reader->getAttributeValue("source"); - image.Source.trim(); - image.SourceIsFilename=false; - } -} - - -//! reads a element and stores it in the texture section -void CColladaFileLoader::readTexture(io::IXMLReaderUTF8* reader) -{ - // add texture to list of loaded textures. - Textures.push_back(SColladaTexture()); - SColladaTexture& texture=Textures.getLast(); - - texture.Id = readId(reader); - #ifdef COLLADA_READER_DEBUG - os::Printer::log("COLLADA reading texture", core::stringc(texture.Id), ELL_DEBUG); - #endif - - if (!reader->isEmptyElement()) - { - readColladaInputs(reader, textureSectionName); - SColladaInput* input = getColladaInput(ECIS_IMAGE); - if (input) - { - const core::stringc imageName = input->Source; - texture.Texture = getTextureFromImage(imageName, NULL); - } - } -} - - -//! reads a element and stores it in the material section -void CColladaFileLoader::readMaterial(io::IXMLReaderUTF8* reader) -{ - // add material to list of loaded materials. - Materials.push_back(SColladaMaterial()); - - SColladaMaterial& material = Materials.getLast(); - material.Id = readId(reader); - #ifdef COLLADA_READER_DEBUG - os::Printer::log("COLLADA reading material", core::stringc(material.Id), ELL_DEBUG); - #endif - - if (Version >= 10400) - { - while(reader->read()) - { - if (reader->getNodeType() == io::EXN_ELEMENT && - instanceEffectName == reader->getNodeName()) - { - material.InstanceEffectId = reader->getAttributeValue("url"); - uriToId(material.InstanceEffectId); - } - else - if (reader->getNodeType() == io::EXN_ELEMENT_END && - materialSectionName == reader->getNodeName()) - { - break; - } - } // end while reader->read(); - } - else - { - if (!reader->isEmptyElement()) - { - readColladaInputs(reader, materialSectionName); - SColladaInput* input = getColladaInput(ECIS_TEXTURE); - if (input) - { - core::stringc textureName = input->Source; - uriToId(textureName); - for (u32 i=0; iType == ECPT_FLOAT3) - material.Mat.AmbientColor = video::SColorf(p->Floats[0],p->Floats[1],p->Floats[2]).toSColor(); - p = getColladaParameter(ECPN_DIFFUSE); - if (p && p->Type == ECPT_FLOAT3) - material.Mat.DiffuseColor = video::SColorf(p->Floats[0],p->Floats[1],p->Floats[2]).toSColor(); - p = getColladaParameter(ECPN_SPECULAR); - if (p && p->Type == ECPT_FLOAT3) - material.Mat.DiffuseColor = video::SColorf(p->Floats[0],p->Floats[1],p->Floats[2]).toSColor(); - p = getColladaParameter(ECPN_SHININESS); - if (p && p->Type == ECPT_FLOAT) - material.Mat.Shininess = p->Floats[0]; -#endif - } - } -} - -void CColladaFileLoader::readEffect(io::IXMLReaderUTF8* reader, SColladaEffect * effect) -{ - static const core::stringc constantNode("constant"); - static const core::stringc lambertNode("lambert"); - static const core::stringc phongNode("phong"); - static const core::stringc blinnNode("blinn"); - static const core::stringc emissionNode("emission"); - static const core::stringc ambientNode("ambient"); - static const core::stringc diffuseNode("diffuse"); - static const core::stringc specularNode("specular"); - static const core::stringc shininessNode("shininess"); - static const core::stringc reflectiveNode("reflective"); - static const core::stringc reflectivityNode("reflectivity"); - static const core::stringc transparentNode("transparent"); - static const core::stringc transparencyNode("transparency"); - static const core::stringc indexOfRefractionNode("index_of_refraction"); - - if (!effect) - { - Effects.push_back(SColladaEffect()); - effect = &Effects.getLast(); - effect->Parameters = new io::CAttributes(); - effect->Id = readId(reader); - effect->Transparency = 1.f; - effect->Mat.Lighting=true; - effect->Mat.NormalizeNormals=true; - #ifdef COLLADA_READER_DEBUG - os::Printer::log("COLLADA reading effect", core::stringc(effect->Id), ELL_DEBUG); - #endif - } - while(reader->read()) - { - if (reader->getNodeType() == io::EXN_ELEMENT) - { - // first come the tags we descend, but ignore the top-levels - if (!reader->isEmptyElement() && ((profileCOMMONSectionName == reader->getNodeName()) || - (techniqueNodeName == reader->getNodeName()))) - readEffect(reader,effect); - else - if (newParamName == reader->getNodeName()) - readParameter(reader, effect->Parameters); - else - // these are the actual materials inside technique - if (constantNode == reader->getNodeName() || - lambertNode == reader->getNodeName() || - phongNode == reader->getNodeName() || - blinnNode == reader->getNodeName()) - { - #ifdef COLLADA_READER_DEBUG - os::Printer::log("COLLADA reading effect part", reader->getNodeName(), ELL_DEBUG); - #endif - effect->Mat.setFlag(irr::video::EMF_GOURAUD_SHADING, - phongNode == reader->getNodeName() || - blinnNode == reader->getNodeName()); - while(reader->read()) - { - if (reader->getNodeType() == io::EXN_ELEMENT) - { - const core::stringc node = reader->getNodeName(); - if (emissionNode == node || ambientNode == node || - diffuseNode == node || specularNode == node || - reflectiveNode == node || transparentNode == node ) - { - // color or texture types - while(reader->read()) - { - if (reader->getNodeType() == io::EXN_ELEMENT && - colorNodeName == reader->getNodeName()) - { - const video::SColorf colorf = readColorNode(reader); - const video::SColor color = colorf.toSColor(); - if (emissionNode == node) - effect->Mat.EmissiveColor = color; - else - if (ambientNode == node) - effect->Mat.AmbientColor = color; - else - if (diffuseNode == node) - effect->Mat.DiffuseColor = color; - else - if (specularNode == node) - effect->Mat.SpecularColor = color; - else - if (transparentNode == node) - effect->Transparency = colorf.getAlpha(); - } - else - if (reader->getNodeType() == io::EXN_ELEMENT && - textureNodeName == reader->getNodeName()) - { - effect->Textures.push_back(reader->getAttributeValue("texture")); - break; - } - else - if (reader->getNodeType() == io::EXN_ELEMENT) - skipSection(reader, false); - else - if (reader->getNodeType() == io::EXN_ELEMENT_END && - node == reader->getNodeName()) - break; - } - } - else - if (shininessNode == node || reflectivityNode == node || - transparencyNode == node || indexOfRefractionNode == node ) - { - // float or param types - while(reader->read()) - { - if (reader->getNodeType() == io::EXN_ELEMENT && - floatNodeName == reader->getNodeName()) - { - f32 f = readFloatNode(reader); - if (shininessNode == node) - effect->Mat.Shininess = f; - else - if (transparencyNode == node) - effect->Transparency *= f; - } - else - if (reader->getNodeType() == io::EXN_ELEMENT) - skipSection(reader, false); - else - if (reader->getNodeType() == io::EXN_ELEMENT_END && - node == reader->getNodeName()) - break; - } - } - else - skipSection(reader, true); // ignore all other nodes - } - else - if (reader->getNodeType() == io::EXN_ELEMENT_END && ( - constantNode == reader->getNodeName() || - lambertNode == reader->getNodeName() || - phongNode == reader->getNodeName() || - blinnNode == reader->getNodeName() - )) - break; - } - } - else - if (!reader->isEmptyElement() && (extraNodeName == reader->getNodeName())) - readEffect(reader,effect); - else - if (doubleSidedNodeName == reader->getNodeName()) - { - // read the GoogleEarth extra flag for double sided polys - s32 doubleSided = 0; - readIntsInsideElement(reader,&doubleSided,1); - if (doubleSided) - { - #ifdef COLLADA_READER_DEBUG - os::Printer::log("Setting double sided flag for effect.", ELL_DEBUG); - #endif - - effect->Mat.setFlag(irr::video::EMF_BACK_FACE_CULLING,false); - } - } - else - skipSection(reader, true); // ignore all other sections - } - else - if (reader->getNodeType() == io::EXN_ELEMENT_END) - { - if (effectSectionName == reader->getNodeName()) - break; - else - if (profileCOMMONSectionName == reader->getNodeName()) - break; - else - if (techniqueNodeName == reader->getNodeName()) - break; - else - if (extraNodeName == reader->getNodeName()) - break; - } - } - - if (effect->Mat.AmbientColor == video::SColor(0) && - effect->Mat.DiffuseColor != video::SColor(0)) - effect->Mat.AmbientColor = effect->Mat.DiffuseColor; - if (effect->Mat.DiffuseColor == video::SColor(0) && - effect->Mat.AmbientColor != video::SColor(0)) - effect->Mat.DiffuseColor = effect->Mat.AmbientColor; - if ((effect->Transparency != 0.0f) && (effect->Transparency != 1.0f)) - { - effect->Mat.MaterialType = irr::video::EMT_TRANSPARENT_VERTEX_ALPHA; - effect->Mat.ZWriteEnable = false; - } - - video::E_TEXTURE_CLAMP twu = video::ETC_REPEAT; - s32 idx = effect->Parameters->findAttribute(wrapsName.c_str()); - if ( idx >= 0 ) - twu = (video::E_TEXTURE_CLAMP)(effect->Parameters->getAttributeAsInt(idx)); - video::E_TEXTURE_CLAMP twv = video::ETC_REPEAT; - idx = effect->Parameters->findAttribute(wraptName.c_str()); - if ( idx >= 0 ) - twv = (video::E_TEXTURE_CLAMP)(effect->Parameters->getAttributeAsInt(idx)); - - for (u32 i=0; iMat.TextureLayer[i].TextureWrapU = twu; - effect->Mat.TextureLayer[i].TextureWrapV = twv; - } - - effect->Mat.setFlag(video::EMF_BILINEAR_FILTER, effect->Parameters->getAttributeAsBool("bilinear")); - effect->Mat.setFlag(video::EMF_TRILINEAR_FILTER, effect->Parameters->getAttributeAsBool("trilinear")); - effect->Mat.setFlag(video::EMF_ANISOTROPIC_FILTER, effect->Parameters->getAttributeAsBool("anisotropic")); -} - - -const SColladaMaterial* CColladaFileLoader::findMaterial(const core::stringc& materialName) -{ - #ifdef COLLADA_READER_DEBUG - os::Printer::log("COLLADA find material", materialName, ELL_DEBUG); - #endif - - // do a quick lookup in the materials - SColladaMaterial matToFind; - matToFind.Id = materialName; - s32 mat = Materials.binary_search(matToFind); - if (mat == -1) - return 0; - // instantiate the material effect if needed - if (Materials[mat].InstanceEffectId.size() != 0) - { - // do a quick lookup in the effects - SColladaEffect effectToFind; - effectToFind.Id = Materials[mat].InstanceEffectId; - s32 effect = Effects.binary_search(effectToFind); - if (effect != -1) - { - // found the effect, instantiate by copying into the material - Materials[mat].Mat = Effects[effect].Mat; - if (Effects[effect].Textures.size()) - Materials[mat].Mat.setTexture(0, getTextureFromImage(Effects[effect].Textures[0], &(Effects[effect]))); - Materials[mat].Transparency = Effects[effect].Transparency; - // and indicate the material is instantiated by removing the effect ref - Materials[mat].InstanceEffectId = ""; - } - else - return 0; - } - return &Materials[mat]; -} - - -void CColladaFileLoader::readBindMaterialSection(io::IXMLReaderUTF8* reader, const core::stringc & id) -{ - #ifdef COLLADA_READER_DEBUG - os::Printer::log("COLLADA reading bind material", ELL_DEBUG); - #endif - - while(reader->read()) - { - if (reader->getNodeType() == io::EXN_ELEMENT) - { - if (instanceMaterialName == reader->getNodeName()) - { - // the symbol to retarget, and the target material - core::stringc meshbufferReference = reader->getAttributeValue("symbol"); - if (meshbufferReference.size()==0) - continue; - core::stringc target = reader->getAttributeValue("target"); - uriToId(target); - if (target.size()==0) - continue; - const SColladaMaterial * material = findMaterial(target); - if (!material) - continue; - // bind any pending materials for this node - meshbufferReference = id+"/"+meshbufferReference; -#ifdef COLLADA_READER_DEBUG - os::Printer::log((core::stringc("Material binding: ")+meshbufferReference+" "+target).c_str(), ELL_DEBUG); -#endif - if (MaterialsToBind.find(meshbufferReference)) - { - core::array & toBind - = MeshesToBind[MaterialsToBind[meshbufferReference]]; -#ifdef COLLADA_READER_DEBUG - os::Printer::log("Material binding now ",material->Id.c_str(), ELL_DEBUG); - os::Printer::log("#meshbuffers",core::stringc(toBind.size()).c_str(), ELL_DEBUG); -#endif - SMesh tmpmesh; - for (u32 i = 0; i < toBind.size(); ++i) - { - toBind[i]->getMaterial() = material->Mat; - tmpmesh.addMeshBuffer(toBind[i]); - - if ((material->Transparency!=0.0f) && (material->Transparency!=1.0f)) - { - toBind[i]->getMaterial().MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA; - toBind[i]->getMaterial().ZWriteEnable = false; - } - } - SceneManager->getMeshManipulator()->setVertexColors(&tmpmesh,material->Mat.DiffuseColor); - if ((material->Transparency!=0.0f) && (material->Transparency!=1.0f)) - { - #ifdef COLLADA_READER_DEBUG - os::Printer::log("COLLADA found transparency material", core::stringc(material->Transparency).c_str(), ELL_DEBUG); - #endif - SceneManager->getMeshManipulator()->setVertexColorAlpha(&tmpmesh, core::floor32(material->Transparency*255.0f)); - } - } - } - } - else - if (reader->getNodeType() == io::EXN_ELEMENT_END && - bindMaterialName == reader->getNodeName()) - break; - } -} - - -//! reads a element and stores it as mesh if possible -void CColladaFileLoader::readGeometry(io::IXMLReaderUTF8* reader) -{ - core::stringc id = readId(reader); - #ifdef COLLADA_READER_DEBUG - os::Printer::log("COLLADA reading geometry", id, ELL_DEBUG); - #endif - - SAnimatedMesh* amesh = new SAnimatedMesh(); - scene::SMesh* mesh = new SMesh(); - amesh->addMesh(mesh); - core::array sources; - bool okToReadArray = false; - - // handles geometry node and the mesh children in this loop - // read sources with arrays and accessor for each mesh - if (!reader->isEmptyElement()) - while(reader->read()) - { - if (reader->getNodeType() == io::EXN_ELEMENT) - { - const char* nodeName = reader->getNodeName(); - if (meshSectionName == nodeName) - { - // inside a mesh section. Don't have to do anything here. - } - else - if (sourceSectionName == nodeName) - { - // create a new source - sources.push_back(SSource()); - sources.getLast().Id = readId(reader); - - #ifdef COLLADA_READER_DEBUG - os::Printer::log("Reading source", sources.getLast().Id.c_str(), ELL_DEBUG); - #endif - } - else - if (arraySectionName == nodeName || floatArraySectionName == nodeName || intArraySectionName == nodeName) - { - // create a new array and read it. - if (!sources.empty()) - { - sources.getLast().Array.Name = readId(reader); - - int count = reader->getAttributeValueAsInt("count"); - sources.getLast().Array.Data.set_used(count); // pre allocate - - // check if type of array is ok - const char* type = reader->getAttributeValue("type"); - okToReadArray = (type && (!strcmp("float", type) || !strcmp("int", type))) || floatArraySectionName == nodeName || intArraySectionName == nodeName; - - #ifdef COLLADA_READER_DEBUG - os::Printer::log("Read array", sources.getLast().Array.Name.c_str(), ELL_DEBUG); - #endif - } - #ifdef COLLADA_READER_DEBUG - else - os::Printer::log("Warning, array outside source found", - readId(reader).c_str(), ELL_DEBUG); - #endif - - } - else - if (accessorSectionName == nodeName) // child of source (below a technique tag) - { - #ifdef COLLADA_READER_DEBUG - os::Printer::log("Reading accessor", ELL_DEBUG); - #endif - SAccessor accessor; - accessor.Count = reader->getAttributeValueAsInt("count"); - accessor.Offset = reader->getAttributeValueAsInt("offset"); - accessor.Stride = reader->getAttributeValueAsInt("stride"); - if (accessor.Stride == 0) - accessor.Stride = 1; - - // the accessor contains some information on how to access (boi!) the array, - // the info is stored in collada style parameters, so just read them. - readColladaParameters(reader, accessorSectionName); - if (!sources.empty()) - { - sources.getLast().Accessors.push_back(accessor); - sources.getLast().Accessors.getLast().Parameters = ColladaParameters; - } - } - else - if (verticesSectionName == nodeName) - { - #ifdef COLLADA_READER_DEBUG - os::Printer::log("Reading vertices", ELL_DEBUG); - #endif - // read vertex input position source - readColladaInputs(reader, verticesSectionName); - } - else - // lines and linestrips missing - if (polygonsSectionName == nodeName || - polylistSectionName == nodeName || - trianglesSectionName == nodeName) - { - // read polygons section - readPolygonSection(reader, sources, mesh, id); - } - else - // trifans, and tristrips missing - if (doubleSidedNodeName == reader->getNodeName()) - { - // read the extra flag for double sided polys - s32 doubleSided = 0; - readIntsInsideElement(reader,&doubleSided,1); - if (doubleSided) - { - #ifdef COLLADA_READER_DEBUG - os::Printer::log("Setting double sided flag for mesh.", ELL_DEBUG); - #endif - amesh->setMaterialFlag(irr::video::EMF_BACK_FACE_CULLING,false); - } - } - else - // techniqueCommon or 'technique profile=common' must not be skipped - if ((techniqueCommonSectionName != nodeName) // Collada 1.2/1.3 - && (techniqueNodeName != nodeName) // Collada 1.4+ - && (extraNodeName != nodeName)) - { - os::Printer::log("COLLADA loader warning: Wrong tag usage found in geometry", reader->getNodeName(), ELL_WARNING); - skipSection(reader, true); // ignore all other sections - } - } // end if node type is element - else - if (reader->getNodeType() == io::EXN_TEXT) - { - // read array data - if (okToReadArray && !sources.empty()) - { - core::array& a = sources.getLast().Array.Data; - core::stringc data = reader->getNodeData(); - data.trim(); - const c8* p = &data[0]; - - for (u32 i=0; igetNodeType() == io::EXN_ELEMENT_END) - { - if (geometrySectionName == reader->getNodeName()) - { - // end of geometry section reached, cancel out - break; - } - } - } // end while reader->read(); - - // add mesh as geometry - - mesh->recalculateBoundingBox(); - amesh->recalculateBoundingBox(); - - // create virtual file name - io::path filename = CurrentlyLoadingMesh; - filename += '#'; - filename += id; - - // add to scene manager - if (LoadedMeshCount) - { - SceneManager->getMeshCache()->addMesh(filename.c_str(), amesh); - os::Printer::log("Added COLLADA mesh", filename.c_str(), ELL_DEBUG); - } - else - { - FirstLoadedMeshName = filename; - FirstLoadedMesh = amesh; - FirstLoadedMesh->grab(); - } - - ++LoadedMeshCount; - mesh->drop(); - amesh->drop(); - - // create geometry prefab - u32 i; - for (i=0; igetId()==id) - { - ((CGeometryPrefab*)Prefabs[i])->Mesh=mesh; - break; - } - } - if (i==Prefabs.size()) - { - CGeometryPrefab* prefab = new CGeometryPrefab(id); - prefab->Mesh = mesh; - Prefabs.push_back(prefab); - } - - // store as dummy mesh if no instances will be created - if (!CreateInstances && !DummyMesh) - { - DummyMesh = amesh; - DummyMesh->grab(); - } -} - - -struct SPolygon -{ - core::array Indices; -}; - -//! reads a polygons section and creates a mesh from it -void CColladaFileLoader::readPolygonSection(io::IXMLReaderUTF8* reader, - core::array& sources, scene::SMesh* mesh, - const core::stringc& geometryId) -{ - #ifdef COLLADA_READER_DEBUG - os::Printer::log("COLLADA reading polygon section", ELL_DEBUG); - #endif - - core::stringc materialName = reader->getAttributeValue("material"); - - core::stringc polygonType = reader->getNodeName(); - const int polygonCount = reader->getAttributeValueAsInt("count"); // Not useful because it only determines the number of primitives, which have arbitrary vertices in case of polygon - core::array polygons; - if (polygonType == polygonsSectionName) - polygons.reallocate(polygonCount); - core::array vCounts; - bool parsePolygonOK = false; - bool parseVcountOK = false; - u32 inputSemanticCount = 0; - bool unresolvedInput=false; - u32 maxOffset = 0; - core::array localInputs; - - // read all and primitives - if (!reader->isEmptyElement()) - while(reader->read()) - { - const char* nodeName = reader->getNodeName(); - - if (reader->getNodeType() == io::EXN_ELEMENT) - { - // polygon node may contain params - if (inputTagName == nodeName) - { - // read input tag - readColladaInput(reader, localInputs); - - // resolve input source - SColladaInput& inp = localInputs.getLast(); - - // get input source array id, if it is a vertex input, take - // the -source attribute. - if (inp.Semantic == ECIS_VERTEX) - { - inp.Source = Inputs[0].Source; - for (u32 i=1; igetNodeType() == io::EXN_ELEMENT_END) - { - if (primitivesName == nodeName) - parsePolygonOK = false; // end parsing a polygon - else - if (vcountName == nodeName) - parseVcountOK = false; // end parsing vcounts - else - if (polygonType == nodeName) - break; // cancel out and create mesh - - } // end is element end - else - if (reader->getNodeType() == io::EXN_TEXT) - { - if (parseVcountOK) - { - core::stringc data = reader->getNodeData(); - data.trim(); - const c8* p = &data[0]; - while(*p) - { - findNextNoneWhiteSpace(&p); - if (*p) - vCounts.push_back(readInt(&p)); - } - parseVcountOK = false; - } - else - if (parsePolygonOK && polygons.size()) - { - core::stringc data = reader->getNodeData(); - data.trim(); - const c8* p = &data[0]; - SPolygon& poly = polygons.getLast(); - if (polygonType == polygonsSectionName) - poly.Indices.reallocate((maxOffset+1)*3); - else - poly.Indices.reallocate(polygonCount*(maxOffset+1)*3); - - if (vCounts.empty()) - { - while(*p) - { - findNextNoneWhiteSpace(&p); - poly.Indices.push_back(readInt(&p)); - } - } - else - { - for (u32 i = 0; i < vCounts.size(); i++) - { - const int polyVCount = vCounts[i]; - core::array polyCorners; - - for (u32 j = 0; j < polyVCount * inputSemanticCount; j++) - { - if (!*p) - break; - findNextNoneWhiteSpace(&p); - polyCorners.push_back(readInt(&p)); - } - - while (polyCorners.size() >= 3 * inputSemanticCount) - { - // add one triangle's worth of indices - for (u32 k = 0; k < inputSemanticCount * 3; ++k) - { - poly.Indices.push_back(polyCorners[k]); - } - - // remove one corner from our poly - polyCorners.erase(inputSemanticCount,inputSemanticCount); - } - polyCorners.clear(); - } - vCounts.clear(); - } - parsePolygonOK = false; - } - } - } // end while reader->read() - - // find source array (we'll ignore accessors for this implementation) - for (u32 i=0; i vertMap; - - for (u32 i=0; i indices; - const u32 vertexCount = polygons[i].Indices.size() / maxOffset; - mbuffer->Vertices.reallocate(mbuffer->Vertices.size()+vertexCount); - - // for all index/semantic groups - for (u32 v=0; v::Node* n = vertMap.find(vtx); - if (n) - { - indices.push_back(n->getValue()); - } - else - { - indices.push_back(mbuffer->getVertexCount()); - mbuffer->Vertices.push_back(vtx); - vertMap.insert(vtx, mbuffer->getVertexCount()-1); - } - } // end for all vertices - - if (polygonsSectionName == polygonType && - indices.size() > 3) - { - // need to tesselate for polygons of 4 or more vertices - // for now we naively turn interpret it as a triangle fan - // as full tesselation is problematic - if (FlipAxis) - { - for (u32 ind = indices.size()-3; ind>0 ; --ind) - { - mbuffer->Indices.push_back(indices[0]); - mbuffer->Indices.push_back(indices[ind+2]); - mbuffer->Indices.push_back(indices[ind+1]); - } - } - else - { - for (u32 ind = 0; ind+2 < indices.size(); ++ind) - { - mbuffer->Indices.push_back(indices[0]); - mbuffer->Indices.push_back(indices[ind+1]); - mbuffer->Indices.push_back(indices[ind+2]); - } - } - } - else - { - // it's just triangles - for (u32 ind = 0; ind < indices.size(); ind+=3) - { - if (FlipAxis) - { - mbuffer->Indices.push_back(indices[ind+2]); - mbuffer->Indices.push_back(indices[ind+1]); - mbuffer->Indices.push_back(indices[ind+0]); - } - else - { - mbuffer->Indices.push_back(indices[ind+0]); - mbuffer->Indices.push_back(indices[ind+1]); - mbuffer->Indices.push_back(indices[ind+2]); - } - } - } - - } // end for all polygons - } - else - { - // lightmap mesh buffer - - scene::SMeshBufferLightMap* mbuffer = new SMeshBufferLightMap(); - buffer = mbuffer; - - for (u32 i=0; iVertices.reallocate(mbuffer->Vertices.size()+vertexCount); - // for all vertices in array - for (u32 v=0; vVertices.push_back(vtx); - - } // end for all vertices - - // add vertex indices - const u32 oldVertexCount = mbuffer->Vertices.size() - vertexCount; - for (u32 face=0; faceIndices.push_back(oldVertexCount + 0); - mbuffer->Indices.push_back(oldVertexCount + 1 + face); - mbuffer->Indices.push_back(oldVertexCount + 2 + face); - } - - } // end for all polygons - } - - const SColladaMaterial* m = findMaterial(materialName); - if (m) - { - buffer->getMaterial() = m->Mat; - SMesh tmpmesh; - tmpmesh.addMeshBuffer(buffer); - SceneManager->getMeshManipulator()->setVertexColors(&tmpmesh,m->Mat.DiffuseColor); - if (m->Transparency != 1.0f) - SceneManager->getMeshManipulator()->setVertexColorAlpha(&tmpmesh,core::floor32(m->Transparency*255.0f)); - } - // add future bind reference for the material - core::stringc meshbufferReference = geometryId+"/"+materialName; - if (!MaterialsToBind.find(meshbufferReference)) - { - MaterialsToBind[meshbufferReference] = MeshesToBind.size(); - MeshesToBind.push_back(core::array()); - } - MeshesToBind[MaterialsToBind[meshbufferReference]].push_back(buffer); - - // calculate normals if there is no slot for it - - if (!normalSlotCount) - SceneManager->getMeshManipulator()->recalculateNormals(buffer, true); - - // recalculate bounding box - buffer->recalculateBoundingBox(); - - // add mesh buffer - mesh->addMeshBuffer(buffer); - #ifdef COLLADA_READER_DEBUG - os::Printer::log("COLLADA added meshbuffer", core::stringc(buffer->getVertexCount())+" vertices, "+core::stringc(buffer->getIndexCount())+" indices.", ELL_DEBUG); - #endif - - buffer->drop(); -} - - -//! reads a element and stores it as prefab -void CColladaFileLoader::readLightPrefab(io::IXMLReaderUTF8* reader) -{ - #ifdef COLLADA_READER_DEBUG - os::Printer::log("COLLADA reading light prefab", ELL_DEBUG); - #endif - - CLightPrefab* prefab = new CLightPrefab(readId(reader)); - - if (!reader->isEmptyElement()) - { - if (Version >= 10400) // start with 1.4 - { - while(reader->read()) - { - if (reader->getNodeType() == io::EXN_ELEMENT) - { - if (pointSectionName == reader->getNodeName()) - prefab->LightData.Type=video::ELT_POINT; - else - if (directionalSectionName == reader->getNodeName()) - prefab->LightData.Type=video::ELT_DIRECTIONAL; - else - if (spotSectionName == reader->getNodeName()) - prefab->LightData.Type=video::ELT_SPOT; - else - if (ambientSectionName == reader->getNodeName()) - prefab->LightData.Type=ELT_AMBIENT; - else - if (colorNodeName == reader->getNodeName()) - prefab->LightData.DiffuseColor=readColorNode(reader); - else - if (constantAttenuationNodeName == reader->getNodeName()) - readFloatsInsideElement(reader,&prefab->LightData.Attenuation.X,1); - else - if (linearAttenuationNodeName == reader->getNodeName()) - readFloatsInsideElement(reader,&prefab->LightData.Attenuation.Y,1); - else - if (quadraticAttenuationNodeName == reader->getNodeName()) - readFloatsInsideElement(reader,&prefab->LightData.Attenuation.Z,1); - else - if (falloffAngleNodeName == reader->getNodeName()) - { - readFloatsInsideElement(reader,&prefab->LightData.OuterCone,1); - prefab->LightData.OuterCone *= core::DEGTORAD; - } - else - if (falloffExponentNodeName == reader->getNodeName()) - readFloatsInsideElement(reader,&prefab->LightData.Falloff,1); - } - else - if (reader->getNodeType() == io::EXN_ELEMENT_END) - { - if ((pointSectionName == reader->getNodeName()) || - (directionalSectionName == reader->getNodeName()) || - (spotSectionName == reader->getNodeName()) || - (ambientSectionName == reader->getNodeName())) - break; - } - } - } - else - { - readColladaParameters(reader, lightPrefabName); - - SColladaParam* p = getColladaParameter(ECPN_COLOR); - if (p && p->Type == ECPT_FLOAT3) - prefab->LightData.DiffuseColor.set(p->Floats[0], p->Floats[1], p->Floats[2]); - } - } - - Prefabs.push_back(prefab); -} - - -//! returns a collada parameter or none if not found -SColladaParam* CColladaFileLoader::getColladaParameter(ECOLLADA_PARAM_NAME name) -{ - for (u32 i=0; i& inputs) -{ - // parse param - SColladaInput p; - - // get type - core::stringc semanticName = reader->getAttributeValue("semantic"); - for (u32 i=0; inputSemanticNames[i]; ++i) - { - if (semanticName == inputSemanticNames[i]) - { - p.Semantic = (ECOLLADA_INPUT_SEMANTIC)i; - break; - } - } - - // get source - p.Source = reader->getAttributeValue("source"); - if (reader->getAttributeValue("offset")) // Collada 1.4+ - p.Offset = (u32)reader->getAttributeValueAsInt("offset"); - else // Collada 1.2/1.3 - p.Offset = (u32)reader->getAttributeValueAsInt("idx"); - p.Set = (u32)reader->getAttributeValueAsInt("set"); - - // add input - inputs.push_back(p); -} - -//! parses all collada inputs inside an element and stores them in Inputs -void CColladaFileLoader::readColladaInputs(io::IXMLReaderUTF8* reader, const core::stringc& parentName) -{ - Inputs.clear(); - - while(reader->read()) - { - if (reader->getNodeType() == io::EXN_ELEMENT && - inputTagName == reader->getNodeName()) - { - readColladaInput(reader, Inputs); - } - else - if (reader->getNodeType() == io::EXN_ELEMENT_END) - { - if (parentName == reader->getNodeName()) - return; // end of parent reached - } - - } // end while reader->read(); -} - -//! parses all collada parameters inside an element and stores them in ColladaParameters -void CColladaFileLoader::readColladaParameters(io::IXMLReaderUTF8* reader, - const core::stringc& parentName) -{ - ColladaParameters.clear(); - - const char* const paramNames[] = {"COLOR", "AMBIENT", "DIFFUSE", - "SPECULAR", "SHININESS", "YFOV", "ZNEAR", "ZFAR", 0}; - - const char* const typeNames[] = {"float", "float2", "float3", 0}; - - while(reader->read()) - { - const char* nodeName = reader->getNodeName(); - if (reader->getNodeType() == io::EXN_ELEMENT && - paramTagName == nodeName) - { - // parse param - SColladaParam p; - - // get type - u32 i; - core::stringc typeName = reader->getAttributeValue("type"); - for (i=0; typeNames[i]; ++i) - if (typeName == typeNames[i]) - { - p.Type = (ECOLLADA_PARAM_TYPE)i; - break; - } - - // get name - core::stringc nameName = reader->getAttributeValue("name"); - for (i=0; typeNames[i]; ++i) - if (nameName == paramNames[i]) - { - p.Name = (ECOLLADA_PARAM_NAME)i; - break; - } - - // read parameter data inside parameter tags - switch(p.Type) - { - case ECPT_FLOAT: - case ECPT_FLOAT2: - case ECPT_FLOAT3: - case ECPT_FLOAT4: - readFloatsInsideElement(reader, p.Floats, p.Type - ECPT_FLOAT + 1); - break; - - // TODO: other types of data (ints, bools or whatever) - default: - break; - } - - // add param - ColladaParameters.push_back(p); - } - else - if (reader->getNodeType() == io::EXN_ELEMENT_END) - { - if (parentName == reader->getNodeName()) - return; // end of parent reached - } - - } // end while reader->read(); -} - - -//! parses a float from a char pointer and moves the pointer -//! to the end of the parsed float -inline f32 CColladaFileLoader::readFloat(const c8** p) -{ - f32 ftmp; - *p = core::fast_atof_move(*p, ftmp); - return ftmp; -} - - -//! parses an int from a char pointer and moves the pointer to -//! the end of the parsed float -inline s32 CColladaFileLoader::readInt(const c8** p) -{ - return (s32)readFloat(p); -} - - -//! places pointer to next begin of a token -void CColladaFileLoader::findNextNoneWhiteSpace(const c8** start) -{ - const c8* p = *start; - - while(*p && (*p==' ' || *p=='\n' || *p=='\r' || *p=='\t')) - ++p; - - // TODO: skip comments - - *start = p; -} - - -//! reads floats from inside of xml element until end of xml element -void CColladaFileLoader::readFloatsInsideElement(io::IXMLReaderUTF8* reader, f32* floats, u32 count) -{ - if (reader->isEmptyElement()) - return; - - while(reader->read()) - { - // TODO: check for comments inside the element - // and ignore them. - - if (reader->getNodeType() == io::EXN_TEXT) - { - // parse float data - core::stringc data = reader->getNodeData(); - data.trim(); - const c8* p = &data[0]; - - for (u32 i=0; igetNodeType() == io::EXN_ELEMENT_END) - break; // end parsing text - } -} - - -//! reads ints from inside of xml element until end of xml element -void CColladaFileLoader::readIntsInsideElement(io::IXMLReaderUTF8* reader, s32* ints, u32 count) -{ - if (reader->isEmptyElement()) - return; - - while(reader->read()) - { - // TODO: check for comments inside the element - // and ignore them. - - if (reader->getNodeType() == io::EXN_TEXT) - { - // parse float data - core::stringc data = reader->getNodeData(); - data.trim(); - const c8* p = &data[0]; - - for (u32 i=0; igetNodeType() == io::EXN_ELEMENT_END) - break; // end parsing text - } -} - - -video::SColorf CColladaFileLoader::readColorNode(io::IXMLReaderUTF8* reader) -{ - if (reader->getNodeType() == io::EXN_ELEMENT && - colorNodeName == reader->getNodeName()) - { - f32 color[4]; - readFloatsInsideElement(reader,color,4); - return video::SColorf(color[0], color[1], color[2], color[3]); - } - - return video::SColorf(); -} - - -f32 CColladaFileLoader::readFloatNode(io::IXMLReaderUTF8* reader) -{ - #ifdef COLLADA_READER_DEBUG - os::Printer::log("COLLADA reading ", ELL_DEBUG); - #endif - - f32 result = 0.0f; - if (reader->getNodeType() == io::EXN_ELEMENT && - floatNodeName == reader->getNodeName()) - { - readFloatsInsideElement(reader,&result,1); - } - - return result; -} - - -//! clears all loaded data -void CColladaFileLoader::clearData() -{ - // delete all prefabs - - for (u32 i=0; idrop(); - - Prefabs.clear(); - - // clear all parameters - ColladaParameters.clear(); - - // clear all materials - Images.clear(); - - // clear all materials - Textures.clear(); - - // clear all materials - Materials.clear(); - - // clear all inputs - Inputs.clear(); - - // clear all effects - for ( u32 i=0; idrop(); - Effects.clear(); - - // clear all the materials to bind - MaterialsToBind.clear(); - MeshesToBind.clear(); -} - - -//! changes the XML URI into an internal id -void CColladaFileLoader::uriToId(core::stringc& str) -{ - // currently, we only remove the # from the begin if there - // because we simply don't support referencing other files. - if (!str.size()) - return; - - if (str[0] == '#') - str.erase(0); -} - - -//! read Collada Id, uses id or name if id is missing -core::stringc CColladaFileLoader::readId(io::IXMLReaderUTF8* reader) -{ - core::stringc id = reader->getAttributeValue("id"); - if (id.size()==0) - id = reader->getAttributeValue("name"); - return id; -} - - -//! create an Irrlicht texture from the reference -video::ITexture* CColladaFileLoader::getTextureFromImage(core::stringc uri, SColladaEffect * effect) -{ - #ifdef COLLADA_READER_DEBUG - os::Printer::log("COLLADA searching texture", uri, ELL_DEBUG); - #endif - video::IVideoDriver* driver = SceneManager->getVideoDriver(); - for (;;) - { - uriToId(uri); - for (u32 i=0; iexistFile(Images[i].Source)) - return driver->getTexture(Images[i].Source); - return driver->getTexture((FileSystem->getFileDir(CurrentlyLoadingMesh)+"/"+Images[i].Source)); - } - else - if (Images[i].Source.size()) - { - //const u32 size = Images[i].Dimension.getArea(); - const u32 size = Images[i].Dimension.Width * Images[i].Dimension.Height;; - u32* data = new u32[size]; // we assume RGBA - u32* ptrdest = data; - const c8* ptrsrc = Images[i].Source.c_str(); - for (u32 j=0; jcreateImageFromData(video::ECF_A8R8G8B8, Images[i].Dimension, data, true, true); - video::ITexture* tex = driver->addTexture((CurrentlyLoadingMesh+"#"+Images[i].Id).c_str(), img); - img->drop(); - return tex; - } - break; - } - } - if (effect && effect->Parameters->getAttributeType(uri.c_str())==io::EAT_STRING) - { - uri = effect->Parameters->getAttributeAsString(uri.c_str()); -#ifdef COLLADA_READER_DEBUG - os::Printer::log("COLLADA now searching texture", uri.c_str(), ELL_DEBUG); -#endif - } - else - break; - } - return 0; -} - - -//! read a parameter and value -void CColladaFileLoader::readParameter(io::IXMLReaderUTF8* reader, io::IAttributes* parameters) -{ - #ifdef COLLADA_READER_DEBUG - os::Printer::log("COLLADA reading parameter", ELL_DEBUG); - #endif - - if ( !parameters ) - return; - - const core::stringc name = reader->getAttributeValue("sid"); - if (!reader->isEmptyElement()) - { - while(reader->read()) - { - if (reader->getNodeType() == io::EXN_ELEMENT) - { - if (floatNodeName == reader->getNodeName()) - { - const f32 f = readFloatNode(reader); - parameters->addFloat(name.c_str(), f); - } - else - if (float2NodeName == reader->getNodeName()) - { - f32 f[2]; - readFloatsInsideElement(reader, f, 2); -// Parameters.addVector2d(name.c_str(), core::vector2df(f[0],f[1])); - } - else - if (float3NodeName == reader->getNodeName()) - { - f32 f[3]; - readFloatsInsideElement(reader, f, 3); - parameters->addVector3d(name.c_str(), core::vector3df(f[0],f[1],f[2])); - } - else - if ((initFromName == reader->getNodeName()) || - (sourceSectionName == reader->getNodeName())) - { - reader->read(); - parameters->addString(name.c_str(), reader->getNodeData()); - } - else - if (wrapsName == reader->getNodeName()) - { - reader->read(); - const core::stringc val = reader->getNodeData(); - if (val == "WRAP") - parameters->addInt(wrapsName.c_str(), (int)video::ETC_REPEAT); - else if ( val== "MIRROR") - parameters->addInt(wrapsName.c_str(), (int)video::ETC_MIRROR); - else if ( val== "CLAMP") - parameters->addInt(wrapsName.c_str(), (int)video::ETC_CLAMP_TO_EDGE); - else if ( val== "BORDER") - parameters->addInt(wrapsName.c_str(), (int)video::ETC_CLAMP_TO_BORDER); - else if ( val== "NONE") - parameters->addInt(wrapsName.c_str(), (int)video::ETC_CLAMP_TO_BORDER); - } - else - if (wraptName == reader->getNodeName()) - { - reader->read(); - const core::stringc val = reader->getNodeData(); - if (val == "WRAP") - parameters->addInt(wraptName.c_str(), (int)video::ETC_REPEAT); - else if ( val== "MIRROR") - parameters->addInt(wraptName.c_str(), (int)video::ETC_MIRROR); - else if ( val== "CLAMP") - parameters->addInt(wraptName.c_str(), (int)video::ETC_CLAMP_TO_EDGE); - else if ( val== "BORDER") - parameters->addInt(wraptName.c_str(), (int)video::ETC_CLAMP_TO_BORDER); - else if ( val== "NONE") - parameters->addInt(wraptName.c_str(), (int)video::ETC_CLAMP_TO_BORDER); - } - else - if (minfilterName == reader->getNodeName()) - { - reader->read(); - const core::stringc val = reader->getNodeData(); - if (val == "LINEAR_MIPMAP_LINEAR") - parameters->addBool("trilinear", true); - else - if (val == "LINEAR_MIPMAP_NEAREST") - parameters->addBool("bilinear", true); - } - else - if (magfilterName == reader->getNodeName()) - { - reader->read(); - const core::stringc val = reader->getNodeData(); - if (val != "LINEAR") - { - parameters->addBool("bilinear", false); - parameters->addBool("trilinear", false); - } - } - else - if (mipfilterName == reader->getNodeName()) - { - parameters->addBool("anisotropic", true); - } - } - else - if(reader->getNodeType() == io::EXN_ELEMENT_END) - { - if (newParamName == reader->getNodeName()) - break; - } - } - } -} - - -} // end namespace scene -} // end namespace irr - -#endif // _IRR_COMPILE_WITH_COLLADA_LOADER_ - diff --git a/lib/irrlicht/source/Irrlicht/CColladaFileLoader.h b/lib/irrlicht/source/Irrlicht/CColladaFileLoader.h deleted file mode 100644 index df1a55189..000000000 --- a/lib/irrlicht/source/Irrlicht/CColladaFileLoader.h +++ /dev/null @@ -1,389 +0,0 @@ -// Copyright (C) 2002-2012 Nikolaus Gebhardt -// This file is part of the "Irrlicht Engine". -// For conditions of distribution and use, see copyright notice in irrlicht.h - -#ifndef __C_COLLADA_MESH_FILE_LOADER_H_INCLUDED__ -#define __C_COLLADA_MESH_FILE_LOADER_H_INCLUDED__ - -#include "IMeshLoader.h" -#include "IFileSystem.h" -#include "IVideoDriver.h" -#include "irrString.h" -#include "SMesh.h" -#include "SMeshBuffer.h" -#include "ISceneManager.h" -#include "irrMap.h" -#include "CAttributes.h" - -namespace irr -{ -namespace scene -{ - -#ifdef _DEBUG -//#define COLLADA_READER_DEBUG -#endif - -class IColladaPrefab; - -enum ECOLLADA_PARAM_NAME -{ - ECPN_COLOR = 0, - ECPN_AMBIENT, - ECPN_DIFFUSE, - ECPN_SPECULAR, - ECPN_SHININESS, - ECPN_TRANSPARENCY, - ECPN_YFOV, - ECPN_ZNEAR, - ECPN_ZFAR, - - ECPN_COUNT -}; - -enum ECOLLADA_PARAM_TYPE -{ - ECPT_FLOAT = 0, - ECPT_FLOAT2, - ECPT_FLOAT3, - ECPT_FLOAT4, - - ECPT_COUNT -}; - -//! Collada Parameter -struct SColladaParam -{ - SColladaParam() - : Name(ECPN_COUNT), Type(ECPT_COUNT) - { - for (int i=0; i<4; ++i) Floats[i] = 0; - } - - ECOLLADA_PARAM_NAME Name; - ECOLLADA_PARAM_TYPE Type; - - f32 Floats[4]; -}; - -enum ECOLLADA_INPUT_SEMANTIC -{ - ECIS_POSITION = 0, - ECIS_VERTEX, - ECIS_NORMAL, - ECIS_TEXCOORD, - ECIS_UV, - ECIS_TANGENT, - ECIS_IMAGE, - ECIS_TEXTURE, - - ECIS_COUNT -}; - -//! Collada Input -struct SColladaInput -{ - SColladaInput() - : Semantic(ECIS_COUNT), Data(0), Offset(0), Set(0), Stride(1) - { - } - - ECOLLADA_INPUT_SEMANTIC Semantic; - core::stringc Source; - f32* Data; - u32 Offset; - u32 Set; - u32 Stride; -}; - -//! Collada images -struct SColladaImage -{ - core::stringc Id; - core::stringc Source; - core::dimension2du Dimension; - bool SourceIsFilename; -}; - - -//! Collada texture -struct SColladaTexture -{ - video::ITexture* Texture; - core::stringc Id; -}; - - -//! Collada material -struct SColladaMaterial -{ - video::SMaterial Mat; - core::stringc Id; - core::stringc InstanceEffectId; - f32 Transparency; - - inline bool operator< (const SColladaMaterial & other) const - { - return Id < other.Id; - } -}; - -//! Collada effect (materials, shaders, and programs) -struct SColladaEffect -{ - core::stringc Id; - f32 Transparency; - core::array Textures; - video::SMaterial Mat; - // TODO: Parameters looks somewhat lazy workaround, I think we should really read all parameters correct. - io::IAttributes * Parameters; - - inline bool operator< (const SColladaEffect & other) const - { - return Id < other.Id; - } -}; - - -struct SNumberArray // for storing float and int arrays -{ - core::stringc Name; - core::array Data; -}; - -struct SAccessor -{ - SAccessor() - : Count(0), Offset(0), Stride(1) {} - // I don't store the source of the accessor here because I assume - // it to use the array of the source this accessor is located in. - - int Count; - int Offset; - int Stride; - - core::array Parameters; // parameters defining the accessor -}; - -struct SSource -{ - core::stringc Id; - SNumberArray Array; - core::array Accessors; -}; - -class CScenePrefab; - -//! Meshloader capable of loading COLLADA meshes and scene descriptions into Irrlicht. -class CColladaFileLoader : public IMeshLoader -{ -public: - - //! Constructor - CColladaFileLoader(scene::ISceneManager* smgr, io::IFileSystem* fs); - - //! destructor - virtual ~CColladaFileLoader(); - - //! returns true if the file maybe is able to be loaded by this class - //! based on the file extension (e.g. ".cob") - virtual bool isALoadableFileExtension(const io::path& filename) const; - - //! creates/loads an animated mesh from the file. - //! \return Pointer to the created mesh. Returns 0 if loading failed. - //! If you no longer need the mesh, you should call IAnimatedMesh::drop(). - //! See IReferenceCounted::drop() for more information. - virtual IAnimatedMesh* createMesh(io::IReadFile* file); - -private: - - //! skips an (unknown) section in the collada document - void skipSection(io::IXMLReaderUTF8* reader, bool reportSkipping); - - //! reads the section and its content - void readColladaSection(io::IXMLReaderUTF8* reader); - - //! reads a section and its content - void readLibrarySection(io::IXMLReaderUTF8* reader); - - //! reads a element and stores it as a prefab - void readVisualScene(io::IXMLReaderUTF8* reader); - - //! reads a section and its content - void readSceneSection(io::IXMLReaderUTF8* reader); - - //! reads a section and its content - void readAssetSection(io::IXMLReaderUTF8* reader); - - //! reads a section and its content - //! if a prefab pointer is passed the nodes are created as scene prefabs children of that prefab - void readNodeSection(io::IXMLReaderUTF8* reader, scene::ISceneNode* parent, CScenePrefab* p=0); - - //! reads a element and its content and creates a matrix from it - core::matrix4 readLookAtNode(io::IXMLReaderUTF8* reader); - - //! reads a element and its content and creates a matrix from it - core::matrix4 readMatrixNode(io::IXMLReaderUTF8* reader); - - //! reads a element and its content and creates a matrix from it - core::matrix4 readPerspectiveNode(io::IXMLReaderUTF8* reader); - - //! reads a element and its content and creates a matrix from it - core::matrix4 readRotateNode(io::IXMLReaderUTF8* reader); - - //! reads a element and its content and creates a matrix from it - core::matrix4 readSkewNode(io::IXMLReaderUTF8* reader); - - //! reads a element and its content and stores it in bbox - void readBboxNode(io::IXMLReaderUTF8* reader, core::aabbox3df& bbox); - - //! reads a element and its content and creates a matrix from it - core::matrix4 readScaleNode(io::IXMLReaderUTF8* reader); - - //! reads a element and its content and creates a matrix from it - core::matrix4 readTranslateNode(io::IXMLReaderUTF8* reader); - - //! reads a element - video::SColorf readColorNode(io::IXMLReaderUTF8* reader); - - //! reads a element - f32 readFloatNode(io::IXMLReaderUTF8* reader); - - //! reads a node - void readInstanceNode(io::IXMLReaderUTF8* reader, - scene::ISceneNode* parent, scene::ISceneNode** outNode, - CScenePrefab* p=0, const core::stringc& type=core::stringc()); - - //! creates a scene node from Prefabs (with name given in 'url') - void instantiateNode(scene::ISceneNode* parent, scene::ISceneNode** outNode=0, - CScenePrefab* p=0, const core::stringc& url="", - const core::stringc& type=core::stringc()); - - //! reads a element and stores it as prefab - void readLightPrefab(io::IXMLReaderUTF8* reader); - - //! reads a element and stores it as prefab - void readCameraPrefab(io::IXMLReaderUTF8* reader); - - //! reads a element and stores it in the image section - void readImage(io::IXMLReaderUTF8* reader); - - //! reads a element and stores it in the texture section - void readTexture(io::IXMLReaderUTF8* reader); - - //! reads a element and stores it in the material section - void readMaterial(io::IXMLReaderUTF8* reader); - - //! reads a element and stores it in the effects section - void readEffect(io::IXMLReaderUTF8* reader, SColladaEffect * effect = 0); - - //! reads a element and stores it as mesh if possible - void readGeometry(io::IXMLReaderUTF8* reader); - - //! parses a float from a char pointer and moves the pointer to - //! the end of the parsed float - inline f32 readFloat(const c8** p); - - //! parses an int from a char pointer and moves the pointer to - //! the end of the parsed float - inline s32 readInt(const c8** p); - - //! places pointer to next begin of a token - void findNextNoneWhiteSpace(const c8** p); - - //! reads floats from inside of xml element until end of xml element - void readFloatsInsideElement(io::IXMLReaderUTF8* reader, f32* floats, u32 count); - - //! reads ints from inside of xml element until end of xml element - void readIntsInsideElement(io::IXMLReaderUTF8* reader, s32* ints, u32 count); - - //! clears all loaded data - void clearData(); - - //! parses all collada parameters inside an element and stores them in ColladaParameters - void readColladaParameters(io::IXMLReaderUTF8* reader, const core::stringc& parentName); - - //! returns a collada parameter or none if not found - SColladaParam* getColladaParameter(ECOLLADA_PARAM_NAME name); - - //! parses all collada inputs inside an element and stores them in Inputs. Reads - //! until first tag which is not an input tag or the end of the parent is reached - void readColladaInputs(io::IXMLReaderUTF8* reader, const core::stringc& parentName); - - //! reads a collada input tag and adds it to the input parameter - void readColladaInput(io::IXMLReaderUTF8* reader, core::array& inputs); - - //! returns a collada input or none if not found - SColladaInput* getColladaInput(ECOLLADA_INPUT_SEMANTIC input); - - //! read Collada Id, uses id or name if id is missing - core::stringc readId(io::IXMLReaderUTF8* reader); - - //! changes the XML URI into an internal id - void uriToId(core::stringc& str); - - //! reads a polygons section and creates a mesh from it - void readPolygonSection(io::IXMLReaderUTF8* reader, - core::array& sources, scene::SMesh* mesh, - const core::stringc& geometryId); - - //! finds a material, possible instancing it - const SColladaMaterial * findMaterial(const core::stringc & materialName); - - //! reads and bind materials as given by the symbol->target bind mapping - void readBindMaterialSection(io::IXMLReaderUTF8* reader, const core::stringc & id); - - //! create an Irrlicht texture from the SColladaImage - video::ITexture* getTextureFromImage(core::stringc uri, SColladaEffect * effect); - - //! read a parameter and value - void readParameter(io::IXMLReaderUTF8* reader, io::IAttributes* parameters); - - scene::ISceneManager* SceneManager; - io::IFileSystem* FileSystem; - - scene::IAnimatedMesh* DummyMesh; - core::stringc CurrentlyLoadingMesh; - - scene::IAnimatedMesh* FirstLoadedMesh; - io::path FirstLoadedMeshName; - s32 LoadedMeshCount; - u32 Version; - bool FlipAxis; - - core::array Prefabs; - core::array ColladaParameters; - core::array Images; - core::array Textures; - core::array Materials; - core::array Inputs; - core::array Effects; - //! meshbuffer reference ("geomid/matname") -> index into MeshesToBind - core::map MaterialsToBind; - //! Array of buffers for each material binding - core::array< core::array > MeshesToBind; - - bool CreateInstances; -}; - - - -//! following class is for holding and createing instances of library objects, -//! named prefabs in this loader. -class IColladaPrefab : public virtual IReferenceCounted -{ -public: - //! creates an instance of this prefab - virtual scene::ISceneNode* addInstance(scene::ISceneNode* parent, - scene::ISceneManager* mgr) = 0; - - //! returns id of this prefab - virtual const core::stringc& getId() = 0; -}; - - -} // end namespace scene -} // end namespace irr - -#endif - diff --git a/lib/irrlicht/source/Irrlicht/CColladaMeshWriter.cpp b/lib/irrlicht/source/Irrlicht/CColladaMeshWriter.cpp deleted file mode 100644 index e5b6df5c2..000000000 --- a/lib/irrlicht/source/Irrlicht/CColladaMeshWriter.cpp +++ /dev/null @@ -1,2245 +0,0 @@ -// Copyright (C) 2002-2012 Nikolaus Gebhardt -// This file is part of the "Irrlicht Engine". -// For conditions of distribution and use, see copyright notice in irrlicht.h - -// TODO: second UV-coordinates currently ignored in textures - -#include "IrrCompileConfig.h" - -#ifdef _IRR_COMPILE_WITH_COLLADA_WRITER_ - -#include "CColladaMeshWriter.h" -#include "os.h" -#include "IFileSystem.h" -#include "IWriteFile.h" -#include "IXMLWriter.h" -#include "IMesh.h" -#include "IAttributes.h" -#include "IAnimatedMeshSceneNode.h" -#include "IMeshSceneNode.h" -#include "ITerrainSceneNode.h" -#include "ILightSceneNode.h" -#include "ICameraSceneNode.h" -#include "ISceneManager.h" - -namespace irr -{ -namespace scene -{ - -//! Which lighting model should be used in the technique (FX) section when exporting effects (materials) -E_COLLADA_TECHNIQUE_FX CColladaMeshWriterProperties::getTechniqueFx(const video::SMaterial& material) const -{ - return ECTF_BLINN; -} - -//! Which texture index should be used when writing the texture of the given sampler color. -s32 CColladaMeshWriterProperties::getTextureIdx(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs) const -{ - // So far we just export in a way which is similar to how we import colladas. - // There might be better ways to do this, but I suppose it depends a lot for which target - // application we export, so in most cases it will have to be done in user-code anyway. - switch ( cs ) - { - case ECCS_DIFFUSE: - return 2; - case ECCS_AMBIENT: - return 1; - case ECCS_EMISSIVE: - return 0; - case ECCS_SPECULAR: - return 3; - case ECCS_TRANSPARENT: - return -1; - case ECCS_REFLECTIVE: - return -1; - }; - return -1; -} - -E_COLLADA_IRR_COLOR CColladaMeshWriterProperties::getColorMapping(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs) const -{ - switch ( cs ) - { - case ECCS_DIFFUSE: - return ECIC_DIFFUSE; - case ECCS_AMBIENT: - return ECIC_AMBIENT; - case ECCS_EMISSIVE: - return ECIC_EMISSIVE; - case ECCS_SPECULAR: - return ECIC_SPECULAR; - case ECCS_TRANSPARENT: - return ECIC_NONE; - case ECCS_REFLECTIVE: - return ECIC_CUSTOM; - }; - - return ECIC_NONE; -} - -//! Return custom colors for certain color types requested by collada. -video::SColor CColladaMeshWriterProperties::getCustomColor(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs) const -{ - return video::SColor(255, 0, 0, 0); -} - - -//! Return the settings for transparence -E_COLLADA_TRANSPARENT_FX CColladaMeshWriterProperties::getTransparentFx(const video::SMaterial& material) const -{ - // TODO: figure out best default mapping - return ECOF_A_ONE; -} - -//! Transparency value for the material. -f32 CColladaMeshWriterProperties::getTransparency(const video::SMaterial& material) const -{ - // TODO: figure out best default mapping - return -1.f; -} - -//! Reflectivity value for that material -f32 CColladaMeshWriterProperties::getReflectivity(const video::SMaterial& material) const -{ - // TODO: figure out best default mapping - return 0.f; -} - -//! Return index of refraction for that material -f32 CColladaMeshWriterProperties::getIndexOfRefraction(const video::SMaterial& material) const -{ - return -1.f; -} - -bool CColladaMeshWriterProperties::isExportable(const irr::scene::ISceneNode * node) const -{ - return node && node->isVisible(); -} - -IMesh* CColladaMeshWriterProperties::getMesh(irr::scene::ISceneNode * node) -{ - if ( !node ) - return 0; - if ( node->getType() == ESNT_ANIMATED_MESH ) - return static_cast(node)->getMesh()->getMesh(0); - // TODO: we need some ISceneNode::hasType() function to get rid of those checks - if ( node->getType() == ESNT_MESH - || node->getType() == ESNT_CUBE - || node->getType() == ESNT_SPHERE - || node->getType() == ESNT_WATER_SURFACE - || node->getType() == ESNT_Q3SHADER_SCENE_NODE - ) - return static_cast(node)->getMesh(); - if ( node->getType() == ESNT_TERRAIN ) - return static_cast(node)->getMesh(); - return 0; -} - -// Check if the node has it's own material overwriting the mesh-materials -bool CColladaMeshWriterProperties::useNodeMaterial(const scene::ISceneNode* node) const -{ - if ( !node ) - return false; - - // TODO: we need some ISceneNode::hasType() function to get rid of those checks - bool useMeshMaterial = ( (node->getType() == ESNT_MESH || - node->getType() == ESNT_CUBE || - node->getType() == ESNT_SPHERE || - node->getType() == ESNT_WATER_SURFACE || - node->getType() == ESNT_Q3SHADER_SCENE_NODE) - && static_cast(node)->isReadOnlyMaterials()) - - || (node->getType() == ESNT_ANIMATED_MESH - && static_cast(node)->isReadOnlyMaterials() ); - - return !useMeshMaterial; -} - - - -CColladaMeshWriterNames::CColladaMeshWriterNames(IColladaMeshWriter * writer) - : ColladaMeshWriter(writer) -{ -} - -irr::core::stringw CColladaMeshWriterNames::nameForMesh(const scene::IMesh* mesh, int instance) -{ - irr::core::stringw name(L"mesh"); - name += nameForPtr(mesh); - if ( instance > 0 ) - { - name += L"i"; - name += irr::core::stringw(instance); - } - return ColladaMeshWriter->toNCName(name); -} - -irr::core::stringw CColladaMeshWriterNames::nameForNode(const scene::ISceneNode* node) -{ - irr::core::stringw name; - // Prefix, because xs::ID can't start with a number, also nicer name - if ( node && node->getType() == ESNT_LIGHT ) - name = L"light"; - else - name = L"node"; - name += nameForPtr(node); - if ( node ) - { - name += irr::core::stringw(node->getName()); - } - return ColladaMeshWriter->toNCName(name); -} - -irr::core::stringw CColladaMeshWriterNames::nameForMaterial(const video::SMaterial & material, int materialId, const scene::IMesh* mesh, const scene::ISceneNode* node) -{ - core::stringw strMat(L"mat"); - - bool nodeMaterial = ColladaMeshWriter->getProperties()->useNodeMaterial(node); - if ( nodeMaterial ) - { - strMat += L"node"; - strMat += nameForPtr(node); - strMat += irr::core::stringw(node->getName()); - } - strMat += L"mesh"; - strMat += nameForPtr(mesh); - strMat += materialId; - return ColladaMeshWriter->toNCName(strMat); -} - -irr::core::stringw CColladaMeshWriterNames::nameForPtr(const void* ptr) const -{ - wchar_t buf[32]; - swprintf(buf, 32, L"%p", ptr); - return irr::core::stringw(buf); -} - - - -CColladaMeshWriter::CColladaMeshWriter( ISceneManager * smgr, video::IVideoDriver* driver, - io::IFileSystem* fs) - : FileSystem(fs), VideoDriver(driver), Writer(0) -{ - - #ifdef _DEBUG - setDebugName("CColladaMeshWriter"); - #endif - - if (VideoDriver) - VideoDriver->grab(); - - if (FileSystem) - FileSystem->grab(); - - if ( smgr ) - setAmbientLight( smgr->getAmbientLight() ); - - CColladaMeshWriterProperties * p = new CColladaMeshWriterProperties(); - setDefaultProperties(p); - setProperties(p); - p->drop(); - - CColladaMeshWriterNames * nameGenerator = new CColladaMeshWriterNames(this); - setDefaultNameGenerator(nameGenerator); - setNameGenerator(nameGenerator); - nameGenerator->drop(); -} - - -CColladaMeshWriter::~CColladaMeshWriter() -{ - if (VideoDriver) - VideoDriver->drop(); - - if (FileSystem) - FileSystem->drop(); -} - - -void CColladaMeshWriter::reset() -{ - LibraryImages.clear(); - Meshes.clear(); - LightNodes.clear(); - CameraNodes.clear(); - MaterialsWritten.clear(); - EffectsWritten.clear(); - MaterialNameCache.clear(); -} - -//! Returns the type of the mesh writer -EMESH_WRITER_TYPE CColladaMeshWriter::getType() const -{ - return EMWT_COLLADA; -} - -//! writes a scene starting with the given node -bool CColladaMeshWriter::writeScene(io::IWriteFile* file, scene::ISceneNode* root) -{ - if (!file || !root) - return false; - - reset(); - - Writer = FileSystem->createXMLWriter(file); - - if (!Writer) - { - os::Printer::log("Could not write file", file->getFileName()); - return false; - } - - Directory = FileSystem->getFileDir(FileSystem->getAbsolutePath( file->getFileName() )); - - // make names for all nodes with exportable meshes - makeMeshNames(root); - - os::Printer::log("Writing scene", file->getFileName()); - - // write COLLADA header - - Writer->writeXMLHeader(); - - Writer->writeElement(L"COLLADA", false, - L"xmlns", L"http://www.collada.org/2005/11/COLLADASchema", - L"version", L"1.4.1"); - Writer->writeLineBreak(); - - // write asset data - writeAsset(); - - // write all materials - Writer->writeElement(L"library_materials", false); - Writer->writeLineBreak(); - writeNodeMaterials(root); - Writer->writeClosingTag(L"library_materials"); - Writer->writeLineBreak(); - - Writer->writeElement(L"library_effects", false); - Writer->writeLineBreak(); - writeNodeEffects(root); - Writer->writeClosingTag(L"library_effects"); - Writer->writeLineBreak(); - - - // images - writeLibraryImages(); - - // lights - Writer->writeElement(L"library_lights", false); - Writer->writeLineBreak(); - - writeAmbientLightElement( getAmbientLight() ); - writeNodeLights(root); - - Writer->writeClosingTag(L"library_lights"); - Writer->writeLineBreak(); - - // cameras - Writer->writeElement(L"library_cameras", false); - Writer->writeLineBreak(); - writeNodeCameras(root); - Writer->writeClosingTag(L"library_cameras"); - Writer->writeLineBreak(); - - // write meshes - Writer->writeElement(L"library_geometries", false); - Writer->writeLineBreak(); - writeAllMeshGeometries(); - Writer->writeClosingTag(L"library_geometries"); - Writer->writeLineBreak(); - - // write scene - Writer->writeElement(L"library_visual_scenes", false); - Writer->writeLineBreak(); - Writer->writeElement(L"visual_scene", false, L"id", L"default_scene"); - Writer->writeLineBreak(); - - // ambient light (instance_light also needs a node as parent so we have to create one) - Writer->writeElement(L"node", false); - Writer->writeLineBreak(); - Writer->writeElement(L"instance_light", true, L"url", L"#ambientlight"); - Writer->writeLineBreak(); - Writer->writeClosingTag(L"node"); - Writer->writeLineBreak(); - - // Write the scenegraph. - if ( root->getType() != ESNT_SCENE_MANAGER ) - { - // TODO: Not certain if we should really write the root or if we should just always only write the children. - // For now writing root to keep backward compatibility for this case, but if anyone needs to _not_ write - // that root-node we can add a parameter for this later on in writeScene. - writeSceneNode(root); - } - else - { - // The visual_scene element is identical to our scenemanager and acts as root, - // so we do not write the root itself if it points to the scenemanager. - const core::list& rootChildren = root->getChildren(); - for ( core::list::ConstIterator it = rootChildren.begin(); - it != rootChildren.end(); - ++ it ) - { - writeSceneNode(*it); - } - } - - - Writer->writeClosingTag(L"visual_scene"); - Writer->writeLineBreak(); - Writer->writeClosingTag(L"library_visual_scenes"); - Writer->writeLineBreak(); - - - // instance scene - Writer->writeElement(L"scene", false); - Writer->writeLineBreak(); - - Writer->writeElement(L"instance_visual_scene", true, L"url", L"#default_scene"); - Writer->writeLineBreak(); - - Writer->writeClosingTag(L"scene"); - Writer->writeLineBreak(); - - - // close everything - - Writer->writeClosingTag(L"COLLADA"); - Writer->drop(); - - return true; -} - -void CColladaMeshWriter::makeMeshNames(irr::scene::ISceneNode * node) -{ - if ( !node || !getProperties() || !getProperties()->isExportable(node) || !getNameGenerator()) - return; - - IMesh* mesh = getProperties()->getMesh(node); - if ( mesh ) - { - if ( !Meshes.find(mesh) ) - { - SColladaMesh cm; - cm.Name = nameForMesh(mesh, 0); - Meshes.insert(mesh, cm); - } - } - - const core::list& children = node->getChildren(); - for ( core::list::ConstIterator it = children.begin(); it != children.end(); ++it ) - { - makeMeshNames(*it); - } -} - -void CColladaMeshWriter::writeNodeMaterials(irr::scene::ISceneNode * node) -{ - if ( !node || !getProperties() || !getProperties()->isExportable(node) ) - return; - - core::array materialNames; - - IMesh* mesh = getProperties()->getMesh(node); - if ( mesh ) - { - MeshNode * n = Meshes.find(mesh); - if ( !getProperties()->useNodeMaterial(node) ) - { - // no material overrides - write mesh materials - if ( n && !n->getValue().MaterialsWritten ) - { - writeMeshMaterials(mesh, getGeometryWriting() == ECGI_PER_MESH_AND_MATERIAL ? &materialNames : NULL); - n->getValue().MaterialsWritten = true; - } - } - else - { - // write node materials - for (u32 i=0; igetMaterialCount(); ++i) - { - video::SMaterial & material = node->getMaterial(i); - core::stringw strMat(nameForMaterial(material, i, mesh, node)); - writeMaterial(strMat); - if ( getGeometryWriting() == ECGI_PER_MESH_AND_MATERIAL ) - materialNames.push_back(strMat); - } - } - - // When we write another mesh-geometry for each new material-list we have - // to figure out here if we need another geometry copy and create a new name here. - if ( n && getGeometryWriting() == ECGI_PER_MESH_AND_MATERIAL ) - { - SGeometryMeshMaterials * geomMat = n->getValue().findGeometryMeshMaterials(materialNames); - if ( geomMat ) - geomMat->MaterialOwners.push_back(node); - else - { - SGeometryMeshMaterials gmm; - if ( n->getValue().GeometryMeshMaterials.empty() ) - gmm.GeometryName = n->getValue().Name; // first one can use the original name - else - gmm.GeometryName = nameForMesh(mesh, n->getValue().GeometryMeshMaterials.size()); - gmm.MaterialNames = materialNames; - gmm.MaterialOwners.push_back(node); - n->getValue().GeometryMeshMaterials.push_back(gmm); - } - } - } - - const core::list& children = node->getChildren(); - for ( core::list::ConstIterator it = children.begin(); it != children.end(); ++it ) - { - writeNodeMaterials( *it ); - } -} - -void CColladaMeshWriter::writeMaterial(const irr::core::stringw& materialname) -{ - if ( MaterialsWritten.find(materialname) ) - return; - MaterialsWritten.insert(materialname, true); - - Writer->writeElement(L"material", false, - L"id", materialname.c_str(), - L"name", materialname.c_str()); - Writer->writeLineBreak(); - - // We don't make a difference between material and effect on export. - // Every material is just using an instance of an effect. - core::stringw strFx(materialname); - strFx += L"-fx"; - Writer->writeElement(L"instance_effect", true, - L"url", (core::stringw(L"#") + strFx).c_str()); - Writer->writeLineBreak(); - - Writer->writeClosingTag(L"material"); - Writer->writeLineBreak(); -} - -void CColladaMeshWriter::writeNodeEffects(irr::scene::ISceneNode * node) -{ - if ( !node || !getProperties() || !getProperties()->isExportable(node) || !getNameGenerator() ) - return; - - IMesh* mesh = getProperties()->getMesh(node); - if ( mesh ) - { - if ( !getProperties()->useNodeMaterial(node) ) - { - // no material overrides - write mesh materials - MeshNode * n = Meshes.find(mesh); - if ( n && !n->getValue().EffectsWritten ) - { - writeMeshEffects(mesh); - n->getValue().EffectsWritten = true; - } - } - else - { - // write node materials - for (u32 i=0; igetMaterialCount(); ++i) - { - video::SMaterial & material = node->getMaterial(i); - irr::core::stringw materialfxname(nameForMaterial(material, i, mesh, node)); - materialfxname += L"-fx"; - writeMaterialEffect(materialfxname, material); - } - } - } - - const core::list& children = node->getChildren(); - for ( core::list::ConstIterator it = children.begin(); it != children.end(); ++it ) - { - writeNodeEffects( *it ); - } -} - -void CColladaMeshWriter::writeNodeLights(irr::scene::ISceneNode * node) -{ - if ( !node || !getProperties() || !getProperties()->isExportable(node)) - return; - - if ( node->getType() == ESNT_LIGHT ) - { - ILightSceneNode * lightNode = static_cast(node); - const video::SLight& lightData = lightNode->getLightData(); - - SColladaLight cLight; - cLight.Name = nameForNode(node); - LightNodes.insert(node, cLight); - - Writer->writeElement(L"light", false, L"id", cLight.Name.c_str()); - Writer->writeLineBreak(); - - Writer->writeElement(L"technique_common", false); - Writer->writeLineBreak(); - - switch ( lightNode->getLightType() ) - { - case video::ELT_POINT: - Writer->writeElement(L"point", false); - Writer->writeLineBreak(); - - writeColorElement(lightData.DiffuseColor, false); - writeNode(L"constant_attenuation ", core::stringw(lightData.Attenuation.X).c_str()); - writeNode(L"linear_attenuation ", core::stringw(lightData.Attenuation.Y).c_str()); - writeNode(L"quadratic_attenuation", core::stringw(lightData.Attenuation.Z).c_str()); - - Writer->writeClosingTag(L"point"); - Writer->writeLineBreak(); - break; - - case video::ELT_SPOT: - Writer->writeElement(L"spot", false); - Writer->writeLineBreak(); - - writeColorElement(lightData.DiffuseColor, false); - - writeNode(L"constant_attenuation ", core::stringw(lightData.Attenuation.X).c_str()); - writeNode(L"linear_attenuation ", core::stringw(lightData.Attenuation.Y).c_str()); - writeNode(L"quadratic_attenuation", core::stringw(lightData.Attenuation.Z).c_str()); - - writeNode(L"falloff_angle", core::stringw(lightData.OuterCone * core::RADTODEG).c_str()); - writeNode(L"falloff_exponent", core::stringw(lightData.Falloff).c_str()); - - Writer->writeClosingTag(L"spot"); - Writer->writeLineBreak(); - break; - - case video::ELT_DIRECTIONAL: - Writer->writeElement(L"directional", false); - Writer->writeLineBreak(); - - writeColorElement(lightData.DiffuseColor, false); - - Writer->writeClosingTag(L"directional"); - Writer->writeLineBreak(); - break; - default: - break; - } - - Writer->writeClosingTag(L"technique_common"); - Writer->writeLineBreak(); - - Writer->writeClosingTag(L"light"); - Writer->writeLineBreak(); - - } - - const core::list& children = node->getChildren(); - for ( core::list::ConstIterator it = children.begin(); it != children.end(); ++it ) - { - writeNodeLights( *it ); - } -} - -void CColladaMeshWriter::writeNodeCameras(irr::scene::ISceneNode * node) -{ - if ( !node || !getProperties() || !getProperties()->isExportable(node) ) - return; - - if ( isCamera(node) ) - { - ICameraSceneNode * cameraNode = static_cast(node); - irr::core::stringw name = nameForNode(node); - CameraNodes.insert(cameraNode, name); - - Writer->writeElement(L"camera", false, L"id", name.c_str()); - Writer->writeLineBreak(); - - Writer->writeElement(L"optics", false); - Writer->writeLineBreak(); - - Writer->writeElement(L"technique_common", false); - Writer->writeLineBreak(); - - if ( cameraNode->isOrthogonal() ) - { - Writer->writeElement(L"orthographic", false); - Writer->writeLineBreak(); - -// writeNode(L"xmag", core::stringw("1.0").c_str()); // TODO: do we need xmag, ymag? -// writeNode(L"ymag", core::stringw("1.0").c_str()); - writeNode(L"aspect_ratio", core::stringw(cameraNode->getAspectRatio()).c_str()); - writeNode(L"znear", core::stringw(cameraNode->getNearValue()).c_str()); - writeNode(L"zfar", core::stringw(cameraNode->getFarValue()).c_str()); - - Writer->writeClosingTag(L"orthographic"); - Writer->writeLineBreak(); - } - else - { - Writer->writeElement(L"perspective", false); - Writer->writeLineBreak(); - - writeNode(L"yfov", core::stringw(cameraNode->getFOV()*core::RADTODEG).c_str()); - writeNode(L"aspect_ratio", core::stringw(cameraNode->getAspectRatio()).c_str()); - writeNode(L"znear", core::stringw(cameraNode->getNearValue()).c_str()); - writeNode(L"zfar", core::stringw(cameraNode->getFarValue()).c_str()); - - Writer->writeClosingTag(L"perspective"); - Writer->writeLineBreak(); - } - - Writer->writeClosingTag(L"technique_common"); - Writer->writeLineBreak(); - - Writer->writeClosingTag(L"optics"); - Writer->writeLineBreak(); - - Writer->writeClosingTag(L"camera"); - Writer->writeLineBreak(); - } - - const core::list& children = node->getChildren(); - for ( core::list::ConstIterator it = children.begin(); it != children.end(); ++it ) - { - writeNodeCameras( *it ); - } -} - -void CColladaMeshWriter::writeAllMeshGeometries() -{ - core::map::ConstIterator it = Meshes.getConstIterator(); - for(; !it.atEnd(); it++ ) - { - IMesh* mesh = it->getKey(); - const SColladaMesh& colladaMesh = it->getValue(); - - if ( getGeometryWriting() == ECGI_PER_MESH_AND_MATERIAL && colladaMesh.GeometryMeshMaterials.size() > 1 ) - { - for ( u32 i=0; iisExportable(node) ) - return; - - // Collada doesn't require to set the id, but some other tools have problems if none exists, so we just add it. - irr::core::stringw nameId(nameForNode(node)); - Writer->writeElement(L"node", false, L"id", nameId.c_str()); - Writer->writeLineBreak(); - - // DummyTransformationSceneNode don't have rotation, position, scale information - // But also don't always export the transformation matrix as that forces us creating - // new DummyTransformationSceneNode's on import. - if ( node->getType() == ESNT_DUMMY_TRANSFORMATION ) - { - writeMatrixElement(node->getRelativeTransformation()); - } - else - { - irr::core::vector3df rot(node->getRotation()); - if ( isCamera(node) && !static_cast(node)->getTargetAndRotationBinding() ) - { - ICameraSceneNode * camNode = static_cast(node); - const core::vector3df toTarget = camNode->getTarget() - camNode->getAbsolutePosition(); - rot = toTarget.getHorizontalAngle(); - } - - writeTranslateElement( node->getPosition() ); - writeRotateElement( irr::core::vector3df(1.f, 0.f, 0.f), rot.X ); - writeRotateElement( irr::core::vector3df(0.f, 1.f, 0.f), rot.Y ); - writeRotateElement( irr::core::vector3df(0.f, 0.f, 1.f), rot.Z ); - writeScaleElement( node->getScale() ); - } - - // instance geometry - IMesh* mesh = getProperties()->getMesh(node); - if ( mesh ) - { - MeshNode * n = Meshes.find(mesh); - if ( n ) - { - const SColladaMesh& colladaMesh = n->getValue(); - writeMeshInstanceGeometry(colladaMesh.findGeometryNameForNode(node), mesh, node); - } - } - - // instance light - if ( node->getType() == ESNT_LIGHT ) - { - LightNode * n = LightNodes.find(node); - if ( n ) - writeLightInstance(n->getValue().Name); - } - - // instance camera - if ( isCamera(node) ) - { - CameraNode * camNode = CameraNodes.find(node); - if ( camNode ) - writeCameraInstance(camNode->getValue()); - } - - const core::list& children = node->getChildren(); - for ( core::list::ConstIterator it = children.begin(); it != children.end(); ++it ) - { - writeSceneNode( *it ); - } - - Writer->writeClosingTag(L"node"); - Writer->writeLineBreak(); -} - -//! writes a mesh -bool CColladaMeshWriter::writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 flags) -{ - if (!file) - return false; - - reset(); - - Writer = FileSystem->createXMLWriter(file); - - if (!Writer) - { - os::Printer::log("Could not write file", file->getFileName()); - return false; - } - - Directory = FileSystem->getFileDir(FileSystem->getAbsolutePath( file->getFileName() )); - - os::Printer::log("Writing mesh", file->getFileName()); - - // write COLLADA header - - Writer->writeXMLHeader(); - - Writer->writeElement(L"COLLADA", false, - L"xmlns", L"http://www.collada.org/2005/11/COLLADASchema", - L"version", L"1.4.1"); - Writer->writeLineBreak(); - - // write asset data - writeAsset(); - - // write all materials - - Writer->writeElement(L"library_materials", false); - Writer->writeLineBreak(); - - writeMeshMaterials(mesh); - - Writer->writeClosingTag(L"library_materials"); - Writer->writeLineBreak(); - - Writer->writeElement(L"library_effects", false); - Writer->writeLineBreak(); - - writeMeshEffects(mesh); - - Writer->writeClosingTag(L"library_effects"); - Writer->writeLineBreak(); - - // images - writeLibraryImages(); - - // write mesh - - Writer->writeElement(L"library_geometries", false); - Writer->writeLineBreak(); - - irr::core::stringw meshname(nameForMesh(mesh, 0)); - writeMeshGeometry(meshname, mesh); - - Writer->writeClosingTag(L"library_geometries"); - Writer->writeLineBreak(); - - // write scene_library - if ( getWriteDefaultScene() ) - { - Writer->writeElement(L"library_visual_scenes", false); - Writer->writeLineBreak(); - - Writer->writeElement(L"visual_scene", false, L"id", L"default_scene"); - Writer->writeLineBreak(); - - Writer->writeElement(L"node", false); - Writer->writeLineBreak(); - - writeMeshInstanceGeometry(meshname, mesh); - - Writer->writeClosingTag(L"node"); - Writer->writeLineBreak(); - - Writer->writeClosingTag(L"visual_scene"); - Writer->writeLineBreak(); - - Writer->writeClosingTag(L"library_visual_scenes"); - Writer->writeLineBreak(); - - - // write scene - Writer->writeElement(L"scene", false); - Writer->writeLineBreak(); - - Writer->writeElement(L"instance_visual_scene", true, L"url", L"#default_scene"); - Writer->writeLineBreak(); - - Writer->writeClosingTag(L"scene"); - Writer->writeLineBreak(); - } - - - // close everything - - Writer->writeClosingTag(L"COLLADA"); - Writer->drop(); - - return true; -} - -void CColladaMeshWriter::writeMeshInstanceGeometry(const irr::core::stringw& meshname, scene::IMesh* mesh, scene::ISceneNode* node) -{ - // - Writer->writeElement(L"instance_geometry", false, L"url", toRef(meshname).c_str()); - Writer->writeLineBreak(); - - Writer->writeElement(L"bind_material", false); - Writer->writeLineBreak(); - - Writer->writeElement(L"technique_common", false); - Writer->writeLineBreak(); - - // instance materials - // - bool useNodeMaterials = node && node->getMaterialCount() == mesh->getMeshBufferCount(); - for (u32 i=0; igetMeshBufferCount(); ++i) - { - irr::core::stringw strMatSymbol(nameForMaterialSymbol(mesh, i)); - core::stringw strMatTarget = "#"; - video::SMaterial & material = useNodeMaterials ? node->getMaterial(i) : mesh->getMeshBuffer(i)->getMaterial(); - strMatTarget += nameForMaterial(material, i, mesh, node); - Writer->writeElement(L"instance_material", false, L"symbol", strMatSymbol.c_str(), L"target", strMatTarget.c_str()); - Writer->writeLineBreak(); - - // TODO: need to handle second UV-set - // - Writer->writeElement(L"bind_vertex_input", true, L"semantic", L"uv", L"input_semantic", L"TEXCOORD", L"input_set", L"0" ); - Writer->writeLineBreak(); - - Writer->writeClosingTag(L"instance_material"); - Writer->writeLineBreak(); - } - - Writer->writeClosingTag(L"technique_common"); - Writer->writeLineBreak(); - - Writer->writeClosingTag(L"bind_material"); - Writer->writeLineBreak(); - - Writer->writeClosingTag(L"instance_geometry"); - Writer->writeLineBreak(); -} - -void CColladaMeshWriter::writeLightInstance(const irr::core::stringw& lightName) -{ - Writer->writeElement(L"instance_light", true, L"url", toRef(lightName).c_str()); - Writer->writeLineBreak(); -} - -void CColladaMeshWriter::writeCameraInstance(const irr::core::stringw& cameraName) -{ - Writer->writeElement(L"instance_camera", true, L"url", toRef(cameraName).c_str()); - Writer->writeLineBreak(); -} - -bool CColladaMeshWriter::hasSecondTextureCoordinates(video::E_VERTEX_TYPE type) const -{ - return type == video::EVT_2TCOORDS; -} - -void CColladaMeshWriter::writeVector(const irr::core::vector3df& vec) -{ - wchar_t tmpbuf[255]; - swprintf(tmpbuf, 255, L"%f %f %f", vec.X, vec.Y, vec.Z); - - Writer->writeText(tmpbuf); -} - -void CColladaMeshWriter::writeUv(const irr::core::vector2df& vec) -{ - // change handedness - wchar_t tmpbuf[255]; - swprintf(tmpbuf, 255, L"%f %f", vec.X, 1.f-vec.Y); - - Writer->writeText(tmpbuf); -} - -void CColladaMeshWriter::writeVector(const irr::core::vector2df& vec) -{ - wchar_t tmpbuf[255]; - swprintf(tmpbuf, 255, L"%f %f", vec.X, vec.Y); - - Writer->writeText(tmpbuf); -} - -void CColladaMeshWriter::writeColor(const irr::video::SColorf& colorf, bool writeAlpha) -{ - wchar_t tmpbuf[255]; - if ( writeAlpha ) - swprintf(tmpbuf, 255, L"%f %f %f %f", colorf.getRed(), colorf.getGreen(), colorf.getBlue(), colorf.getAlpha()); - else - swprintf(tmpbuf, 255, L"%f %f %f", colorf.getRed(), colorf.getGreen(), colorf.getBlue()); - - Writer->writeText(tmpbuf); -} - -irr::core::stringw CColladaMeshWriter::toString(const irr::video::ECOLOR_FORMAT format) const -{ - switch ( format ) - { - case video::ECF_A1R5G5B5: return irr::core::stringw(L"A1R5G5B5"); - case video::ECF_R5G6B5: return irr::core::stringw(L"R5G6B5"); - case video::ECF_R8G8B8: return irr::core::stringw(L"R8G8B8"); - case video::ECF_A8R8G8B8: return irr::core::stringw(L"A8R8G8B8"); - default: return irr::core::stringw(L""); - } -} - -irr::core::stringw CColladaMeshWriter::toString(const irr::video::E_TEXTURE_CLAMP clamp) const -{ - switch ( clamp ) - { - case video::ETC_REPEAT: - return core::stringw(L"WRAP"); - case video::ETC_CLAMP: - case video::ETC_CLAMP_TO_EDGE: - return core::stringw(L"CLAMP"); - case video::ETC_CLAMP_TO_BORDER: - return core::stringw(L"BORDER"); - case video::ETC_MIRROR: - case video::ETC_MIRROR_CLAMP: - case video::ETC_MIRROR_CLAMP_TO_EDGE: - case video::ETC_MIRROR_CLAMP_TO_BORDER: - return core::stringw(L"MIRROR"); - } - return core::stringw(L"NONE"); -} - -irr::core::stringw CColladaMeshWriter::toString(const irr::scene::E_COLLADA_TRANSPARENT_FX transparent) const -{ - if ( transparent & ECOF_RGB_ZERO ) - return core::stringw(L"RGB_ZERO"); - else - return core::stringw(L"A_ONE"); -} - -irr::core::stringw CColladaMeshWriter::toRef(const irr::core::stringw& source) const -{ - irr::core::stringw ref(L"#"); - ref += source; - return ref; -} - -bool CColladaMeshWriter::isCamera(const scene::ISceneNode* node) const -{ - // TODO: we need some ISceneNode::hasType() function to get rid of those checks - if ( node->getType() == ESNT_CAMERA - || node->getType() == ESNT_CAMERA_MAYA - || node->getType() == ESNT_CAMERA_FPS ) - return true; - return false; -} - -irr::core::stringw CColladaMeshWriter::nameForMesh(const scene::IMesh* mesh, int instance) const -{ - IColladaMeshWriterNames * nameGenerator = getNameGenerator(); - if ( nameGenerator ) - { - return nameGenerator->nameForMesh(mesh, instance); - } - return irr::core::stringw(L"missing_name_generator"); -} - -irr::core::stringw CColladaMeshWriter::nameForNode(const scene::ISceneNode* node) const -{ - IColladaMeshWriterNames * nameGenerator = getNameGenerator(); - if ( nameGenerator ) - { - return nameGenerator->nameForNode(node); - } - return irr::core::stringw(L"missing_name_generator"); -} - -irr::core::stringw CColladaMeshWriter::nameForMaterial(const video::SMaterial & material, int materialId, const scene::IMesh* mesh, const scene::ISceneNode* node) -{ - irr::core::stringw matName; - if ( getExportSMaterialsOnlyOnce() ) - { - matName = findCachedMaterialName(material); - if ( !matName.empty() ) - return matName; - } - - IColladaMeshWriterNames * nameGenerator = getNameGenerator(); - if ( nameGenerator ) - { - matName = nameGenerator->nameForMaterial(material, materialId, mesh, node); - } - else - matName = irr::core::stringw(L"missing_name_generator"); - - if ( getExportSMaterialsOnlyOnce() ) - MaterialNameCache.push_back (MaterialName(material, matName)); - return matName; -} - -// Each mesh-material has one symbol which is replaced on instantiation -irr::core::stringw CColladaMeshWriter::nameForMaterialSymbol(const scene::IMesh* mesh, int materialId) const -{ - wchar_t buf[100]; - swprintf(buf, 100, L"mat_symb_%p_%d", mesh, materialId); - return irr::core::stringw(buf); -} - -irr::core::stringw CColladaMeshWriter::findCachedMaterialName(const irr::video::SMaterial& material) const -{ - for ( u32 i=0; i= 'A' && c <= 'Z') - || c == L'_' - || (c >= 'a' && c <= 'z') - || (c >= 0xC0 && c <= 0xD6) - || (c >= 0xD8 && c <= 0xF6) - || (c >= 0xF8 && c <= 0x2FF) - || (c >= 0x370 && c <= 0x37D) - || (c >= 0x37F && c <= 0x1FFF) - || (c >= 0x200C && c <= 0x200D) - || (c >= 0x2070 && c <= 0x218F) - || (c >= 0x2C00 && c <= 0x2FEF) - || (c >= 0x3001 && c <= 0xD7FF) - || (c >= 0xF900 && c <= 0xFDCF) - || (c >= 0xFDF0 && c <= 0xFFFD) -#if __SIZEOF_WCHAR_T__ == 4 || __WCHAR_MAX__ > 0x10000 - || (c >= 0x10000 && c <= 0xEFFFF) -#endif - ; -} - -bool CColladaMeshWriter::isXmlNameChar(wchar_t c) const -{ - return isXmlNameStartChar(c) - || c == L'-' - || c == L'.' - || (c >= '0' && c <= '9') - || c == 0xB7 - || (c >= 0x0300 && c <= 0x036F) - || (c >= 0x203F && c <= 0x2040); -} - -// Restrict the characters to a set of allowed characters in xs::NCName. -irr::core::stringw CColladaMeshWriter::toNCName(const irr::core::stringw& oldString, const irr::core::stringw& prefix) const -{ - irr::core::stringw result(prefix); // help to ensure id starts with a valid char and reduce chance of name-conflicts - if ( oldString.empty() ) - return result; - - result.append( oldString ); - - // We replace all characters not allowed by a replacement char - const wchar_t REPLACMENT = L'-'; - for ( irr::u32 i=1; i < result.size(); ++i ) - { - if ( result[i] == L':' || !isXmlNameChar(result[i]) ) - { - result[i] = REPLACMENT; - } - } - return result; -} - -// Restrict the characters to a set of allowed characters in xs::NCName. -irr::core::stringw CColladaMeshWriter::pathToURI(const irr::io::path& path) const -{ - irr::core::stringw result; - - // is this a relative path? - if ( path.size() > 1 - && path[0] != _IRR_TEXT('/') - && path[0] != _IRR_TEXT('\\') - && path[1] != _IRR_TEXT(':') ) - { - // not already starting with "./" ? - if ( path[0] != _IRR_TEXT('.') - || path[1] != _IRR_TEXT('/') ) - { - result.append(L"./"); - } - } - result.append(path); - - // TODO: make correct URI (without whitespaces) - - return result; -} - -void CColladaMeshWriter::writeAsset() -{ - Writer->writeElement(L"asset", false); - Writer->writeLineBreak(); - - Writer->writeElement(L"contributor", false); - Writer->writeLineBreak(); - Writer->writeElement(L"authoring_tool", false); - Writer->writeText(L"Irrlicht Engine / irrEdit"); // this code has originated from irrEdit 0.7 - Writer->writeClosingTag(L"authoring_tool"); - Writer->writeLineBreak(); - Writer->writeClosingTag(L"contributor"); - Writer->writeLineBreak(); - - // The next two are required - Writer->writeElement(L"created", false); - Writer->writeText(L"2008-01-31T00:00:00Z"); - Writer->writeClosingTag(L"created"); - Writer->writeLineBreak(); - - Writer->writeElement(L"modified", false); - Writer->writeText(L"2008-01-31T00:00:00Z"); - Writer->writeClosingTag(L"modified"); - Writer->writeLineBreak(); - - Writer->writeElement(L"revision", false); - Writer->writeText(L"1.0"); - Writer->writeClosingTag(L"revision"); - Writer->writeLineBreak(); - - Writer->writeClosingTag(L"asset"); - Writer->writeLineBreak(); -} - -void CColladaMeshWriter::writeMeshMaterials(scene::IMesh* mesh, irr::core::array * materialNamesOut) -{ - u32 i; - for (i=0; igetMeshBufferCount(); ++i) - { - video::SMaterial & material = mesh->getMeshBuffer(i)->getMaterial(); - core::stringw strMat(nameForMaterial(material, i, mesh, NULL)); - writeMaterial(strMat); - if ( materialNamesOut ) - materialNamesOut->push_back(strMat); - } -} - -void CColladaMeshWriter::writeMaterialEffect(const irr::core::stringw& materialfxname, const video::SMaterial & material) -{ - if ( EffectsWritten.find(materialfxname) ) - return; - EffectsWritten.insert(materialfxname, true); - - Writer->writeElement(L"effect", false, - L"id", materialfxname.c_str(), - L"name", materialfxname.c_str()); - Writer->writeLineBreak(); - Writer->writeElement(L"profile_COMMON", false); - Writer->writeLineBreak(); - - int numTextures = 0; - if ( getWriteTextures() ) - { - // write texture surfaces and samplers and buffer all used imagess - for ( int t=0; t<4; ++t ) - { - const video::SMaterialLayer& layer = material.TextureLayer[t]; - if ( !layer.Texture ) - break; - ++numTextures; - - if ( LibraryImages.linear_search(layer.Texture) < 0 ) - LibraryImages.push_back( layer.Texture ); - - irr::core::stringw texName("tex"); - texName += irr::core::stringw(t); - - // write texture surface - // - irr::core::stringw texSurface(texName); - texSurface += L"-surface"; - Writer->writeElement(L"newparam", false, L"sid", texSurface.c_str()); - Writer->writeLineBreak(); - // - Writer->writeElement(L"surface", false, L"type", L"2D"); - Writer->writeLineBreak(); - - // internal_texturename - Writer->writeElement(L"init_from", false); - irr::io::path p(FileSystem->getRelativeFilename(layer.Texture->getName().getPath(), Directory)); - Writer->writeText(toNCName(irr::core::stringw(p)).c_str()); - Writer->writeClosingTag(L"init_from"); - Writer->writeLineBreak(); - - // A8R8G8B8 - Writer->writeElement(L"format", false); - video::ECOLOR_FORMAT format = layer.Texture->getColorFormat(); - Writer->writeText(toString(format).c_str()); - Writer->writeClosingTag(L"format"); - Writer->writeLineBreak(); - // - Writer->writeClosingTag(L"surface"); - Writer->writeLineBreak(); - // - Writer->writeClosingTag(L"newparam"); - Writer->writeLineBreak(); - - // write texture sampler - // - irr::core::stringw texSampler(texName); - texSampler += L"-sampler"; - Writer->writeElement(L"newparam", false, L"sid", texSampler.c_str()); - Writer->writeLineBreak(); - // - Writer->writeElement(L"sampler2D", false); - Writer->writeLineBreak(); - - // tex0-surface - Writer->writeElement(L"source", false); - Writer->writeText(texSurface.c_str()); - Writer->writeClosingTag(L"source"); - Writer->writeLineBreak(); - - // WRAP - Writer->writeElement(L"wrap_s", false); - Writer->writeText(toString((video::E_TEXTURE_CLAMP)layer.TextureWrapU).c_str()); - Writer->writeClosingTag(L"wrap_s"); - Writer->writeLineBreak(); - - // WRAP - Writer->writeElement(L"wrap_t", false); - Writer->writeText(toString((video::E_TEXTURE_CLAMP)layer.TextureWrapV).c_str()); - Writer->writeClosingTag(L"wrap_t"); - Writer->writeLineBreak(); - - // LINEAR_MIPMAP_LINEAR - Writer->writeElement(L"minfilter", false); - Writer->writeText(minTexfilterToString(layer.BilinearFilter, layer.TrilinearFilter).c_str()); - Writer->writeClosingTag(L"minfilter"); - Writer->writeLineBreak(); - - // LINEAR - Writer->writeElement(L"magfilter", false); - Writer->writeText(magTexfilterToString(layer.BilinearFilter, layer.TrilinearFilter).c_str()); - Writer->writeClosingTag(L"magfilter"); - Writer->writeLineBreak(); - - // TBD - actually not sure how anisotropic should be written, so for now it writes in a way - // that works with the way the loader reads it again. - if ( layer.AnisotropicFilter ) - { - // LINEAR_MIPMAP_LINEAR - Writer->writeElement(L"mipfilter", false); - Writer->writeText(L"LINEAR_MIPMAP_LINEAR"); - Writer->writeClosingTag(L"mipfilter"); - Writer->writeLineBreak(); - } - - // - Writer->writeClosingTag(L"sampler2D"); - Writer->writeLineBreak(); - // - Writer->writeClosingTag(L"newparam"); - Writer->writeLineBreak(); - } - } - - Writer->writeElement(L"technique", false, L"sid", L"common"); - Writer->writeLineBreak(); - - E_COLLADA_TECHNIQUE_FX techFx = getProperties() ? getProperties()->getTechniqueFx(material) : ECTF_BLINN; - writeFxElement(material, techFx); - - Writer->writeClosingTag(L"technique"); - Writer->writeLineBreak(); - Writer->writeClosingTag(L"profile_COMMON"); - Writer->writeLineBreak(); - Writer->writeClosingTag(L"effect"); - Writer->writeLineBreak(); -} - -void CColladaMeshWriter::writeMeshEffects(scene::IMesh* mesh) -{ - for (u32 i=0; igetMeshBufferCount(); ++i) - { - video::SMaterial & material = mesh->getMeshBuffer(i)->getMaterial(); - irr::core::stringw materialfxname(nameForMaterial(material, i, mesh, NULL)); - materialfxname += L"-fx"; - writeMaterialEffect(materialfxname, material); - } -} - -void CColladaMeshWriter::writeMeshGeometry(const irr::core::stringw& meshname, scene::IMesh* mesh) -{ - core::stringw meshId(meshname); - - Writer->writeElement(L"geometry", false, L"id", meshId.c_str(), L"name", meshId.c_str()); - Writer->writeLineBreak(); - Writer->writeElement(L"mesh"); - Writer->writeLineBreak(); - - // do some statistics for the mesh to know which stuff needs to be saved into - // the file: - // - count vertices - // - check for the need of a second texture coordinate - // - count amount of second texture coordinates - // - check for the need of tangents (TODO) - - u32 totalVertexCount = 0; - u32 totalTCoords2Count = 0; - bool needsTangents = false; // TODO: tangents not supported here yet - u32 i=0; - for (i=0; igetMeshBufferCount(); ++i) - { - totalVertexCount += mesh->getMeshBuffer(i)->getVertexCount(); - - if (hasSecondTextureCoordinates(mesh->getMeshBuffer(i)->getVertexType())) - totalTCoords2Count += mesh->getMeshBuffer(i)->getVertexCount(); - - if (!needsTangents) - needsTangents = mesh->getMeshBuffer(i)->getVertexType() == video::EVT_TANGENTS; - } - - SComponentGlobalStartPos* globalIndices = new SComponentGlobalStartPos[mesh->getMeshBufferCount()]; - - // write positions - core::stringw meshPosId(meshId); - meshPosId += L"-Pos"; - Writer->writeElement(L"source", false, L"id", meshPosId.c_str()); - Writer->writeLineBreak(); - - core::stringw vertexCountStr(totalVertexCount*3); - core::stringw meshPosArrayId(meshPosId); - meshPosArrayId += L"-array"; - Writer->writeElement(L"float_array", false, L"id", meshPosArrayId.c_str(), - L"count", vertexCountStr.c_str()); - Writer->writeLineBreak(); - - for (i=0; igetMeshBufferCount(); ++i) - { - scene::IMeshBuffer* buffer = mesh->getMeshBuffer(i); - video::E_VERTEX_TYPE vtxType = buffer->getVertexType(); - u32 vertexCount = buffer->getVertexCount(); - - globalIndices[i].PosStartIndex = 0; - - if (i!=0) - globalIndices[i].PosStartIndex = globalIndices[i-1].PosLastIndex + 1; - - globalIndices[i].PosLastIndex = globalIndices[i].PosStartIndex + vertexCount - 1; - - switch(vtxType) - { - case video::EVT_STANDARD: - { - video::S3DVertex* vtx = (video::S3DVertex*)buffer->getVertices(); - for (u32 j=0; jwriteLineBreak(); - } - } - break; - case video::EVT_2TCOORDS: - { - video::S3DVertex2TCoords* vtx = (video::S3DVertex2TCoords*)buffer->getVertices(); - for (u32 j=0; jwriteLineBreak(); - } - } - break; - case video::EVT_TANGENTS: - { - video::S3DVertexTangents* vtx = (video::S3DVertexTangents*)buffer->getVertices(); - for (u32 j=0; jwriteLineBreak(); - } - } - break; - } - } - - Writer->writeClosingTag(L"float_array"); - Writer->writeLineBreak(); - - Writer->writeElement(L"technique_common", false); - Writer->writeLineBreak(); - - vertexCountStr = core::stringw(totalVertexCount); - - Writer->writeElement(L"accessor", false, L"source", toRef(meshPosArrayId).c_str(), - L"count", vertexCountStr.c_str(), L"stride", L"3"); - Writer->writeLineBreak(); - - Writer->writeElement(L"param", true, L"name", L"X", L"type", L"float"); - Writer->writeLineBreak(); - Writer->writeElement(L"param", true, L"name", L"Y", L"type", L"float"); - Writer->writeLineBreak(); - Writer->writeElement(L"param", true, L"name", L"Z", L"type", L"float"); - Writer->writeLineBreak(); - - Writer->writeClosingTag(L"accessor"); - Writer->writeLineBreak(); - - Writer->writeClosingTag(L"technique_common"); - Writer->writeLineBreak(); - - Writer->writeClosingTag(L"source"); - Writer->writeLineBreak(); - - // write texture coordinates - - core::stringw meshTexCoord0Id(meshId); - meshTexCoord0Id += L"-TexCoord0"; - Writer->writeElement(L"source", false, L"id", meshTexCoord0Id.c_str()); - Writer->writeLineBreak(); - - vertexCountStr = core::stringw(totalVertexCount*2); - core::stringw meshTexCoordArrayId(meshTexCoord0Id); - meshTexCoordArrayId += L"-array"; - Writer->writeElement(L"float_array", false, L"id", meshTexCoordArrayId.c_str(), - L"count", vertexCountStr.c_str()); - Writer->writeLineBreak(); - - for (i=0; igetMeshBufferCount(); ++i) - { - scene::IMeshBuffer* buffer = mesh->getMeshBuffer(i); - video::E_VERTEX_TYPE vtxType = buffer->getVertexType(); - u32 vertexCount = buffer->getVertexCount(); - - globalIndices[i].TCoord0StartIndex = 0; - - if (i!=0) - globalIndices[i].TCoord0StartIndex = globalIndices[i-1].TCoord0LastIndex + 1; - - globalIndices[i].TCoord0LastIndex = globalIndices[i].TCoord0StartIndex + vertexCount - 1; - - switch(vtxType) - { - case video::EVT_STANDARD: - { - video::S3DVertex* vtx = (video::S3DVertex*)buffer->getVertices(); - for (u32 j=0; jwriteLineBreak(); - } - } - break; - case video::EVT_2TCOORDS: - { - video::S3DVertex2TCoords* vtx = (video::S3DVertex2TCoords*)buffer->getVertices(); - for (u32 j=0; jwriteLineBreak(); - } - } - break; - case video::EVT_TANGENTS: - { - video::S3DVertexTangents* vtx = (video::S3DVertexTangents*)buffer->getVertices(); - for (u32 j=0; jwriteLineBreak(); - } - } - break; - } - } - - Writer->writeClosingTag(L"float_array"); - Writer->writeLineBreak(); - - Writer->writeElement(L"technique_common", false); - Writer->writeLineBreak(); - - vertexCountStr = core::stringw(totalVertexCount); - - Writer->writeElement(L"accessor", false, L"source", toRef(meshTexCoordArrayId).c_str(), - L"count", vertexCountStr.c_str(), L"stride", L"2"); - Writer->writeLineBreak(); - - Writer->writeElement(L"param", true, L"name", L"U", L"type", L"float"); - Writer->writeLineBreak(); - Writer->writeElement(L"param", true, L"name", L"V", L"type", L"float"); - Writer->writeLineBreak(); - - Writer->writeClosingTag(L"accessor"); - Writer->writeLineBreak(); - - Writer->writeClosingTag(L"technique_common"); - Writer->writeLineBreak(); - - Writer->writeClosingTag(L"source"); - Writer->writeLineBreak(); - - // write normals - core::stringw meshNormalId(meshId); - meshNormalId += L"-Normal"; - Writer->writeElement(L"source", false, L"id", meshNormalId.c_str()); - Writer->writeLineBreak(); - - vertexCountStr = core::stringw(totalVertexCount*3); - core::stringw meshNormalArrayId(meshNormalId); - meshNormalArrayId += L"-array"; - Writer->writeElement(L"float_array", false, L"id", meshNormalArrayId.c_str(), - L"count", vertexCountStr.c_str()); - Writer->writeLineBreak(); - - for (i=0; igetMeshBufferCount(); ++i) - { - scene::IMeshBuffer* buffer = mesh->getMeshBuffer(i); - video::E_VERTEX_TYPE vtxType = buffer->getVertexType(); - u32 vertexCount = buffer->getVertexCount(); - - globalIndices[i].NormalStartIndex = 0; - - if (i!=0) - globalIndices[i].NormalStartIndex = globalIndices[i-1].NormalLastIndex + 1; - - globalIndices[i].NormalLastIndex = globalIndices[i].NormalStartIndex + vertexCount - 1; - - switch(vtxType) - { - case video::EVT_STANDARD: - { - video::S3DVertex* vtx = (video::S3DVertex*)buffer->getVertices(); - for (u32 j=0; jwriteLineBreak(); - } - } - break; - case video::EVT_2TCOORDS: - { - video::S3DVertex2TCoords* vtx = (video::S3DVertex2TCoords*)buffer->getVertices(); - for (u32 j=0; jwriteLineBreak(); - } - } - break; - case video::EVT_TANGENTS: - { - video::S3DVertexTangents* vtx = (video::S3DVertexTangents*)buffer->getVertices(); - for (u32 j=0; jwriteLineBreak(); - } - } - break; - } - } - - Writer->writeClosingTag(L"float_array"); - Writer->writeLineBreak(); - - Writer->writeElement(L"technique_common", false); - Writer->writeLineBreak(); - - vertexCountStr = core::stringw(totalVertexCount); - - Writer->writeElement(L"accessor", false, L"source", toRef(meshNormalArrayId).c_str(), - L"count", vertexCountStr.c_str(), L"stride", L"3"); - Writer->writeLineBreak(); - - Writer->writeElement(L"param", true, L"name", L"X", L"type", L"float"); - Writer->writeLineBreak(); - Writer->writeElement(L"param", true, L"name", L"Y", L"type", L"float"); - Writer->writeLineBreak(); - Writer->writeElement(L"param", true, L"name", L"Z", L"type", L"float"); - Writer->writeLineBreak(); - - Writer->writeClosingTag(L"accessor"); - Writer->writeLineBreak(); - - Writer->writeClosingTag(L"technique_common"); - Writer->writeLineBreak(); - - Writer->writeClosingTag(L"source"); - Writer->writeLineBreak(); - - // write second set of texture coordinates - core::stringw meshTexCoord1Id(meshId); - meshTexCoord1Id += L"-TexCoord1"; - if (totalTCoords2Count) - { - Writer->writeElement(L"source", false, L"id", meshTexCoord1Id.c_str()); - Writer->writeLineBreak(); - - vertexCountStr = core::stringw(totalTCoords2Count*2); - core::stringw meshTexCoord1ArrayId(meshTexCoord1Id); - meshTexCoord1ArrayId += L"-array"; - Writer->writeElement(L"float_array", false, L"id", meshTexCoord1ArrayId.c_str(), - L"count", vertexCountStr.c_str()); - Writer->writeLineBreak(); - - for (i=0; igetMeshBufferCount(); ++i) - { - scene::IMeshBuffer* buffer = mesh->getMeshBuffer(i); - video::E_VERTEX_TYPE vtxType = buffer->getVertexType(); - u32 vertexCount = buffer->getVertexCount(); - - if (hasSecondTextureCoordinates(vtxType)) - { - globalIndices[i].TCoord1StartIndex = 0; - - if (i!=0 && globalIndices[i-1].TCoord1LastIndex != -1) - globalIndices[i].TCoord1StartIndex = globalIndices[i-1].TCoord1LastIndex + 1; - - globalIndices[i].TCoord1LastIndex = globalIndices[i].TCoord1StartIndex + vertexCount - 1; - - switch(vtxType) - { - case video::EVT_2TCOORDS: - { - video::S3DVertex2TCoords* vtx = (video::S3DVertex2TCoords*)buffer->getVertices(); - for (u32 j=0; jwriteLineBreak(); - } - } - break; - default: - break; - } - } // end this buffer has 2 texture coordinates - } - - Writer->writeClosingTag(L"float_array"); - Writer->writeLineBreak(); - - Writer->writeElement(L"technique_common", false); - Writer->writeLineBreak(); - - vertexCountStr = core::stringw(totalTCoords2Count); - - Writer->writeElement(L"accessor", false, L"source", toRef(meshTexCoord1ArrayId).c_str(), - L"count", vertexCountStr.c_str(), L"stride", L"2"); - Writer->writeLineBreak(); - - Writer->writeElement(L"param", true, L"name", L"U", L"type", L"float"); - Writer->writeLineBreak(); - Writer->writeElement(L"param", true, L"name", L"V", L"type", L"float"); - Writer->writeLineBreak(); - - Writer->writeClosingTag(L"accessor"); - Writer->writeLineBreak(); - - Writer->writeClosingTag(L"technique_common"); - Writer->writeLineBreak(); - - Writer->writeClosingTag(L"source"); - Writer->writeLineBreak(); - } - - // write tangents - - // TODO - - // write vertices - core::stringw meshVtxId(meshId); - meshVtxId += L"-Vtx"; - Writer->writeElement(L"vertices", false, L"id", meshVtxId.c_str()); - Writer->writeLineBreak(); - - Writer->writeElement(L"input", true, L"semantic", L"POSITION", L"source", toRef(meshPosId).c_str()); - Writer->writeLineBreak(); - - Writer->writeClosingTag(L"vertices"); - Writer->writeLineBreak(); - - // write polygons - - for (i=0; igetMeshBufferCount(); ++i) - { - scene::IMeshBuffer* buffer = mesh->getMeshBuffer(i); - - const u32 polyCount = buffer->getIndexCount() / 3; - core::stringw strPolyCount(polyCount); - irr::core::stringw strMat(nameForMaterialSymbol(mesh, i)); - - Writer->writeElement(L"triangles", false, L"count", strPolyCount.c_str(), - L"material", strMat.c_str()); - Writer->writeLineBreak(); - - Writer->writeElement(L"input", true, L"semantic", L"VERTEX", L"source", toRef(meshVtxId).c_str(), L"offset", L"0"); - Writer->writeLineBreak(); - Writer->writeElement(L"input", true, L"semantic", L"TEXCOORD", L"source", toRef(meshTexCoord0Id).c_str(), L"offset", L"1", L"set", L"0"); - Writer->writeLineBreak(); - Writer->writeElement(L"input", true, L"semantic", L"NORMAL", L"source", toRef(meshNormalId).c_str(), L"offset", L"2"); - Writer->writeLineBreak(); - - bool has2ndTexCoords = hasSecondTextureCoordinates(buffer->getVertexType()); - if (has2ndTexCoords) - { - // TODO: when working on second uv-set - my suspicion is that this one should be called "TEXCOORD2" - // to allow bind_vertex_input to differentiate the uv-sets. - Writer->writeElement(L"input", true, L"semantic", L"TEXCOORD", L"source", toRef(meshTexCoord1Id).c_str(), L"idx", L"3"); - Writer->writeLineBreak(); - } - - // write indices now - - s32 posIdx = globalIndices[i].PosStartIndex; - s32 tCoordIdx = globalIndices[i].TCoord0StartIndex; - s32 normalIdx = globalIndices[i].NormalStartIndex; - s32 tCoord2Idx = globalIndices[i].TCoord1StartIndex; - - Writer->writeElement(L"p", false); - - core::stringw strP; - strP.reserve(100); - for (u32 p=0; pgetIndices()[(p*3) + 0] + posIdx; - strP += " "; - strP += buffer->getIndices()[(p*3) + 0] + tCoordIdx; - strP += " "; - strP += buffer->getIndices()[(p*3) + 0] + normalIdx; - strP += " "; - if (has2ndTexCoords) - { - strP += buffer->getIndices()[(p*3) + 0] + tCoord2Idx; - strP += " "; - } - - strP += buffer->getIndices()[(p*3) + 1] + posIdx; - strP += " "; - strP += buffer->getIndices()[(p*3) + 1] + tCoordIdx; - strP += " "; - strP += buffer->getIndices()[(p*3) + 1] + normalIdx; - strP += " "; - if (has2ndTexCoords) - { - strP += buffer->getIndices()[(p*3) + 1] + tCoord2Idx; - strP += " "; - } - - strP += buffer->getIndices()[(p*3) + 2] + posIdx; - strP += " "; - strP += buffer->getIndices()[(p*3) + 2] + tCoordIdx; - strP += " "; - strP += buffer->getIndices()[(p*3) + 2] + normalIdx; - if (has2ndTexCoords) - { - strP += " "; - strP += buffer->getIndices()[(p*3) + 2] + tCoord2Idx; - } - strP += " "; - - Writer->writeText(strP.c_str()); - } - - Writer->writeClosingTag(L"p"); - Writer->writeLineBreak(); - - // close index buffer section - - Writer->writeClosingTag(L"triangles"); - Writer->writeLineBreak(); - } - - // close mesh and geometry - delete [] globalIndices; - Writer->writeClosingTag(L"mesh"); - Writer->writeLineBreak(); - Writer->writeClosingTag(L"geometry"); - Writer->writeLineBreak(); -} - -void CColladaMeshWriter::writeLibraryImages() -{ - if ( getWriteTextures() && !LibraryImages.empty() ) - { - Writer->writeElement(L"library_images", false); - Writer->writeLineBreak(); - - for ( irr::u32 i=0; igetRelativeFilename(LibraryImages[i]->getName().getPath(), Directory)); - // - irr::core::stringw ncname( toNCName(irr::core::stringw(p)) ); - Writer->writeElement(L"image", false, L"id", ncname.c_str(), L"name", ncname.c_str()); - Writer->writeLineBreak(); - // ../flowers/rose01.jpg - Writer->writeElement(L"init_from", false); - Writer->writeText(pathToURI(p).c_str()); - Writer->writeClosingTag(L"init_from"); - Writer->writeLineBreak(); - // - Writer->writeClosingTag(L"image"); - Writer->writeLineBreak(); - } - - Writer->writeClosingTag(L"library_images"); - Writer->writeLineBreak(); - } -} - -void CColladaMeshWriter::writeColorElement(const video::SColorf & col, bool writeAlpha) -{ - Writer->writeElement(L"color", false); - - writeColor(col, writeAlpha); - - Writer->writeClosingTag(L"color"); - Writer->writeLineBreak(); -} - -void CColladaMeshWriter::writeColorElement(const video::SColor & col, bool writeAlpha) -{ - writeColorElement( video::SColorf(col), writeAlpha ); -} - -void CColladaMeshWriter::writeAmbientLightElement(const video::SColorf & col) -{ - Writer->writeElement(L"light", false, L"id", L"ambientlight"); - Writer->writeLineBreak(); - - Writer->writeElement(L"technique_common", false); - Writer->writeLineBreak(); - - Writer->writeElement(L"ambient", false); - Writer->writeLineBreak(); - - writeColorElement(col, false); - - Writer->writeClosingTag(L"ambient"); - Writer->writeLineBreak(); - - Writer->writeClosingTag(L"technique_common"); - Writer->writeLineBreak(); - - Writer->writeClosingTag(L"light"); - Writer->writeLineBreak(); -} - -s32 CColladaMeshWriter::getCheckedTextureIdx(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs) -{ - if ( !getWriteTextures() - || !getProperties() ) - return -1; - - s32 idx = getProperties()->getTextureIdx(material, cs); - if ( idx >= 0 && !material.TextureLayer[idx].Texture ) - return -1; - - return idx; -} - -video::SColor CColladaMeshWriter::getColorMapping(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs, E_COLLADA_IRR_COLOR colType) -{ - switch ( colType ) - { - case ECIC_NONE: - return video::SColor(255, 0, 0, 0); - - case ECIC_CUSTOM: - return getProperties()->getCustomColor(material, cs); - - case ECIC_DIFFUSE: - return material.DiffuseColor; - - case ECIC_AMBIENT: - return material.AmbientColor; - - case ECIC_EMISSIVE: - return material.EmissiveColor; - - case ECIC_SPECULAR: - return material.SpecularColor; - } - return video::SColor(255, 0, 0, 0); -} - -void CColladaMeshWriter::writeTextureSampler(s32 textureIdx) -{ - irr::core::stringw sampler(L"tex"); - sampler += irr::core::stringw(textureIdx); - sampler += L"-sampler"; - - // - Writer->writeElement(L"texture", true, L"texture", sampler.c_str(), L"texcoord", L"uv" ); - Writer->writeLineBreak(); -} - -void CColladaMeshWriter::writeFxElement(const video::SMaterial & material, E_COLLADA_TECHNIQUE_FX techFx) -{ - core::stringw fxLabel; - bool writeEmission = true; - bool writeAmbient = true; - bool writeDiffuse = true; - bool writeSpecular = true; - bool writeShininess = true; - bool writeReflective = true; - bool writeReflectivity = true; - bool writeTransparent = true; - bool writeTransparency = true; - bool writeIndexOfRefraction = true; - switch ( techFx ) - { - case ECTF_BLINN: - fxLabel = L"blinn"; - break; - case ECTF_PHONG: - fxLabel = L"phong"; - break; - case ECTF_LAMBERT: - fxLabel = L"lambert"; - writeSpecular = false; - writeShininess = false; - break; - case ECTF_CONSTANT: - fxLabel = L"constant"; - writeAmbient = false; - writeDiffuse = false; - writeSpecular = false; - writeShininess = false; - break; - } - - Writer->writeElement(fxLabel.c_str(), false); - Writer->writeLineBreak(); - - // write all interesting material parameters - // attributes must be written in fixed order - if ( getProperties() ) - { - if ( writeEmission ) - { - writeColorFx(material, L"emission", ECCS_EMISSIVE); - } - - if ( writeAmbient ) - { - writeColorFx(material, L"ambient", ECCS_AMBIENT); - } - - if ( writeDiffuse ) - { - writeColorFx(material, L"diffuse", ECCS_DIFFUSE); - } - - if ( writeSpecular ) - { - writeColorFx(material, L"specular", ECCS_SPECULAR); - } - - if ( writeShininess ) - { - Writer->writeElement(L"shininess", false); - Writer->writeLineBreak(); - writeFloatElement(material.Shininess); - Writer->writeClosingTag(L"shininess"); - Writer->writeLineBreak(); - } - - if ( writeReflective ) - { - writeColorFx(material, L"reflective", ECCS_REFLECTIVE); - } - - if ( writeReflectivity ) - { - f32 t = getProperties()->getReflectivity(material); - if ( t >= 0.f ) - { - // 1.000000 - Writer->writeElement(L"reflectivity", false); - Writer->writeLineBreak(); - writeFloatElement(t); - Writer->writeClosingTag(L"reflectivity"); - Writer->writeLineBreak(); - } - } - - if ( writeTransparent ) - { - E_COLLADA_TRANSPARENT_FX transparentFx = getProperties()->getTransparentFx(material); - writeColorFx(material, L"transparent", ECCS_TRANSPARENT, L"opaque", toString(transparentFx).c_str()); - } - - if ( writeTransparency ) - { - f32 t = getProperties()->getTransparency(material); - if ( t >= 0.f ) - { - // 1.000000 - Writer->writeElement(L"transparency", false); - Writer->writeLineBreak(); - writeFloatElement(t); - Writer->writeClosingTag(L"transparency"); - Writer->writeLineBreak(); - } - } - - if ( writeIndexOfRefraction ) - { - f32 t = getProperties()->getIndexOfRefraction(material); - if ( t >= 0.f ) - { - Writer->writeElement(L"index_of_refraction", false); - Writer->writeLineBreak(); - writeFloatElement(t); - Writer->writeClosingTag(L"index_of_refraction"); - Writer->writeLineBreak(); - } - } - } - - - Writer->writeClosingTag(fxLabel.c_str()); - Writer->writeLineBreak(); -} - -void CColladaMeshWriter::writeColorFx(const video::SMaterial & material, const wchar_t * colorname, E_COLLADA_COLOR_SAMPLER cs, const wchar_t* attr1Name, const wchar_t* attr1Value) -{ - irr::s32 idx = getCheckedTextureIdx(material, cs); - E_COLLADA_IRR_COLOR colType = idx < 0 ? getProperties()->getColorMapping(material, cs) : ECIC_NONE; - if ( idx >= 0 || colType != ECIC_NONE ) - { - Writer->writeElement(colorname, false, attr1Name, attr1Value); - Writer->writeLineBreak(); - if ( idx >= 0 ) - writeTextureSampler(idx); - else - writeColorElement(getColorMapping(material, cs, colType)); - Writer->writeClosingTag(colorname); - Writer->writeLineBreak(); - } -} - -void CColladaMeshWriter::writeNode(const wchar_t * nodeName, const wchar_t * content) -{ - Writer->writeElement(nodeName, false); - Writer->writeText(content); - Writer->writeClosingTag(nodeName); - Writer->writeLineBreak(); -} - -void CColladaMeshWriter::writeFloatElement(irr::f32 value) -{ - Writer->writeElement(L"float", false); - Writer->writeText(core::stringw((double)value).c_str()); - Writer->writeClosingTag(L"float"); - Writer->writeLineBreak(); -} - -void CColladaMeshWriter::writeRotateElement(const irr::core::vector3df& axis, irr::f32 angle) -{ - Writer->writeElement(L"rotate", false); - irr::core::stringw txt(axis.X); - txt += L" "; - txt += irr::core::stringw(axis.Y); - txt += L" "; - txt += irr::core::stringw(axis.Z); - txt += L" "; - txt += irr::core::stringw((double)angle); - Writer->writeText(txt.c_str()); - Writer->writeClosingTag(L"rotate"); - Writer->writeLineBreak(); -} - -void CColladaMeshWriter::writeScaleElement(const irr::core::vector3df& scale) -{ - Writer->writeElement(L"scale", false); - irr::core::stringw txt(scale.X); - txt += L" "; - txt += irr::core::stringw(scale.Y); - txt += L" "; - txt += irr::core::stringw(scale.Z); - Writer->writeText(txt.c_str()); - Writer->writeClosingTag(L"scale"); - Writer->writeLineBreak(); -} - -void CColladaMeshWriter::writeTranslateElement(const irr::core::vector3df& translate) -{ - Writer->writeElement(L"translate", false); - irr::core::stringw txt(translate.X); - txt += L" "; - txt += irr::core::stringw(translate.Y); - txt += L" "; - txt += irr::core::stringw(translate.Z); - Writer->writeText(txt.c_str()); - Writer->writeClosingTag(L"translate"); - Writer->writeLineBreak(); -} - -void CColladaMeshWriter::writeMatrixElement(const irr::core::matrix4& matrix) -{ - Writer->writeElement(L"matrix", false); - Writer->writeLineBreak(); - - for ( int a=0; a<4; ++a ) - { - irr::core::stringw txt; - for ( int b=0; b<4; ++b ) - { - if ( b > 0 ) - txt += " "; - // row-column switched compared to Irrlicht - txt += irr::core::stringw(matrix[b*4+a]); - } - Writer->writeText(txt.c_str()); - Writer->writeLineBreak(); - } - - Writer->writeClosingTag(L"matrix"); - Writer->writeLineBreak(); -} - -} // end namespace -} // end namespace - -#endif - diff --git a/lib/irrlicht/source/Irrlicht/CColladaMeshWriter.h b/lib/irrlicht/source/Irrlicht/CColladaMeshWriter.h deleted file mode 100644 index 61f2a2756..000000000 --- a/lib/irrlicht/source/Irrlicht/CColladaMeshWriter.h +++ /dev/null @@ -1,271 +0,0 @@ -// Copyright (C) 2002-2012 Nikolaus Gebhardt -// This file is part of the "Irrlicht Engine". -// For conditions of distribution and use, see copyright notice in irrlicht.h - -#ifndef __IRR_C_COLLADA_MESH_WRITER_H_INCLUDED__ -#define __IRR_C_COLLADA_MESH_WRITER_H_INCLUDED__ - -#include "IColladaMeshWriter.h" -#include "S3DVertex.h" -#include "irrMap.h" -#include "IVideoDriver.h" - -namespace irr -{ -namespace io -{ - class IXMLWriter; - class IFileSystem; -} - -namespace scene -{ - //! Callback interface for properties which can be used to influence collada writing - // (Implementer note: keep namespace labels here to make it easier for users copying this one) - class CColladaMeshWriterProperties : public virtual IColladaMeshWriterProperties - { - public: - //! Which lighting model should be used in the technique (FX) section when exporting effects (materials) - virtual irr::scene::E_COLLADA_TECHNIQUE_FX getTechniqueFx(const irr::video::SMaterial& material) const; - - //! Which texture index should be used when writing the texture of the given sampler color. - virtual irr::s32 getTextureIdx(const irr::video::SMaterial & material, irr::scene::E_COLLADA_COLOR_SAMPLER cs) const; - - //! Return which color from Irrlicht should be used for the color requested by collada - virtual irr::scene::E_COLLADA_IRR_COLOR getColorMapping(const irr::video::SMaterial & material, irr::scene::E_COLLADA_COLOR_SAMPLER cs) const; - - //! Return custom colors for certain color types requested by collada. - virtual irr::video::SColor getCustomColor(const irr::video::SMaterial & material, irr::scene::E_COLLADA_COLOR_SAMPLER cs) const; - - //! Return the settings for transparence - virtual irr::scene::E_COLLADA_TRANSPARENT_FX getTransparentFx(const irr::video::SMaterial& material) const; - - //! Transparency value for that material. - virtual irr::f32 getTransparency(const irr::video::SMaterial& material) const; - - //! Reflectivity value for that material - virtual irr::f32 getReflectivity(const irr::video::SMaterial& material) const; - - //! Return index of refraction for that material - virtual irr::f32 getIndexOfRefraction(const irr::video::SMaterial& material) const; - - //! Should node be used in scene export? By default all visible nodes are exported. - virtual bool isExportable(const irr::scene::ISceneNode * node) const; - - //! Return the mesh for the given nod. If it has no mesh or shouldn't export it's mesh return 0. - virtual irr::scene::IMesh* getMesh(irr::scene::ISceneNode * node); - - //! Return if the node has it's own material overwriting the mesh-materials - virtual bool useNodeMaterial(const scene::ISceneNode* node) const; - }; - - class CColladaMeshWriterNames : public virtual IColladaMeshWriterNames - { - public: - CColladaMeshWriterNames(IColladaMeshWriter * writer); - virtual irr::core::stringw nameForMesh(const scene::IMesh* mesh, int instance); - virtual irr::core::stringw nameForNode(const scene::ISceneNode* node); - virtual irr::core::stringw nameForMaterial(const video::SMaterial & material, int materialId, const scene::IMesh* mesh, const scene::ISceneNode* node); - protected: - irr::core::stringw nameForPtr(const void* ptr) const; - private: - IColladaMeshWriter * ColladaMeshWriter; - }; - - - -//! class to write meshes, implementing a COLLADA (.dae, .xml) writer -/** This writer implementation has been originally developed for irrEdit and then -merged out to the Irrlicht Engine */ -class CColladaMeshWriter : public IColladaMeshWriter -{ -public: - - CColladaMeshWriter(ISceneManager * smgr, video::IVideoDriver* driver, io::IFileSystem* fs); - virtual ~CColladaMeshWriter(); - - //! Returns the type of the mesh writer - virtual EMESH_WRITER_TYPE getType() const; - - //! writes a scene starting with the given node - virtual bool writeScene(io::IWriteFile* file, scene::ISceneNode* root); - - //! writes a mesh - virtual bool writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 flags=EMWF_NONE); - - // Restrict the characters of oldString a set of allowed characters in xs::NCName and add the prefix. - virtual irr::core::stringw toNCName(const irr::core::stringw& oldString, const irr::core::stringw& prefix=irr::core::stringw(L"_NC_")) const; - -protected: - - void reset(); - bool hasSecondTextureCoordinates(video::E_VERTEX_TYPE type) const; - void writeUv(const irr::core::vector2df& vec); - void writeVector(const irr::core::vector2df& vec); - void writeVector(const irr::core::vector3df& vec); - void writeColor(const irr::video::SColorf& colorf, bool writeAlpha=true); - inline irr::core::stringw toString(const irr::video::ECOLOR_FORMAT format) const; - inline irr::core::stringw toString(const irr::video::E_TEXTURE_CLAMP clamp) const; - inline irr::core::stringw toString(const irr::scene::E_COLLADA_TRANSPARENT_FX opaque) const; - inline irr::core::stringw toRef(const irr::core::stringw& source) const; - bool isCamera(const scene::ISceneNode* node) const; - irr::core::stringw nameForMesh(const scene::IMesh* mesh, int instance) const; - irr::core::stringw nameForNode(const scene::ISceneNode* node) const; - irr::core::stringw nameForMaterial(const video::SMaterial & material, int materialId, const scene::IMesh* mesh, const scene::ISceneNode* node); - irr::core::stringw nameForMaterialSymbol(const scene::IMesh* mesh, int materialId) const; - irr::core::stringw findCachedMaterialName(const irr::video::SMaterial& material) const; - irr::core::stringw minTexfilterToString(bool bilinear, bool trilinear) const; - irr::core::stringw magTexfilterToString(bool bilinear, bool trilinear) const; - irr::core::stringw pathToURI(const irr::io::path& path) const; - inline bool isXmlNameStartChar(wchar_t c) const; - inline bool isXmlNameChar(wchar_t c) const; - s32 getCheckedTextureIdx(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs); - video::SColor getColorMapping(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs, E_COLLADA_IRR_COLOR colType); - void writeAsset(); - void makeMeshNames(irr::scene::ISceneNode * node); - void writeNodeMaterials(irr::scene::ISceneNode * node); - void writeNodeEffects(irr::scene::ISceneNode * node); - void writeNodeLights(irr::scene::ISceneNode * node); - void writeNodeCameras(irr::scene::ISceneNode * node); - void writeAllMeshGeometries(); - void writeSceneNode(irr::scene::ISceneNode * node); - void writeMeshMaterials(scene::IMesh* mesh, irr::core::array * materialNamesOut=0); - void writeMeshEffects(scene::IMesh* mesh); - void writeMaterialEffect(const irr::core::stringw& materialname, const video::SMaterial & material); - void writeMeshGeometry(const irr::core::stringw& meshname, scene::IMesh* mesh); - void writeMeshInstanceGeometry(const irr::core::stringw& meshname, scene::IMesh* mesh, scene::ISceneNode* node=0); - void writeMaterial(const irr::core::stringw& materialname); - void writeLightInstance(const irr::core::stringw& lightName); - void writeCameraInstance(const irr::core::stringw& cameraName); - void writeLibraryImages(); - void writeColorFx(const video::SMaterial & material, const wchar_t * colorname, E_COLLADA_COLOR_SAMPLER cs, const wchar_t* attr1Name=0, const wchar_t* attr1Value=0); - void writeAmbientLightElement(const video::SColorf & col); - void writeColorElement(const video::SColor & col, bool writeAlpha=true); - void writeColorElement(const video::SColorf & col, bool writeAlpha=true); - void writeTextureSampler(s32 textureIdx); - void writeFxElement(const video::SMaterial & material, E_COLLADA_TECHNIQUE_FX techFx); - void writeNode(const wchar_t * nodeName, const wchar_t * content); - void writeFloatElement(irr::f32 value); - void writeRotateElement(const irr::core::vector3df& axis, irr::f32 angle); - void writeScaleElement(const irr::core::vector3df& scale); - void writeTranslateElement(const irr::core::vector3df& translate); - void writeMatrixElement(const irr::core::matrix4& matrix); - - struct SComponentGlobalStartPos - { - SComponentGlobalStartPos() : PosStartIndex(-1), PosLastIndex(-1), - NormalStartIndex(-1), NormalLastIndex(-1), - TCoord0StartIndex(-1), TCoord0LastIndex(-1), - TCoord1StartIndex(-1), TCoord1LastIndex(-1) - { } - - s32 PosStartIndex; - s32 PosLastIndex; - - s32 NormalStartIndex; - s32 NormalLastIndex; - - s32 TCoord0StartIndex; - s32 TCoord0LastIndex; - - s32 TCoord1StartIndex; - s32 TCoord1LastIndex; - }; - - io::IFileSystem* FileSystem; - video::IVideoDriver* VideoDriver; - io::IXMLWriter* Writer; - core::array LibraryImages; - io::path Directory; - - // Helper struct for creating geometry copies for the ECGI_PER_MESH_AND_MATERIAL settings. - struct SGeometryMeshMaterials - { - bool equals(const core::array& names) const - { - if ( names.size() != MaterialNames.size() ) - return false; - for ( irr::u32 i=0; i MaterialNames; // Material names exported for this instance - core::array MaterialOwners; // Nodes using this specific mesh-material combination - }; - - // Check per mesh-ptr if stuff has been written for this mesh already - struct SColladaMesh - { - SColladaMesh() : MaterialsWritten(false), EffectsWritten(false) - { - } - - SGeometryMeshMaterials * findGeometryMeshMaterials(const irr::core::array materialNames) - { - for ( irr::u32 i=0; i= 0 ) - return GeometryMeshMaterials[i].GeometryName; - } - return Name; // (shouldn't get here usually) - } - - irr::core::stringw Name; - bool MaterialsWritten; // just an optimization doing that here in addition to the MaterialsWritten map - bool EffectsWritten; // just an optimization doing that here in addition to the EffectsWritten map - - core::array GeometryMeshMaterials; - }; - typedef core::map::Node MeshNode; - core::map Meshes; - - // structure for the lights library - struct SColladaLight - { - SColladaLight() {} - irr::core::stringw Name; - }; - typedef core::map::Node LightNode; - core::map LightNodes; - - // structure for the camera library - typedef core::map::Node CameraNode; - core::map CameraNodes; - - // Check per name if stuff has been written already - // TODO: second parameter not needed, we just don't have a core::set class yet in Irrlicht - core::map MaterialsWritten; - core::map EffectsWritten; - - // Cache material names - struct MaterialName - { - MaterialName(const irr::video::SMaterial & material, const irr::core::stringw& name) - : Material(material), Name(name) - {} - irr::video::SMaterial Material; - irr::core::stringw Name; - }; - irr::core::array< MaterialName > MaterialNameCache; -}; - - -} // end namespace -} // end namespace - -#endif diff --git a/lib/irrlicht/source/Irrlicht/CSceneManager.cpp b/lib/irrlicht/source/Irrlicht/CSceneManager.cpp index 6d7cd688a..991eebfe9 100644 --- a/lib/irrlicht/source/Irrlicht/CSceneManager.cpp +++ b/lib/irrlicht/source/Irrlicht/CSceneManager.cpp @@ -68,10 +68,6 @@ #include "CMY3DMeshFileLoader.h" #endif -#ifdef _IRR_COMPILE_WITH_COLLADA_LOADER_ -#include "CColladaFileLoader.h" -#endif - #ifdef _IRR_COMPILE_WITH_DMF_LOADER_ #include "CDMFLoader.h" #endif @@ -278,9 +274,6 @@ CSceneManager::CSceneManager(video::IVideoDriver* driver, io::IFileSystem* fs, #ifdef _IRR_COMPILE_WITH_BSP_LOADER_ MeshLoaderList.push_back(new CBSPMeshFileLoader(this, FileSystem)); #endif - #ifdef _IRR_COMPILE_WITH_COLLADA_LOADER_ - MeshLoaderList.push_back(new CColladaFileLoader(this, FileSystem)); - #endif #ifdef _IRR_COMPILE_WITH_3DS_LOADER_ MeshLoaderList.push_back(new C3DSMeshFileLoader(this, FileSystem)); #endif