فهرست منبع

+ first version of OBJ exporter

git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@1056 67173fc5-114c-0410-ac8e-9d2fd5bffc1f
aramis_acg 14 سال پیش
والد
کامیت
c58480d608
6فایلهای تغییر یافته به همراه442 افزوده شده و 1 حذف شده
  1. 3 0
      code/CMakeLists.txt
  2. 6 1
      code/ColladaExporter.cpp
  3. 5 0
      code/Exporter.cpp
  4. 294 0
      code/ObjExporter.cpp
  5. 122 0
      code/ObjExporter.h
  6. 12 0
      workspaces/vc9/assimp.vcproj

+ 3 - 0
code/CMakeLists.txt

@@ -313,6 +313,9 @@ SET( Obj_SRCS
 	ObjFileParser.cpp
 	ObjFileParser.cpp
 	ObjFileParser.h
 	ObjFileParser.h
 	ObjTools.h
 	ObjTools.h
+	
+	ObjExporter.h
+	ObjExporter.cpp
 )
 )
 SOURCE_GROUP( Obj FILES ${Obj_SRCS})
 SOURCE_GROUP( Obj FILES ${Obj_SRCS})
 
 

+ 6 - 1
code/ColladaExporter.cpp

@@ -41,6 +41,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "AssimpPCH.h"
 #include "AssimpPCH.h"
 
 
 #ifndef ASSIMP_BUILD_NO_EXPORT
 #ifndef ASSIMP_BUILD_NO_EXPORT
+#ifndef ASSIMP_BUILD_NO_COLLADA_EXPORTER
 #include "ColladaExporter.h"
 #include "ColladaExporter.h"
 
 
 using namespace Assimp;
 using namespace Assimp;
@@ -69,10 +70,13 @@ 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)
 {
 {
+	// make sure that all formatting happens using the standard, C locale and not the user's current locale
+	mOutput.imbue( std::locale("C") );
+
 	mScene = pScene;
 	mScene = pScene;
 
 
 	// set up strings
 	// set up strings
-	endstr = "\n"; // std::endl is too complicated for me to insert here.
+	endstr = "\n"; 
 
 
 	// start writing
 	// start writing
 	WriteFile();
 	WriteFile();
@@ -366,4 +370,5 @@ void ColladaExporter::WriteNode( const aiNode* pNode)
 }
 }
 
 
 #endif
 #endif
+#endif
 
 

+ 5 - 0
code/Exporter.cpp

