- ColladaFileLoader respects now namespaces in materials when searching for texture-images.

- ColladaMshWriter does now write texture-data as well.

git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@3840 dfc29bdd-3216-0410-991c-e03cc46cb475
master
cutealien 2011-06-09 16:55:15 +00:00
parent 7b5fa07671
commit 596ae90bdb
4 changed files with 280 additions and 68 deletions

View File

@ -1272,7 +1272,7 @@ void CColladaFileLoader::readTexture(io::IXMLReaderUTF8* reader)
if (input)
{
const core::stringc imageName = input->Source;
texture.Texture = getTextureFromImage(imageName);
texture.Texture = getTextureFromImage(imageName, NULL);
}
}
}
@ -1370,6 +1370,7 @@ void CColladaFileLoader::readEffect(io::IXMLReaderUTF8* reader, SColladaEffect *
{
Effects.push_back(SColladaEffect());
effect = &Effects.getLast();
effect->Parameters = new io::CAttributes();
effect->Id = readId(reader);
effect->Transparency = 1.f;
effect->Mat.Lighting=true;
@ -1388,7 +1389,7 @@ void CColladaFileLoader::readEffect(io::IXMLReaderUTF8* reader, SColladaEffect *
readEffect(reader,effect);
else
if (newParamName == reader->getNodeName())
readParameter(reader);
readParameter(reader, effect->Parameters);
else
// these are the actual materials inside technique
if (constantNode == reader->getNodeName() ||
@ -1538,10 +1539,10 @@ void CColladaFileLoader::readEffect(io::IXMLReaderUTF8* reader, SColladaEffect *
effect->Mat.MaterialType = irr::video::EMT_TRANSPARENT_VERTEX_ALPHA;
effect->Mat.ZWriteEnable = false;
}
effect->Mat.setFlag(video::EMF_TEXTURE_WRAP, !Parameters.getAttributeAsBool("wrap_s"));
effect->Mat.setFlag(video::EMF_BILINEAR_FILTER, Parameters.getAttributeAsBool("bilinear"));
effect->Mat.setFlag(video::EMF_TRILINEAR_FILTER, Parameters.getAttributeAsBool("trilinear"));
effect->Mat.setFlag(video::EMF_ANISOTROPIC_FILTER, Parameters.getAttributeAsBool("anisotropic"));
effect->Mat.setFlag(video::EMF_TEXTURE_WRAP, !effect->Parameters->getAttributeAsBool("wrap_s"));
effect->Mat.setFlag(video::EMF_BILINEAR_FILTER, effect->Parameters->getAttributeAsBool("bilinear"));
effect->Mat.setFlag(video::EMF_TRILINEAR_FILTER, effect->Parameters->getAttributeAsBool("trilinear"));
effect->Mat.setFlag(video::EMF_ANISOTROPIC_FILTER, effect->Parameters->getAttributeAsBool("anisotropic"));
}
@ -1569,7 +1570,7 @@ const SColladaMaterial* CColladaFileLoader::findMaterial(const core::stringc& ma
// found the effect, instantiate by copying into the material
Materials[mat].Mat = Effects[effect].Mat;
if (Effects[effect].Textures.size())
Materials[mat].Mat.setTexture(0, getTextureFromImage(Effects[effect].Textures[0]));
Materials[mat].Mat.setTexture(0, getTextureFromImage(Effects[effect].Textures[0], &(Effects[effect])));
Materials[mat].Transparency = Effects[effect].Transparency;
// and indicate the material is instantiated by removing the effect ref
Materials[mat].InstanceEffectId = "";
@ -2494,7 +2495,7 @@ void CColladaFileLoader::readColladaInputs(io::IXMLReaderUTF8* reader, const cor
} // end while reader->read();
}
//! parses all collada parameters inside an element and stores them in Parameters
//! parses all collada parameters inside an element and stores them in ColladaParameters
void CColladaFileLoader::readColladaParameters(io::IXMLReaderUTF8* reader,
const core::stringc& parentName)
{
@ -2719,6 +2720,8 @@ void CColladaFileLoader::clearData()
Inputs.clear();
// clear all effects
for ( u32 i=0; i<Effects.size(); ++i )
Effects[i].Parameters->drop();
Effects.clear();
// clear all the materials to bind
@ -2751,7 +2754,7 @@ core::stringc CColladaFileLoader::readId(io::IXMLReaderUTF8* reader)
//! create an Irrlicht texture from the reference
video::ITexture* CColladaFileLoader::getTextureFromImage(core::stringc uri)
video::ITexture* CColladaFileLoader::getTextureFromImage(core::stringc uri, SColladaEffect * effect)
{
#ifdef COLLADA_READER_DEBUG
os::Printer::log("COLLADA searching texture", uri);
@ -2792,9 +2795,9 @@ video::ITexture* CColladaFileLoader::getTextureFromImage(core::stringc uri)
break;
}
}
if (Parameters.getAttributeType(uri.c_str())==io::EAT_STRING)
if (effect && effect->Parameters->getAttributeType(uri.c_str())==io::EAT_STRING)
{
uri = Parameters.getAttributeAsString(uri.c_str());
uri = effect->Parameters->getAttributeAsString(uri.c_str());
#ifdef COLLADA_READER_DEBUG
os::Printer::log("COLLADA now searching texture", uri.c_str());
#endif
@ -2807,12 +2810,15 @@ video::ITexture* CColladaFileLoader::getTextureFromImage(core::stringc uri)
//! read a parameter and value
void CColladaFileLoader::readParameter(io::IXMLReaderUTF8* reader)
void CColladaFileLoader::readParameter(io::IXMLReaderUTF8* reader, io::IAttributes* parameters)
{
#ifdef COLLADA_READER_DEBUG
os::Printer::log("COLLADA reading parameter");
#endif
if ( !parameters )
return;
const core::stringc name = reader->getAttributeValue("sid");
if (!reader->isEmptyElement())
{
@ -2823,7 +2829,7 @@ void CColladaFileLoader::readParameter(io::IXMLReaderUTF8* reader)
if (floatNodeName == reader->getNodeName())
{
const f32 f = readFloatNode(reader);
Parameters.addFloat(name.c_str(), f);
parameters->addFloat(name.c_str(), f);
}
else
if (float2NodeName == reader->getNodeName())
@ -2837,14 +2843,14 @@ void CColladaFileLoader::readParameter(io::IXMLReaderUTF8* reader)
{
f32 f[3];
readFloatsInsideElement(reader, f, 3);
Parameters.addVector3d(name.c_str(), core::vector3df(f[0],f[1],f[2]));
parameters->addVector3d(name.c_str(), core::vector3df(f[0],f[1],f[2]));
}
else
if ((initFromName == reader->getNodeName()) ||
(sourceSectionName == reader->getNodeName()))
{
reader->read();
Parameters.addString(name.c_str(), reader->getNodeData());
parameters->addString(name.c_str(), reader->getNodeData());
}
else
if (wrapsName == reader->getNodeName())
@ -2852,7 +2858,7 @@ void CColladaFileLoader::readParameter(io::IXMLReaderUTF8* reader)
reader->read();
const core::stringc val = reader->getNodeData();
if (val == "WRAP")
Parameters.addBool("wrap_s", true);
parameters->addBool("wrap_s", true);
}
else
if (wraptName == reader->getNodeName())
@ -2860,7 +2866,7 @@ void CColladaFileLoader::readParameter(io::IXMLReaderUTF8* reader)
reader->read();
const core::stringc val = reader->getNodeData();
if (val == "WRAP")
Parameters.addBool("wrap_t", true);
parameters->addBool("wrap_t", true);
}
else
if (minfilterName == reader->getNodeName())
@ -2868,10 +2874,10 @@ void CColladaFileLoader::readParameter(io::IXMLReaderUTF8* reader)
reader->read();
const core::stringc val = reader->getNodeData();
if (val == "LINEAR_MIPMAP_LINEAR")
Parameters.addBool("trilinear", true);
parameters->addBool("trilinear", true);
else
if (val == "LINEAR_MIPMAP_NEAREST")
Parameters.addBool("bilinear", true);
parameters->addBool("bilinear", true);
}
else
if (magfilterName == reader->getNodeName())
@ -2880,14 +2886,14 @@ void CColladaFileLoader::readParameter(io::IXMLReaderUTF8* reader)
const core::stringc val = reader->getNodeData();
if (val != "LINEAR")
{
Parameters.addBool("bilinear", false);
Parameters.addBool("trilinear", false);
parameters->addBool("bilinear", false);
parameters->addBool("trilinear", false);
}
}
else
if (mipfilterName == reader->getNodeName())
{
Parameters.addBool("anisotropic", true);
parameters->addBool("anisotropic", true);
}
}
else

View File

@ -135,6 +135,8 @@ struct SColladaEffect
f32 Transparency;
core::array<core::stringc> Textures;
video::SMaterial Mat;
// TODO: Parameters looks somewhat lazy workaround, I think we should really read all parameters correct.
io::IAttributes * Parameters;
inline bool operator< (const SColladaEffect & other) const
{
@ -298,7 +300,7 @@ private:
//! clears all loaded data
void clearData();
//! parses all collada parameters inside an element and stores them in Parameters
//! parses all collada parameters inside an element and stores them in ColladaParameters
void readColladaParameters(io::IXMLReaderUTF8* reader, const core::stringc& parentName);
//! returns a collada parameter or none if not found
@ -332,10 +334,10 @@ private:
void readBindMaterialSection(io::IXMLReaderUTF8* reader, const core::stringc & id);
//! create an Irrlicht texture from the SColladaImage
video::ITexture* getTextureFromImage(core::stringc uri);
video::ITexture* getTextureFromImage(core::stringc uri, SColladaEffect * effect);
//! read a parameter and value
void readParameter(io::IXMLReaderUTF8* reader);
void readParameter(io::IXMLReaderUTF8* reader, io::IAttributes* parameters);
scene::ISceneManager* SceneManager;
io::IFileSystem* FileSystem;
@ -360,7 +362,6 @@ private:
core::map<core::stringc,u32> MaterialsToBind;
//! Array of buffers for each material binding
core::array< core::array<irr::scene::IMeshBuffer*> > MeshesToBind;
io::CAttributes Parameters;
bool CreateInstances;
};

View File

@ -112,6 +112,7 @@ bool CColladaMeshWriter::writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32
Writer->writeClosingTag(L"asset");
Writer->writeLineBreak();
// write all materials
Writer->writeElement(L"library_materials", false);
@ -142,7 +143,8 @@ bool CColladaMeshWriter::writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32
Writer->writeElement(L"library_effects", false);
Writer->writeLineBreak();
LibraryImages.clear();
for (i=0; i<mesh->getMeshBufferCount(); ++i)
{
core::stringw strMat = "mat";
@ -155,55 +157,182 @@ bool CColladaMeshWriter::writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32
Writer->writeLineBreak();
Writer->writeElement(L"profile_COMMON", false);
Writer->writeLineBreak();
video::SMaterial & material = mesh->getMeshBuffer(i)->getMaterial();
// write texture surfaces and samplers and buffer all used imagess
int numTextures = 0;
for ( int t=0; t<4; ++t )
{
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();
// <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);
Writer->writeText(irr::core::stringw(layer.Texture->getName().getInternalName()).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>
Writer->writeElement(L"source", false);
Writer->writeText(texSurface.c_str());
Writer->writeClosingTag(L"source");
Writer->writeLineBreak();
// <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->writeElement(L"blinn", false);
Writer->writeLineBreak();
// write all interesting material parameters as parameter
{
// write all interesting material parameters
// attributes must be written in fixed order
Writer->writeElement(L"emission", false);
Writer->writeLineBreak();
if ( numTextures < 1 )
writeColorElement(material.EmissiveColor);
else
{
// <texture texture="sampler" texcoord="texCoord"/>
Writer->writeElement(L"texture", true, L"texture", L"tex0-sampler", L"texcoord", L"mesh-TexCoord0" );
Writer->writeLineBreak();
}
Writer->writeClosingTag(L"emission");
Writer->writeLineBreak();
io::IAttributes* attributes = VideoDriver->createAttributesFromMaterial(
mesh->getMeshBuffer(i)->getMaterial());
Writer->writeElement(L"ambient", false);
Writer->writeLineBreak();
if ( numTextures < 2 )
writeColorElement(material.AmbientColor);
else
{
// <texture texture="sampler" texcoord="texCoord"/>
Writer->writeElement(L"texture", true, L"texture", L"tex1-sampler", L"texcoord", L"mesh-TexCoord0" );
Writer->writeLineBreak();
}
Writer->writeClosingTag(L"ambient");
Writer->writeLineBreak();
Writer->writeElement(L"diffuse", false);
Writer->writeLineBreak();
if ( numTextures < 3 )
writeColorElement(material.DiffuseColor);
else
{
// <texture texture="sampler" texcoord="texCoord"/>
Writer->writeElement(L"texture", true, L"texture", L"tex2-sampler", L"texcoord", L"mesh-TexCoord0" );
Writer->writeLineBreak();
}
Writer->writeClosingTag(L"diffuse");
Writer->writeLineBreak();
Writer->writeElement(L"specular", false);
Writer->writeLineBreak();
if ( numTextures < 4 )
writeColorElement(material.SpecularColor);
else
{
// <texture texture="sampler" texcoord="texCoord"/>
Writer->writeElement(L"texture", true, L"texture", L"tex3-sampler", L"texcoord", L"mesh-TexCoord0" );
Writer->writeLineBreak();
}
Writer->writeClosingTag(L"specular");
Writer->writeLineBreak();
// attributes must be written in fixed order
core::stringc str;
s32 attridx = attributes->findAttribute("Emissive");
if ( attridx >= 0 )
{
writeColorAttribute(L"emission", attributes, attridx);
}
attridx = attributes->findAttribute("Ambient");
if ( attridx >= 0 )
{
writeColorAttribute(L"ambient", attributes, attridx);
}
attridx = attributes->findAttribute("Diffuse");
if ( attridx >= 0 )
{
writeColorAttribute(L"diffuse", attributes, attridx);
}
attridx = attributes->findAttribute("Specular");
if ( attridx >= 0 )
{
writeColorAttribute(L"specular", attributes, attridx);
}
attridx = attributes->findAttribute("Shininess");
if ( attridx >= 0 )
{
Writer->writeElement(L"shininess", false);
Writer->writeLineBreak();
Writer->writeElement(L"float", false);
Writer->writeText(core::stringw(attributes->getAttributeAsString(attridx).c_str()).c_str());
Writer->writeText(core::stringw(material.Shininess).c_str());
Writer->writeClosingTag(L"float");
Writer->writeLineBreak();
Writer->writeClosingTag(L"shininess");
Writer->writeLineBreak();
}
attributes->drop();
Writer->writeClosingTag(L"blinn");
Writer->writeLineBreak();
Writer->writeClosingTag(L"technique");
@ -217,6 +346,32 @@ bool CColladaMeshWriter::writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32
Writer->writeClosingTag(L"library_effects");
Writer->writeLineBreak();
// images
if ( !LibraryImages.empty() )
{
Writer->writeElement(L"library_images", false);
Writer->writeLineBreak();
for ( irr::u32 i=0; i<LibraryImages.size(); ++i )
{
//<image name="rose01">
Writer->writeElement(L"image", false, L"name", irr::core::stringw(LibraryImages[i]->getName().getInternalName()).c_str());
Writer->writeLineBreak();
// <init_from>../flowers/rose01.jpg</init_from>
Writer->writeElement(L"init_from", false);
// TODO: path might need some conversion into collada URI-format to replace whitespaces etc.
Writer->writeText(irr::core::stringw(LibraryImages[i]->getName().getPath()).c_str());
Writer->writeClosingTag(L"init_from");
Writer->writeLineBreak();
// </image>
Writer->writeClosingTag(L"image");
Writer->writeLineBreak();
}
Writer->writeClosingTag(L"library_images");
Writer->writeLineBreak();
}
// write mesh
Writer->writeElement(L"library_geometries", false);
@ -737,23 +892,68 @@ inline irr::core::stringw CColladaMeshWriter::toString(const irr::video::SColorf
return str;
}
void CColladaMeshWriter::writeColorAttribute(wchar_t * parentTag, io::IAttributes* attributes, s32 attridx)
inline irr::core::stringw CColladaMeshWriter::toString(const irr::video::ECOLOR_FORMAT format) const
{
Writer->writeElement(parentTag, false);
Writer->writeLineBreak();
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"");
}
}
inline 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");
}
inline 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");
}
void CColladaMeshWriter::writeColorElement(const video::SColor & col)
{
Writer->writeElement(L"color", false);
irr::core::stringw str( toString(attributes->getAttributeAsColorf(attridx)) );
irr::core::stringw str( toString(video::SColorf(col)) );
Writer->writeText(str.c_str());
Writer->writeClosingTag(L"color");
Writer->writeLineBreak();
Writer->writeClosingTag(parentTag);
Writer->writeLineBreak();
}
} // end namespace
} // end namespace

View File

@ -42,7 +42,11 @@ protected:
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::video::SColorf& colorf) const;
inline void writeColorAttribute(wchar_t * parentTag, io::IAttributes* attributes, s32 attridx);
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 minTexfilterToString(bool bilinear, bool trilinear) const;
inline irr::core::stringw magTexfilterToString(bool bilinear, bool trilinear) const;
inline void writeColorElement(const video::SColor & col);
struct SComponentGlobalStartPos
{
@ -68,6 +72,7 @@ protected:
io::IFileSystem* FileSystem;
video::IVideoDriver* VideoDriver;
io::IXMLWriter* Writer;
core::array<video::ITexture*> LibraryImages;
};