Refactoring the extension
parent
81019d5e58
commit
596001c89c
|
@ -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;
|
||||||
|
|
|
@ -509,6 +509,7 @@ namespace glTF2 {
|
||||||
prim.SetObject();
|
prim.SetObject();
|
||||||
|
|
||||||
// Extensions
|
// Extensions
|
||||||
|
if (p.ngonEncoded)
|
||||||
{
|
{
|
||||||
Value exts;
|
Value exts;
|
||||||
exts.SetObject();
|
exts.SetObject();
|
||||||
|
|
|
@ -958,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);
|
||||||
|
|
|
@ -195,6 +195,13 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
|
||||||
|
|
||||||
const aiVector3D* verts = pMesh->mVertices;
|
const aiVector3D* verts = pMesh->mVertices;
|
||||||
|
|
||||||
|
// NGON encoding note: making sure that triangles are not recognized as false ngons.
|
||||||
|
// To do so, we make sure the first indice of the new emitted triangle is not the same as previous one.
|
||||||
|
unsigned int prev_first_indice = (unsigned int)-1;
|
||||||
|
|
||||||
|
// The mesh becomes NGON encoded now, during the triangulation process.
|
||||||
|
pMesh->mPrimitiveTypes |= aiPrimitiveType_NGONEncodingFlag;
|
||||||
|
|
||||||
// use std::unique_ptr to avoid slow std::vector<bool> specialiations
|
// use std::unique_ptr to avoid slow std::vector<bool> specialiations
|
||||||
std::unique_ptr<bool[]> done(new bool[max_out]);
|
std::unique_ptr<bool[]> done(new bool[max_out]);
|
||||||
for( unsigned int a = 0; a < pMesh->mNumFaces; a++) {
|
for( unsigned int a = 0; a < pMesh->mNumFaces; a++) {
|
||||||
|
@ -214,24 +221,12 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
|
||||||
|
|
||||||
aiFace* const last_face = curOut;
|
aiFace* const last_face = curOut;
|
||||||
|
|
||||||
// ngon encoding: making sure that triangles are not recognized as false ngons.
|
|
||||||
// To do so, we make sure the first indice is not the same as previous triangle emitted.
|
|
||||||
unsigned int prev_first_indice = (unsigned int)-1;
|
|
||||||
if (curOut != out) prev_first_indice = (curOut - 1)->mIndices[0];
|
|
||||||
|
|
||||||
// if it's a simple point,line or triangle: just copy it
|
// if it's a simple point,line or triangle: just copy it
|
||||||
if( face.mNumIndices <= 3)
|
if( face.mNumIndices <= 3)
|
||||||
{
|
{
|
||||||
aiFace& nface = *curOut++;
|
aiFace& nface = *curOut++;
|
||||||
nface.mNumIndices = face.mNumIndices;
|
nface.mNumIndices = face.mNumIndices;
|
||||||
nface.mIndices = face.mIndices;
|
nface.mIndices = face.mIndices;
|
||||||
|
|
||||||
if (nface.mIndices[0] == prev_first_indice) {
|
|
||||||
// rotate indices to avoid ngon encoding false ngons
|
|
||||||
std::swap(nface.mIndices[0], nface.mIndices[2]);
|
|
||||||
std::swap(nface.mIndices[1], nface.mIndices[2]);
|
|
||||||
}
|
|
||||||
|
|
||||||
face.mIndices = nullptr;
|
face.mIndices = nullptr;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -242,7 +237,7 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
|
||||||
// this vertex (if it exists) and start tri-fanning from
|
// this vertex (if it exists) and start tri-fanning from
|
||||||
// it.
|
// it.
|
||||||
//
|
//
|
||||||
// Due to ngon encoding, if this concave vertex is the same as the previously
|
// Due to NGON encoding, if this concave vertex is the same as the previously
|
||||||
// emitted triangle, we use the opposite vertex which also happens to work
|
// emitted triangle, we use the opposite vertex which also happens to work
|
||||||
// for tri-fanning a concave quad.
|
// for tri-fanning a concave quad.
|
||||||
// ref: https://github.com/assimp/assimp/pull/3695#issuecomment-805999760
|
// ref: https://github.com/assimp/assimp/pull/3695#issuecomment-805999760
|
||||||
|
@ -265,7 +260,7 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
|
||||||
|
|
||||||
const float angle = std::acos(left*diag) + std::acos(right*diag);
|
const float angle = std::acos(left*diag) + std::acos(right*diag);
|
||||||
if (angle > AI_MATH_PI_F) {
|
if (angle > AI_MATH_PI_F) {
|
||||||
// i is the concave point
|
// this is the concave point
|
||||||
start_vertex = i;
|
start_vertex = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -306,11 +301,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]];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -530,6 +525,17 @@ 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]];
|
||||||
|
|
||||||
|
// NGON encoding: only quads are supported.
|
||||||
|
// For everything else, we make sure we don't emit 'false' ngons. We thus avoid having
|
||||||
|
// 2 consecutive triangles with their first index identical.
|
||||||
|
if (face.mNumIndices != 4 && i[0] == prev_first_indice) {
|
||||||
|
// rotate indices
|
||||||
|
std::swap(i[0], i[2]);
|
||||||
|
std::swap(i[1], i[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
prev_first_indice = i[0];
|
||||||
++f;
|
++f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 = 0x16,
|
||||||
|
|
||||||
/** 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.
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue