ColladMeshWriter: Unified functions in IColladaMeshWriterProperties some more. Can now export reflection and refraction and more flexible color-mapping (which means all effects can now be written). Also some fixed some schema-breaking when writing node-id's.

git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@3865 dfc29bdd-3216-0410-991c-e03cc46cb475
master
cutealien 2011-06-22 19:49:14 +00:00
parent f64b0063a1
commit 84291fd165
3 changed files with 237 additions and 141 deletions

View File

@ -33,46 +33,47 @@ namespace scene
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.
*/
//! How to interpret the opacity in collada
enum E_COLLADA_TRANSPARENT_FX
{
//! default - only alpha channel of color or texture is used. Can't be used together with ECOF_RGB_ZERO.
//! default - only alpha channel of color or texture is used.
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.
//! Alpha values for each RGB channel of color or texture are used.
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
};
//! For mapping irrlicht textures indices to collada color-types
//! Color names collada uses in it's color samplers
enum E_COLLADA_COLOR_SAMPLER
{
ECCS_DIFFUSE,
ECCS_AMBIENT,
ECCS_EMISSIVE,
ECCS_SPECULAR,
ECCS_TRANSPARENT
ECCS_TRANSPARENT,
ECCS_REFLECTIVE,
};
//! Irrlicht colors which can be mapped to E_COLLADA_COLOR_SAMPLER values
enum E_COLLADA_IRR_COLOR
{
//! Don't write this element at all
ECIC_NONE,
//! Check IColladaMeshWriterProperties for custom color
ECIC_CUSTOM,
//! Use SMaterial::DiffuseColor
ECIC_DIFFUSE,
//! Use SMaterial::AmbientColor
ECIC_AMBIENT,
//! Use SMaterial::EmissiveColor
ECIC_EMISSIVE,
//! Use SMaterial::SpecularColor
ECIC_SPECULAR
};
//! Callback interface for properties which can be used to influence collada writing
@ -91,20 +92,42 @@ namespace scene
also the ECOF_RGB_ZERO flag in getTransparentFx. */
virtual s32 getTextureIdx(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs) const = 0;
//! Return the settings for transparence
//! Return which color from Irrlicht should be used for the color requested by collada
/** Note that collada allows exporting either texture or color, not both.
So color mapping is only checked if we have no valid texture already.
By default we try to return best fits when possible. For example ECCS_DIFFUSE is mapped to ECIC_DIFFUSE.
When ECIC_CUSTOM is returned then the result of getCustomColor will be used. */
virtual E_COLLADA_IRR_COLOR getColorMapping(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs) const = 0;
//! Return custom colors for certain color types requested by collada.
/** Only used when getColorMapping returns ECIC_CUSTOM for the same paramters. */
virtual video::SColor getCustomColor(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs) const = 0;
//! Return the transparence color interpretation.
/** Not this is only about ECCS_TRANSPARENT and does not affect getTransparency. */
virtual E_COLLADA_TRANSPARENT_FX getTransparentFx(const video::SMaterial& material) const = 0;
//! Transparency value for the material.
//! Transparency value for that 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;
//! Should node be used in scene export?
//! Reflectivity value for that material
/** The amount of perfect mirror reflection to be added to the reflected light
\return 0.0 - 1.0 for reflectivity and element is not written at all when < 0.f */
virtual f32 getReflectivity(const video::SMaterial& material) const = 0;
//! Return index of refraction for that material
/** By default we don't write that.
\return a value >= 0.f to write <index_of_refraction> when it's < 0 nothing will be written */
virtual f32 getIndexOfRefraction(const video::SMaterial& material) const = 0;
//! Should node be used in scene export? (only needed for scene-writing, ignored in mesh-writing)
//! 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.
//! Return the mesh for the given node. If it has no mesh or shouldn't export it's mesh
//! you can return 0 in which case only the transformation matrix of the node will be used.
virtual IMesh* getMesh(irr::scene::ISceneNode * node) = 0;
};

View File

