Commit f1aea87c authored by cutealien's avatar cutealien

- IColladaMeshWriter now writes a scene by default (most tools can't handle .dae's otherwise)

- In CColladaMeshWriter the texcoords in in mesh-source and those in texture (for effects) don't use the same name anymore. bind_vertex_input does handle that connection and having the same name had complicated the code (and was confusing)
- In Collada export mesh-geometries can now be copied when different materials are using the same mesh. Reason was that many tools (all I tested so far including Irrlicht) can't handle such materials otherwise.


git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@4277 dfc29bdd-3216-0410-991c-e03cc46cb475
parent 26f44f6f
...@@ -76,6 +76,19 @@ namespace scene ...@@ -76,6 +76,19 @@ namespace scene
ECIC_SPECULAR 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 in the scene.
ECGI_PER_MESH_AND_MATERIAL,
// not yet supported, but might be useful as well
// ECGI_PER_NODE
};
//! Callback interface for properties which can be used to influence collada writing //! Callback interface for properties which can be used to influence collada writing
class IColladaMeshWriterProperties : public virtual IReferenceCounted class IColladaMeshWriterProperties : public virtual IReferenceCounted
{ {
...@@ -146,8 +159,11 @@ namespace scene ...@@ -146,8 +159,11 @@ namespace scene
IColladaMeshWriter::getDefaultNameGenerator(). Also names must follow IColladaMeshWriter::getDefaultNameGenerator(). Also names must follow
the xs::NCName standard to be valid, you can run them through the xs::NCName standard to be valid, you can run them through
IColladaMeshWriter::toNCName to ensure that. 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) = 0; virtual irr::core::stringw nameForMesh(const scene::IMesh* mesh, int instance) = 0;
//! Return a unique name for the given node //! Return a unique name for the given node
/** Note that names really must be unique here per node-pointer, so /** Note that names really must be unique here per node-pointer, so
...@@ -180,7 +196,7 @@ namespace scene ...@@ -180,7 +196,7 @@ namespace scene
IColladaMeshWriter() IColladaMeshWriter()
: Properties(0), DefaultProperties(0), NameGenerator(0), DefaultNameGenerator(0) : Properties(0), DefaultProperties(0), NameGenerator(0), DefaultNameGenerator(0)
, WriteTextures(true), WriteDefaultScene(false), AmbientLight(0.f, 0.f, 0.f, 1.f) , WriteTextures(true), WriteDefaultScene(true), AmbientLight(0.f, 0.f, 0.f, 1.f)
{ {
} }
...@@ -241,6 +257,25 @@ namespace scene ...@@ -241,6 +257,25 @@ namespace scene
return AmbientLight; 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;
}
//! Set properties to use by the meshwriter instead of it's default properties. //! 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. /** Overloading properties with an own class allows modifying the writing process in certain ways.
By default properties are set to the DefaultProperties. */ By default properties are set to the DefaultProperties. */
...@@ -331,6 +366,7 @@ namespace scene ...@@ -331,6 +366,7 @@ namespace scene
bool WriteTextures; bool WriteTextures;
bool WriteDefaultScene; bool WriteDefaultScene;
video::SColorf AmbientLight; video::SColorf AmbientLight;
E_COLLADA_GEOMETRY_WRITING GeometryWriting;
}; };
......
This diff is collapsed.
...@@ -59,7 +59,7 @@ namespace scene ...@@ -59,7 +59,7 @@ namespace scene
{ {
public: public:
CColladaMeshWriterNames(IColladaMeshWriter * writer); CColladaMeshWriterNames(IColladaMeshWriter * writer);
virtual irr::core::stringw nameForMesh(const scene::IMesh* mesh); virtual irr::core::stringw nameForMesh(const scene::IMesh* mesh, int instance);
virtual irr::core::stringw nameForNode(const scene::ISceneNode* node); 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); virtual irr::core::stringw nameForMaterial(const video::SMaterial & material, int materialId, const scene::IMesh* mesh, const scene::ISceneNode* node);
protected: protected:
...@@ -104,7 +104,7 @@ protected: ...@@ -104,7 +104,7 @@ protected:
inline irr::core::stringw toString(const irr::video::E_TEXTURE_CLAMP clamp) 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 toString(const irr::scene::E_COLLADA_TRANSPARENT_FX opaque) const;
inline irr::core::stringw toRef(const irr::core::stringw& source) const; inline irr::core::stringw toRef(const irr::core::stringw& source) const;
irr::core::stringw nameForMesh(const scene::IMesh* mesh) const; irr::core::stringw nameForMesh(const scene::IMesh* mesh, int instance) const;
irr::core::stringw nameForNode(const scene::ISceneNode* node) 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) const; irr::core::stringw nameForMaterial(const video::SMaterial & material, int materialId, const scene::IMesh* mesh, const scene::ISceneNode* node) const;
irr::core::stringw nameForMaterialSymbol(const scene::IMesh* mesh, int materialId) const; irr::core::stringw nameForMaterialSymbol(const scene::IMesh* mesh, int materialId) const;
...@@ -121,22 +121,22 @@ protected: ...@@ -121,22 +121,22 @@ protected:
void writeNodeMaterials(irr::scene::ISceneNode * node); void writeNodeMaterials(irr::scene::ISceneNode * node);
void writeNodeEffects(irr::scene::ISceneNode * node); void writeNodeEffects(irr::scene::ISceneNode * node);
void writeNodeLights(irr::scene::ISceneNode * node); void writeNodeLights(irr::scene::ISceneNode * node);
void writeNodeGeometries(irr::scene::ISceneNode * node); void writeAllMeshGeometries();
void writeSceneNode(irr::scene::ISceneNode * node); void writeSceneNode(irr::scene::ISceneNode * node);
void writeMeshMaterials(scene::IMesh* mesh); void writeMeshMaterials(scene::IMesh* mesh, irr::core::array<irr::core::stringw> * materialNamesOut=0);
void writeMeshEffects(scene::IMesh* mesh); void writeMeshEffects(scene::IMesh* mesh);
void writeMaterialEffect(const irr::core::stringw& uvname, const irr::core::stringw& materialname, const video::SMaterial & material); void writeMaterialEffect(const irr::core::stringw& materialname, const video::SMaterial & material);
void writeMeshGeometry(const irr::core::stringw& meshname, scene::IMesh* mesh); 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 writeMeshInstanceGeometry(const irr::core::stringw& meshname, scene::IMesh* mesh, scene::ISceneNode* node=0);
void writeMaterial(const irr::core::stringw& materialname); void writeMaterial(const irr::core::stringw& materialname);
void writeLightInstance(const irr::core::stringw& lightName); void writeLightInstance(const irr::core::stringw& lightName);
void writeLibraryImages(); void writeLibraryImages();
void writeColorFx(const irr::core::stringw& uvname, const video::SMaterial & material, const wchar_t * colorname, E_COLLADA_COLOR_SAMPLER cs, const wchar_t* attr1Name=0, const wchar_t* attr1Value=0); 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 writeAmbientLightElement(const video::SColorf & col);
void writeColorElement(const video::SColor & col, bool writeAlpha=true); void writeColorElement(const video::SColor & col, bool writeAlpha=true);
void writeColorElement(const video::SColorf & col, bool writeAlpha=true); void writeColorElement(const video::SColorf & col, bool writeAlpha=true);
void writeTextureSampler(const irr::core::stringw& uvname, s32 textureIdx); void writeTextureSampler(s32 textureIdx);
void writeFxElement(const irr::core::stringw& uvname, const video::SMaterial & material, E_COLLADA_TECHNIQUE_FX techFx); void writeFxElement(const video::SMaterial & material, E_COLLADA_TECHNIQUE_FX techFx);
void writeFloatElement(irr::f32 value); void writeFloatElement(irr::f32 value);
void writeRotateElement(const irr::core::vector3df& axis, irr::f32 angle); void writeRotateElement(const irr::core::vector3df& axis, irr::f32 angle);
void writeScaleElement(const irr::core::vector3df& scale); void writeScaleElement(const irr::core::vector3df& scale);
...@@ -170,28 +170,69 @@ protected: ...@@ -170,28 +170,69 @@ protected:
core::array<video::ITexture*> LibraryImages; core::array<video::ITexture*> LibraryImages;
io::path Directory; io::path Directory;
// Helper struct for creating geometry copies for the ECGI_PER_MESH_AND_MATERIAL settings.
struct SGeometryMeshMaterials
{
bool equals(const core::array<irr::core::stringw>& names) const
{
if ( names.size() != MaterialNames.size() )
return false;
for ( irr::u32 i=0; i<MaterialNames.size(); ++i )
if ( names[i] != MaterialNames[i] )
return false;
return true;
}
irr::core::stringw GeometryName; // replacing the usual ColladaMesh::Name
core::array<irr::core::stringw> MaterialNames; // Material names exported for this instance
core::array<const ISceneNode*> MaterialOwners; // Nodes using this specific mesh-material combination
};
// Check per mesh-ptr if stuff has been written for this mesh already // Check per mesh-ptr if stuff has been written for this mesh already
struct ColladaMesh struct SColladaMesh
{ {
ColladaMesh() : MaterialsWritten(false), EffectsWritten(false), GeometryWritten(false) SColladaMesh() : MaterialsWritten(false), EffectsWritten(false)
{ {
} }
SGeometryMeshMaterials * findGeometryMeshMaterials(const irr::core::array<irr::core::stringw> materialNames)
{
for ( irr::u32 i=0; i<GeometryMeshMaterials.size(); ++i )
{
if ( GeometryMeshMaterials[i].equals(materialNames) )
return &(GeometryMeshMaterials[i]);
}
return NULL;
}
const irr::core::stringw& findGeometryNameForNode(const ISceneNode* node) const
{
if ( GeometryMeshMaterials.size() < 2 )
return Name;
for ( irr::u32 i=0; i<GeometryMeshMaterials.size(); ++i )
{
if ( GeometryMeshMaterials[i].MaterialOwners.linear_search(node) >= 0 )
return GeometryMeshMaterials[i].GeometryName;
}
return Name; // (shouldn't get here usually)
}
irr::core::stringw Name; irr::core::stringw Name;
bool MaterialsWritten; // just an optimization doing that here in addition to the MaterialsWritten map 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 bool EffectsWritten; // just an optimization doing that here in addition to the EffectsWritten map
bool GeometryWritten;
core::array<SGeometryMeshMaterials> GeometryMeshMaterials;
}; };
typedef core::map<IMesh*, ColladaMesh>::Node MeshNode; typedef core::map<IMesh*, SColladaMesh>::Node MeshNode;
core::map<IMesh*, ColladaMesh> Meshes; core::map<IMesh*, SColladaMesh> Meshes;
struct ColladaLight struct SColladaLight
{ {
ColladaLight() {} SColladaLight() {}
irr::core::stringw Name; irr::core::stringw Name;
}; };
typedef core::map<ISceneNode*, ColladaLight>::Node LightNode; typedef core::map<ISceneNode*, SColladaLight>::Node LightNode;
core::map<ISceneNode*, ColladaLight> LightNodes; core::map<ISceneNode*, SColladaLight> LightNodes;
// Check per name if stuff has been written already // 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 // TODO: second parameter not needed, we just don't have a core::set class yet in Irrlicht
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment