@pmndrs/viverse 0.1.8 → 0.1.10
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.d.ts +5 -4
- package/dist/physics/index.js +29 -20
- package/dist/simple-character.js +4 -3
- package/package.json +2 -2
package/README.md
CHANGED
package/dist/physics/index.d.ts
CHANGED
|
@@ -24,9 +24,9 @@ export type BvhCharacterPhysicsOptions = {
|
|
|
24
24
|
*/
|
|
25
25
|
linearDamping?: number;
|
|
26
26
|
/**
|
|
27
|
-
* @default 0.
|
|
27
|
+
* @default 0.5;
|
|
28
28
|
*/
|
|
29
|
-
|
|
29
|
+
maxGroundSlope?: number;
|
|
30
30
|
} | boolean;
|
|
31
31
|
/**
|
|
32
32
|
* assumes the target object origin is at its bottom
|
|
@@ -37,7 +37,8 @@ export declare class BvhCharacterPhysics {
|
|
|
37
37
|
private destroyed;
|
|
38
38
|
private readonly stateVelocity;
|
|
39
39
|
readonly inputVelocity: Vector3;
|
|
40
|
-
|
|
40
|
+
private notGroundedSeconds;
|
|
41
|
+
get isGrounded(): boolean;
|
|
41
42
|
constructor(character: Object3D, world: BvhPhysicsWorld);
|
|
42
43
|
applyVelocity(velocity: Vector3): void;
|
|
43
44
|
/**
|
|
@@ -45,6 +46,6 @@ export declare class BvhCharacterPhysics {
|
|
|
45
46
|
*/
|
|
46
47
|
update(fullDelta: number, options?: BvhCharacterPhysicsOptions): void;
|
|
47
48
|
destroy(): void;
|
|
48
|
-
shapecastCapsule(position: Vector3, options: Exclude<BvhCharacterPhysicsOptions, boolean>):
|
|
49
|
+
shapecastCapsule(position: Vector3, maxGroundSlope: number, options: Exclude<BvhCharacterPhysicsOptions, boolean>): boolean;
|
|
49
50
|
}
|
|
50
51
|
export * from './world.js';
|
package/dist/physics/index.js
CHANGED
|
@@ -7,8 +7,8 @@ const triPoint = new Vector3();
|
|
|
7
7
|
const capsulePoint = new Vector3();
|
|
8
8
|
const collisionFreePosition = new Vector3();
|
|
9
9
|
const position = new Vector3();
|
|
10
|
-
const collisionDelta = new Vector3();
|
|
11
10
|
const invertedParentMatrix = new Matrix4();
|
|
11
|
+
const YAxis = new Vector3(0, 1, 0);
|
|
12
12
|
/**
|
|
13
13
|
* assumes the target object origin is at its bottom
|
|
14
14
|
*/
|
|
@@ -18,7 +18,10 @@ export class BvhCharacterPhysics {
|
|
|
18
18
|
destroyed = false;
|
|
19
19
|
stateVelocity = new Vector3();
|
|
20
20
|
inputVelocity = new Vector3();
|
|
21
|
-
|
|
21
|
+
notGroundedSeconds = 0;
|
|
22
|
+
get isGrounded() {
|
|
23
|
+
return this.notGroundedSeconds < 0.2;
|
|
24
|
+
}
|
|
22
25
|
constructor(character, world) {
|
|
23
26
|
this.character = character;
|
|
24
27
|
this.world = world;
|
|
@@ -57,13 +60,17 @@ export class BvhCharacterPhysics {
|
|
|
57
60
|
invertedParentMatrix.identity();
|
|
58
61
|
}
|
|
59
62
|
//compute new position based on the state velocity, the input velocity, and the delta
|
|
60
|
-
const yMovement = this.stateVelocity.y * partialDelta;
|
|
61
|
-
position.addScaledVector(this.stateVelocity, partialDelta);
|
|
62
63
|
position.addScaledVector(this.inputVelocity, partialDelta);
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
this.
|
|
64
|
+
position.addScaledVector(this.stateVelocity, partialDelta);
|
|
65
|
+
const isGrounded = this.shapecastCapsule(collisionFreePosition.copy(position), options.maxGroundSlope ?? 1, options) &&
|
|
66
|
+
this.stateVelocity.y < 0;
|
|
67
|
+
this.notGroundedSeconds += partialDelta;
|
|
68
|
+
if (isGrounded) {
|
|
69
|
+
this.notGroundedSeconds = 0;
|
|
70
|
+
}
|
|
71
|
+
if (!isGrounded || this.inputVelocity.lengthSq() > 0) {
|
|
72
|
+
this.character.position.copy(collisionFreePosition).applyMatrix4(invertedParentMatrix);
|
|
73
|
+
}
|
|
67
74
|
//compute new velocity
|
|
68
75
|
// apply gravity
|
|
69
76
|
this.stateVelocity.y += (options.gravity ?? -20) * partialDelta;
|
|
@@ -71,21 +78,15 @@ export class BvhCharacterPhysics {
|
|
|
71
78
|
const dampingFactor = 1.0 / (1.0 + partialDelta * (options.linearDamping ?? 0.1));
|
|
72
79
|
this.stateVelocity.multiplyScalar(dampingFactor);
|
|
73
80
|
// apply collision to velocity
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
if (this.isGrounded) {
|
|
77
|
-
this.stateVelocity.set(0, (options.gravity ?? -20) * partialDelta, 0);
|
|
78
|
-
}
|
|
79
|
-
else if (collisionDelta.length() > 1e-5) {
|
|
80
|
-
collisionDelta.normalize();
|
|
81
|
-
this.stateVelocity.addScaledVector(collisionDelta, -collisionDelta.dot(this.stateVelocity));
|
|
81
|
+
if (isGrounded) {
|
|
82
|
+
this.stateVelocity.set(0, (options.gravity ?? -20) * 0.01, 0);
|
|
82
83
|
}
|
|
83
84
|
}
|
|
84
85
|
}
|
|
85
86
|
destroy() {
|
|
86
87
|
this.destroyed = true;
|
|
87
88
|
}
|
|
88
|
-
shapecastCapsule(position, options) {
|
|
89
|
+
shapecastCapsule(position, maxGroundSlope, options) {
|
|
89
90
|
const radius = options.capsuleRadius ?? 0.4;
|
|
90
91
|
const height = options.capsuleHeight ?? 1.7;
|
|
91
92
|
segment.start.copy(position);
|
|
@@ -97,6 +98,7 @@ export class BvhCharacterPhysics {
|
|
|
97
98
|
aabbox.expandByPoint(segment.end);
|
|
98
99
|
aabbox.min.addScalar(-radius);
|
|
99
100
|
aabbox.max.addScalar(radius);
|
|
101
|
+
let grounded = false;
|
|
100
102
|
for (const bvh of this.world.getBodies()) {
|
|
101
103
|
bvh.shapecast({
|
|
102
104
|
intersectsBounds: (bounds) => bounds.intersectsBox(aabbox),
|
|
@@ -104,9 +106,11 @@ export class BvhCharacterPhysics {
|
|
|
104
106
|
// Use your existing triangle vs segment closestPointToSegment
|
|
105
107
|
const distance = tri.closestPointToSegment(segment, triPoint, capsulePoint);
|
|
106
108
|
if (distance === 0) {
|
|
107
|
-
const
|
|
108
|
-
|
|
109
|
-
|
|
109
|
+
const isCloserToSegmentStart = capsulePoint.distanceTo(segment.start) < capsulePoint.distanceTo(segment.end);
|
|
110
|
+
if (isCloserToSegmentStart) {
|
|
111
|
+
grounded = true;
|
|
112
|
+
}
|
|
113
|
+
const scaledDirection = capsulePoint.sub(isCloserToSegmentStart ? segment.start : segment.end);
|
|
110
114
|
scaledDirection.y += radius;
|
|
111
115
|
segment.start.add(scaledDirection);
|
|
112
116
|
segment.end.add(scaledDirection);
|
|
@@ -114,6 +118,10 @@ export class BvhCharacterPhysics {
|
|
|
114
118
|
else if (distance < radius) {
|
|
115
119
|
const depthInsideCapsule = radius - distance;
|
|
116
120
|
const direction = capsulePoint.sub(triPoint).divideScalar(distance);
|
|
121
|
+
const slope = Math.tan(Math.acos(direction.dot(YAxis)));
|
|
122
|
+
if (direction.y > 0 && slope <= maxGroundSlope) {
|
|
123
|
+
grounded = true;
|
|
124
|
+
}
|
|
117
125
|
segment.start.addScaledVector(direction, depthInsideCapsule);
|
|
118
126
|
segment.end.addScaledVector(direction, depthInsideCapsule);
|
|
119
127
|
}
|
|
@@ -122,6 +130,7 @@ export class BvhCharacterPhysics {
|
|
|
122
130
|
}
|
|
123
131
|
position.copy(segment.start);
|
|
124
132
|
position.y -= radius;
|
|
133
|
+
return grounded;
|
|
125
134
|
}
|
|
126
135
|
}
|
|
127
136
|
export * from './world.js';
|
package/dist/simple-character.js
CHANGED
|
@@ -58,6 +58,7 @@ async function* SimpleCharacterTimeline(camera, character) {
|
|
|
58
58
|
return performance.now() / 1000 - lastTimePressed < (jumpOptions?.bufferTime ?? 0.1);
|
|
59
59
|
}
|
|
60
60
|
function applyJumpForce() {
|
|
61
|
+
lastJump = performance.now() / 1000;
|
|
61
62
|
character.physics.applyVelocity(vector.set(0, (typeof character.options.movement?.jump === 'object' ? character.options.movement?.jump.speed : undefined) ??
|
|
62
63
|
8, 0));
|
|
63
64
|
}
|
|
@@ -152,7 +153,7 @@ async function* SimpleCharacterTimeline(camera, character) {
|
|
|
152
153
|
actions.jumpForward.paused = true;
|
|
153
154
|
actions.jumpForward.fadeIn(character.options.animation?.crossFadeDuration ?? DefaultCrossFadeDuration);
|
|
154
155
|
},
|
|
155
|
-
update: () => void character.physics.inputVelocity.multiplyScalar(
|
|
156
|
+
update: () => void character.physics.inputVelocity.multiplyScalar(0.3),
|
|
156
157
|
until: timePassed((typeof character.options.movement?.jump === 'object'
|
|
157
158
|
? character.options.movement?.jump.delay
|
|
158
159
|
: undefined) ?? DefaultJumDelay, 'seconds'),
|
|
@@ -197,7 +198,7 @@ async function* SimpleCharacterTimeline(camera, character) {
|
|
|
197
198
|
}),
|
|
198
199
|
transitionTo: {
|
|
199
200
|
jumpDown: {
|
|
200
|
-
when: (_, clock) => clock.actionTime > 0.
|
|
201
|
+
when: (_, clock) => clock.actionTime > 0.3 && character.physics.isGrounded,
|
|
201
202
|
},
|
|
202
203
|
finally: 'jumpLoop',
|
|
203
204
|
},
|
|
@@ -226,7 +227,7 @@ async function* SimpleCharacterTimeline(camera, character) {
|
|
|
226
227
|
actions.jumpDown.fadeIn(character.options.animation?.crossFadeDuration ?? DefaultCrossFadeDuration);
|
|
227
228
|
},
|
|
228
229
|
cleanup: () => actions.jumpDown.fadeOut(character.options.animation?.crossFadeDuration ?? DefaultCrossFadeDuration),
|
|
229
|
-
until: timePassed(
|
|
230
|
+
until: timePassed(150, 'milliseconds'),
|
|
230
231
|
}),
|
|
231
232
|
transitionTo: { finally: 'moving' },
|
|
232
233
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pmndrs/viverse",
|
|
3
|
-
"description": "Toolkit for building Three.js Apps for
|
|
3
|
+
"description": "Toolkit for building Three.js Apps for VIVERSE and beyond.",
|
|
4
4
|
"author": "Bela Bohlender",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE",
|
|
6
6
|
"homepage": "https://github.com/pmndrs/viverse",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"peerDependencies": {
|
|
22
22
|
"three": "*"
|
|
23
23
|
},
|
|
24
|
-
"version": "0.1.
|
|
24
|
+
"version": "0.1.10",
|
|
25
25
|
"type": "module",
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"@pixiv/three-vrm": "^3.4.2",
|