@ -48,21 +48,64 @@ s32 CColladaMeshWriterProperties::getTextureIdx(const video::SMaterial & materia
return 3;
case ECCS_TRANSPARENT:
return -1;
case ECCS_REFLECTIVE:
return -1;
};
return -1;
}
E_COLLADA_IRR_COLOR CColladaMeshWriterProperties::getColorMapping(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs) const
{
switch ( cs )
{
case ECCS_DIFFUSE:
return ECIC_DIFFUSE;
case ECCS_AMBIENT:
return ECIC_AMBIENT;
case ECCS_EMISSIVE:
return ECIC_EMISSIVE;
case ECCS_SPECULAR:
return ECIC_SPECULAR;
case ECCS_TRANSPARENT:
return ECIC_NONE;
case ECCS_REFLECTIVE:
return ECIC_CUSTOM;
};
return ECIC_NONE;
}
//! Return custom colors for certain color types requested by collada.
video::SColor CColladaMeshWriterProperties::getCustomColor(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs) const
{
return video::SColor(255, 0, 0, 0);
}
//! Return the settings for transparence
E_COLLADA_TRANSPARENT_FX CColladaMeshWriterProperties::getTransparentFx(const video::SMaterial& material) const
{
// TODO
// TODO: figure out best default mapping
return ECOF_A_ONE;
}
//! Transparency value for the material.
f32 CColladaMeshWriterProperties::getTransparency(const video::SMaterial& material) const
{
// TODO
// TODO: figure out best default mapping
return -1.f;
}
//! Reflectivity value for that material
f32 CColladaMeshWriterProperties::getReflectivity(const video::SMaterial& material) const
{
// TODO: figure out best default mapping
return 0.f;
}
//! Return index of refraction for that material
f32 CColladaMeshWriterProperties::getIndexOfRefraction(const video::SMaterial& material) const
{
return -1.f;
}
@ -596,7 +639,8 @@ irr::core::stringw CColladaMeshWriter::uniqueNameForMesh(const scene::IMesh* mes
irr::core::stringw CColladaMeshWriter::uniqueNameForNode(const scene::ISceneNode* node) const
{
irr::core::stringw name((int)node);
irr::core::stringw name(L"id"); // (prefix, because xs::ID can't start with a number)
name += irr::core::stringw((int)node);
if ( node )
name += irr::core::stringw(node->getName());
return name;
@ -1427,7 +1471,7 @@ void CColladaMeshWriter::writeColorElement(const video::SColor & col)
Writer->writeLineBreak();
}
s32 CColladaMeshWriter::getTextureIdx(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs)
s32 CColladaMeshWriter::getCheckedTextureIdx(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs)
{
if ( !getWriteTextures()
|| !getProperties() )
@ -1440,11 +1484,30 @@ s32 CColladaMeshWriter::getTextureIdx(const video::SMaterial & material, E_COLLA
return idx;
}
bool CColladaMeshWriter::writeTextureSampler(const irr::core::stringw& meshname, s32 textureIdx)
video::SColor CColladaMeshWriter::getColorMapping(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs, E_COLLADA_IRR_COLOR colType)
{
if ( textureIdx < 0 )
return false;
switch ( colType )
{
case ECIC_CUSTOM:
return getProperties()->getCustomColor(material, cs);
case ECIC_DIFFUSE:
return material.DiffuseColor;
case ECIC_AMBIENT:
return material.AmbientColor;
case ECIC_EMISSIVE:
return material.EmissiveColor;
case ECIC_SPECULAR:
return material.SpecularColor;
}
return video::SColor(255, 0, 0, 0);
}
void CColladaMeshWriter::writeTextureSampler(const irr::core::stringw& meshname, s32 textureIdx)
{
irr::core::stringw sampler(L"tex");
sampler += irr::core::stringw(textureIdx);
sampler += L"-sampler";
@ -1455,8 +1518,6 @@ bool CColladaMeshWriter::writeTextureSampler(const irr::core::stringw& 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();
return true;
}
void CColladaMeshWriter::writeFxElement(const irr::core::stringw& meshname, const video::SMaterial & material, E_COLLADA_TECHNIQUE_FX techFx)
@ -1499,105 +1560,88 @@ void CColladaMeshWriter::writeFxElement(const irr::core::stringw& meshname, cons
// write all interesting material parameters
// attributes must be written in fixed order
if ( writeEmission )
if ( getProperties() )
{
Writer->writeElement(L"emission", false);
Writer->writeLineBreak();
if ( !writeTextureSampler( meshname, getTextureIdx(material, ECCS_EMISSIVE)) )
writeColorElement(material.EmissiveColor);
Writer->writeClosingTag(L"emission");
Writer->writeLineBreak();
}
if ( writeAmbient )
{
Writer->writeElement(L"ambient", false);
Writer->writeLineBreak();
if ( !writeTextureSampler( meshname, getTextureIdx(material, ECCS_AMBIENT)) )
writeColorElement(material.AmbientColor);
Writer->writeClosingTag(L"ambient");
Writer->writeLineBreak();
}
if ( writeDiffuse )
{
Writer->writeElement(L"diffuse", false);
Writer->writeLineBreak();
if ( !writeTextureSampler( meshname, getTextureIdx(material, ECCS_DIFFUSE)) )
writeColorElement(material.DiffuseColor);
Writer->writeClosingTag(L"diffuse");
Writer->writeLineBreak();
}
if ( writeSpecular )
{
Writer->writeElement(L"specular", false);
Writer->writeLineBreak();
if ( !writeTextureSampler( meshname, getTextureIdx(material, ECCS_SPECULAR)) )
writeColorElement(material.SpecularColor);
Writer->writeClosingTag(L"specular");
Writer->writeLineBreak();
}
if ( writeShininess )
{
Writer->writeElement(L"shininess", false);
Writer->writeLineBreak();
writeFloatElement(material.Shininess);
Writer->writeClosingTag(L"shininess");
Writer->writeLineBreak();
}
if ( writeReflective )
{
// TODO reflective
}
if ( writeReflectivity )
{
// TODO reflectivity
}
if ( writeTransparent )
{
s32 textureIdx = getTextureIdx(material, ECCS_TRANSPARENT);
E_COLLADA_TRANSPARENT_FX transparentFx = getProperties() ? getProperties()->getTransparentFx(material) : ECOF_A_ONE;
if ( textureIdx >= 0 || transparentFx >= ECOF_TRANSPARENT_DIFFUSE )
if ( writeEmission )
{
Writer->writeElement(L"transparent", false, L"opaque", toString(transparentFx).c_str());
writeColorFx(meshname, material, L"emission", ECCS_EMISSIVE);
}
if ( writeAmbient )
{
writeColorFx(meshname, material, L"ambient", ECCS_AMBIENT);
}
if ( writeDiffuse )
{
writeColorFx(meshname, material, L"diffuse", ECCS_DIFFUSE);
}
if ( writeSpecular )
{
writeColorFx(meshname, material, L"specular", ECCS_SPECULAR);
}
if ( writeShininess )
{
Writer->writeElement(L"shininess", false);
Writer->writeLineBreak();
if ( !writeTextureSampler(meshname, textureIdx) )
writeFloatElement(material.Shininess);
Writer->writeClosingTag(L"shininess");
Writer->writeLineBreak();
}
if ( writeReflective )
{
writeColorFx(meshname, material, L"reflective", ECCS_REFLECTIVE);
}
if ( writeReflectivity )
{
f32 t = getProperties()->getReflectivity(material);
if ( t >= 0.f )
{
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);
// <transparency> <float>1.000000</float> </transparency>
Writer->writeElement(L"reflectivity", false);
Writer->writeLineBreak();
writeFloatElement(t);
Writer->writeClosingTag(L"reflectivity");
Writer->writeLineBreak();
}
Writer->writeClosingTag(L"transparent");
Writer->writeLineBreak();
}
}
if ( writeTransparency && getProperties() )
{
f32 t = getProperties()->getTransparency(material);
if ( t >= 0.f )
if ( writeTransparent )
{
// <transparency> <float>1.000000</float> </transparency>
Writer->writeElement(L"transparency", false);
Writer->writeLineBreak();
writeFloatElement(t);
Writer->writeClosingTag(L"transparency");
Writer->writeLineBreak();
E_COLLADA_TRANSPARENT_FX transparentFx = getProperties()->getTransparentFx(material);
writeColorFx(meshname, material, L"transparent", ECCS_TRANSPARENT, L"opaque", toString(transparentFx).c_str());
}
}
if ( writeIndexOfRefraction )
{
// TODO index_of_refraction>
if ( writeTransparency )
{
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 )
{
f32 t = getProperties()->getIndexOfRefraction(material);
if ( t >= 0.f )
{
Writer->writeElement(L"index_of_refraction", false);
Writer->writeLineBreak();
writeFloatElement(t);
Writer->writeClosingTag(L"index_of_refraction");
Writer->writeLineBreak();
}
}
}
@ -1605,6 +1649,23 @@ void CColladaMeshWriter::writeFxElement(const irr::core::stringw& meshname, cons
Writer->writeLineBreak();
}
void CColladaMeshWriter::writeColorFx(const irr::core::stringw& meshname, const video::SMaterial & material, const wchar_t * colorname, E_COLLADA_COLOR_SAMPLER cs, const wchar_t* attr1Name, const wchar_t* attr1Value)
{
irr::s32 idx = getCheckedTextureIdx(material, cs);
E_COLLADA_IRR_COLOR colType = idx < 0 ? getProperties()->getColorMapping(material, cs) : ECIC_NONE;
if ( idx >= 0 || colType != ECIC_NONE )
{
Writer->writeElement(colorname, false, attr1Name, attr1Value);
Writer->writeLineBreak();
if ( idx >= 0 )
writeTextureSampler( meshname, idx);
else
writeColorElement(getColorMapping(material, cs, colType));
Writer->writeClosingTag(colorname);
Writer->writeLineBreak();
}
}
void CColladaMeshWriter::writeFloatElement(irr::f32 value)
{
Writer->writeElement(L"float", false);

View File

@ -21,29 +21,39 @@ namespace scene
{
//! Callback interface for properties which can be used to influence collada writing
// (Implementer note: keep namespace labels here to make it easier for users copying this one)
class CColladaMeshWriterProperties : public virtual IColladaMeshWriterProperties
{
public:
//! 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 irr::scene::E_COLLADA_TECHNIQUE_FX getTechniqueFx(const irr::video::SMaterial& material) const;
//! 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 */
virtual s32 getTextureIdx(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs) const;
virtual irr::s32 getTextureIdx(const irr::video::SMaterial & material, irr::scene::E_COLLADA_COLOR_SAMPLER cs) const;
//! Return which color from Irrlicht should be used for the color requested by collada
virtual irr::scene::E_COLLADA_IRR_COLOR getColorMapping(const irr::video::SMaterial & material, irr::scene::E_COLLADA_COLOR_SAMPLER cs) const;
//! Return custom colors for certain color types requested by collada.
virtual irr::video::SColor getCustomColor(const irr::video::SMaterial & material, irr::scene::E_COLLADA_COLOR_SAMPLER cs) const;
//! Return the settings for transparence
virtual E_COLLADA_TRANSPARENT_FX getTransparentFx(const video::SMaterial& material) const;
virtual irr::scene::E_COLLADA_TRANSPARENT_FX getTransparentFx(const irr::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;
//! Transparency value for that material.
virtual irr::f32 getTransparency(const irr::video::SMaterial& material) const;
//! Reflectivity value for that material
virtual irr::f32 getReflectivity(const irr::video::SMaterial& material) const;
//! Return index of refraction for that material
virtual irr::f32 getIndexOfRefraction(const irr::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);
virtual irr::scene::IMesh* getMesh(irr::scene::ISceneNode * node);
};
@ -85,7 +95,8 @@ protected:
irr::core::stringw pathToURI(const irr::io::path& path) const;
inline bool isXmlNameStartChar(wchar_t c) const;
inline bool isXmlNameChar(wchar_t c) const;
s32 getTextureIdx(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs);
s32 getCheckedTextureIdx(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs);
video::SColor getColorMapping(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs, E_COLLADA_IRR_COLOR colType);
void writeAsset();
void makeMeshNames(irr::scene::ISceneNode * node);
void writeNodeMaterials(irr::scene::ISceneNode * node);
@ -98,8 +109,9 @@ protected:
void writeMeshGeometry(const irr::core::stringw& meshname, scene::IMesh* mesh);
void writeMeshInstanceGeometry(const irr::core::stringw& meshname, scene::IMesh* mesh);
void writeLibraryImages();
void writeColorFx(const irr::core::stringw& meshname, const video::SMaterial & material, const wchar_t * colorname, E_COLLADA_COLOR_SAMPLER cs, const wchar_t* attr1Name=0, const wchar_t* attr1Value=0);
void writeColorElement(const video::SColor & col);
bool writeTextureSampler(const irr::core::stringw& meshname, s32 textureIdx);
void writeTextureSampler(const irr::core::stringw& meshname, s32 textureIdx);
void writeFxElement(const irr::core::stringw& meshname, const video::SMaterial & material, E_COLLADA_TECHNIQUE_FX techFx);
void writeFloatElement(irr::f32 value);
void writeRotateElement(const irr::core::vector3df& axis, irr::f32 angle);