Skip to content

Commit e6160f1

Browse files
jon-heardRolandCsibrei
authored andcommitted
new feature - slideOnCollide parameter for "abstractMesh.moveWithCollisions" (defaults to true) (BabylonJS#16580)
Optional slideOnCollide parameter added to "abstractMesh.moveWithCollisions", and it's logic implemented
1 parent e36de9a commit e6160f1

File tree

3 files changed

+26
-8
lines changed

3 files changed

+26
-8
lines changed

packages/dev/core/src/Collisions/collider.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -500,11 +500,20 @@ export class Collider {
500500
/**
501501
* @internal
502502
*/
503-
public _getResponse(pos: Vector3, vel: Vector3): void {
503+
public _getResponse(pos: Vector3, vel: Vector3, slideOnCollide: boolean): void {
504+
// Handle straight movement up to collision
505+
504506
pos.addToRef(vel, this._destinationPoint);
505507
vel.scaleInPlace(this._nearestDistance / vel.length());
506508

507509
this._basePoint.addToRef(vel, pos);
510+
511+
if (!slideOnCollide) {
512+
return;
513+
}
514+
515+
// Handle slide movement past collision
516+
508517
pos.subtractToRef(this.intersectionPoint, this._slidePlaneNormal);
509518
this._slidePlaneNormal.normalize();
510519
this._slidePlaneNormal.scaleToRef(this._epsilon, this._displacementVector);

packages/dev/core/src/Collisions/collisionCoordinator.ts

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ export interface ICollisionCoordinator {
1515
maximumRetry: number,
1616
excludedMesh: Nullable<AbstractMesh>,
1717
onNewPosition: (collisionIndex: number, newPosition: Vector3, collidedMesh: Nullable<AbstractMesh>) => void,
18-
collisionIndex: number
18+
collisionIndex: number,
19+
slideOnCollide?: boolean
1920
): void;
2021
init(scene: Scene): void;
2122
}
@@ -36,15 +37,16 @@ export class DefaultCollisionCoordinator implements ICollisionCoordinator {
3637
maximumRetry: number,
3738
excludedMesh: AbstractMesh,
3839
onNewPosition: (collisionIndex: number, newPosition: Vector3, collidedMesh: Nullable<AbstractMesh>) => void,
39-
collisionIndex: number
40+
collisionIndex: number,
41+
slideOnCollide: boolean = true
4042
): void {
4143
position.divideToRef(collider._radius, this._scaledPosition);
4244
displacement.divideToRef(collider._radius, this._scaledVelocity);
4345
collider.collidedMesh = null;
4446
collider._retry = 0;
4547
collider._initialVelocity = this._scaledVelocity;
4648
collider._initialPosition = this._scaledPosition;
47-
this._collideWithWorld(this._scaledPosition, this._scaledVelocity, collider, maximumRetry, this._finalPosition, excludedMesh);
49+
this._collideWithWorld(this._scaledPosition, this._scaledVelocity, collider, maximumRetry, this._finalPosition, slideOnCollide, excludedMesh);
4850

4951
this._finalPosition.multiplyInPlace(collider._radius);
5052
//run the callback
@@ -65,6 +67,7 @@ export class DefaultCollisionCoordinator implements ICollisionCoordinator {
6567
collider: Collider,
6668
maximumRetry: number,
6769
finalPosition: Vector3,
70+
slideOnCollide: boolean,
6871
excludedMesh: Nullable<AbstractMesh> = null
6972
): void {
7073
const closeDistance = AbstractEngine.CollisionsEpsilon * 10.0;
@@ -96,7 +99,11 @@ export class DefaultCollisionCoordinator implements ICollisionCoordinator {
9699
}
97100

98101
if (velocity.x !== 0 || velocity.y !== 0 || velocity.z !== 0) {
99-
collider._getResponse(position, velocity);
102+
collider._getResponse(position, velocity, slideOnCollide);
103+
// Halt all movement at the first collision, if not slideOnCollide
104+
if (!slideOnCollide) {
105+
velocity.setAll(0);
106+
}
100107
}
101108

102109
if (velocity.length() <= closeDistance) {
@@ -105,7 +112,7 @@ export class DefaultCollisionCoordinator implements ICollisionCoordinator {
105112
}
106113

107114
collider._retry++;
108-
this._collideWithWorld(position, velocity, collider, maximumRetry, finalPosition, excludedMesh);
115+
this._collideWithWorld(position, velocity, collider, maximumRetry, finalPosition, slideOnCollide, excludedMesh);
109116
}
110117
}
111118

packages/dev/core/src/Meshes/abstractMesh.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1929,9 +1929,10 @@ export abstract class AbstractMesh extends TransformNode implements IDisposable,
19291929
* Move the mesh using collision engine
19301930
* @see https://doc.babylonjs.com/features/featuresDeepDive/cameras/camera_collisions
19311931
* @param displacement defines the requested displacement vector
1932+
* @param slideOnCollide If true, the mesh will slide along a collider's surface. If false, it will stop moving at the first collision. (true by default)
19321933
* @returns the current mesh
19331934
*/
1934-
public moveWithCollisions(displacement: Vector3): AbstractMesh {
1935+
public moveWithCollisions(displacement: Vector3, slideOnCollide: boolean = true): AbstractMesh {
19351936
const globalPosition = this.getAbsolutePosition();
19361937

19371938
globalPosition.addToRef(this.ellipsoidOffset, this._internalAbstractMeshDataInfo._meshCollisionData._oldPositionForCollisions);
@@ -1950,7 +1951,8 @@ export abstract class AbstractMesh extends TransformNode implements IDisposable,
19501951
this.collisionRetryCount,
19511952
this,
19521953
this._onCollisionPositionChange,
1953-
this.uniqueId
1954+
this.uniqueId,
1955+
slideOnCollide
19541956
);
19551957
return this;
19561958
}

0 commit comments

Comments
 (0)