From 7e82e90b3588ceff05e78359b709c10cbfc30c78 Mon Sep 17 00:00:00 2001 From: Rachel Hwang Date: Thu, 15 Jun 2017 11:11:27 -0400 Subject: [PATCH] adding convexivity test and fan method for convex polygon triangulation --- lib/loadObj.js | 73 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 53 insertions(+), 20 deletions(-) diff --git a/lib/loadObj.js b/lib/loadObj.js index b547be5..04f3928 100644 --- a/lib/loadObj.js +++ b/lib/loadObj.js @@ -49,13 +49,13 @@ function Primitive() { } // OBJ regex patterns are modified from ThreeJS (https://github.com/mrdoob/three.js/blob/master/examples/js/loaders/OBJLoader.js) -var vertexPattern = /v( +[\d|\.|\+|\-|e|E]+)( +[\d|\.|\+|\-|e|E]+)( +[\d|\.|\+|\-|e|E]+)/; // v float float float -var normalPattern = /vn( +[\d|\.|\+|\-|e|E]+)( +[\d|\.|\+|\-|e|E]+)( +[\d|\.|\+|\-|e|E]+)/; // vn float float float -var uvPattern = /vt( +[\d|\.|\+|\-|e|E]+)( +[\d|\.|\+|\-|e|E]+)/; // vt float float -var facePattern1 = /f(\s+-?\d+\/?\/?){3,}/; // f vertex vertex vertex ... -var facePattern2 = /f(\s+-?\d+\/-?\d+){3,}/; // f vertex/uv vertex/uv vertex/uv ... -var facePattern3 = /f(\s+-?\d+\/-?\d+\/-?\d+){3,}/; // f vertex/uv/normal vertex/uv/normal vertex/uv/normal ... -var facePattern4 = /f(\s+-?\d+\/\/-?\d+){3,}/; // f vertex//normal vertex//normal vertex//normal ... +var vertexPattern = /v( +[\d|\.|\+|\-|e|E]+)( +[\d|\.|\+|\-|e|E]+)( +[\d|\.|\+|\-|e|E]+)/; // v float float float +var normalPattern = /vn( +[\d|\.|\+|\-|e|E]+)( +[\d|\.|\+|\-|e|E]+)( +[\d|\.|\+|\-|e|E]+)/; // vn float float float +var uvPattern = /vt( +[\d|\.|\+|\-|e|E]+)( +[\d|\.|\+|\-|e|E]+)/; // vt float float +var facePattern1 = /f(\s+-?\d+\/?\/?){3,}/; // f vertex vertex vertex ... +var facePattern2 = /f(\s+-?\d+\/-?\d+){3,}/; // f vertex/uv vertex/uv vertex/uv ... +var facePattern3 = /f(\s+-?\d+\/-?\d+\/-?\d+){3,}/; // f vertex/uv/normal vertex/uv/normal vertex/uv/normal ... +var facePattern4 = /f(\s+-?\d+\/\/-?\d+){3,}/; // f vertex//normal vertex//normal vertex//normal ... var faceSpacePattern = /f?\s+/; var faceSpaceOrSlashPattern = /(f?\s+)|(\/+\s*)/g; @@ -279,6 +279,29 @@ function loadObj(objPath, options) { return index; } + // 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(); + var scratch2 = new Cartesian3(); + function getTurnDirection(pointA, pointB, pointC) { + var vector1 = Cartesian2.subtract(pointA, pointB, scratch1); + var vector2 = Cartesian2.subtract(pointC, pointB, scratch2); + return vector1.x * vector2.y - vector1.y * vector2.x; + } + + // Given the cartesian 2 vertices of a polygon, determine if convex + function isConvex(positions2D) { + var i; + var turnDirection = getTurnDirection(positions2D[0], positions2D[1], positions2D[2]); + for (i=1; i < positions2D.length-2; ++i) { + var currentTurnDirection = getTurnDirection(positions2D[i], positions2D[i+1], positions2D[i+2]); + if (turnDirection * currentTurnDirection < 0) { + return false; + } + } + return true; + } + function addFace(vertices, positions, uvs, normals) { var u1, u2, u3, n1, n2, n3; @@ -309,34 +332,44 @@ function loadObj(objPath, options) { var vertexIndices = []; var i; - for (i=0; i < vertices.length; ++i) { + for (i = 0; i < vertices.length; ++i) { var u = (defined(uvs)) ? uvs[i] : undefined; var n = (defined(normals)) ? normals[i] : undefined; var index = addVertex(vertices[i], positions[i], u, n); vertexIndices.push(index); - var pi = getOffset(index+1, positions, 3); + // Collect the vertex positions as 3D points + var pi = getOffset(index + 1, positions, 3); var px = mesh.positions.get(pi + 0); var py = mesh.positions.get(pi + 1); var pz = mesh.positions.get(pi + 2); - positions3D.push(new Cartesian3(px, py, pz)); } + var positions2D = projectTo2D(positions3D); - var windingOrder = PolygonPipeline.computeWindingOrder2D(positions2D); + if (isConvex(positions2D)) { + // Use the fan method to triangulate + for (i=1; i < vertices.length-1; ++i) { + primitive.indices.push(vertexIndices[0]); + primitive.indices.push(vertexIndices[i]); + primitive.indices.push(vertexIndices[i+1]); + } + } else { - // Since the projection doesn't respect winding order, reverse the order of - // the vertices before triangulating to enforce counter clockwise. - if (windingOrder === WindingOrder.CLOCKWISE) { - positions2D.reverse(); - } + // Since the projection doesn't respect winding order, reverse the order of + // the vertices before triangulating to enforce counter clockwise. + var windingOrder = PolygonPipeline.computeWindingOrder2D(positions2D); + if (windingOrder === WindingOrder.CLOCKWISE) { + positions2D.reverse(); + } - var positionIndices = PolygonPipeline.triangulate(positions2D); - - for (i=0; i < positionIndices.length; ++i) { - primitive.indices.push(vertexIndices[positionIndices[i]]); + // 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]]); + } } }