-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathcannonUtils.ts
130 lines (120 loc) · 4.25 KB
/
cannonUtils.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
//MIT License
//Copyright (c) 2020-2021 Sean Bradley
import * as THREE from 'three'
import * as CANNON from 'cannon-es'
interface Face3 {
a: number
b: number
c: number
normals: THREE.Vector3[]
}
class CannonUtils {
public static CreateTrimesh(
geometry: THREE.BufferGeometry
): CANNON.Trimesh {
let vertices
if (geometry.index === null) {
vertices = (geometry.attributes.position as THREE.BufferAttribute).array as number[]
} else {
vertices = (geometry.clone().toNonIndexed().attributes.position as THREE.BufferAttribute).array as number[]
}
const indices = Object.keys(vertices).map(Number)
return new CANNON.Trimesh(vertices, indices)
}
public static CreateConvexPolyhedron(
geometry: THREE.BufferGeometry
): CANNON.ConvexPolyhedron {
const position = geometry.attributes.position as THREE.BufferAttribute
const normal = geometry.attributes.normal as THREE.BufferAttribute
const vertices: THREE.Vector3[] = []
for (let i = 0; i < position.count; i++) {
vertices.push(new THREE.Vector3().fromBufferAttribute(position, i))
}
const faces: Face3[] = []
for (let i = 0; i < position.count; i += 3) {
const vertexNormals =
normal === undefined
? []
: [
new THREE.Vector3().fromBufferAttribute(normal, i),
new THREE.Vector3().fromBufferAttribute(
normal,
i + 1
),
new THREE.Vector3().fromBufferAttribute(
normal,
i + 2
),
]
const face: Face3 = {
a: i,
b: i + 1,
c: i + 2,
normals: vertexNormals,
}
faces.push(face)
}
const verticesMap: { [key: string]: number } = {}
const points: CANNON.Vec3[] = []
const changes: number[] = []
for (let i = 0, il = vertices.length; i < il; i++) {
const v = vertices[i]
const key =
Math.round(v.x * 100) +
'_' +
Math.round(v.y * 100) +
'_' +
Math.round(v.z * 100)
if (verticesMap[key] === undefined) {
verticesMap[key] = i
points.push(
new CANNON.Vec3(vertices[i].x, vertices[i].y, vertices[i].z)
)
changes[i] = points.length - 1
} else {
changes[i] = changes[verticesMap[key]]
}
}
const faceIdsToRemove = []
for (let i = 0, il = faces.length; i < il; i++) {
const face = faces[i]
face.a = changes[face.a]
face.b = changes[face.b]
face.c = changes[face.c]
const indices = [face.a, face.b, face.c]
for (let n = 0; n < 3; n++) {
if (indices[n] === indices[(n + 1) % 3]) {
faceIdsToRemove.push(i)
break
}
}
}
for (let i = faceIdsToRemove.length - 1; i >= 0; i--) {
const idx = faceIdsToRemove[i]
faces.splice(idx, 1)
}
const cannonFaces: number[][] = faces.map(function (f) {
return [f.a, f.b, f.c]
})
return new CANNON.ConvexPolyhedron({
vertices: points,
faces: cannonFaces,
})
}
public static offsetCenterOfMass(
body: CANNON.Body,
centreOfMass: CANNON.Vec3
): void {
body.shapeOffsets.forEach(function (offset) {
centreOfMass.vadd(offset, centreOfMass)
})
centreOfMass.scale(1 / body.shapes.length, centreOfMass)
body.shapeOffsets.forEach(function (offset) {
offset.vsub(centreOfMass, offset)
})
const worldCenterOfMass = new CANNON.Vec3()
body.vectorToWorldFrame(centreOfMass, worldCenterOfMass)
body.position.vadd(worldCenterOfMass, body.position)
}
}
export default CannonUtils