Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for 5+ vertices polygon #5375

Merged
merged 4 commits into from
Oct 27, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion resources/web/wwi/nodes/WbMesh.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,6 @@ export default class WbMesh extends WbTriangleMeshGeometry {
queue.push(this.scene.rootnode);
let node;
let indexOffset = 0;
console.log(this.scene)
while (queue.length !== 0) {
node = queue.shift();
// compute absolute transform of this node from all the parents
Expand Down
124 changes: 124 additions & 0 deletions resources/web/wwi/nodes/utils/WbTriangleMesh.js
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,45 @@ export default class WbTriangleMesh {
this.#tmpTexIndices.push(tesselatorOutput[4].z);
this.#tmpTexIndices.push(tesselatorOutput[5].z);
}
} else { // 5+ vertex polygon
for (let j = 0; j < toSize; j += 3) {
const a = coord[tesselatorOutput[j].x];
const b = coord[tesselatorOutput[j + 1].x];
const c = coord[tesselatorOutput[j + 2].x];

// check for colinear edges, and discard this triangle if found
const d = b.sub(a);
const e = c.sub(b);
// don't append if edges are co-linear
if (d.cross(e).almostEquals(new WbVector3(), 0.00001))
continue;

// don't append if two vertices are on the same spot
if (a.equal(b) || a.equal(c) || b.equal(c)) {
console.warn('Duplicate vertices detected while triangulating mesh. ' +
'Try opening your model in 3D modeling software and removing duplicate vertices, then re-importing.');
continue;
}

// see if this triangle has any overlapping vertices and snip triangle to improve tesselation and fill holes
const snippedIndices = this.#cutTriangleIfNeeded(coord, tesselatorOutput, j);
console.assert(snippedIndices.length % 3 === 0);
for (let k = 0; k < snippedIndices.length; k += 3) {
this.#coordIndices.push(snippedIndices[k].x);
this.#coordIndices.push(snippedIndices[k + 1].x);
this.#coordIndices.push(snippedIndices[k + 2].x);
if (this.#normalsValid) {
this.#tmpNormalIndices.push(snippedIndices[k].y);
this.#tmpNormalIndices.push(snippedIndices[k + 1].y);
this.#tmpNormalIndices.push(snippedIndices[k + 2].y);
}
if (this.areTextureCoordinatesValid) {
this.#tmpTexIndices.push(snippedIndices[k].z);
this.#tmpTexIndices.push(snippedIndices[k + 1].z);
this.#tmpTexIndices.push(snippedIndices[k + 2].z);
}
}
}
}
} else
console.warn('current face is invalid');
Expand Down Expand Up @@ -496,4 +535,89 @@ export default class WbTriangleMesh {
index += 3;
}
}

#cutTriangleIfNeeded(coord, tesselatedPolygon, triangleIndex) {
const results = [];

// find the three vertices of this triangle from the tesselated polygon
const firstVertexIndex = tesselatedPolygon[triangleIndex].x;
const secondVertexIndex = tesselatedPolygon[triangleIndex + 1].x;
const thirdVertexIndex = tesselatedPolygon[triangleIndex + 2].x;

const firstNormalIndex = tesselatedPolygon[triangleIndex].y;
const secondNormalIndex = tesselatedPolygon[triangleIndex + 1].y;
const thirdNormalIndex = tesselatedPolygon[triangleIndex + 2].y;

const firstTexCoordIndex = tesselatedPolygon[triangleIndex].z;
const secondTexCoordIndex = tesselatedPolygon[triangleIndex + 1].z;
const thirdTexCoordIndex = tesselatedPolygon[triangleIndex + 2].z;

// prepare triangle edges for snipping checks
const firstEdgeStart = coord[firstVertexIndex];
const firstEdgeEnd = coord[secondVertexIndex];

const secondEdgeStart = coord[secondVertexIndex];
const secondEdgeEnd = coord[thirdVertexIndex];

const thirdEdgeStart = coord[thirdVertexIndex];
const thirdEdgeEnd = coord[firstVertexIndex];

