diff --git a/packages/dev/core/src/Physics/v2/IPhysicsEnginePlugin.ts b/packages/dev/core/src/Physics/v2/IPhysicsEnginePlugin.ts index 1954f01dad1..0f6a2a05728 100644 --- a/packages/dev/core/src/Physics/v2/IPhysicsEnginePlugin.ts +++ b/packages/dev/core/src/Physics/v2/IPhysicsEnginePlugin.ts @@ -351,6 +351,15 @@ export const enum PhysicsMotionType { DYNAMIC, } +/** + * Indicates how to handle position/rotation change of transform node attached to a physics body + */ +export enum PhysicsPrestepType { + DISABLED, + TELEPORT, + ACTION, +} + /** * Controls the body sleep mode. */ diff --git a/packages/dev/core/src/Physics/v2/Plugins/havokPlugin.ts b/packages/dev/core/src/Physics/v2/Plugins/havokPlugin.ts index 41522cc3ec5..9559a8c887d 100644 --- a/packages/dev/core/src/Physics/v2/Plugins/havokPlugin.ts +++ b/packages/dev/core/src/Physics/v2/Plugins/havokPlugin.ts @@ -7,6 +7,7 @@ import { PhysicsConstraintAxis, PhysicsConstraintAxisLimitMode, PhysicsEventType, + PhysicsPrestepType, PhysicsActivationControl, } from "../IPhysicsEnginePlugin"; import type { @@ -1140,19 +1141,25 @@ export class HavokPlugin implements IPhysicsEnginePluginV2 { * same transformation. */ public setPhysicsBodyTransformation(body: PhysicsBody, node: TransformNode) { - const transformNode = body.transformNode; - if (body.numInstances > 0) { - // instances - const m = transformNode as Mesh; - const matrixData = m._thinInstanceDataStorage.matrixData; - if (!matrixData) { - return; // TODO: error handling + if (body.getPrestepType() == PhysicsPrestepType.TELEPORT) { + const transformNode = body.transformNode; + if (body.numInstances > 0) { + // instances + const m = transformNode as Mesh; + const matrixData = m._thinInstanceDataStorage.matrixData; + if (!matrixData) { + return; // TODO: error handling + } + const instancesCount = body.numInstances; + this._createOrUpdateBodyInstances(body, body.getMotionType(), matrixData, 0, instancesCount, true); + } else { + // regular + this._hknp.HP_Body_SetQTransform(body._pluginData.hpBodyId, this._getTransformInfos(node)); } - const instancesCount = body.numInstances; - this._createOrUpdateBodyInstances(body, body.getMotionType(), matrixData, 0, instancesCount, true); + } else if (body.getPrestepType() == PhysicsPrestepType.ACTION) { + this.setTargetTransform(body, node.absolutePosition, node.absoluteRotationQuaternion); } else { - // regular - this._hknp.HP_Body_SetQTransform(body._pluginData.hpBodyId, this._getTransformInfos(node)); + Logger.Warn("Invalid prestep type set to physics body."); } } @@ -2323,7 +2330,8 @@ export class HavokPlugin implements IPhysicsEnginePluginV2 { if (this._bodyCollisionObservable.size && collisionInfo.type !== PhysicsEventType.COLLISION_FINISHED) { const observableA = this._bodyCollisionObservable.get(event.contactOnA.bodyId); const observableB = this._bodyCollisionObservable.get(event.contactOnB.bodyId); - + event.contactOnA.position.subtractToRef(event.contactOnB.position, this._tmpVec3[0]); + const distance = Vector3.Dot(this._tmpVec3[0], event.contactOnB.normal); if (observableA) { observableA.notifyObservers(collisionInfo); } @@ -2333,6 +2341,9 @@ export class HavokPlugin implements IPhysicsEnginePluginV2 { colliderIndex: bodyInfoB.index, collidedAgainst: bodyInfoA.body, collidedAgainstIndex: bodyInfoA.index, + point: event.contactOnB.position, + distance: distance, + impulse: event.impulseApplied, normal: event.contactOnB.normal, type: this._nativeCollisionValueToCollisionType(event.type), }; @@ -2341,7 +2352,8 @@ export class HavokPlugin implements IPhysicsEnginePluginV2 { } else if (this._bodyCollisionEndedObservable.size) { const observableA = this._bodyCollisionEndedObservable.get(event.contactOnA.bodyId); const observableB = this._bodyCollisionEndedObservable.get(event.contactOnB.bodyId); - + event.contactOnA.position.subtractToRef(event.contactOnB.position, this._tmpVec3[0]); + const distance = Vector3.Dot(this._tmpVec3[0], event.contactOnB.normal); if (observableA) { observableA.notifyObservers(collisionInfo); } @@ -2351,6 +2363,9 @@ export class HavokPlugin implements IPhysicsEnginePluginV2 { colliderIndex: bodyInfoB.index, collidedAgainst: bodyInfoA.body, collidedAgainstIndex: bodyInfoA.index, + point: event.contactOnB.position, + distance: distance, + impulse: event.impulseApplied, normal: event.contactOnB.normal, type: this._nativeCollisionValueToCollisionType(event.type), }; diff --git a/packages/dev/core/src/Physics/v2/physicsBody.ts b/packages/dev/core/src/Physics/v2/physicsBody.ts index 102691b604c..03ef803b7ef 100644 --- a/packages/dev/core/src/Physics/v2/physicsBody.ts +++ b/packages/dev/core/src/Physics/v2/physicsBody.ts @@ -1,5 +1,5 @@ import type { IBasePhysicsCollisionEvent, IPhysicsCollisionEvent, IPhysicsEnginePluginV2, PhysicsMassProperties } from "./IPhysicsEnginePlugin"; -import { PhysicsMotionType } from "./IPhysicsEnginePlugin"; +import { PhysicsMotionType, PhysicsPrestepType } from "./IPhysicsEnginePlugin"; import type { PhysicsShape } from "./physicsShape"; import { Vector3, Quaternion, TmpVectors } from "../../Maths/math.vector"; import type { Scene } from "../../scene"; @@ -49,11 +49,18 @@ export class PhysicsBody { * The transform node associated with this Physics Body */ transformNode: TransformNode; + /** * Disable pre-step that consists in updating Physics Body from Transform Node Translation/Orientation. * True by default for maximum performance. */ - disablePreStep: boolean = true; + public get disablePreStep(): boolean { + return this._prestepType == PhysicsPrestepType.DISABLED; + } + + public set disablePreStep(value: boolean) { + this._prestepType = value ? PhysicsPrestepType.DISABLED : PhysicsPrestepType.TELEPORT; + } /** * Disable sync from physics to transformNode. This value is set to true at body creation or at motionType setting when the body is not dynamic. @@ -73,6 +80,7 @@ export class PhysicsBody { private _motionType: PhysicsMotionType; + private _prestepType: PhysicsPrestepType = PhysicsPrestepType.DISABLED; /** * Constructs a new physics body for the given node. * @param transformNode - The Transform Node to construct the physics body for. For better performance, it is advised that this node does not have a parent. @@ -264,6 +272,22 @@ export class PhysicsBody { return this._physicsPlugin.getMotionType(this, instanceIndex); } + /** + * Set the prestep type of the body + * @param prestepType prestep type provided by PhysicsPrestepType + */ + public setPrestepType(prestepType: PhysicsPrestepType): void { + this._prestepType = prestepType; + } + + /** + * Get the current prestep type of the body + * @returns the type of prestep associated with the body and its instance index + */ + public getPrestepType(): PhysicsPrestepType { + return this._prestepType; + } + /** * Computes the mass properties of the physics object, based on the set of physics shapes this body uses. * This method is useful for computing the initial mass properties of a physics object, such as its mass,