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 Importer.cpp
|
nuclear@0
|
43 * @brief Implementation of the CPP-API class #Importer
|
nuclear@0
|
44 */
|
nuclear@0
|
45
|
nuclear@0
|
46 #include "AssimpPCH.h"
|
nuclear@0
|
47 #include "assimp/version.h"
|
nuclear@0
|
48
|
nuclear@0
|
49 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
50 /* Uncomment this line to prevent Assimp from catching unknown exceptions.
|
nuclear@0
|
51 *
|
nuclear@0
|
52 * Note that any Exception except DeadlyImportError may lead to
|
nuclear@0
|
53 * undefined behaviour -> loaders could remain in an unusable state and
|
nuclear@0
|
54 * further imports with the same Importer instance could fail/crash/burn ...
|
nuclear@0
|
55 */
|
nuclear@0
|
56 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
57 #ifndef ASSIMP_BUILD_DEBUG
|
nuclear@0
|
58 # define ASSIMP_CATCH_GLOBAL_EXCEPTIONS
|
nuclear@0
|
59 #endif
|
nuclear@0
|
60
|
nuclear@0
|
61 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
62 // Internal headers
|
nuclear@0
|
63 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
64 #include "Importer.h"
|
nuclear@0
|
65 #include "BaseProcess.h"
|
nuclear@0
|
66
|
nuclear@0
|
67 #include "DefaultIOStream.h"
|
nuclear@0
|
68 #include "DefaultIOSystem.h"
|
nuclear@0
|
69 #include "DefaultProgressHandler.h"
|
nuclear@0
|
70 #include "GenericProperty.h"
|
nuclear@0
|
71 #include "ProcessHelper.h"
|
nuclear@0
|
72 #include "ScenePreprocessor.h"
|
nuclear@0
|
73 #include "MemoryIOWrapper.h"
|
nuclear@0
|
74 #include "Profiler.h"
|
nuclear@0
|
75 #include "TinyFormatter.h"
|
nuclear@0
|
76
|
nuclear@0
|
77 #ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
|
nuclear@0
|
78 # include "ValidateDataStructure.h"
|
nuclear@0
|
79 #endif
|
nuclear@0
|
80
|
nuclear@0
|
81 using namespace Assimp::Profiling;
|
nuclear@0
|
82 using namespace Assimp::Formatter;
|
nuclear@0
|
83
|
nuclear@0
|
84 namespace Assimp {
|
nuclear@0
|
85 // ImporterRegistry.cpp
|
nuclear@0
|
86 void GetImporterInstanceList(std::vector< BaseImporter* >& out);
|
nuclear@0
|
87 // PostStepRegistry.cpp
|
nuclear@0
|
88 void GetPostProcessingStepInstanceList(std::vector< BaseProcess* >& out);
|
nuclear@0
|
89 }
|
nuclear@0
|
90
|
nuclear@0
|
91 using namespace Assimp;
|
nuclear@0
|
92 using namespace Assimp::Intern;
|
nuclear@0
|
93
|
nuclear@0
|
94 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
95 // Intern::AllocateFromAssimpHeap serves as abstract base class. It overrides
|
nuclear@0
|
96 // new and delete (and their array counterparts) of public API classes (e.g. Logger) to
|
nuclear@0
|
97 // utilize our DLL heap.
|
nuclear@0
|
98 // See http://www.gotw.ca/publications/mill15.htm
|
nuclear@0
|
99 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
100 void* AllocateFromAssimpHeap::operator new ( size_t num_bytes) {
|
nuclear@0
|
101 return ::operator new(num_bytes);
|
nuclear@0
|
102 }
|
nuclear@0
|
103
|
nuclear@0
|
104 void* AllocateFromAssimpHeap::operator new ( size_t num_bytes, const std::nothrow_t& ) throw() {
|
nuclear@0
|
105 try {
|
nuclear@0
|
106 return AllocateFromAssimpHeap::operator new( num_bytes );
|
nuclear@0
|
107 }
|
nuclear@0
|
108 catch( ... ) {
|
nuclear@0
|
109 return NULL;
|
nuclear@0
|
110 }
|
nuclear@0
|
111 }
|
nuclear@0
|
112
|
nuclear@0
|
113 void AllocateFromAssimpHeap::operator delete ( void* data) {
|
nuclear@0
|
114 return ::operator delete(data);
|
nuclear@0
|
115 }
|
nuclear@0
|
116
|
nuclear@0
|
117 void* AllocateFromAssimpHeap::operator new[] ( size_t num_bytes) {
|
nuclear@0
|
118 return ::operator new[](num_bytes);
|
nuclear@0
|
119 }
|
nuclear@0
|
120
|
nuclear@0
|
121 void* AllocateFromAssimpHeap::operator new[] ( size_t num_bytes, const std::nothrow_t& ) throw() {
|
nuclear@0
|
122 try {
|
nuclear@0
|
123 return AllocateFromAssimpHeap::operator new[]( num_bytes );
|
nuclear@0
|
124 }
|
nuclear@0
|
125 catch( ... ) {
|
nuclear@0
|
126 return NULL;
|
nuclear@0
|
127 }
|
nuclear@0
|
128 }
|
nuclear@0
|
129
|
nuclear@0
|
130 void AllocateFromAssimpHeap::operator delete[] ( void* data) {
|
nuclear@0
|
131 return ::operator delete[](data);
|
nuclear@0
|
132 }
|
nuclear@0
|
133
|
nuclear@0
|
134 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
135 // Importer constructor.
|
nuclear@0
|
136 Importer::Importer()
|
nuclear@0
|
137 {
|
nuclear@0
|
138 // allocate the pimpl first
|
nuclear@0
|
139 pimpl = new ImporterPimpl();
|
nuclear@0
|
140
|
nuclear@0
|
141 pimpl->mScene = NULL;
|
nuclear@0
|
142 pimpl->mErrorString = "";
|
nuclear@0
|
143
|
nuclear@0
|
144 // Allocate a default IO handler
|
nuclear@0
|
145 pimpl->mIOHandler = new DefaultIOSystem;
|
nuclear@0
|
146 pimpl->mIsDefaultHandler = true;
|
nuclear@0
|
147 pimpl->bExtraVerbose = false; // disable extra verbose mode by default
|
nuclear@0
|
148
|
nuclear@0
|
149 pimpl->mProgressHandler = new DefaultProgressHandler();
|
nuclear@0
|
150 pimpl->mIsDefaultProgressHandler = true;
|
nuclear@0
|
151
|
nuclear@0
|
152 GetImporterInstanceList(pimpl->mImporter);
|
nuclear@0
|
153 GetPostProcessingStepInstanceList(pimpl->mPostProcessingSteps);
|
nuclear@0
|
154
|
nuclear@0
|
155 // Allocate a SharedPostProcessInfo object and store pointers to it in all post-process steps in the list.
|
nuclear@0
|
156 pimpl->mPPShared = new SharedPostProcessInfo();
|
nuclear@0
|
157 for (std::vector<BaseProcess*>::iterator it = pimpl->mPostProcessingSteps.begin();
|
nuclear@0
|
158 it != pimpl->mPostProcessingSteps.end();
|
nuclear@0
|
159 ++it) {
|
nuclear@0
|
160
|
nuclear@0
|
161 (*it)->SetSharedData(pimpl->mPPShared);
|
nuclear@0
|
162 }
|
nuclear@0
|
163 }
|
nuclear@0
|
164
|
nuclear@0
|
165 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
166 // Destructor of Importer
|
nuclear@0
|
167 Importer::~Importer()
|
nuclear@0
|
168 {
|
nuclear@0
|
169 // Delete all import plugins
|
nuclear@0
|
170 for( unsigned int a = 0; a < pimpl->mImporter.size(); a++)
|
nuclear@0
|
171 delete pimpl->mImporter[a];
|
nuclear@0
|
172
|
nuclear@0
|
173 // Delete all post-processing plug-ins
|
nuclear@0
|
174 for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++)
|
nuclear@0
|
175 delete pimpl->mPostProcessingSteps[a];
|
nuclear@0
|
176
|
nuclear@0
|
177 // Delete the assigned IO and progress handler
|
nuclear@0
|
178 delete pimpl->mIOHandler;
|
nuclear@0
|
179 delete pimpl->mProgressHandler;
|
nuclear@0
|
180
|
nuclear@0
|
181 // Kill imported scene. Destructors should do that recursivly
|
nuclear@0
|
182 delete pimpl->mScene;
|
nuclear@0
|
183
|
nuclear@0
|
184 // Delete shared post-processing data
|
nuclear@0
|
185 delete pimpl->mPPShared;
|
nuclear@0
|
186
|
nuclear@0
|
187 // and finally the pimpl itself
|
nuclear@0
|
188 delete pimpl;
|
nuclear@0
|
189 }
|
nuclear@0
|
190
|
nuclear@0
|
191 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
192 // Copy constructor - copies the config of another Importer, not the scene
|
nuclear@0
|
193 Importer::Importer(const Importer &other)
|
nuclear@0
|
194 {
|
nuclear@0
|
195 new(this) Importer();
|
nuclear@0
|
196
|
nuclear@0
|
197 pimpl->mIntProperties = other.pimpl->mIntProperties;
|
nuclear@0
|
198 pimpl->mFloatProperties = other.pimpl->mFloatProperties;
|
nuclear@0
|
199 pimpl->mStringProperties = other.pimpl->mStringProperties;
|
nuclear@0
|
200 }
|
nuclear@0
|
201
|
nuclear@0
|
202 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
203 // Register a custom post-processing step
|
nuclear@0
|
204 aiReturn Importer::RegisterPPStep(BaseProcess* pImp)
|
nuclear@0
|
205 {
|
nuclear@0
|
206 ai_assert(NULL != pImp);
|
nuclear@0
|
207 ASSIMP_BEGIN_EXCEPTION_REGION();
|
nuclear@0
|
208
|
nuclear@0
|
209 pimpl->mPostProcessingSteps.push_back(pImp);
|
nuclear@0
|
210 DefaultLogger::get()->info("Registering custom post-processing step");
|
nuclear@0
|
211
|
nuclear@0
|
212 ASSIMP_END_EXCEPTION_REGION(aiReturn);
|
nuclear@0
|
213 return AI_SUCCESS;
|
nuclear@0
|
214 }
|
nuclear@0
|
215
|
nuclear@0
|
216 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
217 // Register a custom loader plugin
|
nuclear@0
|
218 aiReturn Importer::RegisterLoader(BaseImporter* pImp)
|
nuclear@0
|
219 {
|
nuclear@0
|
220 ai_assert(NULL != pImp);
|
nuclear@0
|
221 ASSIMP_BEGIN_EXCEPTION_REGION();
|
nuclear@0
|
222
|
nuclear@0
|
223 // --------------------------------------------------------------------
|
nuclear@0
|
224 // Check whether we would have two loaders for the same file extension
|
nuclear@0
|
225 // This is absolutely OK, but we should warn the developer of the new
|
nuclear@0
|
226 // loader that his code will probably never be called if the first
|
nuclear@0
|
227 // loader is a bit too lazy in his file checking.
|
nuclear@0
|
228 // --------------------------------------------------------------------
|
nuclear@0
|
229 std::set<std::string> st;
|
nuclear@0
|
230 std::string baked;
|
nuclear@0
|
231 pImp->GetExtensionList(st);
|
nuclear@0
|
232
|
nuclear@0
|
233 for(std::set<std::string>::const_iterator it = st.begin(); it != st.end(); ++it) {
|
nuclear@0
|
234
|
nuclear@0
|
235 #ifdef _DEBUG
|
nuclear@0
|
236 if (IsExtensionSupported(*it)) {
|
nuclear@0
|
237 DefaultLogger::get()->warn("The file extension " + *it + " is already in use");
|
nuclear@0
|
238 }
|
nuclear@0
|
239 #endif
|
nuclear@0
|
240 baked += *it;
|
nuclear@0
|
241 }
|
nuclear@0
|
242
|
nuclear@0
|
243 // add the loader
|
nuclear@0
|
244 pimpl->mImporter.push_back(pImp);
|
nuclear@0
|
245 DefaultLogger::get()->info("Registering custom importer for these file extensions: " + baked);
|
nuclear@0
|
246 ASSIMP_END_EXCEPTION_REGION(aiReturn);
|
nuclear@0
|
247 return AI_SUCCESS;
|
nuclear@0
|
248 }
|
nuclear@0
|
249
|
nuclear@0
|
250 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
251 // Unregister a custom loader plugin
|
nuclear@0
|
252 aiReturn Importer::UnregisterLoader(BaseImporter* pImp)
|
nuclear@0
|
253 {
|
nuclear@0
|
254 if(!pImp) {
|
nuclear@0
|
255 // unregistering a NULL importer is no problem for us ... really!
|
nuclear@0
|
256 return AI_SUCCESS;
|
nuclear@0
|
257 }
|
nuclear@0
|
258
|
nuclear@0
|
259 ASSIMP_BEGIN_EXCEPTION_REGION();
|
nuclear@0
|
260 std::vector<BaseImporter*>::iterator it = std::find(pimpl->mImporter.begin(),
|
nuclear@0
|
261 pimpl->mImporter.end(),pImp);
|
nuclear@0
|
262
|
nuclear@0
|
263 if (it != pimpl->mImporter.end()) {
|
nuclear@0
|
264 pimpl->mImporter.erase(it);
|
nuclear@0
|
265
|
nuclear@0
|
266 std::set<std::string> st;
|
nuclear@0
|
267 pImp->GetExtensionList(st);
|
nuclear@0
|
268
|
nuclear@0
|
269 DefaultLogger::get()->info("Unregistering custom importer: ");
|
nuclear@0
|
270 return AI_SUCCESS;
|
nuclear@0
|
271 }
|
nuclear@0
|
272 DefaultLogger::get()->warn("Unable to remove custom importer: I can't find you ...");
|
nuclear@0
|
273 ASSIMP_END_EXCEPTION_REGION(aiReturn);
|
nuclear@0
|
274 return AI_FAILURE;
|
nuclear@0
|
275 }
|
nuclear@0
|
276
|
nuclear@0
|
277 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
278 // Unregister a custom loader plugin
|
nuclear@0
|
279 aiReturn Importer::UnregisterPPStep(BaseProcess* pImp)
|
nuclear@0
|
280 {
|
nuclear@0
|
281 if(!pImp) {
|
nuclear@0
|
282 // unregistering a NULL ppstep is no problem for us ... really!
|
nuclear@0
|
283 return AI_SUCCESS;
|
nuclear@0
|
284 }
|
nuclear@0
|
285
|
nuclear@0
|
286 ASSIMP_BEGIN_EXCEPTION_REGION();
|
nuclear@0
|
287 std::vector<BaseProcess*>::iterator it = std::find(pimpl->mPostProcessingSteps.begin(),
|
nuclear@0
|
288 pimpl->mPostProcessingSteps.end(),pImp);
|
nuclear@0
|
289
|
nuclear@0
|
290 if (it != pimpl->mPostProcessingSteps.end()) {
|
nuclear@0
|
291 pimpl->mPostProcessingSteps.erase(it);
|
nuclear@0
|
292 DefaultLogger::get()->info("Unregistering custom post-processing step");
|
nuclear@0
|
293 return AI_SUCCESS;
|
nuclear@0
|
294 }
|
nuclear@0
|
295 DefaultLogger::get()->warn("Unable to remove custom post-processing step: I can't find you ..");
|
nuclear@0
|
296 ASSIMP_END_EXCEPTION_REGION(aiReturn);
|
nuclear@0
|
297 return AI_FAILURE;
|
nuclear@0
|
298 }
|
nuclear@0
|
299
|
nuclear@0
|
300 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
301 // Supplies a custom IO handler to the importer to open and access files.
|
nuclear@0
|
302 void Importer::SetIOHandler( IOSystem* pIOHandler)
|
nuclear@0
|
303 {
|
nuclear@0
|
304 ASSIMP_BEGIN_EXCEPTION_REGION();
|
nuclear@0
|
305 // If the new handler is zero, allocate a default IO implementation.
|
nuclear@0
|
306 if (!pIOHandler)
|
nuclear@0
|
307 {
|
nuclear@0
|
308 // Release pointer in the possession of the caller
|
nuclear@0
|
309 pimpl->mIOHandler = new DefaultIOSystem();
|
nuclear@0
|
310 pimpl->mIsDefaultHandler = true;
|
nuclear@0
|
311 }
|
nuclear@0
|
312 // Otherwise register the custom handler
|
nuclear@0
|
313 else if (pimpl->mIOHandler != pIOHandler)
|
nuclear@0
|
314 {
|
nuclear@0
|
315 delete pimpl->mIOHandler;
|
nuclear@0
|
316 pimpl->mIOHandler = pIOHandler;
|
nuclear@0
|
317 pimpl->mIsDefaultHandler = false;
|
nuclear@0
|
318 }
|
nuclear@0
|
319 ASSIMP_END_EXCEPTION_REGION(void);
|
nuclear@0
|
320 }
|
nuclear@0
|
321
|
nuclear@0
|
322 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
323 // Get the currently set IO handler
|
nuclear@0
|
324 IOSystem* Importer::GetIOHandler() const
|
nuclear@0
|
325 {
|
nuclear@0
|
326 return pimpl->mIOHandler;
|
nuclear@0
|
327 }
|
nuclear@0
|
328
|
nuclear@0
|
329 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
330 // Check whether a custom IO handler is currently set
|
nuclear@0
|
331 bool Importer::IsDefaultIOHandler() const
|
nuclear@0
|
332 {
|
nuclear@0
|
333 return pimpl->mIsDefaultHandler;
|
nuclear@0
|
334 }
|
nuclear@0
|
335
|
nuclear@0
|
336 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
337 // Supplies a custom progress handler to get regular callbacks during importing
|
nuclear@0
|
338 void Importer::SetProgressHandler ( ProgressHandler* pHandler )
|
nuclear@0
|
339 {
|
nuclear@0
|
340 ASSIMP_BEGIN_EXCEPTION_REGION();
|
nuclear@0
|
341 // If the new handler is zero, allocate a default implementation.
|
nuclear@0
|
342 if (!pHandler)
|
nuclear@0
|
343 {
|
nuclear@0
|
344 // Release pointer in the possession of the caller
|
nuclear@0
|
345 pimpl->mProgressHandler = new DefaultProgressHandler();
|
nuclear@0
|
346 pimpl->mIsDefaultProgressHandler = true;
|
nuclear@0
|
347 }
|
nuclear@0
|
348 // Otherwise register the custom handler
|
nuclear@0
|
349 else if (pimpl->mProgressHandler != pHandler)
|
nuclear@0
|
350 {
|
nuclear@0
|
351 delete pimpl->mProgressHandler;
|
nuclear@0
|
352 pimpl->mProgressHandler = pHandler;
|
nuclear@0
|
353 pimpl->mIsDefaultProgressHandler = false;
|
nuclear@0
|
354 }
|
nuclear@0
|
355 ASSIMP_END_EXCEPTION_REGION(void);
|
nuclear@0
|
356 }
|
nuclear@0
|
357
|
nuclear@0
|
358 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
359 // Get the currently set progress handler
|
nuclear@0
|
360 ProgressHandler* Importer::GetProgressHandler() const
|
nuclear@0
|
361 {
|
nuclear@0
|
362 return pimpl->mProgressHandler;
|
nuclear@0
|
363 }
|
nuclear@0
|
364
|
nuclear@0
|
365 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
366 // Check whether a custom progress handler is currently set
|
nuclear@0
|
367 bool Importer::IsDefaultProgressHandler() const
|
nuclear@0
|
368 {
|
nuclear@0
|
369 return pimpl->mIsDefaultProgressHandler;
|
nuclear@0
|
370 }
|
nuclear@0
|
371
|
nuclear@0
|
372 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
373 // Validate post process step flags
|
nuclear@0
|
374 bool _ValidateFlags(unsigned int pFlags)
|
nuclear@0
|
375 {
|
nuclear@0
|
376 if (pFlags & aiProcess_GenSmoothNormals && pFlags & aiProcess_GenNormals) {
|
nuclear@0
|
377 DefaultLogger::get()->error("#aiProcess_GenSmoothNormals and #aiProcess_GenNormals are incompatible");
|
nuclear@0
|
378 return false;
|
nuclear@0
|
379 }
|
nuclear@0
|
380 if (pFlags & aiProcess_OptimizeGraph && pFlags & aiProcess_PreTransformVertices) {
|
nuclear@0
|
381 DefaultLogger::get()->error("#aiProcess_OptimizeGraph and #aiProcess_PreTransformVertices are incompatible");
|
nuclear@0
|
382 return false;
|
nuclear@0
|
383 }
|
nuclear@0
|
384 return true;
|
nuclear@0
|
385 }
|
nuclear@0
|
386
|
nuclear@0
|
387 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
388 // Free the current scene
|
nuclear@0
|
389 void Importer::FreeScene( )
|
nuclear@0
|
390 {
|
nuclear@0
|
391 ASSIMP_BEGIN_EXCEPTION_REGION();
|
nuclear@0
|
392 delete pimpl->mScene;
|
nuclear@0
|
393 pimpl->mScene = NULL;
|
nuclear@0
|
394
|
nuclear@0
|
395 pimpl->mErrorString = "";
|
nuclear@0
|
396 ASSIMP_END_EXCEPTION_REGION(void);
|
nuclear@0
|
397 }
|
nuclear@0
|
398
|
nuclear@0
|
399 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
400 // Get the current error string, if any
|
nuclear@0
|
401 const char* Importer::GetErrorString() const
|
nuclear@0
|
402 {
|
nuclear@0
|
403 /* Must remain valid as long as ReadFile() or FreeFile() are not called */
|
nuclear@0
|
404 return pimpl->mErrorString.c_str();
|
nuclear@0
|
405 }
|
nuclear@0
|
406
|
nuclear@0
|
407 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
408 // Enable extra-verbose mode
|
nuclear@0
|
409 void Importer::SetExtraVerbose(bool bDo)
|
nuclear@0
|
410 {
|
nuclear@0
|
411 pimpl->bExtraVerbose = bDo;
|
nuclear@0
|
412 }
|
nuclear@0
|
413
|
nuclear@0
|
414 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
415 // Get the current scene
|
nuclear@0
|
416 const aiScene* Importer::GetScene() const
|
nuclear@0
|
417 {
|
nuclear@0
|
418 return pimpl->mScene;
|
nuclear@0
|
419 }
|
nuclear@0
|
420
|
nuclear@0
|
421 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
422 // Orphan the current scene and return it.
|
nuclear@0
|
423 aiScene* Importer::GetOrphanedScene()
|
nuclear@0
|
424 {
|
nuclear@0
|
425 aiScene* s = pimpl->mScene;
|
nuclear@0
|
426
|
nuclear@0
|
427 ASSIMP_BEGIN_EXCEPTION_REGION();
|
nuclear@0
|
428 pimpl->mScene = NULL;
|
nuclear@0
|
429
|
nuclear@0
|
430 pimpl->mErrorString = ""; /* reset error string */
|
nuclear@0
|
431 ASSIMP_END_EXCEPTION_REGION(aiScene*);
|
nuclear@0
|
432 return s;
|
nuclear@0
|
433 }
|
nuclear@0
|
434
|
nuclear@0
|
435 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
436 // Validate post-processing flags
|
nuclear@0
|
437 bool Importer::ValidateFlags(unsigned int pFlags) const
|
nuclear@0
|
438 {
|
nuclear@0
|
439 ASSIMP_BEGIN_EXCEPTION_REGION();
|
nuclear@0
|
440 // run basic checks for mutually exclusive flags
|
nuclear@0
|
441 if(!_ValidateFlags(pFlags)) {
|
nuclear@0
|
442 return false;
|
nuclear@0
|
443 }
|
nuclear@0
|
444
|
nuclear@0
|
445 // ValidateDS does not anymore occur in the pp list, it plays an awesome extra role ...
|
nuclear@0
|
446 #ifdef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
|
nuclear@0
|
447 if (pFlags & aiProcess_ValidateDataStructure) {
|
nuclear@0
|
448 return false;
|
nuclear@0
|
449 }
|
nuclear@0
|
450 #endif
|
nuclear@0
|
451 pFlags &= ~aiProcess_ValidateDataStructure;
|
nuclear@0
|
452
|
nuclear@0
|
453 // Now iterate through all bits which are set in the flags and check whether we find at least
|
nuclear@0
|
454 // one pp plugin which handles it.
|
nuclear@0
|
455 for (unsigned int mask = 1; mask < (1u << (sizeof(unsigned int)*8-1));mask <<= 1) {
|
nuclear@0
|
456
|
nuclear@0
|
457 if (pFlags & mask) {
|
nuclear@0
|
458
|
nuclear@0
|
459 bool have = false;
|
nuclear@0
|
460 for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++) {
|
nuclear@0
|
461 if (pimpl->mPostProcessingSteps[a]-> IsActive(mask) ) {
|
nuclear@0
|
462
|
nuclear@0
|
463 have = true;
|
nuclear@0
|
464 break;
|
nuclear@0
|
465 }
|
nuclear@0
|
466 }
|
nuclear@0
|
467 if (!have) {
|
nuclear@0
|
468 return false;
|
nuclear@0
|
469 }
|
nuclear@0
|
470 }
|
nuclear@0
|
471 }
|
nuclear@0
|
472 ASSIMP_END_EXCEPTION_REGION(bool);
|
nuclear@0
|
473 return true;
|
nuclear@0
|
474 }
|
nuclear@0
|
475
|
nuclear@0
|
476 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
477 const aiScene* Importer::ReadFileFromMemory( const void* pBuffer,
|
nuclear@0
|
478 size_t pLength,
|
nuclear@0
|
479 unsigned int pFlags,
|
nuclear@0
|
480 const char* pHint /*= ""*/)
|
nuclear@0
|
481 {
|
nuclear@0
|
482 ASSIMP_BEGIN_EXCEPTION_REGION();
|
nuclear@0
|
483 if (!pHint) {
|
nuclear@0
|
484 pHint = "";
|
nuclear@0
|
485 }
|
nuclear@0
|
486
|
nuclear@0
|
487 if (!pBuffer || !pLength || strlen(pHint) > 100) {
|
nuclear@0
|
488 pimpl->mErrorString = "Invalid parameters passed to ReadFileFromMemory()";
|
nuclear@0
|
489 return NULL;
|
nuclear@0
|
490 }
|
nuclear@0
|
491
|
nuclear@0
|
492 // prevent deletion of the previous IOHandler
|
nuclear@0
|
493 IOSystem* io = pimpl->mIOHandler;
|
nuclear@0
|
494 pimpl->mIOHandler = NULL;
|
nuclear@0
|
495
|
nuclear@0
|
496 SetIOHandler(new MemoryIOSystem((const uint8_t*)pBuffer,pLength));
|
nuclear@0
|
497
|
nuclear@0
|
498 // read the file and recover the previous IOSystem
|
nuclear@0
|
499 char fbuff[128];
|
nuclear@0
|
500 sprintf(fbuff,"%s.%s",AI_MEMORYIO_MAGIC_FILENAME,pHint);
|
nuclear@0
|
501
|
nuclear@0
|
502 ReadFile(fbuff,pFlags);
|
nuclear@0
|
503 SetIOHandler(io);
|
nuclear@0
|
504
|
nuclear@0
|
505 ASSIMP_END_EXCEPTION_REGION(const aiScene*);
|
nuclear@0
|
506 return pimpl->mScene;
|
nuclear@0
|
507 }
|
nuclear@0
|
508
|
nuclear@0
|
509 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
510 void WriteLogOpening(const std::string& file)
|
nuclear@0
|
511 {
|
nuclear@0
|
512 Logger* l = DefaultLogger::get();
|
nuclear@0
|
513 if (!l) {
|
nuclear@0
|
514 return;
|
nuclear@0
|
515 }
|
nuclear@0
|
516 l->info("Load " + file);
|
nuclear@0
|
517
|
nuclear@0
|
518 // print a full version dump. This is nice because we don't
|
nuclear@0
|
519 // need to ask the authors of incoming bug reports for
|
nuclear@0
|
520 // the library version they're using - a log dump is
|
nuclear@0
|
521 // sufficient.
|
nuclear@0
|
522 const unsigned int flags = aiGetCompileFlags();
|
nuclear@0
|
523 l->debug(format()
|
nuclear@0
|
524 << "Assimp "
|
nuclear@0
|
525 << aiGetVersionMajor()
|
nuclear@0
|
526 << "."
|
nuclear@0
|
527 << aiGetVersionMinor()
|
nuclear@0
|
528 << "."
|
nuclear@0
|
529 << aiGetVersionRevision()
|
nuclear@0
|
530
|
nuclear@0
|
531 << " "
|
nuclear@0
|
532 #if defined(ASSIMP_BUILD_ARCHITECTURE)
|
nuclear@0
|
533 << ASSIMP_BUILD_ARCHITECTURE
|
nuclear@0
|
534 #elif defined(_M_IX86) || defined(__x86_32__) || defined(__i386__)
|
nuclear@0
|
535 << "x86"
|
nuclear@0
|
536 #elif defined(_M_X64) || defined(__x86_64__)
|
nuclear@0
|
537 << "amd64"
|
nuclear@0
|
538 #elif defined(_M_IA64) || defined(__ia64__)
|
nuclear@0
|
539 << "itanium"
|
nuclear@0
|
540 #elif defined(__ppc__) || defined(__powerpc__)
|
nuclear@0
|
541 << "ppc32"
|
nuclear@0
|
542 #elif defined(__powerpc64__)
|
nuclear@0
|
543 << "ppc64"
|
nuclear@0
|
544 #elif defined(__arm__)
|
nuclear@0
|
545 << "arm"
|
nuclear@0
|
546 #else
|
nuclear@0
|
547 << "<unknown architecture>"
|
nuclear@0
|
548 #endif
|
nuclear@0
|
549
|
nuclear@0
|
550 << " "
|
nuclear@0
|
551 #if defined(ASSIMP_BUILD_COMPILER)
|
nuclear@0
|
552 << ASSIMP_BUILD_COMPILER
|
nuclear@0
|
553 #elif defined(_MSC_VER)
|
nuclear@0
|
554 << "msvc"
|
nuclear@0
|
555 #elif defined(__GNUC__)
|
nuclear@0
|
556 << "gcc"
|
nuclear@0
|
557 #else
|
nuclear@0
|
558 << "<unknown compiler>"
|
nuclear@0
|
559 #endif
|
nuclear@0
|
560
|
nuclear@0
|
561 #ifndef NDEBUG
|
nuclear@0
|
562 << " debug"
|
nuclear@0
|
563 #endif
|
nuclear@0
|
564
|
nuclear@0
|
565 << (flags & ASSIMP_CFLAGS_NOBOOST ? " noboost" : "")
|
nuclear@0
|
566 << (flags & ASSIMP_CFLAGS_SHARED ? " shared" : "")
|
nuclear@0
|
567 << (flags & ASSIMP_CFLAGS_SINGLETHREADED ? " singlethreaded" : "")
|
nuclear@0
|
568 );
|
nuclear@0
|
569 }
|
nuclear@0
|
570
|
nuclear@0
|
571 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
572 // Reads the given file and returns its contents if successful.
|
nuclear@0
|
573 const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags)
|
nuclear@0
|
574 {
|
nuclear@0
|
575 ASSIMP_BEGIN_EXCEPTION_REGION();
|
nuclear@0
|
576 const std::string pFile(_pFile);
|
nuclear@0
|
577
|
nuclear@0
|
578 // ----------------------------------------------------------------------
|
nuclear@0
|
579 // Put a large try block around everything to catch all std::exception's
|
nuclear@0
|
580 // that might be thrown by STL containers or by new().
|
nuclear@0
|
581 // ImportErrorException's are throw by ourselves and caught elsewhere.
|
nuclear@0
|
582 //-----------------------------------------------------------------------
|
nuclear@0
|
583
|
nuclear@0
|
584 WriteLogOpening(pFile);
|
nuclear@0
|
585
|
nuclear@0
|
586 #ifdef ASSIMP_CATCH_GLOBAL_EXCEPTIONS
|
nuclear@0
|
587 try
|
nuclear@0
|
588 #endif // ! ASSIMP_CATCH_GLOBAL_EXCEPTIONS
|
nuclear@0
|
589 {
|
nuclear@0
|
590 // Check whether this Importer instance has already loaded
|
nuclear@0
|
591 // a scene. In this case we need to delete the old one
|
nuclear@0
|
592 if (pimpl->mScene) {
|
nuclear@0
|
593
|
nuclear@0
|
594 DefaultLogger::get()->debug("(Deleting previous scene)");
|
nuclear@0
|
595 FreeScene();
|
nuclear@0
|
596 }
|
nuclear@0
|
597
|
nuclear@0
|
598 // First check if the file is accessable at all
|
nuclear@0
|
599 if( !pimpl->mIOHandler->Exists( pFile)) {
|
nuclear@0
|
600
|
nuclear@0
|
601 pimpl->mErrorString = "Unable to open file \"" + pFile + "\".";
|
nuclear@0
|
602 DefaultLogger::get()->error(pimpl->mErrorString);
|
nuclear@0
|
603 return NULL;
|
nuclear@0
|
604 }
|
nuclear@0
|
605
|
nuclear@0
|
606 boost::scoped_ptr<Profiler> profiler(GetPropertyInteger(AI_CONFIG_GLOB_MEASURE_TIME,0)?new Profiler():NULL);
|
nuclear@0
|
607 if (profiler) {
|
nuclear@0
|
608 profiler->BeginRegion("total");
|
nuclear@0
|
609 }
|
nuclear@0
|
610
|
nuclear@0
|
611 // Find an worker class which can handle the file
|
nuclear@0
|
612 BaseImporter* imp = NULL;
|
nuclear@0
|
613 for( unsigned int a = 0; a < pimpl->mImporter.size(); a++) {
|
nuclear@0
|
614
|
nuclear@0
|
615 if( pimpl->mImporter[a]->CanRead( pFile, pimpl->mIOHandler, false)) {
|
nuclear@0
|
616 imp = pimpl->mImporter[a];
|
nuclear@0
|
617 break;
|
nuclear@0
|
618 }
|
nuclear@0
|
619 }
|
nuclear@0
|
620
|
nuclear@0
|
621 if (!imp) {
|
nuclear@0
|
622 // not so bad yet ... try format auto detection.
|
nuclear@0
|
623 const std::string::size_type s = pFile.find_last_of('.');
|
nuclear@0
|
624 if (s != std::string::npos) {
|
nuclear@0
|
625 DefaultLogger::get()->info("File extension not known, trying signature-based detection");
|
nuclear@0
|
626 for( unsigned int a = 0; a < pimpl->mImporter.size(); a++) {
|
nuclear@0
|
627
|
nuclear@0
|
628 if( pimpl->mImporter[a]->CanRead( pFile, pimpl->mIOHandler, true)) {
|
nuclear@0
|
629 imp = pimpl->mImporter[a];
|
nuclear@0
|
630 break;
|
nuclear@0
|
631 }
|
nuclear@0
|
632 }
|
nuclear@0
|
633 }
|
nuclear@0
|
634 // Put a proper error message if no suitable importer was found
|
nuclear@0
|
635 if( !imp) {
|
nuclear@0
|
636 pimpl->mErrorString = "No suitable reader found for the file format of file \"" + pFile + "\".";
|
nuclear@0
|
637 DefaultLogger::get()->error(pimpl->mErrorString);
|
nuclear@0
|
638 return NULL;
|
nuclear@0
|
639 }
|
nuclear@0
|
640 }
|
nuclear@0
|
641
|
nuclear@0
|
642 // Dispatch the reading to the worker class for this format
|
nuclear@0
|
643 DefaultLogger::get()->info("Found a matching importer for this file format");
|
nuclear@0
|
644 pimpl->mProgressHandler->Update();
|
nuclear@0
|
645
|
nuclear@0
|
646 if (profiler) {
|
nuclear@0
|
647 profiler->BeginRegion("import");
|
nuclear@0
|
648 }
|
nuclear@0
|
649
|
nuclear@0
|
650 pimpl->mScene = imp->ReadFile( this, pFile, pimpl->mIOHandler);
|
nuclear@0
|
651 pimpl->mProgressHandler->Update();
|
nuclear@0
|
652
|
nuclear@0
|
653 if (profiler) {
|
nuclear@0
|
654 profiler->EndRegion("import");
|
nuclear@0
|
655 }
|
nuclear@0
|
656
|
nuclear@0
|
657 // If successful, apply all active post processing steps to the imported data
|
nuclear@0
|
658 if( pimpl->mScene) {
|
nuclear@0
|
659
|
nuclear@0
|
660 #ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
|
nuclear@0
|
661 // The ValidateDS process is an exception. It is executed first, even before ScenePreprocessor is called.
|
nuclear@0
|
662 if (pFlags & aiProcess_ValidateDataStructure)
|
nuclear@0
|
663 {
|
nuclear@0
|
664 ValidateDSProcess ds;
|
nuclear@0
|
665 ds.ExecuteOnScene (this);
|
nuclear@0
|
666 if (!pimpl->mScene) {
|
nuclear@0
|
667 return NULL;
|
nuclear@0
|
668 }
|
nuclear@0
|
669 }
|
nuclear@0
|
670 #endif // no validation
|
nuclear@0
|
671
|
nuclear@0
|
672 // Preprocess the scene and prepare it for post-processing
|
nuclear@0
|
673 if (profiler) {
|
nuclear@0
|
674 profiler->BeginRegion("preprocess");
|
nuclear@0
|
675 }
|
nuclear@0
|
676
|
nuclear@0
|
677 ScenePreprocessor pre(pimpl->mScene);
|
nuclear@0
|
678 pre.ProcessScene();
|
nuclear@0
|
679
|
nuclear@0
|
680 pimpl->mProgressHandler->Update();
|
nuclear@0
|
681 if (profiler) {
|
nuclear@0
|
682 profiler->EndRegion("preprocess");
|
nuclear@0
|
683 }
|
nuclear@0
|
684
|
nuclear@0
|
685 // Ensure that the validation process won't be called twice
|
nuclear@0
|
686 ApplyPostProcessing(pFlags & (~aiProcess_ValidateDataStructure));
|
nuclear@0
|
687 }
|
nuclear@0
|
688 // if failed, extract the error string
|
nuclear@0
|
689 else if( !pimpl->mScene) {
|
nuclear@0
|
690 pimpl->mErrorString = imp->GetErrorText();
|
nuclear@0
|
691 }
|
nuclear@0
|
692
|
nuclear@0
|
693 // clear any data allocated by post-process steps
|
nuclear@0
|
694 pimpl->mPPShared->Clean();
|
nuclear@0
|
695
|
nuclear@0
|
696 if (profiler) {
|
nuclear@0
|
697 profiler->EndRegion("total");
|
nuclear@0
|
698 }
|
nuclear@0
|
699 }
|
nuclear@0
|
700 #ifdef ASSIMP_CATCH_GLOBAL_EXCEPTIONS
|
nuclear@0
|
701 catch (std::exception &e)
|
nuclear@0
|
702 {
|
nuclear@0
|
703 #if (defined _MSC_VER) && (defined _CPPRTTI)
|
nuclear@0
|
704 // if we have RTTI get the full name of the exception that occured
|
nuclear@0
|
705 pimpl->mErrorString = std::string(typeid( e ).name()) + ": " + e.what();
|
nuclear@0
|
706 #else
|
nuclear@0
|
707 pimpl->mErrorString = std::string("std::exception: ") + e.what();
|
nuclear@0
|
708 #endif
|
nuclear@0
|
709
|
nuclear@0
|
710 DefaultLogger::get()->error(pimpl->mErrorString);
|
nuclear@0
|
711 delete pimpl->mScene; pimpl->mScene = NULL;
|
nuclear@0
|
712 }
|
nuclear@0
|
713 #endif // ! ASSIMP_CATCH_GLOBAL_EXCEPTIONS
|
nuclear@0
|
714
|
nuclear@0
|
715 // either successful or failure - the pointer expresses it anyways
|
nuclear@0
|
716 ASSIMP_END_EXCEPTION_REGION(const aiScene*);
|
nuclear@0
|
717 return pimpl->mScene;
|
nuclear@0
|
718 }
|
nuclear@0
|
719
|
nuclear@0
|
720
|
nuclear@0
|
721 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
722 // Apply post-processing to the currently bound scene
|
nuclear@0
|
723 const aiScene* Importer::ApplyPostProcessing(unsigned int pFlags)
|
nuclear@0
|
724 {
|
nuclear@0
|
725 ASSIMP_BEGIN_EXCEPTION_REGION();
|
nuclear@0
|
726 // Return immediately if no scene is active
|
nuclear@0
|
727 if (!pimpl->mScene) {
|
nuclear@0
|
728 return NULL;
|
nuclear@0
|
729 }
|
nuclear@0
|
730
|
nuclear@0
|
731 // If no flags are given, return the current scene with no further action
|
nuclear@0
|
732 if (!pFlags) {
|
nuclear@0
|
733 return pimpl->mScene;
|
nuclear@0
|
734 }
|
nuclear@0
|
735
|
nuclear@0
|
736 // In debug builds: run basic flag validation
|
nuclear@0
|
737 ai_assert(_ValidateFlags(pFlags));
|
nuclear@0
|
738 DefaultLogger::get()->info("Entering post processing pipeline");
|
nuclear@0
|
739
|
nuclear@0
|
740 #ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
|
nuclear@0
|
741 // The ValidateDS process plays an exceptional role. It isn't contained in the global
|
nuclear@0
|
742 // list of post-processing steps, so we need to call it manually.
|
nuclear@0
|
743 if (pFlags & aiProcess_ValidateDataStructure)
|
nuclear@0
|
744 {
|
nuclear@0
|
745 ValidateDSProcess ds;
|
nuclear@0
|
746 ds.ExecuteOnScene (this);
|
nuclear@0
|
747 if (!pimpl->mScene) {
|
nuclear@0
|
748 return NULL;
|
nuclear@0
|
749 }
|
nuclear@0
|
750 }
|
nuclear@0
|
751 #endif // no validation
|
nuclear@0
|
752 #ifdef _DEBUG
|
nuclear@0
|
753 if (pimpl->bExtraVerbose)
|
nuclear@0
|
754 {
|
nuclear@0
|
755 #ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
|
nuclear@0
|
756 DefaultLogger::get()->error("Verbose Import is not available due to build settings");
|
nuclear@0
|
757 #endif // no validation
|
nuclear@0
|
758 pFlags |= aiProcess_ValidateDataStructure;
|
nuclear@0
|
759 }
|
nuclear@0
|
760 #else
|
nuclear@0
|
761 if (pimpl->bExtraVerbose) {
|
nuclear@0
|
762 DefaultLogger::get()->warn("Not a debug build, ignoring extra verbose setting");
|
nuclear@0
|
763 }
|
nuclear@0
|
764 #endif // ! DEBUG
|
nuclear@0
|
765
|
nuclear@0
|
766 boost::scoped_ptr<Profiler> profiler(GetPropertyInteger(AI_CONFIG_GLOB_MEASURE_TIME,0)?new Profiler():NULL);
|
nuclear@0
|
767 for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++) {
|
nuclear@0
|
768
|
nuclear@0
|
769 BaseProcess* process = pimpl->mPostProcessingSteps[a];
|
nuclear@0
|
770 if( process->IsActive( pFlags)) {
|
nuclear@0
|
771
|
nuclear@0
|
772 if (profiler) {
|
nuclear@0
|
773 profiler->BeginRegion("postprocess");
|
nuclear@0
|
774 }
|
nuclear@0
|
775
|
nuclear@0
|
776 process->ExecuteOnScene ( this );
|
nuclear@0
|
777 pimpl->mProgressHandler->Update();
|
nuclear@0
|
778
|
nuclear@0
|
779 if (profiler) {
|
nuclear@0
|
780 profiler->EndRegion("postprocess");
|
nuclear@0
|
781 }
|
nuclear@0
|
782 }
|
nuclear@0
|
783 if( !pimpl->mScene) {
|
nuclear@0
|
784 break;
|
nuclear@0
|
785 }
|
nuclear@0
|
786 #ifdef _DEBUG
|
nuclear@0
|
787
|
nuclear@0
|
788 #ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
|
nuclear@0
|
789 continue;
|
nuclear@0
|
790 #endif // no validation
|
nuclear@0
|
791
|
nuclear@0
|
792 // If the extra verbose mode is active, execute the ValidateDataStructureStep again - after each step
|
nuclear@0
|
793 if (pimpl->bExtraVerbose) {
|
nuclear@0
|
794 DefaultLogger::get()->debug("Verbose Import: revalidating data structures");
|
nuclear@0
|
795
|
nuclear@0
|
796 ValidateDSProcess ds;
|
nuclear@0
|
797 ds.ExecuteOnScene (this);
|
nuclear@0
|
798 if( !pimpl->mScene) {
|
nuclear@0
|
799 DefaultLogger::get()->error("Verbose Import: failed to revalidate data structures");
|
nuclear@0
|
800 break;
|
nuclear@0
|
801 }
|
nuclear@0
|
802 }
|
nuclear@0
|
803 #endif // ! DEBUG
|
nuclear@0
|
804 }
|
nuclear@0
|
805
|
nuclear@0
|
806 // update private scene flags
|
nuclear@0
|
807 if( pimpl->mScene )
|
nuclear@0
|
808 ScenePriv(pimpl->mScene)->mPPStepsApplied |= pFlags;
|
nuclear@0
|
809
|
nuclear@0
|
810 // clear any data allocated by post-process steps
|
nuclear@0
|
811 pimpl->mPPShared->Clean();
|
nuclear@0
|
812 DefaultLogger::get()->info("Leaving post processing pipeline");
|
nuclear@0
|
813
|
nuclear@0
|
814 ASSIMP_END_EXCEPTION_REGION(const aiScene*);
|
nuclear@0
|
815 return pimpl->mScene;
|
nuclear@0
|
816 }
|
nuclear@0
|
817
|
nuclear@0
|
818 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
819 // Helper function to check whether an extension is supported by ASSIMP
|
nuclear@0
|
820 bool Importer::IsExtensionSupported(const char* szExtension) const
|
nuclear@0
|
821 {
|
nuclear@0
|
822 return NULL != GetImporter(szExtension);
|
nuclear@0
|
823 }
|
nuclear@0
|
824
|
nuclear@0
|
825 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
826 size_t Importer::GetImporterCount() const
|
nuclear@0
|
827 {
|
nuclear@0
|
828 return pimpl->mImporter.size();
|
nuclear@0
|
829 }
|
nuclear@0
|
830
|
nuclear@0
|
831 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
832 const aiImporterDesc* Importer::GetImporterInfo(size_t index) const
|
nuclear@0
|
833 {
|
nuclear@0
|
834 if (index >= pimpl->mImporter.size()) {
|
nuclear@0
|
835 return NULL;
|
nuclear@0
|
836 }
|
nuclear@0
|
837 return pimpl->mImporter[index]->GetInfo();
|
nuclear@0
|
838 }
|
nuclear@0
|
839
|
nuclear@0
|
840
|
nuclear@0
|
841 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
842 BaseImporter* Importer::GetImporter (size_t index) const
|
nuclear@0
|
843 {
|
nuclear@0
|
844 if (index >= pimpl->mImporter.size()) {
|
nuclear@0
|
845 return NULL;
|
nuclear@0
|
846 }
|
nuclear@0
|
847 return pimpl->mImporter[index];
|
nuclear@0
|
848 }
|
nuclear@0
|
849
|
nuclear@0
|
850 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
851 // Find a loader plugin for a given file extension
|
nuclear@0
|
852 BaseImporter* Importer::GetImporter (const char* szExtension) const
|
nuclear@0
|
853 {
|
nuclear@0
|
854 return GetImporter(GetImporterIndex(szExtension));
|
nuclear@0
|
855 }
|
nuclear@0
|
856
|
nuclear@0
|
857 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
858 // Find a loader plugin for a given file extension
|
nuclear@0
|
859 size_t Importer::GetImporterIndex (const char* szExtension) const
|
nuclear@0
|
860 {
|
nuclear@0
|
861 ai_assert(szExtension);
|
nuclear@0
|
862 ASSIMP_BEGIN_EXCEPTION_REGION();
|
nuclear@0
|
863
|
nuclear@0
|
864 // skip over wildcard and dot characters at string head --
|
nuclear@0
|
865 for(;*szExtension == '*' || *szExtension == '.'; ++szExtension);
|
nuclear@0
|
866
|
nuclear@0
|
867 std::string ext(szExtension);
|
nuclear@0
|
868 if (ext.empty()) {
|
nuclear@0
|
869 return static_cast<size_t>(-1);
|
nuclear@0
|
870 }
|
nuclear@0
|
871 std::transform(ext.begin(),ext.end(), ext.begin(), tolower);
|
nuclear@0
|
872
|
nuclear@0
|
873 std::set<std::string> str;
|
nuclear@0
|
874 for (std::vector<BaseImporter*>::const_iterator i = pimpl->mImporter.begin();i != pimpl->mImporter.end();++i) {
|
nuclear@0
|
875 str.clear();
|
nuclear@0
|
876
|
nuclear@0
|
877 (*i)->GetExtensionList(str);
|
nuclear@0
|
878 for (std::set<std::string>::const_iterator it = str.begin(); it != str.end(); ++it) {
|
nuclear@0
|
879 if (ext == *it) {
|
nuclear@0
|
880 return std::distance(static_cast< std::vector<BaseImporter*>::const_iterator >(pimpl->mImporter.begin()), i);
|
nuclear@0
|
881 }
|
nuclear@0
|
882 }
|
nuclear@0
|
883 }
|
nuclear@0
|
884 ASSIMP_END_EXCEPTION_REGION(size_t);
|
nuclear@0
|
885 return static_cast<size_t>(-1);
|
nuclear@0
|
886 }
|
nuclear@0
|
887
|
nuclear@0
|
888 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
889 // Helper function to build a list of all file extensions supported by ASSIMP
|
nuclear@0
|
890 void Importer::GetExtensionList(aiString& szOut) const
|
nuclear@0
|
891 {
|
nuclear@0
|
892 ASSIMP_BEGIN_EXCEPTION_REGION();
|
nuclear@0
|
893 std::set<std::string> str;
|
nuclear@0
|
894 for (std::vector<BaseImporter*>::const_iterator i = pimpl->mImporter.begin();i != pimpl->mImporter.end();++i) {
|
nuclear@0
|
895 (*i)->GetExtensionList(str);
|
nuclear@0
|
896 }
|
nuclear@0
|
897
|
nuclear@0
|
898 for (std::set<std::string>::const_iterator it = str.begin();; ) {
|
nuclear@0
|
899 szOut.Append("*.");
|
nuclear@0
|
900 szOut.Append((*it).c_str());
|
nuclear@0
|
901
|
nuclear@0
|
902 if (++it == str.end()) {
|
nuclear@0
|
903 break;
|
nuclear@0
|
904 }
|
nuclear@0
|
905 szOut.Append(";");
|
nuclear@0
|
906 }
|
nuclear@0
|
907 ASSIMP_END_EXCEPTION_REGION(void);
|
nuclear@0
|
908 }
|
nuclear@0
|
909
|
nuclear@0
|
910 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
911 // Set a configuration property
|
nuclear@0
|
912 void Importer::SetPropertyInteger(const char* szName, int iValue,
|
nuclear@0
|
913 bool* bWasExisting /*= NULL*/)
|
nuclear@0
|
914 {
|
nuclear@0
|
915 ASSIMP_BEGIN_EXCEPTION_REGION();
|
nuclear@0
|
916 SetGenericProperty<int>(pimpl->mIntProperties, szName,iValue,bWasExisting);
|
nuclear@0
|
917 ASSIMP_END_EXCEPTION_REGION(void);
|
nuclear@0
|
918 }
|
nuclear@0
|
919
|
nuclear@0
|
920 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
921 // Set a configuration property
|
nuclear@0
|
922 void Importer::SetPropertyFloat(const char* szName, float iValue,
|
nuclear@0
|
923 bool* bWasExisting /*= NULL*/)
|
nuclear@0
|
924 {
|
nuclear@0
|
925 ASSIMP_BEGIN_EXCEPTION_REGION();
|
nuclear@0
|
926 SetGenericProperty<float>(pimpl->mFloatProperties, szName,iValue,bWasExisting);
|
nuclear@0
|
927 ASSIMP_END_EXCEPTION_REGION(void);
|
nuclear@0
|
928 }
|
nuclear@0
|
929
|
nuclear@0
|
930 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
931 // Set a configuration property
|
nuclear@0
|
932 void Importer::SetPropertyString(const char* szName, const std::string& value,
|
nuclear@0
|
933 bool* bWasExisting /*= NULL*/)
|
nuclear@0
|
934 {
|
nuclear@0
|
935 ASSIMP_BEGIN_EXCEPTION_REGION();
|
nuclear@0
|
936 SetGenericProperty<std::string>(pimpl->mStringProperties, szName,value,bWasExisting);
|
nuclear@0
|
937 ASSIMP_END_EXCEPTION_REGION(void);
|
nuclear@0
|
938 }
|
nuclear@0
|
939
|
nuclear@0
|
940 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
941 // Get a configuration property
|
nuclear@0
|
942 int Importer::GetPropertyInteger(const char* szName,
|
nuclear@0
|
943 int iErrorReturn /*= 0xffffffff*/) const
|
nuclear@0
|
944 {
|
nuclear@0
|
945 return GetGenericProperty<int>(pimpl->mIntProperties,szName,iErrorReturn);
|
nuclear@0
|
946 }
|
nuclear@0
|
947
|
nuclear@0
|
948 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
949 // Get a configuration property
|
nuclear@0
|
950 float Importer::GetPropertyFloat(const char* szName,
|
nuclear@0
|
951 float iErrorReturn /*= 10e10*/) const
|
nuclear@0
|
952 {
|
nuclear@0
|
953 return GetGenericProperty<float>(pimpl->mFloatProperties,szName,iErrorReturn);
|
nuclear@0
|
954 }
|
nuclear@0
|
955
|
nuclear@0
|
956 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
957 // Get a configuration property
|
nuclear@0
|
958 const std::string& Importer::GetPropertyString(const char* szName,
|
nuclear@0
|
959 const std::string& iErrorReturn /*= ""*/) const
|
nuclear@0
|
960 {
|
nuclear@0
|
961 return GetGenericProperty<std::string>(pimpl->mStringProperties,szName,iErrorReturn);
|
nuclear@0
|
962 }
|
nuclear@0
|
963
|
nuclear@0
|
964 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
965 // Get the memory requirements of a single node
|
nuclear@0
|
966 inline void AddNodeWeight(unsigned int& iScene,const aiNode* pcNode)
|
nuclear@0
|
967 {
|
nuclear@0
|
968 iScene += sizeof(aiNode);
|
nuclear@0
|
969 iScene += sizeof(unsigned int) * pcNode->mNumMeshes;
|
nuclear@0
|
970 iScene += sizeof(void*) * pcNode->mNumChildren;
|
nuclear@0
|
971
|
nuclear@0
|
972 for (unsigned int i = 0; i < pcNode->mNumChildren;++i) {
|
nuclear@0
|
973 AddNodeWeight(iScene,pcNode->mChildren[i]);
|
nuclear@0
|
974 }
|
nuclear@0
|
975 }
|
nuclear@0
|
976
|
nuclear@0
|
977 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
978 // Get the memory requirements of the scene
|
nuclear@0
|
979 void Importer::GetMemoryRequirements(aiMemoryInfo& in) const
|
nuclear@0
|
980 {
|
nuclear@0
|
981 in = aiMemoryInfo();
|
nuclear@0
|
982 aiScene* mScene = pimpl->mScene;
|
nuclear@0
|
983
|
nuclear@0
|
984 // return if we have no scene loaded
|
nuclear@0
|
985 if (!pimpl->mScene)
|
nuclear@0
|
986 return;
|
nuclear@0
|
987
|
nuclear@0
|
988
|
nuclear@0
|
989 in.total = sizeof(aiScene);
|
nuclear@0
|
990
|
nuclear@0
|
991 // add all meshes
|
nuclear@0
|
992 for (unsigned int i = 0; i < mScene->mNumMeshes;++i)
|
nuclear@0
|
993 {
|
nuclear@0
|
994 in.meshes += sizeof(aiMesh);
|
nuclear@0
|
995 if (mScene->mMeshes[i]->HasPositions()) {
|
nuclear@0
|
996 in.meshes += sizeof(aiVector3D) * mScene->mMeshes[i]->mNumVertices;
|
nuclear@0
|
997 }
|
nuclear@0
|
998
|
nuclear@0
|
999 if (mScene->mMeshes[i]->HasNormals()) {
|
nuclear@0
|
1000 in.meshes += sizeof(aiVector3D) * mScene->mMeshes[i]->mNumVertices;
|
nuclear@0
|
1001 }
|
nuclear@0
|
1002
|
nuclear@0
|
1003 if (mScene->mMeshes[i]->HasTangentsAndBitangents()) {
|
nuclear@0
|
1004 in.meshes += sizeof(aiVector3D) * mScene->mMeshes[i]->mNumVertices * 2;
|
nuclear@0
|
1005 }
|
nuclear@0
|
1006
|
nuclear@0
|
1007 for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS;++a) {
|
nuclear@0
|
1008 if (mScene->mMeshes[i]->HasVertexColors(a)) {
|
nuclear@0
|
1009 in.meshes += sizeof(aiColor4D) * mScene->mMeshes[i]->mNumVertices;
|
nuclear@0
|
1010 }
|
nuclear@0
|
1011 else break;
|
nuclear@0
|
1012 }
|
nuclear@0
|
1013 for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS;++a) {
|
nuclear@0
|
1014 if (mScene->mMeshes[i]->HasTextureCoords(a)) {
|
nuclear@0
|
1015 in.meshes += sizeof(aiVector3D) * mScene->mMeshes[i]->mNumVertices;
|
nuclear@0
|
1016 }
|
nuclear@0
|
1017 else break;
|
nuclear@0
|
1018 }
|
nuclear@0
|
1019 if (mScene->mMeshes[i]->HasBones()) {
|
nuclear@0
|
1020 in.meshes += sizeof(void*) * mScene->mMeshes[i]->mNumBones;
|
nuclear@0
|
1021 for (unsigned int p = 0; p < mScene->mMeshes[i]->mNumBones;++p) {
|
nuclear@0
|
1022 in.meshes += sizeof(aiBone);
|
nuclear@0
|
1023 in.meshes += mScene->mMeshes[i]->mBones[p]->mNumWeights * sizeof(aiVertexWeight);
|
nuclear@0
|
1024 }
|
nuclear@0
|
1025 }
|
nuclear@0
|
1026 in.meshes += (sizeof(aiFace) + 3 * sizeof(unsigned int))*mScene->mMeshes[i]->mNumFaces;
|
nuclear@0
|
1027 }
|
nuclear@0
|
1028 in.total += in.meshes;
|
nuclear@0
|
1029
|
nuclear@0
|
1030 // add all embedded textures
|
nuclear@0
|
1031 for (unsigned int i = 0; i < mScene->mNumTextures;++i) {
|
nuclear@0
|
1032 const aiTexture* pc = mScene->mTextures[i];
|
nuclear@0
|
1033 in.textures += sizeof(aiTexture);
|
nuclear@0
|
1034 if (pc->mHeight) {
|
nuclear@0
|
1035 in.textures += 4 * pc->mHeight * pc->mWidth;
|
nuclear@0
|
1036 }
|
nuclear@0
|
1037 else in.textures += pc->mWidth;
|
nuclear@0
|
1038 }
|
nuclear@0
|
1039 in.total += in.textures;
|
nuclear@0
|
1040
|
nuclear@0
|
1041 // add all animations
|
nuclear@0
|
1042 for (unsigned int i = 0; i < mScene->mNumAnimations;++i) {
|
nuclear@0
|
1043 const aiAnimation* pc = mScene->mAnimations[i];
|
nuclear@0
|
1044 in.animations += sizeof(aiAnimation);
|
nuclear@0
|
1045
|
nuclear@0
|
1046 // add all bone anims
|
nuclear@0
|
1047 for (unsigned int a = 0; a < pc->mNumChannels; ++a) {
|
nuclear@0
|
1048 const aiNodeAnim* pc2 = pc->mChannels[i];
|
nuclear@0
|
1049 in.animations += sizeof(aiNodeAnim);
|
nuclear@0
|
1050 in.animations += pc2->mNumPositionKeys * sizeof(aiVectorKey);
|
nuclear@0
|
1051 in.animations += pc2->mNumScalingKeys * sizeof(aiVectorKey);
|
nuclear@0
|
1052 in.animations += pc2->mNumRotationKeys * sizeof(aiQuatKey);
|
nuclear@0
|
1053 }
|
nuclear@0
|
1054 }
|
nuclear@0
|
1055 in.total += in.animations;
|
nuclear@0
|
1056
|
nuclear@0
|
1057 // add all cameras and all lights
|
nuclear@0
|
1058 in.total += in.cameras = sizeof(aiCamera) * mScene->mNumCameras;
|
nuclear@0
|
1059 in.total += in.lights = sizeof(aiLight) * mScene->mNumLights;
|
nuclear@0
|
1060
|
nuclear@0
|
1061 // add all nodes
|
nuclear@0
|
1062 AddNodeWeight(in.nodes,mScene->mRootNode);
|
nuclear@0
|
1063 in.total += in.nodes;
|
nuclear@0
|
1064
|
nuclear@0
|
1065 // add all materials
|
nuclear@0
|
1066 for (unsigned int i = 0; i < mScene->mNumMaterials;++i) {
|
nuclear@0
|
1067 const aiMaterial* pc = mScene->mMaterials[i];
|
nuclear@0
|
1068 in.materials += sizeof(aiMaterial);
|
nuclear@0
|
1069 in.materials += pc->mNumAllocated * sizeof(void*);
|
nuclear@0
|
1070
|
nuclear@0
|
1071 for (unsigned int a = 0; a < pc->mNumProperties;++a) {
|
nuclear@0
|
1072 in.materials += pc->mProperties[a]->mDataLength;
|
nuclear@0
|
1073 }
|
nuclear@0
|
1074 }
|
nuclear@0
|
1075 in.total += in.materials;
|
nuclear@0
|
1076 }
|
nuclear@0
|
1077
|