1 | /* |
2 | Open Asset Import Library (assimp) |
3 | ---------------------------------------------------------------------- |
4 | |
5 | Copyright (c) 2006-2017, assimp team |
6 | |
7 | All rights reserved. |
8 | |
9 | Redistribution and use of this software in source and binary forms, |
10 | with or without modification, are permitted provided that the |
11 | following conditions are met: |
12 | |
13 | * Redistributions of source code must retain the above |
14 | copyright notice, this list of conditions and the |
15 | following disclaimer. |
16 | |
17 | * Redistributions in binary form must reproduce the above |
18 | copyright notice, this list of conditions and the |
19 | following disclaimer in the documentation and/or other |
20 | materials provided with the distribution. |
21 | |
22 | * Neither the name of the assimp team, nor the names of its |
23 | contributors may be used to endorse or promote products |
24 | derived from this software without specific prior |
25 | written permission of the assimp team. |
26 | |
27 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
28 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
29 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
30 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
31 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
32 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
33 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
34 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
35 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
36 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
37 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
38 | |
39 | @author: Richard Steffen, 2014 |
40 | ---------------------------------------------------------------------- |
41 | */ |
42 | |
43 | |
44 | #ifndef ASSIMP_BUILD_NO_EXPORT |
45 | #ifndef ASSIMP_BUILD_NO_X_EXPORTER |
46 | |
47 | #include "XFileExporter.h" |
48 | #include "ConvertToLHProcess.h" |
49 | #include "Bitmap.h" |
50 | #include "BaseImporter.h" |
51 | #include "fast_atof.h" |
52 | #include <assimp/SceneCombiner.h> |
53 | #include <assimp/DefaultIOSystem.h> |
54 | #include <ctime> |
55 | #include <set> |
56 | #include <memory> |
57 | #include "Exceptional.h" |
58 | #include <assimp/IOSystem.hpp> |
59 | #include <assimp/scene.h> |
60 | #include <assimp/light.h> |
61 | |
62 | using namespace Assimp; |
63 | |
64 | namespace Assimp |
65 | { |
66 | |
67 | // ------------------------------------------------------------------------------------------------ |
68 | // Worker function for exporting a scene to Collada. Prototyped and registered in Exporter.cpp |
69 | void ExportSceneXFile(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties) |
70 | { |
71 | std::string path = DefaultIOSystem::absolutePath(std::string(pFile)); |
72 | std::string file = DefaultIOSystem::completeBaseName(std::string(pFile)); |
73 | |
74 | // create/copy Properties |
75 | ExportProperties props(*pProperties); |
76 | |
77 | // set standard properties if not set |
78 | if (!props.HasPropertyBool(AI_CONFIG_EXPORT_XFILE_64BIT)) props.SetPropertyBool(AI_CONFIG_EXPORT_XFILE_64BIT, false); |
79 | |
80 | // invoke the exporter |
81 | XFileExporter iDoTheExportThing( pScene, pIOSystem, path, file, &props); |
82 | |
83 | if (iDoTheExportThing.mOutput.fail()) { |
84 | throw DeadlyExportError("output data creation failed. Most likely the file became too large: " + std::string(pFile)); |
85 | } |
86 | |
87 | // we're still here - export successfully completed. Write result to the given IOSYstem |
88 | std::unique_ptr<IOStream> outfile (pIOSystem->Open(pFile,"wt" )); |
89 | if(outfile == NULL) { |
90 | throw DeadlyExportError("could not open output .x file: " + std::string(pFile)); |
91 | } |
92 | |
93 | // XXX maybe use a small wrapper around IOStream that behaves like std::stringstream in order to avoid the extra copy. |
94 | outfile->Write( iDoTheExportThing.mOutput.str().c_str(), static_cast<size_t>(iDoTheExportThing.mOutput.tellp()),1); |
95 | } |
96 | |
97 | } // end of namespace Assimp |
98 | |
99 | |
100 | // ------------------------------------------------------------------------------------------------ |
101 | // Constructor for a specific scene to export |
102 | XFileExporter::XFileExporter(const aiScene* pScene, IOSystem* pIOSystem, const std::string& path, const std::string& file, const ExportProperties* pProperties) |
103 | : mProperties(pProperties), |
104 | mIOSystem(pIOSystem), |
105 | mPath(path), |
106 | mFile(file), |
107 | mScene(pScene), |
108 | mSceneOwned(false), |
109 | endstr("\n" ) |
110 | { |
111 | // make sure that all formatting happens using the standard, C locale and not the user's current locale |
112 | mOutput.imbue( std::locale("C" ) ); |
113 | mOutput.precision(16); |
114 | |
115 | // start writing |
116 | WriteFile(); |
117 | } |
118 | |
119 | // ------------------------------------------------------------------------------------------------ |
120 | // Destructor |
121 | XFileExporter::~XFileExporter() |
122 | { |
123 | if(mSceneOwned) { |
124 | delete mScene; |
125 | } |
126 | } |
127 | |
128 | // ------------------------------------------------------------------------------------------------ |
129 | // Starts writing the contents |
130 | void XFileExporter::WriteFile() |
131 | { |
132 | // note, that all realnumber values must be comma separated in x files |
133 | mOutput.setf(std::ios::fixed); |
134 | mOutput.precision(16); // precission for double |
135 | |
136 | // entry of writing the file |
137 | WriteHeader(); |
138 | |
139 | mOutput << startstr << "Frame DXCC_ROOT {" << endstr; |
140 | PushTag(); |
141 | |
142 | aiMatrix4x4 I; // identity |
143 | WriteFrameTransform(I); |
144 | |
145 | WriteNode(mScene->mRootNode); |
146 | PopTag(); |
147 | |
148 | mOutput << startstr << "}" << endstr; |
149 | |
150 | } |
151 | |
152 | // ------------------------------------------------------------------------------------------------ |
153 | // Writes the asset header |
154 | void XFileExporter::() |
155 | { |
156 | if (mProperties->GetPropertyBool(AI_CONFIG_EXPORT_XFILE_64BIT) == true) |
157 | mOutput << startstr << "xof 0303txt 0064" << endstr; |
158 | else |
159 | mOutput << startstr << "xof 0303txt 0032" << endstr; |
160 | mOutput << endstr; |
161 | mOutput << startstr << "template Frame {" << endstr; |
162 | PushTag(); |
163 | mOutput << startstr << "<3d82ab46-62da-11cf-ab39-0020af71e433>" << endstr; |
164 | mOutput << startstr << "[...]" << endstr; |
165 | PopTag(); |
166 | mOutput << startstr << "}" << endstr; |
167 | mOutput << endstr; |
168 | mOutput << startstr << "template Matrix4x4 {" << endstr; |
169 | PushTag(); |
170 | mOutput << startstr << "<f6f23f45-7686-11cf-8f52-0040333594a3>" << endstr; |
171 | mOutput << startstr << "array FLOAT matrix[16];" << endstr; |
172 | PopTag(); |
173 | mOutput << startstr << "}" << endstr; |
174 | mOutput << endstr; |
175 | mOutput << startstr << "template FrameTransformMatrix {" << endstr; |
176 | PushTag(); |
177 | mOutput << startstr << "<f6f23f41-7686-11cf-8f52-0040333594a3>" << endstr; |
178 | mOutput << startstr << "Matrix4x4 frameMatrix;" << endstr; |
179 | PopTag(); |
180 | mOutput << startstr << "}" << endstr; |
181 | mOutput << endstr; |
182 | mOutput << startstr << "template Vector {" << endstr; |
183 | PushTag(); |
184 | mOutput << startstr << "<3d82ab5e-62da-11cf-ab39-0020af71e433>" << endstr; |
185 | mOutput << startstr << "FLOAT x;" << endstr; |
186 | mOutput << startstr << "FLOAT y;" << endstr; |
187 | mOutput << startstr << "FLOAT z;" << endstr; |
188 | PopTag(); |
189 | mOutput << startstr << "}" << endstr; |
190 | mOutput << endstr; |
191 | mOutput << startstr << "template MeshFace {" << endstr; |
192 | PushTag(); |
193 | mOutput << startstr << "<3d82ab5f-62da-11cf-ab39-0020af71e433>" << endstr; |
194 | mOutput << startstr << "DWORD nFaceVertexIndices;" << endstr; |
195 | mOutput << startstr << "array DWORD faceVertexIndices[nFaceVertexIndices];" << endstr; |
196 | PopTag(); |
197 | mOutput << startstr << "}" << endstr; |
198 | mOutput << endstr; |
199 | mOutput << startstr << "template Mesh {" << endstr; |
200 | PushTag(); |
201 | mOutput << startstr << "<3d82ab44-62da-11cf-ab39-0020af71e433>" << endstr; |
202 | mOutput << startstr << "DWORD nVertices;" << endstr; |
203 | mOutput << startstr << "array Vector vertices[nVertices];" << endstr; |
204 | mOutput << startstr << "DWORD nFaces;" << endstr; |
205 | mOutput << startstr << "array MeshFace faces[nFaces];" << endstr; |
206 | mOutput << startstr << "[...]" << endstr; |
207 | PopTag(); |
208 | mOutput << startstr << "}" << endstr; |
209 | mOutput << endstr; |
210 | mOutput << startstr << "template MeshNormals {" << endstr; |
211 | PushTag(); |
212 | mOutput << startstr << "<f6f23f43-7686-11cf-8f52-0040333594a3>" << endstr; |
213 | mOutput << startstr << "DWORD nNormals;" << endstr; |
214 | mOutput << startstr << "array Vector normals[nNormals];" << endstr; |
215 | mOutput << startstr << "DWORD nFaceNormals;" << endstr; |
216 | mOutput << startstr << "array MeshFace faceNormals[nFaceNormals];" << endstr; |
217 | PopTag(); |
218 | mOutput << startstr << "}" << endstr; |
219 | mOutput << endstr; |
220 | mOutput << startstr << "template Coords2d {" << endstr; |
221 | PushTag(); |
222 | mOutput << startstr << "<f6f23f44-7686-11cf-8f52-0040333594a3>" << endstr; |
223 | mOutput << startstr << "FLOAT u;" << endstr; |
224 | mOutput << startstr << "FLOAT v;" << endstr; |
225 | PopTag(); |
226 | mOutput << startstr << "}" << endstr; |
227 | mOutput << endstr; |
228 | mOutput << startstr << "template MeshTextureCoords {" << endstr; |
229 | PushTag(); |
230 | mOutput << startstr << "<f6f23f40-7686-11cf-8f52-0040333594a3>" << endstr; |
231 | mOutput << startstr << "DWORD nTextureCoords;" << endstr; |
232 | mOutput << startstr << "array Coords2d textureCoords[nTextureCoords];" << endstr; |
233 | PopTag(); |
234 | mOutput << startstr << "}" << endstr; |
235 | mOutput << endstr; |
236 | mOutput << startstr << "template ColorRGBA {" << endstr; |
237 | PushTag(); |
238 | mOutput << startstr << "<35ff44e0-6c7c-11cf-8f52-0040333594a3>" << endstr; |
239 | mOutput << startstr << "FLOAT red;" << endstr; |
240 | mOutput << startstr << "FLOAT green;" << endstr; |
241 | mOutput << startstr << "FLOAT blue;" << endstr; |
242 | mOutput << startstr << "FLOAT alpha;" << endstr; |
243 | PopTag(); |
244 | mOutput << startstr << "}" << endstr; |
245 | mOutput << endstr; |
246 | mOutput << startstr << "template IndexedColor {" << endstr; |
247 | PushTag(); |
248 | mOutput << startstr << "<1630b820-7842-11cf-8f52-0040333594a3>" << endstr; |
249 | mOutput << startstr << "DWORD index;" << endstr; |
250 | mOutput << startstr << "ColorRGBA indexColor;" << endstr; |
251 | PopTag(); |
252 | mOutput << startstr << "}" << endstr; |
253 | mOutput << endstr; |
254 | mOutput << startstr << "template MeshVertexColors {" << endstr; |
255 | PushTag(); |
256 | mOutput << startstr << "<1630b821-7842-11cf-8f52-0040333594a3>" << endstr; |
257 | mOutput << startstr << "DWORD nVertexColors;" << endstr; |
258 | mOutput << startstr << "array IndexedColor vertexColors[nVertexColors];" << endstr; |
259 | PopTag(); |
260 | mOutput << startstr << "}" << endstr; |
261 | mOutput << endstr; |
262 | mOutput << startstr << "template VertexElement {" << endstr; |
263 | PushTag(); |
264 | mOutput << startstr << "<f752461c-1e23-48f6-b9f8-8350850f336f>" << endstr; |
265 | mOutput << startstr << "DWORD Type;" << endstr; |
266 | mOutput << startstr << "DWORD Method;" << endstr; |
267 | mOutput << startstr << "DWORD Usage;" << endstr; |
268 | mOutput << startstr << "DWORD UsageIndex;" << endstr; |
269 | PopTag(); |
270 | mOutput << startstr << "}" << endstr; |
271 | mOutput << endstr; |
272 | mOutput << startstr << "template DeclData {" << endstr; |
273 | PushTag(); |
274 | mOutput << startstr << "<bf22e553-292c-4781-9fea-62bd554bdd93>" << endstr; |
275 | mOutput << startstr << "DWORD nElements;" << endstr; |
276 | mOutput << startstr << "array VertexElement Elements[nElements];" << endstr; |
277 | mOutput << startstr << "DWORD nDWords;" << endstr; |
278 | mOutput << startstr << "array DWORD data[nDWords];" << endstr; |
279 | PopTag(); |
280 | mOutput << startstr << "}" << endstr; |
281 | mOutput << endstr; |
282 | } |
283 | |
284 | |
285 | // Writes the material setup |
286 | void XFileExporter::WriteFrameTransform(aiMatrix4x4& m) |
287 | { |
288 | mOutput << startstr << "FrameTransformMatrix {" << endstr << " " ; |
289 | PushTag(); |
290 | mOutput << startstr << m.a1 << ", " << m.b1 << ", " << m.c1 << ", " << m.d1 << "," << endstr; |
291 | mOutput << startstr << m.a2 << ", " << m.b2 << ", " << m.c2 << ", " << m.d2 << "," << endstr; |
292 | mOutput << startstr << m.a3 << ", " << m.b3 << ", " << m.c3 << ", " << m.d3 << "," << endstr; |
293 | mOutput << startstr << m.a4 << ", " << m.b4 << ", " << m.c4 << ", " << m.d4 << ";;" << endstr; |
294 | PopTag(); |
295 | mOutput << startstr << "}" << endstr << endstr; |
296 | } |
297 | |
298 | |
299 | // ------------------------------------------------------------------------------------------------ |
300 | // Recursively writes the given node |
301 | void XFileExporter::WriteNode( aiNode* pNode) |
302 | { |
303 | if (pNode->mName.length==0) |
304 | { |
305 | std::stringstream ss; |
306 | ss << "Node_" << pNode; |
307 | pNode->mName.Set(ss.str()); |
308 | } |
309 | mOutput << startstr << "Frame " << toXFileString(pNode->mName) << " {" << endstr; |
310 | |
311 | PushTag(); |
312 | |
313 | aiMatrix4x4 m = pNode->mTransformation; |
314 | |
315 | WriteFrameTransform(m); |
316 | |
317 | for (size_t i = 0; i < pNode->mNumMeshes; ++i) |
318 | WriteMesh(mScene->mMeshes[pNode->mMeshes[i]]); |
319 | |
320 | // recursive call the Nodes |
321 | for (size_t i = 0; i < pNode->mNumChildren; ++i) |
322 | WriteNode(pNode->mChildren[i]); |
323 | |
324 | PopTag(); |
325 | |
326 | mOutput << startstr << "}" << endstr << endstr; |
327 | } |
328 | |
329 | void XFileExporter::WriteMesh(aiMesh* mesh) |
330 | { |
331 | mOutput << startstr << "Mesh " << toXFileString(mesh->mName) << "_mShape" << " {" << endstr; |
332 | |
333 | PushTag(); |
334 | |
335 | // write all the vertices |
336 | mOutput << startstr << mesh->mNumVertices << ";" << endstr; |
337 | for (size_t a = 0; a < mesh->mNumVertices; a++) |
338 | { |
339 | aiVector3D &v = mesh->mVertices[a]; |
340 | mOutput << startstr << v[0] << ";" << v[1] << ";" << v[2] << ";" ; |
341 | if (a < mesh->mNumVertices - 1) |
342 | mOutput << "," << endstr; |
343 | else |
344 | mOutput << ";" << endstr; |
345 | } |
346 | |
347 | // write all the faces |
348 | mOutput << startstr << mesh->mNumFaces << ";" << endstr; |
349 | for( size_t a = 0; a < mesh->mNumFaces; ++a ) |
350 | { |
351 | const aiFace& face = mesh->mFaces[a]; |
352 | mOutput << startstr << face.mNumIndices << ";" ; |
353 | // must be counter clockwise triangle |
354 | //for(int b = face.mNumIndices - 1; b >= 0 ; --b) |
355 | for(size_t b = 0; b < face.mNumIndices ; ++b) |
356 | { |
357 | mOutput << face.mIndices[b]; |
358 | //if (b > 0) |
359 | if (b<face.mNumIndices-1) |
360 | mOutput << "," ; |
361 | else |
362 | mOutput << ";" ; |
363 | } |
364 | |
365 | if (a < mesh->mNumFaces - 1) |
366 | mOutput << "," << endstr; |
367 | else |
368 | mOutput << ";" << endstr; |
369 | } |
370 | |
371 | mOutput << endstr; |
372 | |
373 | if (mesh->HasTextureCoords(0)) |
374 | { |
375 | const aiMaterial* mat = mScene->mMaterials[mesh->mMaterialIndex]; |
376 | aiString relpath; |
377 | mat->Get(_AI_MATKEY_TEXTURE_BASE, aiTextureType_DIFFUSE, 0, relpath); |
378 | |
379 | mOutput << startstr << "MeshMaterialList {" << endstr; |
380 | PushTag(); |
381 | mOutput << startstr << "1;" << endstr; // number of materials |
382 | mOutput << startstr << mesh->mNumFaces << ";" << endstr; // number of faces |
383 | mOutput << startstr; |
384 | for( size_t a = 0; a < mesh->mNumFaces; ++a ) |
385 | { |
386 | mOutput << "0" ; // the material index |
387 | if (a < mesh->mNumFaces - 1) |
388 | mOutput << ", " ; |
389 | else |
390 | mOutput << ";" << endstr; |
391 | } |
392 | mOutput << startstr << "Material {" << endstr; |
393 | PushTag(); |
394 | mOutput << startstr << "1.0; 1.0; 1.0; 1.000000;;" << endstr; |
395 | mOutput << startstr << "1.000000;" << endstr; // power |
396 | mOutput << startstr << "0.000000; 0.000000; 0.000000;;" << endstr; // specularity |
397 | mOutput << startstr << "0.000000; 0.000000; 0.000000;;" << endstr; // emission |
398 | mOutput << startstr << "TextureFilename { \"" ; |
399 | |
400 | writePath(relpath); |
401 | |
402 | mOutput << "\"; }" << endstr; |
403 | PopTag(); |
404 | mOutput << startstr << "}" << endstr; |
405 | PopTag(); |
406 | mOutput << startstr << "}" << endstr; |
407 | } |
408 | |
409 | // write normals (every vertex has one) |
410 | if (mesh->HasNormals()) |
411 | { |
412 | mOutput << endstr << startstr << "MeshNormals {" << endstr; |
413 | mOutput << startstr << mesh->mNumVertices << ";" << endstr; |
414 | for (size_t a = 0; a < mesh->mNumVertices; a++) |
415 | { |
416 | aiVector3D &v = mesh->mNormals[a]; |
417 | // because we have a LHS and also changed wth winding, we need to invert the normals again |
418 | mOutput << startstr << -v[0] << ";" << -v[1] << ";" << -v[2] << ";" ; |
419 | if (a < mesh->mNumVertices - 1) |
420 | mOutput << "," << endstr; |
421 | else |
422 | mOutput << ";" << endstr; |
423 | } |
424 | |
425 | mOutput << startstr << mesh->mNumFaces << ";" << endstr; |
426 | for (size_t a = 0; a < mesh->mNumFaces; a++) |
427 | { |
428 | const aiFace& face = mesh->mFaces[a]; |
429 | mOutput << startstr << face.mNumIndices << ";" ; |
430 | |
431 | //for(int b = face.mNumIndices-1; b >= 0 ; --b) |
432 | for(size_t b = 0; b < face.mNumIndices ; ++b) |
433 | { |
434 | mOutput << face.mIndices[b]; |
435 | //if (b > 0) |
436 | if (b<face.mNumIndices-1) |
437 | mOutput << "," ; |
438 | else |
439 | mOutput << ";" ; |
440 | } |
441 | |
442 | if (a < mesh->mNumFaces-1) |
443 | mOutput << "," << endstr; |
444 | else |
445 | mOutput << ";" << endstr; |
446 | } |
447 | mOutput << startstr << "}" << endstr; |
448 | } |
449 | |
450 | // write texture UVs if available |
451 | if (mesh->HasTextureCoords(0)) |
452 | { |
453 | mOutput << endstr << startstr << "MeshTextureCoords {" << endstr; |
454 | mOutput << startstr << mesh->mNumVertices << ";" << endstr; |
455 | for (size_t a = 0; a < mesh->mNumVertices; a++) |
456 | //for (int a = (int)mesh->mNumVertices-1; a >=0 ; a--) |
457 | { |
458 | aiVector3D& uv = mesh->mTextureCoords[0][a]; // uv of first uv layer for the vertex |
459 | mOutput << startstr << uv.x << ";" << uv.y; |
460 | if (a < mesh->mNumVertices-1) |
461 | //if (a >0 ) |
462 | mOutput << ";," << endstr; |
463 | else |
464 | mOutput << ";;" << endstr; |
465 | } |
466 | mOutput << startstr << "}" << endstr; |
467 | } |
468 | |
469 | // write color channel if available |
470 | if (mesh->HasVertexColors(0)) |
471 | { |
472 | mOutput << endstr << startstr << "MeshVertexColors {" << endstr; |
473 | mOutput << startstr << mesh->mNumVertices << ";" << endstr; |
474 | for (size_t a = 0; a < mesh->mNumVertices; a++) |
475 | { |
476 | aiColor4D& mColors = mesh->mColors[0][a]; // color of first vertex color set for the vertex |
477 | mOutput << startstr << a << ";" << mColors.r << ";" << mColors.g << ";" << mColors.b << ";" << mColors.a << ";;" ; |
478 | if (a < mesh->mNumVertices-1) |
479 | mOutput << "," << endstr; |
480 | else |
481 | mOutput << ";" << endstr; |
482 | } |
483 | mOutput << startstr << "}" << endstr; |
484 | } |
485 | /* |
486 | else |
487 | { |
488 | mOutput << endstr << startstr << "MeshVertexColors {" << endstr; |
489 | mOutput << startstr << mesh->mNumVertices << ";" << endstr; |
490 | for (size_t a = 0; a < mesh->mNumVertices; a++) |
491 | { |
492 | aiColor4D* mColors = mesh->mColors[a]; |
493 | mOutput << startstr << a << ";0.500000;0.000000;0.000000;0.500000;;"; |
494 | if (a < mesh->mNumVertices-1) |
495 | mOutput << "," << endstr; |
496 | else |
497 | mOutput << ";" << endstr; |
498 | } |
499 | mOutput << startstr << "}" << endstr; |
500 | } |
501 | */ |
502 | PopTag(); |
503 | mOutput << startstr << "}" << endstr << endstr; |
504 | |
505 | } |
506 | |
507 | std::string XFileExporter::toXFileString(aiString &name) |
508 | { |
509 | std::string pref = "" ; // node name prefix to prevent unexpected start of string |
510 | std::string str = pref + std::string(name.C_Str()); |
511 | for (int i=0; i < (int) str.length(); ++i) |
512 | { |
513 | if ((str[i] >= '0' && str[i] <= '9') || // 0-9 |
514 | (str[i] >= 'A' && str[i] <= 'Z') || // A-Z |
515 | (str[i] >= 'a' && str[i] <= 'z')) // a-z |
516 | continue; |
517 | str[i] = '_'; |
518 | } |
519 | return str; |
520 | } |
521 | |
522 | void XFileExporter::writePath(const aiString &path) |
523 | { |
524 | std::string str = std::string(path.C_Str()); |
525 | BaseImporter::ConvertUTF8toISO8859_1(str); |
526 | |
527 | while( str.find( "\\\\" ) != std::string::npos) |
528 | str.replace( str.find( "\\\\" ), 2, "\\" ); |
529 | |
530 | while( str.find( "\\" ) != std::string::npos) |
531 | str.replace( str.find( "\\" ), 1, "/" ); |
532 | |
533 | mOutput << str; |
534 | |
535 | } |
536 | |
537 | #endif |
538 | #endif |
539 | |