vrshoot
view libs/assimp/ObjExporter.cpp @ 0:b2f14e535253
initial commit
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sat, 01 Feb 2014 19:58:19 +0200 |
parents | |
children |
line source
1 /*
2 Open Asset Import Library (assimp)
3 ----------------------------------------------------------------------
5 Copyright (c) 2006-2012, assimp team
6 All rights reserved.
8 Redistribution and use of this software in source and binary forms,
9 with or without modification, are permitted provided that the
10 following conditions are met:
12 * Redistributions of source code must retain the above
13 copyright notice, this list of conditions and the
14 following disclaimer.
16 * Redistributions in binary form must reproduce the above
17 copyright notice, this list of conditions and the
18 following disclaimer in the documentation and/or other
19 materials provided with the distribution.
21 * Neither the name of the assimp team, nor the names of its
22 contributors may be used to endorse or promote products
23 derived from this software without specific prior
24 written permission of the assimp team.
26 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
29 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
36 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 ----------------------------------------------------------------------
39 */
41 #include "AssimpPCH.h"
43 #ifndef ASSIMP_BUILD_NO_EXPORT
44 #ifndef ASSIMP_BUILD_NO_OBJ_EXPORTER
46 #include "ObjExporter.h"
47 #include "assimp/version.h"
49 using namespace Assimp;
50 namespace Assimp {
52 // ------------------------------------------------------------------------------------------------
53 // Worker function for exporting a scene to Wavefront OBJ. Prototyped and registered in Exporter.cpp
54 void ExportSceneObj(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene)
55 {
56 // invoke the exporter
57 ObjExporter exporter(pFile, pScene);
59 // we're still here - export successfully completed. Write both the main OBJ file and the material script
60 {
61 boost::scoped_ptr<IOStream> outfile (pIOSystem->Open(pFile,"wt"));
62 if(outfile == NULL) {
63 throw DeadlyExportError("could not open output .obj file: " + std::string(pFile));
64 }
65 outfile->Write( exporter.mOutput.str().c_str(), static_cast<size_t>(exporter.mOutput.tellp()),1);
66 }
67 {
68 boost::scoped_ptr<IOStream> outfile (pIOSystem->Open(exporter.GetMaterialLibFileName(),"wt"));
69 if(outfile == NULL) {
70 throw DeadlyExportError("could not open output .mtl file: " + std::string(exporter.GetMaterialLibFileName()));
71 }
72 outfile->Write( exporter.mOutputMat.str().c_str(), static_cast<size_t>(exporter.mOutputMat.tellp()),1);
73 }
74 }
76 } // end of namespace Assimp
79 // ------------------------------------------------------------------------------------------------
80 ObjExporter :: ObjExporter(const char* _filename, const aiScene* pScene)
81 : filename(_filename)
82 , pScene(pScene)
83 , endl("\n")
84 {
85 // make sure that all formatting happens using the standard, C locale and not the user's current locale
86 const std::locale& l = std::locale("C");
87 mOutput.imbue(l);
88 mOutputMat.imbue(l);
90 WriteGeometryFile();
91 WriteMaterialFile();
92 }
94 // ------------------------------------------------------------------------------------------------
95 std::string ObjExporter :: GetMaterialLibName()
96 {
97 // within the Obj file, we use just the relative file name with the path stripped
98 const std::string& s = GetMaterialLibFileName();
99 std::string::size_type il = s.find_last_of("/\\");
100 if (il != std::string::npos) {
101 return s.substr(il + 1);
102 }
104 return s;
105 }
107 // ------------------------------------------------------------------------------------------------
108 std::string ObjExporter :: GetMaterialLibFileName()
109 {
110 return filename + ".mtl";
111 }
113 // ------------------------------------------------------------------------------------------------
114 void ObjExporter :: WriteHeader(std::ostringstream& out)
115 {
116 out << "# File produced by Open Asset Import Library (http://www.assimp.sf.net)" << endl;
117 out << "# (assimp v" << aiGetVersionMajor() << '.' << aiGetVersionMinor() << '.' << aiGetVersionRevision() << ")" << endl << endl;
118 }
120 // ------------------------------------------------------------------------------------------------
121 std::string ObjExporter :: GetMaterialName(unsigned int index)
122 {
123 const aiMaterial* const mat = pScene->mMaterials[index];
124 aiString s;
125 if(AI_SUCCESS == mat->Get(AI_MATKEY_NAME,s)) {
126 return std::string(s.data,s.length);
127 }
129 char number[ sizeof(unsigned int) * 3 + 1 ];
130 ASSIMP_itoa10(number,index);
131 return "$Material_" + std::string(number);
132 }
134 // ------------------------------------------------------------------------------------------------
135 void ObjExporter :: WriteMaterialFile()
136 {
137 WriteHeader(mOutputMat);
139 for(unsigned int i = 0; i < pScene->mNumMaterials; ++i) {
140 const aiMaterial* const mat = pScene->mMaterials[i];
142 int illum = 1;
143 mOutputMat << "newmtl " << GetMaterialName(i) << endl;
145 aiColor4D c;
146 if(AI_SUCCESS == mat->Get(AI_MATKEY_COLOR_DIFFUSE,c)) {
147 mOutputMat << "kd " << c.r << " " << c.g << " " << c.b << endl;
148 }
149 if(AI_SUCCESS == mat->Get(AI_MATKEY_COLOR_AMBIENT,c)) {
150 mOutputMat << "ka " << c.r << " " << c.g << " " << c.b << endl;
151 }
152 if(AI_SUCCESS == mat->Get(AI_MATKEY_COLOR_SPECULAR,c)) {
153 mOutputMat << "ks " << c.r << " " << c.g << " " << c.b << endl;
154 }
156 float o;
157 if(AI_SUCCESS == mat->Get(AI_MATKEY_OPACITY,o)) {
158 mOutputMat << "d " << o << endl;
159 }
161 if(AI_SUCCESS == mat->Get(AI_MATKEY_SHININESS,o) && o) {
162 mOutputMat << "Ns " << o << endl;
163 illum = 2;
164 }
166 mOutputMat << "illum " << illum << endl;
168 aiString s;
169 if(AI_SUCCESS == mat->Get(AI_MATKEY_TEXTURE_DIFFUSE(0),s)) {
170 mOutputMat << "map_kd " << s.data << endl;
171 }
172 if(AI_SUCCESS == mat->Get(AI_MATKEY_TEXTURE_AMBIENT(0),s)) {
173 mOutputMat << "map_ka " << s.data << endl;
174 }
175 if(AI_SUCCESS == mat->Get(AI_MATKEY_TEXTURE_SPECULAR(0),s)) {
176 mOutputMat << "map_ks " << s.data << endl;
177 }
178 if(AI_SUCCESS == mat->Get(AI_MATKEY_TEXTURE_SHININESS(0),s)) {
179 mOutputMat << "map_ns " << s.data << endl;
180 }
181 if(AI_SUCCESS == mat->Get(AI_MATKEY_TEXTURE_HEIGHT(0),s) || AI_SUCCESS == mat->Get(AI_MATKEY_TEXTURE_NORMALS(0),s)) {
182 // implementations seem to vary here, so write both variants
183 mOutputMat << "bump " << s.data << endl;
184 mOutputMat << "map_bump " << s.data << endl;
185 }
187 mOutputMat << endl;
188 }
189 }
191 // ------------------------------------------------------------------------------------------------
192 void ObjExporter :: WriteGeometryFile()
193 {
194 WriteHeader(mOutput);
195 mOutput << "mtllib " << GetMaterialLibName() << endl << endl;
197 // collect mesh geometry
198 aiMatrix4x4 mBase;
199 AddNode(pScene->mRootNode,mBase);
201 // write vertex positions
202 mOutput << "# " << vp.size() << " vertex positions" << endl;
203 BOOST_FOREACH(const aiVector3D& v, vp) {
204 mOutput << "v " << v.x << " " << v.y << " " << v.z << endl;
205 }
206 mOutput << endl;
208 // write uv coordinates
209 mOutput << "# " << vt.size() << " UV coordinates" << endl;
210 BOOST_FOREACH(const aiVector3D& v, vt) {
211 mOutput << "vt " << v.x << " " << v.y << " " << v.z << endl;
212 }
213 mOutput << endl;
215 // write vertex normals
216 mOutput << "# " << vn.size() << " vertex normals" << endl;
217 BOOST_FOREACH(const aiVector3D& v, vn) {
218 mOutput << "vn " << v.x << " " << v.y << " " << v.z << endl;
219 }
220 mOutput << endl;
222 // now write all mesh instances
223 BOOST_FOREACH(const MeshInstance& m, meshes) {
224 mOutput << "# Mesh \'" << m.name << "\' with " << m.faces.size() << " faces" << endl;
225 mOutput << "g " << m.name << endl;
226 mOutput << "usemtl " << m.matname << endl;
228 BOOST_FOREACH(const Face& f, m.faces) {
229 mOutput << f.kind << ' ';
230 BOOST_FOREACH(const FaceVertex& fv, f.indices) {
231 mOutput << ' ' << fv.vp;
233 if (f.kind != 'p') {
234 if (fv.vt || f.kind == 'f') {
235 mOutput << '/';
236 }
237 if (fv.vt) {
238 mOutput << fv.vt;
239 }
240 if (f.kind == 'f') {
241 mOutput << '/';
242 if (fv.vn) {
243 mOutput << fv.vn;
244 }
245 }
246 }
247 }
249 mOutput << endl;
250 }
251 mOutput << endl;
252 }
253 }
255 // ------------------------------------------------------------------------------------------------
256 void ObjExporter :: AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4x4& mat)
257 {
258 meshes.push_back(MeshInstance());
259 MeshInstance& mesh = meshes.back();
261 mesh.name = std::string(name.data,name.length) + (m->mName.length ? "_"+std::string(m->mName.data,m->mName.length) : "");
262 mesh.matname = GetMaterialName(m->mMaterialIndex);
264 mesh.faces.resize(m->mNumFaces);
265 for(unsigned int i = 0; i < m->mNumFaces; ++i) {
266 const aiFace& f = m->mFaces[i];
268 Face& face = mesh.faces[i];
269 switch (f.mNumIndices) {
270 case 1:
271 face.kind = 'p';
272 break;
273 case 2:
274 face.kind = 'l';
275 break;
276 default:
277 face.kind = 'f';
278 }
279 face.indices.resize(f.mNumIndices);
281 for(unsigned int a = 0; a < f.mNumIndices; ++a) {
282 const unsigned int idx = f.mIndices[a];
284 // XXX need a way to check if this is an unique vertex or if we had it already,
285 // in which case we should instead reference the previous occurrence.
286 ai_assert(m->mVertices);
287 vp.push_back( mat * m->mVertices[idx] );
288 face.indices[a].vp = vp.size();
290 if (m->mNormals) {
291 vn.push_back( m->mNormals[idx] );
292 }
293 face.indices[a].vn = vn.size();
295 if (m->mTextureCoords[0]) {
296 vt.push_back( m->mTextureCoords[0][idx] );
297 }
298 face.indices[a].vt = vt.size();
299 }
300 }
301 }
303 // ------------------------------------------------------------------------------------------------
304 void ObjExporter :: AddNode(const aiNode* nd, const aiMatrix4x4& mParent)
305 {
306 const aiMatrix4x4& mAbs = mParent * nd->mTransformation;
308 for(unsigned int i = 0; i < nd->mNumMeshes; ++i) {
309 AddMesh(nd->mName, pScene->mMeshes[nd->mMeshes[i]],mAbs);
310 }
312 for(unsigned int i = 0; i < nd->mNumChildren; ++i) {
313 AddNode(nd->mChildren[i],mAbs);
314 }
315 }
317 #endif
318 #endif