@pmndrs/viverse 0.1.11 → 0.1.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/physics/index.js +24 -29
- package/dist/physics/world.d.ts +9 -4
- package/dist/physics/world.js +86 -10
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -28,7 +28,7 @@ npm install three @react-three/fiber @react-three/viverse
|
|
|
28
28
|
|
|
29
29
|
```tsx
|
|
30
30
|
const world = new BvhPhysicsWorld()
|
|
31
|
-
world.
|
|
31
|
+
world.addBody(ground.scene, false)
|
|
32
32
|
const character = new SimpleCharacter(camera, world, canvas, { model: { url: profile.activeAvatar?.vrmUrl } })
|
|
33
33
|
scene.add(character)
|
|
34
34
|
```
|
package/dist/physics/index.js
CHANGED
|
@@ -99,35 +99,30 @@ export class BvhCharacterPhysics {
|
|
|
99
99
|
aabbox.min.addScalar(-radius);
|
|
100
100
|
aabbox.max.addScalar(radius);
|
|
101
101
|
let grounded = false;
|
|
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
|
-
segment.end.addScaledVector(direction, depthInsideCapsule);
|
|
127
|
-
}
|
|
128
|
-
},
|
|
129
|
-
});
|
|
130
|
-
}
|
|
102
|
+
this.world.shapecast((bounds) => bounds.intersectsBox(aabbox), (tri) => {
|
|
103
|
+
// Use your existing triangle vs segment closestPointToSegment
|
|
104
|
+
const distance = tri.closestPointToSegment(segment, triPoint, capsulePoint);
|
|
105
|
+
if (distance === 0) {
|
|
106
|
+
const isCloserToSegmentStart = capsulePoint.distanceTo(segment.start) < capsulePoint.distanceTo(segment.end);
|
|
107
|
+
if (isCloserToSegmentStart) {
|
|
108
|
+
grounded = true;
|
|
109
|
+
}
|
|
110
|
+
const scaledDirection = capsulePoint.sub(isCloserToSegmentStart ? segment.start : segment.end);
|
|
111
|
+
scaledDirection.y += radius;
|
|
112
|
+
segment.start.add(scaledDirection);
|
|
113
|
+
segment.end.add(scaledDirection);
|
|
114
|
+
}
|
|
115
|
+
else if (distance < radius) {
|
|
116
|
+
const depthInsideCapsule = radius - distance;
|
|
117
|
+
const direction = capsulePoint.sub(triPoint).divideScalar(distance);
|
|
118
|
+
const slope = Math.tan(Math.acos(direction.dot(YAxis)));
|
|
119
|
+
if (direction.y > 0 && slope <= maxGroundSlope) {
|
|
120
|
+
grounded = true;
|
|
121
|
+
}
|
|
122
|
+
segment.start.addScaledVector(direction, depthInsideCapsule);
|
|
123
|
+
segment.end.addScaledVector(direction, depthInsideCapsule);
|
|
124
|
+
}
|
|
125
|
+
});
|
|
131
126
|
position.copy(segment.start);
|
|
132
127
|
position.y -= radius;
|
|
133
128
|
return grounded;
|
package/dist/physics/world.d.ts
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
|
-
import { Object3D, Ray } from 'three';
|
|
2
|
-
import {
|
|
1
|
+
import { Box3, Object3D, Ray } from 'three';
|
|
2
|
+
import { ExtendedTriangle } from 'three-mesh-bvh';
|
|
3
3
|
export declare class BvhPhysicsWorld {
|
|
4
|
-
private
|
|
5
|
-
|
|
4
|
+
private map;
|
|
5
|
+
/**
|
|
6
|
+
* @deprecated use addBody(object, false) instead
|
|
7
|
+
*/
|
|
6
8
|
addFixedBody(object: Object3D): void;
|
|
9
|
+
addBody(object: Object3D, dynamic: boolean): void;
|
|
7
10
|
removeFixedBody(object: Object3D): void;
|
|
11
|
+
private computeMatrix;
|
|
12
|
+
shapecast(intersectsBounds: (box: Box3) => boolean, intersectsTriangle: (triangle: ExtendedTriangle) => void): void;
|
|
8
13
|
raycast(ray: Ray, far: number): number | undefined;
|
|
9
14
|
}
|
package/dist/physics/world.js
CHANGED
|
@@ -1,21 +1,97 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Box3, InstancedMesh, Matrix4, Ray, Vector3 } from 'three';
|
|
2
|
+
import { computeBoundsTree, StaticGeometryGenerator, ExtendedTriangle } from 'three-mesh-bvh';
|
|
3
|
+
const rayHelper = new Ray();
|
|
4
|
+
const farPointHelper = new Vector3();
|
|
5
|
+
const boxHelper = new Box3();
|
|
6
|
+
const triangleHelper = new ExtendedTriangle();
|
|
7
|
+
const matrixHelper = new Matrix4();
|
|
2
8
|
export class BvhPhysicsWorld {
|
|
3
|
-
map =
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
9
|
+
map = [];
|
|
10
|
+
/**
|
|
11
|
+
* @deprecated use addBody(object, false) instead
|
|
12
|
+
*/
|
|
7
13
|
addFixedBody(object) {
|
|
14
|
+
this.addBody(object, false);
|
|
15
|
+
}
|
|
16
|
+
addBody(object, dynamic) {
|
|
8
17
|
object.updateWorldMatrix(true, true);
|
|
9
|
-
|
|
10
|
-
|
|
18
|
+
if (!(object instanceof InstancedMesh)) {
|
|
19
|
+
const parent = object.parent;
|
|
20
|
+
if (dynamic) {
|
|
21
|
+
object.parent = null;
|
|
22
|
+
object.updateMatrixWorld(true);
|
|
23
|
+
}
|
|
24
|
+
const geometry = new StaticGeometryGenerator(object).generate();
|
|
25
|
+
this.map.push({ object, bvh: computeBoundsTree.apply(geometry), dynamic });
|
|
26
|
+
if (dynamic) {
|
|
27
|
+
object.parent = parent;
|
|
28
|
+
object.updateMatrixWorld(true);
|
|
29
|
+
}
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
if (object.children.length > 0) {
|
|
33
|
+
throw new Error(`cannot add InstancedMesh with children`);
|
|
34
|
+
}
|
|
35
|
+
const bvh = computeBoundsTree.apply(object.geometry);
|
|
36
|
+
for (let i = 0; i < object.instanceMatrix.count; i++) {
|
|
37
|
+
this.map.push({
|
|
38
|
+
object,
|
|
39
|
+
bvh,
|
|
40
|
+
instanceIndex: i,
|
|
41
|
+
dynamic,
|
|
42
|
+
});
|
|
43
|
+
}
|
|
11
44
|
}
|
|
12
45
|
removeFixedBody(object) {
|
|
13
|
-
this.map.
|
|
46
|
+
this.map = this.map.filter((entry) => entry.object != object);
|
|
47
|
+
}
|
|
48
|
+
computeMatrix({ dynamic, object, instanceIndex }, target) {
|
|
49
|
+
if (!dynamic && instanceIndex == null) {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
if (instanceIndex == null) {
|
|
53
|
+
target.copy(object.matrixWorld);
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
;
|
|
57
|
+
object.getMatrixAt(instanceIndex, target);
|
|
58
|
+
target.premultiply(object.matrixWorld);
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
shapecast(intersectsBounds, intersectsTriangle) {
|
|
62
|
+
for (const entry of this.map) {
|
|
63
|
+
entry.bvh.shapecast({
|
|
64
|
+
intersectsBounds: (box) => {
|
|
65
|
+
boxHelper.copy(box);
|
|
66
|
+
if (this.computeMatrix(entry, matrixHelper)) {
|
|
67
|
+
boxHelper.applyMatrix4(matrixHelper);
|
|
68
|
+
}
|
|
69
|
+
return intersectsBounds(boxHelper);
|
|
70
|
+
},
|
|
71
|
+
intersectsTriangle: (triangle) => {
|
|
72
|
+
triangleHelper.copy(triangle);
|
|
73
|
+
if (this.computeMatrix(entry, matrixHelper)) {
|
|
74
|
+
triangleHelper.a.applyMatrix4(matrixHelper);
|
|
75
|
+
triangleHelper.b.applyMatrix4(matrixHelper);
|
|
76
|
+
triangleHelper.c.applyMatrix4(matrixHelper);
|
|
77
|
+
}
|
|
78
|
+
intersectsTriangle(triangleHelper);
|
|
79
|
+
},
|
|
80
|
+
});
|
|
81
|
+
}
|
|
14
82
|
}
|
|
15
83
|
raycast(ray, far) {
|
|
16
84
|
let result;
|
|
17
|
-
for (const
|
|
18
|
-
|
|
85
|
+
for (const entry of this.map.values()) {
|
|
86
|
+
rayHelper.copy(ray);
|
|
87
|
+
let farHelper = far;
|
|
88
|
+
if (this.computeMatrix(entry, matrixHelper)) {
|
|
89
|
+
matrixHelper.invert();
|
|
90
|
+
farPointHelper.copy(ray.origin).addScaledVector(ray.direction, far).applyMatrix4(matrixHelper);
|
|
91
|
+
rayHelper.applyMatrix4(matrixHelper);
|
|
92
|
+
farHelper = farPointHelper.distanceTo(rayHelper.origin);
|
|
93
|
+
}
|
|
94
|
+
for (const intersection of entry.bvh.raycast(rayHelper, undefined, 0, farHelper)) {
|
|
19
95
|
if (result != null && intersection.distance >= result) {
|
|
20
96
|
continue;
|
|
21
97
|
}
|