miniassimp

view src/Assimp.cpp @ 0:879c81d94345

initial commit
author John Tsiombikas <nuclear@member.fsf.org>
date Mon, 28 Jan 2019 18:19:26 +0200
parents
children
line source
1 /*
2 ---------------------------------------------------------------------------
3 Open Asset Import Library (assimp)
4 ---------------------------------------------------------------------------
6 Copyright (c) 2006-2018, assimp team
10 All rights reserved.
12 Redistribution and use of this software in source and binary forms,
13 with or without modification, are permitted provided that the following
14 conditions are met:
16 * Redistributions of source code must retain the above
17 copyright notice, this list of conditions and the
18 following disclaimer.
20 * Redistributions in binary form must reproduce the above
21 copyright notice, this list of conditions and the
22 following disclaimer in the documentation and/or other
23 materials provided with the distribution.
25 * Neither the name of the assimp team, nor the names of its
26 contributors may be used to endorse or promote products
27 derived from this software without specific prior
28 written permission of the assimp team.
30 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
31 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
32 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
33 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
34 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
35 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
36 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
37 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
38 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
39 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
40 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41 ---------------------------------------------------------------------------
42 */
43 /** @file Assimp.cpp
44 * @brief Implementation of the Plain-C API
45 */
47 #include <miniassimp/cimport.h>
48 #include <miniassimp/LogStream.hpp>
49 #include <miniassimp/DefaultLogger.hpp>
50 #include <miniassimp/Importer.hpp>
51 #include <miniassimp/importerdesc.h>
52 #include <miniassimp/scene.h>
53 #include <miniassimp/GenericProperty.h>
54 #include <miniassimp/Exceptional.h>
55 #include <miniassimp/BaseImporter.h>
57 #include "CInterfaceIOWrapper.h"
58 #include "Importer.h"
59 #include "ScenePrivate.h"
61 #include <list>
63 // ------------------------------------------------------------------------------------------------
64 #ifndef ASSIMP_BUILD_SINGLETHREADED
65 # include <thread>
66 # include <mutex>
67 #endif
68 // ------------------------------------------------------------------------------------------------
69 using namespace Assimp;
71 namespace Assimp {
72 // underlying structure for aiPropertyStore
73 typedef BatchLoader::PropertyMap PropertyMap;
75 /** Stores the LogStream objects for all active C log streams */
76 struct mpred {
77 bool operator () (const aiLogStream& s0, const aiLogStream& s1) const {
78 return s0.callback<s1.callback&&s0.user<s1.user;
79 }
80 };
81 typedef std::map<aiLogStream, Assimp::LogStream*, mpred> LogStreamMap;
83 /** Stores the LogStream objects allocated by #aiGetPredefinedLogStream */
84 typedef std::list<Assimp::LogStream*> PredefLogStreamMap;
86 /** Local storage of all active log streams */
87 static LogStreamMap gActiveLogStreams;
89 /** Local storage of LogStreams allocated by #aiGetPredefinedLogStream */
90 static PredefLogStreamMap gPredefinedStreams;
92 /** Error message of the last failed import process */
93 static std::string gLastErrorString;
95 /** Verbose logging active or not? */
96 static aiBool gVerboseLogging = false;
98 /** will return all registered importers. */
99 void GetImporterInstanceList(std::vector< BaseImporter* >& out);
101 /** will delete all registered importers. */
102 void DeleteImporterInstanceList(std::vector< BaseImporter* >& out);
103 } // namespace assimp
106 #ifndef ASSIMP_BUILD_SINGLETHREADED
107 /** Global mutex to manage the access to the log-stream map */
108 static std::mutex gLogStreamMutex;
109 #endif
111 // ------------------------------------------------------------------------------------------------
112 // Custom LogStream implementation for the C-API
113 class LogToCallbackRedirector : public LogStream {
114 public:
115 explicit LogToCallbackRedirector(const aiLogStream& s)
116 : stream (s) {
117 ai_assert(NULL != s.callback);
118 }
120 ~LogToCallbackRedirector() {
121 #ifndef ASSIMP_BUILD_SINGLETHREADED
122 std::lock_guard<std::mutex> lock(gLogStreamMutex);
123 #endif
124 // (HACK) Check whether the 'stream.user' pointer points to a
125 // custom LogStream allocated by #aiGetPredefinedLogStream.
126 // In this case, we need to delete it, too. Of course, this
127 // might cause strange problems, but the chance is quite low.
129 PredefLogStreamMap::iterator it = std::find(gPredefinedStreams.begin(),
130 gPredefinedStreams.end(), (Assimp::LogStream*)stream.user);
132 if (it != gPredefinedStreams.end()) {
133 delete *it;
134 gPredefinedStreams.erase(it);
135 }
136 }
138 /** @copydoc LogStream::write */
139 void write(const char* message) {
140 stream.callback(message,stream.user);
141 }
143 private:
144 aiLogStream stream;
145 };
147 // ------------------------------------------------------------------------------------------------
148 void ReportSceneNotFoundError() {
149 ASSIMP_LOG_ERROR("Unable to find the Assimp::Importer for this aiScene. "
150 "The C-API does not accept scenes produced by the C++ API and vice versa");
152 ai_assert(false);
153 }
155 // ------------------------------------------------------------------------------------------------
156 // Reads the given file and returns its content.
157 const aiScene* aiImportFile( const char* pFile, unsigned int pFlags) {
158 return aiImportFileEx(pFile,pFlags,NULL);
159 }
161 // ------------------------------------------------------------------------------------------------
162 const aiScene* aiImportFileEx( const char* pFile, unsigned int pFlags, aiFileIO* pFS) {
163 return aiImportFileExWithProperties(pFile, pFlags, pFS, NULL);
164 }
166 // ------------------------------------------------------------------------------------------------
167 const aiScene* aiImportFileExWithProperties( const char* pFile, unsigned int pFlags,
168 aiFileIO* pFS, const aiPropertyStore* props) {
169 ai_assert(NULL != pFile);
171 const aiScene* scene = NULL;
172 ASSIMP_BEGIN_EXCEPTION_REGION();
174 // create an Importer for this file
175 Assimp::Importer* imp = new Assimp::Importer();
177 // copy properties
178 if(props) {
179 const PropertyMap* pp = reinterpret_cast<const PropertyMap*>(props);
180 ImporterPimpl* pimpl = imp->Pimpl();
181 pimpl->mIntProperties = pp->ints;
182 pimpl->mFloatProperties = pp->floats;
183 pimpl->mStringProperties = pp->strings;
184 pimpl->mMatrixProperties = pp->matrices;
185 }
186 // setup a custom IO system if necessary
187 if (pFS) {
188 imp->SetIOHandler( new CIOSystemWrapper (pFS) );
189 }
191 // and have it read the file
192 scene = imp->ReadFile( pFile, pFlags);
194 // if succeeded, store the importer in the scene and keep it alive
195 if( scene) {
196 ScenePrivateData* priv = const_cast<ScenePrivateData*>( ScenePriv(scene) );
197 priv->mOrigImporter = imp;
198 } else {
199 // if failed, extract error code and destroy the import
200 gLastErrorString = imp->GetErrorString();
201 delete imp;
202 }
204 // return imported data. If the import failed the pointer is NULL anyways
205 ASSIMP_END_EXCEPTION_REGION(const aiScene*);
207 return scene;
208 }
210 // ------------------------------------------------------------------------------------------------
211 const aiScene* aiImportFileFromMemory(
212 const char* pBuffer,
213 unsigned int pLength,
214 unsigned int pFlags,
215 const char* pHint)
216 {
217 return aiImportFileFromMemoryWithProperties(pBuffer, pLength, pFlags, pHint, NULL);
218 }
220 // ------------------------------------------------------------------------------------------------
221 const aiScene* aiImportFileFromMemoryWithProperties(
222 const char* pBuffer,
223 unsigned int pLength,
224 unsigned int pFlags,
225 const char* pHint,
226 const aiPropertyStore* props)
227 {
228 ai_assert( NULL != pBuffer );
229 ai_assert( 0 != pLength );
231 const aiScene* scene = NULL;
232 ASSIMP_BEGIN_EXCEPTION_REGION();
234 // create an Importer for this file
235 Assimp::Importer* imp = new Assimp::Importer();
237 // copy properties
238 if(props) {
239 const PropertyMap* pp = reinterpret_cast<const PropertyMap*>(props);
240 ImporterPimpl* pimpl = imp->Pimpl();
241 pimpl->mIntProperties = pp->ints;
242 pimpl->mFloatProperties = pp->floats;
243 pimpl->mStringProperties = pp->strings;
244 pimpl->mMatrixProperties = pp->matrices;
245 }
247 // and have it read the file from the memory buffer
248 scene = imp->ReadFileFromMemory( pBuffer, pLength, pFlags,pHint);
250 // if succeeded, store the importer in the scene and keep it alive
251 if( scene) {
252 ScenePrivateData* priv = const_cast<ScenePrivateData*>( ScenePriv(scene) );
253 priv->mOrigImporter = imp;
254 }
255 else {
256 // if failed, extract error code and destroy the import
257 gLastErrorString = imp->GetErrorString();
258 delete imp;
259 }
260 // return imported data. If the import failed the pointer is NULL anyways
261 ASSIMP_END_EXCEPTION_REGION(const aiScene*);
262 return scene;
263 }
265 // ------------------------------------------------------------------------------------------------
266 // Releases all resources associated with the given import process.
267 void aiReleaseImport( const aiScene* pScene)
268 {
269 if (!pScene) {
270 return;
271 }
273 ASSIMP_BEGIN_EXCEPTION_REGION();
275 // find the importer associated with this data
276 const ScenePrivateData* priv = ScenePriv(pScene);
277 if( !priv || !priv->mOrigImporter) {
278 delete pScene;
279 }
280 else {
281 // deleting the Importer also deletes the scene
282 // Note: the reason that this is not written as 'delete priv->mOrigImporter'
283 // is a suspected bug in gcc 4.4+ (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52339)
284 Importer* importer = priv->mOrigImporter;
285 delete importer;
286 }
288 ASSIMP_END_EXCEPTION_REGION(void);
289 }
291 // ------------------------------------------------------------------------------------------------
292 ASSIMP_API const aiScene* aiApplyPostProcessing(const aiScene* pScene,
293 unsigned int pFlags)
294 {
295 const aiScene* sc = NULL;
298 ASSIMP_BEGIN_EXCEPTION_REGION();
300 // find the importer associated with this data
301 const ScenePrivateData* priv = ScenePriv(pScene);
302 if( !priv || !priv->mOrigImporter) {
303 ReportSceneNotFoundError();
304 return NULL;
305 }
307 sc = priv->mOrigImporter->ApplyPostProcessing(pFlags);
309 if (!sc) {
310 aiReleaseImport(pScene);
311 return NULL;
312 }
314 ASSIMP_END_EXCEPTION_REGION(const aiScene*);
315 return sc;
316 }
318 // ------------------------------------------------------------------------------------------------
319 ASSIMP_API const aiScene *aiApplyCustomizedPostProcessing( const aiScene *scene,
320 BaseProcess* process,
321 bool requestValidation ) {
322 const aiScene* sc( NULL );
324 ASSIMP_BEGIN_EXCEPTION_REGION();
326 // find the importer associated with this data
327 const ScenePrivateData* priv = ScenePriv( scene );
328 if ( NULL == priv || NULL == priv->mOrigImporter ) {
329 ReportSceneNotFoundError();
330 return NULL;
331 }
333 sc = priv->mOrigImporter->ApplyCustomizedPostProcessing( process, requestValidation );
335 if ( !sc ) {
336 aiReleaseImport( scene );
337 return NULL;
338 }
340 ASSIMP_END_EXCEPTION_REGION( const aiScene* );
342 return sc;
343 }
345 // ------------------------------------------------------------------------------------------------
346 void CallbackToLogRedirector (const char* msg, char* dt)
347 {
348 ai_assert( NULL != msg );
349 ai_assert( NULL != dt );
350 LogStream* s = (LogStream*)dt;
352 s->write(msg);
353 }
355 // ------------------------------------------------------------------------------------------------
356 ASSIMP_API aiLogStream aiGetPredefinedLogStream(aiDefaultLogStream pStream,const char* file)
357 {
358 aiLogStream sout;
360 ASSIMP_BEGIN_EXCEPTION_REGION();
361 LogStream* stream = LogStream::createDefaultStream(pStream,file);
362 if (!stream) {
363 sout.callback = NULL;
364 sout.user = NULL;
365 }
366 else {
367 sout.callback = &CallbackToLogRedirector;
368 sout.user = (char*)stream;
369 }
370 gPredefinedStreams.push_back(stream);
371 ASSIMP_END_EXCEPTION_REGION(aiLogStream);
372 return sout;
373 }
375 // ------------------------------------------------------------------------------------------------
376 ASSIMP_API void aiAttachLogStream( const aiLogStream* stream )
377 {
378 ASSIMP_BEGIN_EXCEPTION_REGION();
380 #ifndef ASSIMP_BUILD_SINGLETHREADED
381 std::lock_guard<std::mutex> lock(gLogStreamMutex);
382 #endif
384 LogStream* lg = new LogToCallbackRedirector(*stream);
385 gActiveLogStreams[*stream] = lg;
387 if (DefaultLogger::isNullLogger()) {
388 DefaultLogger::create(NULL,(gVerboseLogging == AI_TRUE ? Logger::VERBOSE : Logger::NORMAL));
389 }
390 DefaultLogger::get()->attachStream(lg);
391 ASSIMP_END_EXCEPTION_REGION(void);
392 }
394 // ------------------------------------------------------------------------------------------------
395 ASSIMP_API aiReturn aiDetachLogStream( const aiLogStream* stream)
396 {
397 ASSIMP_BEGIN_EXCEPTION_REGION();
399 #ifndef ASSIMP_BUILD_SINGLETHREADED
400 std::lock_guard<std::mutex> lock(gLogStreamMutex);
401 #endif
402 // find the log-stream associated with this data
403 LogStreamMap::iterator it = gActiveLogStreams.find( *stream);
404 // it should be there... else the user is playing fools with us
405 if( it == gActiveLogStreams.end()) {
406 return AI_FAILURE;
407 }
408 DefaultLogger::get()->detatchStream( it->second );
409 delete it->second;
411 gActiveLogStreams.erase( it);
413 if (gActiveLogStreams.empty()) {
414 DefaultLogger::kill();
415 }
416 ASSIMP_END_EXCEPTION_REGION(aiReturn);
417 return AI_SUCCESS;
418 }
420 // ------------------------------------------------------------------------------------------------
421 ASSIMP_API void aiDetachAllLogStreams(void)
422 {
423 ASSIMP_BEGIN_EXCEPTION_REGION();
424 #ifndef ASSIMP_BUILD_SINGLETHREADED
425 std::lock_guard<std::mutex> lock(gLogStreamMutex);
426 #endif
427 Logger *logger( DefaultLogger::get() );
428 if ( NULL == logger ) {
429 return;
430 }
432 for (LogStreamMap::iterator it = gActiveLogStreams.begin(); it != gActiveLogStreams.end(); ++it) {
433 logger->detatchStream( it->second );
434 delete it->second;
435 }
436 gActiveLogStreams.clear();
437 DefaultLogger::kill();
439 ASSIMP_END_EXCEPTION_REGION(void);
440 }
442 // ------------------------------------------------------------------------------------------------
443 ASSIMP_API void aiEnableVerboseLogging(aiBool d)
444 {
445 if (!DefaultLogger::isNullLogger()) {
446 DefaultLogger::get()->setLogSeverity((d == AI_TRUE ? Logger::VERBOSE : Logger::NORMAL));
447 }
448 gVerboseLogging = d;
449 }
451 // ------------------------------------------------------------------------------------------------
452 // Returns the error text of the last failed import process.
453 const char* aiGetErrorString()
454 {
455 return gLastErrorString.c_str();
456 }
458 // -----------------------------------------------------------------------------------------------
459 // Return the description of a importer given its index
460 const aiImporterDesc* aiGetImportFormatDescription( size_t pIndex)
461 {
462 return Importer().GetImporterInfo(pIndex);
463 }
465 // -----------------------------------------------------------------------------------------------
466 // Return the number of importers
467 size_t aiGetImportFormatCount(void)
468 {
469 return Importer().GetImporterCount();
470 }
472 // ------------------------------------------------------------------------------------------------
473 // Returns the error text of the last failed import process.
474 aiBool aiIsExtensionSupported(const char* szExtension)
475 {
476 ai_assert(NULL != szExtension);
477 aiBool candoit=AI_FALSE;
478 ASSIMP_BEGIN_EXCEPTION_REGION();
480 // FIXME: no need to create a temporary Importer instance just for that ..
481 Assimp::Importer tmp;
482 candoit = tmp.IsExtensionSupported(std::string(szExtension)) ? AI_TRUE : AI_FALSE;
484 ASSIMP_END_EXCEPTION_REGION(aiBool);
485 return candoit;
486 }
488 // ------------------------------------------------------------------------------------------------
489 // Get a list of all file extensions supported by ASSIMP
490 void aiGetExtensionList(aiString* szOut)
491 {
492 ai_assert(NULL != szOut);
493 ASSIMP_BEGIN_EXCEPTION_REGION();
495 // FIXME: no need to create a temporary Importer instance just for that ..
496 Assimp::Importer tmp;
497 tmp.GetExtensionList(*szOut);
499 ASSIMP_END_EXCEPTION_REGION(void);
500 }
502 // ------------------------------------------------------------------------------------------------
503 // Get the memory requirements for a particular import.
504 void aiGetMemoryRequirements(const C_STRUCT aiScene* pIn,
505 C_STRUCT aiMemoryInfo* in)
506 {
507 ASSIMP_BEGIN_EXCEPTION_REGION();
509 // find the importer associated with this data
510 const ScenePrivateData* priv = ScenePriv(pIn);
511 if( !priv || !priv->mOrigImporter) {
512 ReportSceneNotFoundError();
513 return;
514 }
516 return priv->mOrigImporter->GetMemoryRequirements(*in);
517 ASSIMP_END_EXCEPTION_REGION(void);
518 }
520 // ------------------------------------------------------------------------------------------------
521 ASSIMP_API aiPropertyStore* aiCreatePropertyStore(void)
522 {
523 return reinterpret_cast<aiPropertyStore*>( new PropertyMap() );
524 }
526 // ------------------------------------------------------------------------------------------------
527 ASSIMP_API void aiReleasePropertyStore(aiPropertyStore* p)
528 {
529 delete reinterpret_cast<PropertyMap*>(p);
530 }
532 // ------------------------------------------------------------------------------------------------
533 // Importer::SetPropertyInteger
534 ASSIMP_API void aiSetImportPropertyInteger(aiPropertyStore* p, const char* szName, int value)
535 {
536 ASSIMP_BEGIN_EXCEPTION_REGION();
537 PropertyMap* pp = reinterpret_cast<PropertyMap*>(p);
538 SetGenericProperty<int>(pp->ints,szName,value);
539 ASSIMP_END_EXCEPTION_REGION(void);
540 }
542 // ------------------------------------------------------------------------------------------------
543 // Importer::SetPropertyFloat
544 ASSIMP_API void aiSetImportPropertyFloat(aiPropertyStore* p, const char* szName, ai_real value)
545 {
546 ASSIMP_BEGIN_EXCEPTION_REGION();
547 PropertyMap* pp = reinterpret_cast<PropertyMap*>(p);
548 SetGenericProperty<ai_real>(pp->floats,szName,value);
549 ASSIMP_END_EXCEPTION_REGION(void);
550 }
552 // ------------------------------------------------------------------------------------------------
553 // Importer::SetPropertyString
554 ASSIMP_API void aiSetImportPropertyString(aiPropertyStore* p, const char* szName,
555 const C_STRUCT aiString* st)
556 {
557 if (!st) {
558 return;
559 }
560 ASSIMP_BEGIN_EXCEPTION_REGION();
561 PropertyMap* pp = reinterpret_cast<PropertyMap*>(p);
562 SetGenericProperty<std::string>(pp->strings,szName,std::string(st->C_Str()));
563 ASSIMP_END_EXCEPTION_REGION(void);
564 }
566 // ------------------------------------------------------------------------------------------------
567 // Importer::SetPropertyMatrix
568 ASSIMP_API void aiSetImportPropertyMatrix(aiPropertyStore* p, const char* szName,
569 const C_STRUCT aiMatrix4x4* mat)
570 {
571 if (!mat) {
572 return;
573 }
574 ASSIMP_BEGIN_EXCEPTION_REGION();
575 PropertyMap* pp = reinterpret_cast<PropertyMap*>(p);
576 SetGenericProperty<aiMatrix4x4>(pp->matrices,szName,*mat);
577 ASSIMP_END_EXCEPTION_REGION(void);
578 }
580 // ------------------------------------------------------------------------------------------------
581 // Rotation matrix to quaternion
582 ASSIMP_API void aiCreateQuaternionFromMatrix(aiQuaternion* quat,const aiMatrix3x3* mat)
583 {
584 ai_assert( NULL != quat );
585 ai_assert( NULL != mat );
586 *quat = aiQuaternion(*mat);
587 }
589 // ------------------------------------------------------------------------------------------------
590 // Matrix decomposition
591 ASSIMP_API void aiDecomposeMatrix(const aiMatrix4x4* mat,aiVector3D* scaling,
592 aiQuaternion* rotation,
593 aiVector3D* position)
594 {
595 ai_assert( NULL != rotation );
596 ai_assert( NULL != position );
597 ai_assert( NULL != scaling );
598 ai_assert( NULL != mat );
599 mat->Decompose(*scaling,*rotation,*position);
600 }
602 // ------------------------------------------------------------------------------------------------
603 // Matrix transpose
604 ASSIMP_API void aiTransposeMatrix3(aiMatrix3x3* mat)
605 {
606 ai_assert(NULL != mat);
607 mat->Transpose();
608 }
610 // ------------------------------------------------------------------------------------------------
611 ASSIMP_API void aiTransposeMatrix4(aiMatrix4x4* mat)
612 {
613 ai_assert(NULL != mat);
614 mat->Transpose();
615 }
617 // ------------------------------------------------------------------------------------------------
618 // Vector transformation
619 ASSIMP_API void aiTransformVecByMatrix3(aiVector3D* vec,
620 const aiMatrix3x3* mat)
621 {
622 ai_assert( NULL != mat );
623 ai_assert( NULL != vec);
624 *vec *= (*mat);
625 }
627 // ------------------------------------------------------------------------------------------------
628 ASSIMP_API void aiTransformVecByMatrix4(aiVector3D* vec,
629 const aiMatrix4x4* mat)
630 {
631 ai_assert( NULL != mat );
632 ai_assert( NULL != vec );
634 *vec *= (*mat);
635 }
637 // ------------------------------------------------------------------------------------------------
638 // Matrix multiplication
639 ASSIMP_API void aiMultiplyMatrix4(
640 aiMatrix4x4* dst,
641 const aiMatrix4x4* src)
642 {
643 ai_assert( NULL != dst );
644 ai_assert( NULL != src );
645 *dst = (*dst) * (*src);
646 }
648 // ------------------------------------------------------------------------------------------------
649 ASSIMP_API void aiMultiplyMatrix3(
650 aiMatrix3x3* dst,
651 const aiMatrix3x3* src)
652 {
653 ai_assert( NULL != dst );
654 ai_assert( NULL != src );
655 *dst = (*dst) * (*src);
656 }
658 // ------------------------------------------------------------------------------------------------
659 // Matrix identity
660 ASSIMP_API void aiIdentityMatrix3(
661 aiMatrix3x3* mat)
662 {
663 ai_assert(NULL != mat);
664 *mat = aiMatrix3x3();
665 }
667 // ------------------------------------------------------------------------------------------------
668 ASSIMP_API void aiIdentityMatrix4(
669 aiMatrix4x4* mat)
670 {
671 ai_assert(NULL != mat);
672 *mat = aiMatrix4x4();
673 }
675 // ------------------------------------------------------------------------------------------------
676 ASSIMP_API C_STRUCT const aiImporterDesc* aiGetImporterDesc( const char *extension ) {
677 if( NULL == extension ) {
678 return NULL;
679 }
680 const aiImporterDesc *desc( NULL );
681 std::vector< BaseImporter* > out;
682 GetImporterInstanceList( out );
683 for( size_t i = 0; i < out.size(); ++i ) {
684 if( 0 == strncmp( out[ i ]->GetInfo()->mFileExtensions, extension, strlen( extension ) ) ) {
685 desc = out[ i ]->GetInfo();
686 break;
687 }
688 }
690 DeleteImporterInstanceList(out);
692 return desc;
693 }
695 // ------------------------------------------------------------------------------------------------