Skip to content

Commit 2ada598

Browse files
committed
Retrieve 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 generated faces in ConvexHull addresses this - Fixes donmccurdy#76
1 parent 144fd6b commit 2ada598

File tree

3 files changed

+51
-80
lines changed

3 files changed

+51
-80
lines changed

lib/ConvexHull.d.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Mesh, Vector3 } from 'three';
1+
import { Vector3 } from 'three';
22

33
declare class HalfEdge {
44
next: HalfEdge;
@@ -12,5 +12,6 @@ declare class Face {
1212

1313
declare class ConvexHull {
1414
public faces: Face[];
15-
setFromObject(mesh: Mesh): this;
15+
setFromPoints(points: Vector3[]): this;
16+
collectFaces(): number[][];
1617
}

lib/ConvexHull.js

+30-52
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import {
2-
BufferGeometry,
32
Line3,
43
Plane,
54
Triangle,
65
Vector3
76
} from 'three';
7+
88
/**
99
* Ported from: https://github.com/maurizzzio/quickhull3d/ by Mauricio Poppe (https://github.com/maurizzzio)
1010
*/
@@ -42,6 +42,18 @@ var ConvexHull = ( function () {
4242

4343
Object.assign( ConvexHull.prototype, {
4444

45+
collectFaces: function () {
46+
const faceIndices = []
47+
for (let i = 0; i < this.faces.length; i += 1) {
48+
if (this.faces[i].mark !== Visible) {
49+
throw Error('attempt to include a destroyed face in the hull');
50+
}
51+
const indices = this.faces[i].collectIndices();
52+
faceIndices.push(indices);
53+
}
54+
return faceIndices;
55+
},
56+
4557
setFromPoints: function ( points ) {
4658

4759
if ( Array.isArray( points ) !== true ) {
@@ -60,7 +72,7 @@ var ConvexHull = ( function () {
6072

6173
for ( var i = 0, l = points.length; i < l; i ++ ) {
6274

63-
this.vertices.push( new VertexNode( points[ i ] ) );
75+
this.vertices.push( new VertexNode( points[ i ], i ) );
6476

6577
}
6678

@@ -70,54 +82,6 @@ var ConvexHull = ( function () {
7082

7183
},
7284

73-
setFromObject: function ( object ) {
74-
75-
var points = [];
76-
77-
object.updateMatrixWorld( true );
78-
79-
object.traverse( function ( node ) {
80-
81-
var i, l, point;
82-
83-
var geometry = node.geometry;
84-
85-
if ( geometry === undefined ) return;
86-
87-
if ( geometry.isGeometry ) {
88-
89-
geometry = geometry.toBufferGeometry
90-
? geometry.toBufferGeometry()
91-
: new BufferGeometry().fromGeometry( geometry );
92-
93-
}
94-
95-
if ( geometry.isBufferGeometry ) {
96-
97-
var attribute = geometry.attributes.position;
98-
99-
if ( attribute !== undefined ) {
100-
101-
for ( i = 0, l = attribute.count; i < l; i ++ ) {
102-
103-
point = new Vector3();
104-
105-
point.fromBufferAttribute( attribute, i ).applyMatrix4( node.matrixWorld );
106-
107-
points.push( point );
108-
109-
}
110-
111-
}
112-
113-
}
114-
115-
} );
116-
117-
return this.setFromPoints( points );
118-
119-
},
120-
12185
containsPoint: function ( point ) {
12286

12387
var faces = this.faces;
@@ -980,6 +944,17 @@ var ConvexHull = ( function () {
980944

981945
Object.assign( Face.prototype, {
982946

947+
collectIndices: function () {
948+
const indices = [];
949+
let edge = this.edge;
950+
console.log(this.edge)
951+
do {
952+
indices.push(edge.head().index);
953+
edge = edge.next || null;
954+
} while (edge !== this.edge);
955+
return indices;
956+
},
957+
983958
getEdge: function ( i ) {
984959

985960
var edge = this.edge;
@@ -1105,12 +1080,15 @@ var ConvexHull = ( function () {
11051080

11061081
// A vertex as a double linked list node.
11071082

1108-
function VertexNode( point ) {
1083+
function VertexNode( point, index ) {
11091084

11101085
this.point = point;
1086+
// index in the input array
1087+
this.index = index;
11111088
this.prev = null;
11121089
this.next = null;
1113-
this.face = null; // the face that is able to see this vertex
1090+
// the face that is able to see this vertex
1091+
this.face = null;
11141092

11151093
}
11161094

src/index.ts

+18-26
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import { Box, Quaternion as CQuaternion, ConvexPolyhedron, Cylinder, Shape, Sphere, Trimesh, Vec3 } from 'cannon-es';
2-
import { Box3, BufferGeometry, CylinderGeometry, MathUtils, Mesh, Object3D, SphereGeometry, Vector3 } from 'three';
3-
import { ConvexHull } from '../lib/ConvexHull.js';
1+
import { Box, ConvexPolyhedron, Cylinder, Quaternion as CQuaternion, Shape, Sphere, Trimesh, Vec3 } from 'cannon-es';
2+
import { Box3, BufferGeometry, CylinderGeometry, MathUtils, Object3D, SphereGeometry, Vector3 } from 'three';
3+
import { ConvexHull } from '../lib/ConvexHull';
44
import { getComponent, getGeometry, getVertices } from './utils';
55

66
const PI_2 = Math.PI / 2;
@@ -254,34 +254,26 @@ function getConvexPolyhedronParameters (object: Object3D): ShapeParameters<Shape
254254
);
255255
}
256256

257-
// Compute the 3D convex hull.
258-
const hull = new ConvexHull().setFromObject(new Mesh(geometry));
259-
const hullFaces = hull.faces;
260-
const vertices: number[] = [];
261-
const faces: number[][] = [];
262-
263-
let currentFaceVertex = 0;
264-
for (let i = 0; i < hullFaces.length; i++) {
265-
const hullFace = hullFaces[ i ];
266-
const face: number[] = [];
267-
faces.push(face);
268-
269-
let edge = hullFace.edge;
270-
do {
271-
const point = edge.head().point;
272-
vertices.push(point.x, point.y, point.z);
273-
face.push(currentFaceVertex);
274-
currentFaceVertex++;
275-
edge = edge.next;
276-
} while ( edge !== hullFace.edge );
257+
// Get geometry points
258+
const points: Vector3[] = [];
259+
for (let i = 0; i < geometry.attributes.position.array.length; i += 3) {
260+
points.push(
261+
new Vector3(
262+
geometry.attributes.position.array[i],
263+
geometry.attributes.position.array[i + 1],
264+
geometry.attributes.position.array[i + 2]
265+
)
266+
);
277267
}
278268

279-
const verticesTypedArray = new Float32Array(vertices.length);
280-
verticesTypedArray.set(vertices);
269+
// Get convex hull faces
270+
const faces = new ConvexHull().setFromPoints(points).collectFaces();
271+
272+
const vertices = geometry.attributes.position.array as Float32Array
281273

282274
return {
283275
type: ShapeType.HULL,
284-
params: { vertices: verticesTypedArray, faces },
276+
params: { vertices, faces },
285277
};
286278
}
287279

0 commit comments

Comments
 (0)