mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-07-14 16:14:38 +00:00
update assimp to 5.2.3 Bugfix-Release
This commit is contained in:
parent
3f796d2a06
commit
f297476092
1150 changed files with 165834 additions and 112019 deletions
442
Engine/lib/assimp/code/AssetLib/M3D/M3DExporter.cpp
Normal file
442
Engine/lib/assimp/code/AssetLib/M3D/M3DExporter.cpp
Normal file
|
|
@ -0,0 +1,442 @@
|
|||
/*
|
||||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2022, assimp team
|
||||
Copyright (c) 2019 bzt
|
||||
|
||||
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.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
#ifndef ASSIMP_BUILD_NO_EXPORT
|
||||
#ifndef ASSIMP_BUILD_NO_M3D_EXPORTER
|
||||
|
||||
#define M3D_IMPLEMENTATION
|
||||
#define M3D_NOIMPORTER
|
||||
#define M3D_EXPORTER
|
||||
#ifndef ASSIMP_BUILD_NO_M3D_IMPORTER
|
||||
#define M3D_NODUP
|
||||
|
||||
|
||||
// Header files, standard library.
|
||||
#include <memory> // shared_ptr
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <assimp/Exceptional.h> // DeadlyExportError
|
||||
#include <assimp/StreamWriter.h> // StreamWriterLE
|
||||
#include <assimp/material.h> // aiTextureType
|
||||
#include <assimp/mesh.h>
|
||||
#include <assimp/scene.h>
|
||||
#include <assimp/version.h> // aiGetVersion
|
||||
#include <assimp/DefaultLogger.hpp>
|
||||
#include <assimp/Exporter.hpp>
|
||||
#include <assimp/IOSystem.hpp>
|
||||
|
||||
#include "M3DExporter.h"
|
||||
#include "M3DMaterials.h"
|
||||
#include "M3DWrapper.h"
|
||||
|
||||
// RESOURCES:
|
||||
// https://gitlab.com/bztsrc/model3d/blob/master/docs/m3d_format.md
|
||||
// https://gitlab.com/bztsrc/model3d/blob/master/docs/a3d_format.md
|
||||
|
||||
/*
|
||||
* Currently supports static meshes, vertex colors, materials, textures
|
||||
*
|
||||
* For animation, it would require the following conversions:
|
||||
* - aiNode (bones) -> m3d_t.bone (with parent id, position vector and orientation quaternion)
|
||||
* - aiMesh.aiBone -> m3d_t.skin (per vertex, with bone id, weight pairs)
|
||||
* - aiAnimation -> m3d_action (frame with timestamp and list of bone id, position, orientation
|
||||
* triplets, instead of per bone timestamp + lists)
|
||||
*/
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Conversion functions
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// helper to add a vertex (private to NodeWalk)
|
||||
m3dv_t *AddVrtx(m3dv_t *vrtx, uint32_t *numvrtx, m3dv_t *v, uint32_t *idx) {
|
||||
if (v->x == (M3D_FLOAT)-0.0) v->x = (M3D_FLOAT)0.0;
|
||||
if (v->y == (M3D_FLOAT)-0.0) v->y = (M3D_FLOAT)0.0;
|
||||
if (v->z == (M3D_FLOAT)-0.0) v->z = (M3D_FLOAT)0.0;
|
||||
if (v->w == (M3D_FLOAT)-0.0) v->w = (M3D_FLOAT)0.0;
|
||||
vrtx = (m3dv_t *)M3D_REALLOC(vrtx, ((*numvrtx) + 1) * sizeof(m3dv_t));
|
||||
memcpy(&vrtx[*numvrtx], v, sizeof(m3dv_t));
|
||||
*idx = *numvrtx;
|
||||
(*numvrtx)++;
|
||||
return vrtx;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// helper to add a tmap (private to NodeWalk)
|
||||
m3dti_t *AddTmap(m3dti_t *tmap, uint32_t *numtmap, m3dti_t *ti, uint32_t *idx) {
|
||||
tmap = (m3dti_t *)M3D_REALLOC(tmap, ((*numtmap) + 1) * sizeof(m3dti_t));
|
||||
memcpy(&tmap[*numtmap], ti, sizeof(m3dti_t));
|
||||
*idx = *numtmap;
|
||||
(*numtmap)++;
|
||||
return tmap;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// convert aiColor4D into uint32_t
|
||||
uint32_t mkColor(aiColor4D *c) {
|
||||
return ((uint8_t)(c->a * 255) << 24L) |
|
||||
((uint8_t)(c->b * 255) << 16L) |
|
||||
((uint8_t)(c->g * 255) << 8L) |
|
||||
((uint8_t)(c->r * 255) << 0L);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// add a material property to the output
|
||||
void addProp(m3dm_t *m, uint8_t type, uint32_t value) {
|
||||
unsigned int i;
|
||||
i = m->numprop++;
|
||||
m->prop = (m3dp_t *)M3D_REALLOC(m->prop, m->numprop * sizeof(m3dp_t));
|
||||
if (!m->prop) {
|
||||
throw DeadlyExportError("memory allocation error");
|
||||
}
|
||||
m->prop[i].type = type;
|
||||
m->prop[i].value.num = value;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// convert aiString to identifier safe C string. This is a duplication of _m3d_safestr
|
||||
char *SafeStr(aiString str, bool isStrict) {
|
||||
char *s = (char *)&str.data;
|
||||
char *d, *ret;
|
||||
int i, len;
|
||||
|
||||
for (len = str.length + 1; *s && (*s == ' ' || *s == '\t'); s++, len--)
|
||||
;
|
||||
if (len > 255) len = 255;
|
||||
ret = (char *)M3D_MALLOC(len + 1);
|
||||
if (!ret) {
|
||||
throw DeadlyExportError("memory allocation error");
|
||||
}
|
||||
for (i = 0, d = ret; i < len && *s && *s != '\r' && *s != '\n'; s++, d++, i++) {
|
||||
*d = isStrict && (*s == ' ' || *s == '\t' || *s == '/' || *s == '\\') ? '_' : (*s == '\t' ? ' ' : *s);
|
||||
}
|
||||
for (; d > ret && (*(d - 1) == ' ' || *(d - 1) == '\t'); d--)
|
||||
;
|
||||
*d = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// add a material to the output
|
||||
M3D_INDEX addMaterial(const Assimp::M3DWrapper &m3d, const aiMaterial *mat) {
|
||||
unsigned int mi = M3D_NOTDEFINED;
|
||||
aiColor4D c;
|
||||
aiString name;
|
||||
ai_real f;
|
||||
char *fn;
|
||||
|
||||
if (mat && mat->Get(AI_MATKEY_NAME, name) == AI_SUCCESS && name.length &&
|
||||
strcmp((char *)&name.data, AI_DEFAULT_MATERIAL_NAME)) {
|
||||
// check if we have saved a material by this name. This has to be done
|
||||
// because only the referenced materials should be added to the output
|
||||
for (unsigned int i = 0; i < m3d->nummaterial; i++)
|
||||
if (!strcmp((char *)&name.data, m3d->material[i].name)) {
|
||||
mi = i;
|
||||
break;
|
||||
}
|
||||
// if not found, add the material to the output
|
||||
if (mi == M3D_NOTDEFINED) {
|
||||
unsigned int k;
|
||||
mi = m3d->nummaterial++;
|
||||
m3d->material = (m3dm_t *)M3D_REALLOC(m3d->material, m3d->nummaterial * sizeof(m3dm_t));
|
||||
if (!m3d->material) {
|
||||
throw DeadlyExportError("memory allocation error");
|
||||
}
|
||||
m3d->material[mi].name = SafeStr(name, true);
|
||||
m3d->material[mi].numprop = 0;
|
||||
m3d->material[mi].prop = nullptr;
|
||||
// iterate through the material property table and see what we got
|
||||
for (k = 0; k < 15; k++) {
|
||||
unsigned int j;
|
||||
if (m3d_propertytypes[k].format == m3dpf_map)
|
||||
continue;
|
||||
if (aiProps[k].pKey) {
|
||||
switch (m3d_propertytypes[k].format) {
|
||||
case m3dpf_color:
|
||||
if (mat->Get(aiProps[k].pKey, aiProps[k].type,
|
||||
aiProps[k].index, c) == AI_SUCCESS)
|
||||
addProp(&m3d->material[mi],
|
||||
m3d_propertytypes[k].id, mkColor(&c));
|
||||
break;
|
||||
case m3dpf_float:
|
||||
if (mat->Get(aiProps[k].pKey, aiProps[k].type,
|
||||
aiProps[k].index, f) == AI_SUCCESS) {
|
||||
uint32_t f_uint32;
|
||||
memcpy(&f_uint32, &f, sizeof(uint32_t));
|
||||
addProp(&m3d->material[mi],
|
||||
m3d_propertytypes[k].id,
|
||||
/* not (uint32_t)f, because we don't want to convert
|
||||
* it, we want to see it as 32 bits of memory */
|
||||
f_uint32);
|
||||
}
|
||||
break;
|
||||
case m3dpf_uint8:
|
||||
if (mat->Get(aiProps[k].pKey, aiProps[k].type,
|
||||
aiProps[k].index, j) == AI_SUCCESS) {
|
||||
// special conversion for illumination model property
|
||||
if (m3d_propertytypes[k].id == m3dp_il) {
|
||||
switch (j) {
|
||||
case aiShadingMode_NoShading: j = 0; break;
|
||||
case aiShadingMode_Phong: j = 2; break;
|
||||
default: j = 1; break;
|
||||
}
|
||||
}
|
||||
addProp(&m3d->material[mi],
|
||||
m3d_propertytypes[k].id, j);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (mat->Get(aiProps[k].pKey, aiProps[k].type,
|
||||
aiProps[k].index, j) == AI_SUCCESS)
|
||||
addProp(&m3d->material[mi],
|
||||
m3d_propertytypes[k].id, j);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (aiTxProps[k].pKey &&
|
||||
mat->GetTexture((aiTextureType)aiTxProps[k].type,
|
||||
aiTxProps[k].index, &name, nullptr, nullptr, nullptr,
|
||||
nullptr, nullptr) == AI_SUCCESS) {
|
||||
unsigned int i;
|
||||
for (j = name.length - 1; j > 0 && name.data[j] != '.'; j++)
|
||||
;
|
||||
if (j && name.data[j] == '.' &&
|
||||
(name.data[j + 1] == 'p' || name.data[j + 1] == 'P') &&
|
||||
(name.data[j + 1] == 'n' || name.data[j + 1] == 'N') &&
|
||||
(name.data[j + 1] == 'g' || name.data[j + 1] == 'G'))
|
||||
name.data[j] = 0;
|
||||
// do we have this texture saved already?
|
||||
fn = SafeStr(name, true);
|
||||
for (j = 0, i = M3D_NOTDEFINED; j < m3d->numtexture; j++)
|
||||
if (!strcmp(fn, m3d->texture[j].name)) {
|
||||
i = j;
|
||||
free(fn);
|
||||
break;
|
||||
}
|
||||
if (i == M3D_NOTDEFINED) {
|
||||
i = m3d->numtexture++;
|
||||
m3d->texture = (m3dtx_t *)M3D_REALLOC(
|
||||
m3d->texture,
|
||||
m3d->numtexture * sizeof(m3dtx_t));
|
||||
if (!m3d->texture) {
|
||||
throw DeadlyExportError("memory allocation error");
|
||||
}
|
||||
// we don't need the texture itself, only its name
|
||||
m3d->texture[i].name = fn;
|
||||
m3d->texture[i].w = 0;
|
||||
m3d->texture[i].h = 0;
|
||||
m3d->texture[i].d = nullptr;
|
||||
}
|
||||
addProp(&m3d->material[mi],
|
||||
m3d_propertytypes[k].id + 128, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return mi;
|
||||
}
|
||||
|
||||
namespace Assimp {
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Worker function for exporting a scene to binary M3D.
|
||||
// Prototyped and registered in Exporter.cpp
|
||||
void ExportSceneM3D(
|
||||
const char *pFile,
|
||||
IOSystem *pIOSystem,
|
||||
const aiScene *pScene,
|
||||
const ExportProperties *pProperties) {
|
||||
// initialize the exporter
|
||||
M3DExporter exporter(pScene, pProperties);
|
||||
|
||||
// perform binary export
|
||||
exporter.doExport(pFile, pIOSystem, false);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Worker function for exporting a scene to ASCII A3D.
|
||||
// Prototyped and registered in Exporter.cpp
|
||||
void ExportSceneM3DA(
|
||||
const char *pFile,
|
||||
IOSystem *pIOSystem,
|
||||
const aiScene *pScene,
|
||||
const ExportProperties *pProperties
|
||||
|
||||
) {
|
||||
// initialize the exporter
|
||||
M3DExporter exporter(pScene, pProperties);
|
||||
|
||||
// perform ascii export
|
||||
exporter.doExport(pFile, pIOSystem, true);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
M3DExporter::M3DExporter(const aiScene *pScene, const ExportProperties *pProperties) :
|
||||
mScene(pScene),
|
||||
mProperties(pProperties),
|
||||
outfile() {
|
||||
// empty
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void M3DExporter::doExport(
|
||||
const char *pFile,
|
||||
IOSystem *pIOSystem,
|
||||
bool toAscii) {
|
||||
// TODO: convert mProperties into M3D_EXP_* flags
|
||||
(void)mProperties;
|
||||
|
||||
// open the indicated file for writing (in binary / ASCII mode)
|
||||
outfile.reset(pIOSystem->Open(pFile, toAscii ? "wt" : "wb"));
|
||||
if (!outfile) {
|
||||
throw DeadlyExportError("could not open output .m3d file: " + std::string(pFile));
|
||||
}
|
||||
|
||||
M3DWrapper m3d;
|
||||
if (!m3d) {
|
||||
throw DeadlyExportError("memory allocation error");
|
||||
}
|
||||
m3d->name = SafeStr(mScene->mRootNode->mName, false);
|
||||
|
||||
// Create a model from assimp structures
|
||||
aiMatrix4x4 m;
|
||||
NodeWalk(m3d, mScene->mRootNode, m);
|
||||
|
||||
// serialize the structures
|
||||
unsigned int size;
|
||||
unsigned char *output = m3d.Save(M3D_EXP_FLOAT, M3D_EXP_EXTRA | (toAscii ? M3D_EXP_ASCII : 0), size);
|
||||
|
||||
if (!output || size < 8) {
|
||||
throw DeadlyExportError("unable to serialize into Model 3D");
|
||||
}
|
||||
|
||||
// Write out serialized model
|
||||
outfile->Write(output, size, 1);
|
||||
|
||||
// explicitly release file pointer,
|
||||
// so we don't have to rely on class destruction.
|
||||
outfile.reset();
|
||||
|
||||
M3D_FREE(m3d->name);
|
||||
m3d->name = nullptr;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// recursive node walker
|
||||
void M3DExporter::NodeWalk(const M3DWrapper &m3d, const aiNode *pNode, aiMatrix4x4 m) {
|
||||
aiMatrix4x4 nm = m * pNode->mTransformation;
|
||||
|
||||
for (unsigned int i = 0; i < pNode->mNumMeshes; i++) {
|
||||
const aiMesh *mesh = mScene->mMeshes[pNode->mMeshes[i]];
|
||||
unsigned int mi = M3D_NOTDEFINED;
|
||||
if (mScene->mMaterials) {
|
||||
// get the material for this mesh
|
||||
mi = addMaterial(m3d, mScene->mMaterials[mesh->mMaterialIndex]);
|
||||
}
|
||||
// iterate through the mesh faces
|
||||
for (unsigned int j = 0; j < mesh->mNumFaces; j++) {
|
||||
unsigned int n;
|
||||
const aiFace *face = &(mesh->mFaces[j]);
|
||||
// only triangle meshes supported for now
|
||||
if (face->mNumIndices != 3) {
|
||||
throw DeadlyExportError("use aiProcess_Triangulate before export");
|
||||
}
|
||||
// add triangle to the output
|
||||
n = m3d->numface++;
|
||||
m3d->face = (m3df_t *)M3D_REALLOC(m3d->face,
|
||||
m3d->numface * sizeof(m3df_t));
|
||||
if (!m3d->face) {
|
||||
throw DeadlyExportError("memory allocation error");
|
||||
}
|
||||
/* set all index to -1 by default */
|
||||
m3d->face[n].vertex[0] = m3d->face[n].vertex[1] = m3d->face[n].vertex[2] =
|
||||
m3d->face[n].normal[0] = m3d->face[n].normal[1] = m3d->face[n].normal[2] =
|
||||
m3d->face[n].texcoord[0] = m3d->face[n].texcoord[1] = m3d->face[n].texcoord[2] = M3D_UNDEF;
|
||||
m3d->face[n].materialid = mi;
|
||||
for (unsigned int k = 0; k < face->mNumIndices; k++) {
|
||||
// get the vertex's index
|
||||
unsigned int l = face->mIndices[k];
|
||||
unsigned int idx;
|
||||
m3dv_t vertex;
|
||||
m3dti_t ti;
|
||||
// multiply the position vector by the transformation matrix
|
||||
aiVector3D v = mesh->mVertices[l];
|
||||
v *= nm;
|
||||
vertex.x = v.x;
|
||||
vertex.y = v.y;
|
||||
vertex.z = v.z;
|
||||
vertex.w = 1.0;
|
||||
vertex.color = 0;
|
||||
vertex.skinid = M3D_UNDEF;
|
||||
// add color if defined
|
||||
if (mesh->HasVertexColors(0))
|
||||
vertex.color = mkColor(&mesh->mColors[0][l]);
|
||||
// save the vertex to the output
|
||||
m3d->vertex = AddVrtx(m3d->vertex, &m3d->numvertex,
|
||||
&vertex, &idx);
|
||||
m3d->face[n].vertex[k] = (M3D_INDEX)idx;
|
||||
// do we have texture coordinates?
|
||||
if (mesh->HasTextureCoords(0)) {
|
||||
ti.u = mesh->mTextureCoords[0][l].x;
|
||||
ti.v = mesh->mTextureCoords[0][l].y;
|
||||
m3d->tmap = AddTmap(m3d->tmap, &m3d->numtmap, &ti, &idx);
|
||||
m3d->face[n].texcoord[k] = (M3D_INDEX)idx;
|
||||
}
|
||||
// do we have normal vectors?
|
||||
if (mesh->HasNormals()) {
|
||||
vertex.x = mesh->mNormals[l].x;
|
||||
vertex.y = mesh->mNormals[l].y;
|
||||
vertex.z = mesh->mNormals[l].z;
|
||||
vertex.color = 0;
|
||||
m3d->vertex = AddVrtx(m3d->vertex, &m3d->numvertex, &vertex, &idx);
|
||||
m3d->face[n].normal[k] = (M3D_INDEX)idx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// repeat for the children nodes
|
||||
for (unsigned int i = 0; i < pNode->mNumChildren; i++) {
|
||||
NodeWalk(m3d, pNode->mChildren[i], nm);
|
||||
}
|
||||
}
|
||||
} // namespace Assimp
|
||||
#endif
|
||||
#endif // ASSIMP_BUILD_NO_M3D_EXPORTER
|
||||
#endif // ASSIMP_BUILD_NO_EXPORT
|
||||
93
Engine/lib/assimp/code/AssetLib/M3D/M3DExporter.h
Normal file
93
Engine/lib/assimp/code/AssetLib/M3D/M3DExporter.h
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2022, assimp team
|
||||
Copyright (c) 2019 bzt
|
||||
|
||||
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 M3DExporter.h
|
||||
* @brief Declares the exporter class to write a scene to a Model 3D file
|
||||
*/
|
||||
#ifndef AI_M3DEXPORTER_H_INC
|
||||
#define AI_M3DEXPORTER_H_INC
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_M3D_IMPORTER
|
||||
#ifndef ASSIMP_BUILD_NO_M3D_EXPORTER
|
||||
|
||||
#include <assimp/types.h>
|
||||
#include <assimp/StreamWriter.h> // StreamWriterLE
|
||||
#include <assimp/Exceptional.h> // DeadlyExportError
|
||||
|
||||
#include <memory> // shared_ptr
|
||||
|
||||
struct aiScene;
|
||||
struct aiNode;
|
||||
struct aiMaterial;
|
||||
struct aiFace;
|
||||
|
||||
namespace Assimp {
|
||||
class IOSystem;
|
||||
class IOStream;
|
||||
class ExportProperties;
|
||||
|
||||
class M3DWrapper;
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
/** Helper class to export a given scene to an M3D file. */
|
||||
// ---------------------------------------------------------------------
|
||||
class M3DExporter {
|
||||
public:
|
||||
/// Constructor for a specific scene to export
|
||||
M3DExporter(const aiScene* pScene, const ExportProperties* pProperties);
|
||||
// call this to do the actual export
|
||||
void doExport(const char* pFile, IOSystem* pIOSystem, bool toAscii);
|
||||
|
||||
private:
|
||||
const aiScene* mScene; // the scene to export
|
||||
const ExportProperties* mProperties; // currently unused
|
||||
std::shared_ptr<IOStream> outfile; // file to write to
|
||||
|
||||
// helper to do the recursive walking
|
||||
void NodeWalk(const M3DWrapper &m3d, const aiNode* pNode, aiMatrix4x4 m);
|
||||
};
|
||||
}
|
||||
|
||||
#endif // #ifndef ASSIMP_BUILD_NO_M3D_IMPORTER
|
||||
#endif // ASSIMP_BUILD_NO_M3D_EXPORTER
|
||||
|
||||
#endif // AI_M3DEXPORTER_H_INC
|
||||
789
Engine/lib/assimp/code/AssetLib/M3D/M3DImporter.cpp
Normal file
789
Engine/lib/assimp/code/AssetLib/M3D/M3DImporter.cpp
Normal file
|
|
@ -0,0 +1,789 @@
|
|||
/*
|
||||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2022, assimp team
|
||||
Copyright (c) 2019 bzt
|
||||
|
||||
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.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_M3D_IMPORTER
|
||||
|
||||
#define M3D_IMPLEMENTATION
|
||||
#define M3D_NONORMALS /* leave the post-processing to Assimp */
|
||||
#define M3D_NOWEIGHTS
|
||||
#define M3D_NOANIMATION
|
||||
|
||||
#include <assimp/DefaultIOSystem.h>
|
||||
#include <assimp/IOStreamBuffer.h>
|
||||
#include <assimp/ai_assert.h>
|
||||
#include <assimp/importerdesc.h>
|
||||
#include <assimp/scene.h>
|
||||
#include <assimp/DefaultLogger.hpp>
|
||||
#include <assimp/Importer.hpp>
|
||||
#include <memory>
|
||||
|
||||
#include "M3DImporter.h"
|
||||
#include "M3DMaterials.h"
|
||||
#include "M3DWrapper.h"
|
||||
|
||||
// RESOURCES:
|
||||
// https://gitlab.com/bztsrc/model3d/blob/master/docs/m3d_format.md
|
||||
// https://gitlab.com/bztsrc/model3d/blob/master/docs/a3d_format.md
|
||||
|
||||
/*
|
||||
Unfortunately aiNode has bone structures and meshes too, yet we can't assign
|
||||
the mesh to a bone aiNode as a skin may refer to several aiNodes. Therefore
|
||||
I've decided to import into this structure:
|
||||
|
||||
aiScene->mRootNode
|
||||
| |->mMeshes (all the meshes)
|
||||
| \->children (empty if there's no skeleton imported, no meshes)
|
||||
| \->skeleton root aiNode*
|
||||
| |->bone aiNode
|
||||
| | \->subbone aiNode
|
||||
| |->bone aiNode
|
||||
| | ...
|
||||
| \->bone aiNode
|
||||
\->mMeshes[]
|
||||
\->aiBone, referencing mesh-less aiNodes from above
|
||||
|
||||
* - normally one, but if a model has several skeleton roots, then all of them
|
||||
are listed in aiScene->mRootNode->children, but all without meshes
|
||||
*/
|
||||
|
||||
static const aiImporterDesc desc = {
|
||||
"Model 3D Importer",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
aiImporterFlags_SupportTextFlavour | aiImporterFlags_SupportBinaryFlavour,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
"m3d a3d"
|
||||
};
|
||||
|
||||
namespace Assimp {
|
||||
|
||||
using namespace std;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Default constructor
|
||||
M3DImporter::M3DImporter() :
|
||||
mScene(nullptr) {
|
||||
// empty
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Returns true, if file is a binary or ASCII Model 3D file.
|
||||
bool M3DImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {
|
||||
// don't use CheckMagicToken because that checks with swapped bytes too, leading to false
|
||||
// positives. This magic is not uint32_t, but char[4], so memcmp is the best way
|
||||
std::unique_ptr<IOStream> pStream(pIOHandler->Open(pFile, "rb"));
|
||||
unsigned char data[4];
|
||||
if (4 != pStream->Read(data, 1, 4)) {
|
||||
return false;
|
||||
}
|
||||
return !memcmp(data, "3DMO", 4) /* bin */
|
||||
#ifdef M3D_ASCII
|
||||
|| !memcmp(data, "3dmo", 4) /* ASCII */
|
||||
#endif
|
||||
;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
const aiImporterDesc *M3DImporter::GetInfo() const {
|
||||
return &desc;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Model 3D import implementation
|
||||
void M3DImporter::InternReadFile(const std::string &file, aiScene *pScene, IOSystem *pIOHandler) {
|
||||
// Read file into memory
|
||||
std::unique_ptr<IOStream> pStream(pIOHandler->Open(file, "rb"));
|
||||
if (!pStream.get()) {
|
||||
throw DeadlyImportError("Failed to open file ", file, ".");
|
||||
}
|
||||
|
||||
// Get the file-size and validate it, throwing an exception when fails
|
||||
size_t fileSize = pStream->FileSize();
|
||||
if (fileSize < 8) {
|
||||
throw DeadlyImportError("M3D-file ", file, " is too small.");
|
||||
}
|
||||
std::vector<unsigned char> buffer(fileSize);
|
||||
if (fileSize != pStream->Read(buffer.data(), 1, fileSize)) {
|
||||
throw DeadlyImportError("Failed to read the file ", file, ".");
|
||||
}
|
||||
// extra check for binary format's first 8 bytes. Not done for the ASCII variant
|
||||
if (!memcmp(buffer.data(), "3DMO", 4) && memcmp(buffer.data() + 4, &fileSize, 4)) {
|
||||
throw DeadlyImportError("Bad binary header in file ", file, ".");
|
||||
}
|
||||
// make sure there's a terminator zero character, as input must be ASCIIZ
|
||||
if (!memcmp(buffer.data(), "3dmo", 4)) {
|
||||
buffer.push_back(0);
|
||||
}
|
||||
|
||||
// Get the path for external assets
|
||||
std::string folderName("./");
|
||||
std::string::size_type pos = file.find_last_of("\\/");
|
||||
if (pos != std::string::npos) {
|
||||
folderName = file.substr(0, pos);
|
||||
if (!folderName.empty()) {
|
||||
pIOHandler->PushDirectory(folderName);
|
||||
}
|
||||
}
|
||||
|
||||
//DefaultLogger::create("/dev/stderr", Logger::VERBOSE);
|
||||
ASSIMP_LOG_DEBUG("M3D: loading ", file);
|
||||
|
||||
// let the C SDK do the hard work for us
|
||||
M3DWrapper m3d(pIOHandler, buffer);
|
||||
|
||||
if (!m3d) {
|
||||
throw DeadlyImportError("Unable to parse ", file, " as M3D.");
|
||||
}
|
||||
|
||||
// create the root node
|
||||
pScene->mRootNode = new aiNode;
|
||||
pScene->mRootNode->mName = aiString(m3d.Name());
|
||||
pScene->mRootNode->mTransformation = aiMatrix4x4();
|
||||
pScene->mRootNode->mNumChildren = 0;
|
||||
mScene = pScene;
|
||||
|
||||
ASSIMP_LOG_DEBUG("M3D: root node ", m3d.Name());
|
||||
|
||||
// now we just have to fill up the Assimp structures in pScene
|
||||
importMaterials(m3d);
|
||||
importTextures(m3d);
|
||||
importBones(m3d, M3D_NOTDEFINED, pScene->mRootNode);
|
||||
importMeshes(m3d);
|
||||
importAnimations(m3d);
|
||||
|
||||
// Pop directory stack
|
||||
if (pIOHandler->StackSize() > 0) {
|
||||
pIOHandler->PopDirectory();
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// convert materials. properties are converted using a static table in M3DMaterials.h
|
||||
void M3DImporter::importMaterials(const M3DWrapper &m3d) {
|
||||
unsigned int i, j, k, l, n;
|
||||
m3dm_t *m;
|
||||
aiString name = aiString(AI_DEFAULT_MATERIAL_NAME);
|
||||
aiColor4D c;
|
||||
ai_real f;
|
||||
|
||||
ai_assert(mScene != nullptr);
|
||||
ai_assert(m3d);
|
||||
|
||||
mScene->mNumMaterials = m3d->nummaterial + 1;
|
||||
mScene->mMaterials = new aiMaterial *[mScene->mNumMaterials];
|
||||
|
||||
ASSIMP_LOG_DEBUG("M3D: importMaterials ", mScene->mNumMaterials);
|
||||
|
||||
// add a default material as first
|
||||
aiMaterial *defaultMat = new aiMaterial;
|
||||
defaultMat->AddProperty(&name, AI_MATKEY_NAME);
|
||||
c.a = 1.0f;
|
||||
c.b = c.g = c.r = 0.6f;
|
||||
defaultMat->AddProperty(&c, 1, AI_MATKEY_COLOR_DIFFUSE);
|
||||
mScene->mMaterials[0] = defaultMat;
|
||||
|
||||
if (!m3d->nummaterial || !m3d->material) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < m3d->nummaterial; i++) {
|
||||
m = &m3d->material[i];
|
||||
aiMaterial *newMat = new aiMaterial;
|
||||
name.Set(std::string(m->name));
|
||||
newMat->AddProperty(&name, AI_MATKEY_NAME);
|
||||
for (j = 0; j < m->numprop; j++) {
|
||||
// look up property type
|
||||
// 0 - 127 scalar values,
|
||||
// 128 - 255 the same properties but for texture maps
|
||||
k = 256;
|
||||
for (l = 0; l < sizeof(m3d_propertytypes) / sizeof(m3d_propertytypes[0]); l++)
|
||||
if (m->prop[j].type == m3d_propertytypes[l].id ||
|
||||
m->prop[j].type == m3d_propertytypes[l].id + 128) {
|
||||
k = l;
|
||||
break;
|
||||
}
|
||||
// should never happen, but be safe than sorry
|
||||
if (k == 256)
|
||||
continue;
|
||||
|
||||
// scalar properties
|
||||
if (m->prop[j].type < 128 && aiProps[k].pKey) {
|
||||
switch (m3d_propertytypes[k].format) {
|
||||
case m3dpf_color:
|
||||
c = mkColor(m->prop[j].value.color);
|
||||
newMat->AddProperty(&c, 1, aiProps[k].pKey, aiProps[k].type, aiProps[k].index);
|
||||
break;
|
||||
case m3dpf_float:
|
||||
f = m->prop[j].value.fnum;
|
||||
newMat->AddProperty(&f, 1, aiProps[k].pKey, aiProps[k].type, aiProps[k].index);
|
||||
break;
|
||||
default:
|
||||
n = m->prop[j].value.num;
|
||||
if (m->prop[j].type == m3dp_il) {
|
||||
switch (n) {
|
||||
case 0:
|
||||
n = aiShadingMode_NoShading;
|
||||
break;
|
||||
case 2:
|
||||
n = aiShadingMode_Phong;
|
||||
break;
|
||||
default:
|
||||
n = aiShadingMode_Gouraud;
|
||||
break;
|
||||
}
|
||||
}
|
||||
newMat->AddProperty(&n, 1, aiProps[k].pKey, aiProps[k].type, aiProps[k].index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// texture map properties
|
||||
if (m->prop[j].type >= 128 && aiTxProps[k].pKey &&
|
||||
// extra check, should never happen, do we have the referred texture?
|
||||
m->prop[j].value.textureid < m3d->numtexture &&
|
||||
m3d->texture[m->prop[j].value.textureid].name) {
|
||||
name.Set(std::string(std::string(m3d->texture[m->prop[j].value.textureid].name) + ".png"));
|
||||
newMat->AddProperty(&name, aiTxProps[k].pKey, aiTxProps[k].type, aiTxProps[k].index);
|
||||
n = 0;
|
||||
newMat->AddProperty(&n, 1, _AI_MATKEY_UVWSRC_BASE, aiProps[k].type, aiProps[k].index);
|
||||
}
|
||||
}
|
||||
mScene->mMaterials[i + 1] = newMat;
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// import textures, this is the simplest of all
|
||||
void M3DImporter::importTextures(const M3DWrapper &m3d) {
|
||||
unsigned int i;
|
||||
const char *formatHint[] = {
|
||||
"rgba0800",
|
||||
"rgba0808",
|
||||
"rgba8880",
|
||||
"rgba8888"
|
||||
};
|
||||
m3dtx_t *t;
|
||||
|
||||
ai_assert(mScene != nullptr);
|
||||
ai_assert(m3d);
|
||||
|
||||
mScene->mNumTextures = m3d->numtexture;
|
||||
ASSIMP_LOG_DEBUG("M3D: importTextures ", mScene->mNumTextures);
|
||||
|
||||
if (!m3d->numtexture || !m3d->texture) {
|
||||
return;
|
||||
}
|
||||
|
||||
mScene->mTextures = new aiTexture *[m3d->numtexture];
|
||||
for (i = 0; i < m3d->numtexture; i++) {
|
||||
unsigned int j, k;
|
||||
t = &m3d->texture[i];
|
||||
aiTexture *tx = new aiTexture;
|
||||
tx->mFilename = aiString(std::string(t->name) + ".png");
|
||||
if (!t->w || !t->h || !t->f || !t->d) {
|
||||
/* without ASSIMP_USE_M3D_READFILECB, we only have the filename, but no texture data ever */
|
||||
tx->mWidth = 0;
|
||||
tx->mHeight = 0;
|
||||
memcpy(tx->achFormatHint, "png\000", 4);
|
||||
tx->pcData = nullptr;
|
||||
} else {
|
||||
/* if we have the texture loaded, set format hint and pcData too */
|
||||
tx->mWidth = t->w;
|
||||
tx->mHeight = t->h;
|
||||
strcpy(tx->achFormatHint, formatHint[t->f - 1]);
|
||||
tx->pcData = new aiTexel[tx->mWidth * tx->mHeight];
|
||||
for (j = k = 0; j < tx->mWidth * tx->mHeight; j++) {
|
||||
switch (t->f) {
|
||||
case 1: tx->pcData[j].g = t->d[k++]; break;
|
||||
case 2:
|
||||
tx->pcData[j].g = t->d[k++];
|
||||
tx->pcData[j].a = t->d[k++];
|
||||
break;
|
||||
case 3:
|
||||
tx->pcData[j].r = t->d[k++];
|
||||
tx->pcData[j].g = t->d[k++];
|
||||
tx->pcData[j].b = t->d[k++];
|
||||
tx->pcData[j].a = 255;
|
||||
break;
|
||||
case 4:
|
||||
tx->pcData[j].r = t->d[k++];
|
||||
tx->pcData[j].g = t->d[k++];
|
||||
tx->pcData[j].b = t->d[k++];
|
||||
tx->pcData[j].a = t->d[k++];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
mScene->mTextures[i] = tx;
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// this is tricky. M3D has a global vertex and UV list, and faces are indexing them
|
||||
// individually. In assimp there're per mesh vertex and UV lists, and they must be
|
||||
// indexed simultaneously.
|
||||
void M3DImporter::importMeshes(const M3DWrapper &m3d) {
|
||||
ASSIMP_LOG_DEBUG("M3D: importMeshes ", m3d->numface);
|
||||
|
||||
if (!m3d->numface || !m3d->face || !m3d->numvertex || !m3d->vertex) {
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned int i, j, k, l, numpoly = 3, lastMat = M3D_INDEXMAX;
|
||||
std::vector<aiMesh *> *meshes = new std::vector<aiMesh *>();
|
||||
std::vector<aiFace> *faces = nullptr;
|
||||
std::vector<aiVector3D> *vertices = nullptr;
|
||||
std::vector<aiVector3D> *normals = nullptr;
|
||||
std::vector<aiVector3D> *texcoords = nullptr;
|
||||
std::vector<aiColor4D> *colors = nullptr;
|
||||
std::vector<unsigned int> *vertexids = nullptr;
|
||||
aiMesh *pMesh = nullptr;
|
||||
|
||||
ai_assert(mScene != nullptr);
|
||||
ai_assert(m3d);
|
||||
ai_assert(mScene->mRootNode != nullptr);
|
||||
|
||||
for (i = 0; i < m3d->numface; i++) {
|
||||
// we must switch mesh if material changes
|
||||
if (lastMat != m3d->face[i].materialid) {
|
||||
lastMat = m3d->face[i].materialid;
|
||||
if (pMesh && vertices && vertices->size() && faces && faces->size()) {
|
||||
populateMesh(m3d, pMesh, faces, vertices, normals, texcoords, colors, vertexids);
|
||||
meshes->push_back(pMesh);
|
||||
delete faces;
|
||||
delete vertices;
|
||||
delete normals;
|
||||
delete texcoords;
|
||||
delete colors;
|
||||
delete vertexids; // this is not stored in pMesh, just to collect bone vertices
|
||||
}
|
||||
pMesh = new aiMesh;
|
||||
pMesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
|
||||
pMesh->mMaterialIndex = lastMat + 1;
|
||||
faces = new std::vector<aiFace>();
|
||||
vertices = new std::vector<aiVector3D>();
|
||||
normals = new std::vector<aiVector3D>();
|
||||
texcoords = new std::vector<aiVector3D>();
|
||||
colors = new std::vector<aiColor4D>();
|
||||
vertexids = new std::vector<unsigned int>();
|
||||
}
|
||||
// add a face to temporary vector
|
||||
aiFace *pFace = new aiFace;
|
||||
pFace->mNumIndices = numpoly;
|
||||
pFace->mIndices = new unsigned int[numpoly];
|
||||
for (j = 0; j < numpoly; j++) {
|
||||
aiVector3D pos, uv, norm;
|
||||
k = static_cast<unsigned int>(vertices->size());
|
||||
pFace->mIndices[j] = k;
|
||||
l = m3d->face[i].vertex[j];
|
||||
if (l >= m3d->numvertex) continue;
|
||||
pos.x = m3d->vertex[l].x;
|
||||
pos.y = m3d->vertex[l].y;
|
||||
pos.z = m3d->vertex[l].z;
|
||||
vertices->push_back(pos);
|
||||
colors->push_back(mkColor(m3d->vertex[l].color));
|
||||
// add a bone to temporary vector
|
||||
if (m3d->vertex[l].skinid != M3D_UNDEF && m3d->vertex[l].skinid != M3D_INDEXMAX && m3d->skin && m3d->bone) {
|
||||
// this is complicated, because M3D stores a list of bone id / weight pairs per
|
||||
// vertex but assimp uses lists of local vertex id/weight pairs per local bone list
|
||||
vertexids->push_back(l);
|
||||
}
|
||||
l = m3d->face[i].texcoord[j];
|
||||
if (l != M3D_UNDEF && l < m3d->numtmap) {
|
||||
uv.x = m3d->tmap[l].u;
|
||||
uv.y = m3d->tmap[l].v;
|
||||
uv.z = 0.0;
|
||||
texcoords->push_back(uv);
|
||||
}
|
||||
l = m3d->face[i].normal[j];
|
||||
if (l != M3D_UNDEF && l < m3d->numvertex) {
|
||||
norm.x = m3d->vertex[l].x;
|
||||
norm.y = m3d->vertex[l].y;
|
||||
norm.z = m3d->vertex[l].z;
|
||||
normals->push_back(norm);
|
||||
}
|
||||
}
|
||||
faces->push_back(*pFace);
|
||||
delete pFace;
|
||||
}
|
||||
// if there's data left in the temporary vectors, flush them
|
||||
if (pMesh && vertices->size() && faces->size()) {
|
||||
populateMesh(m3d, pMesh, faces, vertices, normals, texcoords, colors, vertexids);
|
||||
meshes->push_back(pMesh);
|
||||
}
|
||||
|
||||
// create global mesh list in scene
|
||||
mScene->mNumMeshes = static_cast<unsigned int>(meshes->size());
|
||||
mScene->mMeshes = new aiMesh *[mScene->mNumMeshes];
|
||||
std::copy(meshes->begin(), meshes->end(), mScene->mMeshes);
|
||||
|
||||
// create mesh indices in root node
|
||||
mScene->mRootNode->mNumMeshes = static_cast<unsigned int>(meshes->size());
|
||||
mScene->mRootNode->mMeshes = new unsigned int[meshes->size()];
|
||||
for (i = 0; i < meshes->size(); i++) {
|
||||
mScene->mRootNode->mMeshes[i] = i;
|
||||
}
|
||||
|
||||
delete meshes;
|
||||
if (faces) delete faces;
|
||||
if (vertices) delete vertices;
|
||||
if (normals) delete normals;
|
||||
if (texcoords) delete texcoords;
|
||||
if (colors) delete colors;
|
||||
if (vertexids) delete vertexids;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// a reentrant node parser. Otherwise this is simple
|
||||
void M3DImporter::importBones(const M3DWrapper &m3d, unsigned int parentid, aiNode *pParent) {
|
||||
unsigned int i, n;
|
||||
|
||||
ai_assert(pParent != nullptr);
|
||||
ai_assert(mScene != nullptr);
|
||||
ai_assert(m3d);
|
||||
|
||||
ASSIMP_LOG_DEBUG("M3D: importBones ", m3d->numbone, " parentid ", (int)parentid);
|
||||
|
||||
if (!m3d->numbone || !m3d->bone) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (n = 0, i = parentid + 1; i < m3d->numbone; i++) {
|
||||
if (m3d->bone[i].parent == parentid) {
|
||||
n++;
|
||||
}
|
||||
}
|
||||
pParent->mChildren = new aiNode *[n];
|
||||
|
||||
for (i = parentid + 1; i < m3d->numbone; i++) {
|
||||
if (m3d->bone[i].parent == parentid) {
|
||||
aiNode *pChild = new aiNode;
|
||||
pChild->mParent = pParent;
|
||||
pChild->mName = aiString(std::string(m3d->bone[i].name));
|
||||
convertPose(m3d, &pChild->mTransformation, m3d->bone[i].pos, m3d->bone[i].ori);
|
||||
pChild->mNumChildren = 0;
|
||||
pParent->mChildren[pParent->mNumChildren] = pChild;
|
||||
pParent->mNumChildren++;
|
||||
importBones(m3d, i, pChild);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// this is another headache. M3D stores list of changed bone id/position/orientation triplets and
|
||||
// a timestamp per frame, but assimp needs timestamp and lists of position, orientation lists per
|
||||
// bone, so we have to convert between the two conceptually different representation forms
|
||||
void M3DImporter::importAnimations(const M3DWrapper &m3d) {
|
||||
unsigned int i, j, k, l, pos, ori;
|
||||
double t;
|
||||
m3da_t *a;
|
||||
|
||||
ai_assert(mScene != nullptr);
|
||||
ai_assert(m3d);
|
||||
|
||||
mScene->mNumAnimations = m3d->numaction;
|
||||
|
||||
ASSIMP_LOG_DEBUG("M3D: importAnimations ", mScene->mNumAnimations);
|
||||
|
||||
if (!m3d->numaction || !m3d->action || !m3d->numbone || !m3d->bone || !m3d->vertex) {
|
||||
return;
|
||||
}
|
||||
|
||||
mScene->mAnimations = new aiAnimation *[m3d->numaction];
|
||||
for (i = 0; i < m3d->numaction; i++) {
|
||||
a = &m3d->action[i];
|
||||
aiAnimation *pAnim = new aiAnimation;
|
||||
pAnim->mName = aiString(std::string(a->name));
|
||||
pAnim->mDuration = ((double)a->durationmsec) / 10;
|
||||
pAnim->mTicksPerSecond = 100;
|
||||
// now we know how many bones are referenced in this animation
|
||||
pAnim->mNumChannels = m3d->numbone;
|
||||
pAnim->mChannels = new aiNodeAnim *[pAnim->mNumChannels];
|
||||
for (l = 0; l < m3d->numbone; l++) {
|
||||
unsigned int n;
|
||||
pAnim->mChannels[l] = new aiNodeAnim;
|
||||
pAnim->mChannels[l]->mNodeName = aiString(std::string(m3d->bone[l].name));
|
||||
// now n is the size of positions / orientations arrays
|
||||
pAnim->mChannels[l]->mNumPositionKeys = pAnim->mChannels[l]->mNumRotationKeys = a->numframe;
|
||||
pAnim->mChannels[l]->mPositionKeys = new aiVectorKey[a->numframe];
|
||||
pAnim->mChannels[l]->mRotationKeys = new aiQuatKey[a->numframe];
|
||||
pos = m3d->bone[l].pos;
|
||||
ori = m3d->bone[l].ori;
|
||||
for (j = n = 0; j < a->numframe; j++) {
|
||||
t = ((double)a->frame[j].msec) / 10;
|
||||
for (k = 0; k < a->frame[j].numtransform; k++) {
|
||||
if (a->frame[j].transform[k].boneid == l) {
|
||||
pos = a->frame[j].transform[k].pos;
|
||||
ori = a->frame[j].transform[k].ori;
|
||||
}
|
||||
}
|
||||
if (pos >= m3d->numvertex || ori >= m3d->numvertex) continue;
|
||||
m3dv_t *v = &m3d->vertex[pos];
|
||||
m3dv_t *q = &m3d->vertex[ori];
|
||||
pAnim->mChannels[l]->mPositionKeys[j].mTime = t;
|
||||
pAnim->mChannels[l]->mPositionKeys[j].mValue.x = v->x;
|
||||
pAnim->mChannels[l]->mPositionKeys[j].mValue.y = v->y;
|
||||
pAnim->mChannels[l]->mPositionKeys[j].mValue.z = v->z;
|
||||
pAnim->mChannels[l]->mRotationKeys[j].mTime = t;
|
||||
pAnim->mChannels[l]->mRotationKeys[j].mValue.w = q->w;
|
||||
pAnim->mChannels[l]->mRotationKeys[j].mValue.x = q->x;
|
||||
pAnim->mChannels[l]->mRotationKeys[j].mValue.y = q->y;
|
||||
pAnim->mChannels[l]->mRotationKeys[j].mValue.z = q->z;
|
||||
} // foreach frame
|
||||
} // foreach bones
|
||||
mScene->mAnimations[i] = pAnim;
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// convert uint32_t into aiColor4D
|
||||
aiColor4D M3DImporter::mkColor(uint32_t c) {
|
||||
aiColor4D color;
|
||||
color.a = ((float)((c >> 24) & 0xff)) / 255;
|
||||
color.b = ((float)((c >> 16) & 0xff)) / 255;
|
||||
color.g = ((float)((c >> 8) & 0xff)) / 255;
|
||||
color.r = ((float)((c >> 0) & 0xff)) / 255;
|
||||
return color;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// convert a position id and orientation id into a 4 x 4 transformation matrix
|
||||
void M3DImporter::convertPose(const M3DWrapper &m3d, aiMatrix4x4 *m, unsigned int posid, unsigned int orientid) {
|
||||
ai_assert(m != nullptr);
|
||||
ai_assert(m3d);
|
||||
ai_assert(posid != M3D_UNDEF);
|
||||
ai_assert(posid < m3d->numvertex);
|
||||
ai_assert(orientid != M3D_UNDEF);
|
||||
ai_assert(orientid < m3d->numvertex);
|
||||
if (!m3d->numvertex || !m3d->vertex)
|
||||
return;
|
||||
m3dv_t *p = &m3d->vertex[posid];
|
||||
m3dv_t *q = &m3d->vertex[orientid];
|
||||
|
||||
/* quaternion to matrix. Do NOT use aiQuaternion to aiMatrix3x3, gives bad results */
|
||||
if (q->x == 0.0 && q->y == 0.0 && q->z >= 0.7071065 && q->z <= 0.7071075 && q->w == 0.0) {
|
||||
m->a2 = m->a3 = m->b1 = m->b3 = m->c1 = m->c2 = 0.0;
|
||||
m->a1 = m->b2 = m->c3 = -1.0;
|
||||
} else {
|
||||
m->a1 = 1 - 2 * (q->y * q->y + q->z * q->z);
|
||||
if (m->a1 > -M3D_EPSILON && m->a1 < M3D_EPSILON) m->a1 = 0.0;
|
||||
m->a2 = 2 * (q->x * q->y - q->z * q->w);
|
||||
if (m->a2 > -M3D_EPSILON && m->a2 < M3D_EPSILON) m->a2 = 0.0;
|
||||
m->a3 = 2 * (q->x * q->z + q->y * q->w);
|
||||
if (m->a3 > -M3D_EPSILON && m->a3 < M3D_EPSILON) m->a3 = 0.0;
|
||||
m->b1 = 2 * (q->x * q->y + q->z * q->w);
|
||||
if (m->b1 > -M3D_EPSILON && m->b1 < M3D_EPSILON) m->b1 = 0.0;
|
||||
m->b2 = 1 - 2 * (q->x * q->x + q->z * q->z);
|
||||
if (m->b2 > -M3D_EPSILON && m->b2 < M3D_EPSILON) m->b2 = 0.0;
|
||||
m->b3 = 2 * (q->y * q->z - q->x * q->w);
|
||||
if (m->b3 > -M3D_EPSILON && m->b3 < M3D_EPSILON) m->b3 = 0.0;
|
||||
m->c1 = 2 * (q->x * q->z - q->y * q->w);
|
||||
if (m->c1 > -M3D_EPSILON && m->c1 < M3D_EPSILON) m->c1 = 0.0;
|
||||
m->c2 = 2 * (q->y * q->z + q->x * q->w);
|
||||
if (m->c2 > -M3D_EPSILON && m->c2 < M3D_EPSILON) m->c2 = 0.0;
|
||||
m->c3 = 1 - 2 * (q->x * q->x + q->y * q->y);
|
||||
if (m->c3 > -M3D_EPSILON && m->c3 < M3D_EPSILON) m->c3 = 0.0;
|
||||
}
|
||||
|
||||
/* set translation */
|
||||
m->a4 = p->x;
|
||||
m->b4 = p->y;
|
||||
m->c4 = p->z;
|
||||
|
||||
m->d1 = 0;
|
||||
m->d2 = 0;
|
||||
m->d3 = 0;
|
||||
m->d4 = 1;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// find a node by name
|
||||
aiNode *M3DImporter::findNode(aiNode *pNode, const aiString &name) {
|
||||
ai_assert(pNode != nullptr);
|
||||
ai_assert(mScene != nullptr);
|
||||
|
||||
if (pNode->mName == name) {
|
||||
return pNode;
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < pNode->mNumChildren; i++) {
|
||||
aiNode *pChild = findNode(pNode->mChildren[i], name);
|
||||
if (pChild) {
|
||||
return pChild;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// fills up offsetmatrix in mBones
|
||||
void M3DImporter::calculateOffsetMatrix(aiNode *pNode, aiMatrix4x4 *m) {
|
||||
ai_assert(pNode != nullptr);
|
||||
ai_assert(mScene != nullptr);
|
||||
|
||||
if (pNode->mParent) {
|
||||
calculateOffsetMatrix(pNode->mParent, m);
|
||||
*m *= pNode->mTransformation;
|
||||
} else {
|
||||
*m = pNode->mTransformation;
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// because M3D has a global mesh, global vertex ids and stores materialid on the face, we need
|
||||
// temporary lists to collect data for an aiMesh, which requires local arrays and local indices
|
||||
// this function fills up an aiMesh with those temporary lists
|
||||
void M3DImporter::populateMesh(const M3DWrapper &m3d, aiMesh *pMesh, std::vector<aiFace> *faces, std::vector<aiVector3D> *vertices,
|
||||
std::vector<aiVector3D> *normals, std::vector<aiVector3D> *texcoords, std::vector<aiColor4D> *colors,
|
||||
std::vector<unsigned int> *vertexids) {
|
||||
|
||||
ai_assert(pMesh != nullptr);
|
||||
ai_assert(faces != nullptr);
|
||||
ai_assert(vertices != nullptr);
|
||||
ai_assert(normals != nullptr);
|
||||
ai_assert(texcoords != nullptr);
|
||||
ai_assert(colors != nullptr);
|
||||
ai_assert(vertexids != nullptr);
|
||||
ai_assert(m3d);
|
||||
|
||||
ASSIMP_LOG_DEBUG("M3D: populateMesh numvertices ", vertices->size(), " numfaces ", faces->size(),
|
||||
" numnormals ", normals->size(), " numtexcoord ", texcoords->size(), " numbones ", m3d->numbone);
|
||||
|
||||
if (vertices->size() && faces->size()) {
|
||||
pMesh->mNumFaces = static_cast<unsigned int>(faces->size());
|
||||
pMesh->mFaces = new aiFace[pMesh->mNumFaces];
|
||||
std::copy(faces->begin(), faces->end(), pMesh->mFaces);
|
||||
pMesh->mNumVertices = static_cast<unsigned int>(vertices->size());
|
||||
pMesh->mVertices = new aiVector3D[pMesh->mNumVertices];
|
||||
std::copy(vertices->begin(), vertices->end(), pMesh->mVertices);
|
||||
if (normals->size() == vertices->size()) {
|
||||
pMesh->mNormals = new aiVector3D[pMesh->mNumVertices];
|
||||
std::copy(normals->begin(), normals->end(), pMesh->mNormals);
|
||||
}
|
||||
if (texcoords->size() == vertices->size()) {
|
||||
pMesh->mTextureCoords[0] = new aiVector3D[pMesh->mNumVertices];
|
||||
std::copy(texcoords->begin(), texcoords->end(), pMesh->mTextureCoords[0]);
|
||||
pMesh->mNumUVComponents[0] = 2;
|
||||
}
|
||||
if (colors->size() == vertices->size()) {
|
||||
pMesh->mColors[0] = new aiColor4D[pMesh->mNumVertices];
|
||||
std::copy(colors->begin(), colors->end(), pMesh->mColors[0]);
|
||||
}
|
||||
// this is complicated, because M3D stores a list of bone id / weight pairs per
|
||||
// vertex but assimp uses lists of local vertex id/weight pairs per local bone list
|
||||
pMesh->mNumBones = m3d->numbone;
|
||||
// we need aiBone with mOffsetMatrix for bones without weights as well
|
||||
if (pMesh->mNumBones && m3d->numbone && m3d->bone) {
|
||||
pMesh->mBones = new aiBone *[pMesh->mNumBones];
|
||||
for (unsigned int i = 0; i < m3d->numbone; i++) {
|
||||
aiNode *pNode;
|
||||
pMesh->mBones[i] = new aiBone;
|
||||
pMesh->mBones[i]->mName = aiString(std::string(m3d->bone[i].name));
|
||||
pMesh->mBones[i]->mNumWeights = 0;
|
||||
pNode = findNode(mScene->mRootNode, pMesh->mBones[i]->mName);
|
||||
if (pNode) {
|
||||
calculateOffsetMatrix(pNode, &pMesh->mBones[i]->mOffsetMatrix);
|
||||
pMesh->mBones[i]->mOffsetMatrix.Inverse();
|
||||
} else
|
||||
pMesh->mBones[i]->mOffsetMatrix = aiMatrix4x4();
|
||||
}
|
||||
if (vertexids->size() && m3d->numvertex && m3d->vertex && m3d->numskin && m3d->skin) {
|
||||
unsigned int i, j;
|
||||
// first count how many vertices we have per bone
|
||||
for (i = 0; i < vertexids->size(); i++) {
|
||||
if (vertexids->at(i) >= m3d->numvertex) {
|
||||
continue;
|
||||
}
|
||||
unsigned int s = m3d->vertex[vertexids->at(i)].skinid;
|
||||
if (s != M3D_UNDEF && s != M3D_INDEXMAX) {
|
||||
for (unsigned int k = 0; k < M3D_NUMBONE && m3d->skin[s].weight[k] > 0.0; k++) {
|
||||
aiString name = aiString(std::string(m3d->bone[m3d->skin[s].boneid[k]].name));
|
||||
for (j = 0; j < pMesh->mNumBones; j++) {
|
||||
if (pMesh->mBones[j]->mName == name) {
|
||||
pMesh->mBones[j]->mNumWeights++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// allocate mWeights
|
||||
for (j = 0; j < pMesh->mNumBones; j++) {
|
||||
aiBone *pBone = pMesh->mBones[j];
|
||||
if (pBone->mNumWeights) {
|
||||
pBone->mWeights = new aiVertexWeight[pBone->mNumWeights];
|
||||
pBone->mNumWeights = 0;
|
||||
}
|
||||
}
|
||||
// fill up with data
|
||||
for (i = 0; i < vertexids->size(); i++) {
|
||||
if (vertexids->at(i) >= m3d->numvertex) continue;
|
||||
unsigned int s = m3d->vertex[vertexids->at(i)].skinid;
|
||||
if (s != M3D_UNDEF && s != M3D_INDEXMAX && s < m3d->numskin) {
|
||||
for (unsigned int k = 0; k < M3D_NUMBONE && m3d->skin[s].weight[k] > 0.0; k++) {
|
||||
if (m3d->skin[s].boneid[k] >= m3d->numbone) continue;
|
||||
aiString name = aiString(std::string(m3d->bone[m3d->skin[s].boneid[k]].name));
|
||||
for (j = 0; j < pMesh->mNumBones; j++) {
|
||||
if (pMesh->mBones[j]->mName == name) {
|
||||
aiBone *pBone = pMesh->mBones[j];
|
||||
pBone->mWeights[pBone->mNumWeights].mVertexId = i;
|
||||
pBone->mWeights[pBone->mNumWeights].mWeight = m3d->skin[s].weight[k];
|
||||
pBone->mNumWeights++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} // foreach skin
|
||||
}
|
||||
} // foreach vertexids
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
} // Namespace Assimp
|
||||
|
||||
#endif // !! ASSIMP_BUILD_NO_M3D_IMPORTER
|
||||
105
Engine/lib/assimp/code/AssetLib/M3D/M3DImporter.h
Normal file
105
Engine/lib/assimp/code/AssetLib/M3D/M3DImporter.h
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2022, assimp team
|
||||
Copyright (c) 2019 bzt
|
||||
|
||||
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 M3DImporter.h
|
||||
* @brief Declares the importer class to read a scene from a Model 3D file
|
||||
*/
|
||||
#ifndef AI_M3DIMPORTER_H_INC
|
||||
#define AI_M3DIMPORTER_H_INC
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_M3D_IMPORTER
|
||||
|
||||
#include <assimp/BaseImporter.h>
|
||||
#include <assimp/material.h>
|
||||
#include <vector>
|
||||
|
||||
struct aiMesh;
|
||||
struct aiNode;
|
||||
struct aiMaterial;
|
||||
struct aiFace;
|
||||
|
||||
namespace Assimp {
|
||||
|
||||
class M3DWrapper;
|
||||
|
||||
class M3DImporter : public BaseImporter {
|
||||
public:
|
||||
/// \brief Default constructor
|
||||
M3DImporter();
|
||||
~M3DImporter() override {}
|
||||
|
||||
/// \brief Returns whether the class can handle the format of the given file.
|
||||
/// \remark See BaseImporter::CanRead() for details.
|
||||
bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const override;
|
||||
|
||||
protected:
|
||||
//! \brief Appends the supported extension.
|
||||
const aiImporterDesc *GetInfo() const override;
|
||||
|
||||
//! \brief File import implementation.
|
||||
void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) override;
|
||||
|
||||
private:
|
||||
void importMaterials(const M3DWrapper &m3d);
|
||||
void importTextures(const M3DWrapper &m3d);
|
||||
void importMeshes(const M3DWrapper &m3d);
|
||||
void importBones(const M3DWrapper &m3d, unsigned int parentid, aiNode *pParent);
|
||||
void importAnimations(const M3DWrapper &m3d);
|
||||
|
||||
// helper functions
|
||||
aiColor4D mkColor(uint32_t c);
|
||||
void convertPose(const M3DWrapper &m3d, aiMatrix4x4 *m, unsigned int posid, unsigned int orientid);
|
||||
aiNode *findNode(aiNode *pNode, const aiString &name);
|
||||
void calculateOffsetMatrix(aiNode *pNode, aiMatrix4x4 *m);
|
||||
void populateMesh(const M3DWrapper &m3d, aiMesh *pMesh, std::vector<aiFace> *faces, std::vector<aiVector3D> *verteces,
|
||||
std::vector<aiVector3D> *normals, std::vector<aiVector3D> *texcoords, std::vector<aiColor4D> *colors,
|
||||
std::vector<unsigned int> *vertexids);
|
||||
|
||||
private:
|
||||
aiScene *mScene = nullptr; // the scene to import to
|
||||
};
|
||||
|
||||
} // Namespace Assimp
|
||||
|
||||
#endif // ASSIMP_BUILD_NO_M3D_IMPORTER
|
||||
|
||||
#endif // AI_M3DIMPORTER_H_INC
|
||||
106
Engine/lib/assimp/code/AssetLib/M3D/M3DMaterials.h
Normal file
106
Engine/lib/assimp/code/AssetLib/M3D/M3DMaterials.h
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2022, assimp team
|
||||
Copyright (c) 2019 bzt
|
||||
|
||||
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 M3DMaterials.h
|
||||
* @brief Declares the Assimp and Model 3D file material type relations
|
||||
*/
|
||||
#ifndef AI_M3DMATERIALS_H_INC
|
||||
#define AI_M3DMATERIALS_H_INC
|
||||
|
||||
/*
|
||||
* In the m3d.h header, there's a static array which defines the material
|
||||
* properties, called m3d_propertytypes. These must have the same size, and
|
||||
* list the matching Assimp materials for those properties. Used by both the
|
||||
* M3DImporter and the M3DExporter, so you have to define these relations
|
||||
* only once. D.R.Y. and K.I.S.S.
|
||||
*/
|
||||
typedef struct {
|
||||
const char *pKey;
|
||||
unsigned int type;
|
||||
unsigned int index;
|
||||
} aiMatProp;
|
||||
|
||||
/* --- Scalar Properties --- !!!!! must match m3d_propertytypes !!!!! */
|
||||
static const aiMatProp aiProps[] = {
|
||||
{ AI_MATKEY_COLOR_DIFFUSE }, /* m3dp_Kd */
|
||||
{ AI_MATKEY_COLOR_AMBIENT }, /* m3dp_Ka */
|
||||
{ AI_MATKEY_COLOR_SPECULAR }, /* m3dp_Ks */
|
||||
{ AI_MATKEY_SHININESS }, /* m3dp_Ns */
|
||||
{ AI_MATKEY_COLOR_EMISSIVE }, /* m3dp_Ke */
|
||||
{ AI_MATKEY_COLOR_REFLECTIVE }, /* m3dp_Tf */
|
||||
{ AI_MATKEY_BUMPSCALING }, /* m3dp_Km */
|
||||
{ AI_MATKEY_OPACITY }, /* m3dp_d */
|
||||
{ AI_MATKEY_SHADING_MODEL }, /* m3dp_il */
|
||||
|
||||
{ nullptr, 0, 0 }, /* m3dp_Pr */
|
||||
{ AI_MATKEY_REFLECTIVITY }, /* m3dp_Pm */
|
||||
{ nullptr, 0, 0 }, /* m3dp_Ps */
|
||||
{ AI_MATKEY_REFRACTI }, /* m3dp_Ni */
|
||||
{ nullptr, 0, 0 }, /* m3dp_Nt */
|
||||
{ nullptr, 0, 0 },
|
||||
{ nullptr, 0, 0 },
|
||||
{ nullptr, 0, 0 }
|
||||
};
|
||||
|
||||
/* --- Texture Map Properties --- !!!!! must match m3d_propertytypes !!!!! */
|
||||
static const aiMatProp aiTxProps[] = {
|
||||
{ AI_MATKEY_TEXTURE_DIFFUSE(0) }, /* m3dp_map_Kd */
|
||||
{ AI_MATKEY_TEXTURE(aiTextureType_AMBIENT_OCCLUSION,0) },/* m3dp_map_Ka */
|
||||
{ AI_MATKEY_TEXTURE_SPECULAR(0) }, /* m3dp_map_Ks */
|
||||
{ AI_MATKEY_TEXTURE_SHININESS(0) }, /* m3dp_map_Ns */
|
||||
{ AI_MATKEY_TEXTURE_EMISSIVE(0) }, /* m3dp_map_Ke */
|
||||
{ nullptr, 0, 0 }, /* m3dp_map_Tf */
|
||||
{ AI_MATKEY_TEXTURE_HEIGHT(0) }, /* m3dp_bump */
|
||||
{ AI_MATKEY_TEXTURE_OPACITY(0) }, /* m3dp_map_d */
|
||||
{ AI_MATKEY_TEXTURE_NORMALS(0) }, /* m3dp_map_N */
|
||||
|
||||
{ AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE_ROUGHNESS,0) },/* m3dp_map_Pr */
|
||||
{ AI_MATKEY_TEXTURE(aiTextureType_METALNESS,0) }, /* m3dp_map_Pm */
|
||||
{ nullptr, 0, 0 }, /* m3dp_map_Ps */
|
||||
{ AI_MATKEY_TEXTURE(aiTextureType_REFLECTION,0) }, /* m3dp_map_Ni */
|
||||
{ nullptr, 0, 0 }, /* m3dp_map_Nt */
|
||||
{ nullptr, 0, 0 },
|
||||
{ nullptr, 0, 0 },
|
||||
{ nullptr, 0, 0 }
|
||||
};
|
||||
|
||||
#endif // AI_M3DMATERIALS_H_INC
|
||||
152
Engine/lib/assimp/code/AssetLib/M3D/M3DWrapper.cpp
Normal file
152
Engine/lib/assimp/code/AssetLib/M3D/M3DWrapper.cpp
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
/*
|
||||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2022, assimp team
|
||||
Copyright (c) 2019 bzt
|
||||
|
||||
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.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
#ifndef ASSIMP_BUILD_NO_M3D_IMPORTER
|
||||
#if !(ASSIMP_BUILD_NO_EXPORT || ASSIMP_BUILD_NO_M3D_EXPORTER)
|
||||
|
||||
#include "M3DWrapper.h"
|
||||
|
||||
#include <assimp/DefaultIOSystem.h>
|
||||
#include <assimp/IOStreamBuffer.h>
|
||||
#include <assimp/ai_assert.h>
|
||||
|
||||
#ifdef ASSIMP_USE_M3D_READFILECB
|
||||
|
||||
#if (__cplusplus >= 201103L) || !defined(_MSC_VER) || (_MSC_VER >= 1900) // C++11 and MSVC 2015 onwards
|
||||
#define threadlocal thread_local
|
||||
#else
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1800) // there's an alternative for MSVC 2013
|
||||
#define threadlocal __declspec(thread)
|
||||
#else
|
||||
#define threadlocal
|
||||
#endif
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
|
||||
// workaround: the M3D SDK expects a C callback, but we want to use Assimp::IOSystem to implement that
|
||||
threadlocal void *m3dimporter_pIOHandler;
|
||||
|
||||
unsigned char *m3dimporter_readfile(char *fn, unsigned int *size) {
|
||||
ai_assert(nullptr != fn);
|
||||
ai_assert(nullptr != size);
|
||||
std::string file(fn);
|
||||
std::unique_ptr<Assimp::IOStream> pStream(
|
||||
(reinterpret_cast<Assimp::IOSystem *>(m3dimporter_pIOHandler))->Open(file, "rb"));
|
||||
size_t fileSize = 0;
|
||||
unsigned char *data = nullptr;
|
||||
// sometimes pStream is nullptr in a single-threaded scenario too for some reason
|
||||
// (should be an empty object returning nothing I guess)
|
||||
if (pStream) {
|
||||
fileSize = pStream->FileSize();
|
||||
// should be allocated with malloc(), because the library will call free() to deallocate
|
||||
data = (unsigned char *)malloc(fileSize);
|
||||
if (!data || !pStream.get() || !fileSize || fileSize != pStream->Read(data, 1, fileSize)) {
|
||||
pStream.reset();
|
||||
*size = 0;
|
||||
// don't throw a deadly exception, it's not fatal if we can't read an external asset
|
||||
return nullptr;
|
||||
}
|
||||
pStream.reset();
|
||||
}
|
||||
*size = (int)fileSize;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace Assimp {
|
||||
M3DWrapper::M3DWrapper() {
|
||||
// use malloc() here because m3d_free() will call free()
|
||||
m3d_ = (m3d_t *)calloc(1, sizeof(m3d_t));
|
||||
}
|
||||
|
||||
M3DWrapper::M3DWrapper(IOSystem *pIOHandler, const std::vector<unsigned char> &buffer) {
|
||||
if (nullptr == pIOHandler) {
|
||||
ai_assert(nullptr != pIOHandler);
|
||||
}
|
||||
|
||||
#ifdef ASSIMP_USE_M3D_READFILECB
|
||||
// pass this IOHandler to the C callback in a thread-local pointer
|
||||
m3dimporter_pIOHandler = pIOHandler;
|
||||
m3d_ = m3d_load(const_cast<unsigned char *>(buffer.data()), m3dimporter_readfile, free, nullptr);
|
||||
// Clear the C callback
|
||||
m3dimporter_pIOHandler = nullptr;
|
||||
#else
|
||||
m3d_ = m3d_load(const_cast<unsigned char *>(buffer.data()), nullptr, nullptr, nullptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
M3DWrapper::~M3DWrapper() {
|
||||
reset();
|
||||
}
|
||||
|
||||
void M3DWrapper::reset() {
|
||||
ClearSave();
|
||||
if (m3d_) {
|
||||
m3d_free(m3d_);
|
||||
}
|
||||
m3d_ = nullptr;
|
||||
}
|
||||
|
||||
unsigned char *M3DWrapper::Save(int quality, int flags, unsigned int &size) {
|
||||
#if (!(ASSIMP_BUILD_NO_EXPORT || ASSIMP_BUILD_NO_M3D_EXPORTER))
|
||||
ClearSave();
|
||||
saved_output_ = m3d_save(m3d_, quality, flags, &size);
|
||||
return saved_output_;
|
||||
#else
|
||||
(void)quality;
|
||||
(void)flags;
|
||||
(void)size;
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
void M3DWrapper::ClearSave() {
|
||||
if (saved_output_) {
|
||||
M3D_FREE(saved_output_);
|
||||
}
|
||||
saved_output_ = nullptr;
|
||||
}
|
||||
} // namespace Assimp
|
||||
|
||||
#endif
|
||||
#endif
|
||||
134
Engine/lib/assimp/code/AssetLib/M3D/M3DWrapper.h
Normal file
134
Engine/lib/assimp/code/AssetLib/M3D/M3DWrapper.h
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
#pragma once
|
||||
/*
|
||||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2022, assimp team
|
||||
Copyright (c) 2019 bzt
|
||||
|
||||
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 M3DWrapper.h
|
||||
* @brief Declares a class to wrap the C m3d SDK
|
||||
*/
|
||||
#ifndef AI_M3DWRAPPER_H_INC
|
||||
#define AI_M3DWRAPPER_H_INC
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_M3D_IMPORTER
|
||||
#if !(ASSIMP_BUILD_NO_EXPORT || ASSIMP_BUILD_NO_M3D_EXPORTER)
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
// Assimp specific M3D configuration. Comment out these defines to remove functionality
|
||||
//#define ASSIMP_USE_M3D_READFILECB
|
||||
|
||||
// Share stb_image's PNG loader with other importers/exporters instead of bringing our own copy.
|
||||
#define STBI_ONLY_PNG
|
||||
#include <stb/stb_image.h>
|
||||
|
||||
#include "m3d.h"
|
||||
|
||||
namespace Assimp {
|
||||
|
||||
class IOSystem;
|
||||
|
||||
/// brief The M3D-Wrapper, provudes c++ access to the data.
|
||||
class M3DWrapper {
|
||||
public:
|
||||
/// Construct an empty M3D model
|
||||
explicit M3DWrapper();
|
||||
|
||||
/// Construct an M3D model from provided buffer
|
||||
/// @note The m3d.h SDK function does not mark the data as const. Have assumed it does not write.
|
||||
/// BUG: SECURITY: The m3d.h SDK cannot be informed of the buffer size. BUFFER OVERFLOW IS CERTAIN
|
||||
explicit M3DWrapper(IOSystem *pIOHandler, const std::vector<unsigned char> &buffer);
|
||||
|
||||
/// Theclasss destructor.
|
||||
~M3DWrapper();
|
||||
|
||||
/// Will reset the wrapper, all data will become nullptr.
|
||||
void reset();
|
||||
|
||||
// The Name access, empty string returned when no m3d instance.
|
||||
std::string Name() const;
|
||||
|
||||
/// Executes a save.
|
||||
unsigned char *Save(int quality, int flags, unsigned int &size);
|
||||
|
||||
/// Clearer
|
||||
void ClearSave();
|
||||
|
||||
/// True for m3d instance exists.
|
||||
explicit operator bool() const;
|
||||
|
||||
// Allow direct access to M3D API
|
||||
m3d_t *operator->() const;
|
||||
m3d_t *M3D() const;
|
||||
|
||||
private:
|
||||
m3d_t *m3d_ = nullptr;
|
||||
unsigned char *saved_output_ = nullptr;
|
||||
};
|
||||
|
||||
inline std::string M3DWrapper::Name() const {
|
||||
if (nullptr != m3d_) {
|
||||
if (nullptr != m3d_->name) {
|
||||
return std::string(m3d_->name);
|
||||
}
|
||||
}
|
||||
return std::string();
|
||||
}
|
||||
|
||||
inline M3DWrapper::operator bool() const {
|
||||
return m3d_ != nullptr;
|
||||
}
|
||||
|
||||
inline m3d_t *M3DWrapper::operator->() const {
|
||||
return m3d_;
|
||||
}
|
||||
|
||||
inline m3d_t *M3DWrapper::M3D() const {
|
||||
return m3d_;
|
||||
}
|
||||
|
||||
} // namespace Assimp
|
||||
|
||||
#endif
|
||||
#endif // ASSIMP_BUILD_NO_M3D_IMPORTER
|
||||
|
||||
#endif // AI_M3DWRAPPER_H_INC
|
||||
4902
Engine/lib/assimp/code/AssetLib/M3D/m3d.h
Normal file
4902
Engine/lib/assimp/code/AssetLib/M3D/m3d.h
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue