mirror of
https://github.com/CesiumGS/obj2gltf.git
synced 2024-11-23 16:44:05 -05:00
adding winding order sanitization when normals are provided
This commit is contained in:
parent
2396899f5d
commit
2105e7bf82
@ -58,10 +58,10 @@ var facePattern3 = /f(\s+-?\d+\/-?\d+\/-?\d+){3,}/;
|
||||
var facePattern4 = /f(\s+-?\d+\/\/-?\d+){3,}/; // f vertex//normal vertex//normal vertex//normal ...
|
||||
|
||||
// Just for line continuations
|
||||
var facePattern5 = /((\s|^)+-?\d+\/?(\s|$)){1,}/; // f vertex vertex vertex ...
|
||||
var facePattern6 = /((\s|^)+-?\d+\/-?\d+(\s|$)){1,}/; // f vertex/uv vertex/uv vertex/uv ...
|
||||
var facePattern7 = /((\s|^)+-?\d+\/-?\d+\/-?\d+(\s|$)+){1,}/; // f vertex/uv/normal vertex/uv/normal vertex/uv/normal ...
|
||||
var facePattern8 = /((\s|^)+-?\d+\/\/-?\d+(\s|$)){1,}/; // f vertex//normal vertex//normal vertex//normal ...
|
||||
var facePattern5 = /((\s|^)+-?\d+\/?(\s|$)){1,}/; // f vertex vertex vertex ...
|
||||
var facePattern6 = /((\s|^)+-?\d+\/-?\d+(\s|$)){1,}/; // f vertex/uv vertex/uv vertex/uv ...
|
||||
var facePattern7 = /((\s|^)+-?\d+\/-?\d+\/-?\d+(\s|$)+){1,}/; // f vertex/uv/normal vertex/uv/normal vertex/uv/normal ...
|
||||
var facePattern8 = /((\s|^)+-?\d+\/\/-?\d+(\s|$)){1,}/; // f vertex//normal vertex//normal vertex//normal ...
|
||||
|
||||
|
||||
var faceSpacePattern = /(f?\s+)|(\s+\/)|(\s*\\)/g;
|
||||
@ -314,6 +314,14 @@ function loadObj(objPath, options) {
|
||||
return Cartesian3.fromElements(px, py, pz, result);
|
||||
}
|
||||
|
||||
function get3DNormal(index, result) {
|
||||
var ni = getOffset(index, normals, 3);
|
||||
var nx = normals.get(ni + 0);
|
||||
var ny = normals.get(ni + 1);
|
||||
var nz = normals.get(ni + 2);
|
||||
return Cartesian3.fromElements(nx, ny, nz, result);
|
||||
}
|
||||
|
||||
// Given a sequence of three points A B C, determine whether vector BC
|
||||
// "turns" clockwise (positive) or counter-clockwise (negative) from vector AB
|
||||
var scratch1 = new Cartesian3();
|
||||
@ -337,9 +345,45 @@ function loadObj(objPath, options) {
|
||||
return true;
|
||||
}
|
||||
|
||||
var scratch3 = new Cartesian3();
|
||||
// Checks if winding order matches the given normal.
|
||||
function isWindingCorrect(positionIndex1, positionIndex2, positionIndex3, normal) {
|
||||
var A = get3DPoint(positionIndex1, scratch1);
|
||||
var B = get3DPoint(positionIndex2, scratch2);
|
||||
var C = get3DPoint(positionIndex3, scratch3);
|
||||
|
||||
Cartesian3.subtract(A, B, scratch1);
|
||||
Cartesian3.subtract(C, B, scratch2);
|
||||
var cross = Cartesian3.cross(A, C, scratch1);
|
||||
|
||||
return (Cartesian3.dot(normal, cross) >= 0);
|
||||
}
|
||||
|
||||
function addTriangle(index1, index2, index3, correctWinding) {
|
||||
if (correctWinding) {
|
||||
primitive.indices.push(index1);
|
||||
primitive.indices.push(index2);
|
||||
primitive.indices.push(index3);
|
||||
} else {
|
||||
primitive.indices.push(index1);
|
||||
primitive.indices.push(index3);
|
||||
primitive.indices.push(index2);
|
||||
}
|
||||
}
|
||||
|
||||
var scratchNormal = new Cartesian3();
|
||||
function addFace(vertices, positions, uvs, normals) {
|
||||
|
||||
var u1, u2, u3, n1, n2, n3;
|
||||
var windingCorrect = true;
|
||||
var faceNormal;
|
||||
|
||||
// If normals are defined, find a face normal to use in winding order sanitization.
|
||||
// If no face normal, we have to assume the winding is correct.
|
||||
if (normals) {
|
||||
faceNormal = get3DNormal(normals[0], scratchNormal);
|
||||
windingCorrect = isWindingCorrect(positions[0], positions[1], positions[2], faceNormal);
|
||||
}
|
||||
|
||||
if (vertices.length === 3) {
|
||||
|
||||
@ -359,9 +403,7 @@ function loadObj(objPath, options) {
|
||||
var index2 = addVertex(vertices[1], positions[1], u2, n2);
|
||||
var index3 = addVertex(vertices[2], positions[2], u3, n3);
|
||||
|
||||
primitive.indices.push(index1);
|
||||
primitive.indices.push(index2);
|
||||
primitive.indices.push(index3);
|
||||
addTriangle(index1, index2, index3, windingCorrect);
|
||||
} else { // Triangulate if the face is not a triangle
|
||||
var positions3D = [];
|
||||
var vertexIndices = [];
|
||||
@ -383,22 +425,20 @@ function loadObj(objPath, options) {
|
||||
|
||||
if (isConvex(positions2D)) {
|
||||
for (i=1; i < vertices.length-1; ++i) {
|
||||
primitive.indices.push(vertexIndices[0]);
|
||||
primitive.indices.push(vertexIndices[i]);
|
||||
primitive.indices.push(vertexIndices[i+1]);
|
||||
addTriangle(vertexIndices[0], vertexIndices[i], vertexIndices[i+1], windingCorrect);
|
||||
}
|
||||
} else {
|
||||
// Since the projection doesn't respect winding order, reverse the order of
|
||||
// Since the projection doesn't preserve winding order, reverse the order of
|
||||
// the vertices before triangulating to enforce counter clockwise.
|
||||
var windingOrder = PolygonPipeline.computeWindingOrder2D(positions2D);
|
||||
if (windingOrder === WindingOrder.CLOCKWISE) {
|
||||
var projectedWindingOrder = PolygonPipeline.computeWindingOrder2D(positions2D);
|
||||
if (projectedWindingOrder === WindingOrder.CLOCKWISE) {
|
||||
positions2D.reverse();
|
||||
}
|
||||
|
||||
// Use an ear-clipping algorithm to triangulate
|
||||
var positionIndices = PolygonPipeline.triangulate(positions2D);
|
||||
for (i = 0; i < positionIndices.length; ++i) {
|
||||
primitive.indices.push(vertexIndices[positionIndices[i]]);
|
||||
for (i = 0; i < positionIndices.length-2; i += 3) {
|
||||
addTriangle(vertexIndices[positionIndices[i]], vertexIndices[positionIndices[i+1]], vertexIndices[positionIndices[i+2]], windingCorrect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user