Coverage Report

Created: 2026-07-30 07:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/assimp/code/Common/Assimp.cpp
Line
Count
Source
1
/*
2
---------------------------------------------------------------------------
3
Open Asset Import Library (assimp)
4
---------------------------------------------------------------------------
5
6
Copyright (c) 2006-2026, 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/BaseImporter.h>
46
#include <assimp/Exceptional.h>
47
#include <assimp/GenericProperty.h>
48
#include <assimp/cimport.h>
49
#include <assimp/importerdesc.h>
50
#include <assimp/scene.h>
51
#include <assimp/DefaultLogger.hpp>
52
#include <assimp/Importer.hpp>
53
#include <assimp/LogStream.hpp>
54
55
#include "CApi/CInterfaceIOWrapper.h"
56
#include "Importer.h"
57
#include "ScenePrivate.h"
58
59
#include <list>
60
61
// ------------------------------------------------------------------------------------------------
62
#ifndef ASSIMP_BUILD_SINGLETHREADED
63
#include <mutex>
64
#include <thread>
65
#endif
66
// ------------------------------------------------------------------------------------------------
67
using namespace Assimp;
68
69
namespace Assimp {
70
71
// underlying structure for aiPropertyStore
72
using PropertyMap =  BatchLoader::PropertyMap ;
73
74
#if defined(__has_warning)
75
#   if __has_warning("-Wordered-compare-function-pointers")
76
#   pragma GCC diagnostic push
77
#   pragma GCC diagnostic ignored "-Wordered-compare-function-pointers"
78
#endif
79
#endif
80
81
/** Stores the LogStream objects for all active C log streams */
82
struct mpred {
83
0
    bool operator()(const aiLogStream &s0, const aiLogStream &s1) const {
84
0
        return s0.callback < s1.callback && s0.user < s1.user;
85
0
    }
86
};
87
88
#if defined(__has_warning)
89
#if __has_warning("-Wordered-compare-function-pointers")
90
#pragma GCC diagnostic pop
91
#endif
92
#endif
93
typedef std::map<aiLogStream, Assimp::LogStream *, mpred> LogStreamMap;
94
95
/** Stores the LogStream objects allocated by #aiGetPredefinedLogStream */
96
typedef std::list<Assimp::LogStream *> PredefLogStreamMap;
97
98
/** Local storage of all active log streams */
99
static LogStreamMap gActiveLogStreams;
100
101
/** Local storage of LogStreams allocated by #aiGetPredefinedLogStream */
102
static PredefLogStreamMap gPredefinedStreams;
103
104
/** Error message of the last failed import process */
105
static std::string gLastErrorString;
106
107
/** Verbose logging active or not? */
108
static aiBool gVerboseLogging = false;
109
110
/** will return all registered importers. */
111
void GetImporterInstanceList(std::vector<BaseImporter *> &out);
112
113
/** will delete all registered importers. */
114
void DeleteImporterInstanceList(std::vector<BaseImporter *> &out);
115
116
} // namespace Assimp
117
118
#ifndef ASSIMP_BUILD_SINGLETHREADED
119
/** Global mutex to manage the access to the log-stream map */
120
static std::mutex gLogStreamMutex;
121
#endif
122
123
// ------------------------------------------------------------------------------------------------
124
// Custom LogStream implementation for the C-API
125
class LogToCallbackRedirector final : public LogStream {
126
public:
127
    explicit LogToCallbackRedirector(const aiLogStream &s) :
128
0
            mStream(s) {
129
0
        ai_assert(nullptr != s.callback);
130
0
    }
131
132
0
    ~LogToCallbackRedirector() override {
133
#ifndef ASSIMP_BUILD_SINGLETHREADED
134
        std::lock_guard<std::mutex> lock(gLogStreamMutex);
135
#endif
136
        // (HACK) Check whether the 'stream.user' pointer points to a
137
        // custom LogStream allocated by #aiGetPredefinedLogStream.
138
        // In this case, we need to delete it, too. Of course, this
139
        // might cause strange problems, but the chance is quite low.
140
141
0
        PredefLogStreamMap::iterator it = std::find(gPredefinedStreams.begin(),
142
0
                gPredefinedStreams.end(), (Assimp::LogStream *)mStream.user);
143
144
0
        if (it != gPredefinedStreams.end()) {
145
0
            delete *it;
146
0
            gPredefinedStreams.erase(it);
147
0
        }
148
0
    }
149
150
    /** @copydoc LogStream::write */
151
0
    void write(const char *message) override {
152
0
        mStream.callback(message, mStream.user);
153
0
    }
154
155
private:
156
    const aiLogStream &mStream;
157
};
158
159
// ------------------------------------------------------------------------------------------------
160
0
void ReportSceneNotFoundError() {
161
0
    ASSIMP_LOG_ERROR("Unable to find the Assimp::Importer for this aiScene. "
162
0
                     "The C-API does not accept scenes produced by the C++ API and vice versa");
163
164
0
    ai_assert(false);
165
0
}
166
167
// ------------------------------------------------------------------------------------------------
168
// Reads the given file and returns its content.
169
0
const aiScene *aiImportFile(const char *pFile, unsigned int pFlags) {
170
0
    return aiImportFileEx(pFile, pFlags, nullptr);
171
0
}
172
173
// ------------------------------------------------------------------------------------------------
174
0
const aiScene *aiImportFileEx(const char *pFile, unsigned int pFlags, aiFileIO *pFS) {
175
0
    return aiImportFileExWithProperties(pFile, pFlags, pFS, nullptr);
176
0
}
177
178
// ------------------------------------------------------------------------------------------------
179
const aiScene *aiImportFileExWithProperties(const char *pFile, unsigned int pFlags,
180
0
        aiFileIO *pFS, const aiPropertyStore *props) {
181
0
    ai_assert(nullptr != pFile);
182
183
0
    const aiScene *scene = nullptr;
184
0
    ASSIMP_BEGIN_EXCEPTION_REGION();
185
186
    // create an Importer for this file
187
0
    Assimp::Importer *imp = new Assimp::Importer();
188
189
    // copy properties
190
0
    if (props) {
191
0
        const PropertyMap *pp = reinterpret_cast<const PropertyMap *>(props);
192
0
        ImporterPimpl *pimpl = imp->Pimpl();
193
0
        pimpl->mIntProperties = pp->ints;
194
0
        pimpl->mFloatProperties = pp->floats;
195
0
        pimpl->mStringProperties = pp->strings;
196
0
        pimpl->mMatrixProperties = pp->matrices;
197
0
    }
198
    // setup a custom IO system if necessary
199
0
    if (pFS) {
200
0
        imp->SetIOHandler(new CIOSystemWrapper(pFS));
201
0
    }
202
203
    // and have it read the file
204
0
    scene = imp->ReadFile(pFile, pFlags);
205
206
    // if succeeded, store the importer in the scene and keep it alive
207
0
    if (scene) {
208
0
        ScenePrivateData *priv = const_cast<ScenePrivateData *>(ScenePriv(scene));
209
0
        priv->mOrigImporter = imp;
210
0
    } else {
211
        // if failed, extract error code and destroy the import
212
0
        gLastErrorString = imp->GetErrorString();
213
0
        delete imp;
214
0
    }
215
216
    // return imported data. If the import failed the pointer is nullptr anyways
217
0
    ASSIMP_END_EXCEPTION_REGION(const aiScene *);
218
219
0
    return scene;
220
0
}
221
222
// ------------------------------------------------------------------------------------------------
223
const aiScene *aiImportFileFromMemory(
224
        const char *pBuffer,
225
        unsigned int pLength,
226
        unsigned int pFlags,
227
0
        const char *pHint) {
228
0
    return aiImportFileFromMemoryWithProperties(pBuffer, pLength, pFlags, pHint, nullptr);
229
0
}
230
231
// ------------------------------------------------------------------------------------------------
232
const aiScene *aiImportFileFromMemoryWithProperties(
233
        const char *pBuffer,
234
        unsigned int pLength,
235
        unsigned int pFlags,
236
        const char *pHint,
237
0
        const aiPropertyStore *props) {
238
0
    if (pBuffer == nullptr) {
239
0
        return nullptr;
240
0
    }
241
242
0
    if (pLength == 0u) {
243
0
        return nullptr;
244
0
    }
245
246
0
    const aiScene *scene = nullptr;
247
0
    ASSIMP_BEGIN_EXCEPTION_REGION();
248
249
    // create an Importer for this file
250
0
    Assimp::Importer *imp = new Assimp::Importer();
251
252
    // copy properties
253
0
    if (props) {
254
0
        const PropertyMap *pp = reinterpret_cast<const PropertyMap *>(props);
255
0
        ImporterPimpl *pimpl = imp->Pimpl();
256
0
        pimpl->mIntProperties = pp->ints;
257
0
        pimpl->mFloatProperties = pp->floats;
258
0
        pimpl->mStringProperties = pp->strings;
259
0
        pimpl->mMatrixProperties = pp->matrices;
260
0
    }
261
262
    // and have it read the file from the memory buffer
263
0
    scene = imp->ReadFileFromMemory(pBuffer, pLength, pFlags, pHint);
264
265
    // if succeeded, store the importer in the scene and keep it alive
266
0
    if (scene) {
267
0
        ScenePrivateData *priv = const_cast<ScenePrivateData *>(ScenePriv(scene));
268
0
        priv->mOrigImporter = imp;
269
0
    } else {
270
        // if failed, extract error code and destroy the import
271
0
        gLastErrorString = imp->GetErrorString();
272
0
        delete imp;
273
0
    }
274
    // return imported data. If the import failed the pointer is nullptr anyways
275
0
    ASSIMP_END_EXCEPTION_REGION(const aiScene *);
276
0
    return scene;
277
0
}
278
279
// ------------------------------------------------------------------------------------------------
280
// Releases all resources associated with the given import process.
281
0
void aiReleaseImport(const aiScene *pScene) {
282
0
    if (!pScene) {
283
0
        return;
284
0
    }
285
286
0
    ASSIMP_BEGIN_EXCEPTION_REGION();
287
288
    // find the importer associated with this data
289
0
    const ScenePrivateData *priv = ScenePriv(pScene);
290
0
    if (!priv || !priv->mOrigImporter) {
291
0
        delete pScene;
292
0
    } else {
293
        // deleting the Importer also deletes the scene
294
        // Note: the reason that this is not written as 'delete priv->mOrigImporter'
295
        // is a suspected bug in gcc 4.4+ (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52339)
296
0
        Importer *importer = priv->mOrigImporter;
297
0
        delete importer;
298
0
    }
299
300
0
    ASSIMP_END_EXCEPTION_REGION(void);
301
0
}
302
303
// ------------------------------------------------------------------------------------------------
304
ASSIMP_API const aiScene *aiApplyPostProcessing(const aiScene *pScene,
305
0
        unsigned int pFlags) {
306
0
    const aiScene *sc = nullptr;
307
308
0
    ASSIMP_BEGIN_EXCEPTION_REGION();
309
310
    // find the importer associated with this data
311
0
    const ScenePrivateData *priv = ScenePriv(pScene);
312
0
    if (!priv || !priv->mOrigImporter) {
313
0
        ReportSceneNotFoundError();
314
0
        return nullptr;
315
0
    }
316
317
0
    sc = priv->mOrigImporter->ApplyPostProcessing(pFlags);
318
319
0
    if (!sc) {
320
0
        aiReleaseImport(pScene);
321
0
        return nullptr;
322
0
    }
323
324
0
    ASSIMP_END_EXCEPTION_REGION(const aiScene *);
325
0
    return sc;
326
0
}
327
328
// ------------------------------------------------------------------------------------------------
329
ASSIMP_API const aiScene *aiApplyCustomizedPostProcessing(const aiScene *scene,
330
        BaseProcess *process,
331
0
        bool requestValidation) {
332
0
    const aiScene *sc(nullptr);
333
334
0
    ASSIMP_BEGIN_EXCEPTION_REGION();
335
336
    // find the importer associated with this data
337
0
    const ScenePrivateData *priv = ScenePriv(scene);
338
0
    if (nullptr == priv || nullptr == priv->mOrigImporter) {
339
0
        ReportSceneNotFoundError();
340
0
        return nullptr;
341
0
    }
342
343
0
    sc = priv->mOrigImporter->ApplyCustomizedPostProcessing(process, requestValidation);
344
345
0
    if (!sc) {
346
0
        aiReleaseImport(scene);
347
0
        return nullptr;
348
0
    }
349
350
0
    ASSIMP_END_EXCEPTION_REGION(const aiScene *);
351
352
0
    return sc;
353
0
}
354
355
// ------------------------------------------------------------------------------------------------
356
0
void CallbackToLogRedirector(const char *msg, char *dt) {
357
0
    ai_assert(nullptr != msg);
358
0
    ai_assert(nullptr != dt);
359
0
    LogStream *stream = (LogStream *)dt;
360
0
    if (stream != nullptr) {
361
0
        stream->write(msg);
362
0
    }
363
0
}
364
365
static LogStream *DefaultStream = nullptr;
366
367
// ------------------------------------------------------------------------------------------------
368
0
ASSIMP_API aiLogStream aiGetPredefinedLogStream(aiDefaultLogStream pStream, const char *file) {
369
0
    aiLogStream sout;
370
371
0
    ASSIMP_BEGIN_EXCEPTION_REGION();
372
0
    if (DefaultStream == nullptr) {
373
0
        DefaultStream = LogStream::createDefaultStream(pStream, file);
374
0
    }
375
376
0
    if (!DefaultStream) {
377
0
        sout.callback = nullptr;
378
0
        sout.user = nullptr;
379
0
    } else {
380
0
        sout.callback = &CallbackToLogRedirector;
381
0
        sout.user = (char *)DefaultStream;
382
0
    }
383
0
    gPredefinedStreams.push_back(DefaultStream);
384
0
    ASSIMP_END_EXCEPTION_REGION(aiLogStream);
385
0
    return sout;
386
0
}
387
388
// ------------------------------------------------------------------------------------------------
389
0
ASSIMP_API void aiAttachLogStream(const aiLogStream *stream) {
390
0
    ASSIMP_BEGIN_EXCEPTION_REGION();
391
392
#ifndef ASSIMP_BUILD_SINGLETHREADED
393
    std::lock_guard<std::mutex> lock(gLogStreamMutex);
394
#endif
395
396
0
    LogStream *lg = new LogToCallbackRedirector(*stream);
397
0
    gActiveLogStreams[*stream] = lg;
398
399
0
    if (DefaultLogger::isNullLogger()) {
400
0
        DefaultLogger::create(nullptr, (gVerboseLogging == AI_TRUE ? Logger::VERBOSE : Logger::NORMAL));
401
0
    }
402
0
    DefaultLogger::get()->attachStream(lg);
403
0
    ASSIMP_END_EXCEPTION_REGION(void);
404
0
}
405
406
// ------------------------------------------------------------------------------------------------
407
0
ASSIMP_API aiReturn aiDetachLogStream(const aiLogStream *stream) {
408
0
    ASSIMP_BEGIN_EXCEPTION_REGION();
409
410
#ifndef ASSIMP_BUILD_SINGLETHREADED
411
    std::lock_guard<std::mutex> lock(gLogStreamMutex);
412
#endif
413
    // find the log-stream associated with this data
414
0
    LogStreamMap::iterator it = gActiveLogStreams.find(*stream);
415
    // it should be there... else the user is playing fools with us
416
0
    if (it == gActiveLogStreams.end()) {
417
0
        return AI_FAILURE;
418
0
    }
419
0
    DefaultLogger::get()->detachStream(it->second);
420
0
    delete it->second;
421
422
0
    if ((Assimp::LogStream *)stream->user == DefaultStream) {
423
0
        DefaultStream = nullptr;
424
0
    }
425
426
0
    gActiveLogStreams.erase(it);
427
428
0
    if (gActiveLogStreams.empty()) {
429
0
        DefaultLogger::kill();
430
0
    }
431
0
    ASSIMP_END_EXCEPTION_REGION(aiReturn);
432
0
    return AI_SUCCESS;
433
0
}
434
435
// ------------------------------------------------------------------------------------------------
436
0
ASSIMP_API void aiDetachAllLogStreams(void) {
437
0
    ASSIMP_BEGIN_EXCEPTION_REGION();
438
#ifndef ASSIMP_BUILD_SINGLETHREADED
439
    std::lock_guard<std::mutex> lock(gLogStreamMutex);
440
#endif
441
0
    Logger *logger(DefaultLogger::get());
442
0
    if (nullptr == logger) {
443
0
        return;
444
0
    }
445
446
0
    for (LogStreamMap::iterator it = gActiveLogStreams.begin(); it != gActiveLogStreams.end(); ++it) {
447
0
        logger->detachStream(it->second);
448
0
        delete it->second;
449
0
    }
450
0
    gActiveLogStreams.clear();
451
0
    DefaultLogger::kill();
452
453
0
    ASSIMP_END_EXCEPTION_REGION(void);
454
0
}
455
456
// ------------------------------------------------------------------------------------------------
457
0
ASSIMP_API void aiEnableVerboseLogging(aiBool d) {
458
0
    if (!DefaultLogger::isNullLogger()) {
459
0
        DefaultLogger::get()->setLogSeverity((d == AI_TRUE ? Logger::VERBOSE : Logger::NORMAL));
460
0
    }
461
0
    gVerboseLogging = d;
462
0
}
463
464
// ------------------------------------------------------------------------------------------------
465
// Returns the error text of the last failed import process.
466
0
const char *aiGetErrorString() {
467
0
    return gLastErrorString.c_str();
468
0
}
469
470
// -----------------------------------------------------------------------------------------------
471
// Return the description of a importer given its index
472
0
const aiImporterDesc *aiGetImportFormatDescription(size_t pIndex) {
473
0
    return Importer().GetImporterInfo(pIndex);
474
0
}
475
476
// -----------------------------------------------------------------------------------------------
477
// Return the number of importers
478
0
size_t aiGetImportFormatCount(void) {
479
0
    return Importer().GetImporterCount();
480
0
}
481
482
// ------------------------------------------------------------------------------------------------
483
// Returns the error text of the last failed import process.
484
0
aiBool aiIsExtensionSupported(const char *szExtension) {
485
0
    ai_assert(nullptr != szExtension);
486
0
    aiBool candoit = AI_FALSE;
487
0
    ASSIMP_BEGIN_EXCEPTION_REGION();
488
489
    // FIXME: no need to create a temporary Importer instance just for that ..
490
0
    Assimp::Importer tmp;
491
0
    candoit = tmp.IsExtensionSupported(std::string(szExtension)) ? AI_TRUE : AI_FALSE;
492
493
0
    ASSIMP_END_EXCEPTION_REGION(aiBool);
494
0
    return candoit;
495
0
}
496
497
// ------------------------------------------------------------------------------------------------
498
// Get a list of all file extensions supported by ASSIMP
499
0
void aiGetExtensionList(aiString *szOut) {
500
0
    ai_assert(nullptr != szOut);
501
0
    ASSIMP_BEGIN_EXCEPTION_REGION();
502
503
    // FIXME: no need to create a temporary Importer instance just for that ..
504
0
    Assimp::Importer tmp;
505
0
    tmp.GetExtensionList(*szOut);
506
507
0
    ASSIMP_END_EXCEPTION_REGION(void);
508
0
}
509
510
// ------------------------------------------------------------------------------------------------
511
// Get the memory requirements for a particular import.
512
void aiGetMemoryRequirements(const C_STRUCT aiScene *pIn,
513
0
        C_STRUCT aiMemoryInfo *in) {
514
0
    ASSIMP_BEGIN_EXCEPTION_REGION();
515
516
    // find the importer associated with this data
517
0
    const ScenePrivateData *priv = ScenePriv(pIn);
518
0
    if (!priv || !priv->mOrigImporter) {
519
0
        ReportSceneNotFoundError();
520
0
        return;
521
0
    }
522
523
0
    return priv->mOrigImporter->GetMemoryRequirements(*in);
524
0
    ASSIMP_END_EXCEPTION_REGION(void);
525
0
}
526
527
// ------------------------------------------------------------------------------------------------
528
0
ASSIMP_API const C_STRUCT aiTexture *aiGetEmbeddedTexture(const C_STRUCT aiScene *pIn, const char *filename) {
529
0
    return pIn->GetEmbeddedTexture(filename);
530
0
}
531
532
// ------------------------------------------------------------------------------------------------
533
0
ASSIMP_API aiPropertyStore *aiCreatePropertyStore(void) {
534
0
    return reinterpret_cast<aiPropertyStore *>(new PropertyMap());
535
0
}
536
537
// ------------------------------------------------------------------------------------------------
538
0
ASSIMP_API void aiReleasePropertyStore(aiPropertyStore *p) {
539
0
    delete reinterpret_cast<PropertyMap *>(p);
540
0
}
541
542
// ------------------------------------------------------------------------------------------------
543
// Importer::SetPropertyInteger
544
0
ASSIMP_API void aiSetImportPropertyInteger(aiPropertyStore *p, const char *szName, int value) {
545
0
    ASSIMP_BEGIN_EXCEPTION_REGION();
546
0
    PropertyMap *pp = reinterpret_cast<PropertyMap *>(p);
547
0
    SetGenericProperty<int>(pp->ints, szName, value);
548
0
    ASSIMP_END_EXCEPTION_REGION(void);
549
0
}
550
551
// ------------------------------------------------------------------------------------------------
552
// Importer::SetPropertyFloat
553
0
ASSIMP_API void aiSetImportPropertyFloat(aiPropertyStore *p, const char *szName, ai_real value) {
554
0
    ASSIMP_BEGIN_EXCEPTION_REGION();
555
0
    PropertyMap *pp = reinterpret_cast<PropertyMap *>(p);
556
0
    SetGenericProperty<ai_real>(pp->floats, szName, value);
557
0
    ASSIMP_END_EXCEPTION_REGION(void);
558
0
}
559
560
// ------------------------------------------------------------------------------------------------
561
// Importer::SetPropertyString
562
ASSIMP_API void aiSetImportPropertyString(aiPropertyStore *p, const char *szName,
563
0
        const C_STRUCT aiString *st) {
564
0
    if (!st) {
565
0
        return;
566
0
    }
567
0
    ASSIMP_BEGIN_EXCEPTION_REGION();
568
0
    PropertyMap *pp = reinterpret_cast<PropertyMap *>(p);
569
0
    SetGenericProperty<std::string>(pp->strings, szName, std::string(st->C_Str()));
570
0
    ASSIMP_END_EXCEPTION_REGION(void);
571
0
}
572
573
// ------------------------------------------------------------------------------------------------
574
// Importer::SetPropertyMatrix
575
ASSIMP_API void aiSetImportPropertyMatrix(aiPropertyStore *p, const char *szName,
576
0
        const C_STRUCT aiMatrix4x4 *mat) {
577
0
    if (!mat) {
578
0
        return;
579
0
    }
580
0
    ASSIMP_BEGIN_EXCEPTION_REGION();
581
0
    PropertyMap *pp = reinterpret_cast<PropertyMap *>(p);
582
0
    SetGenericProperty<aiMatrix4x4>(pp->matrices, szName, *mat);
583
0
    ASSIMP_END_EXCEPTION_REGION(void);
584
0
}
585
586
// ------------------------------------------------------------------------------------------------
587
// Rotation matrix to quaternion
588
0
ASSIMP_API void aiCreateQuaternionFromMatrix(aiQuaternion *quat, const aiMatrix3x3 *mat) {
589
0
    ai_assert(nullptr != quat);
590
0
    ai_assert(nullptr != mat);
591
0
    *quat = aiQuaternion(*mat);
592
0
}
593
594
// ------------------------------------------------------------------------------------------------
595
// Matrix decomposition
596
ASSIMP_API void aiDecomposeMatrix(const aiMatrix4x4 *mat, aiVector3D *scaling,
597
        aiQuaternion *rotation,
598
0
        aiVector3D *position) {
599
0
    ai_assert(nullptr != rotation);
600
0
    ai_assert(nullptr != position);
601
0
    ai_assert(nullptr != scaling);
602
0
    ai_assert(nullptr != mat);
603
0
    mat->Decompose(*scaling, *rotation, *position);
604
0
}
605
606
// ------------------------------------------------------------------------------------------------
607
// Matrix transpose
608
0
ASSIMP_API void aiTransposeMatrix3(aiMatrix3x3 *mat) {
609
0
    ai_assert(nullptr != mat);
610
0
    mat->Transpose();
611
0
}
612
613
// ------------------------------------------------------------------------------------------------
614
0
ASSIMP_API void aiTransposeMatrix4(aiMatrix4x4 *mat) {
615
0
    ai_assert(nullptr != mat);
616
0
    mat->Transpose();
617
0
}
618
619
// ------------------------------------------------------------------------------------------------
620
// Vector transformation
621
ASSIMP_API void aiTransformVecByMatrix3(aiVector3D *vec,
622
0
        const aiMatrix3x3 *mat) {
623
0
    ai_assert(nullptr != mat);
624
0
    ai_assert(nullptr != vec);
625
0
    *vec *= (*mat);
626
0
}
627
628
// ------------------------------------------------------------------------------------------------
629
ASSIMP_API void aiTransformVecByMatrix4(aiVector3D *vec,
630
0
        const aiMatrix4x4 *mat) {
631
0
    ai_assert(nullptr != mat);
632
0
    ai_assert(nullptr != vec);
633
634
0
    *vec *= (*mat);
635
0
}
636
637
// ------------------------------------------------------------------------------------------------
638
// Matrix multiplication
639
ASSIMP_API void aiMultiplyMatrix4(
640
        aiMatrix4x4 *dst,
641
0
        const aiMatrix4x4 *src) {
642
0
    ai_assert(nullptr != dst);
643
0
    ai_assert(nullptr != src);
644
0
    *dst = (*dst) * (*src);
645
0
}
646
647
// ------------------------------------------------------------------------------------------------
648
ASSIMP_API void aiMultiplyMatrix3(
649
        aiMatrix3x3 *dst,
650
0
        const aiMatrix3x3 *src) {
651
0
    ai_assert(nullptr != dst);
652
0
    ai_assert(nullptr != src);
653
0
    *dst = (*dst) * (*src);
654
0
}
655
656
// ------------------------------------------------------------------------------------------------
657
// Matrix identity
658
ASSIMP_API void aiIdentityMatrix3(
659
0
        aiMatrix3x3 *mat) {
660
0
    ai_assert(nullptr != mat);
661
0
    *mat = aiMatrix3x3();
662
0
}
663
664
// ------------------------------------------------------------------------------------------------
665
ASSIMP_API void aiIdentityMatrix4(
666
0
        aiMatrix4x4 *mat) {
667
0
    ai_assert(nullptr != mat);
668
0
    *mat = aiMatrix4x4();
669
0
}
670
671
// ------------------------------------------------------------------------------------------------
672
0
ASSIMP_API C_STRUCT const aiImporterDesc *aiGetImporterDesc(const char *extension) {
673
0
    if (nullptr == extension) {
674
0
        return nullptr;
675
0
    }
676
0
    const aiImporterDesc *desc(nullptr);
677
0
    std::vector<BaseImporter *> out;
678
0
    GetImporterInstanceList(out);
679
0
    for (size_t i = 0; i < out.size(); ++i) {
680
0
        if (0 == strncmp(out[i]->GetInfo()->mFileExtensions, extension, strlen(extension))) {
681
0
            desc = out[i]->GetInfo();
682
0
            break;
683
0
        }
684
0
    }
685
686
0
    DeleteImporterInstanceList(out);
687
688
0
    return desc;
689
0
}
690
691
// ------------------------------------------------------------------------------------------------
692
ASSIMP_API int aiVector2AreEqual(
693
        const C_STRUCT aiVector2D *a,
694
0
        const C_STRUCT aiVector2D *b) {
695
0
    ai_assert(nullptr != a);
696
0
    ai_assert(nullptr != b);
697
0
    return *a == *b;
698
0
}
699
700
// ------------------------------------------------------------------------------------------------
701
ASSIMP_API int aiVector2AreEqualEpsilon(
702
        const C_STRUCT aiVector2D *a,
703
        const C_STRUCT aiVector2D *b,
704
0
        const float epsilon) {
705
0
    ai_assert(nullptr != a);
706
0
    ai_assert(nullptr != b);
707
0
    return a->Equal(*b, epsilon);
708
0
}
709
710
// ------------------------------------------------------------------------------------------------
711
ASSIMP_API void aiVector2Add(
712
        C_STRUCT aiVector2D *dst,
713
0
        const C_STRUCT aiVector2D *src) {
714
0
    ai_assert(nullptr != dst);
715
0
    ai_assert(nullptr != src);
716
0
    *dst = *dst + *src;
717
0
}
718
719
// ------------------------------------------------------------------------------------------------
720
ASSIMP_API void aiVector2Subtract(
721
        C_STRUCT aiVector2D *dst,
722
0
        const C_STRUCT aiVector2D *src) {
723
0
    ai_assert(nullptr != dst);
724
0
    ai_assert(nullptr != src);
725
0
    *dst = *dst - *src;
726
0
}
727
728
// ------------------------------------------------------------------------------------------------
729
ASSIMP_API void aiVector2Scale(
730
        C_STRUCT aiVector2D *dst,
731
0
        const float s) {
732
0
    ai_assert(nullptr != dst);
733
0
    *dst *= s;
734
0
}
735
736
// ------------------------------------------------------------------------------------------------
737
ASSIMP_API void aiVector2SymMul(
738
        C_STRUCT aiVector2D *dst,
739
0
        const C_STRUCT aiVector2D *other) {
740
0
    ai_assert(nullptr != dst);
741
0
    ai_assert(nullptr != other);
742
0
    *dst = dst->SymMul(*other);
743
0
}
744
745
// ------------------------------------------------------------------------------------------------
746
ASSIMP_API void aiVector2DivideByScalar(
747
        C_STRUCT aiVector2D *dst,
748
0
        const float s) {
749
0
    ai_assert(nullptr != dst);
750
0
    *dst /= s;
751
0
}
752
753
// ------------------------------------------------------------------------------------------------
754
ASSIMP_API void aiVector2DivideByVector(
755
        C_STRUCT aiVector2D *dst,
756
0
        C_STRUCT aiVector2D *v) {
757
0
    ai_assert(nullptr != dst);
758
0
    ai_assert(nullptr != v);
759
0
    *dst = *dst / *v;
760
0
}
761
762
// ------------------------------------------------------------------------------------------------
763
ASSIMP_API ai_real aiVector2Length(
764
0
        const C_STRUCT aiVector2D *v) {
765
0
    ai_assert(nullptr != v);
766
0
    return v->Length();
767
0
}
768
769
// ------------------------------------------------------------------------------------------------
770
ASSIMP_API ai_real aiVector2SquareLength(
771
0
        const C_STRUCT aiVector2D *v) {
772
0
    ai_assert(nullptr != v);
773
0
    return v->SquareLength();
774
0
}
775
776
// ------------------------------------------------------------------------------------------------
777
ASSIMP_API void aiVector2Negate(
778
0
        C_STRUCT aiVector2D *dst) {
779
0
    ai_assert(nullptr != dst);
780
0
    *dst = -(*dst);
781
0
}
782
783
// ------------------------------------------------------------------------------------------------
784
ASSIMP_API ai_real aiVector2DotProduct(
785
        const C_STRUCT aiVector2D *a,
786
0
        const C_STRUCT aiVector2D *b) {
787
0
    ai_assert(nullptr != a);
788
0
    ai_assert(nullptr != b);
789
0
    return (*a) * (*b);
790
0
}
791
792
// ------------------------------------------------------------------------------------------------
793
ASSIMP_API void aiVector2Normalize(
794
0
        C_STRUCT aiVector2D *v) {
795
0
    ai_assert(nullptr != v);
796
0
    v->Normalize();
797
0
}
798
799
// ------------------------------------------------------------------------------------------------
800
ASSIMP_API int aiVector3AreEqual(
801
        const C_STRUCT aiVector3D *a,
802
0
        const C_STRUCT aiVector3D *b) {
803
0
    ai_assert(nullptr != a);
804
0
    ai_assert(nullptr != b);
805
0
    return *a == *b;
806
0
}
807
808
// ------------------------------------------------------------------------------------------------
809
ASSIMP_API int aiVector3AreEqualEpsilon(
810
        const C_STRUCT aiVector3D *a,
811
        const C_STRUCT aiVector3D *b,
812
0
        const float epsilon) {
813
0
    ai_assert(nullptr != a);
814
0
    ai_assert(nullptr != b);
815
0
    return a->Equal(*b, epsilon);
816
0
}
817
818
// ------------------------------------------------------------------------------------------------
819
ASSIMP_API int aiVector3LessThan(
820
        const C_STRUCT aiVector3D *a,
821
0
        const C_STRUCT aiVector3D *b) {
822
0
    ai_assert(nullptr != a);
823
0
    ai_assert(nullptr != b);
824
0
    return *a < *b;
825
0
}
826
827
// ------------------------------------------------------------------------------------------------
828
ASSIMP_API void aiVector3Add(
829
        C_STRUCT aiVector3D *dst,
830
0
        const C_STRUCT aiVector3D *src) {
831
0
    ai_assert(nullptr != dst);
832
0
    ai_assert(nullptr != src);
833
0
    *dst = *dst + *src;
834
0
}
835
836
// ------------------------------------------------------------------------------------------------
837
ASSIMP_API void aiVector3Subtract(
838
        C_STRUCT aiVector3D *dst,
839
0
        const C_STRUCT aiVector3D *src) {
840
0
    ai_assert(nullptr != dst);
841
0
    ai_assert(nullptr != src);
842
0
    *dst = *dst - *src;
843
0
}
844
845
// ------------------------------------------------------------------------------------------------
846
ASSIMP_API void aiVector3Scale(
847
        C_STRUCT aiVector3D *dst,
848
0
        const float s) {
849
0
    ai_assert(nullptr != dst);
850
0
    *dst *= s;
851
0
}
852
853
// ------------------------------------------------------------------------------------------------
854
ASSIMP_API void aiVector3SymMul(
855
        C_STRUCT aiVector3D *dst,
856
0
        const C_STRUCT aiVector3D *other) {
857
0
    ai_assert(nullptr != dst);
858
0
    ai_assert(nullptr != other);
859
0
    *dst = dst->SymMul(*other);
860
0
}
861
862
// ------------------------------------------------------------------------------------------------
863
ASSIMP_API void aiVector3DivideByScalar(
864
0
        C_STRUCT aiVector3D *dst, const float s) {
865
0
    ai_assert(nullptr != dst);
866
0
    *dst /= s;
867
0
}
868
869
// ------------------------------------------------------------------------------------------------
870
ASSIMP_API void aiVector3DivideByVector(
871
        C_STRUCT aiVector3D *dst,
872
0
        C_STRUCT aiVector3D *v) {
873
0
    ai_assert(nullptr != dst);
874
0
    ai_assert(nullptr != v);
875
0
    *dst = *dst / *v;
876
0
}
877
878
// ------------------------------------------------------------------------------------------------
879
ASSIMP_API ai_real aiVector3Length(
880
0
        const C_STRUCT aiVector3D *v) {
881
0
    ai_assert(nullptr != v);
882
0
    return v->Length();
883
0
}
884
885
// ------------------------------------------------------------------------------------------------
886
ASSIMP_API ai_real aiVector3SquareLength(
887
0
        const C_STRUCT aiVector3D *v) {
888
0
    ai_assert(nullptr != v);
889
0
    return v->SquareLength();
890
0
}
891
892
// ------------------------------------------------------------------------------------------------
893
ASSIMP_API void aiVector3Negate(
894
0
        C_STRUCT aiVector3D *dst) {
895
0
    ai_assert(nullptr != dst);
896
0
    *dst = -(*dst);
897
0
}
898
899
// ------------------------------------------------------------------------------------------------
900
ASSIMP_API ai_real aiVector3DotProduct(
901
        const C_STRUCT aiVector3D *a,
902
0
        const C_STRUCT aiVector3D *b) {
903
0
    ai_assert(nullptr != a);
904
0
    ai_assert(nullptr != b);
905
0
    return (*a) * (*b);
906
0
}
907
908
// ------------------------------------------------------------------------------------------------
909
ASSIMP_API void aiVector3CrossProduct(
910
        C_STRUCT aiVector3D *dst,
911
        const C_STRUCT aiVector3D *a,
912
0
        const C_STRUCT aiVector3D *b) {
913
0
    ai_assert(nullptr != dst);
914
0
    ai_assert(nullptr != a);
915
0
    ai_assert(nullptr != b);
916
0
    *dst = *a ^ *b;
917
0
}
918
919
// ------------------------------------------------------------------------------------------------
920
ASSIMP_API void aiVector3Normalize(
921
0
        C_STRUCT aiVector3D *v) {
922
0
    ai_assert(nullptr != v);
923
0
    v->Normalize();
924
0
}
925
926
// ------------------------------------------------------------------------------------------------
927
ASSIMP_API void aiVector3NormalizeSafe(
928
0
        C_STRUCT aiVector3D *v) {
929
0
    ai_assert(nullptr != v);
930
0
    v->NormalizeSafe();
931
0
}
932
933
// ------------------------------------------------------------------------------------------------
934
ASSIMP_API void aiVector3RotateByQuaternion(
935
        C_STRUCT aiVector3D *v,
936
0
        const C_STRUCT aiQuaternion *q) {
937
0
    ai_assert(nullptr != v);
938
0
    ai_assert(nullptr != q);
939
0
    *v = q->Rotate(*v);
940
0
}
941
942
// ------------------------------------------------------------------------------------------------
943
ASSIMP_API void aiMatrix3FromMatrix4(
944
        C_STRUCT aiMatrix3x3 *dst,
945
0
        const C_STRUCT aiMatrix4x4 *mat) {
946
0
    ai_assert(nullptr != dst);
947
0
    ai_assert(nullptr != mat);
948
0
    *dst = aiMatrix3x3(*mat);
949
0
}
950
951
// ------------------------------------------------------------------------------------------------
952
ASSIMP_API void aiMatrix3FromQuaternion(
953
        C_STRUCT aiMatrix3x3 *mat,
954
0
        const C_STRUCT aiQuaternion *q) {
955
0
    ai_assert(nullptr != mat);
956
0
    ai_assert(nullptr != q);
957
0
    *mat = q->GetMatrix();
958
0
}
959
960
// ------------------------------------------------------------------------------------------------
961
ASSIMP_API int aiMatrix3AreEqual(
962
        const C_STRUCT aiMatrix3x3 *a,
963
0
        const C_STRUCT aiMatrix3x3 *b) {
964
0
    ai_assert(nullptr != a);
965
0
    ai_assert(nullptr != b);
966
0
    return *a == *b;
967
0
}
968
969
// ------------------------------------------------------------------------------------------------
970
ASSIMP_API int aiMatrix3AreEqualEpsilon(
971
        const C_STRUCT aiMatrix3x3 *a,
972
        const C_STRUCT aiMatrix3x3 *b,
973
0
        const float epsilon) {
974
0
    ai_assert(nullptr != a);
975
0
    ai_assert(nullptr != b);
976
0
    return a->Equal(*b, epsilon);
977
0
}
978
979
// ------------------------------------------------------------------------------------------------
980
0
ASSIMP_API void aiMatrix3Inverse(C_STRUCT aiMatrix3x3 *mat) {
981
0
    ai_assert(nullptr != mat);
982
0
    mat->Inverse();
983
0
}
984
985
// ------------------------------------------------------------------------------------------------
986
0
ASSIMP_API ai_real aiMatrix3Determinant(const C_STRUCT aiMatrix3x3 *mat) {
987
0
    ai_assert(nullptr != mat);
988
0
    return mat->Determinant();
989
0
}
990
991
// ------------------------------------------------------------------------------------------------
992
ASSIMP_API void aiMatrix3RotationZ(
993
        C_STRUCT aiMatrix3x3 *mat,
994
0
        const float angle) {
995
0
    ai_assert(nullptr != mat);
996
0
    aiMatrix3x3::RotationZ(angle, *mat);
997
0
}
998
999
// ------------------------------------------------------------------------------------------------
1000
ASSIMP_API void aiMatrix3FromRotationAroundAxis(
1001
        C_STRUCT aiMatrix3x3 *mat,
1002
        const C_STRUCT aiVector3D *axis,
1003
0
        const float angle) {
1004
0
    ai_assert(nullptr != mat);
1005
0
    ai_assert(nullptr != axis);
1006
0
    aiMatrix3x3::Rotation(angle, *axis, *mat);
1007
0
}
1008
1009
// ------------------------------------------------------------------------------------------------
1010
ASSIMP_API void aiMatrix3Translation(
1011
        C_STRUCT aiMatrix3x3 *mat,
1012
0
        const C_STRUCT aiVector2D *translation) {
1013
0
    ai_assert(nullptr != mat);
1014
0
    ai_assert(nullptr != translation);
1015
0
    aiMatrix3x3::Translation(*translation, *mat);
1016
0
}
1017
1018
// ------------------------------------------------------------------------------------------------
1019
ASSIMP_API void aiMatrix3FromTo(
1020
        C_STRUCT aiMatrix3x3 *mat,
1021
        const C_STRUCT aiVector3D *from,
1022
0
        const C_STRUCT aiVector3D *to) {
1023
0
    ai_assert(nullptr != mat);
1024
0
    ai_assert(nullptr != from);
1025
0
    ai_assert(nullptr != to);
1026
0
    aiMatrix3x3::FromToMatrix(*from, *to, *mat);
1027
0
}
1028
1029
// ------------------------------------------------------------------------------------------------
1030
ASSIMP_API void aiMatrix4FromMatrix3(
1031
        C_STRUCT aiMatrix4x4 *dst,
1032
0
        const C_STRUCT aiMatrix3x3 *mat) {
1033
0
    ai_assert(nullptr != dst);
1034
0
    ai_assert(nullptr != mat);
1035
0
    *dst = aiMatrix4x4(*mat);
1036
0
}
1037
1038
// ------------------------------------------------------------------------------------------------
1039
ASSIMP_API void aiMatrix4FromScalingQuaternionPosition(
1040
        C_STRUCT aiMatrix4x4 *mat,
1041
        const C_STRUCT aiVector3D *scaling,
1042
        const C_STRUCT aiQuaternion *rotation,
1043
0
        const C_STRUCT aiVector3D *position) {
1044
0
    ai_assert(nullptr != mat);
1045
0
    ai_assert(nullptr != scaling);
1046
0
    ai_assert(nullptr != rotation);
1047
0
    ai_assert(nullptr != position);
1048
0
    *mat = aiMatrix4x4(*scaling, *rotation, *position);
1049
0
}
1050
1051
// ------------------------------------------------------------------------------------------------
1052
ASSIMP_API void aiMatrix4Add(
1053
        C_STRUCT aiMatrix4x4 *dst,
1054
0
        const C_STRUCT aiMatrix4x4 *src) {
1055
0
    ai_assert(nullptr != dst);
1056
0
    ai_assert(nullptr != src);
1057
0
    *dst = *dst + *src;
1058
0
}
1059
1060
// ------------------------------------------------------------------------------------------------
1061
ASSIMP_API int aiMatrix4AreEqual(
1062
        const C_STRUCT aiMatrix4x4 *a,
1063
0
        const C_STRUCT aiMatrix4x4 *b) {
1064
0
    ai_assert(nullptr != a);
1065
0
    ai_assert(nullptr != b);
1066
0
    return *a == *b;
1067
0
}
1068
1069
// ------------------------------------------------------------------------------------------------
1070
ASSIMP_API int aiMatrix4AreEqualEpsilon(
1071
        const C_STRUCT aiMatrix4x4 *a,
1072
        const C_STRUCT aiMatrix4x4 *b,
1073
0
        const float epsilon) {
1074
0
    ai_assert(nullptr != a);
1075
0
    ai_assert(nullptr != b);
1076
0
    return a->Equal(*b, epsilon);
1077
0
}
1078
1079
// ------------------------------------------------------------------------------------------------
1080
0
ASSIMP_API void aiMatrix4Inverse(C_STRUCT aiMatrix4x4 *mat) {
1081
0
    ai_assert(nullptr != mat);
1082
0
    mat->Inverse();
1083
0
}
1084
1085
// ------------------------------------------------------------------------------------------------
1086
0
ASSIMP_API ai_real aiMatrix4Determinant(const C_STRUCT aiMatrix4x4 *mat) {
1087
0
    ai_assert(nullptr != mat);
1088
0
    return mat->Determinant();
1089
0
}
1090
1091
// ------------------------------------------------------------------------------------------------
1092
0
ASSIMP_API int aiMatrix4IsIdentity(const C_STRUCT aiMatrix4x4 *mat) {
1093
0
    ai_assert(nullptr != mat);
1094
0
    return mat->IsIdentity();
1095
0
}
1096
1097
// ------------------------------------------------------------------------------------------------
1098
ASSIMP_API void aiMatrix4DecomposeIntoScalingEulerAnglesPosition(
1099
        const C_STRUCT aiMatrix4x4 *mat,
1100
        C_STRUCT aiVector3D *scaling,
1101
        C_STRUCT aiVector3D *rotation,
1102
0
        C_STRUCT aiVector3D *position) {
1103
0
    ai_assert(nullptr != mat);
1104
0
    ai_assert(nullptr != scaling);
1105
0
    ai_assert(nullptr != rotation);
1106
0
    ai_assert(nullptr != position);
1107
0
    mat->Decompose(*scaling, *rotation, *position);
1108
0
}
1109
1110
// ------------------------------------------------------------------------------------------------
1111
ASSIMP_API void aiMatrix4DecomposeIntoScalingAxisAnglePosition(
1112
        const C_STRUCT aiMatrix4x4 *mat,
1113
        C_STRUCT aiVector3D *scaling,
1114
        C_STRUCT aiVector3D *axis,
1115
        ai_real *angle,
1116
0
        C_STRUCT aiVector3D *position) {
1117
0
    ai_assert(nullptr != mat);
1118
0
    ai_assert(nullptr != scaling);
1119
0
    ai_assert(nullptr != axis);
1120
0
    ai_assert(nullptr != angle);
1121
0
    ai_assert(nullptr != position);
1122
0
    mat->Decompose(*scaling, *axis, *angle, *position);
1123
0
}
1124
1125
// ------------------------------------------------------------------------------------------------
1126
ASSIMP_API void aiMatrix4DecomposeNoScaling(
1127
        const C_STRUCT aiMatrix4x4 *mat,
1128
        C_STRUCT aiQuaternion *rotation,
1129
0
        C_STRUCT aiVector3D *position) {
1130
0
    ai_assert(nullptr != mat);
1131
0
    ai_assert(nullptr != rotation);
1132
0
    ai_assert(nullptr != position);
1133
0
    mat->DecomposeNoScaling(*rotation, *position);
1134
0
}
1135
1136
// ------------------------------------------------------------------------------------------------
1137
ASSIMP_API void aiMatrix4FromEulerAngles(
1138
        C_STRUCT aiMatrix4x4 *mat,
1139
0
        float x, float y, float z) {
1140
0
    ai_assert(nullptr != mat);
1141
0
    mat->FromEulerAnglesXYZ(x, y, z);
1142
0
}
1143
1144
// ------------------------------------------------------------------------------------------------
1145
ASSIMP_API void aiMatrix4RotationX(
1146
        C_STRUCT aiMatrix4x4 *mat,
1147
0
        const float angle) {
1148
0
    ai_assert(nullptr != mat);
1149
0
    aiMatrix4x4::RotationX(angle, *mat);
1150
0
}
1151
1152
// ------------------------------------------------------------------------------------------------
1153
ASSIMP_API void aiMatrix4RotationY(
1154
        C_STRUCT aiMatrix4x4 *mat,
1155
0
        const float angle) {
1156
0
    ai_assert(nullptr != mat);
1157
0
    aiMatrix4x4::RotationY(angle, *mat);
1158
0
}
1159
1160
// ------------------------------------------------------------------------------------------------
1161
ASSIMP_API void aiMatrix4RotationZ(
1162
        C_STRUCT aiMatrix4x4 *mat,
1163
0
        const float angle) {
1164
0
    ai_assert(nullptr != mat);
1165
0
    aiMatrix4x4::RotationZ(angle, *mat);
1166
0
}
1167
1168
// ------------------------------------------------------------------------------------------------
1169
ASSIMP_API void aiMatrix4FromRotationAroundAxis(
1170
        C_STRUCT aiMatrix4x4 *mat,
1171
        const C_STRUCT aiVector3D *axis,
1172
0
        const float angle) {
1173
0
    ai_assert(nullptr != mat);
1174
0
    ai_assert(nullptr != axis);
1175
0
    aiMatrix4x4::Rotation(angle, *axis, *mat);
1176
0
}
1177
1178
// ------------------------------------------------------------------------------------------------
1179
ASSIMP_API void aiMatrix4Translation(
1180
        C_STRUCT aiMatrix4x4 *mat,
1181
0
        const C_STRUCT aiVector3D *translation) {
1182
0
    ai_assert(nullptr != mat);
1183
0
    ai_assert(nullptr != translation);
1184
0
    aiMatrix4x4::Translation(*translation, *mat);
1185
0
}
1186
1187
// ------------------------------------------------------------------------------------------------
1188
ASSIMP_API void aiMatrix4Scaling(
1189
        C_STRUCT aiMatrix4x4 *mat,
1190
0
        const C_STRUCT aiVector3D *scaling) {
1191
0
    ai_assert(nullptr != mat);
1192
0
    ai_assert(nullptr != scaling);
1193
0
    aiMatrix4x4::Scaling(*scaling, *mat);
1194
0
}
1195
1196
// ------------------------------------------------------------------------------------------------
1197
ASSIMP_API void aiMatrix4FromTo(
1198
        C_STRUCT aiMatrix4x4 *mat,
1199
        const C_STRUCT aiVector3D *from,
1200
0
        const C_STRUCT aiVector3D *to) {
1201
0
    ai_assert(nullptr != mat);
1202
0
    ai_assert(nullptr != from);
1203
0
    ai_assert(nullptr != to);
1204
0
    aiMatrix4x4::FromToMatrix(*from, *to, *mat);
1205
0
}
1206
1207
// ------------------------------------------------------------------------------------------------
1208
ASSIMP_API void aiQuaternionFromEulerAngles(
1209
        C_STRUCT aiQuaternion *q,
1210
0
        float x, float y, float z) {
1211
0
    ai_assert(nullptr != q);
1212
0
    *q = aiQuaternion(x, y, z);
1213
0
}
1214
1215
// ------------------------------------------------------------------------------------------------
1216
ASSIMP_API void aiQuaternionFromAxisAngle(
1217
        C_STRUCT aiQuaternion *q,
1218
        const C_STRUCT aiVector3D *axis,
1219
0
        const float angle) {
1220
0
    ai_assert(nullptr != q);
1221
0
    ai_assert(nullptr != axis);
1222
0
    *q = aiQuaternion(*axis, angle);
1223
0
}
1224
1225
// ------------------------------------------------------------------------------------------------
1226
ASSIMP_API void aiQuaternionFromNormalizedQuaternion(
1227
        C_STRUCT aiQuaternion *q,
1228
0
        const C_STRUCT aiVector3D *normalized) {
1229
0
    ai_assert(nullptr != q);
1230
0
    ai_assert(nullptr != normalized);
1231
0
    *q = aiQuaternion(*normalized);
1232
0
}
1233
1234
// ------------------------------------------------------------------------------------------------
1235
ASSIMP_API int aiQuaternionAreEqual(
1236
        const C_STRUCT aiQuaternion *a,
1237
0
        const C_STRUCT aiQuaternion *b) {
1238
0
    ai_assert(nullptr != a);
1239
0
    ai_assert(nullptr != b);
1240
0
    return *a == *b;
1241
0
}
1242
1243
// ------------------------------------------------------------------------------------------------
1244
ASSIMP_API int aiQuaternionAreEqualEpsilon(
1245
        const C_STRUCT aiQuaternion *a,
1246
        const C_STRUCT aiQuaternion *b,
1247
0
        const float epsilon) {
1248
0
    ai_assert(nullptr != a);
1249
0
    ai_assert(nullptr != b);
1250
0
    return a->Equal(*b, epsilon);
1251
0
}
1252
1253
// ------------------------------------------------------------------------------------------------
1254
ASSIMP_API void aiQuaternionNormalize(
1255
0
        C_STRUCT aiQuaternion *q) {
1256
0
    ai_assert(nullptr != q);
1257
0
    q->Normalize();
1258
0
}
1259
1260
// ------------------------------------------------------------------------------------------------
1261
ASSIMP_API void aiQuaternionConjugate(
1262
0
        C_STRUCT aiQuaternion *q) {
1263
0
    ai_assert(nullptr != q);
1264
0
    q->Conjugate();
1265
0
}
1266
1267
// ------------------------------------------------------------------------------------------------
1268
ASSIMP_API void aiQuaternionMultiply(
1269
        C_STRUCT aiQuaternion *dst,
1270
0
        const C_STRUCT aiQuaternion *q) {
1271
0
    ai_assert(nullptr != dst);
1272
0
    ai_assert(nullptr != q);
1273
0
    *dst = (*dst) * (*q);
1274
0
}
1275
1276
// ------------------------------------------------------------------------------------------------
1277
ASSIMP_API void aiQuaternionInterpolate(
1278
        C_STRUCT aiQuaternion *dst,
1279
        const C_STRUCT aiQuaternion *start,
1280
        const C_STRUCT aiQuaternion *end,
1281
0
        const float factor) {
1282
0
    ai_assert(nullptr != dst);
1283
0
    ai_assert(nullptr != start);
1284
    ai_assert(nullptr != end);
1285
0
    aiQuaternion::Interpolate(*dst, *start, *end, factor);
1286
0
}
1287
1288
// stb_image is a lightweight image loader. It is shared by:
1289
//  - M3D import
1290
//  - PBRT export
1291
// Since it's a header-only library, its implementation must be instantiated in some cpp file.
1292
// Don't scatter this task over multiple importers/exporters. Maintain it in a central place (here!).
1293
1294
#define ASSIMP_HAS_PBRT_EXPORT (!ASSIMP_BUILD_NO_EXPORT && !ASSIMP_BUILD_NO_PBRT_EXPORTER)
1295
#define ASSIMP_HAS_M3D ((!ASSIMP_BUILD_NO_EXPORT && !ASSIMP_BUILD_NO_M3D_EXPORTER) || !ASSIMP_BUILD_NO_M3D_IMPORTER)
1296
1297
#ifndef STB_USE_HUNTER
1298
#if ASSIMP_HAS_PBRT_EXPORT
1299
#define ASSIMP_NEEDS_STB_IMAGE 1
1300
#elif ASSIMP_HAS_M3D
1301
#define ASSIMP_NEEDS_STB_IMAGE 1
1302
#define STBI_ONLY_PNG
1303
#endif
1304
#endif
1305
1306
// Ensure all symbols are linked correctly
1307
#if ASSIMP_NEEDS_STB_IMAGE
1308
// Share stb_image's PNG loader with other importers/exporters instead of bringing our own copy.
1309
#define STBI_ONLY_PNG
1310
#ifdef ASSIMP_USE_STB_IMAGE_STATIC
1311
#define STB_IMAGE_STATIC
1312
#endif
1313
#define STB_IMAGE_IMPLEMENTATION
1314
#include "Common/StbCommon.h"
1315
#endif