rev |
line source |
nuclear@0
|
1 /*
|
nuclear@0
|
2 ---------------------------------------------------------------------------
|
nuclear@0
|
3 Open Asset Import Library (assimp)
|
nuclear@0
|
4 ---------------------------------------------------------------------------
|
nuclear@0
|
5
|
nuclear@0
|
6 Copyright (c) 2006-2012, assimp team
|
nuclear@0
|
7
|
nuclear@0
|
8 All rights reserved.
|
nuclear@0
|
9
|
nuclear@0
|
10 Redistribution and use of this software in source and binary forms,
|
nuclear@0
|
11 with or without modification, are permitted provided that the following
|
nuclear@0
|
12 conditions are met:
|
nuclear@0
|
13
|
nuclear@0
|
14 * Redistributions of source code must retain the above
|
nuclear@0
|
15 copyright notice, this list of conditions and the
|
nuclear@0
|
16 following disclaimer.
|
nuclear@0
|
17
|
nuclear@0
|
18 * Redistributions in binary form must reproduce the above
|
nuclear@0
|
19 copyright notice, this list of conditions and the
|
nuclear@0
|
20 following disclaimer in the documentation and/or other
|
nuclear@0
|
21 materials provided with the distribution.
|
nuclear@0
|
22
|
nuclear@0
|
23 * Neither the name of the assimp team, nor the names of its
|
nuclear@0
|
24 contributors may be used to endorse or promote products
|
nuclear@0
|
25 derived from this software without specific prior
|
nuclear@0
|
26 written permission of the assimp team.
|
nuclear@0
|
27
|
nuclear@0
|
28 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
nuclear@0
|
29 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
nuclear@0
|
30 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
nuclear@0
|
31 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
nuclear@0
|
32 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
nuclear@0
|
33 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
nuclear@0
|
34 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
nuclear@0
|
35 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
nuclear@0
|
36 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
nuclear@0
|
37 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
nuclear@0
|
38 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
nuclear@0
|
39 ---------------------------------------------------------------------------
|
nuclear@0
|
40 */
|
nuclear@0
|
41
|
nuclear@0
|
42 /** @file Implementation of the XGL/ZGL importer class */
|
nuclear@0
|
43
|
nuclear@0
|
44 #include "AssimpPCH.h"
|
nuclear@0
|
45 #ifndef ASSIMP_BUILD_NO_XGL_IMPORTER
|
nuclear@0
|
46
|
nuclear@0
|
47 #include "XGLLoader.h"
|
nuclear@0
|
48 #include "ParsingUtils.h"
|
nuclear@0
|
49 #include "fast_atof.h"
|
nuclear@0
|
50
|
nuclear@0
|
51 #include "StreamReader.h"
|
nuclear@0
|
52 #include "MemoryIOWrapper.h"
|
nuclear@0
|
53
|
nuclear@0
|
54 using namespace Assimp;
|
nuclear@0
|
55 using namespace irr;
|
nuclear@0
|
56 using namespace irr::io;
|
nuclear@0
|
57
|
nuclear@0
|
58
|
nuclear@0
|
59 // zlib is needed for compressed XGL files
|
nuclear@0
|
60 #ifndef ASSIMP_BUILD_NO_COMPRESSED_XGL
|
nuclear@0
|
61 # ifdef ASSIMP_BUILD_NO_OWN_ZLIB
|
nuclear@0
|
62 # include <zlib.h>
|
nuclear@0
|
63 # else
|
nuclear@0
|
64 # include "../contrib/zlib/zlib.h"
|
nuclear@0
|
65 # endif
|
nuclear@0
|
66 #endif
|
nuclear@0
|
67
|
nuclear@0
|
68
|
nuclear@0
|
69 // scopeguard for a malloc'ed buffer
|
nuclear@0
|
70 struct free_it
|
nuclear@0
|
71 {
|
nuclear@0
|
72 free_it(void* free) : free(free) {}
|
nuclear@0
|
73 ~free_it() {
|
nuclear@0
|
74 ::free(this->free);
|
nuclear@0
|
75 }
|
nuclear@0
|
76
|
nuclear@0
|
77 void* free;
|
nuclear@0
|
78 };
|
nuclear@0
|
79
|
nuclear@0
|
80 namespace Assimp { // this has to be in here because LogFunctions is in ::Assimp
|
nuclear@0
|
81 template<> const std::string LogFunctions<XGLImporter>::log_prefix = "XGL: ";
|
nuclear@0
|
82
|
nuclear@0
|
83 }
|
nuclear@0
|
84
|
nuclear@0
|
85 static const aiImporterDesc desc = {
|
nuclear@0
|
86 "XGL Importer",
|
nuclear@0
|
87 "",
|
nuclear@0
|
88 "",
|
nuclear@0
|
89 "",
|
nuclear@0
|
90 aiImporterFlags_SupportTextFlavour,
|
nuclear@0
|
91 0,
|
nuclear@0
|
92 0,
|
nuclear@0
|
93 0,
|
nuclear@0
|
94 0,
|
nuclear@0
|
95 "xgl zgl"
|
nuclear@0
|
96 };
|
nuclear@0
|
97
|
nuclear@0
|
98
|
nuclear@0
|
99 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
100 // Constructor to be privately used by Importer
|
nuclear@0
|
101 XGLImporter::XGLImporter()
|
nuclear@0
|
102 {}
|
nuclear@0
|
103
|
nuclear@0
|
104 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
105 // Destructor, private as well
|
nuclear@0
|
106 XGLImporter::~XGLImporter()
|
nuclear@0
|
107 {}
|
nuclear@0
|
108
|
nuclear@0
|
109 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
110 // Returns whether the class can handle the format of the given file.
|
nuclear@0
|
111 bool XGLImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
|
nuclear@0
|
112 {
|
nuclear@0
|
113 /* NOTE: A simple check for the file extension is not enough
|
nuclear@0
|
114 * here. XGL and ZGL are ok, but xml is too generic
|
nuclear@0
|
115 * and might be collada as well. So open the file and
|
nuclear@0
|
116 * look for typical signal tokens.
|
nuclear@0
|
117 */
|
nuclear@0
|
118 const std::string extension = GetExtension(pFile);
|
nuclear@0
|
119
|
nuclear@0
|
120 if (extension == "xgl" || extension == "zgl") {
|
nuclear@0
|
121 return true;
|
nuclear@0
|
122 }
|
nuclear@0
|
123 else if (extension == "xml" || checkSig) {
|
nuclear@0
|
124 ai_assert(pIOHandler != NULL);
|
nuclear@0
|
125
|
nuclear@0
|
126 const char* tokens[] = {"<world>","<World>","<WORLD>"};
|
nuclear@0
|
127 return SearchFileHeaderForToken(pIOHandler,pFile,tokens,3);
|
nuclear@0
|
128 }
|
nuclear@0
|
129 return false;
|
nuclear@0
|
130 }
|
nuclear@0
|
131
|
nuclear@0
|
132 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
133 // Get a list of all file extensions which are handled by this class
|
nuclear@0
|
134 const aiImporterDesc* XGLImporter::GetInfo () const
|
nuclear@0
|
135 {
|
nuclear@0
|
136 return &desc;
|
nuclear@0
|
137 }
|
nuclear@0
|
138
|
nuclear@0
|
139 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
140 // Imports the given file into the given scene structure.
|
nuclear@0
|
141 void XGLImporter::InternReadFile( const std::string& pFile,
|
nuclear@0
|
142 aiScene* pScene, IOSystem* pIOHandler)
|
nuclear@0
|
143 {
|
nuclear@0
|
144 #ifndef ASSIMP_BUILD_NO_COMPRESSED_XGL
|
nuclear@0
|
145 Bytef* dest = NULL;
|
nuclear@0
|
146 free_it free_it_really(dest);
|
nuclear@0
|
147 #endif
|
nuclear@0
|
148
|
nuclear@0
|
149 scene = pScene;
|
nuclear@0
|
150 boost::shared_ptr<IOStream> stream( pIOHandler->Open( pFile, "rb"));
|
nuclear@0
|
151
|
nuclear@0
|
152 // check whether we can read from the file
|
nuclear@0
|
153 if( stream.get() == NULL) {
|
nuclear@0
|
154 throw DeadlyImportError( "Failed to open XGL/ZGL file " + pFile + "");
|
nuclear@0
|
155 }
|
nuclear@0
|
156
|
nuclear@0
|
157 // see if its compressed, if so uncompress it
|
nuclear@0
|
158 if (GetExtension(pFile) == "zgl") {
|
nuclear@0
|
159 #ifdef ASSIMP_BUILD_NO_COMPRESSED_XGL
|
nuclear@0
|
160 ThrowException("Cannot read ZGL file since Assimp was built without compression support");
|
nuclear@0
|
161 #else
|
nuclear@0
|
162 boost::scoped_ptr<StreamReaderLE> raw_reader(new StreamReaderLE(stream));
|
nuclear@0
|
163
|
nuclear@0
|
164 // build a zlib stream
|
nuclear@0
|
165 z_stream zstream;
|
nuclear@0
|
166 zstream.opaque = Z_NULL;
|
nuclear@0
|
167 zstream.zalloc = Z_NULL;
|
nuclear@0
|
168 zstream.zfree = Z_NULL;
|
nuclear@0
|
169 zstream.data_type = Z_BINARY;
|
nuclear@0
|
170
|
nuclear@0
|
171 // raw decompression without a zlib or gzip header
|
nuclear@0
|
172 inflateInit2(&zstream, -MAX_WBITS);
|
nuclear@0
|
173
|
nuclear@0
|
174 // skip two extra bytes, zgl files do carry a crc16 upfront (I think)
|
nuclear@0
|
175 raw_reader->IncPtr(2);
|
nuclear@0
|
176
|
nuclear@0
|
177 zstream.next_in = reinterpret_cast<Bytef*>( raw_reader->GetPtr() );
|
nuclear@0
|
178 zstream.avail_in = raw_reader->GetRemainingSize();
|
nuclear@0
|
179
|
nuclear@0
|
180 size_t total = 0l;
|
nuclear@0
|
181
|
nuclear@0
|
182 // and decompress the data .... do 1k chunks in the hope that we won't kill the stack
|
nuclear@0
|
183 #define MYBLOCK 1024
|
nuclear@0
|
184 Bytef block[MYBLOCK];
|
nuclear@0
|
185 int ret;
|
nuclear@0
|
186 do {
|
nuclear@0
|
187 zstream.avail_out = MYBLOCK;
|
nuclear@0
|
188 zstream.next_out = block;
|
nuclear@0
|
189 ret = inflate(&zstream, Z_NO_FLUSH);
|
nuclear@0
|
190
|
nuclear@0
|
191 if (ret != Z_STREAM_END && ret != Z_OK) {
|
nuclear@0
|
192 ThrowException("Failure decompressing this file using gzip, seemingly it is NOT a compressed .XGL file");
|
nuclear@0
|
193 }
|
nuclear@0
|
194 const size_t have = MYBLOCK - zstream.avail_out;
|
nuclear@0
|
195 total += have;
|
nuclear@0
|
196 dest = reinterpret_cast<Bytef*>( realloc(dest,total) );
|
nuclear@0
|
197 memcpy(dest + total - have,block,have);
|
nuclear@0
|
198 }
|
nuclear@0
|
199 while (ret != Z_STREAM_END);
|
nuclear@0
|
200
|
nuclear@0
|
201 // terminate zlib
|
nuclear@0
|
202 inflateEnd(&zstream);
|
nuclear@0
|
203
|
nuclear@0
|
204 // replace the input stream with a memory stream
|
nuclear@0
|
205 stream.reset(new MemoryIOStream(reinterpret_cast<uint8_t*>(dest),total));
|
nuclear@0
|
206 #endif
|
nuclear@0
|
207 }
|
nuclear@0
|
208
|
nuclear@0
|
209 // construct the irrXML parser
|
nuclear@0
|
210 CIrrXML_IOStreamReader st(stream.get());
|
nuclear@0
|
211 boost::scoped_ptr<IrrXMLReader> read( createIrrXMLReader((IFileReadCallBack*) &st) );
|
nuclear@0
|
212 reader = read.get();
|
nuclear@0
|
213
|
nuclear@0
|
214 // parse the XML file
|
nuclear@0
|
215 TempScope scope;
|
nuclear@0
|
216
|
nuclear@0
|
217 while (ReadElement()) {
|
nuclear@0
|
218 if (!ASSIMP_stricmp(reader->getNodeName(),"world")) {
|
nuclear@0
|
219 ReadWorld(scope);
|
nuclear@0
|
220 }
|
nuclear@0
|
221 }
|
nuclear@0
|
222
|
nuclear@0
|
223
|
nuclear@0
|
224 std::vector<aiMesh*>& meshes = scope.meshes_linear;
|
nuclear@0
|
225 std::vector<aiMaterial*>& materials = scope.materials_linear;
|
nuclear@0
|
226 if(!meshes.size() || !materials.size()) {
|
nuclear@0
|
227 ThrowException("failed to extract data from XGL file, no meshes loaded");
|
nuclear@0
|
228 }
|
nuclear@0
|
229
|
nuclear@0
|
230 // copy meshes
|
nuclear@0
|
231 scene->mNumMeshes = static_cast<unsigned int>(meshes.size());
|
nuclear@0
|
232 scene->mMeshes = new aiMesh*[scene->mNumMeshes]();
|
nuclear@0
|
233 std::copy(meshes.begin(),meshes.end(),scene->mMeshes);
|
nuclear@0
|
234
|
nuclear@0
|
235 // copy materials
|
nuclear@0
|
236 scene->mNumMaterials = static_cast<unsigned int>(materials.size());
|
nuclear@0
|
237 scene->mMaterials = new aiMaterial*[scene->mNumMaterials]();
|
nuclear@0
|
238 std::copy(materials.begin(),materials.end(),scene->mMaterials);
|
nuclear@0
|
239
|
nuclear@0
|
240 if (scope.light) {
|
nuclear@0
|
241 scene->mNumLights = 1;
|
nuclear@0
|
242 scene->mLights = new aiLight*[1];
|
nuclear@0
|
243 scene->mLights[0] = scope.light;
|
nuclear@0
|
244
|
nuclear@0
|
245 scope.light->mName = scene->mRootNode->mName;
|
nuclear@0
|
246 }
|
nuclear@0
|
247
|
nuclear@0
|
248 scope.dismiss();
|
nuclear@0
|
249 }
|
nuclear@0
|
250
|
nuclear@0
|
251 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
252 bool XGLImporter::ReadElement()
|
nuclear@0
|
253 {
|
nuclear@0
|
254 while(reader->read()) {
|
nuclear@0
|
255 if (reader->getNodeType() == EXN_ELEMENT) {
|
nuclear@0
|
256 return true;
|
nuclear@0
|
257 }
|
nuclear@0
|
258 }
|
nuclear@0
|
259 return false;
|
nuclear@0
|
260 }
|
nuclear@0
|
261
|
nuclear@0
|
262 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
263 bool XGLImporter::ReadElementUpToClosing(const char* closetag)
|
nuclear@0
|
264 {
|
nuclear@0
|
265 while(reader->read()) {
|
nuclear@0
|
266 if (reader->getNodeType() == EXN_ELEMENT) {
|
nuclear@0
|
267 return true;
|
nuclear@0
|
268 }
|
nuclear@0
|
269 else if (reader->getNodeType() == EXN_ELEMENT_END && !ASSIMP_stricmp(reader->getNodeName(),closetag)) {
|
nuclear@0
|
270 return false;
|
nuclear@0
|
271 }
|
nuclear@0
|
272 }
|
nuclear@0
|
273 LogError("unexpected EOF, expected closing <" + std::string(closetag) + "> tag");
|
nuclear@0
|
274 return false;
|
nuclear@0
|
275 }
|
nuclear@0
|
276
|
nuclear@0
|
277 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
278 bool XGLImporter::SkipToText()
|
nuclear@0
|
279 {
|
nuclear@0
|
280 while(reader->read()) {
|
nuclear@0
|
281 if (reader->getNodeType() == EXN_TEXT) {
|
nuclear@0
|
282 return true;
|
nuclear@0
|
283 }
|
nuclear@0
|
284 else if (reader->getNodeType() == EXN_ELEMENT || reader->getNodeType() == EXN_ELEMENT_END) {
|
nuclear@0
|
285 ThrowException("expected text contents but found another element (or element end)");
|
nuclear@0
|
286 }
|
nuclear@0
|
287 }
|
nuclear@0
|
288 return false;
|
nuclear@0
|
289 }
|
nuclear@0
|
290
|
nuclear@0
|
291 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
292 std::string XGLImporter::GetElementName()
|
nuclear@0
|
293 {
|
nuclear@0
|
294 const char* s = reader->getNodeName();
|
nuclear@0
|
295 size_t len = strlen(s);
|
nuclear@0
|
296
|
nuclear@0
|
297 std::string ret;
|
nuclear@0
|
298 ret.resize(len);
|
nuclear@0
|
299
|
nuclear@0
|
300 std::transform(s,s+len,ret.begin(),::tolower);
|
nuclear@0
|
301 return ret;
|
nuclear@0
|
302 }
|
nuclear@0
|
303
|
nuclear@0
|
304 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
305 void XGLImporter::ReadWorld(TempScope& scope)
|
nuclear@0
|
306 {
|
nuclear@0
|
307 while (ReadElementUpToClosing("world")) {
|
nuclear@0
|
308 const std::string& s = GetElementName();
|
nuclear@0
|
309 // XXX right now we'd skip <lighting> if it comes after
|
nuclear@0
|
310 // <object> or <mesh>
|
nuclear@0
|
311 if (s == "lighting") {
|
nuclear@0
|
312 ReadLighting(scope);
|
nuclear@0
|
313 }
|
nuclear@0
|
314 else if (s == "object" || s == "mesh" || s == "mat") {
|
nuclear@0
|
315 break;
|
nuclear@0
|
316 }
|
nuclear@0
|
317 }
|
nuclear@0
|
318
|
nuclear@0
|
319
|
nuclear@0
|
320 aiNode* const nd = ReadObject(scope,true,"world");
|
nuclear@0
|
321 if(!nd) {
|
nuclear@0
|
322 ThrowException("failure reading <world>");
|
nuclear@0
|
323 }
|
nuclear@0
|
324 if(!nd->mName.length) {
|
nuclear@0
|
325 nd->mName.Set("WORLD");
|
nuclear@0
|
326 }
|
nuclear@0
|
327
|
nuclear@0
|
328 scene->mRootNode = nd;
|
nuclear@0
|
329 }
|
nuclear@0
|
330
|
nuclear@0
|
331 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
332 void XGLImporter::ReadLighting(TempScope& scope)
|
nuclear@0
|
333 {
|
nuclear@0
|
334 while (ReadElementUpToClosing("lighting")) {
|
nuclear@0
|
335 const std::string& s = GetElementName();
|
nuclear@0
|
336 if (s == "directionallight") {
|
nuclear@0
|
337 scope.light = ReadDirectionalLight();
|
nuclear@0
|
338 }
|
nuclear@0
|
339 else if (s == "ambient") {
|
nuclear@0
|
340 LogWarn("ignoring <ambient> tag");
|
nuclear@0
|
341 }
|
nuclear@0
|
342 else if (s == "spheremap") {
|
nuclear@0
|
343 LogWarn("ignoring <spheremap> tag");
|
nuclear@0
|
344 }
|
nuclear@0
|
345 }
|
nuclear@0
|
346 }
|
nuclear@0
|
347
|
nuclear@0
|
348 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
349 aiLight* XGLImporter::ReadDirectionalLight()
|
nuclear@0
|
350 {
|
nuclear@0
|
351 ScopeGuard<aiLight> l(new aiLight());
|
nuclear@0
|
352 l->mType = aiLightSource_DIRECTIONAL;
|
nuclear@0
|
353
|
nuclear@0
|
354 while (ReadElementUpToClosing("directionallight")) {
|
nuclear@0
|
355 const std::string& s = GetElementName();
|
nuclear@0
|
356 if (s == "direction") {
|
nuclear@0
|
357 l->mDirection = ReadVec3();
|
nuclear@0
|
358 }
|
nuclear@0
|
359 else if (s == "diffuse") {
|
nuclear@0
|
360 l->mColorDiffuse = ReadCol3();
|
nuclear@0
|
361 }
|
nuclear@0
|
362 else if (s == "specular") {
|
nuclear@0
|
363 l->mColorSpecular = ReadCol3();
|
nuclear@0
|
364 }
|
nuclear@0
|
365 }
|
nuclear@0
|
366 return l.dismiss();
|
nuclear@0
|
367 }
|
nuclear@0
|
368
|
nuclear@0
|
369 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
370 aiNode* XGLImporter::ReadObject(TempScope& scope, bool skipFirst, const char* closetag)
|
nuclear@0
|
371 {
|
nuclear@0
|
372 ScopeGuard<aiNode> nd(new aiNode());
|
nuclear@0
|
373 std::vector<aiNode*> children;
|
nuclear@0
|
374 std::vector<unsigned int> meshes;
|
nuclear@0
|
375
|
nuclear@0
|
376 try {
|
nuclear@0
|
377 while (skipFirst || ReadElementUpToClosing(closetag)) {
|
nuclear@0
|
378 skipFirst = false;
|
nuclear@0
|
379
|
nuclear@0
|
380 const std::string& s = GetElementName();
|
nuclear@0
|
381 if (s == "mesh") {
|
nuclear@0
|
382 const size_t prev = scope.meshes_linear.size();
|
nuclear@0
|
383 if(ReadMesh(scope)) {
|
nuclear@0
|
384 const size_t newc = scope.meshes_linear.size();
|
nuclear@0
|
385 for(size_t i = 0; i < newc-prev; ++i) {
|
nuclear@0
|
386 meshes.push_back(static_cast<unsigned int>(i+prev));
|
nuclear@0
|
387 }
|
nuclear@0
|
388 }
|
nuclear@0
|
389 }
|
nuclear@0
|
390 else if (s == "mat") {
|
nuclear@0
|
391 ReadMaterial(scope);
|
nuclear@0
|
392 }
|
nuclear@0
|
393 else if (s == "object") {
|
nuclear@0
|
394 children.push_back(ReadObject(scope));
|
nuclear@0
|
395 }
|
nuclear@0
|
396 else if (s == "objectref") {
|
nuclear@0
|
397 // XXX
|
nuclear@0
|
398 }
|
nuclear@0
|
399 else if (s == "meshref") {
|
nuclear@0
|
400 const unsigned int id = static_cast<unsigned int>( ReadIndexFromText() );
|
nuclear@0
|
401
|
nuclear@0
|
402 std::multimap<unsigned int, aiMesh*>::iterator it = scope.meshes.find(id), end = scope.meshes.end();
|
nuclear@0
|
403 if (it == end) {
|
nuclear@0
|
404 ThrowException("<meshref> index out of range");
|
nuclear@0
|
405 }
|
nuclear@0
|
406
|
nuclear@0
|
407 for(; it != end && (*it).first == id; ++it) {
|
nuclear@0
|
408 // ok, this is n^2 and should get optimized one day
|
nuclear@0
|
409 aiMesh* const m = (*it).second;
|
nuclear@0
|
410
|
nuclear@0
|
411 unsigned int i = 0, mcount = static_cast<unsigned int>(scope.meshes_linear.size());
|
nuclear@0
|
412 for(; i < mcount; ++i) {
|
nuclear@0
|
413 if (scope.meshes_linear[i] == m) {
|
nuclear@0
|
414 meshes.push_back(i);
|
nuclear@0
|
415 break;
|
nuclear@0
|
416 }
|
nuclear@0
|
417 }
|
nuclear@0
|
418
|
nuclear@0
|
419 ai_assert(i < mcount);
|
nuclear@0
|
420 }
|
nuclear@0
|
421 }
|
nuclear@0
|
422 else if (s == "transform") {
|
nuclear@0
|
423 nd->mTransformation = ReadTrafo();
|
nuclear@0
|
424 }
|
nuclear@0
|
425 }
|
nuclear@0
|
426
|
nuclear@0
|
427 } catch(...) {
|
nuclear@0
|
428 BOOST_FOREACH(aiNode* ch, children) {
|
nuclear@0
|
429 delete ch;
|
nuclear@0
|
430 }
|
nuclear@0
|
431 throw;
|
nuclear@0
|
432 }
|
nuclear@0
|
433
|
nuclear@0
|
434 // link meshes to node
|
nuclear@0
|
435 nd->mNumMeshes = static_cast<unsigned int>(meshes.size());
|
nuclear@0
|
436 if (nd->mNumMeshes) {
|
nuclear@0
|
437 nd->mMeshes = new unsigned int[nd->mNumMeshes]();
|
nuclear@0
|
438 for(unsigned int i = 0; i < nd->mNumMeshes; ++i) {
|
nuclear@0
|
439 nd->mMeshes[i] = meshes[i];
|
nuclear@0
|
440 }
|
nuclear@0
|
441 }
|
nuclear@0
|
442
|
nuclear@0
|
443 // link children to parent
|
nuclear@0
|
444 nd->mNumChildren = static_cast<unsigned int>(children.size());
|
nuclear@0
|
445 if (nd->mNumChildren) {
|
nuclear@0
|
446 nd->mChildren = new aiNode*[nd->mNumChildren]();
|
nuclear@0
|
447 for(unsigned int i = 0; i < nd->mNumChildren; ++i) {
|
nuclear@0
|
448 nd->mChildren[i] = children[i];
|
nuclear@0
|
449 children[i]->mParent = nd;
|
nuclear@0
|
450 }
|
nuclear@0
|
451 }
|
nuclear@0
|
452
|
nuclear@0
|
453 return nd.dismiss();
|
nuclear@0
|
454 }
|
nuclear@0
|
455
|
nuclear@0
|
456 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
457 aiMatrix4x4 XGLImporter::ReadTrafo()
|
nuclear@0
|
458 {
|
nuclear@0
|
459 aiVector3D forward, up, right, position;
|
nuclear@0
|
460 float scale = 1.0f;
|
nuclear@0
|
461
|
nuclear@0
|
462 while (ReadElementUpToClosing("transform")) {
|
nuclear@0
|
463 const std::string& s = GetElementName();
|
nuclear@0
|
464 if (s == "forward") {
|
nuclear@0
|
465 forward = ReadVec3();
|
nuclear@0
|
466 }
|
nuclear@0
|
467 else if (s == "up") {
|
nuclear@0
|
468 up = ReadVec3();
|
nuclear@0
|
469 }
|
nuclear@0
|
470 else if (s == "position") {
|
nuclear@0
|
471 position = ReadVec3();
|
nuclear@0
|
472 }
|
nuclear@0
|
473 if (s == "scale") {
|
nuclear@0
|
474 scale = ReadFloat();
|
nuclear@0
|
475 if(scale < 0.f) {
|
nuclear@0
|
476 // this is wrong, but we can leave the value and pass it to the caller
|
nuclear@0
|
477 LogError("found negative scaling in <transform>, ignoring");
|
nuclear@0
|
478 }
|
nuclear@0
|
479 }
|
nuclear@0
|
480 }
|
nuclear@0
|
481
|
nuclear@0
|
482 aiMatrix4x4 m;
|
nuclear@0
|
483 if(forward.SquareLength() < 1e-4 || up.SquareLength() < 1e-4) {
|
nuclear@0
|
484 LogError("A direction vector in <transform> is zero, ignoring trafo");
|
nuclear@0
|
485 return m;
|
nuclear@0
|
486 }
|
nuclear@0
|
487
|
nuclear@0
|
488 forward.Normalize();
|
nuclear@0
|
489 up.Normalize();
|
nuclear@0
|
490
|
nuclear@0
|
491 right = forward ^ up;
|
nuclear@0
|
492 if (fabs(up * forward) > 1e-4) {
|
nuclear@0
|
493 // this is definitely wrong - a degenerate coordinate space ruins everything
|
nuclear@0
|
494 // so subtitute identity transform.
|
nuclear@0
|
495 LogError("<forward> and <up> vectors in <transform> are skewing, ignoring trafo");
|
nuclear@0
|
496 return m;
|
nuclear@0
|
497 }
|
nuclear@0
|
498
|
nuclear@0
|
499 right *= scale;
|
nuclear@0
|
500 up *= scale;
|
nuclear@0
|
501 forward *= scale;
|
nuclear@0
|
502
|
nuclear@0
|
503 m.a1 = right.x;
|
nuclear@0
|
504 m.b1 = right.y;
|
nuclear@0
|
505 m.c1 = right.z;
|
nuclear@0
|
506
|
nuclear@0
|
507 m.a2 = up.x;
|
nuclear@0
|
508 m.b2 = up.y;
|
nuclear@0
|
509 m.c2 = up.z;
|
nuclear@0
|
510
|
nuclear@0
|
511 m.a3 = forward.x;
|
nuclear@0
|
512 m.b3 = forward.y;
|
nuclear@0
|
513 m.c3 = forward.z;
|
nuclear@0
|
514
|
nuclear@0
|
515 m.a4 = position.x;
|
nuclear@0
|
516 m.b4 = position.y;
|
nuclear@0
|
517 m.c4 = position.z;
|
nuclear@0
|
518
|
nuclear@0
|
519 return m;
|
nuclear@0
|
520 }
|
nuclear@0
|
521
|
nuclear@0
|
522 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
523 aiMesh* XGLImporter::ToOutputMesh(const TempMaterialMesh& m)
|
nuclear@0
|
524 {
|
nuclear@0
|
525 ScopeGuard<aiMesh> mesh(new aiMesh());
|
nuclear@0
|
526
|
nuclear@0
|
527 mesh->mNumVertices = static_cast<unsigned int>(m.positions.size());
|
nuclear@0
|
528 mesh->mVertices = new aiVector3D[mesh->mNumVertices];
|
nuclear@0
|
529 std::copy(m.positions.begin(),m.positions.end(),mesh->mVertices);
|
nuclear@0
|
530
|
nuclear@0
|
531 if(m.normals.size()) {
|
nuclear@0
|
532 mesh->mNormals = new aiVector3D[mesh->mNumVertices];
|
nuclear@0
|
533 std::copy(m.normals.begin(),m.normals.end(),mesh->mNormals);
|
nuclear@0
|
534 }
|
nuclear@0
|
535
|
nuclear@0
|
536 if(m.uvs.size()) {
|
nuclear@0
|
537 mesh->mNumUVComponents[0] = 2;
|
nuclear@0
|
538 mesh->mTextureCoords[0] = new aiVector3D[mesh->mNumVertices];
|
nuclear@0
|
539
|
nuclear@0
|
540 for(unsigned int i = 0; i < mesh->mNumVertices; ++i) {
|
nuclear@0
|
541 mesh->mTextureCoords[0][i] = aiVector3D(m.uvs[i].x,m.uvs[i].y,0.f);
|
nuclear@0
|
542 }
|
nuclear@0
|
543 }
|
nuclear@0
|
544
|
nuclear@0
|
545 mesh->mNumFaces = static_cast<unsigned int>(m.vcounts.size());
|
nuclear@0
|
546 mesh->mFaces = new aiFace[m.vcounts.size()];
|
nuclear@0
|
547
|
nuclear@0
|
548 unsigned int idx = 0;
|
nuclear@0
|
549 for(unsigned int i = 0; i < mesh->mNumFaces; ++i) {
|
nuclear@0
|
550 aiFace& f = mesh->mFaces[i];
|
nuclear@0
|
551 f.mNumIndices = m.vcounts[i];
|
nuclear@0
|
552 f.mIndices = new unsigned int[f.mNumIndices];
|
nuclear@0
|
553 for(unsigned int c = 0; c < f.mNumIndices; ++c) {
|
nuclear@0
|
554 f.mIndices[c] = idx++;
|
nuclear@0
|
555 }
|
nuclear@0
|
556 }
|
nuclear@0
|
557
|
nuclear@0
|
558 ai_assert(idx == mesh->mNumVertices);
|
nuclear@0
|
559
|
nuclear@0
|
560 mesh->mPrimitiveTypes = m.pflags;
|
nuclear@0
|
561 mesh->mMaterialIndex = m.matid;
|
nuclear@0
|
562 return mesh.dismiss();
|
nuclear@0
|
563 }
|
nuclear@0
|
564
|
nuclear@0
|
565 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
566 bool XGLImporter::ReadMesh(TempScope& scope)
|
nuclear@0
|
567 {
|
nuclear@0
|
568 TempMesh t;
|
nuclear@0
|
569
|
nuclear@0
|
570 std::map<unsigned int, TempMaterialMesh> bymat;
|
nuclear@0
|
571 const unsigned int mesh_id = ReadIDAttr();
|
nuclear@0
|
572
|
nuclear@0
|
573 while (ReadElementUpToClosing("mesh")) {
|
nuclear@0
|
574 const std::string& s = GetElementName();
|
nuclear@0
|
575
|
nuclear@0
|
576 if (s == "mat") {
|
nuclear@0
|
577 ReadMaterial(scope);
|
nuclear@0
|
578 }
|
nuclear@0
|
579 else if (s == "p") {
|
nuclear@0
|
580 if (!reader->getAttributeValue("ID")) {
|
nuclear@0
|
581 LogWarn("no ID attribute on <p>, ignoring");
|
nuclear@0
|
582 }
|
nuclear@0
|
583 else {
|
nuclear@0
|
584 int id = reader->getAttributeValueAsInt("ID");
|
nuclear@0
|
585 t.points[id] = ReadVec3();
|
nuclear@0
|
586 }
|
nuclear@0
|
587 }
|
nuclear@0
|
588 else if (s == "n") {
|
nuclear@0
|
589 if (!reader->getAttributeValue("ID")) {
|
nuclear@0
|
590 LogWarn("no ID attribute on <n>, ignoring");
|
nuclear@0
|
591 }
|
nuclear@0
|
592 else {
|
nuclear@0
|
593 int id = reader->getAttributeValueAsInt("ID");
|
nuclear@0
|
594 t.normals[id] = ReadVec3();
|
nuclear@0
|
595 }
|
nuclear@0
|
596 }
|
nuclear@0
|
597 else if (s == "tc") {
|
nuclear@0
|
598 if (!reader->getAttributeValue("ID")) {
|
nuclear@0
|
599 LogWarn("no ID attribute on <tc>, ignoring");
|
nuclear@0
|
600 }
|
nuclear@0
|
601 else {
|
nuclear@0
|
602 int id = reader->getAttributeValueAsInt("ID");
|
nuclear@0
|
603 t.uvs[id] = ReadVec2();
|
nuclear@0
|
604 }
|
nuclear@0
|
605 }
|
nuclear@0
|
606 else if (s == "f" || s == "l" || s == "p") {
|
nuclear@0
|
607 const unsigned int vcount = s == "f" ? 3 : (s == "l" ? 2 : 1);
|
nuclear@0
|
608
|
nuclear@0
|
609 unsigned int mid = ~0u;
|
nuclear@0
|
610 TempFace tf[3];
|
nuclear@0
|
611 bool has[3] = {0};
|
nuclear@0
|
612
|
nuclear@0
|
613 while (ReadElementUpToClosing(s.c_str())) {
|
nuclear@0
|
614 const std::string& s = GetElementName();
|
nuclear@0
|
615 if (s == "fv1" || s == "lv1" || s == "pv1") {
|
nuclear@0
|
616 ReadFaceVertex(t,tf[0]);
|
nuclear@0
|
617 has[0] = true;
|
nuclear@0
|
618 }
|
nuclear@0
|
619 else if (s == "fv2" || s == "lv2") {
|
nuclear@0
|
620 ReadFaceVertex(t,tf[1]);
|
nuclear@0
|
621 has[1] = true;
|
nuclear@0
|
622 }
|
nuclear@0
|
623 else if (s == "fv3") {
|
nuclear@0
|
624 ReadFaceVertex(t,tf[2]);
|
nuclear@0
|
625 has[2] = true;
|
nuclear@0
|
626 }
|
nuclear@0
|
627 else if (s == "mat") {
|
nuclear@0
|
628 if (mid != ~0u) {
|
nuclear@0
|
629 LogWarn("only one material tag allowed per <f>");
|
nuclear@0
|
630 }
|
nuclear@0
|
631 mid = ResolveMaterialRef(scope);
|
nuclear@0
|
632 }
|
nuclear@0
|
633 else if (s == "matref") {
|
nuclear@0
|
634 if (mid != ~0u) {
|
nuclear@0
|
635 LogWarn("only one material tag allowed per <f>");
|
nuclear@0
|
636 }
|
nuclear@0
|
637 mid = ResolveMaterialRef(scope);
|
nuclear@0
|
638 }
|
nuclear@0
|
639 }
|
nuclear@0
|
640
|
nuclear@0
|
641 if (mid == ~0u) {
|
nuclear@0
|
642 ThrowException("missing material index");
|
nuclear@0
|
643 }
|
nuclear@0
|
644
|
nuclear@0
|
645 bool nor = false;
|
nuclear@0
|
646 bool uv = false;
|
nuclear@0
|
647 for(unsigned int i = 0; i < vcount; ++i) {
|
nuclear@0
|
648 if (!has[i]) {
|
nuclear@0
|
649 ThrowException("missing face vertex data");
|
nuclear@0
|
650 }
|
nuclear@0
|
651
|
nuclear@0
|
652 nor = nor || tf[i].has_normal;
|
nuclear@0
|
653 uv = uv || tf[i].has_uv;
|
nuclear@0
|
654 }
|
nuclear@0
|
655
|
nuclear@0
|
656 if (mid >= (1<<30)) {
|
nuclear@0
|
657 LogWarn("material indices exhausted, this may cause errors in the output");
|
nuclear@0
|
658 }
|
nuclear@0
|
659 unsigned int meshId = mid | ((nor?1:0)<<31) | ((uv?1:0)<<30);
|
nuclear@0
|
660
|
nuclear@0
|
661 TempMaterialMesh& mesh = bymat[meshId];
|
nuclear@0
|
662 mesh.matid = mid;
|
nuclear@0
|
663
|
nuclear@0
|
664 for(unsigned int i = 0; i < vcount; ++i) {
|
nuclear@0
|
665 mesh.positions.push_back(tf[i].pos);
|
nuclear@0
|
666 if(nor) {
|
nuclear@0
|
667 mesh.normals.push_back(tf[i].normal);
|
nuclear@0
|
668 }
|
nuclear@0
|
669 if(uv) {
|
nuclear@0
|
670 mesh.uvs.push_back(tf[i].uv);
|
nuclear@0
|
671 }
|
nuclear@0
|
672
|
nuclear@0
|
673 mesh.pflags |= 1 << (vcount-1);
|
nuclear@0
|
674 }
|
nuclear@0
|
675
|
nuclear@0
|
676 mesh.vcounts.push_back(vcount);
|
nuclear@0
|
677 }
|
nuclear@0
|
678 }
|
nuclear@0
|
679
|
nuclear@0
|
680 // finally extract output meshes and add them to the scope
|
nuclear@0
|
681 typedef std::pair<unsigned int, TempMaterialMesh> pairt;
|
nuclear@0
|
682 BOOST_FOREACH(const pairt& p, bymat) {
|
nuclear@0
|
683 aiMesh* const m = ToOutputMesh(p.second);
|
nuclear@0
|
684 scope.meshes_linear.push_back(m);
|
nuclear@0
|
685
|
nuclear@0
|
686 // if this is a definition, keep it on the stack
|
nuclear@0
|
687 if(mesh_id != ~0u) {
|
nuclear@0
|
688 scope.meshes.insert(std::pair<unsigned int, aiMesh*>(mesh_id,m));
|
nuclear@0
|
689 }
|
nuclear@0
|
690 }
|
nuclear@0
|
691
|
nuclear@0
|
692 // no id == not a reference, insert this mesh right *here*
|
nuclear@0
|
693 return mesh_id == ~0u;
|
nuclear@0
|
694 }
|
nuclear@0
|
695
|
nuclear@0
|
696 // ----------------------------------------------------------------------------------------------
|
nuclear@0
|
697 unsigned int XGLImporter::ResolveMaterialRef(TempScope& scope)
|
nuclear@0
|
698 {
|
nuclear@0
|
699 const std::string& s = GetElementName();
|
nuclear@0
|
700 if (s == "mat") {
|
nuclear@0
|
701 ReadMaterial(scope);
|
nuclear@0
|
702 return scope.materials_linear.size()-1;
|
nuclear@0
|
703 }
|
nuclear@0
|
704
|
nuclear@0
|
705 const int id = ReadIndexFromText();
|
nuclear@0
|
706
|
nuclear@0
|
707 std::map<unsigned int, aiMaterial*>::iterator it = scope.materials.find(id), end = scope.materials.end();
|
nuclear@0
|
708 if (it == end) {
|
nuclear@0
|
709 ThrowException("<matref> index out of range");
|
nuclear@0
|
710 }
|
nuclear@0
|
711
|
nuclear@0
|
712 // ok, this is n^2 and should get optimized one day
|
nuclear@0
|
713 aiMaterial* const m = (*it).second;
|
nuclear@0
|
714
|
nuclear@0
|
715 unsigned int i = 0, mcount = static_cast<unsigned int>(scope.materials_linear.size());
|
nuclear@0
|
716 for(; i < mcount; ++i) {
|
nuclear@0
|
717 if (scope.materials_linear[i] == m) {
|
nuclear@0
|
718 return i;
|
nuclear@0
|
719 }
|
nuclear@0
|
720 }
|
nuclear@0
|
721
|
nuclear@0
|
722 ai_assert(false);
|
nuclear@0
|
723 return 0;
|
nuclear@0
|
724 }
|
nuclear@0
|
725
|
nuclear@0
|
726 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
727 void XGLImporter::ReadMaterial(TempScope& scope)
|
nuclear@0
|
728 {
|
nuclear@0
|
729 const unsigned int mat_id = ReadIDAttr();
|
nuclear@0
|
730
|
nuclear@0
|
731 ScopeGuard<aiMaterial> mat(new aiMaterial());
|
nuclear@0
|
732 while (ReadElementUpToClosing("mat")) {
|
nuclear@0
|
733 const std::string& s = GetElementName();
|
nuclear@0
|
734 if (s == "amb") {
|
nuclear@0
|
735 const aiColor3D c = ReadCol3();
|
nuclear@0
|
736 mat->AddProperty(&c,1,AI_MATKEY_COLOR_AMBIENT);
|
nuclear@0
|
737 }
|
nuclear@0
|
738 else if (s == "diff") {
|
nuclear@0
|
739 const aiColor3D c = ReadCol3();
|
nuclear@0
|
740 mat->AddProperty(&c,1,AI_MATKEY_COLOR_DIFFUSE);
|
nuclear@0
|
741 }
|
nuclear@0
|
742 else if (s == "spec") {
|
nuclear@0
|
743 const aiColor3D c = ReadCol3();
|
nuclear@0
|
744 mat->AddProperty(&c,1,AI_MATKEY_COLOR_SPECULAR);
|
nuclear@0
|
745 }
|
nuclear@0
|
746 else if (s == "emiss") {
|
nuclear@0
|
747 const aiColor3D c = ReadCol3();
|
nuclear@0
|
748 mat->AddProperty(&c,1,AI_MATKEY_COLOR_EMISSIVE);
|
nuclear@0
|
749 }
|
nuclear@0
|
750 else if (s == "alpha") {
|
nuclear@0
|
751 const float f = ReadFloat();
|
nuclear@0
|
752 mat->AddProperty(&f,1,AI_MATKEY_OPACITY);
|
nuclear@0
|
753 }
|
nuclear@0
|
754 else if (s == "shine") {
|
nuclear@0
|
755 const float f = ReadFloat();
|
nuclear@0
|
756 mat->AddProperty(&f,1,AI_MATKEY_SHININESS);
|
nuclear@0
|
757 }
|
nuclear@0
|
758 }
|
nuclear@0
|
759
|
nuclear@0
|
760 scope.materials[mat_id] = mat;
|
nuclear@0
|
761 scope.materials_linear.push_back(mat.dismiss());
|
nuclear@0
|
762 }
|
nuclear@0
|
763
|
nuclear@0
|
764
|
nuclear@0
|
765 // ----------------------------------------------------------------------------------------------
|
nuclear@0
|
766 void XGLImporter::ReadFaceVertex(const TempMesh& t, TempFace& out)
|
nuclear@0
|
767 {
|
nuclear@0
|
768 const std::string& end = GetElementName();
|
nuclear@0
|
769
|
nuclear@0
|
770 bool havep = false;
|
nuclear@0
|
771 while (ReadElementUpToClosing(end.c_str())) {
|
nuclear@0
|
772 const std::string& s = GetElementName();
|
nuclear@0
|
773 if (s == "pref") {
|
nuclear@0
|
774 const unsigned int id = ReadIndexFromText();
|
nuclear@0
|
775 std::map<unsigned int, aiVector3D>::const_iterator it = t.points.find(id);
|
nuclear@0
|
776 if (it == t.points.end()) {
|
nuclear@0
|
777 ThrowException("point index out of range");
|
nuclear@0
|
778 }
|
nuclear@0
|
779
|
nuclear@0
|
780 out.pos = (*it).second;
|
nuclear@0
|
781 havep = true;
|
nuclear@0
|
782 }
|
nuclear@0
|
783 else if (s == "nref") {
|
nuclear@0
|
784 const unsigned int id = ReadIndexFromText();
|
nuclear@0
|
785 std::map<unsigned int, aiVector3D>::const_iterator it = t.normals.find(id);
|
nuclear@0
|
786 if (it == t.normals.end()) {
|
nuclear@0
|
787 ThrowException("normal index out of range");
|
nuclear@0
|
788 }
|
nuclear@0
|
789
|
nuclear@0
|
790 out.normal = (*it).second;
|
nuclear@0
|
791 out.has_normal = true;
|
nuclear@0
|
792 }
|
nuclear@0
|
793 else if (s == "tcref") {
|
nuclear@0
|
794 const unsigned int id = ReadIndexFromText();
|
nuclear@0
|
795 std::map<unsigned int, aiVector2D>::const_iterator it = t.uvs.find(id);
|
nuclear@0
|
796 if (it == t.uvs.end()) {
|
nuclear@0
|
797 ThrowException("uv index out of range");
|
nuclear@0
|
798 }
|
nuclear@0
|
799
|
nuclear@0
|
800 out.uv = (*it).second;
|
nuclear@0
|
801 out.has_uv = true;
|
nuclear@0
|
802 }
|
nuclear@0
|
803 else if (s == "p") {
|
nuclear@0
|
804 out.pos = ReadVec3();
|
nuclear@0
|
805 }
|
nuclear@0
|
806 else if (s == "n") {
|
nuclear@0
|
807 out.normal = ReadVec3();
|
nuclear@0
|
808 }
|
nuclear@0
|
809 else if (s == "tc") {
|
nuclear@0
|
810 out.uv = ReadVec2();
|
nuclear@0
|
811 }
|
nuclear@0
|
812 }
|
nuclear@0
|
813
|
nuclear@0
|
814 if (!havep) {
|
nuclear@0
|
815 ThrowException("missing <pref> in <fvN> element");
|
nuclear@0
|
816 }
|
nuclear@0
|
817 }
|
nuclear@0
|
818
|
nuclear@0
|
819 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
820 unsigned int XGLImporter::ReadIDAttr()
|
nuclear@0
|
821 {
|
nuclear@0
|
822 for(int i = 0, e = reader->getAttributeCount(); i < e; ++i) {
|
nuclear@0
|
823
|
nuclear@0
|
824 if(!ASSIMP_stricmp(reader->getAttributeName(i),"id")) {
|
nuclear@0
|
825 return reader->getAttributeValueAsInt(i);
|
nuclear@0
|
826 }
|
nuclear@0
|
827 }
|
nuclear@0
|
828 return ~0u;
|
nuclear@0
|
829 }
|
nuclear@0
|
830
|
nuclear@0
|
831 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
832 float XGLImporter::ReadFloat()
|
nuclear@0
|
833 {
|
nuclear@0
|
834 if(!SkipToText()) {
|
nuclear@0
|
835 LogError("unexpected EOF reading float element contents");
|
nuclear@0
|
836 return 0.f;
|
nuclear@0
|
837 }
|
nuclear@0
|
838 const char* s = reader->getNodeData(), *se;
|
nuclear@0
|
839
|
nuclear@0
|
840 if(!SkipSpaces(&s)) {
|
nuclear@0
|
841 LogError("unexpected EOL, failed to parse float");
|
nuclear@0
|
842 return 0.f;
|
nuclear@0
|
843 }
|
nuclear@0
|
844
|
nuclear@0
|
845 float t;
|
nuclear@0
|
846 se = fast_atoreal_move(s,t);
|
nuclear@0
|
847
|
nuclear@0
|
848 if (se == s) {
|
nuclear@0
|
849 LogError("failed to read float text");
|
nuclear@0
|
850 return 0.f;
|
nuclear@0
|
851 }
|
nuclear@0
|
852
|
nuclear@0
|
853 return t;
|
nuclear@0
|
854 }
|
nuclear@0
|
855
|
nuclear@0
|
856 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
857 unsigned int XGLImporter::ReadIndexFromText()
|
nuclear@0
|
858 {
|
nuclear@0
|
859 if(!SkipToText()) {
|
nuclear@0
|
860 LogError("unexpected EOF reading index element contents");
|
nuclear@0
|
861 return ~0u;
|
nuclear@0
|
862 }
|
nuclear@0
|
863 const char* s = reader->getNodeData(), *se;
|
nuclear@0
|
864 if(!SkipSpaces(&s)) {
|
nuclear@0
|
865 LogError("unexpected EOL, failed to parse index element");
|
nuclear@0
|
866 return ~0u;
|
nuclear@0
|
867 }
|
nuclear@0
|
868
|
nuclear@0
|
869 const unsigned int t = strtoul10(s,&se);
|
nuclear@0
|
870
|
nuclear@0
|
871 if (se == s) {
|
nuclear@0
|
872 LogError("failed to read index");
|
nuclear@0
|
873 return ~0u;
|
nuclear@0
|
874 }
|
nuclear@0
|
875
|
nuclear@0
|
876 return t;
|
nuclear@0
|
877 }
|
nuclear@0
|
878
|
nuclear@0
|
879 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
880 aiVector2D XGLImporter::ReadVec2()
|
nuclear@0
|
881 {
|
nuclear@0
|
882 aiVector2D vec;
|
nuclear@0
|
883
|
nuclear@0
|
884 if(!SkipToText()) {
|
nuclear@0
|
885 LogError("unexpected EOF reading vec2 contents");
|
nuclear@0
|
886 return vec;
|
nuclear@0
|
887 }
|
nuclear@0
|
888 const char* s = reader->getNodeData();
|
nuclear@0
|
889
|
nuclear@0
|
890 for(int i = 0; i < 2; ++i) {
|
nuclear@0
|
891 if(!SkipSpaces(&s)) {
|
nuclear@0
|
892 LogError("unexpected EOL, failed to parse vec2");
|
nuclear@0
|
893 return vec;
|
nuclear@0
|
894 }
|
nuclear@0
|
895 vec[i] = fast_atof(&s);
|
nuclear@0
|
896
|
nuclear@0
|
897 SkipSpaces(&s);
|
nuclear@0
|
898 if (i != 1 && *s != ',') {
|
nuclear@0
|
899 LogError("expected comma, failed to parse vec2");
|
nuclear@0
|
900 return vec;
|
nuclear@0
|
901 }
|
nuclear@0
|
902 ++s;
|
nuclear@0
|
903 }
|
nuclear@0
|
904
|
nuclear@0
|
905 return vec;
|
nuclear@0
|
906 }
|
nuclear@0
|
907
|
nuclear@0
|
908 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
909 aiVector3D XGLImporter::ReadVec3()
|
nuclear@0
|
910 {
|
nuclear@0
|
911 aiVector3D vec;
|
nuclear@0
|
912
|
nuclear@0
|
913 if(!SkipToText()) {
|
nuclear@0
|
914 LogError("unexpected EOF reading vec3 contents");
|
nuclear@0
|
915 return vec;
|
nuclear@0
|
916 }
|
nuclear@0
|
917 const char* s = reader->getNodeData();
|
nuclear@0
|
918
|
nuclear@0
|
919 for(int i = 0; i < 3; ++i) {
|
nuclear@0
|
920 if(!SkipSpaces(&s)) {
|
nuclear@0
|
921 LogError("unexpected EOL, failed to parse vec3");
|
nuclear@0
|
922 return vec;
|
nuclear@0
|
923 }
|
nuclear@0
|
924 vec[i] = fast_atof(&s);
|
nuclear@0
|
925
|
nuclear@0
|
926 SkipSpaces(&s);
|
nuclear@0
|
927 if (i != 2 && *s != ',') {
|
nuclear@0
|
928 LogError("expected comma, failed to parse vec3");
|
nuclear@0
|
929 return vec;
|
nuclear@0
|
930 }
|
nuclear@0
|
931 ++s;
|
nuclear@0
|
932 }
|
nuclear@0
|
933
|
nuclear@0
|
934 return vec;
|
nuclear@0
|
935 }
|
nuclear@0
|
936
|
nuclear@0
|
937 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
938 aiColor3D XGLImporter::ReadCol3()
|
nuclear@0
|
939 {
|
nuclear@0
|
940 const aiVector3D& v = ReadVec3();
|
nuclear@0
|
941 if (v.x < 0.f || v.x > 1.0f || v.y < 0.f || v.y > 1.0f || v.z < 0.f || v.z > 1.0f) {
|
nuclear@0
|
942 LogWarn("color values out of range, ignoring");
|
nuclear@0
|
943 }
|
nuclear@0
|
944 return aiColor3D(v.x,v.y,v.z);
|
nuclear@0
|
945 }
|
nuclear@0
|
946
|
nuclear@0
|
947 #endif
|