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;
}; };
......
...@@ -142,10 +142,15 @@ CColladaMeshWriterNames::CColladaMeshWriterNames(IColladaMeshWriter * writer) ...@@ -142,10 +142,15 @@ CColladaMeshWriterNames::CColladaMeshWriterNames(IColladaMeshWriter * writer)
{ {
} }
irr::core::stringw CColladaMeshWriterNames::nameForMesh(const scene::IMesh* mesh) irr::core::stringw CColladaMeshWriterNames::nameForMesh(const scene::IMesh* mesh, int instance)
{ {
irr::core::stringw name(L"mesh"); irr::core::stringw name(L"mesh");
name += nameForPtr(mesh); name += nameForPtr(mesh);
if ( instance > 0 )
{
name += L"i";
name += irr::core::stringw(instance);
}
return ColladaMeshWriter->toNCName(name); return ColladaMeshWriter->toNCName(name);
} }
...@@ -320,7 +325,7 @@ bool CColladaMeshWriter::writeScene(io::IWriteFile* file, scene::ISceneNode* roo ...@@ -320,7 +325,7 @@ bool CColladaMeshWriter::writeScene(io::IWriteFile* file, scene::ISceneNode* roo
// write meshes // write meshes
Writer->writeElement(L"library_geometries", false); Writer->writeElement(L"library_geometries", false);
Writer->writeLineBreak(); Writer->writeLineBreak();
writeNodeGeometries(root); writeAllMeshGeometries();
Writer->writeClosingTag(L"library_geometries"); Writer->writeClosingTag(L"library_geometries");
Writer->writeLineBreak(); Writer->writeLineBreak();
...@@ -395,8 +400,8 @@ void CColladaMeshWriter::makeMeshNames(irr::scene::ISceneNode * node) ...@@ -395,8 +400,8 @@ void CColladaMeshWriter::makeMeshNames(irr::scene::ISceneNode * node)
{ {
if ( !Meshes.find(mesh) ) if ( !Meshes.find(mesh) )
{ {
ColladaMesh cm; SColladaMesh cm;
cm.Name = nameForMesh(mesh); cm.Name = nameForMesh(mesh, 0);
Meshes.insert(mesh, cm); Meshes.insert(mesh, cm);
} }
} }
...@@ -413,17 +418,19 @@ void CColladaMeshWriter::writeNodeMaterials(irr::scene::ISceneNode * node) ...@@ -413,17 +418,19 @@ void CColladaMeshWriter::writeNodeMaterials(irr::scene::ISceneNode * node)
if ( !node || !getProperties() || !getProperties()->isExportable(node) ) if ( !node || !getProperties() || !getProperties()->isExportable(node) )
return; return;
core::array<irr::core::stringw> materialNames;
IMesh* mesh = getProperties()->getMesh(node); IMesh* mesh = getProperties()->getMesh(node);
if ( mesh ) if ( mesh )
{ {
MeshNode * n = Meshes.find(mesh);
if ( node->getType() == ESNT_MESH if ( node->getType() == ESNT_MESH
&& static_cast<IMeshSceneNode*>(node)->isReadOnlyMaterials() ) && static_cast<IMeshSceneNode*>(node)->isReadOnlyMaterials() )
{ {
// no material overrides - write mesh materials // no material overrides - write mesh materials
MeshNode * n = Meshes.find(mesh);
if ( n && !n->getValue().MaterialsWritten ) if ( n && !n->getValue().MaterialsWritten )
{ {
writeMeshMaterials(mesh); writeMeshMaterials(mesh, getGeometryWriting() == ECGI_PER_MESH_AND_MATERIAL ? &materialNames : NULL);
n->getValue().MaterialsWritten = true; n->getValue().MaterialsWritten = true;
} }
} }
...@@ -435,6 +442,28 @@ void CColladaMeshWriter::writeNodeMaterials(irr::scene::ISceneNode * node) ...@@ -435,6 +442,28 @@ void CColladaMeshWriter::writeNodeMaterials(irr::scene::ISceneNode * node)
video::SMaterial & material = node->getMaterial(i); video::SMaterial & material = node->getMaterial(i);
core::stringw strMat(nameForMaterial(material, i, mesh, node)); core::stringw strMat(nameForMaterial(material, i, mesh, node));
writeMaterial(strMat); 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);
} }
} }
} }
...@@ -490,16 +519,13 @@ void CColladaMeshWriter::writeNodeEffects(irr::scene::ISceneNode * node) ...@@ -490,16 +519,13 @@ void CColladaMeshWriter::writeNodeEffects(irr::scene::ISceneNode * node)
} }
else else
{ {
irr::core::stringw uvname(nameForMesh(mesh));
uvname += L"-TexCoord0"; // TODO: need to handle second UV-set
// write node materials // write node materials
for (u32 i=0; i<node->getMaterialCount(); ++i) for (u32 i=0; i<node->getMaterialCount(); ++i)
{ {
video::SMaterial & material = node->getMaterial(i); video::SMaterial & material = node->getMaterial(i);
irr::core::stringw materialfxname(nameForMaterial(material, i, mesh, node)); irr::core::stringw materialfxname(nameForMaterial(material, i, mesh, node));
materialfxname += L"-fx"; materialfxname += L"-fx";
writeMaterialEffect(uvname, materialfxname, material); writeMaterialEffect(materialfxname, material);
} }
} }
} }
...@@ -521,7 +547,7 @@ void CColladaMeshWriter::writeNodeLights(irr::scene::ISceneNode * node) ...@@ -521,7 +547,7 @@ void CColladaMeshWriter::writeNodeLights(irr::scene::ISceneNode * node)
ILightSceneNode * lightNode = static_cast<ILightSceneNode*>(node); ILightSceneNode * lightNode = static_cast<ILightSceneNode*>(node);
const video::SLight& lightData = lightNode->getLightData(); const video::SLight& lightData = lightNode->getLightData();
ColladaLight cLight; SColladaLight cLight;
cLight.Name = nameForNode(node); cLight.Name = nameForNode(node);
LightNodes.insert(node, cLight); LightNodes.insert(node, cLight);
...@@ -614,26 +640,25 @@ void CColladaMeshWriter::writeNodeLights(irr::scene::ISceneNode * node) ...@@ -614,26 +640,25 @@ void CColladaMeshWriter::writeNodeLights(irr::scene::ISceneNode * node)
} }
} }
void CColladaMeshWriter::writeNodeGeometries(irr::scene::ISceneNode * node) void CColladaMeshWriter::writeAllMeshGeometries()
{ {
if ( !node || !getProperties() || !getProperties()->isExportable(node) ) core::map<IMesh*, SColladaMesh>::ConstIterator it = Meshes.getConstIterator();
return; for(; !it.atEnd(); it++ )
IMesh* mesh = getProperties()->getMesh(node);
if ( mesh )
{ {
MeshNode * n = Meshes.find(mesh); IMesh* mesh = it->getKey();
if ( n && !n->getValue().GeometryWritten ) const SColladaMesh& colladaMesh = it->getValue();
if ( getGeometryWriting() == ECGI_PER_MESH_AND_MATERIAL && colladaMesh.GeometryMeshMaterials.size() > 1 )
{ {
writeMeshGeometry(n->getValue().Name, mesh); for ( u32 i=0; i<colladaMesh.GeometryMeshMaterials.size(); ++i )
n->getValue().GeometryWritten = true; {
writeMeshGeometry(colladaMesh.GeometryMeshMaterials[i].GeometryName, mesh);
}
}
else
{
writeMeshGeometry(colladaMesh.Name, mesh);
} }
}
const core::list<ISceneNode*>& children = node->getChildren();
for ( core::list<ISceneNode*>::ConstIterator it = children.begin(); it != children.end(); ++it )
{
writeNodeGeometries( *it );
} }
} }
...@@ -670,7 +695,10 @@ void CColladaMeshWriter::writeSceneNode(irr::scene::ISceneNode * node ) ...@@ -670,7 +695,10 @@ void CColladaMeshWriter::writeSceneNode(irr::scene::ISceneNode * node )
{ {
MeshNode * n = Meshes.find(mesh); MeshNode * n = Meshes.find(mesh);
if ( n ) if ( n )
writeMeshInstanceGeometry(n->getValue().Name, mesh, node); {
const SColladaMesh& colladaMesh = n->getValue();
writeMeshInstanceGeometry(colladaMesh.findGeometryNameForNode(node), mesh, node);
}
} }
// instance light // instance light
...@@ -751,7 +779,7 @@ bool CColladaMeshWriter::writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 ...@@ -751,7 +779,7 @@ bool CColladaMeshWriter::writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32
Writer->writeElement(L"library_geometries", false); Writer->writeElement(L"library_geometries", false);
Writer->writeLineBreak(); Writer->writeLineBreak();
irr::core::stringw meshname(nameForMesh(mesh)); irr::core::stringw meshname(nameForMesh(mesh, 0));
writeMeshGeometry(meshname, mesh); writeMeshGeometry(meshname, mesh);
Writer->writeClosingTag(L"library_geometries"); Writer->writeClosingTag(L"library_geometries");
...@@ -804,8 +832,7 @@ bool CColladaMeshWriter::writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 ...@@ -804,8 +832,7 @@ bool CColladaMeshWriter::writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32
void CColladaMeshWriter::writeMeshInstanceGeometry(const irr::core::stringw& meshname, scene::IMesh* mesh, scene::ISceneNode* node) void CColladaMeshWriter::writeMeshInstanceGeometry(const irr::core::stringw& meshname, scene::IMesh* mesh, scene::ISceneNode* node)
{ {
//<instance_geometry url="#mesh"> //<instance_geometry url="#mesh">
core::stringw meshId(meshname); Writer->writeElement(L"instance_geometry", false, L"url", toRef(meshname).c_str());
Writer->writeElement(L"instance_geometry", false, L"url", toRef(meshId).c_str());
Writer->writeLineBreak(); Writer->writeLineBreak();
Writer->writeElement(L"bind_material", false); Writer->writeElement(L"bind_material", false);
...@@ -826,10 +853,9 @@ void CColladaMeshWriter::writeMeshInstanceGeometry(const irr::core::stringw& mes ...@@ -826,10 +853,9 @@ void CColladaMeshWriter::writeMeshInstanceGeometry(const irr::core::stringw& mes
Writer->writeElement(L"instance_material", false, L"symbol", strMatSymbol.c_str(), L"target", strMatTarget.c_str()); Writer->writeElement(L"instance_material", false, L"symbol", strMatSymbol.c_str(), L"target", strMatTarget.c_str());
Writer->writeLineBreak(); Writer->writeLineBreak();
// <bind_vertex_input semantic="mesh-TexCoord0" input_semantic="TEXCOORD" input_set="0"/> // TODO: need to handle second UV-set
core::stringw meshTexCoordId(meshname); // <bind_vertex_input semantic="uv" input_semantic="TEXCOORD" input_set="0"/>
meshTexCoordId += L"-TexCoord0"; // 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->writeElement(L"bind_vertex_input", true, L"semantic", meshTexCoordId.c_str(), L"input_semantic", L"TEXCOORD", L"input_set", L"0" );
Writer->writeLineBreak(); Writer->writeLineBreak();
Writer->writeClosingTag(L"instance_material"); Writer->writeClosingTag(L"instance_material");
...@@ -940,12 +966,12 @@ irr::core::stringw CColladaMeshWriter::toRef(const irr::core::stringw& source) c ...@@ -940,12 +966,12 @@ irr::core::stringw CColladaMeshWriter::toRef(const irr::core::stringw& source) c
return ref; return ref;
} }
irr::core::stringw CColladaMeshWriter::nameForMesh(const scene::IMesh* mesh) const irr::core::stringw CColladaMeshWriter::nameForMesh(const scene::IMesh* mesh, int instance) const
{ {
IColladaMeshWriterNames * nameGenerator = getNameGenerator(); IColladaMeshWriterNames * nameGenerator = getNameGenerator();
if ( nameGenerator ) if ( nameGenerator )
{ {
return nameGenerator->nameForMesh(mesh); return nameGenerator->nameForMesh(mesh, instance);
} }
return irr::core::stringw(L"missing_name_generator"); return irr::core::stringw(L"missing_name_generator");
} }
...@@ -1109,7 +1135,7 @@ void CColladaMeshWriter::writeAsset() ...@@ -1109,7 +1135,7 @@ void CColladaMeshWriter::writeAsset()
Writer->writeLineBreak(); Writer->writeLineBreak();
} }
void CColladaMeshWriter::writeMeshMaterials(scene::IMesh* mesh) void CColladaMeshWriter::writeMeshMaterials(scene::IMesh* mesh, irr::core::array<irr::core::stringw> * materialNamesOut)
{ {
u32 i; u32 i;
for (i=0; i<mesh->getMeshBufferCount(); ++i) for (i=0; i<mesh->getMeshBufferCount(); ++i)
...@@ -1117,10 +1143,12 @@ void CColladaMeshWriter::writeMeshMaterials(scene::IMesh* mesh) ...@@ -1117,10 +1143,12 @@ void CColladaMeshWriter::writeMeshMaterials(scene::IMesh* mesh)
video::SMaterial & material = mesh->getMeshBuffer(i)->getMaterial(); video::SMaterial & material = mesh->getMeshBuffer(i)->getMaterial();
core::stringw strMat(nameForMaterial(material, i, mesh, NULL)); core::stringw strMat(nameForMaterial(material, i, mesh, NULL));
writeMaterial(strMat); writeMaterial(strMat);
if ( materialNamesOut )
materialNamesOut->push_back(strMat);
} }
} }
void CColladaMeshWriter::writeMaterialEffect(const irr::core::stringw& uvname, const irr::core::stringw& materialfxname, const video::SMaterial & material) void CColladaMeshWriter::writeMaterialEffect(const irr::core::stringw& materialfxname, const video::SMaterial & material)
{ {
if ( EffectsWritten.find(materialfxname) ) if ( EffectsWritten.find(materialfxname) )
return; return;
...@@ -1244,7 +1272,7 @@ void CColladaMeshWriter::writeMaterialEffect(const irr::core::stringw& uvname, c ...@@ -1244,7 +1272,7 @@ void CColladaMeshWriter::writeMaterialEffect(const irr::core::stringw& uvname, c
Writer->writeLineBreak(); Writer->writeLineBreak();
E_COLLADA_TECHNIQUE_FX techFx = getProperties() ? getProperties()->getTechniqueFx(material) : ECTF_BLINN; E_COLLADA_TECHNIQUE_FX techFx = getProperties() ? getProperties()->getTechniqueFx(material) : ECTF_BLINN;
writeFxElement(uvname, material, techFx); writeFxElement(material, techFx);
Writer->writeClosingTag(L"technique"); Writer->writeClosingTag(L"technique");
Writer->writeLineBreak(); Writer->writeLineBreak();
...@@ -1256,15 +1284,12 @@ void CColladaMeshWriter::writeMaterialEffect(const irr::core::stringw& uvname, c ...@@ -1256,15 +1284,12 @@ void CColladaMeshWriter::writeMaterialEffect(const irr::core::stringw& uvname, c
void CColladaMeshWriter::writeMeshEffects(scene::IMesh* mesh) void CColladaMeshWriter::writeMeshEffects(scene::IMesh* mesh)
{ {
irr::core::stringw uvname(nameForMesh(mesh));
uvname += L"-TexCoord0"; // TODO: need to handle second UV-set
for (u32 i=0; i<mesh->getMeshBufferCount(); ++i) for (u32 i=0; i<mesh->getMeshBufferCount(); ++i)
{ {
video::SMaterial & material = mesh->getMeshBuffer(i)->getMaterial(); video::SMaterial & material = mesh->getMeshBuffer(i)->getMaterial();
irr::core::stringw materialfxname(nameForMaterial(material, i, mesh, NULL)); irr::core::stringw materialfxname(nameForMaterial(material, i, mesh, NULL));
materialfxname += L"-fx"; materialfxname += L"-fx";
writeMaterialEffect(uvname, materialfxname, material); writeMaterialEffect(materialfxname, material);
} }
} }
...@@ -1682,6 +1707,8 @@ void CColladaMeshWriter::writeMeshGeometry(const irr::core::stringw& meshname, s ...@@ -1682,6 +1707,8 @@ void CColladaMeshWriter::writeMeshGeometry(const irr::core::stringw& meshname, s
bool has2ndTexCoords = hasSecondTextureCoordinates(buffer->getVertexType()); bool has2ndTexCoords = hasSecondTextureCoordinates(buffer->getVertexType());
if (has2ndTexCoords) 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->writeElement(L"input", true, L"semantic", L"TEXCOORD", L"source", toRef(meshTexCoord1Id).c_str(), L"idx", L"3");
Writer->writeLineBreak(); Writer->writeLineBreak();
} }
...@@ -1861,18 +1888,18 @@ video::SColor CColladaMeshWriter::getColorMapping(const video::SMaterial & mater ...@@ -1861,18 +1888,18 @@ video::SColor CColladaMeshWriter::getColorMapping(const video::SMaterial & mater
return video::SColor(255, 0, 0, 0); return video::SColor(255, 0, 0, 0);
} }
void CColladaMeshWriter::writeTextureSampler(const irr::core::stringw& uvname, s32 textureIdx) void CColladaMeshWriter::writeTextureSampler(s32 textureIdx)
{ {
irr::core::stringw sampler(L"tex"); irr::core::stringw sampler(L"tex");
sampler += irr::core::stringw(textureIdx); sampler += irr::core::stringw(textureIdx);
sampler += L"-sampler"; sampler += L"-sampler";
// <texture texture="sampler" texcoord="texCoordUv"/> // <texture texture="sampler" texcoord="texCoordUv"/>
Writer->writeElement(L"texture", true, L"texture", sampler.c_str(), L"texcoord", uvname.c_str() ); Writer->writeElement(L"texture", true, L"texture", sampler.c_str(), L"texcoord", L"uv" );
Writer->writeLineBreak(); Writer->writeLineBreak();
} }
void CColladaMeshWriter::writeFxElement(const irr::core::stringw& uvname, const video::SMaterial & material, E_COLLADA_TECHNIQUE_FX techFx) void CColladaMeshWriter::writeFxElement(const video::SMaterial & material, E_COLLADA_TECHNIQUE_FX techFx)
{ {
core::stringw fxLabel; core::stringw fxLabel;
bool writeEmission = true; bool writeEmission = true;
...@@ -1916,22 +1943,22 @@ void CColladaMeshWriter::writeFxElement(const irr::core::stringw& uvname, const ...@@ -1916,22 +1943,22 @@ void CColladaMeshWriter::writeFxElement(const irr::core::stringw& uvname, const
{ {
if ( writeEmission ) if ( writeEmission )
{ {
writeColorFx(uvname, material, L"emission", ECCS_EMISSIVE); writeColorFx(material, L"emission", ECCS_EMISSIVE);
} }
if ( writeAmbient ) if ( writeAmbient )
{ {
writeColorFx(uvname, material, L"ambient", ECCS_AMBIENT); writeColorFx(material, L"ambient", ECCS_AMBIENT);
} }
if ( writeDiffuse ) if ( writeDiffuse )
{ {
writeColorFx(uvname, material, L"diffuse", ECCS_DIFFUSE); writeColorFx(material, L"diffuse", ECCS_DIFFUSE);
} }
if ( writeSpecular ) if ( writeSpecular )
{ {
writeColorFx(uvname, material, L"specular", ECCS_SPECULAR); writeColorFx(material, L"specular", ECCS_SPECULAR);
} }
if ( writeShininess ) if ( writeShininess )
...@@ -1945,7 +1972,7 @@ void CColladaMeshWriter::writeFxElement(const irr::core::stringw& uvname, const ...@@ -1945,7 +1972,7 @@ void CColladaMeshWriter::writeFxElement(const irr::core::stringw& uvname, const
if ( writeReflective ) if ( writeReflective )
{ {
writeColorFx(uvname, material, L"reflective", ECCS_REFLECTIVE); writeColorFx(material, L"reflective", ECCS_REFLECTIVE);
} }
if ( writeReflectivity ) if ( writeReflectivity )
...@@ -1965,7 +1992,7 @@ void CColladaMeshWriter::writeFxElement(const irr::core::stringw& uvname, const ...@@ -1965,7 +1992,7 @@ void CColladaMeshWriter::writeFxElement(const irr::core::stringw& uvname, const
if ( writeTransparent ) if ( writeTransparent )
{ {
E_COLLADA_TRANSPARENT_FX transparentFx = getProperties()->getTransparentFx(material); E_COLLADA_TRANSPARENT_FX transparentFx = getProperties()->getTransparentFx(material);
writeColorFx(uvname, material, L"transparent", ECCS_TRANSPARENT, L"opaque", toString(transparentFx).c_str()); writeColorFx(material, L"transparent", ECCS_TRANSPARENT, L"opaque", toString(transparentFx).c_str());
} }
if ( writeTransparency ) if ( writeTransparency )
...@@ -2001,7 +2028,7 @@ void CColladaMeshWriter::writeFxElement(const irr::core::stringw& uvname, const ...@@ -2001,7 +2028,7 @@ void CColladaMeshWriter::writeFxElement(const irr::core::stringw& uvname, const
Writer->writeLineBreak(); Writer->writeLineBreak();
} }
void CColladaMeshWriter::writeColorFx(const irr::core::stringw& uvname, const video::SMaterial & material, const wchar_t * colorname, E_COLLADA_COLOR_SAMPLER cs, const wchar_t* attr1Name, const wchar_t* attr1Value) 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); irr::s32 idx = getCheckedTextureIdx(material, cs);
E_COLLADA_IRR_COLOR colType = idx < 0 ? getProperties()->getColorMapping(material, cs) : ECIC_NONE; E_COLLADA_IRR_COLOR colType = idx < 0 ? getProperties()->getColorMapping(material, cs) : ECIC_NONE;
...@@ -2010,7 +2037,7 @@ void CColladaMeshWriter::writeColorFx(const irr::core::stringw& uvname, const vi ...@@ -2010,7 +2037,7 @@ void CColladaMeshWriter::writeColorFx(const irr::core::stringw& uvname, const vi
Writer->writeElement(colorname, false, attr1Name, attr1Value); Writer->writeElement(colorname, false, attr1Name, attr1Value);
Writer->writeLineBreak(); Writer->writeLineBreak();
if ( idx >= 0 ) if ( idx >= 0 )
writeTextureSampler( uvname, idx); writeTextureSampler(idx);
else else
writeColorElement(getColorMapping(material, cs, colType)); writeColorElement(getColorMapping(material, cs, colType));
Writer->writeClosingTag(colorname); Writer->writeClosingTag(colorname);
......
...@@ -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