Commit 87f86371 authored by cutealien's avatar cutealien

- add overloaded map::getValue which can return a reference

- simplified IColladaMeshWriterProperties interface
- ColladaMeshWriter can now write complete scenes as well as just writing single meshes.


git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@3859 dfc29bdd-3216-0410-991c-e03cc46cb475
parent 7d101163
...@@ -6,6 +6,8 @@ ...@@ -6,6 +6,8 @@
#define __IRR_I_COLLADA_MESH_WRITER_H_INCLUDED__ #define __IRR_I_COLLADA_MESH_WRITER_H_INCLUDED__
#include "IMeshWriter.h" #include "IMeshWriter.h"
#include "ISceneNode.h"
#include "IAnimatedMesh.h"
#include "SMaterial.h" #include "SMaterial.h"
namespace irr namespace irr
...@@ -63,7 +65,18 @@ namespace scene ...@@ -63,7 +65,18 @@ namespace scene
ECOF_TRANSPARENT_SPECULAR = 16 ECOF_TRANSPARENT_SPECULAR = 16
}; };
//! For mapping irrlicht textures indices to collada color-types
enum E_COLLADA_COLOR_SAMPLER
{
ECCS_DIFFUSE,
ECCS_AMBIENT,
ECCS_EMISSIVE,
ECCS_SPECULAR,
ECCS_TRANSPARENT
};
//! Callback interface for properties which can be used to influence collada writing //! Callback interface for properties which can be used to influence collada writing
//! NOTE: Interface is still work in process and might change some more before 1.8 release
class IColladaMeshWriterProperties : public virtual IReferenceCounted class IColladaMeshWriterProperties : public virtual IReferenceCounted
{ {
public: public:
...@@ -72,27 +85,11 @@ namespace scene ...@@ -72,27 +85,11 @@ namespace scene
//! Which lighting model should be used in the technique (FX) section when exporting effects (materials) //! 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; virtual E_COLLADA_TECHNIQUE_FX getTechniqueFx(const video::SMaterial& material) const = 0;
//! Which texture index should be used when writing the emissive texture //! 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 */ /** \return the index to the texture-layer or -1 if that texture should never be exported
virtual s32 getEmissiveTextureIdx(const video::SMaterial& material) const = 0; 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. */
//! Which texture index should be used when writing the ambient texture virtual s32 getTextureIdx(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs) const = 0;
/** \return the index to the texture-layer or -1 if that texture should never be exported */
virtual s32 getAmbientTextureIdx(const video::SMaterial& material) const = 0;
//! Which texture index should be used when writing the diffuse texture
/** \return the index to the texture-layer or -1 if that texture should never be exported */
virtual s32 getDiffuseTextureIdx(const video::SMaterial& material) const = 0;
//! Which texture index should be used when writing the specular texture
/** \return the index to the texture-layer or -1 if that texture should never be exported */
virtual s32 getSpecularTextureIdx(const video::SMaterial& material) const = 0;
//! Which texture index should be used when writing the transparent texture
/** Note: By default the alpha channel is used, if you want to use RGB you have to set
the ECOF_RGB_ZERO flag in getTransparentFx.
\return the index to the texture-layer or -1 if that texture should never be exported */
virtual s32 getTransparentTextureIdx( const video::SMaterial& material) const = 0;
//! Return the settings for transparence //! Return the settings for transparence
virtual E_COLLADA_TRANSPARENT_FX getTransparentFx(const video::SMaterial& material) const = 0; virtual E_COLLADA_TRANSPARENT_FX getTransparentFx(const video::SMaterial& material) const = 0;
...@@ -101,6 +98,14 @@ namespace scene ...@@ -101,6 +98,14 @@ namespace scene
/** This value is additional to transparent settings, if both are set they will be multiplicated. /** 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 */ \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; virtual f32 getTransparency(const video::SMaterial& material) const = 0;
//! Should node be used in scene export?
//! 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 return 0
//! then only the transformation matrix of the node will be used.
virtual IMesh* getMesh(irr::scene::ISceneNode * node) = 0;
}; };
...@@ -109,8 +114,7 @@ namespace scene ...@@ -109,8 +114,7 @@ namespace scene
{ {
public: public:
IColladaMeshWriter() : Properties(0), DefaultProperties(0), WriteTextures(true), WriteScene(false) IColladaMeshWriter() : Properties(0), DefaultProperties(0), WriteTextures(true), WriteDefaultScene(false)
{ {
} }
...@@ -123,6 +127,10 @@ namespace scene ...@@ -123,6 +127,10 @@ namespace scene
DefaultProperties->drop(); DefaultProperties->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 //! Set if texture information should be written
virtual void setWriteTextures(bool write) virtual void setWriteTextures(bool write)
{ {
...@@ -135,19 +143,20 @@ namespace scene ...@@ -135,19 +143,20 @@ namespace scene
return WriteTextures; return WriteTextures;
} }
//! Set if a default scene should be written //! 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. /** 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. The scene is doing an instantiation of the mesh.
When using writeScene this flag is ignored (as we have scene there already)
*/ */
virtual void setWriteScene(bool write) virtual void setWriteDefaultScene(bool write)
{ {
WriteScene = write; WriteDefaultScene = write;
} }
//! Get if a default scene should be written //! Get if a default scene should be written
virtual bool getWriteScene() const virtual bool getWriteDefaultScene() const
{ {
return WriteScene; return WriteDefaultScene;
} }
//! 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.
...@@ -194,7 +203,7 @@ namespace scene ...@@ -194,7 +203,7 @@ namespace scene
IColladaMeshWriterProperties * Properties; IColladaMeshWriterProperties * Properties;
IColladaMeshWriterProperties * DefaultProperties; IColladaMeshWriterProperties * DefaultProperties;
bool WriteTextures; bool WriteTextures;
bool WriteScene; bool WriteDefaultScene;
}; };
......
...@@ -58,6 +58,12 @@ class map ...@@ -58,6 +58,12 @@ class map
return Value; return Value;
} }
ValueTypeRB& getValue()
{
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
return Value;
}
KeyTypeRB getKey() const KeyTypeRB getKey() const
{ {
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
// This file is part of the "Irrlicht Engine". // This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h // For conditions of distribution and use, see copyright notice in irrlicht.h
// TODO: second UV-coordinates currently ignored in textures
#include "IrrCompileConfig.h" #include "IrrCompileConfig.h"
#ifdef _IRR_COMPILE_WITH_COLLADA_WRITER_ #ifdef _IRR_COMPILE_WITH_COLLADA_WRITER_
...@@ -13,6 +15,9 @@ ...@@ -13,6 +15,9 @@
#include "IXMLWriter.h" #include "IXMLWriter.h"
#include "IMesh.h" #include "IMesh.h"
#include "IAttributes.h" #include "IAttributes.h"
#include "IAnimatedMeshSceneNode.h"
#include "IMeshSceneNode.h"
#include "ITerrainSceneNode.h"
namespace irr namespace irr
{ {
...@@ -25,34 +30,25 @@ E_COLLADA_TECHNIQUE_FX CColladaMeshWriterProperties::getTechniqueFx(const video: ...@@ -25,34 +30,25 @@ E_COLLADA_TECHNIQUE_FX CColladaMeshWriterProperties::getTechniqueFx(const video:
return ECTF_BLINN; return ECTF_BLINN;
} }
//! Which texture index should be used when setting the emissive texture //! Which texture index should be used when writing the texture of the given sampler color.
s32 CColladaMeshWriterProperties::getEmissiveTextureIdx(const video::SMaterial& material) const s32 CColladaMeshWriterProperties::getTextureIdx(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs) const
{
return 0;
}
//! Which texture index should be used when setting the ambient texture
s32 CColladaMeshWriterProperties::getAmbientTextureIdx(const video::SMaterial& material) const
{
return 1;
}
//! Which texture index should be used when setting the diffuse texture
s32 CColladaMeshWriterProperties::getDiffuseTextureIdx(const video::SMaterial& material) const
{ {
return 2; // 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.
//! Which texture index should be used when setting the specular texture switch ( cs )
s32 CColladaMeshWriterProperties::getSpecularTextureIdx(const video::SMaterial& material) const {
{ case ECCS_DIFFUSE:
return 3; return 2;
} case ECCS_AMBIENT:
return 1;
//! Which texture index should be used when writing the transparent texture case ECCS_EMISSIVE:
s32 CColladaMeshWriterProperties::getTransparentTextureIdx( const video::SMaterial& material) const return 0;
{ case ECCS_SPECULAR:
// TODO return 3;
case ECCS_TRANSPARENT:
return -1;
};
return -1; return -1;
} }
...@@ -70,6 +66,30 @@ f32 CColladaMeshWriterProperties::getTransparency(const video::SMaterial& materi ...@@ -70,6 +66,30 @@ f32 CColladaMeshWriterProperties::getTransparency(const video::SMaterial& materi
return -1.f; 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<IAnimatedMeshSceneNode*>(node)->getMesh()->getMesh(0);
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<IMeshSceneNode*>(node)->getMesh();
if ( node->getType() == ESNT_TERRAIN )
return static_cast<ITerrainSceneNode*>(node)->getMesh();
return 0;
}
CColladaMeshWriter::CColladaMeshWriter(video::IVideoDriver* driver, CColladaMeshWriter::CColladaMeshWriter(video::IVideoDriver* driver,
io::IFileSystem* fs) io::IFileSystem* fs)
...@@ -109,9 +129,8 @@ EMESH_WRITER_TYPE CColladaMeshWriter::getType() const ...@@ -109,9 +129,8 @@ EMESH_WRITER_TYPE CColladaMeshWriter::getType() const
return EMWT_COLLADA; return EMWT_COLLADA;
} }
//! writes a scene starting with the given node
//! writes a mesh bool CColladaMeshWriter::writeScene(io::IWriteFile* file, scene::ISceneNode* root)
bool CColladaMeshWriter::writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 flags)
{ {
if (!file) if (!file)
return false; return false;
...@@ -126,7 +145,11 @@ bool CColladaMeshWriter::writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 ...@@ -126,7 +145,11 @@ bool CColladaMeshWriter::writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32
Directory = FileSystem->getFileDir(FileSystem->getAbsolutePath( file->getFileName() )); Directory = FileSystem->getFileDir(FileSystem->getAbsolutePath( file->getFileName() ));
os::Printer::log("Writing mesh", file->getFileName()); // make names for all nodes with exportable meshes
Meshes.clear();
makeMeshNames(root);
os::Printer::log("Writing scene", file->getFileName());
// write COLLADA header // write COLLADA header
...@@ -138,537 +161,877 @@ bool CColladaMeshWriter::writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 ...@@ -138,537 +161,877 @@ bool CColladaMeshWriter::writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32
Writer->writeLineBreak(); Writer->writeLineBreak();
// write asset data // write asset data
writeAsset();
Writer->writeElement(L"asset", false); // write all materials
Writer->writeElement(L"library_materials", false);
Writer->writeLineBreak(); Writer->writeLineBreak();
writeNodeMaterials(root);
Writer->writeElement(L"contributor", false); Writer->writeClosingTag(L"library_materials");
Writer->writeLineBreak(); Writer->writeLineBreak();
Writer->writeElement(L"authoring_tool", false);
Writer->writeText(L"Irrlicht Engine / irrEdit"); // this code has originated from irrEdit 0.7 LibraryImages.clear();
Writer->writeClosingTag(L"authoring_tool"); Writer->writeElement(L"library_effects", false);
Writer->writeLineBreak(); Writer->writeLineBreak();
Writer->writeClosingTag(L"contributor"); writeNodeEffects(root);
Writer->writeClosingTag(L"library_effects");
Writer->writeLineBreak(); Writer->writeLineBreak();
// The next two are required
Writer->writeElement(L"created", false); // images
Writer->writeText(L"2008-01-31T00:00:00Z"); writeLibraryImages();
Writer->writeClosingTag(L"created");
// write meshes
Writer->writeElement(L"library_geometries", false);
Writer->writeLineBreak();
writeNodeGeometries(root);
Writer->writeClosingTag(L"library_geometries");
Writer->writeLineBreak(); Writer->writeLineBreak();
Writer->writeElement(L"modified", false); // write scene
Writer->writeText(L"2008-01-31T00:00:00Z"); Writer->writeElement(L"library_visual_scenes", false);
Writer->writeClosingTag(L"modified"); Writer->writeLineBreak();
Writer->writeElement(L"visual_scene", false, L"id", L"default_scene");
Writer->writeLineBreak();
writeSceneNode(root);
Writer->writeClosingTag(L"visual_scene");
Writer->writeLineBreak();
Writer->writeClosingTag(L"library_visual_scenes");
Writer->writeLineBreak(); Writer->writeLineBreak();
Writer->writeElement(L"revision", false);
Writer->writeText(L"1.0"); // instance scene
Writer->writeClosingTag(L"revision"); Writer->writeElement(L"scene", false);
Writer->writeLineBreak(); Writer->writeLineBreak();
Writer->writeClosingTag(L"asset"); Writer->writeElement(L"instance_visual_scene", true, L"url", L"#default_scene");
Writer->writeLineBreak();
Writer->writeClosingTag(L"scene");
Writer->writeLineBreak(); Writer->writeLineBreak();
// write all materials // close everything
Writer->writeElement(L"library_materials", false); Writer->writeClosingTag(L"COLLADA");
Writer->writeLineBreak(); Writer->drop();
u32 i; return true;
for (i=0; i<mesh->getMeshBufferCount(); ++i) }
{
core::stringw strMat = "mat";
strMat += i;
Writer->writeElement(L"material", false, void CColladaMeshWriter::makeMeshNames(irr::scene::ISceneNode * node)
L"id", strMat.c_str(), {
L"name", strMat.c_str()); if ( !node || !getProperties() || !getProperties()->isExportable(node) )
Writer->writeLineBreak(); return;
strMat += L"-fx"; IMesh* mesh = getProperties()->getMesh(node);
Writer->writeElement(L"instance_effect", true, if ( mesh )
L"url", (core::stringw(L"#") + strMat).c_str()); {
Writer->writeLineBreak(); if ( !Meshes.find(mesh) )
{
ColladaMesh cm;
cm.Name = uniqueNameForMesh(mesh);
Meshes.insert(mesh, cm);
}
}
Writer->writeClosingTag(L"material"); const core::list<ISceneNode*>& children = node->getChildren();
Writer->writeLineBreak(); for ( auto it = children.begin(); it != children.end(); ++it )
{
makeMeshNames(*it);
} }
}
Writer->writeClosingTag(L"library_materials"); void CColladaMeshWriter::writeNodeMaterials(irr::scene::ISceneNode * node)
Writer->writeLineBreak(); {
if ( !node || !getProperties() || !getProperties()->isExportable(node) )
return;
Writer->writeElement(L"library_effects", false); IMesh* mesh = getProperties()->getMesh(node);
Writer->writeLineBreak(); if ( mesh )
LibraryImages.clear();
for (i=0; i<mesh->getMeshBufferCount(); ++i)
{ {
core::stringw strMat = "mat"; MeshNode * n = Meshes.find(mesh);
strMat += i; if ( n && !n->getValue().MaterialWritten )
strMat += L"-fx"; {
writeMeshMaterials(n->getValue().Name, mesh);
n->getValue().MaterialWritten = true;
}
}
Writer->writeElement(L"effect", false, const core::list<ISceneNode*>& children = node->getChildren();
L"id", strMat.c_str(), for ( auto it = children.begin(); it != children.end(); ++it )
L"name", strMat.c_str()); {
Writer->writeLineBreak(); writeNodeMaterials( *it );
Writer->writeElement(L"profile_COMMON", false); }
Writer->writeLineBreak(); }
video::SMaterial & material = mesh->getMeshBuffer(i)->getMaterial(); void CColladaMeshWriter::writeNodeEffects(irr::scene::ISceneNode * node)
{
if ( !node || !getProperties() || !getProperties()->isExportable(node) )
return;
int numTextures = 0; IMesh* mesh = getProperties()->getMesh(node);
if ( getWriteTextures() ) if ( mesh )
{
MeshNode * n = Meshes.find(mesh);
if ( n && !n->getValue().EffectWritten )
{ {
// write texture surfaces and samplers and buffer all used imagess irr::core::stringw meshname(n->getValue().Name);
for ( int t=0; t<4; ++t ) for (u32 i=0; i<node->getMaterialCount(); ++i)
{ {
video::SMaterialLayer& layer = material.TextureLayer[t]; core::stringw strMat = "mat";
if ( !layer.Texture ) strMat += meshname;
break; strMat += i;
++numTextures; strMat += L"-fx";
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
//<newparam sid="tex0-surface">
irr::core::stringw texSurface(texName);
texSurface += L"-surface";
Writer->writeElement(L"newparam", false, L"sid", texSurface.c_str());
Writer->writeLineBreak();
// <surface type="2D">
Writer->writeElement(L"surface", false, L"type", L"2D");
Writer->writeLineBreak();
// <init_from>internal_texturename</init_from>
Writer->writeElement(L"init_from", false);
irr::io::path p(FileSystem->getRelativeFilename(layer.Texture->getName().getPath(), Directory));
Writer->writeText(pathToNCName(p).c_str());
Writer->writeClosingTag(L"init_from");
Writer->writeLineBreak();
// <format>A8R8G8B8</format>
Writer->writeElement(L"format", false);
video::ECOLOR_FORMAT format = layer.Texture->getColorFormat();
Writer->writeText(toString(format).c_str());
Writer->writeClosingTag(L"format");
Writer->writeLineBreak();
// </surface>
Writer->writeClosingTag(L"surface");
Writer->writeLineBreak();
// </newparam>
Writer->writeClosingTag(L"newparam");
Writer->writeLineBreak();
// write texture sampler
// <newparam sid="tex0-sampler">
irr::core::stringw texSampler(texName);
texSampler += L"-sampler";
Writer->writeElement(L"newparam", false, L"sid", texSampler.c_str());
Writer->writeLineBreak();
// <sampler2D>
Writer->writeElement(L"sampler2D", false);
Writer->writeLineBreak();
// <source>tex0-surface</source> video::SMaterial & material = node->getMaterial(i);
Writer->writeElement(L"source", false); writeMaterialEffect(meshname, strMat, material);
Writer->writeText(texSurface.c_str()); }
Writer->writeClosingTag(L"source"); n->getValue().EffectWritten = true;
Writer->writeLineBreak(); }
}
// <wrap_s>WRAP</wrap_s> const core::list<ISceneNode*>& children = node->getChildren();
Writer->writeElement(L"wrap_s", false); for ( auto it = children.begin(); it != children.end(); ++it )
Writer->writeText(toString((video::E_TEXTURE_CLAMP)layer.TextureWrapU).c_str()); {
Writer->writeClosingTag(L"wrap_s"); writeNodeEffects( *it );
Writer->writeLineBreak(); }
}
// <wrap_t>WRAP</wrap_t> void CColladaMeshWriter::writeNodeGeometries(irr::scene::ISceneNode * node)
Writer->writeElement(L"wrap_t", false); {
Writer->writeText(toString((video::E_TEXTURE_CLAMP)layer.TextureWrapV).c_str()); if ( !node || !getProperties() || !getProperties()->isExportable(node) )
Writer->writeClosingTag(L"wrap_t"); return;
Writer->writeLineBreak();
// <minfilter>LINEAR_MIPMAP_LINEAR</minfilter> IMesh* mesh = getProperties()->getMesh(node);
Writer->writeElement(L"minfilter", false); if ( mesh )
Writer->writeText(minTexfilterToString(layer.BilinearFilter, layer.TrilinearFilter).c_str()); {
Writer->writeClosingTag(L"minfilter"); MeshNode * n = Meshes.find(mesh);
Writer->writeLineBreak(); if ( n && !n->getValue().GeometryWritten )
{
writeMeshGeometry(n->getValue().Name, mesh);
n->getValue().GeometryWritten = true;
}
}
// <magfilter>LINEAR</magfilter> const core::list<ISceneNode*>& children = node->getChildren();
Writer->writeElement(L"magfilter", false); for ( auto it = children.begin(); it != children.end(); ++it )
Writer->writeText(magTexfilterToString(layer.BilinearFilter, layer.TrilinearFilter).c_str()); {
Writer->writeClosingTag(L"magfilter"); writeNodeGeometries( *it );
Writer->writeLineBreak(); }
}
// TBD - actually not sure how anisotropic should be written, so for now it writes in a way void CColladaMeshWriter::writeSceneNode(irr::scene::ISceneNode * node )
// that works with the way the loader reads it again. {
if ( layer.AnisotropicFilter ) if ( !node || !getProperties() || !getProperties()->isExportable(node) )
{ return;
// <mipfilter>LINEAR_MIPMAP_LINEAR</mipfilter>
Writer->writeElement(L"mipfilter", false);
Writer->writeText(L"LINEAR_MIPMAP_LINEAR");
Writer->writeClosingTag(L"mipfilter");
Writer->writeLineBreak();
}
// </sampler2D> // Collada doesn't require to set the id, but some other tools have problems if none exists, so we just add it).
Writer->writeClosingTag(L"sampler2D"); irr::core::stringw nameId(uniqueNameForNode(node));
Writer->writeLineBreak(); Writer->writeElement(L"node", false, L"id", nameId.c_str());
// </newparam> Writer->writeLineBreak();
Writer->writeClosingTag(L"newparam");
Writer->writeLineBreak();
}
}
Writer->writeElement(L"technique", false, L"sid", L"common"); irr::core::vector3df rot(node->getRotation());
Writer->writeLineBreak(); 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() );
E_COLLADA_TECHNIQUE_FX techFx = getProperties() ? getProperties()->getTechniqueFx(material) : ECTF_BLINN; IMesh* mesh = getProperties()->getMesh(node);
writeFxElement(material, techFx); if ( mesh )
{
MeshNode * n = Meshes.find(mesh);
if ( n )
writeMeshInstanceGeometry(n->getValue().Name, mesh);
}
Writer->writeClosingTag(L"technique"); const core::list<ISceneNode*>& children = node->getChildren();
Writer->writeLineBreak(); for ( auto it = children.begin(); it != children.end(); ++it )
Writer->writeClosingTag(L"profile_COMMON"); {
Writer->writeLineBreak(); writeSceneNode( *it );
Writer->writeClosingTag(L"effect");
Writer->writeLineBreak();
} }
Writer->writeClosingTag(L"library_effects"); Writer->writeClosingTag(L"node");
Writer->writeLineBreak(); Writer->writeLineBreak();
}
// images //! writes a mesh
if ( getWriteTextures() && !LibraryImages.empty() ) bool CColladaMeshWriter::writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 flags)
{ {
Writer->writeElement(L"library_images", false); if (!file)
Writer->writeLineBreak(); return false;
for ( irr::u32 i=0; i<LibraryImages.size(); ++i ) Writer = FileSystem->createXMLWriter(file);
{
irr::io::path p(FileSystem->getRelativeFilename(LibraryImages[i]->getName().getPath(), Directory));
//<image name="rose01">
irr::core::stringw ncname(pathToNCName(p));
Writer->writeElement(L"image", false, L"id", ncname.c_str(), L"name", ncname.c_str());
Writer->writeLineBreak();
// <init_from>../flowers/rose01.jpg</init_from>
Writer->writeElement(L"init_from", false);
Writer->writeText(pathToURI(p).c_str());
Writer->writeClosingTag(L"init_from");
Writer->writeLineBreak();
// </image>
Writer->writeClosingTag(L"image");
Writer->writeLineBreak();
}
Writer->writeClosingTag(L"library_images"); if (!Writer)
Writer->writeLineBreak(); {
os::Printer::log("Could not write file", file->getFileName());
return false;
} }
// write mesh Directory = FileSystem->getFileDir(FileSystem->getAbsolutePath( file->getFileName() ));
Writer->writeElement(L"library_geometries", false); os::Printer::log("Writing mesh", file->getFileName());
Writer->writeLineBreak();
// write COLLADA header
Writer->writeElement(L"geometry", false, L"id", L"mesh", L"name", L"mesh"); 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(); Writer->writeLineBreak();
Writer->writeElement(L"mesh");
// write asset data
writeAsset();
// write all materials
Writer->writeElement(L"library_materials", false);
Writer->writeLineBreak(); Writer->writeLineBreak();
// do some statistics for the mesh to know which stuff needs to be saved into irr::core::stringw meshname(L"name");
// the file: writeMeshMaterials(meshname, mesh);
// - 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; Writer->writeClosingTag(L"library_materials");
u32 totalTCoords2Count = 0; Writer->writeLineBreak();
bool needsTangents = false; // TODO: tangents not supported here yet
for (i=0; i<mesh->getMeshBufferCount(); ++i) LibraryImages.clear();
{ Writer->writeElement(L"library_effects", false);
totalVertexCount += mesh->getMeshBuffer(i)->getVertexCount(); Writer->writeLineBreak();
if (hasSecondTextureCoordinates(mesh->getMeshBuffer(i)->getVertexType())) writeMeshEffects(meshname, mesh);
totalTCoords2Count += mesh->getMeshBuffer(i)->getVertexCount();
if (!needsTangents) Writer->writeClosingTag(L"library_effects");
needsTangents = mesh->getMeshBuffer(i)->getVertexType() == video::EVT_TANGENTS; Writer->writeLineBreak();
}
SComponentGlobalStartPos* globalIndices = new SComponentGlobalStartPos[mesh->getMeshBufferCount()]; // images
writeLibraryImages();
// write positions // write mesh
Writer->writeElement(L"source", false, L"id", L"mesh-Pos"); Writer->writeElement(L"library_geometries", false);
Writer->writeLineBreak(); Writer->writeLineBreak();
core::stringw vertexCountStr(totalVertexCount*3); writeMeshGeometry(meshname, mesh);
Writer->writeElement(L"float_array", false, L"id", L"mesh-Pos-array",
L"count", vertexCountStr.c_str()); Writer->writeClosingTag(L"library_geometries");
Writer->writeLineBreak(); Writer->writeLineBreak();
for (i=0; i<mesh->getMeshBufferCount(); ++i) // write scene_library
if ( getWriteDefaultScene() )
{ {
scene::IMeshBuffer* buffer = mesh->getMeshBuffer(i); Writer->writeElement(L"library_visual_scenes", false);
video::E_VERTEX_TYPE vtxType = buffer->getVertexType(); Writer->writeLineBreak();
u32 vertexCount = buffer->getVertexCount();
globalIndices[i].PosStartIndex = 0; Writer->writeElement(L"visual_scene", false, L"id", L"default_scene");
Writer->writeLineBreak();
if (i!=0) Writer->writeElement(L"node", false);
globalIndices[i].PosStartIndex = globalIndices[i-1].PosLastIndex + 1; Writer->writeLineBreak();
globalIndices[i].PosLastIndex = globalIndices[i].PosStartIndex + vertexCount - 1; writeMeshInstanceGeometry(meshname, mesh);
switch(vtxType) Writer->writeClosingTag(L"node");
{ Writer->writeLineBreak();
case video::EVT_STANDARD:
{
video::S3DVertex* vtx = (video::S3DVertex*)buffer->getVertices();
for (u32 j=0; j<vertexCount; ++j)
{
Writer->writeText(toString(vtx[j].Pos).c_str());
Writer->writeLineBreak();
}
}
break;
case video::EVT_2TCOORDS:
{
video::S3DVertex2TCoords* vtx = (video::S3DVertex2TCoords*)buffer->getVertices();
for (u32 j=0; j<vertexCount; ++j)
{
Writer->writeText(toString(vtx[j].Pos).c_str());
Writer->writeLineBreak();
}
}
break;
case video::EVT_TANGENTS:
{
video::S3DVertexTangents* vtx = (video::S3DVertexTangents*)buffer->getVertices();
for (u32 j=0; j<vertexCount; ++j)
{
Writer->writeText(toString(vtx[j].Pos).c_str());
Writer->writeLineBreak();
}
}
break;
}
}
Writer->writeClosingTag(L"float_array"); Writer->writeClosingTag(L"visual_scene");
Writer->writeLineBreak(); Writer->writeLineBreak();
Writer->writeElement(L"technique_common", false); Writer->writeClosingTag(L"library_visual_scenes");
Writer->writeLineBreak(); Writer->writeLineBreak();
vertexCountStr = core::stringw(totalVertexCount);
Writer->writeElement(L"accessor", false, L"source", L"#mesh-Pos-array", // write scene
L"count", vertexCountStr.c_str(), L"stride", L"3"); Writer->writeElement(L"scene", false);
Writer->writeLineBreak(); Writer->writeLineBreak();
Writer->writeElement(L"param", true, L"name", L"X", L"type", L"float"); Writer->writeElement(L"instance_visual_scene", true, L"url", L"#default_scene");
Writer->writeLineBreak();
Writer->writeElement(L"param", true, L"name", L"Y", L"type", L"float");
Writer->writeLineBreak(); Writer->writeLineBreak();
Writer->writeElement(L"param", true, L"name", L"Z", L"type", L"float");
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)
{
//<instance_geometry url="#mesh">
core::stringw meshId("mesh-");
meshId += meshname;
Writer->writeElement(L"instance_geometry", false, L"url", toRef(meshId).c_str());
Writer->writeLineBreak();
Writer->writeElement(L"bind_material", false);
Writer->writeLineBreak();
Writer->writeElement(L"technique_common", false);
Writer->writeLineBreak(); Writer->writeLineBreak();
// instance materials
// <instance_material symbol="leaf" target="#MidsummerLeaf01"/>
for (u32 i=0; i<mesh->getMeshBufferCount(); ++i)
{
core::stringw strMat = "mat";
strMat += meshname;
strMat += i;
core::stringw strMatInst(L"#");
strMatInst += strMat;
Writer->writeElement(L"instance_material", false, L"symbol", strMat.c_str(), L"target", strMatInst.c_str());
Writer->writeLineBreak();
Writer->writeClosingTag(L"accessor"); // <bind_vertex_input semantic="mesh-TexCoord0" input_semantic="TEXCOORD"/>
core::stringw meshTexCoordId("mesh-");
meshTexCoordId += meshname;
meshTexCoordId += L"-TexCoord0"; // TODO: need to handle second UV-set
Writer->writeElement(L"bind_vertex_input", true, L"semantic", meshTexCoordId.c_str(), L"input_semantic", L"TEXCOORD" );
Writer->writeLineBreak();
Writer->writeClosingTag(L"instance_material");
Writer->writeLineBreak();
}
Writer->writeClosingTag(L"technique_common");
Writer->writeLineBreak(); Writer->writeLineBreak();
Writer->writeClosingTag(L"technique_common"); Writer->writeClosingTag(L"bind_material");
Writer->writeLineBreak(); Writer->writeLineBreak();
Writer->writeClosingTag(L"source"); Writer->writeClosingTag(L"instance_geometry");
Writer->writeLineBreak(); Writer->writeLineBreak();
}
// write texture coordinates bool CColladaMeshWriter::hasSecondTextureCoordinates(video::E_VERTEX_TYPE type) const
{
return type == video::EVT_2TCOORDS;
}
Writer->writeElement(L"source", false, L"id", L"mesh-TexCoord0"); irr::core::stringw CColladaMeshWriter::toString(const irr::core::vector3df& vec) const
Writer->writeLineBreak(); {
c8 tmpbuf[255];
snprintf(tmpbuf, 255, "%f %f %f", vec.X, vec.Y, vec.Z);
core::stringw str = tmpbuf;
vertexCountStr = core::stringw(totalVertexCount*2); return str;
Writer->writeElement(L"float_array", false, L"id", L"mesh-TexCoord0-array", }
L"count", vertexCountStr.c_str());
Writer->writeLineBreak();
for (i=0; i<mesh->getMeshBufferCount(); ++i) irr::core::stringw CColladaMeshWriter::toString(const irr::core::vector2df& vec) const
{
c8 tmpbuf[255];
snprintf(tmpbuf, 255, "%f %f", vec.X, vec.Y);
core::stringw str = tmpbuf;
return str;
}
irr::core::stringw CColladaMeshWriter::toString(const irr::video::SColorf& colorf) const
{
c8 tmpbuf[255];
snprintf(tmpbuf, 255, "%f %f %f %f", colorf.getRed(), colorf.getGreen(), colorf.getBlue(), colorf.getAlpha());
core::stringw str = tmpbuf;
return str;
}
irr::core::stringw CColladaMeshWriter::toString(const irr::video::ECOLOR_FORMAT format) const
{
switch ( format )
{ {
scene::IMeshBuffer* buffer = mesh->getMeshBuffer(i); case video::ECF_A1R5G5B5: return irr::core::stringw(L"A1R5G5B5");
video::E_VERTEX_TYPE vtxType = buffer->getVertexType(); case video::ECF_R5G6B5: return irr::core::stringw(L"R5G6B5");
u32 vertexCount = buffer->getVertexCount(); 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;
}
irr::core::stringw CColladaMeshWriter::uniqueNameForMesh(const scene::IMesh* mesh) const
{
return irr::core::stringw( (int)mesh );
}
irr::core::stringw CColladaMeshWriter::uniqueNameForNode(const scene::ISceneNode* node) const
{
irr::core::stringw name((int)node);
if ( node )
name += irr::core::stringw(node->getName());
return name;
}
irr::core::stringw CColladaMeshWriter::minTexfilterToString(bool bilinear, bool trilinear) const
{
if ( trilinear )
return core::stringw(L"LINEAR_MIPMAP_LINEAR");
else if ( bilinear )
return core::stringw(L"LINEAR_MIPMAP_NEAREST");
return core::stringw(L"NONE");
}
inline irr::core::stringw CColladaMeshWriter::magTexfilterToString(bool bilinear, bool trilinear) const
{
if ( bilinear || trilinear )
return core::stringw(L"LINEAR");
return core::stringw(L"NONE");
}
bool CColladaMeshWriter::isXmlNameStartChar(wchar_t c) const
{
return (c >= '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)
|| (c >= 0x10000 && c <= 0xEFFFF);
}
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);
}
globalIndices[i].TCoord0StartIndex = 0; // Restrict the characters to a set of allowed characters in xs::NCName.
irr::core::stringw CColladaMeshWriter::pathToNCName(const irr::io::path& path) const
{
irr::core::stringw result(L"_NCNAME_"); // ensure id starts with a valid char and reduce chance of name-conflicts
if ( path.empty() )
return result;
if (i!=0) result.append( irr::core::stringw(path) );
globalIndices[i].TCoord0StartIndex = globalIndices[i-1].TCoord0LastIndex + 1;
globalIndices[i].TCoord0LastIndex = globalIndices[i].TCoord0StartIndex + vertexCount - 1; // 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;
}
switch(vtxType) 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('/') )
{ {
case video::EVT_STANDARD: result.append(L"./");
{
video::S3DVertex* vtx = (video::S3DVertex*)buffer->getVertices();
for (u32 j=0; j<vertexCount; ++j)
{
Writer->writeText(toString(vtx[j].TCoords).c_str());
Writer->writeLineBreak();
}
}
break;
case video::EVT_2TCOORDS:
{
video::S3DVertex2TCoords* vtx = (video::S3DVertex2TCoords*)buffer->getVertices();
for (u32 j=0; j<vertexCount; ++j)
{
Writer->writeText(toString(vtx[j].TCoords).c_str());
Writer->writeLineBreak();
}
}
break;
case video::EVT_TANGENTS:
{
video::S3DVertexTangents* vtx = (video::S3DVertexTangents*)buffer->getVertices();
for (u32 j=0; j<vertexCount; ++j)
{
Writer->writeText(toString(vtx[j].TCoords).c_str());
Writer->writeLineBreak();
}
}
break;
} }
} }
result.append(path);
// TODO: make correct URI (without whitespaces)
return result;
}
Writer->writeClosingTag(L"float_array"); void CColladaMeshWriter::writeAsset()
{
Writer->writeElement(L"asset", false);
Writer->writeLineBreak(); Writer->writeLineBreak();
Writer->writeElement(L"technique_common", false); 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->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(const irr::core::stringw& meshname, scene::IMesh* mesh)
{
u32 i;
for (i=0; i<mesh->getMeshBufferCount(); ++i)
{
core::stringw strMat = "mat";
strMat += meshname;
strMat += i;
Writer->writeElement(L"material", false,
L"id", strMat.c_str(),
L"name", strMat.c_str());
Writer->writeLineBreak();
vertexCountStr = core::stringw(totalVertexCount); strMat += L"-fx";
Writer->writeElement(L"instance_effect", true,
L"url", (core::stringw(L"#") + strMat).c_str());
Writer->writeLineBreak();
Writer->writeElement(L"accessor", false, L"source", L"#mesh-TexCoord0-array", Writer->writeClosingTag(L"material");
L"count", vertexCountStr.c_str(), L"stride", L"2");
Writer->writeLineBreak(); Writer->writeLineBreak();
}
}
void CColladaMeshWriter::writeMaterialEffect(const irr::core::stringw& meshname, const irr::core::stringw& materialname, const video::SMaterial & material)
{
Writer->writeElement(L"effect", false,
L"id", materialname.c_str(),
L"name", materialname.c_str());
Writer->writeLineBreak();
Writer->writeElement(L"profile_COMMON", false);
Writer->writeLineBreak();
Writer->writeElement(L"param", true, L"name", L"U", L"type", L"float"); 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
//<newparam sid="tex0-surface">
irr::core::stringw texSurface(texName);
texSurface += L"-surface";
Writer->writeElement(L"newparam", false, L"sid", texSurface.c_str());
Writer->writeLineBreak(); Writer->writeLineBreak();
Writer->writeElement(L"param", true, L"name", L"V", L"type", L"float"); // <surface type="2D">
Writer->writeElement(L"surface", false, L"type", L"2D");
Writer->writeLineBreak();
// <init_from>internal_texturename</init_from>
Writer->writeElement(L"init_from", false);
irr::io::path p(FileSystem->getRelativeFilename(layer.Texture->getName().getPath(), Directory));
Writer->writeText(pathToNCName(p).c_str());
Writer->writeClosingTag(L"init_from");
Writer->writeLineBreak();
// <format>A8R8G8B8</format>
Writer->writeElement(L"format", false);
video::ECOLOR_FORMAT format = layer.Texture->getColorFormat();
Writer->writeText(toString(format).c_str());
Writer->writeClosingTag(L"format");
Writer->writeLineBreak();
// </surface>
Writer->writeClosingTag(L"surface");
Writer->writeLineBreak();
// </newparam>
Writer->writeClosingTag(L"newparam");
Writer->writeLineBreak(); Writer->writeLineBreak();
Writer->writeClosingTag(L"accessor"); // write texture sampler
Writer->writeLineBreak(); // <newparam sid="tex0-sampler">
irr::core::stringw texSampler(texName);
texSampler += L"-sampler";
Writer->writeElement(L"newparam", false, L"sid", texSampler.c_str());
Writer->writeLineBreak();
// <sampler2D>
Writer->writeElement(L"sampler2D", false);
Writer->writeLineBreak();
Writer->writeClosingTag(L"technique_common"); // <source>tex0-surface</source>
Writer->writeLineBreak(); Writer->writeElement(L"source", false);
Writer->writeText(texSurface.c_str());
Writer->writeClosingTag(L"source");
Writer->writeLineBreak();
Writer->writeClosingTag(L"source"); // <wrap_s>WRAP</wrap_s>
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_t>WRAP</wrap_t>
Writer->writeElement(L"wrap_t", false);
Writer->writeText(toString((video::E_TEXTURE_CLAMP)layer.TextureWrapV).c_str());
Writer->writeClosingTag(L"wrap_t");
Writer->writeLineBreak();
// <minfilter>LINEAR_MIPMAP_LINEAR</minfilter>
Writer->writeElement(L"minfilter", false);
Writer->writeText(minTexfilterToString(layer.BilinearFilter, layer.TrilinearFilter).c_str());
Writer->writeClosingTag(L"minfilter");
Writer->writeLineBreak();
// <magfilter>LINEAR</magfilter>
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 )
{
// <mipfilter>LINEAR_MIPMAP_LINEAR</mipfilter>
Writer->writeElement(L"mipfilter", false);
Writer->writeText(L"LINEAR_MIPMAP_LINEAR");
Writer->writeClosingTag(L"mipfilter");
Writer->writeLineBreak();
}
// </sampler2D>
Writer->writeClosingTag(L"sampler2D");
Writer->writeLineBreak();
// </newparam>
Writer->writeClosingTag(L"newparam");
Writer->writeLineBreak();
}
}
Writer->writeElement(L"technique", false, L"sid", L"common");
Writer->writeLineBreak(); Writer->writeLineBreak();
// write normals E_COLLADA_TECHNIQUE_FX techFx = getProperties() ? getProperties()->getTechniqueFx(material) : ECTF_BLINN;
writeFxElement(meshname, material, techFx);
Writer->writeElement(L"source", false, L"id", L"mesh-Normal"); Writer->writeClosingTag(L"technique");
Writer->writeLineBreak();
Writer->writeClosingTag(L"profile_COMMON");
Writer->writeLineBreak();
Writer->writeClosingTag(L"effect");
Writer->writeLineBreak(); Writer->writeLineBreak();
}
void CColladaMeshWriter::writeMeshEffects(const irr::core::stringw& meshname, scene::IMesh* mesh)
{
for (u32 i=0; i<mesh->getMeshBufferCount(); ++i)
{
core::stringw strMat = "mat";
strMat += meshname;
strMat += i;
strMat += L"-fx";
video::SMaterial & material = mesh->getMeshBuffer(i)->getMaterial();
writeMaterialEffect(meshname, strMat, material);
}
}
void CColladaMeshWriter::writeMeshGeometry(const irr::core::stringw& meshname, scene::IMesh* mesh)
{
core::stringw meshId("mesh-");
meshId += meshname;
vertexCountStr = core::stringw(totalVertexCount*3); Writer->writeElement(L"geometry", false, L"id", meshId.c_str(), L"name", meshId.c_str());
Writer->writeElement(L"float_array", false, L"id", L"mesh-Normal-array", Writer->writeLineBreak();
L"count", vertexCountStr.c_str()); Writer->writeElement(L"mesh");
Writer->writeLineBreak(); 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; i<mesh->getMeshBufferCount(); ++i) for (i=0; i<mesh->getMeshBufferCount(); ++i)
{ {
scene::IMeshBuffer* buffer = mesh->getMeshBuffer(i); totalVertexCount += mesh->getMeshBuffer(i)->getVertexCount();
video::E_VERTEX_TYPE vtxType = buffer->getVertexType();
u32 vertexCount = buffer->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();
globalIndices[i].NormalStartIndex = 0; for (i=0; i<mesh->getMeshBufferCount(); ++i)
{
scene::IMeshBuffer* buffer = mesh->getMeshBuffer(i);
video::E_VERTEX_TYPE vtxType = buffer->getVertexType();
u32 vertexCount = buffer->getVertexCount();
if (i!=0) globalIndices[i].PosStartIndex = 0;
globalIndices[i].NormalStartIndex = globalIndices[i-1].NormalLastIndex + 1;
globalIndices[i].NormalLastIndex = globalIndices[i].NormalStartIndex + vertexCount - 1; if (i!=0)
globalIndices[i].PosStartIndex = globalIndices[i-1].PosLastIndex + 1;
switch(vtxType) globalIndices[i].PosLastIndex = globalIndices[i].PosStartIndex + vertexCount - 1;
{
case video::EVT_STANDARD: switch(vtxType)
{ {
video::S3DVertex* vtx = (video::S3DVertex*)buffer->getVertices(); case video::EVT_STANDARD:
for (u32 j=0; j<vertexCount; ++j)
{ {
Writer->writeText(toString(vtx[j].Normal).c_str()); video::S3DVertex* vtx = (video::S3DVertex*)buffer->getVertices();
Writer->writeLineBreak(); for (u32 j=0; j<vertexCount; ++j)
{
Writer->writeText(toString(vtx[j].Pos).c_str());
Writer->writeLineBreak();
}
} }
} break;
break; case video::EVT_2TCOORDS:
case video::EVT_2TCOORDS:
{
video::S3DVertex2TCoords* vtx = (video::S3DVertex2TCoords*)buffer->getVertices();
for (u32 j=0; j<vertexCount; ++j)
{ {
Writer->writeText(toString(vtx[j].Normal).c_str()); video::S3DVertex2TCoords* vtx = (video::S3DVertex2TCoords*)buffer->getVertices();
Writer->writeLineBreak(); for (u32 j=0; j<vertexCount; ++j)
{
Writer->writeText(toString(vtx[j].Pos).c_str());
Writer->writeLineBreak();
}
} }
} break;
break; case video::EVT_TANGENTS:
case video::EVT_TANGENTS:
{
video::S3DVertexTangents* vtx = (video::S3DVertexTangents*)buffer->getVertices();
for (u32 j=0; j<vertexCount; ++j)
{ {
Writer->writeText(toString(vtx[j].Normal).c_str()); video::S3DVertexTangents* vtx = (video::S3DVertexTangents*)buffer->getVertices();
Writer->writeLineBreak(); for (u32 j=0; j<vertexCount; ++j)
{
Writer->writeText(toString(vtx[j].Pos).c_str());
Writer->writeLineBreak();
}
} }
break;
} }
break;
} }
}
Writer->writeClosingTag(L"float_array");
Writer->writeLineBreak();
Writer->writeElement(L"technique_common", false);
Writer->writeLineBreak();
vertexCountStr = core::stringw(totalVertexCount); Writer->writeClosingTag(L"float_array");
Writer->writeLineBreak();
Writer->writeElement(L"accessor", false, L"source", L"#mesh-Normal-array", Writer->writeElement(L"technique_common", false);
L"count", vertexCountStr.c_str(), L"stride", L"3");
Writer->writeLineBreak(); Writer->writeLineBreak();
Writer->writeElement(L"param", true, L"name", L"X", L"type", L"float"); vertexCountStr = core::stringw(totalVertexCount);
Writer->writeLineBreak();
Writer->writeElement(L"param", true, L"name", L"Y", L"type", L"float"); Writer->writeElement(L"accessor", false, L"source", toRef(meshPosArrayId).c_str(),
Writer->writeLineBreak(); L"count", vertexCountStr.c_str(), L"stride", L"3");
Writer->writeElement(L"param", true, L"name", L"Z", L"type", L"float");
Writer->writeLineBreak(); Writer->writeLineBreak();
Writer->writeClosingTag(L"accessor"); Writer->writeElement(L"param", true, L"name", L"X", L"type", L"float");
Writer->writeLineBreak(); 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"technique_common"); Writer->writeClosingTag(L"accessor");
Writer->writeLineBreak(); Writer->writeLineBreak();
Writer->writeClosingTag(L"technique_common");
Writer->writeLineBreak();
Writer->writeClosingTag(L"source"); Writer->writeClosingTag(L"source");
Writer->writeLineBreak(); Writer->writeLineBreak();
// write second set of texture coordinates // write texture coordinates
if (totalTCoords2Count) core::stringw meshTexCoord0Id(meshId);
{ meshTexCoord0Id += L"-TexCoord0";
Writer->writeElement(L"source", false, L"id", L"mesh-TexCoord1"); Writer->writeElement(L"source", false, L"id", meshTexCoord0Id.c_str());
Writer->writeLineBreak(); Writer->writeLineBreak();
vertexCountStr = core::stringw(totalTCoords2Count*2); vertexCountStr = core::stringw(totalVertexCount*2);
Writer->writeElement(L"float_array", false, L"id", L"mesh-TexCoord1-array", core::stringw meshTexCoordArrayId(meshTexCoord0Id);
L"count", vertexCountStr.c_str()); meshTexCoordArrayId += L"-array";
Writer->writeElement(L"float_array", false, L"id", meshTexCoordArrayId.c_str(),
L"count", vertexCountStr.c_str());
Writer->writeLineBreak(); Writer->writeLineBreak();
for (i=0; i<mesh->getMeshBufferCount(); ++i) for (i=0; i<mesh->getMeshBufferCount(); ++i)
...@@ -677,31 +1040,46 @@ bool CColladaMeshWriter::writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 ...@@ -677,31 +1040,46 @@ bool CColladaMeshWriter::writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32
video::E_VERTEX_TYPE vtxType = buffer->getVertexType(); video::E_VERTEX_TYPE vtxType = buffer->getVertexType();
u32 vertexCount = buffer->getVertexCount(); u32 vertexCount = buffer->getVertexCount();
if (hasSecondTextureCoordinates(vtxType)) globalIndices[i].TCoord0StartIndex = 0;
{
globalIndices[i].TCoord1StartIndex = 0;
if (i!=0 && globalIndices[i-1].TCoord1LastIndex != -1) if (i!=0)
globalIndices[i].TCoord1StartIndex = globalIndices[i-1].TCoord1LastIndex + 1; globalIndices[i].TCoord0StartIndex = globalIndices[i-1].TCoord0LastIndex + 1;
globalIndices[i].TCoord1LastIndex = globalIndices[i].TCoord1StartIndex + vertexCount - 1; globalIndices[i].TCoord0LastIndex = globalIndices[i].TCoord0StartIndex + vertexCount - 1;
switch(vtxType) switch(vtxType)
{
case video::EVT_STANDARD:
{ {
case video::EVT_2TCOORDS: video::S3DVertex* vtx = (video::S3DVertex*)buffer->getVertices();
for (u32 j=0; j<vertexCount; ++j)
{ {
video::S3DVertex2TCoords* vtx = (video::S3DVertex2TCoords*)buffer->getVertices(); Writer->writeText(toString(vtx[j].TCoords).c_str());
for (u32 j=0; j<vertexCount; ++j) Writer->writeLineBreak();
{ }
Writer->writeText(toString(vtx[j].TCoords2).c_str()); }
Writer->writeLineBreak(); break;
} case video::EVT_2TCOORDS:
{
video::S3DVertex2TCoords* vtx = (video::S3DVertex2TCoords*)buffer->getVertices();
for (u32 j=0; j<vertexCount; ++j)
{
Writer->writeText(toString(vtx[j].TCoords).c_str());
Writer->writeLineBreak();
}
}
break;
case video::EVT_TANGENTS:
{
video::S3DVertexTangents* vtx = (video::S3DVertexTangents*)buffer->getVertices();
for (u32 j=0; j<vertexCount; ++j)
{
Writer->writeText(toString(vtx[j].TCoords).c_str());
Writer->writeLineBreak();
} }
break;
default:
break;
} }
} // end this buffer has 2 texture coordinates break;
}
} }
Writer->writeClosingTag(L"float_array"); Writer->writeClosingTag(L"float_array");
...@@ -710,10 +1088,10 @@ bool CColladaMeshWriter::writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 ...@@ -710,10 +1088,10 @@ bool CColladaMeshWriter::writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32
Writer->writeElement(L"technique_common", false); Writer->writeElement(L"technique_common", false);
Writer->writeLineBreak(); Writer->writeLineBreak();
vertexCountStr = core::stringw(totalTCoords2Count); vertexCountStr = core::stringw(totalVertexCount);
Writer->writeElement(L"accessor", false, L"source", L"#mesh-TexCoord1-array", Writer->writeElement(L"accessor", false, L"source", toRef(meshTexCoordArrayId).c_str(),
L"count", vertexCountStr.c_str(), L"stride", L"2"); L"count", vertexCountStr.c_str(), L"stride", L"2");
Writer->writeLineBreak(); Writer->writeLineBreak();
Writer->writeElement(L"param", true, L"name", L"U", L"type", L"float"); Writer->writeElement(L"param", true, L"name", L"U", L"type", L"float");
...@@ -727,373 +1105,315 @@ bool CColladaMeshWriter::writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 ...@@ -727,373 +1105,315 @@ bool CColladaMeshWriter::writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32
Writer->writeClosingTag(L"technique_common"); Writer->writeClosingTag(L"technique_common");
Writer->writeLineBreak(); Writer->writeLineBreak();
Writer->writeClosingTag(L"source"); Writer->writeClosingTag(L"source");
Writer->writeLineBreak();
}
// write tangents
// TODO
// write vertices
Writer->writeElement(L"vertices", false, L"id", L"mesh-Vtx");
Writer->writeLineBreak();
Writer->writeElement(L"input", true, L"semantic", L"POSITION", L"source", L"#mesh-Pos");
Writer->writeLineBreak(); Writer->writeLineBreak();
Writer->writeClosingTag(L"vertices"); // write normals
core::stringw meshNormalId(meshId);
meshNormalId += L"-Normal";
Writer->writeElement(L"source", false, L"id", meshNormalId.c_str());
Writer->writeLineBreak(); Writer->writeLineBreak();
// write polygons vertexCountStr = core::stringw(totalVertexCount*3);
core::stringw meshNormalArrayId(meshNormalId);
for (i=0; i<mesh->getMeshBufferCount(); ++i) meshNormalArrayId += L"-array";
{ Writer->writeElement(L"float_array", false, L"id", meshNormalArrayId.c_str(),
scene::IMeshBuffer* buffer = mesh->getMeshBuffer(i); L"count", vertexCountStr.c_str());
const u32 polyCount = buffer->getIndexCount() / 3;
core::stringw strPolyCount(polyCount);
core::stringw strMat = "mat";
strMat += 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", L"#mesh-Vtx", L"offset", L"0");
Writer->writeLineBreak();
Writer->writeElement(L"input", true, L"semantic", L"TEXCOORD", L"source", L"#mesh-TexCoord0", L"offset", L"1");
Writer->writeLineBreak();
Writer->writeElement(L"input", true, L"semantic", L"NORMAL", L"source", L"#mesh-Normal", L"offset", L"2");
Writer->writeLineBreak(); Writer->writeLineBreak();
bool has2ndTexCoords = hasSecondTextureCoordinates(buffer->getVertexType()); for (i=0; i<mesh->getMeshBufferCount(); ++i)
if (has2ndTexCoords)
{ {
Writer->writeElement(L"input", true, L"semantic", L"TEXCOORD", L"source", L"#mesh-TexCoord1", L"idx", L"3"); scene::IMeshBuffer* buffer = mesh->getMeshBuffer(i);
Writer->writeLineBreak(); video::E_VERTEX_TYPE vtxType = buffer->getVertexType();
} u32 vertexCount = buffer->getVertexCount();
// 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);
for (u32 p=0; p<polyCount; ++p) globalIndices[i].NormalStartIndex = 0;
{
core::stringw strP;
strP += buffer->getIndices()[(p*3) + 0] + posIdx; if (i!=0)
strP += " "; globalIndices[i].NormalStartIndex = globalIndices[i-1].NormalLastIndex + 1;
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; globalIndices[i].NormalLastIndex = globalIndices[i].NormalStartIndex + vertexCount - 1;
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; switch(vtxType)
strP += " ";
strP += buffer->getIndices()[(p*3) + 2] + tCoordIdx;
strP += " ";
strP += buffer->getIndices()[(p*3) + 2] + normalIdx;
if (has2ndTexCoords)
{ {
strP += " "; case video::EVT_STANDARD:
strP += buffer->getIndices()[(p*3) + 2] + tCoord2Idx; {
video::S3DVertex* vtx = (video::S3DVertex*)buffer->getVertices();
for (u32 j=0; j<vertexCount; ++j)
{
Writer->writeText(toString(vtx[j].Normal).c_str());
Writer->writeLineBreak();
}
}
break;
case video::EVT_2TCOORDS:
{
video::S3DVertex2TCoords* vtx = (video::S3DVertex2TCoords*)buffer->getVertices();
for (u32 j=0; j<vertexCount; ++j)
{
Writer->writeText(toString(vtx[j].Normal).c_str());
Writer->writeLineBreak();
}
}
break;
case video::EVT_TANGENTS:
{
video::S3DVertexTangents* vtx = (video::S3DVertexTangents*)buffer->getVertices();
for (u32 j=0; j<vertexCount; ++j)
{
Writer->writeText(toString(vtx[j].Normal).c_str());
Writer->writeLineBreak();
}
}
break;
} }
strP += " ";
Writer->writeText(strP.c_str());
} }
Writer->writeClosingTag(L"p"); Writer->writeClosingTag(L"float_array");
Writer->writeLineBreak(); Writer->writeLineBreak();
// close index buffer section Writer->writeElement(L"technique_common", false);
Writer->writeClosingTag(L"triangles");
Writer->writeLineBreak(); Writer->writeLineBreak();
}
// close mesh and geometry vertexCountStr = core::stringw(totalVertexCount);
Writer->writeClosingTag(L"mesh"); Writer->writeElement(L"accessor", false, L"source", toRef(meshNormalArrayId).c_str(),
Writer->writeLineBreak(); L"count", vertexCountStr.c_str(), L"stride", L"3");
Writer->writeClosingTag(L"geometry"); Writer->writeLineBreak();
Writer->writeLineBreak();
Writer->writeClosingTag(L"library_geometries"); Writer->writeElement(L"param", true, L"name", L"X", L"type", L"float");
Writer->writeLineBreak(); 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();
// write scene_library Writer->writeClosingTag(L"source");
if ( getWriteScene() ) Writer->writeLineBreak();
// write second set of texture coordinates
core::stringw meshTexCoord1Id(meshId);
meshTexCoord1Id += L"-TexCoord1";
if (totalTCoords2Count)
{ {
Writer->writeElement(L"library_visual_scenes", false); Writer->writeElement(L"source", false, L"id", meshTexCoord1Id.c_str());
Writer->writeLineBreak(); Writer->writeLineBreak();
Writer->writeElement(L"visual_scene", false, L"id", L"default_scene"); 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(); Writer->writeLineBreak();
Writer->writeElement(L"node", false); for (i=0; i<mesh->getMeshBufferCount(); ++i)
Writer->writeLineBreak(); {
scene::IMeshBuffer* buffer = mesh->getMeshBuffer(i);
//<instance_geometry url="#mesh"> video::E_VERTEX_TYPE vtxType = buffer->getVertexType();
Writer->writeElement(L"instance_geometry", false, L"url", L"#mesh"); u32 vertexCount = buffer->getVertexCount();
Writer->writeLineBreak();
Writer->writeElement(L"bind_material", false); if (hasSecondTextureCoordinates(vtxType))
Writer->writeLineBreak(); {
globalIndices[i].TCoord1StartIndex = 0;
Writer->writeElement(L"technique_common", false); if (i!=0 && globalIndices[i-1].TCoord1LastIndex != -1)
Writer->writeLineBreak(); globalIndices[i].TCoord1StartIndex = globalIndices[i-1].TCoord1LastIndex + 1;
// instance materials
// <instance_material symbol="leaf" target="#MidsummerLeaf01"/>
for (i=0; i<mesh->getMeshBufferCount(); ++i)
{
core::stringw strMat = "mat";
strMat += i;
core::stringw strMatInst(L"#");
strMatInst += strMat;
Writer->writeElement(L"instance_material", false, L"symbol", strMat.c_str(), L"target", strMatInst.c_str());
Writer->writeLineBreak();
// <bind_vertex_input semantic="mesh-TexCoord0" input_semantic="TEXCOORD"/> globalIndices[i].TCoord1LastIndex = globalIndices[i].TCoord1StartIndex + vertexCount - 1;
Writer->writeElement(L"bind_vertex_input", true, L"semantic", L"mesh-TexCoord0", L"input_semantic", L"TEXCOORD" );
Writer->writeLineBreak();
Writer->writeClosingTag(L"instance_material"); switch(vtxType)
{
case video::EVT_2TCOORDS:
{
video::S3DVertex2TCoords* vtx = (video::S3DVertex2TCoords*)buffer->getVertices();
for (u32 j=0; j<vertexCount; ++j)
{
Writer->writeText(toString(vtx[j].TCoords2).c_str());
Writer->writeLineBreak(); Writer->writeLineBreak();
} }
}
Writer->writeClosingTag(L"technique_common"); break;
Writer->writeLineBreak(); default:
break;
Writer->writeClosingTag(L"bind_material"); }
Writer->writeLineBreak(); } // end this buffer has 2 texture coordinates
}
Writer->writeClosingTag(L"instance_geometry");
Writer->writeLineBreak();
Writer->writeClosingTag(L"node"); Writer->writeClosingTag(L"float_array");
Writer->writeLineBreak(); Writer->writeLineBreak();
Writer->writeClosingTag(L"visual_scene"); Writer->writeElement(L"technique_common", false);
Writer->writeLineBreak(); Writer->writeLineBreak();
vertexCountStr = core::stringw(totalTCoords2Count);
Writer->writeClosingTag(L"library_visual_scenes"); Writer->writeElement(L"accessor", false, L"source", toRef(meshTexCoord1ArrayId).c_str(),
Writer->writeLineBreak(); 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();
// write scene Writer->writeClosingTag(L"accessor");
Writer->writeElement(L"scene", false); Writer->writeLineBreak();
Writer->writeLineBreak();
Writer->writeElement(L"instance_visual_scene", true, L"url", L"#default_scene"); Writer->writeClosingTag(L"technique_common");
Writer->writeLineBreak(); Writer->writeLineBreak();
Writer->writeClosingTag(L"scene"); Writer->writeClosingTag(L"source");
Writer->writeLineBreak(); Writer->writeLineBreak();
} }
// close everything
Writer->writeClosingTag(L"COLLADA");
Writer->drop();
delete [] globalIndices;
return true;
}
bool CColladaMeshWriter::hasSecondTextureCoordinates(video::E_VERTEX_TYPE type) const
{
return type == video::EVT_2TCOORDS;
}
irr::core::stringw CColladaMeshWriter::toString(const irr::core::vector3df& vec) const
{
c8 tmpbuf[255];
snprintf(tmpbuf, 255, "%f %f %f", vec.X, vec.Y, vec.Z);
core::stringw str = tmpbuf;
return str; // write tangents
}
irr::core::stringw CColladaMeshWriter::toString(const irr::core::vector2df& vec) const // TODO
{
c8 tmpbuf[255];
snprintf(tmpbuf, 255, "%f %f", vec.X, vec.Y);
core::stringw str = tmpbuf;
return str; // write vertices
} core::stringw meshVtxId(meshId);
meshVtxId += L"-Vtx";
Writer->writeElement(L"vertices", false, L"id", meshVtxId.c_str());
Writer->writeLineBreak();
irr::core::stringw CColladaMeshWriter::toString(const irr::video::SColorf& colorf) const Writer->writeElement(L"input", true, L"semantic", L"POSITION", L"source", toRef(meshPosId).c_str());
{ Writer->writeLineBreak();
c8 tmpbuf[255];
snprintf(tmpbuf, 255, "%f %f %f %f", colorf.getRed(), colorf.getGreen(), colorf.getBlue(), colorf.getAlpha());
core::stringw str = tmpbuf;
return str; Writer->writeClosingTag(L"vertices");
} Writer->writeLineBreak();
irr::core::stringw CColladaMeshWriter::toString(const irr::video::ECOLOR_FORMAT format) const // write polygons
{
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 for (i=0; i<mesh->getMeshBufferCount(); ++i)
{
switch ( clamp )
{ {
case video::ETC_REPEAT: scene::IMeshBuffer* buffer = mesh->getMeshBuffer(i);
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::minTexfilterToString(bool bilinear, bool trilinear) const const u32 polyCount = buffer->getIndexCount() / 3;
{ core::stringw strPolyCount(polyCount);
if ( trilinear ) core::stringw strMat = "mat";
return core::stringw(L"LINEAR_MIPMAP_LINEAR"); strMat += meshname;
else if ( bilinear ) strMat += i;
return core::stringw(L"LINEAR_MIPMAP_NEAREST");
return core::stringw(L"NONE");
}
inline irr::core::stringw CColladaMeshWriter::magTexfilterToString(bool bilinear, bool trilinear) const Writer->writeElement(L"triangles", false, L"count", strPolyCount.c_str(),
{ L"material", strMat.c_str());
if ( bilinear || trilinear ) Writer->writeLineBreak();
return core::stringw(L"LINEAR");
return core::stringw(L"NONE"); 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");
Writer->writeLineBreak();
Writer->writeElement(L"input", true, L"semantic", L"NORMAL", L"source", toRef(meshNormalId).c_str(), L"offset", L"2");
Writer->writeLineBreak();
bool CColladaMeshWriter::isXmlNameStartChar(wchar_t c) const bool has2ndTexCoords = hasSecondTextureCoordinates(buffer->getVertexType());
{ if (has2ndTexCoords)
return (c >= 'A' && c <= 'Z') {
|| c == L'_' Writer->writeElement(L"input", true, L"semantic", L"TEXCOORD", L"source", toRef(meshTexCoord1Id).c_str(), L"idx", L"3");
|| (c >= 'a' && c <= 'z') Writer->writeLineBreak();
|| (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)
|| (c >= 0x10000 && c <= 0xEFFFF);
}
bool CColladaMeshWriter::isXmlNameChar(wchar_t c) const // write indices now
{
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. s32 posIdx = globalIndices[i].PosStartIndex;
irr::core::stringw CColladaMeshWriter::pathToNCName(const irr::io::path& path) const s32 tCoordIdx = globalIndices[i].TCoord0StartIndex;
{ s32 normalIdx = globalIndices[i].NormalStartIndex;
irr::core::stringw result(L"_NCNAME_"); // ensure id starts with a valid char and reduce chance of name-conflicts s32 tCoord2Idx = globalIndices[i].TCoord1StartIndex;
if ( path.empty() )
return result;
result.append( irr::core::stringw(path) ); Writer->writeElement(L"p", false);
// We replace all characters not allowed by a replacement char for (u32 p=0; p<polyCount; ++p)
const wchar_t REPLACMENT = L'-';
for ( irr::u32 i=1; i < result.size(); ++i )
{
if ( result[i] == L':' || !isXmlNameChar(result[i]) )
{ {
result[i] = REPLACMENT; core::stringw strP;
strP += buffer->getIndices()[(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();
} }
return result;
// close mesh and geometry
delete [] globalIndices;
Writer->writeClosingTag(L"mesh");
Writer->writeLineBreak();
Writer->writeClosingTag(L"geometry");
Writer->writeLineBreak();
} }
irr::core::stringw CColladaMeshWriter::pathToURI(const irr::io::path& path) const void CColladaMeshWriter::writeLibraryImages()
{ {
irr::core::stringw result; if ( getWriteTextures() && !LibraryImages.empty() )
// 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 "./" ? Writer->writeElement(L"library_images", false);
if ( path[0] != _IRR_TEXT('.') Writer->writeLineBreak();
|| path[1] != _IRR_TEXT('/') )
for ( irr::u32 i=0; i<LibraryImages.size(); ++i )
{ {
result.append(L"./"); irr::io::path p(FileSystem->getRelativeFilename(LibraryImages[i]->getName().getPath(), Directory));
//<image name="rose01">
irr::core::stringw ncname(pathToNCName(p));
Writer->writeElement(L"image", false, L"id", ncname.c_str(), L"name", ncname.c_str());
Writer->writeLineBreak();
// <init_from>../flowers/rose01.jpg</init_from>
Writer->writeElement(L"init_from", false);
Writer->writeText(pathToURI(p).c_str());
Writer->writeClosingTag(L"init_from");
Writer->writeLineBreak();
// </image>
Writer->writeClosingTag(L"image");
Writer->writeLineBreak();
} }
}
result.append(path);
// TODO: make correct URI (without whitespaces)
return result; Writer->writeClosingTag(L"library_images");
Writer->writeLineBreak();
}
} }
void CColladaMeshWriter::writeColorElement(const video::SColor & col) void CColladaMeshWriter::writeColorElement(const video::SColor & col)
...@@ -1113,33 +1433,14 @@ s32 CColladaMeshWriter::getTextureIdx(const video::SMaterial & material, E_COLLA ...@@ -1113,33 +1433,14 @@ s32 CColladaMeshWriter::getTextureIdx(const video::SMaterial & material, E_COLLA
|| !getProperties() ) || !getProperties() )
return -1; return -1;
s32 idx = -1; s32 idx = getProperties()->getTextureIdx(material, cs);
switch ( cs )
{
case ECS_DIFFUSE:
idx = getProperties()->getDiffuseTextureIdx(material);
break;
case ECS_AMBIENT:
idx = getProperties()->getAmbientTextureIdx(material);
break;
case ECS_EMISSIVE:
idx = getProperties()->getEmissiveTextureIdx(material);
break;
case ECS_SPECULAR:
idx = getProperties()->getSpecularTextureIdx(material);
break;
case ECS_TRANSPARENT:
idx = getProperties()->getTransparentTextureIdx(material);
break;
}
if ( idx >= 0 && !material.TextureLayer[idx].Texture ) if ( idx >= 0 && !material.TextureLayer[idx].Texture )
return -1; return -1;
return idx; return idx;
} }
bool CColladaMeshWriter::writeTextureSampler(s32 textureIdx) bool CColladaMeshWriter::writeTextureSampler(const irr::core::stringw& meshname, s32 textureIdx)
{ {
if ( textureIdx < 0 ) if ( textureIdx < 0 )
return false; return false;
...@@ -1149,13 +1450,16 @@ bool CColladaMeshWriter::writeTextureSampler(s32 textureIdx) ...@@ -1149,13 +1450,16 @@ bool CColladaMeshWriter::writeTextureSampler(s32 textureIdx)
sampler += L"-sampler"; sampler += L"-sampler";
// <texture texture="sampler" texcoord="texCoord"/> // <texture texture="sampler" texcoord="texCoord"/>
Writer->writeElement(L"texture", true, L"texture", sampler.c_str(), L"texcoord", L"mesh-TexCoord0" ); core::stringw meshTexCoordId("mesh-");
meshTexCoordId += meshname;
meshTexCoordId += L"-TexCoord0"; // TODO: need to handle second UV-set
Writer->writeElement(L"texture", true, L"texture", sampler.c_str(), L"texcoord", meshTexCoordId.c_str() );
Writer->writeLineBreak(); Writer->writeLineBreak();
return true; return true;
} }
void CColladaMeshWriter::writeFxElement(const video::SMaterial & material, E_COLLADA_TECHNIQUE_FX techFx) void CColladaMeshWriter::writeFxElement(const irr::core::stringw& meshname, const video::SMaterial & material, E_COLLADA_TECHNIQUE_FX techFx)
{ {
core::stringw fxLabel; core::stringw fxLabel;
bool writeEmission = true; bool writeEmission = true;
...@@ -1199,7 +1503,7 @@ void CColladaMeshWriter::writeFxElement(const video::SMaterial & material, E_COL ...@@ -1199,7 +1503,7 @@ void CColladaMeshWriter::writeFxElement(const video::SMaterial & material, E_COL
{ {
Writer->writeElement(L"emission", false); Writer->writeElement(L"emission", false);
Writer->writeLineBreak(); Writer->writeLineBreak();
if ( !writeTextureSampler( getTextureIdx(material, ECS_EMISSIVE)) ) if ( !writeTextureSampler( meshname, getTextureIdx(material, ECCS_EMISSIVE)) )
writeColorElement(material.EmissiveColor); writeColorElement(material.EmissiveColor);
Writer->writeClosingTag(L"emission"); Writer->writeClosingTag(L"emission");
Writer->writeLineBreak(); Writer->writeLineBreak();
...@@ -1209,7 +1513,7 @@ void CColladaMeshWriter::writeFxElement(const video::SMaterial & material, E_COL ...@@ -1209,7 +1513,7 @@ void CColladaMeshWriter::writeFxElement(const video::SMaterial & material, E_COL
{ {
Writer->writeElement(L"ambient", false); Writer->writeElement(L"ambient", false);
Writer->writeLineBreak(); Writer->writeLineBreak();
if ( !writeTextureSampler( getTextureIdx(material, ECS_AMBIENT)) ) if ( !writeTextureSampler( meshname, getTextureIdx(material, ECCS_AMBIENT)) )
writeColorElement(material.AmbientColor); writeColorElement(material.AmbientColor);
Writer->writeClosingTag(L"ambient"); Writer->writeClosingTag(L"ambient");
Writer->writeLineBreak(); Writer->writeLineBreak();
...@@ -1219,7 +1523,7 @@ void CColladaMeshWriter::writeFxElement(const video::SMaterial & material, E_COL ...@@ -1219,7 +1523,7 @@ void CColladaMeshWriter::writeFxElement(const video::SMaterial & material, E_COL
{ {
Writer->writeElement(L"diffuse", false); Writer->writeElement(L"diffuse", false);
Writer->writeLineBreak(); Writer->writeLineBreak();
if ( !writeTextureSampler( getTextureIdx(material, ECS_DIFFUSE)) ) if ( !writeTextureSampler( meshname, getTextureIdx(material, ECCS_DIFFUSE)) )
writeColorElement(material.DiffuseColor); writeColorElement(material.DiffuseColor);
Writer->writeClosingTag(L"diffuse"); Writer->writeClosingTag(L"diffuse");
Writer->writeLineBreak(); Writer->writeLineBreak();
...@@ -1229,7 +1533,7 @@ void CColladaMeshWriter::writeFxElement(const video::SMaterial & material, E_COL ...@@ -1229,7 +1533,7 @@ void CColladaMeshWriter::writeFxElement(const video::SMaterial & material, E_COL
{ {
Writer->writeElement(L"specular", false); Writer->writeElement(L"specular", false);
Writer->writeLineBreak(); Writer->writeLineBreak();
if ( !writeTextureSampler( getTextureIdx(material, ECS_SPECULAR)) ) if ( !writeTextureSampler( meshname, getTextureIdx(material, ECCS_SPECULAR)) )
writeColorElement(material.SpecularColor); writeColorElement(material.SpecularColor);
Writer->writeClosingTag(L"specular"); Writer->writeClosingTag(L"specular");
Writer->writeLineBreak(); Writer->writeLineBreak();
...@@ -1255,13 +1559,13 @@ void CColladaMeshWriter::writeFxElement(const video::SMaterial & material, E_COL ...@@ -1255,13 +1559,13 @@ void CColladaMeshWriter::writeFxElement(const video::SMaterial & material, E_COL
if ( writeTransparent ) if ( writeTransparent )
{ {
s32 textureIdx = getTextureIdx(material, ECS_TRANSPARENT); s32 textureIdx = getTextureIdx(material, ECCS_TRANSPARENT);
E_COLLADA_TRANSPARENT_FX transparentFx = getProperties() ? getProperties()->getTransparentFx(material) : ECOF_A_ONE; E_COLLADA_TRANSPARENT_FX transparentFx = getProperties() ? getProperties()->getTransparentFx(material) : ECOF_A_ONE;
if ( textureIdx >= 0 || transparentFx >= ECOF_TRANSPARENT_DIFFUSE ) if ( textureIdx >= 0 || transparentFx >= ECOF_TRANSPARENT_DIFFUSE )
{ {
Writer->writeElement(L"transparent", false, L"opaque", toString(transparentFx).c_str()); Writer->writeElement(L"transparent", false, L"opaque", toString(transparentFx).c_str());
Writer->writeLineBreak(); Writer->writeLineBreak();
if ( !writeTextureSampler(textureIdx) ) if ( !writeTextureSampler(meshname, textureIdx) )
{ {
if ( transparentFx & ECOF_TRANSPARENT_DIFFUSE ) if ( transparentFx & ECOF_TRANSPARENT_DIFFUSE )
writeColorElement(material.DiffuseColor); writeColorElement(material.DiffuseColor);
...@@ -1309,6 +1613,47 @@ void CColladaMeshWriter::writeFloatElement(irr::f32 value) ...@@ -1309,6 +1613,47 @@ void CColladaMeshWriter::writeFloatElement(irr::f32 value)
Writer->writeLineBreak(); 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(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();
}
} // end namespace } // end namespace
} // end namespace } // end namespace
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "IColladaMeshWriter.h" #include "IColladaMeshWriter.h"
#include "S3DVertex.h" #include "S3DVertex.h"
#include "irrMap.h"
#include "IVideoDriver.h" #include "IVideoDriver.h"
namespace irr namespace irr
...@@ -26,27 +27,9 @@ namespace scene ...@@ -26,27 +27,9 @@ namespace scene
//! Which lighting model should be used in the technique (FX) section when exporting effects (materials) //! 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; virtual E_COLLADA_TECHNIQUE_FX getTechniqueFx(const video::SMaterial& material) const;
//! Which texture index should be used when setting the emissive texture //! 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 */ /** \return the index to the texture-layer or -1 if that texture should never be exported */
virtual s32 getEmissiveTextureIdx(const video::SMaterial& material) const; virtual s32 getTextureIdx(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs) const;
//! Which texture index should be used when setting the ambient texture
/** \return the index to the texture-layer or -1 if that texture should never be exported */
virtual s32 getAmbientTextureIdx(const video::SMaterial& material) const;
//! Which texture index should be used when setting the diffuse texture
/** \return the index to the texture-layer or -1 if that texture should never be exported */
virtual s32 getDiffuseTextureIdx(const video::SMaterial& material) const;
//! Which texture index should be used when setting the specular texture
/** \return the index to the texture-layer or -1 if that texture should never be exported */
virtual s32 getSpecularTextureIdx(const video::SMaterial& material) const;
//! Which texture index should be used when writing the transparent texture
/** Note: By default the alpha channel is used, if you want to use RGB you have to set
the ECOF_RGB_ZERO flag in getTransparentFx.
\return the index to the texture-layer or -1 if that texture should never be exported */
virtual s32 getTransparentTextureIdx( const video::SMaterial& material) const;
//! Return the settings for transparence //! Return the settings for transparence
virtual E_COLLADA_TRANSPARENT_FX getTransparentFx(const video::SMaterial& material) const; virtual E_COLLADA_TRANSPARENT_FX getTransparentFx(const video::SMaterial& material) const;
...@@ -55,6 +38,12 @@ namespace scene ...@@ -55,6 +38,12 @@ namespace scene
/** This value is additional to transparent settings, if both are set they will be multiplicated. /** 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 */ \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; virtual f32 getTransparency(const 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 IMesh* getMesh(irr::scene::ISceneNode * node);
}; };
...@@ -71,21 +60,15 @@ public: ...@@ -71,21 +60,15 @@ public:
//! Returns the type of the mesh writer //! Returns the type of the mesh writer
virtual EMESH_WRITER_TYPE getType() const; 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 //! writes a mesh
virtual bool writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 flags=EMWF_NONE); virtual bool writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 flags=EMWF_NONE);
protected: protected:
enum E_COLLADA_COLOR_SAMPLER
{
ECS_DIFFUSE,
ECS_AMBIENT,
ECS_EMISSIVE,
ECS_SPECULAR,
ECS_TRANSPARENT
};
bool hasSecondTextureCoordinates(video::E_VERTEX_TYPE type) const; bool hasSecondTextureCoordinates(video::E_VERTEX_TYPE type) const;
inline irr::core::stringw toString(const irr::core::vector3df& vec) const; inline irr::core::stringw toString(const irr::core::vector3df& vec) const;
inline irr::core::stringw toString(const irr::core::vector2df& vec) const; inline irr::core::stringw toString(const irr::core::vector2df& vec) const;
...@@ -93,6 +76,9 @@ protected: ...@@ -93,6 +76,9 @@ protected:
inline irr::core::stringw toString(const irr::video::ECOLOR_FORMAT format) const; 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::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;
irr::core::stringw uniqueNameForMesh(const scene::IMesh* mesh) const;
irr::core::stringw uniqueNameForNode(const scene::ISceneNode* node) const;
irr::core::stringw minTexfilterToString(bool bilinear, bool trilinear) const; irr::core::stringw minTexfilterToString(bool bilinear, bool trilinear) const;
irr::core::stringw magTexfilterToString(bool bilinear, bool trilinear) const; irr::core::stringw magTexfilterToString(bool bilinear, bool trilinear) const;
irr::core::stringw pathToNCName(const irr::io::path& path) const; irr::core::stringw pathToNCName(const irr::io::path& path) const;
...@@ -100,10 +86,25 @@ protected: ...@@ -100,10 +86,25 @@ protected:
inline bool isXmlNameStartChar(wchar_t c) const; inline bool isXmlNameStartChar(wchar_t c) const;
inline bool isXmlNameChar(wchar_t c) const; inline bool isXmlNameChar(wchar_t c) const;
s32 getTextureIdx(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs); s32 getTextureIdx(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs);
void writeAsset();
void makeMeshNames(irr::scene::ISceneNode * node);
void writeNodeMaterials(irr::scene::ISceneNode * node);
void writeNodeEffects(irr::scene::ISceneNode * node);
void writeNodeGeometries(irr::scene::ISceneNode * node);
void writeSceneNode(irr::scene::ISceneNode * node);
void writeMeshMaterials(const irr::core::stringw& meshname, scene::IMesh* mesh);
void writeMeshEffects(const irr::core::stringw& meshname, scene::IMesh* mesh);
void writeMaterialEffect(const irr::core::stringw& meshname, 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);
void writeLibraryImages();
void writeColorElement(const video::SColor & col); void writeColorElement(const video::SColor & col);
bool writeTextureSampler(s32 textureIdx); bool writeTextureSampler(const irr::core::stringw& meshname, s32 textureIdx);
void writeFxElement(const video::SMaterial & material, E_COLLADA_TECHNIQUE_FX techFx); void writeFxElement(const irr::core::stringw& meshname, 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 writeScaleElement(const irr::core::vector3df& scale);
void writeTranslateElement(const irr::core::vector3df& translate);
struct SComponentGlobalStartPos struct SComponentGlobalStartPos
{ {
...@@ -131,6 +132,20 @@ protected: ...@@ -131,6 +132,20 @@ protected:
io::IXMLWriter* Writer; io::IXMLWriter* Writer;
core::array<video::ITexture*> LibraryImages; core::array<video::ITexture*> LibraryImages;
io::path Directory; io::path Directory;
struct ColladaMesh
{
ColladaMesh() : MaterialWritten(false), EffectWritten(false), GeometryWritten(false)
{
}
irr::core::stringw Name;
bool MaterialWritten;
bool EffectWritten;
bool GeometryWritten;
};
typedef core::map<IMesh*, ColladaMesh>::Node MeshNode;
core::map<IMesh*, ColladaMesh> Meshes;
}; };
......
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