diff --git a/code/ColladaExporter.cpp b/code/ColladaExporter.cpp
index f5658bb1d..1d8b04d42 100644
--- a/code/ColladaExporter.cpp
+++ b/code/ColladaExporter.cpp
@@ -94,6 +94,7 @@ void ColladaExporter::WriteFile()
WriteHeader();
+ WriteMaterials();
WriteGeometryLibrary();
WriteSceneLibrary();
@@ -127,6 +128,155 @@ void ColladaExporter::WriteHeader()
mOutput << startstr << "" << endstr;
}
+// ------------------------------------------------------------------------------------------------
+// Reads a single surface entry from the given material keys
+void ColladaExporter::ReadMaterialSurface( Surface& poSurface, const aiMaterial* pSrcMat, aiTextureType pTexture, const char* pKey, size_t pType, size_t pIndex)
+{
+ if( pSrcMat->GetTextureCount( pTexture) > 0 )
+ {
+ aiString texfile;
+ unsigned int uvChannel = 0;
+ pSrcMat->GetTexture( pTexture, 0, &texfile, nullptr, &uvChannel);
+ poSurface.texture = texfile.C_Str();
+ poSurface.channel = uvChannel;
+ } else
+ {
+ if( pKey )
+ pSrcMat->Get( pKey, pType, pIndex, poSurface.color);
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+// Writes an image entry for the given surface
+void ColladaExporter::WriteImageEntry( const Surface& pSurface, const std::string& pNameAdd)
+{
+ if( !pSurface.texture.empty() )
+ {
+ mOutput << startstr << "" << endstr;
+ PushTag();
+ mOutput << startstr << "" << pSurface.texture << "" << endstr;
+ PopTag();
+ mOutput << startstr << "" << endstr;
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+// Writes a color-or-texture entry into an effect definition
+void ColladaExporter::WriteTextureColorEntry( const Surface& pSurface, const std::string& pTypeName, const std::string& pImageName)
+{
+ mOutput << startstr << "<" << pTypeName << ">" << endstr;
+ PushTag();
+ if( pSurface.texture.empty() )
+ {
+ mOutput << startstr << "" << pSurface.color.r << " " << pSurface.color.g << " " << pSurface.color.b << " " << pSurface.color.a << "" << endstr;
+ } else
+ {
+ mOutput << startstr << "" << endstr;
+ }
+ PopTag();
+ mOutput << startstr << "" << pTypeName << ">" << endstr;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Writes the material setup
+void ColladaExporter::WriteMaterials()
+{
+ materials.resize( mScene->mNumMaterials);
+
+ /// collect all materials from the scene
+ for( size_t a = 0; a < mScene->mNumMaterials; ++a )
+ {
+ const aiMaterial* mat = mScene->mMaterials[a];
+
+ aiString name;
+ if( mat->Get( AI_MATKEY_NAME, name) != aiReturn_SUCCESS )
+ name = "mat";
+ materials[a].name = boost::lexical_cast (a) + name.C_Str();
+
+ ReadMaterialSurface( materials[a].ambient, mat, aiTextureType_AMBIENT, AI_MATKEY_COLOR_AMBIENT);
+ ReadMaterialSurface( materials[a].diffuse, mat, aiTextureType_DIFFUSE, AI_MATKEY_COLOR_DIFFUSE);
+ ReadMaterialSurface( materials[a].specular, mat, aiTextureType_SPECULAR, AI_MATKEY_COLOR_SPECULAR);
+ ReadMaterialSurface( materials[a].emissive, mat, aiTextureType_EMISSIVE, AI_MATKEY_COLOR_EMISSIVE);
+ ReadMaterialSurface( materials[a].reflective, mat, aiTextureType_REFLECTION, AI_MATKEY_COLOR_REFLECTIVE);
+ ReadMaterialSurface( materials[a].normal, mat, aiTextureType_NORMALS, nullptr, 0, 0);
+
+ mat->Get( AI_MATKEY_SHININESS, materials[a].shininess);
+ }
+
+ // output textures if present
+ mOutput << startstr << "" << endstr;
+ PushTag();
+ for( auto it = materials.cbegin(); it != materials.cend(); ++it )
+ {
+ const Material& mat = *it;
+ WriteImageEntry( mat.ambient, mat.name + "_ambient_image");
+ WriteImageEntry( mat.diffuse, mat.name + "_diffuse_image");
+ WriteImageEntry( mat.specular, mat.name + "_specular_image");
+ WriteImageEntry( mat.emissive, mat.name + "_emissive_image");
+ WriteImageEntry( mat.reflective, mat.name + "_reflective_image");
+ WriteImageEntry( mat.normal, mat.name + "_normal_image");
+ }
+ PopTag();
+ mOutput << startstr << "" << endstr;
+
+ // output effects - those are the actual carriers of information
+ mOutput << startstr << "" << endstr;
+ PushTag();
+ for( auto it = materials.cbegin(); it != materials.cend(); ++it )
+ {
+ const Material& mat = *it;
+ // this is so ridiculous it must be right
+ mOutput << startstr << "" << endstr;
+ PushTag();
+ mOutput << startstr << "" << endstr;
+ PushTag();
+ mOutput << startstr << "" << endstr;
+ PushTag();
+ mOutput << startstr << "" << endstr;
+ PushTag();
+
+ WriteTextureColorEntry( mat.ambient, "ambient", mat.name + "_ambient_image");
+ WriteTextureColorEntry( mat.diffuse, "diffuse", mat.name + "_diffuse_image");
+ WriteTextureColorEntry( mat.specular, "specular", mat.name + "_specular_image");
+ WriteTextureColorEntry( mat.emissive, "emission", mat.name + "_emissive_image");
+ WriteTextureColorEntry( mat.reflective, "reflective", mat.name + "_reflective_image");
+ if( !mat.normal.texture.empty() )
+ WriteTextureColorEntry( mat.normal, "bump", mat.name + "_normal_image");
+
+ mOutput << startstr << "" << endstr;
+ PushTag();
+ mOutput << startstr << "" << mat.shininess << "" << endstr;
+ PopTag();
+ mOutput << startstr << "" << endstr;
+
+ PopTag();
+ mOutput << startstr << "" << endstr;
+ PopTag();
+ mOutput << startstr << "" << endstr;
+ PopTag();
+ mOutput << startstr << "" << endstr;
+ PopTag();
+ mOutput << startstr << "" << endstr;
+ }
+ PopTag();
+ mOutput << startstr << "" << endstr;
+
+ // write materials - they're just effect references
+ mOutput << startstr << "" << endstr;
+ PushTag();
+ for( auto it = materials.cbegin(); it != materials.cend(); ++it )
+ {
+ const Material& mat = *it;
+ mOutput << startstr << "" << endstr;
+ PushTag();
+ mOutput << startstr << "" << endstr;
+ PopTag();
+ mOutput << startstr << "" << endstr;
+ }
+ PopTag();
+ mOutput << startstr << "" << endstr;
+}
+
// ------------------------------------------------------------------------------------------------
// Writes the geometry library
void ColladaExporter::WriteGeometryLibrary()
@@ -199,7 +349,7 @@ void ColladaExporter::WriteGeometry( size_t pIndex)
mOutput << startstr << "" << endstr;
// write face setup
- mOutput << startstr << "mNumFaces << "\" material=\"tellme\">" << endstr;
+ mOutput << startstr << "mNumFaces << "\" material=\"theresonlyone\">" << endstr;
PushTag();
mOutput << startstr << "" << endstr;
@@ -356,8 +506,16 @@ void ColladaExporter::WriteNode( const aiNode* pNode)
// const aiMesh* mesh = mScene->mMeshes[pNode->mMeshes[a]];
mOutput << startstr << "mMeshes[a]) << "\">" << endstr;
PushTag();
-
+ mOutput << startstr << "" << endstr;
+ PushTag();
+ mOutput << startstr << "" << endstr;
+ PushTag();
+ mOutput << startstr << "mMeshes[pNode->mMeshes[a]]->mMaterialIndex].name << "\" />" << endstr;
PopTag();
+ mOutput << startstr << "" << endstr;
+ PopTag();
+ mOutput << startstr << "" << endstr;
+ PopTag();
mOutput << startstr << "" << endstr;
}
diff --git a/code/ColladaExporter.h b/code/ColladaExporter.h
index c4fd2f6f2..cfe5a8db7 100644
--- a/code/ColladaExporter.h
+++ b/code/ColladaExporter.h
@@ -68,6 +68,9 @@ protected:
/// Writes the asset header
void WriteHeader();
+ /// Writes the material setup
+ void WriteMaterials();
+
/// Writes the geometry library
void WriteGeometryLibrary();
@@ -105,6 +108,36 @@ protected:
std::string startstr;
/// current line end string for simple stream insertion
std::string endstr;
+
+ // pair of color and texture - texture precedences color
+ struct Surface
+ {
+ aiColor4D color;
+ std::string texture;
+ size_t channel;
+ Surface() { channel = 0; }
+ };
+
+ // summarize a material in an convinient way.
+ struct Material
+ {
+ std::string name;
+ Surface ambient, diffuse, specular, emissive, reflective, normal;
+ float shininess; /// specular exponent
+
+ Material() { shininess = 16.0f; }
+ };
+
+ std::vector materials;
+
+protected:
+ /// Dammit C++ - y u no compile two-pass? No I have to add all methods below the struct definitions
+ /// Reads a single surface entry from the given material keys
+ void ReadMaterialSurface( Surface& poSurface, const aiMaterial* pSrcMat, aiTextureType pTexture, const char* pKey, size_t pType, size_t pIndex);
+ /// Writes an image entry for the given surface
+ void WriteImageEntry( const Surface& pSurface, const std::string& pNameAdd);
+ /// Writes a color-or-texture entry into an effect definition
+ void WriteTextureColorEntry( const Surface& pSurface, const std::string& pTypeName, const std::string& pImageName);
};
}