From 3a13f2476ddf0edce301506a1ba821cd4942c402 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CIsaac?= Date: Mon, 15 Aug 2022 20:01:42 +1000 Subject: [PATCH] Use connected faces from generated convex hull Motivation: - Generated convex hulls did not have connected faces, which is required for convex-convex collision in cannon-es - Using the connected faces generated by ConvexHull addresses this - Fixes #76 --- lib/ConvexHull.d.ts | 1 + lib/ConvexHull.js | 55 +++++++++++++++++++++++++++++++++++++++++---- src/index.ts | 41 +++++++++++++-------------------- 3 files changed, 67 insertions(+), 30 deletions(-) diff --git a/lib/ConvexHull.d.ts b/lib/ConvexHull.d.ts index f2521d2..b342ec2 100644 --- a/lib/ConvexHull.d.ts +++ b/lib/ConvexHull.d.ts @@ -13,4 +13,5 @@ declare class Face { declare class ConvexHull { public faces: Face[]; setFromObject(mesh: Mesh): this; + collectFacesAndVertices(): { faces: number[][]; vertices: Vector3[]; } } diff --git a/lib/ConvexHull.js b/lib/ConvexHull.js index fe37696..9ed1be6 100644 --- a/lib/ConvexHull.js +++ b/lib/ConvexHull.js @@ -1,5 +1,4 @@ import { - BufferGeometry, Line3, Plane, Triangle, @@ -42,6 +41,41 @@ var ConvexHull = ( function () { Object.assign( ConvexHull.prototype, { + collectFacesAndVertices: function () { + // Get face vertex indices. + // These indices reference the array positions of all input vertices, which include vertices inside the convex hull. + // These will be re-mapped to the convex hull's vertices, which exclude interior vertices. + const faceIndices = this.faces.map((f) => f.collectIndices()); + + // Get distinct vertex indices referenced by convex hull faces, in ascending order. + const referencedFaceIndices = Array.from(new Set(faceIndices.flat())).sort(); + + // Create a mapping between the original vertex indices to new vertex indices, + // excluding vertex indices that are not part of the generated convex hull. + const originalToNewIndex = new Map(); + for (let i = 0; i < referencedFaceIndices.length; i++) { + originalToNewIndex.set(referencedFaceIndices[i], i); + } + + // Get faces with remapped vertex indices. + const faces = []; + for (let i = 0; i < faceIndices.length; i++) { + const indices = faceIndices[i]; + const a = originalToNewIndex.get(indices[0]); + const b = originalToNewIndex.get(indices[1]); + const c = originalToNewIndex.get(indices[2]); + faces.push([a, b, c]); + } + + // Get vertices referenced by faces. + const vertices = []; + for (let i = 0; i < referencedFaceIndices.length; i++) { + vertices.push(this.vertices[referencedFaceIndices[i]].point); + } + + return { faces, vertices }; + }, + setFromPoints: function ( points ) { if ( Array.isArray( points ) !== true ) { @@ -60,7 +94,7 @@ var ConvexHull = ( function () { for ( var i = 0, l = points.length; i < l; i ++ ) { - this.vertices.push( new VertexNode( points[ i ] ) ); + this.vertices.push( new VertexNode( points[ i ], i ) ); } @@ -980,6 +1014,16 @@ var ConvexHull = ( function () { Object.assign( Face.prototype, { + collectIndices: function () { + const indices = []; + let edge = this.edge; + do { + indices.push(edge.head().index); + edge = edge.next; + } while (edge !== this.edge); + return indices; + }, + getEdge: function ( i ) { var edge = this.edge; @@ -1105,12 +1149,15 @@ var ConvexHull = ( function () { // A vertex as a double linked list node. - function VertexNode( point ) { + function VertexNode( point, index ) { this.point = point; + // index in the input array + this.index = index; this.prev = null; this.next = null; - this.face = null; // the face that is able to see this vertex + // the face that is able to see this vertex + this.face = null; } diff --git a/src/index.ts b/src/index.ts index 8527579..e8c4b0e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,6 +1,6 @@ -import { Box, Quaternion as CQuaternion, ConvexPolyhedron, Cylinder, Shape, Sphere, Trimesh, Vec3 } from 'cannon-es'; +import { Box, ConvexPolyhedron, Cylinder, Quaternion as CQuaternion, Shape, Sphere, Trimesh, Vec3 } from 'cannon-es'; import { Box3, BufferGeometry, CylinderGeometry, MathUtils, Mesh, Object3D, SphereGeometry, Vector3 } from 'three'; -import { ConvexHull } from '../lib/ConvexHull.js'; +import { ConvexHull } from '../lib/ConvexHull'; import { getComponent, getGeometry, getVertices } from './utils'; const PI_2 = Math.PI / 2; @@ -254,34 +254,23 @@ function getConvexPolyhedronParameters (object: Object3D): ShapeParameters