1 /*
2 ---------------------------------------------------------------------------
3 Open Asset Import Library (assimp)
4 ---------------------------------------------------------------------------
5
6 Copyright (c) 2006-2015, 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 <boost/thread/thread.hpp>
63 # include <boost/thread/mutex.hpp>
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 } // namespace assimp
100
101
102 #ifndef ASSIMP_BUILD_SINGLETHREADED
103 /** Global mutex to manage the access to the logstream map */
104 static boost::mutex gLogStreamMutex;
105 #endif
106
107
108 // ------------------------------------------------------------------------------------------------
109 // Custom LogStream implementation for the C-API
110 class LogToCallbackRedirector : public LogStream
111 {
112 public:
LogToCallbackRedirector(const aiLogStream & s)113 explicit LogToCallbackRedirector(const aiLogStream& s)
114 : stream (s) {
115 ai_assert(NULL != s.callback);
116 }
117
~LogToCallbackRedirector()118 ~LogToCallbackRedirector() {
119 #ifndef ASSIMP_BUILD_SINGLETHREADED
120 boost::mutex::scoped_lock lock(gLogStreamMutex);
121 #endif
122 // (HACK) Check whether the 'stream.user' pointer points to a
123 // custom LogStream allocated by #aiGetPredefinedLogStream.
124 // In this case, we need to delete it, too. Of course, this
125 // might cause strange problems, but the chance is quite low.
126
127 PredefLogStreamMap::iterator it = std::find(gPredefinedStreams.begin(),
128 gPredefinedStreams.end(), (Assimp::LogStream*)stream.user);
129
130 if (it != gPredefinedStreams.end()) {
131 delete *it;
132 gPredefinedStreams.erase(it);
133 }
134 }
135
136 /** @copydoc LogStream::write */
write(const char * message)137 void write(const char* message) {
138 stream.callback(message,stream.user);
139 }
140
141 private:
142 aiLogStream stream;
143 };
144
145 // ------------------------------------------------------------------------------------------------
ReportSceneNotFoundError()146 void ReportSceneNotFoundError()
147 {
148 DefaultLogger::get()->error("Unable to find the Assimp::Importer for this aiScene. "
149 "The C-API does not accept scenes produced by the C++ API and vice versa");
150
151 assert(false);
152 }
153
154 // ------------------------------------------------------------------------------------------------
155 // Reads the given file and returns its content.
aiImportFile(const char * pFile,unsigned int pFlags)156 const aiScene* aiImportFile( const char* pFile, unsigned int pFlags)
157 {
158 return aiImportFileEx(pFile,pFlags,NULL);
159 }
160
161 // ------------------------------------------------------------------------------------------------
aiImportFileEx(const char * pFile,unsigned int pFlags,aiFileIO * pFS)162 const aiScene* aiImportFileEx( const char* pFile, unsigned int pFlags, aiFileIO* pFS)
163 {
164 return aiImportFileExWithProperties(pFile, pFlags, pFS, NULL);
165 }
166
167 // ------------------------------------------------------------------------------------------------
aiImportFileExWithProperties(const char * pFile,unsigned int pFlags,aiFileIO * pFS,const aiPropertyStore * props)168 const aiScene* aiImportFileExWithProperties( const char* pFile, unsigned int pFlags,
169 aiFileIO* pFS,
170 const aiPropertyStore* props)
171 {
172 ai_assert(NULL != pFile);
173
174 const aiScene* scene = NULL;
175 ASSIMP_BEGIN_EXCEPTION_REGION();
176
177 // create an Importer for this file
178 Assimp::Importer* imp = new Assimp::Importer();
179
180 // copy properties
181 if(props) {
182 const PropertyMap* pp = reinterpret_cast<const PropertyMap*>(props);
183 ImporterPimpl* pimpl = imp->Pimpl();
184 pimpl->mIntProperties = pp->ints;
185 pimpl->mFloatProperties = pp->floats;
186 pimpl->mStringProperties = pp->strings;
187 pimpl->mMatrixProperties = pp->matrices;
188 }
189 // setup a custom IO system if necessary
190 if (pFS) {
191 imp->SetIOHandler( new CIOSystemWrapper (pFS) );
192 }
193
194 // and have it read the file
195 scene = imp->ReadFile( pFile, pFlags);
196
197 // if succeeded, store the importer in the scene and keep it alive
198 if( scene) {
199 ScenePrivateData* priv = const_cast<ScenePrivateData*>( ScenePriv(scene) );
200 priv->mOrigImporter = imp;
201 }
202 else {
203 // if failed, extract error code and destroy the import
204 gLastErrorString = imp->GetErrorString();
205 delete imp;
206 }
207
208 // return imported data. If the import failed the pointer is NULL anyways
209 ASSIMP_END_EXCEPTION_REGION(const aiScene*);
210 return scene;
211 }
212
213 // ------------------------------------------------------------------------------------------------
aiImportFileFromMemory(const char * pBuffer,unsigned int pLength,unsigned int pFlags,const char * pHint)214 const aiScene* aiImportFileFromMemory(
215 const char* pBuffer,
216 unsigned int pLength,
217 unsigned int pFlags,
218 const char* pHint)
219 {
220 return aiImportFileFromMemoryWithProperties(pBuffer, pLength, pFlags, pHint, NULL);
221 }
222
223 // ------------------------------------------------------------------------------------------------
aiImportFileFromMemoryWithProperties(const char * pBuffer,unsigned int pLength,unsigned int pFlags,const char * pHint,const aiPropertyStore * props)224 const aiScene* aiImportFileFromMemoryWithProperties(
225 const char* pBuffer,
226 unsigned int pLength,
227 unsigned int pFlags,
228 const char* pHint,
229 const aiPropertyStore* props)
230 {
231 ai_assert(NULL != pBuffer && 0 != pLength);
232
233 const aiScene* scene = NULL;
234 ASSIMP_BEGIN_EXCEPTION_REGION();
235
236 // create an Importer for this file
237 Assimp::Importer* imp = new Assimp::Importer();
238
239 // copy properties
240 if(props) {
241 const PropertyMap* pp = reinterpret_cast<const PropertyMap*>(props);
242 ImporterPimpl* pimpl = imp->Pimpl();
243 pimpl->mIntProperties = pp->ints;
244 pimpl->mFloatProperties = pp->floats;
245 pimpl->mStringProperties = pp->strings;
246 pimpl->mMatrixProperties = pp->matrices;
247 }
248
249 // and have it read the file from the memory buffer
250 scene = imp->ReadFileFromMemory( pBuffer, pLength, pFlags,pHint);
251
252 // if succeeded, store the importer in the scene and keep it alive
253 if( scene) {
254 ScenePrivateData* priv = const_cast<ScenePrivateData*>( ScenePriv(scene) );
255 priv->mOrigImporter = imp;
256 }
257 else {
258 // if failed, extract error code and destroy the import
259 gLastErrorString = imp->GetErrorString();
260 delete imp;
261 }
262 // return imported data. If the import failed the pointer is NULL anyways
263 ASSIMP_END_EXCEPTION_REGION(const aiScene*);
264 return scene;
265 }
266
267 // ------------------------------------------------------------------------------------------------
268 // Releases all resources associated with the given import process.
aiReleaseImport(const aiScene * pScene)269 void aiReleaseImport( const aiScene* pScene)
270 {
271 if (!pScene) {
272 return;
273 }
274
275 ASSIMP_BEGIN_EXCEPTION_REGION();
276
277 // find the importer associated with this data
278 const ScenePrivateData* priv = ScenePriv(pScene);
279 if( !priv || !priv->mOrigImporter) {
280 delete pScene;
281 }
282 else {
283 // deleting the Importer also deletes the scene
284 // Note: the reason that this is not written as 'delete priv->mOrigImporter'
285 // is a suspected bug in gcc 4.4+ (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52339)
286 Importer* importer = priv->mOrigImporter;
287 delete importer;
288 }
289
290 ASSIMP_END_EXCEPTION_REGION(void);
291 }
292
293 // ------------------------------------------------------------------------------------------------
aiApplyPostProcessing(const aiScene * pScene,unsigned int pFlags)294 ASSIMP_API const aiScene* aiApplyPostProcessing(const aiScene* pScene,
295 unsigned int pFlags)
296 {
297 const aiScene* sc = NULL;
298
299
300 ASSIMP_BEGIN_EXCEPTION_REGION();
301
302 // find the importer associated with this data
303 const ScenePrivateData* priv = ScenePriv(pScene);
304 if( !priv || !priv->mOrigImporter) {
305 ReportSceneNotFoundError();
306 return NULL;
307 }
308
309 sc = priv->mOrigImporter->ApplyPostProcessing(pFlags);
310
311 if (!sc) {
312 aiReleaseImport(pScene);
313 return NULL;
314 }
315
316 ASSIMP_END_EXCEPTION_REGION(const aiScene*);
317 return sc;
318 }
319
320 // ------------------------------------------------------------------------------------------------
CallbackToLogRedirector(const char * msg,char * dt)321 void CallbackToLogRedirector (const char* msg, char* dt)
322 {
323 ai_assert(NULL != msg && NULL != dt);
324 LogStream* s = (LogStream*)dt;
325
326 s->write(msg);
327 }
328
329 // ------------------------------------------------------------------------------------------------
aiGetPredefinedLogStream(aiDefaultLogStream pStream,const char * file)330 ASSIMP_API aiLogStream aiGetPredefinedLogStream(aiDefaultLogStream pStream,const char* file)
331 {
332 aiLogStream sout;
333
334 ASSIMP_BEGIN_EXCEPTION_REGION();
335 LogStream* stream = LogStream::createDefaultStream(pStream,file);
336 if (!stream) {
337 sout.callback = NULL;
338 sout.user = NULL;
339 }
340 else {
341 sout.callback = &CallbackToLogRedirector;
342 sout.user = (char*)stream;
343 }
344 gPredefinedStreams.push_back(stream);
345 ASSIMP_END_EXCEPTION_REGION(aiLogStream);
346 return sout;
347 }
348
349 // ------------------------------------------------------------------------------------------------
aiAttachLogStream(const aiLogStream * stream)350 ASSIMP_API void aiAttachLogStream( const aiLogStream* stream )
351 {
352 ASSIMP_BEGIN_EXCEPTION_REGION();
353
354 #ifndef ASSIMP_BUILD_SINGLETHREADED
355 boost::mutex::scoped_lock lock(gLogStreamMutex);
356 #endif
357
358 LogStream* lg = new LogToCallbackRedirector(*stream);
359 gActiveLogStreams[*stream] = lg;
360
361 if (DefaultLogger::isNullLogger()) {
362 DefaultLogger::create(NULL,(gVerboseLogging == AI_TRUE ? Logger::VERBOSE : Logger::NORMAL));
363 }
364 DefaultLogger::get()->attachStream(lg);
365 ASSIMP_END_EXCEPTION_REGION(void);
366 }
367
368 // ------------------------------------------------------------------------------------------------
aiDetachLogStream(const aiLogStream * stream)369 ASSIMP_API aiReturn aiDetachLogStream( const aiLogStream* stream)
370 {
371 ASSIMP_BEGIN_EXCEPTION_REGION();
372
373 #ifndef ASSIMP_BUILD_SINGLETHREADED
374 boost::mutex::scoped_lock lock(gLogStreamMutex);
375 #endif
376 // find the logstream associated with this data
377 LogStreamMap::iterator it = gActiveLogStreams.find( *stream);
378 // it should be there... else the user is playing fools with us
379 if( it == gActiveLogStreams.end()) {
380 return AI_FAILURE;
381 }
382 DefaultLogger::get()->detatchStream( it->second );
383 delete it->second;
384
385 gActiveLogStreams.erase( it);
386
387 if (gActiveLogStreams.empty()) {
388 DefaultLogger::kill();
389 }
390 ASSIMP_END_EXCEPTION_REGION(aiReturn);
391 return AI_SUCCESS;
392 }
393
394 // ------------------------------------------------------------------------------------------------
aiDetachAllLogStreams(void)395 ASSIMP_API void aiDetachAllLogStreams(void)
396 {
397 ASSIMP_BEGIN_EXCEPTION_REGION();
398 #ifndef ASSIMP_BUILD_SINGLETHREADED
399 boost::mutex::scoped_lock lock(gLogStreamMutex);
400 #endif
401 for (LogStreamMap::iterator it = gActiveLogStreams.begin(); it != gActiveLogStreams.end(); ++it) {
402 DefaultLogger::get()->detatchStream( it->second );
403 delete it->second;
404 }
405 gActiveLogStreams.clear();
406 DefaultLogger::kill();
407 ASSIMP_END_EXCEPTION_REGION(void);
408 }
409
410 // ------------------------------------------------------------------------------------------------
aiEnableVerboseLogging(aiBool d)411 ASSIMP_API void aiEnableVerboseLogging(aiBool d)
412 {
413 if (!DefaultLogger::isNullLogger()) {
414 DefaultLogger::get()->setLogSeverity((d == AI_TRUE ? Logger::VERBOSE : Logger::NORMAL));
415 }
416 gVerboseLogging = d;
417 }
418
419 // ------------------------------------------------------------------------------------------------
420 // Returns the error text of the last failed import process.
aiGetErrorString()421 const char* aiGetErrorString()
422 {
423 return gLastErrorString.c_str();
424 }
425
426 // -----------------------------------------------------------------------------------------------
427 // Return the description of a importer given its index
aiGetImportFormatDescription(size_t pIndex)428 const aiImporterDesc* aiGetImportFormatDescription( size_t pIndex)
429 {
430 return Importer().GetImporterInfo(pIndex);
431 }
432
433 // -----------------------------------------------------------------------------------------------
434 // Return the number of importers
aiGetImportFormatCount(void)435 size_t aiGetImportFormatCount(void)
436 {
437 return Importer().GetImporterCount();
438 }
439
440
441 // ------------------------------------------------------------------------------------------------
442 // Returns the error text of the last failed import process.
aiIsExtensionSupported(const char * szExtension)443 aiBool aiIsExtensionSupported(const char* szExtension)
444 {
445 ai_assert(NULL != szExtension);
446 aiBool candoit=AI_FALSE;
447 ASSIMP_BEGIN_EXCEPTION_REGION();
448
449 // FIXME: no need to create a temporary Importer instance just for that ..
450 Assimp::Importer tmp;
451 candoit = tmp.IsExtensionSupported(std::string(szExtension)) ? AI_TRUE : AI_FALSE;
452
453 ASSIMP_END_EXCEPTION_REGION(aiBool);
454 return candoit;
455 }
456
457 // ------------------------------------------------------------------------------------------------
458 // Get a list of all file extensions supported by ASSIMP
aiGetExtensionList(aiString * szOut)459 void aiGetExtensionList(aiString* szOut)
460 {
461 ai_assert(NULL != szOut);
462 ASSIMP_BEGIN_EXCEPTION_REGION();
463
464 // FIXME: no need to create a temporary Importer instance just for that ..
465 Assimp::Importer tmp;
466 tmp.GetExtensionList(*szOut);
467
468 ASSIMP_END_EXCEPTION_REGION(void);
469 }
470
471 // ------------------------------------------------------------------------------------------------
472 // Get the memory requirements for a particular import.
aiGetMemoryRequirements(const C_STRUCT aiScene * pIn,C_STRUCT aiMemoryInfo * in)473 void aiGetMemoryRequirements(const C_STRUCT aiScene* pIn,
474 C_STRUCT aiMemoryInfo* in)
475 {
476 ASSIMP_BEGIN_EXCEPTION_REGION();
477
478 // find the importer associated with this data
479 const ScenePrivateData* priv = ScenePriv(pIn);
480 if( !priv || !priv->mOrigImporter) {
481 ReportSceneNotFoundError();
482 return;
483 }
484
485 return priv->mOrigImporter->GetMemoryRequirements(*in);
486 ASSIMP_END_EXCEPTION_REGION(void);
487 }
488
489 // ------------------------------------------------------------------------------------------------
aiCreatePropertyStore(void)490 ASSIMP_API aiPropertyStore* aiCreatePropertyStore(void)
491 {
492 return reinterpret_cast<aiPropertyStore*>( new PropertyMap() );
493 }
494
495
496 // ------------------------------------------------------------------------------------------------
aiReleasePropertyStore(aiPropertyStore * p)497 ASSIMP_API void aiReleasePropertyStore(aiPropertyStore* p)
498 {
499 delete reinterpret_cast<PropertyMap*>(p);
500 }
501
502 // ------------------------------------------------------------------------------------------------
503 // Importer::SetPropertyInteger
aiSetImportPropertyInteger(aiPropertyStore * p,const char * szName,int value)504 ASSIMP_API void aiSetImportPropertyInteger(aiPropertyStore* p, const char* szName, int value)
505 {
506 ASSIMP_BEGIN_EXCEPTION_REGION();
507 PropertyMap* pp = reinterpret_cast<PropertyMap*>(p);
508 SetGenericProperty<int>(pp->ints,szName,value);
509 ASSIMP_END_EXCEPTION_REGION(void);
510 }
511
512 // ------------------------------------------------------------------------------------------------
513 // Importer::SetPropertyFloat
aiSetImportPropertyFloat(aiPropertyStore * p,const char * szName,float value)514 ASSIMP_API void aiSetImportPropertyFloat(aiPropertyStore* p, const char* szName, float value)
515 {
516 ASSIMP_BEGIN_EXCEPTION_REGION();
517 PropertyMap* pp = reinterpret_cast<PropertyMap*>(p);
518 SetGenericProperty<float>(pp->floats,szName,value);
519 ASSIMP_END_EXCEPTION_REGION(void);
520 }
521
522 // ------------------------------------------------------------------------------------------------
523 // Importer::SetPropertyString
aiSetImportPropertyString(aiPropertyStore * p,const char * szName,const C_STRUCT aiString * st)524 ASSIMP_API void aiSetImportPropertyString(aiPropertyStore* p, const char* szName,
525 const C_STRUCT aiString* st)
526 {
527 if (!st) {
528 return;
529 }
530 ASSIMP_BEGIN_EXCEPTION_REGION();
531 PropertyMap* pp = reinterpret_cast<PropertyMap*>(p);
532 SetGenericProperty<std::string>(pp->strings,szName,std::string(st->C_Str()));
533 ASSIMP_END_EXCEPTION_REGION(void);
534 }
535
536 // ------------------------------------------------------------------------------------------------
537 // Importer::SetPropertyMatrix
aiSetImportPropertyMatrix(aiPropertyStore * p,const char * szName,const C_STRUCT aiMatrix4x4 * mat)538 ASSIMP_API void aiSetImportPropertyMatrix(aiPropertyStore* p, const char* szName,
539 const C_STRUCT aiMatrix4x4* mat)
540 {
541 if (!mat) {
542 return;
543 }
544 ASSIMP_BEGIN_EXCEPTION_REGION();
545 PropertyMap* pp = reinterpret_cast<PropertyMap*>(p);
546 SetGenericProperty<aiMatrix4x4>(pp->matrices,szName,*mat);
547 ASSIMP_END_EXCEPTION_REGION(void);
548 }
549
550 // ------------------------------------------------------------------------------------------------
551 // Rotation matrix to quaternion
aiCreateQuaternionFromMatrix(aiQuaternion * quat,const aiMatrix3x3 * mat)552 ASSIMP_API void aiCreateQuaternionFromMatrix(aiQuaternion* quat,const aiMatrix3x3* mat)
553 {
554 ai_assert(NULL != quat && NULL != mat);
555 *quat = aiQuaternion(*mat);
556 }
557
558 // ------------------------------------------------------------------------------------------------
559 // Matrix decomposition
aiDecomposeMatrix(const aiMatrix4x4 * mat,aiVector3D * scaling,aiQuaternion * rotation,aiVector3D * position)560 ASSIMP_API void aiDecomposeMatrix(const aiMatrix4x4* mat,aiVector3D* scaling,
561 aiQuaternion* rotation,
562 aiVector3D* position)
563 {
564 ai_assert(NULL != rotation && NULL != position && NULL != scaling && NULL != mat);
565 mat->Decompose(*scaling,*rotation,*position);
566 }
567
568 // ------------------------------------------------------------------------------------------------
569 // Matrix transpose
aiTransposeMatrix3(aiMatrix3x3 * mat)570 ASSIMP_API void aiTransposeMatrix3(aiMatrix3x3* mat)
571 {
572 ai_assert(NULL != mat);
573 mat->Transpose();
574 }
575
576 // ------------------------------------------------------------------------------------------------
aiTransposeMatrix4(aiMatrix4x4 * mat)577 ASSIMP_API void aiTransposeMatrix4(aiMatrix4x4* mat)
578 {
579 ai_assert(NULL != mat);
580 mat->Transpose();
581 }
582
583 // ------------------------------------------------------------------------------------------------
584 // Vector transformation
aiTransformVecByMatrix3(aiVector3D * vec,const aiMatrix3x3 * mat)585 ASSIMP_API void aiTransformVecByMatrix3(aiVector3D* vec,
586 const aiMatrix3x3* mat)
587 {
588 ai_assert(NULL != mat && NULL != vec);
589 *vec *= (*mat);
590 }
591
592 // ------------------------------------------------------------------------------------------------
aiTransformVecByMatrix4(aiVector3D * vec,const aiMatrix4x4 * mat)593 ASSIMP_API void aiTransformVecByMatrix4(aiVector3D* vec,
594 const aiMatrix4x4* mat)
595 {
596 ai_assert(NULL != mat && NULL != vec);
597 *vec *= (*mat);
598 }
599
600 // ------------------------------------------------------------------------------------------------
601 // Matrix multiplication
aiMultiplyMatrix4(aiMatrix4x4 * dst,const aiMatrix4x4 * src)602 ASSIMP_API void aiMultiplyMatrix4(
603 aiMatrix4x4* dst,
604 const aiMatrix4x4* src)
605 {
606 ai_assert(NULL != dst && NULL != src);
607 *dst = (*dst) * (*src);
608 }
609
610 // ------------------------------------------------------------------------------------------------
aiMultiplyMatrix3(aiMatrix3x3 * dst,const aiMatrix3x3 * src)611 ASSIMP_API void aiMultiplyMatrix3(
612 aiMatrix3x3* dst,
613 const aiMatrix3x3* src)
614 {
615 ai_assert(NULL != dst && NULL != src);
616 *dst = (*dst) * (*src);
617 }
618
619 // ------------------------------------------------------------------------------------------------
620 // Matrix identity
aiIdentityMatrix3(aiMatrix3x3 * mat)621 ASSIMP_API void aiIdentityMatrix3(
622 aiMatrix3x3* mat)
623 {
624 ai_assert(NULL != mat);
625 *mat = aiMatrix3x3();
626 }
627
628 // ------------------------------------------------------------------------------------------------
aiIdentityMatrix4(aiMatrix4x4 * mat)629 ASSIMP_API void aiIdentityMatrix4(
630 aiMatrix4x4* mat)
631 {
632 ai_assert(NULL != mat);
633 *mat = aiMatrix4x4();
634 }
635
636 // ------------------------------------------------------------------------------------------------
aiGetImporterDesc(const char * extension)637 ASSIMP_API C_STRUCT const aiImporterDesc* aiGetImporterDesc( const char *extension ) {
638 if( NULL == extension ) {
639 return NULL;
640 }
641 const aiImporterDesc *desc( NULL );
642 std::vector< BaseImporter* > out;
643 GetImporterInstanceList( out );
644 for( size_t i = 0; i < out.size(); ++i ) {
645 if( 0 == strncmp( out[ i ]->GetInfo()->mFileExtensions, extension, strlen( extension ) ) ) {
646 desc = out[ i ]->GetInfo();
647 break;
648 }
649 }
650
651 return desc;
652 }
653
654 // ------------------------------------------------------------------------------------------------
655