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