Merge branch 'master' into Q1MDLgroup
commit
83c0dce075
|
@ -39,7 +39,7 @@ Take a look into the https://github.com/assimp/assimp/blob/master/Build.md file.
|
||||||
### Ports ###
|
### Ports ###
|
||||||
* [Android](port/AndroidJNI/README.md)
|
* [Android](port/AndroidJNI/README.md)
|
||||||
* [Python](port/PyAssimp/README.md)
|
* [Python](port/PyAssimp/README.md)
|
||||||
* [.NET](https://github.com/assimp/assimp-net)
|
* [.NET](https://bitbucket.org/Starnick/assimpnet/src/master/)
|
||||||
* [Pascal](port/AssimpPascal/Readme.md)
|
* [Pascal](port/AssimpPascal/Readme.md)
|
||||||
* [Javascript (Alpha)](https://github.com/makc/assimp2json)
|
* [Javascript (Alpha)](https://github.com/makc/assimp2json)
|
||||||
* [Unity 3d Plugin](https://www.assetstore.unity3d.com/en/#!/content/91777)
|
* [Unity 3d Plugin](https://www.assetstore.unity3d.com/en/#!/content/91777)
|
||||||
|
|
|
@ -508,6 +508,12 @@ void ResolveVertexDataArray(std::vector<T>& data_out, const Scope& source,
|
||||||
std::vector<int> uvIndices;
|
std::vector<int> uvIndices;
|
||||||
ParseVectorDataArray(uvIndices,GetRequiredElement(source,indexDataElementName));
|
ParseVectorDataArray(uvIndices,GetRequiredElement(source,indexDataElementName));
|
||||||
|
|
||||||
|
if (uvIndices.size() > vertex_count) {
|
||||||
|
FBXImporter::LogWarn(Formatter::format("trimming length of input array for ByPolygonVertex mapping: ")
|
||||||
|
<< uvIndices.size() << ", expected " << vertex_count);
|
||||||
|
uvIndices.resize(vertex_count);
|
||||||
|
}
|
||||||
|
|
||||||
if (uvIndices.size() != vertex_count) {
|
if (uvIndices.size() != vertex_count) {
|
||||||
FBXImporter::LogError(Formatter::format("length of input data unexpected for ByPolygonVertex mapping: ")
|
FBXImporter::LogError(Formatter::format("length of input data unexpected for ByPolygonVertex mapping: ")
|
||||||
<< uvIndices.size() << ", expected " << vertex_count);
|
<< uvIndices.size() << ", expected " << vertex_count);
|
||||||
|
|
|
@ -158,6 +158,9 @@ void HMPImporter::InternReadFile(const std::string &pFile,
|
||||||
szBuffer[3] = ((char *)&iMagic)[3];
|
szBuffer[3] = ((char *)&iMagic)[3];
|
||||||
szBuffer[4] = '\0';
|
szBuffer[4] = '\0';
|
||||||
|
|
||||||
|
delete[] mBuffer;
|
||||||
|
mBuffer = nullptr;
|
||||||
|
|
||||||
// We're definitely unable to load this file
|
// We're definitely unable to load this file
|
||||||
throw DeadlyImportError("Unknown HMP subformat ", pFile,
|
throw DeadlyImportError("Unknown HMP subformat ", pFile,
|
||||||
". Magic word (", szBuffer, ") is not known");
|
". Magic word (", szBuffer, ") is not known");
|
||||||
|
|
|
@ -250,7 +250,7 @@ void MDCImporter::InternReadFile(
|
||||||
|
|
||||||
// get the number of valid surfaces
|
// get the number of valid surfaces
|
||||||
BE_NCONST MDC::Surface *pcSurface, *pcSurface2;
|
BE_NCONST MDC::Surface *pcSurface, *pcSurface2;
|
||||||
pcSurface = pcSurface2 = new (mBuffer + pcHeader->ulOffsetSurfaces) MDC::Surface;
|
pcSurface = pcSurface2 = reinterpret_cast<BE_NCONST MDC::Surface *>(mBuffer + pcHeader->ulOffsetSurfaces);
|
||||||
unsigned int iNumShaders = 0;
|
unsigned int iNumShaders = 0;
|
||||||
for (unsigned int i = 0; i < pcHeader->ulNumSurfaces; ++i) {
|
for (unsigned int i = 0; i < pcHeader->ulNumSurfaces; ++i) {
|
||||||
// validate the surface header
|
// validate the surface header
|
||||||
|
@ -260,7 +260,7 @@ void MDCImporter::InternReadFile(
|
||||||
++pScene->mNumMeshes;
|
++pScene->mNumMeshes;
|
||||||
}
|
}
|
||||||
iNumShaders += pcSurface2->ulNumShaders;
|
iNumShaders += pcSurface2->ulNumShaders;
|
||||||
pcSurface2 = new ((int8_t *)pcSurface2 + pcSurface2->ulOffsetEnd) MDC::Surface;
|
pcSurface2 = reinterpret_cast<BE_NCONST MDC::Surface *>((BE_NCONST int8_t *)pcSurface2 + pcSurface2->ulOffsetEnd);
|
||||||
}
|
}
|
||||||
aszShaders.reserve(iNumShaders);
|
aszShaders.reserve(iNumShaders);
|
||||||
pScene->mMeshes = new aiMesh *[pScene->mNumMeshes];
|
pScene->mMeshes = new aiMesh *[pScene->mNumMeshes];
|
||||||
|
@ -405,7 +405,7 @@ void MDCImporter::InternReadFile(
|
||||||
pcFaceCur->mIndices[2] = iOutIndex + 0;
|
pcFaceCur->mIndices[2] = iOutIndex + 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pcSurface = new ((int8_t *)pcSurface + pcSurface->ulOffsetEnd) MDC::Surface;
|
pcSurface = reinterpret_cast<BE_NCONST MDC::Surface *>((BE_NCONST int8_t *)pcSurface + pcSurface->ulOffsetEnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
// create a flat node graph with a root node and one child for each surface
|
// create a flat node graph with a root node and one child for each surface
|
||||||
|
|
|
@ -500,7 +500,7 @@ void MS3DImporter::InternReadFile( const std::string& pFile,
|
||||||
throw DeadlyImportError("MS3D: Encountered invalid triangle index, file is malformed");
|
throw DeadlyImportError("MS3D: Encountered invalid triangle index, file is malformed");
|
||||||
}
|
}
|
||||||
|
|
||||||
TempTriangle& t = triangles[g.triangles[i]];
|
TempTriangle& t = triangles[g.triangles[j]];
|
||||||
f.mIndices = new unsigned int[f.mNumIndices=3];
|
f.mIndices = new unsigned int[f.mNumIndices=3];
|
||||||
|
|
||||||
for (unsigned int k = 0; k < 3; ++k,++n) {
|
for (unsigned int k = 0; k < 3; ++k,++n) {
|
||||||
|
@ -508,7 +508,7 @@ void MS3DImporter::InternReadFile( const std::string& pFile,
|
||||||
throw DeadlyImportError("MS3D: Encountered invalid vertex index, file is malformed");
|
throw DeadlyImportError("MS3D: Encountered invalid vertex index, file is malformed");
|
||||||
}
|
}
|
||||||
|
|
||||||
const TempVertex& v = vertices[t.indices[i]];
|
const TempVertex& v = vertices[t.indices[k]];
|
||||||
for(unsigned int a = 0; a < 4; ++a) {
|
for(unsigned int a = 0; a < 4; ++a) {
|
||||||
if (v.bone_id[a] != UINT_MAX) {
|
if (v.bone_id[a] != UINT_MAX) {
|
||||||
if (v.bone_id[a] >= joints.size()) {
|
if (v.bone_id[a] >= joints.size()) {
|
||||||
|
@ -524,9 +524,9 @@ void MS3DImporter::InternReadFile( const std::string& pFile,
|
||||||
// collect vertex components
|
// collect vertex components
|
||||||
m->mVertices[n] = v.pos;
|
m->mVertices[n] = v.pos;
|
||||||
|
|
||||||
m->mNormals[n] = t.normals[i];
|
m->mNormals[n] = t.normals[k];
|
||||||
m->mTextureCoords[0][n] = aiVector3D(t.uv[i].x,1.f-t.uv[i].y,0.0);
|
m->mTextureCoords[0][n] = aiVector3D(t.uv[k].x,1.f-t.uv[k].y,0.0);
|
||||||
f.mIndices[i] = n;
|
f.mIndices[k] = n;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -813,6 +813,11 @@ struct Mesh : public Object {
|
||||||
AccessorList position, normal, tangent;
|
AccessorList position, normal, tangent;
|
||||||
};
|
};
|
||||||
std::vector<Target> targets;
|
std::vector<Target> targets;
|
||||||
|
|
||||||
|
// extension: FB_ngon_encoding
|
||||||
|
bool ngonEncoded;
|
||||||
|
|
||||||
|
Primitive(): ngonEncoded(false) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<Primitive> primitives;
|
std::vector<Primitive> primitives;
|
||||||
|
@ -1108,6 +1113,7 @@ public:
|
||||||
bool KHR_materials_clearcoat;
|
bool KHR_materials_clearcoat;
|
||||||
bool KHR_materials_transmission;
|
bool KHR_materials_transmission;
|
||||||
bool KHR_draco_mesh_compression;
|
bool KHR_draco_mesh_compression;
|
||||||
|
bool FB_ngon_encoding;
|
||||||
} extensionsUsed;
|
} extensionsUsed;
|
||||||
|
|
||||||
//! Keeps info about the required extensions
|
//! Keeps info about the required extensions
|
||||||
|
|
|
@ -507,6 +507,20 @@ namespace glTF2 {
|
||||||
Mesh::Primitive& p = m.primitives[i];
|
Mesh::Primitive& p = m.primitives[i];
|
||||||
Value prim;
|
Value prim;
|
||||||
prim.SetObject();
|
prim.SetObject();
|
||||||
|
|
||||||
|
// Extensions
|
||||||
|
if (p.ngonEncoded)
|
||||||
|
{
|
||||||
|
Value exts;
|
||||||
|
exts.SetObject();
|
||||||
|
|
||||||
|
Value FB_ngon_encoding;
|
||||||
|
FB_ngon_encoding.SetObject();
|
||||||
|
|
||||||
|
exts.AddMember(StringRef("FB_ngon_encoding"), FB_ngon_encoding, w.mAl);
|
||||||
|
prim.AddMember("extensions", exts, w.mAl);
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
prim.AddMember("mode", Value(int(p.mode)).Move(), w.mAl);
|
prim.AddMember("mode", Value(int(p.mode)).Move(), w.mAl);
|
||||||
|
|
||||||
|
@ -874,6 +888,10 @@ namespace glTF2 {
|
||||||
if (this->mAsset.extensionsUsed.KHR_materials_transmission) {
|
if (this->mAsset.extensionsUsed.KHR_materials_transmission) {
|
||||||
exts.PushBack(StringRef("KHR_materials_transmission"), mAl);
|
exts.PushBack(StringRef("KHR_materials_transmission"), mAl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this->mAsset.extensionsUsed.FB_ngon_encoding) {
|
||||||
|
exts.PushBack(StringRef("FB_ngon_encoding"), mAl);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!exts.Empty())
|
if (!exts.Empty())
|
||||||
|
|
|
@ -97,6 +97,9 @@ glTF2Exporter::glTF2Exporter(const char* filename, IOSystem* pIOSystem, const ai
|
||||||
|
|
||||||
mAsset.reset( new Asset( pIOSystem ) );
|
mAsset.reset( new Asset( pIOSystem ) );
|
||||||
|
|
||||||
|
// Always on as our triangulation process is aware of this type of encoding
|
||||||
|
mAsset->extensionsUsed.FB_ngon_encoding = true;
|
||||||
|
|
||||||
if (isBinary) {
|
if (isBinary) {
|
||||||
mAsset->SetAsBinary();
|
mAsset->SetAsBinary();
|
||||||
}
|
}
|
||||||
|
@ -955,6 +958,7 @@ void glTF2Exporter::ExportMeshes()
|
||||||
m->name = name;
|
m->name = name;
|
||||||
|
|
||||||
p.material = mAsset->materials.Get(aim->mMaterialIndex);
|
p.material = mAsset->materials.Get(aim->mMaterialIndex);
|
||||||
|
p.ngonEncoded = (aim->mPrimitiveTypes & aiPrimitiveType_NGONEncodingFlag) != 0;
|
||||||
|
|
||||||
/******************* Vertices ********************/
|
/******************* Vertices ********************/
|
||||||
Ref<Accessor> v = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mVertices, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT, BufferViewTarget_ARRAY_BUFFER);
|
Ref<Accessor> v = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mVertices, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT, BufferViewTarget_ARRAY_BUFFER);
|
||||||
|
|
|
@ -76,6 +76,87 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
using namespace Assimp;
|
using namespace Assimp;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Helper struct used to simplify NGON encoding functions.
|
||||||
|
*/
|
||||||
|
struct NGONEncoder {
|
||||||
|
NGONEncoder() : mLastNGONFirstIndex((unsigned int)-1) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Encode the current triangle, and make sure it is recognized as a triangle.
|
||||||
|
*
|
||||||
|
* This method will rotate indices in tri if needed in order to avoid tri to be considered
|
||||||
|
* part of the previous ngon. This method is to be used whenever you want to emit a real triangle,
|
||||||
|
* and make sure it is seen as a triangle.
|
||||||
|
*
|
||||||
|
* @param tri Triangle to encode.
|
||||||
|
*/
|
||||||
|
void ngonEncodeTriangle(aiFace * tri) {
|
||||||
|
ai_assert(tri->mNumIndices == 3);
|
||||||
|
|
||||||
|
// Rotate indices in new triangle to avoid ngon encoding false ngons
|
||||||
|
// Otherwise, the new triangle would be considered part of the previous NGON.
|
||||||
|
if (isConsideredSameAsLastNgon(tri)) {
|
||||||
|
std::swap(tri->mIndices[0], tri->mIndices[2]);
|
||||||
|
std::swap(tri->mIndices[1], tri->mIndices[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
mLastNGONFirstIndex = tri->mIndices[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Encode a quad (2 triangles) in ngon encoding, and make sure they are seen as a single ngon.
|
||||||
|
*
|
||||||
|
* @param tri1 First quad triangle
|
||||||
|
* @param tri2 Second quad triangle
|
||||||
|
*
|
||||||
|
* @pre Triangles must be properly fanned from the most appropriate vertex.
|
||||||
|
*/
|
||||||
|
void ngonEncodeQuad(aiFace *tri1, aiFace *tri2) {
|
||||||
|
ai_assert(tri1->mNumIndices == 3);
|
||||||
|
ai_assert(tri2->mNumIndices == 3);
|
||||||
|
ai_assert(tri1->mIndices[0] == tri2->mIndices[0]);
|
||||||
|
|
||||||
|
// If the selected fanning vertex is the same as the previously
|
||||||
|
// emitted ngon, we use the opposite vertex which also happens to work
|
||||||
|
// for tri-fanning a concave quad.
|
||||||
|
// ref: https://github.com/assimp/assimp/pull/3695#issuecomment-805999760
|
||||||
|
if (isConsideredSameAsLastNgon(tri1)) {
|
||||||
|
// Right-rotate indices for tri1 (index 2 becomes the new fanning vertex)
|
||||||
|
std::swap(tri1->mIndices[0], tri1->mIndices[2]);
|
||||||
|
std::swap(tri1->mIndices[1], tri1->mIndices[2]);
|
||||||
|
|
||||||
|
// Left-rotate indices for tri2 (index 2 becomes the new fanning vertex)
|
||||||
|
std::swap(tri2->mIndices[1], tri2->mIndices[2]);
|
||||||
|
std::swap(tri2->mIndices[0], tri2->mIndices[2]);
|
||||||
|
|
||||||
|
ai_assert(tri1->mIndices[0] == tri2->mIndices[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
mLastNGONFirstIndex = tri1->mIndices[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Check whether this triangle would be considered part of the lastly emitted ngon or not.
|
||||||
|
*
|
||||||
|
* @param tri Current triangle.
|
||||||
|
* @return true If used as is, this triangle will be part of last ngon.
|
||||||
|
* @return false If used as is, this triangle is not considered part of the last ngon.
|
||||||
|
*/
|
||||||
|
bool isConsideredSameAsLastNgon(const aiFace * tri) const {
|
||||||
|
ai_assert(tri->mNumIndices == 3);
|
||||||
|
return tri->mIndices[0] == mLastNGONFirstIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
unsigned int mLastNGONFirstIndex;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Constructor to be privately used by Importer
|
// Constructor to be privately used by Importer
|
||||||
TriangulateProcess::TriangulateProcess()
|
TriangulateProcess::TriangulateProcess()
|
||||||
|
@ -175,10 +256,15 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
|
||||||
pMesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
|
pMesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
|
||||||
pMesh->mPrimitiveTypes &= ~aiPrimitiveType_POLYGON;
|
pMesh->mPrimitiveTypes &= ~aiPrimitiveType_POLYGON;
|
||||||
|
|
||||||
|
// The mesh becomes NGON encoded now, during the triangulation process.
|
||||||
|
pMesh->mPrimitiveTypes |= aiPrimitiveType_NGONEncodingFlag;
|
||||||
|
|
||||||
aiFace* out = new aiFace[numOut](), *curOut = out;
|
aiFace* out = new aiFace[numOut](), *curOut = out;
|
||||||
std::vector<aiVector3D> temp_verts3d(max_out+2); /* temporary storage for vertices */
|
std::vector<aiVector3D> temp_verts3d(max_out+2); /* temporary storage for vertices */
|
||||||
std::vector<aiVector2D> temp_verts(max_out+2);
|
std::vector<aiVector2D> temp_verts(max_out+2);
|
||||||
|
|
||||||
|
NGONEncoder ngonEncoder;
|
||||||
|
|
||||||
// Apply vertex colors to represent the face winding?
|
// Apply vertex colors to represent the face winding?
|
||||||
#ifdef AI_BUILD_TRIANGULATE_COLOR_FACE_WINDING
|
#ifdef AI_BUILD_TRIANGULATE_COLOR_FACE_WINDING
|
||||||
if (!pMesh->mColors[0])
|
if (!pMesh->mColors[0])
|
||||||
|
@ -220,8 +306,11 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
|
||||||
aiFace& nface = *curOut++;
|
aiFace& nface = *curOut++;
|
||||||
nface.mNumIndices = face.mNumIndices;
|
nface.mNumIndices = face.mNumIndices;
|
||||||
nface.mIndices = face.mIndices;
|
nface.mIndices = face.mIndices;
|
||||||
|
|
||||||
face.mIndices = nullptr;
|
face.mIndices = nullptr;
|
||||||
|
|
||||||
|
// points and lines don't require ngon encoding (and are not supported either!)
|
||||||
|
if (nface.mNumIndices == 3) ngonEncoder.ngonEncodeTriangle(&nface);
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// optimized code for quadrilaterals
|
// optimized code for quadrilaterals
|
||||||
|
@ -274,6 +363,9 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
|
||||||
|
|
||||||
// prevent double deletion of the indices field
|
// prevent double deletion of the indices field
|
||||||
face.mIndices = nullptr;
|
face.mIndices = nullptr;
|
||||||
|
|
||||||
|
ngonEncoder.ngonEncodeQuad(&nface, &sface);
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -284,11 +376,11 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
|
||||||
// modeling suite to make extensive use of highly concave, monster polygons ...
|
// modeling suite to make extensive use of highly concave, monster polygons ...
|
||||||
// so we need to apply the full 'ear cutting' algorithm to get it right.
|
// so we need to apply the full 'ear cutting' algorithm to get it right.
|
||||||
|
|
||||||
// RERQUIREMENT: polygon is expected to be simple and *nearly* planar.
|
// REQUIREMENT: polygon is expected to be simple and *nearly* planar.
|
||||||
// We project it onto a plane to get a 2d triangle.
|
// We project it onto a plane to get a 2d triangle.
|
||||||
|
|
||||||
// Collect all vertices of of the polygon.
|
// Collect all vertices of of the polygon.
|
||||||
for (tmp = 0; tmp < max; ++tmp) {
|
for (tmp = 0; tmp < max; ++tmp) {
|
||||||
temp_verts3d[tmp] = verts[idx[tmp]];
|
temp_verts3d[tmp] = verts[idx[tmp]];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -508,6 +600,11 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
|
||||||
i[0] = idx[i[0]];
|
i[0] = idx[i[0]];
|
||||||
i[1] = idx[i[1]];
|
i[1] = idx[i[1]];
|
||||||
i[2] = idx[i[2]];
|
i[2] = idx[i[2]];
|
||||||
|
|
||||||
|
// IMPROVEMENT: Polygons are not supported yet by this ngon encoding + triangulation step.
|
||||||
|
// So we encode polygons as regular triangles. No way to reconstruct the original
|
||||||
|
// polygon in this case.
|
||||||
|
ngonEncoder.ngonEncodeTriangle(f);
|
||||||
++f;
|
++f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -97,7 +97,7 @@ inline T getEpsilon() {
|
||||||
/// @brief Will return the constant PI for the requested type.
|
/// @brief Will return the constant PI for the requested type.
|
||||||
/// @return Pi
|
/// @return Pi
|
||||||
template<class T>
|
template<class T>
|
||||||
inline T PI() {
|
inline T aiPi() {
|
||||||
return static_cast<T>(3.14159265358979323846);
|
return static_cast<T>(3.14159265358979323846);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -50,6 +50,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
namespace Assimp {
|
namespace Assimp {
|
||||||
|
|
||||||
|
/// @brief Will find a node by its name.
|
||||||
struct find_node_by_name_predicate {
|
struct find_node_by_name_predicate {
|
||||||
std::string mName;
|
std::string mName;
|
||||||
find_node_by_name_predicate(const std::string &name) :
|
find_node_by_name_predicate(const std::string &name) :
|
||||||
|
@ -88,7 +89,11 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear() {
|
void clear() {
|
||||||
mData.resize(0);
|
if(mData.empty()) {
|
||||||
|
mDoc = nullptr;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mData.clear();
|
||||||
delete mDoc;
|
delete mDoc;
|
||||||
mDoc = nullptr;
|
mDoc = nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -398,6 +398,24 @@ enum aiPrimitiveType {
|
||||||
*/
|
*/
|
||||||
aiPrimitiveType_POLYGON = 0x8,
|
aiPrimitiveType_POLYGON = 0x8,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A flag to determine whether this triangles only mesh is NGON encoded.
|
||||||
|
*
|
||||||
|
* NGON encoding is a special encoding that tells whether 2 or more consecutive triangles
|
||||||
|
* should be considered as a triangle fan. This is identified by looking at the first vertex index.
|
||||||
|
* 2 consecutive triangles with the same 1st vertex index are part of the same
|
||||||
|
* NGON.
|
||||||
|
*
|
||||||
|
* At the moment, only quads (concave or convex) are supported, meaning that polygons are 'seen' as
|
||||||
|
* triangles, as usual after a triangulation pass.
|
||||||
|
*
|
||||||
|
* To get an NGON encoded mesh, please use the aiProcess_Triangulate post process.
|
||||||
|
*
|
||||||
|
* @see aiProcess_Triangulate
|
||||||
|
* @link https://github.com/KhronosGroup/glTF/pull/1620
|
||||||
|
*/
|
||||||
|
aiPrimitiveType_NGONEncodingFlag = 0x10,
|
||||||
|
|
||||||
/** This value is not used. It is just here to force the
|
/** This value is not used. It is just here to force the
|
||||||
* compiler to map this enum to a 32 Bit integer.
|
* compiler to map this enum to a 32 Bit integer.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -57,7 +57,7 @@ protected:
|
||||||
aiMatrix4x4 get_predetermined_transformation_matrix_for_decomposition() const {
|
aiMatrix4x4 get_predetermined_transformation_matrix_for_decomposition() const {
|
||||||
aiMatrix4x4 t, r;
|
aiMatrix4x4 t, r;
|
||||||
aiMatrix4x4::Translation(aiVector3D(14,-25,-8), t);
|
aiMatrix4x4::Translation(aiVector3D(14,-25,-8), t);
|
||||||
aiMatrix4x4::Rotation(Math::PI<float>() / 4.0f, aiVector3D(1).Normalize(), r);
|
aiMatrix4x4::Rotation(Math::aiPi<float>() / 4.0f, aiVector3D(1).Normalize(), r);
|
||||||
return t * r;
|
return t * r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -59,7 +59,7 @@ TEST_F(AssimpAPITest_aiQuaternion, aiCreateQuaternionFromMatrixTest) {
|
||||||
// to prevent running into division by zero.
|
// to prevent running into division by zero.
|
||||||
aiMatrix3x3 m, r;
|
aiMatrix3x3 m, r;
|
||||||
aiMatrix3x3::Translation(aiVector2D(14,-25), m);
|
aiMatrix3x3::Translation(aiVector2D(14,-25), m);
|
||||||
aiMatrix3x3::RotationZ(Math::PI<float>() / 4.0f, r);
|
aiMatrix3x3::RotationZ(Math::aiPi<float>() / 4.0f, r);
|
||||||
m = m * r;
|
m = m * r;
|
||||||
|
|
||||||
result_cpp = aiQuaternion(m);
|
result_cpp = aiQuaternion(m);
|
||||||
|
@ -127,8 +127,8 @@ TEST_F(AssimpAPITest_aiQuaternion, aiQuaternionInterpolateTest) {
|
||||||
// Use predetermined quaternions to prevent division by zero
|
// Use predetermined quaternions to prevent division by zero
|
||||||
// during slerp calculations.
|
// during slerp calculations.
|
||||||
const float INTERPOLATION(0.5f);
|
const float INTERPOLATION(0.5f);
|
||||||
const auto q1 = aiQuaternion(aiVector3D(-1,1,1).Normalize(), Math::PI<float>() / 4.0f);
|
const auto q1 = aiQuaternion(aiVector3D(-1,1,1).Normalize(), Math::aiPi<float>() / 4.0f);
|
||||||
const auto q2 = aiQuaternion(aiVector3D(1,2,1).Normalize(), Math::PI<float>() / 2.0f);
|
const auto q2 = aiQuaternion(aiVector3D(1,2,1).Normalize(), Math::aiPi<float>() / 2.0f);
|
||||||
aiQuaternion::Interpolate(result_cpp, q1, q2, INTERPOLATION);
|
aiQuaternion::Interpolate(result_cpp, q1, q2, INTERPOLATION);
|
||||||
aiQuaternionInterpolate(&result_c, &q1, &q2, INTERPOLATION);
|
aiQuaternionInterpolate(&result_c, &q1, &q2, INTERPOLATION);
|
||||||
EXPECT_EQ(result_cpp, result_c);
|
EXPECT_EQ(result_cpp, result_c);
|
||||||
|
|
|
@ -51,6 +51,6 @@ const float AssimpMathTest::Epsilon = Math::getEpsilon<float>();
|
||||||
RandomUniformFloatGenerator AssimpMathTest::RandNonZero(1.0f, 100.0f);
|
RandomUniformFloatGenerator AssimpMathTest::RandNonZero(1.0f, 100.0f);
|
||||||
|
|
||||||
// Initialize with an interval of [-PI,PI] inclusively.
|
// Initialize with an interval of [-PI,PI] inclusively.
|
||||||
RandomUniformFloatGenerator AssimpMathTest::RandPI(-Math::PI<float>(), Math::PI<float>());
|
RandomUniformFloatGenerator AssimpMathTest::RandPI(-Math::aiPi<float>(), Math::aiPi<float>());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue