Commit 6296a1c1 authored by cutealien's avatar cutealien

ColladaMeshWriter - add infrastructure to export transparent textures.

git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@3851 dfc29bdd-3216-0410-991c-e03cc46cb475
parent ac6e07f8
...@@ -17,7 +17,7 @@ namespace io ...@@ -17,7 +17,7 @@ namespace io
namespace scene namespace scene
{ {
// Lighting models - more or less the way Collada categorizes materials //! Lighting models - more or less the way Collada categorizes materials
enum E_COLLADA_TECHNIQUE_FX enum E_COLLADA_TECHNIQUE_FX
{ {
//! Blinn-phong which is default for opengl and dx fixed function pipelines. //! Blinn-phong which is default for opengl and dx fixed function pipelines.
...@@ -31,6 +31,38 @@ namespace scene ...@@ -31,6 +31,38 @@ namespace scene
ECTF_CONSTANT ECTF_CONSTANT
}; };
//! How to export opacity to collada
/** Note that there is also a check for transparent textures in IColladaMeshWriterProperties
which will be evaluated additionally to the flags:
No ECOF_TRANSPARENT_* flag and no texture => <transparent> will not be written at all.
No ECOF_TRANSPARENT_* flag but a valid texture => texture will be written.
ECOF_TRANSPARENT_* flag is set and no texture => A color will be written.
Both, a ECOF_TRANSPARENT_* flag and a valid texture => only the texture will be written.
You can only have either ECOF_A_ONE or ECOF_RGB_ZERO otherwise ECOF_RGB_ZERO is used.
You can only have one of the ECOF_TRANSPARENT_* flags otherwise the first is used.
*/
enum E_COLLADA_TRANSPARENT_FX
{
//! default - only alpha channel of color or texture is used. Can't be used together with ECOF_RGB_ZERO.
ECOF_A_ONE = 0,
//! Alpha values for each RGB channel of color or texture are used. Can't be used together with ECOF_A_ONE.
ECOF_RGB_ZERO = 1,
//! Write diffuse material color as transparent
ECOF_TRANSPARENT_DIFFUSE = 2,
//! Write ambient material color as transparent
ECOF_TRANSPARENT_AMBIENT = 4,
//! Write emissive material color as transparent
ECOF_TRANSPARENT_EMISSIVE = 8,
//! Write specular material color as transparent
ECOF_TRANSPARENT_SPECULAR = 16,
};
//! 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
{ {
...@@ -40,22 +72,35 @@ namespace scene ...@@ -40,22 +72,35 @@ 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 setting the emissive texture //! Which texture index should be used when writing the emissive texture
/** \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; virtual s32 getEmissiveTextureIdx(const video::SMaterial& material) const = 0;
//! Which texture index should be used when setting the ambient texture //! Which texture index should be used when writing the ambient texture
/** \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 getAmbientTextureIdx(const video::SMaterial& material) const = 0; virtual s32 getAmbientTextureIdx(const video::SMaterial& material) const = 0;
//! Which texture index should be used when setting the diffuse texture //! 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 */ /** \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; virtual s32 getDiffuseTextureIdx(const video::SMaterial& material) const = 0;
//! Which texture index should be used when setting the specular texture //! 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 */ /** \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; 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
virtual E_COLLADA_TRANSPARENT_FX getTransparentFx(const video::SMaterial& material) const = 0;
//! Transparency value for the material.
/** This value is additional to transparent settings, if both are set they will be multiplicated.
\return 1.0 for fully transparent, 0.0 for not transparent and not written at all when < 0.f */
virtual f32 getTransparency(const video::SMaterial& material) const = 0;
}; };
......
...@@ -49,6 +49,27 @@ s32 CColladaMeshWriterProperties::getSpecularTextureIdx(const video::SMaterial& ...@@ -49,6 +49,27 @@ s32 CColladaMeshWriterProperties::getSpecularTextureIdx(const video::SMaterial&
return 3; return 3;
} }
//! Which texture index should be used when writing the transparent texture
s32 CColladaMeshWriterProperties::getTransparentTextureIdx( const video::SMaterial& material) const
{
// TODO
return -1;
}
//! Return the settings for transparence
E_COLLADA_TRANSPARENT_FX CColladaMeshWriterProperties::getTransparentFx(const video::SMaterial& material) const
{
// TODO
return ECOF_A_ONE;
}
//! Transparency value for the material.
f32 CColladaMeshWriterProperties::getTransparency(const video::SMaterial& material) const
{
// TODO
return -1.f;
}
CColladaMeshWriter::CColladaMeshWriter(video::IVideoDriver* driver, CColladaMeshWriter::CColladaMeshWriter(video::IVideoDriver* driver,
io::IFileSystem* fs) io::IFileSystem* fs)
...@@ -933,7 +954,7 @@ irr::core::stringw CColladaMeshWriter::toString(const irr::core::vector2df& vec) ...@@ -933,7 +954,7 @@ irr::core::stringw CColladaMeshWriter::toString(const irr::core::vector2df& vec)
return str; return str;
} }
inline irr::core::stringw CColladaMeshWriter::toString(const irr::video::SColorf& colorf) const irr::core::stringw CColladaMeshWriter::toString(const irr::video::SColorf& colorf) const
{ {
c8 tmpbuf[255]; c8 tmpbuf[255];
snprintf(tmpbuf, 255, "%f %f %f %f", colorf.getRed(), colorf.getGreen(), colorf.getBlue(), colorf.getAlpha()); snprintf(tmpbuf, 255, "%f %f %f %f", colorf.getRed(), colorf.getGreen(), colorf.getBlue(), colorf.getAlpha());
...@@ -942,7 +963,7 @@ inline irr::core::stringw CColladaMeshWriter::toString(const irr::video::SColorf ...@@ -942,7 +963,7 @@ inline irr::core::stringw CColladaMeshWriter::toString(const irr::video::SColorf
return str; return str;
} }
inline irr::core::stringw CColladaMeshWriter::toString(const irr::video::ECOLOR_FORMAT format) const irr::core::stringw CColladaMeshWriter::toString(const irr::video::ECOLOR_FORMAT format) const
{ {
switch ( format ) switch ( format )
{ {
...@@ -954,7 +975,7 @@ inline irr::core::stringw CColladaMeshWriter::toString(const irr::video::ECOLOR_ ...@@ -954,7 +975,7 @@ inline irr::core::stringw CColladaMeshWriter::toString(const irr::video::ECOLOR_
} }
} }
inline irr::core::stringw CColladaMeshWriter::toString(const irr::video::E_TEXTURE_CLAMP clamp) const irr::core::stringw CColladaMeshWriter::toString(const irr::video::E_TEXTURE_CLAMP clamp) const
{ {
switch ( clamp ) switch ( clamp )
{ {
...@@ -974,7 +995,15 @@ inline irr::core::stringw CColladaMeshWriter::toString(const irr::video::E_TEXTU ...@@ -974,7 +995,15 @@ inline irr::core::stringw CColladaMeshWriter::toString(const irr::video::E_TEXTU
return core::stringw(L"NONE"); return core::stringw(L"NONE");
} }
inline irr::core::stringw CColladaMeshWriter::minTexfilterToString(bool bilinear, bool trilinear) const 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
{ {
if ( trilinear ) if ( trilinear )
return core::stringw(L"LINEAR_MIPMAP_LINEAR"); return core::stringw(L"LINEAR_MIPMAP_LINEAR");
...@@ -1078,36 +1107,45 @@ void CColladaMeshWriter::writeColorElement(const video::SColor & col) ...@@ -1078,36 +1107,45 @@ void CColladaMeshWriter::writeColorElement(const video::SColor & col)
Writer->writeLineBreak(); Writer->writeLineBreak();
} }
bool CColladaMeshWriter::writeTextureSampler(const video::SMaterial & material, video::E_COLOR_MATERIAL cm) s32 CColladaMeshWriter::getTextureIdx(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs)
{ {
if ( !getWriteTextures() if ( !getWriteTextures()
|| !getProperties() ) || !getProperties() )
return false; return -1;
s32 idx = -1; s32 idx = -1;
switch ( cm ) switch ( cs )
{ {
case video::ECM_DIFFUSE: case ECS_DIFFUSE:
idx = getProperties()->getDiffuseTextureIdx(material); idx = getProperties()->getDiffuseTextureIdx(material);
break; break;
case video::ECM_AMBIENT: case ECS_AMBIENT:
idx = getProperties()->getAmbientTextureIdx(material); idx = getProperties()->getAmbientTextureIdx(material);
break; break;
case video::ECM_EMISSIVE: case ECS_EMISSIVE:
idx = getProperties()->getEmissiveTextureIdx(material); idx = getProperties()->getEmissiveTextureIdx(material);
break; break;
case video::ECM_SPECULAR: case ECS_SPECULAR:
idx = getProperties()->getSpecularTextureIdx(material); idx = getProperties()->getSpecularTextureIdx(material);
break; break;
default: case ECS_TRANSPARENT:
idx = getProperties()->getTransparentTextureIdx(material);
break; break;
} }
if ( idx < 0 || !material.TextureLayer[idx].Texture ) if ( idx >= 0 && !material.TextureLayer[idx].Texture )
return -1;
return idx;
}
bool CColladaMeshWriter::writeTextureSampler(s32 textureIdx)
{
if ( textureIdx < 0 )
return false; return false;
irr::core::stringw sampler(L"tex"); irr::core::stringw sampler(L"tex");
sampler += irr::core::stringw(idx); sampler += irr::core::stringw(textureIdx);
sampler += L"-sampler"; sampler += L"-sampler";
// <texture texture="sampler" texcoord="texCoord"/> // <texture texture="sampler" texcoord="texCoord"/>
...@@ -1161,7 +1199,7 @@ void CColladaMeshWriter::writeFxElement(const video::SMaterial & material, E_COL ...@@ -1161,7 +1199,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(material, video::ECM_EMISSIVE) ) if ( !writeTextureSampler( getTextureIdx(material, ECS_EMISSIVE)) )
writeColorElement(material.EmissiveColor); writeColorElement(material.EmissiveColor);
Writer->writeClosingTag(L"emission"); Writer->writeClosingTag(L"emission");
Writer->writeLineBreak(); Writer->writeLineBreak();
...@@ -1171,7 +1209,7 @@ void CColladaMeshWriter::writeFxElement(const video::SMaterial & material, E_COL ...@@ -1171,7 +1209,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(material, video::ECM_AMBIENT) ) if ( !writeTextureSampler( getTextureIdx(material, ECS_AMBIENT)) )
writeColorElement(material.AmbientColor); writeColorElement(material.AmbientColor);
Writer->writeClosingTag(L"ambient"); Writer->writeClosingTag(L"ambient");
Writer->writeLineBreak(); Writer->writeLineBreak();
...@@ -1181,7 +1219,7 @@ void CColladaMeshWriter::writeFxElement(const video::SMaterial & material, E_COL ...@@ -1181,7 +1219,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(material, video::ECM_DIFFUSE) ) if ( !writeTextureSampler( getTextureIdx(material, ECS_DIFFUSE)) )
writeColorElement(material.DiffuseColor); writeColorElement(material.DiffuseColor);
Writer->writeClosingTag(L"diffuse"); Writer->writeClosingTag(L"diffuse");
Writer->writeLineBreak(); Writer->writeLineBreak();
...@@ -1191,7 +1229,7 @@ void CColladaMeshWriter::writeFxElement(const video::SMaterial & material, E_COL ...@@ -1191,7 +1229,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(material, video::ECM_SPECULAR) ) if ( !writeTextureSampler( getTextureIdx(material, ECS_SPECULAR)) )
writeColorElement(material.SpecularColor); writeColorElement(material.SpecularColor);
Writer->writeClosingTag(L"specular"); Writer->writeClosingTag(L"specular");
Writer->writeLineBreak(); Writer->writeLineBreak();
...@@ -1201,25 +1239,76 @@ void CColladaMeshWriter::writeFxElement(const video::SMaterial & material, E_COL ...@@ -1201,25 +1239,76 @@ void CColladaMeshWriter::writeFxElement(const video::SMaterial & material, E_COL
{ {
Writer->writeElement(L"shininess", false); Writer->writeElement(L"shininess", false);
Writer->writeLineBreak(); Writer->writeLineBreak();
Writer->writeElement(L"float", false); writeFloatElement(material.Shininess);
Writer->writeText(core::stringw(material.Shininess).c_str());
Writer->writeClosingTag(L"float");
Writer->writeLineBreak();
Writer->writeClosingTag(L"shininess"); Writer->writeClosingTag(L"shininess");
Writer->writeLineBreak(); Writer->writeLineBreak();
} }
// missing: if ( writeReflective )
// reflective {
// reflectivity // TODO reflective
// transparent }
// transparency if ( writeReflectivity )
// index_of_refraction> {
// TODO reflectivity
}
if ( writeTransparent )
{
s32 textureIdx = getTextureIdx(material, ECS_TRANSPARENT);
E_COLLADA_TRANSPARENT_FX transparentFx = getProperties() ? getProperties()->getTransparentFx(material) : ECOF_A_ONE;
if ( textureIdx >= 0 || transparentFx >= ECOF_TRANSPARENT_DIFFUSE )
{
Writer->writeElement(L"transparent", false, L"opaque", toString(transparentFx).c_str());
Writer->writeLineBreak();
if ( !writeTextureSampler(textureIdx) )
{
if ( transparentFx & ECOF_TRANSPARENT_DIFFUSE )
writeColorElement(material.DiffuseColor);
else if ( transparentFx & ECOF_TRANSPARENT_AMBIENT)
writeColorElement(material.AmbientColor);
else if ( transparentFx & ECOF_TRANSPARENT_EMISSIVE )
writeColorElement(material.EmissiveColor);
else if ( transparentFx & ECOF_TRANSPARENT_SPECULAR )
writeColorElement(material.SpecularColor);
}
Writer->writeClosingTag(L"transparent");
Writer->writeLineBreak();
}
}
if ( writeTransparency && getProperties() )
{
f32 t = getProperties()->getTransparency(material);
if ( t >= 0.f )
{
// <transparency> <float>1.000000</float> </transparency>
Writer->writeElement(L"transparency", false);
Writer->writeLineBreak();
writeFloatElement(t);
Writer->writeClosingTag(L"transparency");
Writer->writeLineBreak();
}
}
if ( writeIndexOfRefraction )
{
// TODO index_of_refraction>
}
Writer->writeClosingTag(fxLabel.c_str()); Writer->writeClosingTag(fxLabel.c_str());
Writer->writeLineBreak(); Writer->writeLineBreak();
} }
void CColladaMeshWriter::writeFloatElement(irr::f32 value)
{
Writer->writeElement(L"float", false);
Writer->writeText(core::stringw(value).c_str());
Writer->writeClosingTag(L"float");
Writer->writeLineBreak();
}
} // end namespace } // end namespace
} // end namespace } // end namespace
......
...@@ -41,6 +41,20 @@ namespace scene ...@@ -41,6 +41,20 @@ namespace scene
//! Which texture index should be used when setting the specular texture //! 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 */ /** \return the index to the texture-layer or -1 if that texture should never be exported */
virtual s32 getSpecularTextureIdx(const video::SMaterial& material) const; 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
virtual E_COLLADA_TRANSPARENT_FX getTransparentFx(const video::SMaterial& material) const;
//! Transparency value for the material.
/** This value is additional to transparent settings, if both are set they will be multiplicated.
\return 1.0 for fully transparent, 0.0 for not transparent and not written at all when < 0.f */
virtual f32 getTransparency(const video::SMaterial& material) const;
}; };
...@@ -62,6 +76,15 @@ public: ...@@ -62,6 +76,15 @@ public:
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;
...@@ -69,15 +92,18 @@ protected: ...@@ -69,15 +92,18 @@ protected:
inline irr::core::stringw toString(const irr::video::SColorf& colorf) const; inline irr::core::stringw toString(const irr::video::SColorf& colorf) const;
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;
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;
irr::core::stringw pathToURI(const irr::io::path& path) const; irr::core::stringw pathToURI(const irr::io::path& path) const;
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);
void writeColorElement(const video::SColor & col); void writeColorElement(const video::SColor & col);
bool writeTextureSampler(const video::SMaterial & material, video::E_COLOR_MATERIAL cm); bool writeTextureSampler(s32 textureIdx);
void writeFxElement(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);
struct SComponentGlobalStartPos struct SComponentGlobalStartPos
{ {
......
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