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
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
class IColladaMeshWriterProperties : public virtual IReferenceCounted
{
......@@ -146,8 +159,11 @@ namespace scene
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) = 0;
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
......@@ -180,7 +196,7 @@ namespace scene
IColladaMeshWriter()
: 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
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.
/** Overloading properties with an own class allows modifying the writing process in certain ways.
By default properties are set to the DefaultProperties. */
......@@ -331,6 +366,7 @@ namespace scene
bool WriteTextures;
bool WriteDefaultScene;
video::SColorf AmbientLight;
E_COLLADA_GEOMETRY_WRITING GeometryWriting;
};
......
This diff is collapsed.
......@@ -59,7 +59,7 @@ namespace scene
{
public:
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 nameForMaterial(const video::SMaterial & material, int materialId, const scene::IMesh* mesh, const scene::ISceneNode* node);
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::scene::E_COLLADA_TRANSPARENT_FX opaque) 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 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;
......@@ -121,22 +121,22 @@ protected:
void writeNodeMaterials(irr::scene::ISceneNode * node);
void writeNodeEffects(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 writeMeshMaterials(scene::IMesh* mesh);
void writeMeshMaterials(scene::IMesh* mesh, irr::core::array<irr::core::stringw> * materialNamesOut=0);
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 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 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 writeColorElement(const video::SColor & col, bool writeAlpha=true);
void writeColorElement(const video::SColorf & col, bool writeAlpha=true);
void writeTextureSampler(const irr::core::stringw& uvname, s32 textureIdx);
void writeFxElement(const irr::core::stringw& uvname, const video::SMaterial & material, E_COLLADA_TECHNIQUE_FX techFx);
void writeTextureSampler(s32 textureIdx);
void writeFxElement(const video::SMaterial & material, E_COLLADA_TECHNIQUE_FX techFx);
void writeFloatElement(irr::f32 value);
void writeRotateElement(const irr::core::vector3df& axis, irr::f32 angle);
void writeScaleElement(const irr::core::vector3df& scale);
......@@ -170,28 +170,69 @@ protected:
core::array<video::ITexture*> 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<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
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;
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 GeometryWritten;
core::array<SGeometryMeshMaterials> GeometryMeshMaterials;
};
typedef core::map<IMesh*, ColladaMesh>::Node MeshNode;
core::map<IMesh*, ColladaMesh> Meshes;
typedef core::map<IMesh*, SColladaMesh>::Node MeshNode;
core::map<IMesh*, SColladaMesh> Meshes;
struct ColladaLight
struct SColladaLight
{
ColladaLight() {}
SColladaLight() {}
irr::core::stringw Name;
};
typedef core::map<ISceneNode*, ColladaLight>::Node LightNode;
core::map<ISceneNode*, ColladaLight> LightNodes;
typedef core::map<ISceneNode*, SColladaLight>::Node LightNode;
core::map<ISceneNode*, SColladaLight> LightNodes;
// 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
......
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