summaryrefslogtreecommitdiff
path: root/libs/assimp/code/AssetLib/B3D
diff options
context:
space:
mode:
Diffstat (limited to 'libs/assimp/code/AssetLib/B3D')
-rw-r--r--libs/assimp/code/AssetLib/B3D/B3DImporter.cpp744
-rw-r--r--libs/assimp/code/AssetLib/B3D/B3DImporter.h132
2 files changed, 876 insertions, 0 deletions
diff --git a/libs/assimp/code/AssetLib/B3D/B3DImporter.cpp b/libs/assimp/code/AssetLib/B3D/B3DImporter.cpp
new file mode 100644
index 0000000..c4ef75b
--- /dev/null
+++ b/libs/assimp/code/AssetLib/B3D/B3DImporter.cpp
@@ -0,0 +1,744 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2022, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file B3DImporter.cpp
+ * @brief Implementation of the b3d importer class
+ */
+
+#ifndef ASSIMP_BUILD_NO_B3D_IMPORTER
+
+// internal headers
+#include "AssetLib/B3D/B3DImporter.h"
+#include "PostProcessing/ConvertToLHProcess.h"
+#include "PostProcessing/TextureTransform.h"
+
+#include <assimp/StringUtils.h>
+#include <assimp/anim.h>
+#include <assimp/importerdesc.h>
+#include <assimp/scene.h>
+#include <assimp/DefaultLogger.hpp>
+#include <assimp/IOSystem.hpp>
+
+#include <memory>
+
+using namespace Assimp;
+using namespace std;
+
+static const aiImporterDesc desc = {
+ "BlitzBasic 3D Importer",
+ "",
+ "",
+ "http://www.blitzbasic.com/",
+ aiImporterFlags_SupportBinaryFlavour,
+ 0,
+ 0,
+ 0,
+ 0,
+ "b3d"
+};
+
+#ifdef _MSC_VER
+#pragma warning(disable : 4018)
+#endif
+
+//#define DEBUG_B3D
+
+template<typename T>
+void DeleteAllBarePointers(std::vector<T> &x) {
+ for (auto p : x) {
+ delete p;
+ }
+}
+
+B3DImporter::~B3DImporter() {
+ // empty
+}
+
+// ------------------------------------------------------------------------------------------------
+bool B3DImporter::CanRead(const std::string &pFile, IOSystem * /*pIOHandler*/, bool /*checkSig*/) const {
+ size_t pos = pFile.find_last_of('.');
+ if (pos == string::npos) {
+ return false;
+ }
+
+ string ext = pFile.substr(pos + 1);
+ if (ext.size() != 3) {
+ return false;
+ }
+
+ return (ext[0] == 'b' || ext[0] == 'B') && (ext[1] == '3') && (ext[2] == 'd' || ext[2] == 'D');
+}
+
+// ------------------------------------------------------------------------------------------------
+// Loader meta information
+const aiImporterDesc *B3DImporter::GetInfo() const {
+ return &desc;
+}
+
+// ------------------------------------------------------------------------------------------------
+void B3DImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) {
+ std::unique_ptr<IOStream> file(pIOHandler->Open(pFile));
+
+ // Check whether we can read from the file
+ if (file.get() == nullptr) {
+ throw DeadlyImportError("Failed to open B3D file ", pFile, ".");
+ }
+
+ // check whether the .b3d file is large enough to contain
+ // at least one chunk.
+ size_t fileSize = file->FileSize();
+ if (fileSize < 8) {
+ throw DeadlyImportError("B3D File is too small.");
+ }
+
+ _pos = 0;
+ _buf.resize(fileSize);
+ file->Read(&_buf[0], 1, fileSize);
+ _stack.clear();
+
+ ReadBB3D(pScene);
+}
+
+// ------------------------------------------------------------------------------------------------
+AI_WONT_RETURN void B3DImporter::Oops() {
+ throw DeadlyImportError("B3D Importer - INTERNAL ERROR");
+}
+
+// ------------------------------------------------------------------------------------------------
+AI_WONT_RETURN void B3DImporter::Fail(const string &str) {
+#ifdef DEBUG_B3D
+ ASSIMP_LOG_ERROR("Error in B3D file data: ", str);
+#endif
+ throw DeadlyImportError("B3D Importer - error in B3D file data: ", str);
+}
+
+// ------------------------------------------------------------------------------------------------
+int B3DImporter::ReadByte() {
+ if (_pos > _buf.size()) {
+ Fail("EOF");
+ }
+
+ return _buf[_pos++];
+}
+
+// ------------------------------------------------------------------------------------------------
+int B3DImporter::ReadInt() {
+ if (_pos + 4 > _buf.size()) {
+ Fail("EOF");
+ }
+
+ int n;
+ memcpy(&n, &_buf[_pos], 4);
+ _pos += 4;
+
+ return n;
+}
+
+// ------------------------------------------------------------------------------------------------
+float B3DImporter::ReadFloat() {
+ if (_pos + 4 > _buf.size()) {
+ Fail("EOF");
+ }
+
+ float n;
+ memcpy(&n, &_buf[_pos], 4);
+ _pos += 4;
+
+ return n;
+}
+
+// ------------------------------------------------------------------------------------------------
+aiVector2D B3DImporter::ReadVec2() {
+ float x = ReadFloat();
+ float y = ReadFloat();
+ return aiVector2D(x, y);
+}
+
+// ------------------------------------------------------------------------------------------------
+aiVector3D B3DImporter::ReadVec3() {
+ float x = ReadFloat();
+ float y = ReadFloat();
+ float z = ReadFloat();
+ return aiVector3D(x, y, z);
+}
+
+// ------------------------------------------------------------------------------------------------
+aiQuaternion B3DImporter::ReadQuat() {
+ // (aramis_acg) Fix to adapt the loader to changed quat orientation
+ float w = -ReadFloat();
+ float x = ReadFloat();
+ float y = ReadFloat();
+ float z = ReadFloat();
+ return aiQuaternion(w, x, y, z);
+}
+
+// ------------------------------------------------------------------------------------------------
+string B3DImporter::ReadString() {
+ if (_pos > _buf.size()) {
+ Fail("EOF");
+ }
+ string str;
+ while (_pos < _buf.size()) {
+ char c = (char)ReadByte();
+ if (!c) {
+ return str;
+ }
+ str += c;
+ }
+ return string();
+}
+
+// ------------------------------------------------------------------------------------------------
+string B3DImporter::ReadChunk() {
+ string tag;
+ for (int i = 0; i < 4; ++i) {
+ tag += char(ReadByte());
+ }
+#ifdef DEBUG_B3D
+ ASSIMP_LOG_DEBUG("ReadChunk: ", tag);
+#endif
+ unsigned sz = (unsigned)ReadInt();
+ _stack.push_back(_pos + sz);
+ return tag;
+}
+
+// ------------------------------------------------------------------------------------------------
+void B3DImporter::ExitChunk() {
+ _pos = _stack.back();
+ _stack.pop_back();
+}
+
+// ------------------------------------------------------------------------------------------------
+size_t B3DImporter::ChunkSize() {
+ return _stack.back() - _pos;
+}
+// ------------------------------------------------------------------------------------------------
+
+template <class T>
+T *B3DImporter::to_array(const vector<T> &v) {
+ if (v.empty()) {
+ return 0;
+ }
+ T *p = new T[v.size()];
+ for (size_t i = 0; i < v.size(); ++i) {
+ p[i] = v[i];
+ }
+ return p;
+}
+
+// ------------------------------------------------------------------------------------------------
+template <class T>
+T **unique_to_array(vector<std::unique_ptr<T>> &v) {
+ if (v.empty()) {
+ return 0;
+ }
+ T **p = new T *[v.size()];
+ for (size_t i = 0; i < v.size(); ++i) {
+ p[i] = v[i].release();
+ }
+ return p;
+}
+
+// ------------------------------------------------------------------------------------------------
+void B3DImporter::ReadTEXS() {
+ while (ChunkSize()) {
+ string name = ReadString();
+ /*int flags=*/ReadInt();
+ /*int blend=*/ReadInt();
+ /*aiVector2D pos=*/ReadVec2();
+ /*aiVector2D scale=*/ReadVec2();
+ /*float rot=*/ReadFloat();
+
+ _textures.push_back(name);
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+void B3DImporter::ReadBRUS() {
+ int n_texs = ReadInt();
+ if (n_texs < 0 || n_texs > 8) {
+ Fail("Bad texture count");
+ }
+ while (ChunkSize()) {
+ string name = ReadString();
+ aiVector3D color = ReadVec3();
+ float alpha = ReadFloat();
+ float shiny = ReadFloat();
+ /*int blend=**/ ReadInt();
+ int fx = ReadInt();
+
+ std::unique_ptr<aiMaterial> mat(new aiMaterial);
+
+ // Name
+ aiString ainame(name);
+ mat->AddProperty(&ainame, AI_MATKEY_NAME);
+
+ // Diffuse color
+ mat->AddProperty(&color, 1, AI_MATKEY_COLOR_DIFFUSE);
+
+ // Opacity
+ mat->AddProperty(&alpha, 1, AI_MATKEY_OPACITY);
+
+ // Specular color
+ aiColor3D speccolor(shiny, shiny, shiny);
+ mat->AddProperty(&speccolor, 1, AI_MATKEY_COLOR_SPECULAR);
+
+ // Specular power
+ float specpow = shiny * 128;
+ mat->AddProperty(&specpow, 1, AI_MATKEY_SHININESS);
+
+ // Double sided
+ if (fx & 0x10) {
+ int i = 1;
+ mat->AddProperty(&i, 1, AI_MATKEY_TWOSIDED);
+ }
+
+ //Textures
+ for (int i = 0; i < n_texs; ++i) {
+ int texid = ReadInt();
+ if (texid < -1 || (texid >= 0 && texid >= static_cast<int>(_textures.size()))) {
+ Fail("Bad texture id");
+ }
+ if (i == 0 && texid >= 0) {
+ aiString texname(_textures[texid]);
+ mat->AddProperty(&texname, AI_MATKEY_TEXTURE_DIFFUSE(0));
+ }
+ }
+ _materials.emplace_back(std::move(mat));
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+void B3DImporter::ReadVRTS() {
+ _vflags = ReadInt();
+ _tcsets = ReadInt();
+ _tcsize = ReadInt();
+ if (_tcsets < 0 || _tcsets > 4 || _tcsize < 0 || _tcsize > 4) {
+ Fail("Bad texcoord data");
+ }
+
+ int sz = 12 + (_vflags & 1 ? 12 : 0) + (_vflags & 2 ? 16 : 0) + (_tcsets * _tcsize * 4);
+ size_t n_verts = ChunkSize() / sz;
+
+ int v0 = static_cast<int>(_vertices.size());
+ _vertices.resize(v0 + n_verts);
+
+ for (unsigned int i = 0; i < n_verts; ++i) {
+ Vertex &v = _vertices[v0 + i];
+
+ memset(v.bones, 0, sizeof(v.bones));
+ memset(v.weights, 0, sizeof(v.weights));
+
+ v.vertex = ReadVec3();
+
+ if (_vflags & 1) {
+ v.normal = ReadVec3();
+ }
+
+ if (_vflags & 2) {
+ ReadQuat(); //skip v 4bytes...
+ }
+
+ for (int j = 0; j < _tcsets; ++j) {
+ float t[4] = { 0, 0, 0, 0 };
+ for (int k = 0; k < _tcsize; ++k) {
+ t[k] = ReadFloat();
+ }
+ t[1] = 1 - t[1];
+ if (!j) {
+ v.texcoords = aiVector3D(t[0], t[1], t[2]);
+ }
+ }
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+void B3DImporter::ReadTRIS(int v0) {
+ int matid = ReadInt();
+ if (matid == -1) {
+ matid = 0;
+ } else if (matid < 0 || matid >= (int)_materials.size()) {
+#ifdef DEBUG_B3D
+ ASSIMP_LOG_ERROR("material id=", matid);
+#endif
+ Fail("Bad material id");
+ }
+
+ std::unique_ptr<aiMesh> mesh(new aiMesh);
+
+ mesh->mMaterialIndex = matid;
+ mesh->mNumFaces = 0;
+ mesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
+
+ size_t n_tris = ChunkSize() / 12;
+ aiFace *face = mesh->mFaces = new aiFace[n_tris];
+
+ for (unsigned int i = 0; i < n_tris; ++i) {
+ int i0 = ReadInt() + v0;
+ int i1 = ReadInt() + v0;
+ int i2 = ReadInt() + v0;
+ if (i0 < 0 || i0 >= (int)_vertices.size() || i1 < 0 || i1 >= (int)_vertices.size() || i2 < 0 || i2 >= (int)_vertices.size()) {
+#ifdef DEBUG_B3D
+ ASSIMP_LOG_ERROR("Bad triangle index: i0=", i0, ", i1=", i1, ", i2=", i2);
+#endif
+ Fail("Bad triangle index");
+ continue;
+ }
+ face->mNumIndices = 3;
+ face->mIndices = new unsigned[3];
+ face->mIndices[0] = i0;
+ face->mIndices[1] = i1;
+ face->mIndices[2] = i2;
+ ++mesh->mNumFaces;
+ ++face;
+ }
+
+ _meshes.emplace_back(std::move(mesh));
+}
+
+// ------------------------------------------------------------------------------------------------
+void B3DImporter::ReadMESH() {
+ /*int matid=*/ReadInt();
+
+ int v0 = static_cast<int>(_vertices.size());
+
+ while (ChunkSize()) {
+ string t = ReadChunk();
+ if (t == "VRTS") {
+ ReadVRTS();
+ } else if (t == "TRIS") {
+ ReadTRIS(v0);
+ }
+ ExitChunk();
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+void B3DImporter::ReadBONE(int id) {
+ while (ChunkSize()) {
+ int vertex = ReadInt();
+ float weight = ReadFloat();
+ if (vertex < 0 || vertex >= (int)_vertices.size()) {
+ Fail("Bad vertex index");
+ }
+
+ Vertex &v = _vertices[vertex];
+ for (int i = 0; i < 4; ++i) {
+ if (!v.weights[i]) {
+ v.bones[i] = static_cast<unsigned char>(id);
+ v.weights[i] = weight;
+ break;
+ }
+ }
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+void B3DImporter::ReadKEYS(aiNodeAnim *nodeAnim) {
+ vector<aiVectorKey> trans, scale;
+ vector<aiQuatKey> rot;
+ int flags = ReadInt();
+ while (ChunkSize()) {
+ int frame = ReadInt();
+ if (flags & 1) {
+ trans.push_back(aiVectorKey(frame, ReadVec3()));
+ }
+ if (flags & 2) {
+ scale.push_back(aiVectorKey(frame, ReadVec3()));
+ }
+ if (flags & 4) {
+ rot.push_back(aiQuatKey(frame, ReadQuat()));
+ }
+ }
+
+ if (flags & 1) {
+ nodeAnim->mNumPositionKeys = static_cast<unsigned int>(trans.size());
+ nodeAnim->mPositionKeys = to_array(trans);
+ }
+
+ if (flags & 2) {
+ nodeAnim->mNumScalingKeys = static_cast<unsigned int>(scale.size());
+ nodeAnim->mScalingKeys = to_array(scale);
+ }
+
+ if (flags & 4) {
+ nodeAnim->mNumRotationKeys = static_cast<unsigned int>(rot.size());
+ nodeAnim->mRotationKeys = to_array(rot);
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+void B3DImporter::ReadANIM() {
+ /*int flags=*/ReadInt();
+ int frames = ReadInt();
+ float fps = ReadFloat();
+
+ std::unique_ptr<aiAnimation> anim(new aiAnimation);
+
+ anim->mDuration = frames;
+ anim->mTicksPerSecond = fps;
+ _animations.emplace_back(std::move(anim));
+}
+
+// ------------------------------------------------------------------------------------------------
+aiNode *B3DImporter::ReadNODE(aiNode *parent) {
+
+ string name = ReadString();
+ aiVector3D t = ReadVec3();
+ aiVector3D s = ReadVec3();
+ aiQuaternion r = ReadQuat();
+
+ aiMatrix4x4 trans, scale, rot;
+
+ aiMatrix4x4::Translation(t, trans);
+ aiMatrix4x4::Scaling(s, scale);
+ rot = aiMatrix4x4(r.GetMatrix());
+
+ aiMatrix4x4 tform = trans * rot * scale;
+
+ int nodeid = static_cast<int>(_nodes.size());
+
+ aiNode *node = new aiNode(name);
+ _nodes.push_back(node);
+
+ node->mParent = parent;
+ node->mTransformation = tform;
+
+ std::unique_ptr<aiNodeAnim> nodeAnim;
+ vector<unsigned> meshes;
+ vector<aiNode *> children;
+
+ while (ChunkSize()) {
+ const string chunk = ReadChunk();
+ if (chunk == "MESH") {
+ unsigned int n = static_cast<unsigned int>(_meshes.size());
+ ReadMESH();
+ for (unsigned int i = n; i < static_cast<unsigned int>(_meshes.size()); ++i) {
+ meshes.push_back(i);
+ }
+ } else if (chunk == "BONE") {
+ ReadBONE(nodeid);
+ } else if (chunk == "ANIM") {
+ ReadANIM();
+ } else if (chunk == "KEYS") {
+ if (!nodeAnim) {
+ nodeAnim.reset(new aiNodeAnim);
+ nodeAnim->mNodeName = node->mName;
+ }
+ ReadKEYS(nodeAnim.get());
+ } else if (chunk == "NODE") {
+ aiNode *child = ReadNODE(node);
+ children.push_back(child);
+ }
+ ExitChunk();
+ }
+
+ if (nodeAnim) {
+ _nodeAnims.emplace_back(std::move(nodeAnim));
+ }
+
+ node->mNumMeshes = static_cast<unsigned int>(meshes.size());
+ node->mMeshes = to_array(meshes);
+
+ node->mNumChildren = static_cast<unsigned int>(children.size());
+ node->mChildren = to_array(children);
+
+ return node;
+}
+
+// ------------------------------------------------------------------------------------------------
+void B3DImporter::ReadBB3D(aiScene *scene) {
+
+ _textures.clear();
+
+ _materials.clear();
+
+ _vertices.clear();
+
+ _meshes.clear();
+
+ DeleteAllBarePointers(_nodes);
+ _nodes.clear();
+
+ _nodeAnims.clear();
+
+ _animations.clear();
+
+ string t = ReadChunk();
+ if (t == "BB3D") {
+ int version = ReadInt();
+
+ if (!DefaultLogger::isNullLogger()) {
+ char dmp[128];
+ ai_snprintf(dmp, 128, "B3D file format version: %i", version);
+ ASSIMP_LOG_INFO(dmp);
+ }
+
+ while (ChunkSize()) {
+ const string chunk = ReadChunk();
+ if (chunk == "TEXS") {
+ ReadTEXS();
+ } else if (chunk == "BRUS") {
+ ReadBRUS();
+ } else if (chunk == "NODE") {
+ ReadNODE(0);
+ }
+ ExitChunk();
+ }
+ }
+ ExitChunk();
+
+ if (!_nodes.size()) {
+ Fail("No nodes");
+ }
+
+ if (!_meshes.size()) {
+ Fail("No meshes");
+ }
+
+ // Fix nodes/meshes/bones
+ for (size_t i = 0; i < _nodes.size(); ++i) {
+ aiNode *node = _nodes[i];
+
+ for (size_t j = 0; j < node->mNumMeshes; ++j) {
+ aiMesh *mesh = _meshes[node->mMeshes[j]].get();
+
+ int n_tris = mesh->mNumFaces;
+ int n_verts = mesh->mNumVertices = n_tris * 3;
+
+ aiVector3D *mv = mesh->mVertices = new aiVector3D[n_verts], *mn = 0, *mc = 0;
+ if (_vflags & 1) {
+ mn = mesh->mNormals = new aiVector3D[n_verts];
+ }
+ if (_tcsets) {
+ mc = mesh->mTextureCoords[0] = new aiVector3D[n_verts];
+ }
+
+ aiFace *face = mesh->mFaces;
+
+ vector<vector<aiVertexWeight>> vweights(_nodes.size());
+
+ for (int vertIdx = 0; vertIdx < n_verts; vertIdx += 3) {
+ for (int faceIndex = 0; faceIndex < 3; ++faceIndex) {
+ Vertex &v = _vertices[face->mIndices[faceIndex]];
+
+ *mv++ = v.vertex;
+ if (mn) *mn++ = v.normal;
+ if (mc) *mc++ = v.texcoords;
+
+ face->mIndices[faceIndex] = vertIdx + faceIndex;
+
+ for (int k = 0; k < 4; ++k) {
+ if (!v.weights[k])
+ break;
+
+ int bone = v.bones[k];
+ float weight = v.weights[k];
+
+ vweights[bone].push_back(aiVertexWeight(vertIdx + faceIndex, weight));
+ }
+ }
+ ++face;
+ }
+
+ vector<aiBone *> bones;
+ for (size_t weightIndx = 0; weightIndx < vweights.size(); ++weightIndx) {
+ vector<aiVertexWeight> &weights = vweights[weightIndx];
+ if (!weights.size()) {
+ continue;
+ }
+
+ aiBone *bone = new aiBone;
+ bones.push_back(bone);
+
+ aiNode *bnode = _nodes[weightIndx];
+
+ bone->mName = bnode->mName;
+ bone->mNumWeights = static_cast<unsigned int>(weights.size());
+ bone->mWeights = to_array(weights);
+
+ aiMatrix4x4 mat = bnode->mTransformation;
+ while (bnode->mParent) {
+ bnode = bnode->mParent;
+ mat = bnode->mTransformation * mat;
+ }
+ bone->mOffsetMatrix = mat.Inverse();
+ }
+ mesh->mNumBones = static_cast<unsigned int>(bones.size());
+ mesh->mBones = to_array(bones);
+ }
+ }
+
+ //nodes
+ scene->mRootNode = _nodes[0];
+ _nodes.clear(); // node ownership now belongs to scene
+
+ //material
+ if (!_materials.size()) {
+ _materials.emplace_back(std::unique_ptr<aiMaterial>(new aiMaterial));
+ }
+ scene->mNumMaterials = static_cast<unsigned int>(_materials.size());
+ scene->mMaterials = unique_to_array(_materials);
+
+ //meshes
+ scene->mNumMeshes = static_cast<unsigned int>(_meshes.size());
+ scene->mMeshes = unique_to_array(_meshes);
+
+ //animations
+ if (_animations.size() == 1 && _nodeAnims.size()) {
+
+ aiAnimation *anim = _animations.back().get();
+ anim->mNumChannels = static_cast<unsigned int>(_nodeAnims.size());
+ anim->mChannels = unique_to_array(_nodeAnims);
+
+ scene->mNumAnimations = static_cast<unsigned int>(_animations.size());
+ scene->mAnimations = unique_to_array(_animations);
+ }
+
+ // convert to RH
+ MakeLeftHandedProcess makeleft;
+ makeleft.Execute(scene);
+
+ FlipWindingOrderProcess flip;
+ flip.Execute(scene);
+}
+
+#endif // !! ASSIMP_BUILD_NO_B3D_IMPORTER
diff --git a/libs/assimp/code/AssetLib/B3D/B3DImporter.h b/libs/assimp/code/AssetLib/B3D/B3DImporter.h
new file mode 100644
index 0000000..e47d907
--- /dev/null
+++ b/libs/assimp/code/AssetLib/B3D/B3DImporter.h
@@ -0,0 +1,132 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2022, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/**
+ * @file Definition of the .b3d importer class.
+ */
+#pragma once
+#ifndef AI_B3DIMPORTER_H_INC
+#define AI_B3DIMPORTER_H_INC
+
+#include <assimp/types.h>
+#include <assimp/mesh.h>
+#include <assimp/material.h>
+#include <assimp/BaseImporter.h>
+
+#include <memory>
+#include <vector>
+
+struct aiNodeAnim;
+struct aiNode;
+struct aiAnimation;
+
+namespace Assimp{
+
+class B3DImporter : public BaseImporter{
+public:
+ B3DImporter() = default;
+ ~B3DImporter() override;
+ bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const override;
+
+protected:
+ const aiImporterDesc* GetInfo () const override;
+ void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) override;
+
+private:
+
+ int ReadByte();
+ int ReadInt();
+ float ReadFloat();
+ aiVector2D ReadVec2();
+ aiVector3D ReadVec3();
+ aiQuaternion ReadQuat();
+ std::string ReadString();
+ std::string ReadChunk();
+ void ExitChunk();
+ size_t ChunkSize();
+
+ template<class T>
+ T *to_array( const std::vector<T> &v );
+
+ struct Vertex{
+ aiVector3D vertex;
+ aiVector3D normal;
+ aiVector3D texcoords;
+ unsigned char bones[4];
+ float weights[4];
+ };
+
+ AI_WONT_RETURN void Oops() AI_WONT_RETURN_SUFFIX;
+ AI_WONT_RETURN void Fail(const std::string &str) AI_WONT_RETURN_SUFFIX;
+
+ void ReadTEXS();
+ void ReadBRUS();
+
+ void ReadVRTS();
+ void ReadTRIS( int v0 );
+ void ReadMESH();
+ void ReadBONE( int id );
+ void ReadKEYS( aiNodeAnim *nodeAnim );
+ void ReadANIM();
+
+ aiNode *ReadNODE( aiNode *parent );
+
+ void ReadBB3D( aiScene *scene );
+
+ size_t _pos;
+ std::vector<unsigned char> _buf;
+ std::vector<size_t> _stack;
+
+ std::vector<std::string> _textures;
+ std::vector<std::unique_ptr<aiMaterial> > _materials;
+
+ int _vflags,_tcsets,_tcsize;
+ std::vector<Vertex> _vertices;
+
+ std::vector<aiNode*> _nodes;
+ std::vector<std::unique_ptr<aiMesh> > _meshes;
+ std::vector<std::unique_ptr<aiNodeAnim> > _nodeAnims;
+ std::vector<std::unique_ptr<aiAnimation> > _animations;
+};
+
+}
+
+#endif