@@ -62,6 +62,7 @@ namespace Assimp {
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Exporter worker function prototypes. Should not be necessary to #ifndef them, it's just a prototype
 // Exporter worker function prototypes. Should not be necessary to #ifndef them, it's just a prototype
 void ExportSceneCollada(const char*,IOSystem*, const aiScene*);
 void ExportSceneCollada(const char*,IOSystem*, const aiScene*);
+void ExportSceneObj(const char*,IOSystem*, const aiScene*);
 void ExportScene3DS(const char*, IOSystem*, const aiScene*) {}
 void ExportScene3DS(const char*, IOSystem*, const aiScene*) {}
 
 
 /// Function pointer type of a Export worker function
 /// Function pointer type of a Export worker function
@@ -95,6 +96,10 @@ ExportFormatEntry gExporters[] =
 	ExportFormatEntry( "collada", "COLLADA - Digital Asset Exchange Schema", "dae", &ExportSceneCollada),
 	ExportFormatEntry( "collada", "COLLADA - Digital Asset Exchange Schema", "dae", &ExportSceneCollada),
 #endif
 #endif
 
 
+#ifndef ASSIMP_BUILD_NO_OBJ_EXPORTER
+	ExportFormatEntry( "obj", "Wavefront OBJ format", "obj", &ExportSceneObj),
+#endif
+
 #ifndef ASSIMP_BUILD_NO_3DS_EXPORTER
 #ifndef ASSIMP_BUILD_NO_3DS_EXPORTER
 	ExportFormatEntry( "3ds", "Autodesk 3DS (legacy format)", "3ds" , &ExportScene3DS),
 	ExportFormatEntry( "3ds", "Autodesk 3DS (legacy format)", "3ds" , &ExportScene3DS),
 #endif
 #endif

+ 294 - 0
code/ObjExporter.cpp

@@ -0,0 +1,294 @@
+/*
+Open Asset Import Library (ASSIMP)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2010, ASSIMP Development Team
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms, 
+with or without modification, are permitted provided that the 
+following conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of the ASSIMP team, nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission of the ASSIMP Development Team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+#include "AssimpPCH.h"
+
+#ifndef ASSIMP_BUILD_NO_EXPORT
+#ifndef ASSIMP_BUILD_NO_OBJ_EXPORTER
+
+#include "ObjExporter.h"
+#include "../include/aiVersion.h"
+
+using namespace Assimp;
+namespace Assimp	{
+
+// ------------------------------------------------------------------------------------------------
+// Worker function for exporting a scene to Wavefront OBJ. Prototyped and registered in Exporter.cpp
+void ExportSceneObj(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene)
+{
+	// invoke the exporter 
+	ObjExporter exporter(pFile, pScene);
+
+	// we're still here - export successfully completed. Write both the main OBJ file and the material script
+	{
+		boost::scoped_ptr<IOStream> outfile (pIOSystem->Open(pFile,"wt"));
+		outfile->Write( exporter.mOutput.str().c_str(), static_cast<size_t>(exporter.mOutput.tellp()),1);
+	}
+	{
+		boost::scoped_ptr<IOStream> outfile (pIOSystem->Open(exporter.GetMaterialLibFileName(),"wt"));
+		outfile->Write( exporter.mOutputMat.str().c_str(), static_cast<size_t>(exporter.mOutputMat.tellp()),1);
+	}
+}
+
+} // end of namespace Assimp
+
+
+// ------------------------------------------------------------------------------------------------
+ObjExporter :: ObjExporter(const char* _filename, const aiScene* pScene)
+: filename(_filename)
+, pScene(pScene)
+, endl("\n") 
+{
+	// make sure that all formatting happens using the standard, C locale and not the user's current locale
+	const std::locale& l = std::locale("C");
+	mOutput.imbue(l);
+	mOutputMat.imbue(l);
+
+	WriteGeometryFile();
+	WriteMaterialFile();
+}
+
+// ------------------------------------------------------------------------------------------------
+std::string ObjExporter :: GetMaterialLibName()
+{	
+	// within the Obj file, we use just the relative file name with the path stripped
+	const std::string& s = GetMaterialLibFileName();
+	std::string::size_type il = s.find_last_of("/\\");
+	if (il != std::string::npos) {
+		return s.substr(il + 1);
+	}
+
+	return s;
+}
+
+// ------------------------------------------------------------------------------------------------
+std::string ObjExporter :: GetMaterialLibFileName()
+{	
+	return filename + ".mtl";
+}
+
+// ------------------------------------------------------------------------------------------------
+void ObjExporter :: WriteHeader(std::ostringstream& out)
+{
+	out << "# File produced by Open Asset Import Library (http://www.assimp.sf.net)" << endl;
+	out << "# (assimp v" << aiGetVersionMajor() << '.' << aiGetVersionMinor() << '.' << aiGetVersionRevision() << ")" << endl  << endl;
+}
+
+// ------------------------------------------------------------------------------------------------
+std::string ObjExporter :: GetMaterialName(unsigned int index)
+{
+	const aiMaterial* const mat = pScene->mMaterials[index];
+	aiString s;
+	if(AI_SUCCESS == mat->Get(AI_MATKEY_NAME,s)) {
+		return std::string(s.data,s.length);
+	}
+
+	char number[ sizeof(unsigned int) * 3 + 1 ];
+	ASSIMP_itoa10(number,index);
+	return "$Material_" + std::string(number);
+}
+
+// ------------------------------------------------------------------------------------------------
+void ObjExporter :: WriteMaterialFile()
+{
+	WriteHeader(mOutputMat);
+
+	for(unsigned int i = 0; i < pScene->mNumMaterials; ++i) {
+		const aiMaterial* const mat = pScene->mMaterials[i];
+
+		int illum = 1;
+		mOutputMat << "newmtl " << GetMaterialName(i)  << endl;
+
+		aiColor4D c;
+		if(AI_SUCCESS == mat->Get(AI_MATKEY_COLOR_DIFFUSE,c)) {
+			mOutputMat << "kd " << c.r << " " << c.g << " " << c.b << endl;
+		}
+		if(AI_SUCCESS == mat->Get(AI_MATKEY_COLOR_AMBIENT,c)) {
+			mOutputMat << "ka " << c.r << " " << c.g << " " << c.b << endl;
+		}
+		if(AI_SUCCESS == mat->Get(AI_MATKEY_COLOR_SPECULAR,c)) {
+			mOutputMat << "ks " << c.r << " " << c.g << " " << c.b << endl;
+		}
+
+		float o;
+		if(AI_SUCCESS == mat->Get(AI_MATKEY_OPACITY,o)) {
+			mOutputMat << "d " << o << endl;
+		}
+
+		if(AI_SUCCESS == mat->Get(AI_MATKEY_SHININESS,o) && o) {
+			mOutputMat << "Ns " << o << endl;
+			illum = 2;
+		}
+
+		mOutputMat << "illum " << illum << endl;
+
+		aiString s;
+		if(AI_SUCCESS == mat->Get(AI_MATKEY_TEXTURE_DIFFUSE(0),s)) {
+			mOutputMat << "map_kd " << s.data << endl;
+		}
+		if(AI_SUCCESS == mat->Get(AI_MATKEY_TEXTURE_AMBIENT(0),s)) {
+			mOutputMat << "map_ka " << s.data << endl;
+		}
+		if(AI_SUCCESS == mat->Get(AI_MATKEY_TEXTURE_SPECULAR(0),s)) {
+			mOutputMat << "map_ks " << s.data << endl;
+		}
+		if(AI_SUCCESS == mat->Get(AI_MATKEY_TEXTURE_SHININESS(0),s)) {
+			mOutputMat << "map_ns " << s.data << endl;
+		}
+		if(AI_SUCCESS == mat->Get(AI_MATKEY_TEXTURE_HEIGHT(0),s) || AI_SUCCESS == mat->Get(AI_MATKEY_TEXTURE_NORMALS(0),s)) {
+			// implementations seem to vary here, so write both variants
+			mOutputMat << "bump " << s.data << endl;
+			mOutputMat << "map_bump " << s.data << endl;
+		}
+
+		mOutputMat << endl;
+	}
+}
+
+// ------------------------------------------------------------------------------------------------
+void ObjExporter :: WriteGeometryFile()
+{
+	WriteHeader(mOutput);
+	mOutput << "mtllib "  << GetMaterialLibName() << endl << endl;
+
+	// collect mesh geometry
+	aiMatrix4x4 mBase;
+	AddNode(pScene->mRootNode,mBase);
+
+	// write vertex positions
+	mOutput << "# " << vp.size() << " vertex positions" << endl;
+	BOOST_FOREACH(const aiVector3D& v, vp) {
+		mOutput << "v  " << v.x << " " << v.y << " " << v.z << endl;
+	}
+	mOutput << endl;
+
+	// write uv coordinates
+	mOutput << "# " << vt.size() << " UV coordinates" << endl;
+	BOOST_FOREACH(const aiVector3D& v, vt) {
+		mOutput << "vt " << v.x << " " << v.y << " " << v.z << endl;
+	}
+	mOutput << endl;
+
+	// write vertex normals
+	mOutput << "# " << vn.size() << " vertex normals" << endl;
+	BOOST_FOREACH(const aiVector3D& v, vn) {
+		mOutput << "vn " << v.x << " " << v.y << " " << v.z << endl;
+	}
+	mOutput << endl;
+
+	// now write all mesh instances
+	BOOST_FOREACH(const MeshInstance& m, meshes) {
+		mOutput << "# Mesh \'" << m.name << "\' with " << m.faces.size() << " faces" << endl;
+		mOutput << "g " << m.name << endl;
+		mOutput << "usemtl " << m.matname << endl;
+
+		BOOST_FOREACH(const Face& f, m.faces) {
+			mOutput << "f ";
+			BOOST_FOREACH(const FaceVertex& fv, f.indices) {
+				mOutput << " " << fv.vp << "/";
+				if (fv.vt) {
+					mOutput << fv.vt;
+				}
+				mOutput << "/";
+				if (fv.vn) {
+					mOutput << fv.vn;
+				}
+			}
+
+			mOutput << endl;
+		}
+		mOutput << endl;
+	}
+}
+
+// ------------------------------------------------------------------------------------------------
+void ObjExporter :: AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4x4& mat)
+{
+	meshes.push_back(MeshInstance());
+	MeshInstance& mesh = meshes.back();
+
+	mesh.name = std::string(name.data,name.length) + (m->mName.length ? "_"+std::string(m->mName.data,m->mName.length) : "");
+	mesh.matname = GetMaterialName(m->mMaterialIndex);
+
+	mesh.faces.resize(m->mNumFaces);
+	for(unsigned int i = 0; i < m->mNumFaces; ++i) {
+		const aiFace& f = m->mFaces[i];
+
+		Face& face = mesh.faces[i];
+		face.indices.resize(f.mNumIndices);
+
+		for(unsigned int a = 0; a < f.mNumIndices; ++a) {
+			const unsigned int idx = f.mIndices[a];
+
+			// XXX need a way to check if this is an unique vertex or if we had it already, 
+			// in which case we should instead reference the previous occurrence.
+			ai_assert(m->mVertices);
+			vp.push_back( mat * m->mVertices[idx] );
+			face.indices[a].vp = vp.size();
+
+			if (m->mNormals) {
+				vn.push_back( m->mNormals[idx] );
+			}
+			face.indices[a].vn = vn.size();
+
+			if (m->mTextureCoords[0]) {
+				vt.push_back( m->mTextureCoords[0][idx] );
+			}
+			face.indices[a].vt = vt.size();
+		}
+	}
+}
+
+// ------------------------------------------------------------------------------------------------
+void ObjExporter :: AddNode(const aiNode* nd, const aiMatrix4x4& mParent)
+{
+	const aiMatrix4x4& mAbs = mParent * nd->mTransformation;
+
+	for(unsigned int i = 0; i < nd->mNumMeshes; ++i) {
+		AddMesh(nd->mName, pScene->mMeshes[nd->mMeshes[i]],mAbs);
+	}
+
+	for(unsigned int i = 0; i < nd->mNumChildren; ++i) {
+		AddNode(nd->mChildren[i],mAbs);
+	}
+}
+
+#endif
+#endif

+ 122 - 0
code/ObjExporter.h

@@ -0,0 +1,122 @@
+/*
+Open Asset Import Library (ASSIMP)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2010, ASSIMP Development Team
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms, 
+with or without modification, are permitted provided that the 
+following conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of the ASSIMP team, nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission of the ASSIMP Development Team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file ColladaExporter.h
+ * Declares the exporter class to write a scene to a Collada file
+ */
+#ifndef AI_OBJEXPORTER_H_INC
+#define AI_OBJEXPORTER_H_INC
+
+#include <sstream>
+
+struct aiScene;
+struct aiNode;
+
+namespace Assimp	
+{
+
+// ------------------------------------------------------------------------------------------------
+/** Helper class to export a given scene to an OBJ file. */
+// ------------------------------------------------------------------------------------------------
+class ASSIMP_API ObjExporter
+{
+public:
+	/// Constructor for a specific scene to export
+	ObjExporter(const char* filename, const aiScene* pScene);
+
+public:
+
+	std::string GetMaterialLibName();
+	std::string GetMaterialLibFileName();
+	
+public:
+
+	/// public stringstreams to write all output into
+	std::ostringstream mOutput, mOutputMat;
+
+private:
+
+	// intermediate data structures
+	struct FaceVertex 
+	{
+		FaceVertex()
+			: vp(),vn(),vt() 
+		{
+		}
+
+		// one-based, 0 means: 'does not exist'
+		unsigned int vp,vn,vt;
+	};
+
+	struct Face {
+		std::vector<FaceVertex> indices;
+	};
+
+	struct MeshInstance {
+
+		std::string name, matname;
+		std::vector<Face> faces;
+	};
+
+	void WriteHeader(std::ostringstream& out);
+
+	void WriteMaterialFile();
+	void WriteGeometryFile();
+
+	std::string GetMaterialName(unsigned int index);
+
+	void AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4x4& mat);
+	void AddNode(const aiNode* nd, const aiMatrix4x4& mParent);
+
+private:
+
+	const std::string filename;
+	const aiScene* const pScene;
+
+	std::vector<aiVector3D> vp, vn, vt;
+	std::vector<MeshInstance> meshes;
+
+	// this endl() doesn't flush() the stream
+	const std::string endl;
+};
+
+}
+
+#endif

+ 12 - 0
workspaces/vc9/assimp.vcproj

@@ -4176,6 +4176,18 @@
 					Name="3ds"
 					Name="3ds"
 					>
 					>
 				</Filter>
 				</Filter>
+				<Filter
+					Name="obj"
+					>
+					<File
+						RelativePath="..\..\code\ObjExporter.cpp"
+						>
+					</File>
+					<File
+						RelativePath="..\..\code\ObjExporter.h"
+						>
+					</File>
+				</Filter>
 			</Filter>
 			</Filter>
 		</Filter>
 		</Filter>
 		<Filter
 		<Filter