185 lines
6.6 KiB
C++
185 lines
6.6 KiB
C++
/*
|
|
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 BlenderBMesh.cpp
|
|
* @brief Conversion of Blender's new BMesh stuff
|
|
*/
|
|
|
|
#ifndef ASSIMP_BUILD_NO_BLEND_IMPORTER
|
|
|
|
#include "BlenderBMesh.h"
|
|
#include "BlenderDNA.h"
|
|
#include "BlenderScene.h"
|
|
#include "BlenderTessellator.h"
|
|
|
|
namespace Assimp {
|
|
template <>
|
|
const char *LogFunctions<BlenderBMeshConverter>::Prefix() {
|
|
static auto prefix = "BLEND_BMESH: ";
|
|
return prefix;
|
|
}
|
|
} // namespace Assimp
|
|
|
|
using namespace Assimp;
|
|
using namespace Assimp::Blender;
|
|
using namespace Assimp::Formatter;
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
BlenderBMeshConverter::BlenderBMeshConverter(const Mesh *mesh) :
|
|
BMesh(mesh),
|
|
triMesh(nullptr) {
|
|
ai_assert(nullptr != mesh);
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
BlenderBMeshConverter::~BlenderBMeshConverter() {
|
|
DestroyTriMesh();
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
bool BlenderBMeshConverter::ContainsBMesh() const {
|
|
// TODO - Should probably do some additional verification here
|
|
return BMesh->totpoly && BMesh->totloop && BMesh->totvert;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
const Mesh *BlenderBMeshConverter::TriangulateBMesh() {
|
|
AssertValidMesh();
|
|
AssertValidSizes();
|
|
PrepareTriMesh();
|
|
|
|
for (int i = 0; i < BMesh->totpoly; ++i) {
|
|
const MPoly &poly = BMesh->mpoly[i];
|
|
ConvertPolyToFaces(poly);
|
|
}
|
|
|
|
return triMesh;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
void BlenderBMeshConverter::AssertValidMesh() {
|
|
if (!ContainsBMesh()) {
|
|
ThrowException("BlenderBMeshConverter requires a BMesh with \"polygons\" - please call BlenderBMeshConverter::ContainsBMesh to check this first");
|
|
}
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
void BlenderBMeshConverter::AssertValidSizes() {
|
|
if (BMesh->totpoly != static_cast<int>(BMesh->mpoly.size())) {
|
|
ThrowException("BMesh poly array has incorrect size");
|
|
}
|
|
if (BMesh->totloop != static_cast<int>(BMesh->mloop.size())) {
|
|
ThrowException("BMesh loop array has incorrect size");
|
|
}
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
void BlenderBMeshConverter::PrepareTriMesh() {
|
|
if (triMesh) {
|
|
DestroyTriMesh();
|
|
}
|
|
|
|
triMesh = new Mesh(*BMesh);
|
|
triMesh->totface = 0;
|
|
triMesh->mface.clear();
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
void BlenderBMeshConverter::DestroyTriMesh() {
|
|
delete triMesh;
|
|
triMesh = nullptr;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
void BlenderBMeshConverter::ConvertPolyToFaces(const MPoly &poly) {
|
|
const MLoop *polyLoop = &BMesh->mloop[poly.loopstart];
|
|
|
|
if (poly.totloop == 3 || poly.totloop == 4) {
|
|
AddFace(polyLoop[0].v, polyLoop[1].v, polyLoop[2].v, poly.totloop == 4 ? polyLoop[3].v : 0);
|
|
|
|
// UVs are optional, so only convert when present.
|
|
if (BMesh->mloopuv.size()) {
|
|
if ((poly.loopstart + poly.totloop) > static_cast<int>(BMesh->mloopuv.size())) {
|
|
ThrowException("BMesh uv loop array has incorrect size");
|
|
}
|
|
const MLoopUV *loopUV = &BMesh->mloopuv[poly.loopstart];
|
|
AddTFace(loopUV[0].uv, loopUV[1].uv, loopUV[2].uv, poly.totloop == 4 ? loopUV[3].uv : nullptr);
|
|
}
|
|
} else if (poly.totloop > 4) {
|
|
#if ASSIMP_BLEND_WITH_GLU_TESSELLATE
|
|
BlenderTessellatorGL tessGL(*this);
|
|
tessGL.Tessellate(polyLoop, poly.totloop, triMesh->mvert);
|
|
#elif ASSIMP_BLEND_WITH_POLY_2_TRI
|
|
BlenderTessellatorP2T tessP2T(*this);
|
|
tessP2T.Tessellate(polyLoop, poly.totloop, triMesh->mvert);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
void BlenderBMeshConverter::AddFace(int v1, int v2, int v3, int v4) {
|
|
MFace face;
|
|
face.v1 = v1;
|
|
face.v2 = v2;
|
|
face.v3 = v3;
|
|
face.v4 = v4;
|
|
face.flag = 0;
|
|
// TODO - Work out how materials work
|
|
face.mat_nr = 0;
|
|
triMesh->mface.push_back(face);
|
|
triMesh->totface = static_cast<int>(triMesh->mface.size());
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
void BlenderBMeshConverter::AddTFace(const float *uv1, const float *uv2, const float *uv3, const float *uv4) {
|
|
MTFace mtface;
|
|
memcpy(&mtface.uv[0], uv1, sizeof(float) * 2);
|
|
memcpy(&mtface.uv[1], uv2, sizeof(float) * 2);
|
|
memcpy(&mtface.uv[2], uv3, sizeof(float) * 2);
|
|
|
|
if (uv4) {
|
|
memcpy(&mtface.uv[3], uv4, sizeof(float) * 2);
|
|
}
|
|
|
|
triMesh->mtface.push_back(mtface);
|
|
}
|
|
|
|
#endif // ASSIMP_BUILD_NO_BLEND_IMPORTER
|