-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathCapsuleEntity.js
More file actions
81 lines (68 loc) · 3.08 KB
/
CapsuleEntity.js
File metadata and controls
81 lines (68 loc) · 3.08 KB
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
import * as THREE from 'https://cdn.skypack.dev/three@0.138.0';
class CapsuleEntity extends THREE.Object3D {
constructor(radius, size) {
super();
this.box = new THREE.Box3();
this.velocity = new THREE.Vector3();
this.horizontalVelocity = new THREE.Vector3();
this.radius = radius;
this.size = size;
this.onGround = false;
this.gravity = -300;
this.segment = new THREE.Line3(new THREE.Vector3(), new THREE.Vector3(0, -size, 0.0));
this.friction = 0.99;
}
update(delta, bvh) {
const collider = bvh;
this.velocity.y += this.onGround ? 0 : delta * this.gravity;
this.position.addScaledVector(this.velocity, delta);
this.position.add(this.horizontalVelocity);
this.horizontalVelocity.multiplyScalar(this.friction);
this.updateMatrixWorld();
const tempBox = new THREE.Box3();
const tempMat = new THREE.Matrix4();
const tempSegment = new THREE.Line3();
tempBox.makeEmpty();
tempMat.copy(collider.matrixWorld).invert();
tempSegment.copy(this.segment);
tempSegment.start.applyMatrix4(this.matrixWorld).applyMatrix4(tempMat);
tempSegment.end.applyMatrix4(this.matrixWorld).applyMatrix4(tempMat);
tempBox.expandByPoint(tempSegment.start);
tempBox.expandByPoint(tempSegment.end);
tempBox.min.addScalar(-this.radius);
tempBox.max.addScalar(this.radius);
const tempVector = new THREE.Vector3();
const tempVector2 = new THREE.Vector3();
collider.geometry.boundsTree.shapecast({
intersectsBounds: box => box.intersectsBox(tempBox),
intersectsTriangle: tri => {
// check if the triangle is intersecting the capsule and adjust the
// capsule position if it is.
const triPoint = tempVector;
const capsulePoint = tempVector2;
const distance = tri.closestPointToSegment(tempSegment, triPoint, capsulePoint);
if (distance < this.radius) {
const depth = this.radius - distance;
const direction = capsulePoint.sub(triPoint).normalize();
tempSegment.start.addScaledVector(direction, depth);
tempSegment.end.addScaledVector(direction, depth);
}
}
});
const newPosition = tempVector;
newPosition.copy(tempSegment.start).applyMatrix4(collider.matrixWorld);
const deltaVector = tempVector2;
deltaVector.subVectors(newPosition, this.position);
this.onGround = deltaVector.y > Math.abs(delta * this.velocity.y * 0.25);
const offset = Math.max(0.0, deltaVector.length() - 1e-5);
deltaVector.normalize().multiplyScalar(offset);
this.position.add(deltaVector);
if (!this.onGround) {
deltaVector.normalize();
this.velocity.addScaledVector(deltaVector, -deltaVector.dot(this.velocity));
} else {
this.velocity.set(0, 0, 0);
}
}
}
export { CapsuleEntity };