const checkedIndices = new Set();
// for all vertices not in this triangle
for (let i = 0; i < tesselatedPolygon.length; i++) {
// skip vertices from this triangle
if (tesselatedPolygon[i].x === firstVertexIndex || tesselatedPolygon[i].x === secondVertexIndex ||
tesselatedPolygon[i].x === thirdVertexIndex)
continue;
// skip vertices we've already checked
else if (checkedIndices.has(tesselatedPolygon[i].x))
continue;
else if (coord[tesselatedPolygon[i].x].isOnEdgeBetweenVertices(firstEdgeStart, firstEdgeEnd)) {
// case 1: vertex is on the first edge of the triangle

// first triangle
results.push(new WbVector3(firstVertexIndex, firstNormalIndex, firstTexCoordIndex));
results.push(new WbVector3(tesselatedPolygon[i].x, tesselatedPolygon[i].y, tesselatedPolygon[i].z));
results.push(new WbVector3(thirdVertexIndex, thirdNormalIndex, thirdTexCoordIndex));
// second triangle
results.push(new WbVector3(tesselatedPolygon[i].x, tesselatedPolygon[i].y, tesselatedPolygon[i].z));
results.push(new WbVector3(secondVertexIndex, secondNormalIndex, secondTexCoordIndex));
results.push(new WbVector3(thirdVertexIndex, thirdNormalIndex, thirdTexCoordIndex));
} else if (coord[tesselatedPolygon[i].x].isOnEdgeBetweenVertices(secondEdgeStart, secondEdgeEnd)) {
// case 2: vertex is on the second edge of the triangle

// first triangle
results.push(new WbVector3(secondVertexIndex, secondNormalIndex, secondTexCoordIndex));
results.push(new WbVector3(tesselatedPolygon[i].x, tesselatedPolygon[i].y, tesselatedPolygon[i].z));
results.push(new WbVector3(firstVertexIndex, firstNormalIndex, firstTexCoordIndex));
// second triangle
results.push(new WbVector3(tesselatedPolygon[i].x, tesselatedPolygon[i].y, tesselatedPolygon[i].z));
results.push(new WbVector3(thirdVertexIndex, thirdNormalIndex, thirdTexCoordIndex));
results.push(new WbVector3(firstVertexIndex, firstNormalIndex, firstTexCoordIndex));
} else if (coord[tesselatedPolygon[i].x].isOnEdgeBetweenVertices(thirdEdgeStart, thirdEdgeEnd)) {
// case 3: vertex is on the third edge of the triangle

// first triangle
results.push(new WbVector3(thirdVertexIndex, thirdNormalIndex, thirdTexCoordIndex));
results.push(new WbVector3(tesselatedPolygon[i].x, tesselatedPolygon[i].y, tesselatedPolygon[i].z));
results.push(new WbVector3(secondVertexIndex, secondNormalIndex, secondTexCoordIndex));
// second triangle
results.push(new WbVector3(tesselatedPolygon[i].x, tesselatedPolygon[i].y, tesselatedPolygon[i].z));
results.push(new WbVector3(firstVertexIndex, firstNormalIndex, firstTexCoordIndex));
results.push(new WbVector3(secondVertexIndex, secondNormalIndex, secondTexCoordIndex));
}

// add this vertex to the list of those already checked
checkedIndices.add(tesselatedPolygon[i].x);
}

// default - no need to cut the triangle, return it as-was
if (results.length === 0) {
results.push(new WbVector3(firstVertexIndex, firstNormalIndex, firstTexCoordIndex));
results.push(new WbVector3(secondVertexIndex, secondNormalIndex, secondTexCoordIndex));
results.push(new WbVector3(thirdVertexIndex, thirdNormalIndex, thirdTexCoordIndex));
}

return results;
}
}
16 changes: 16 additions & 0 deletions resources/web/wwi/nodes/utils/WbVector3.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,4 +90,20 @@ export default class WbVector3 {
toString() {
return this.x + ' ' + this.y + ' ' + this.z;
}

// test if this point is on a given line segment
isOnEdgeBetweenVertices(lineStart, lineEnd, tolerance = 0.000001) {
const lineSegment = lineEnd.sub(lineStart);
const toPoint = this.sub(lineStart);

// the points aren't aligned
if (!lineSegment.cross(toPoint).almostEquals(new WbVector3(), tolerance))
return false;

// the point isn't on the segment
if (lineSegment.dot(toPoint) < 0 || lineSegment.dot(toPoint) > lineSegment.length2())
return false;

return true;
}
}