In Collada: first preliminary support for export of embeded textures

pull/261/head
Léo Terziman 2013-12-05 17:54:12 +01:00
parent 8bbe14c052
commit 54e4c6b20b
2 changed files with 97 additions and 7 deletions

View File

@ -44,6 +44,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_COLLADA_EXPORTER #ifndef ASSIMP_BUILD_NO_COLLADA_EXPORTER
#include "ColladaExporter.h" #include "ColladaExporter.h"
#include "fast_atof.h"
#include "SceneCombiner.h" #include "SceneCombiner.h"
#include <ctime> #include <ctime>
@ -58,8 +59,24 @@ namespace Assimp
// Worker function for exporting a scene to Collada. Prototyped and registered in Exporter.cpp // Worker function for exporting a scene to Collada. Prototyped and registered in Exporter.cpp
void ExportSceneCollada(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene) void ExportSceneCollada(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene)
{ {
std::string path = "";
const char* end_path = strrchr(pFile, '/');
if(end_path != NULL) {
path = std::string(pFile, end_path + 1 - pFile);
} else {
// We need to test both types of folder separators because pIOSystem->getOsSeparator() is not reliable.
// Moreover, the path given by some applications is not even consistent with the OS specific type of separator.
end_path = strrchr(pFile, '\\');
if(end_path != NULL) {
path = std::string(pFile, end_path + 1 - pFile);
}
}
// invoke the exporter // invoke the exporter
ColladaExporter iDoTheExportThing( pScene); ColladaExporter iDoTheExportThing( pScene, pIOSystem, path);
// we're still here - export successfully completed. Write result to the given IOSYstem // we're still here - export successfully completed. Write result to the given IOSYstem
boost::scoped_ptr<IOStream> outfile (pIOSystem->Open(pFile,"wt")); boost::scoped_ptr<IOStream> outfile (pIOSystem->Open(pFile,"wt"));
@ -76,7 +93,7 @@ void ExportSceneCollada(const char* pFile,IOSystem* pIOSystem, const aiScene* pS
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Constructor for a specific scene to export // Constructor for a specific scene to export
ColladaExporter::ColladaExporter( const aiScene* pScene) ColladaExporter::ColladaExporter( const aiScene* pScene, IOSystem* pIOSystem, const std::string& path) : mIOSystem(pIOSystem), mPath(path)
{ {
// make sure that all formatting happens using the standard, C locale and not the user's current locale // make sure that all formatting happens using the standard, C locale and not the user's current locale
mOutput.imbue( std::locale("C") ); mOutput.imbue( std::locale("C") );
@ -110,6 +127,7 @@ void ColladaExporter::WriteFile()
mOutput << "<COLLADA xmlns=\"http://www.collada.org/2005/11/COLLADASchema\" version=\"1.4.1\">" << endstr; mOutput << "<COLLADA xmlns=\"http://www.collada.org/2005/11/COLLADASchema\" version=\"1.4.1\">" << endstr;
PushTag(); PushTag();
WriteTextures();
WriteHeader(); WriteHeader();
WriteMaterials(); WriteMaterials();
@ -161,7 +179,7 @@ void ColladaExporter::WriteHeader()
float scale = 1.0; float scale = 1.0;
if(std::abs(scaling.x - scaling.y) <= epsilon && std::abs(scaling.x - scaling.z) <= epsilon && std::abs(scaling.y - scaling.z) <= epsilon) { if(std::abs(scaling.x - scaling.y) <= epsilon && std::abs(scaling.x - scaling.z) <= epsilon && std::abs(scaling.y - scaling.z) <= epsilon) {
scale = scaling.x; scale = (float) ((((double) scaling.x) + ((double) scaling.y) + ((double) scaling.z)) / 3.0);
} else { } else {
add_root_node = true; add_root_node = true;
} }
@ -221,6 +239,41 @@ void ColladaExporter::WriteHeader()
mOutput << startstr << "</asset>" << endstr; mOutput << startstr << "</asset>" << endstr;
} }
// ------------------------------------------------------------------------------------------------
// Write the embedded textures
void ColladaExporter::WriteTextures() {
static const unsigned int buffer_size = 1024;
char str[buffer_size];
if(mScene->HasTextures()) {
for(unsigned int i = 0; i < mScene->mNumTextures; i++) {
// It would be great to be able to create a directory in portable standard C++, but it's not the case,
// so we just write the textures in the current directory.
aiTexture* texture = mScene->mTextures[i];
ASSIMP_itoa10(str, buffer_size, i);
std::string name = std::string("Texture_") + str + "." + ((const char*) texture->achFormatHint);
boost::scoped_ptr<IOStream> outfile(mIOSystem->Open(mPath + name, "wb"));
if(outfile == NULL) {
throw DeadlyExportError("could not open output texture file: " + mPath + name);
}
if(texture->mHeight == 0) {
outfile->Write((void*) texture->pcData, texture->mWidth, 1);
} else {
//TODO
}
outfile->Flush();
textures.insert(std::make_pair(i, name));
}
}
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Reads a single surface entry from the given material keys // 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) void ColladaExporter::ReadMaterialSurface( Surface& poSurface, const aiMaterial* pSrcMat, aiTextureType pTexture, const char* pKey, size_t pType, size_t pIndex)
@ -230,7 +283,33 @@ void ColladaExporter::ReadMaterialSurface( Surface& poSurface, const aiMaterial*
aiString texfile; aiString texfile;
unsigned int uvChannel = 0; unsigned int uvChannel = 0;
pSrcMat->GetTexture( pTexture, 0, &texfile, NULL, &uvChannel); pSrcMat->GetTexture( pTexture, 0, &texfile, NULL, &uvChannel);
poSurface.texture = texfile.C_Str();
std::string index_str(texfile.C_Str());
if(index_str.size() != 0 && index_str[0] == '*')
{
unsigned int index;
index_str = index_str.substr(1, std::string::npos);
try {
index = (unsigned int) strtoul10_64(index_str.c_str());
} catch(std::exception& error) {
throw DeadlyExportError(error.what());
}
std::map<unsigned int, std::string>::const_iterator name = textures.find(index);
if(name != textures.end()) {
poSurface.texture = name->second;
} else {
throw DeadlyExportError("could not find embedded texture at index " + index_str);
}
} else
{
poSurface.texture = texfile.C_Str();
}
poSurface.channel = uvChannel; poSurface.channel = uvChannel;
poSurface.exist = true; poSurface.exist = true;
} else } else

View File

@ -59,7 +59,7 @@ class ColladaExporter
{ {
public: public:
/// Constructor for a specific scene to export /// Constructor for a specific scene to export
ColladaExporter( const aiScene* pScene); ColladaExporter( const aiScene* pScene, IOSystem* pIOSystem, const std::string& path);
/// Destructor /// Destructor
virtual ~ColladaExporter(); virtual ~ColladaExporter();
@ -71,8 +71,11 @@ protected:
/// Writes the asset header /// Writes the asset header
void WriteHeader(); void WriteHeader();
/// Writes the material setup /// Writes the embedded textures
void WriteMaterials(); void WriteTextures();
/// Writes the material setup
void WriteMaterials();
/// Writes the geometry library /// Writes the geometry library
void WriteGeometryLibrary(); void WriteGeometryLibrary();
@ -104,6 +107,12 @@ public:
std::stringstream mOutput; std::stringstream mOutput;
protected: protected:
/// The IOSystem for output
IOSystem* mIOSystem;
/// Path of the directory where the scene will be exported
std::string mPath;
/// The scene to be written /// The scene to be written
const aiScene* mScene; const aiScene* mScene;
bool mSceneOwned; bool mSceneOwned;
@ -143,6 +152,8 @@ protected:
std::vector<Material> materials; std::vector<Material> materials;
std::map<unsigned int, std::string> textures;
protected: protected:
/// Dammit C++ - y u no compile two-pass? No I have to add all methods below the struct definitions /// 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 /// Reads a single surface entry from the given material keys