Ver Fonte

In Collada: first preliminary support for export of embeded textures

Léo Terziman há 11 anos atrás
pai
commit
54e4c6b20b
2 ficheiros alterados com 97 adições e 7 exclusões
  1. 83 4
      code/ColladaExporter.cpp
  2. 14 3
      code/ColladaExporter.h

+ 83 - 4
code/ColladaExporter.cpp

@@ -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

+ 14 - 3
code/ColladaExporter.h

@@ -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
-  void WriteMaterials();
+	/// Writes the embedded textures
+	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