Skip to content

Commit

Permalink
Physics Prestep Types (#15227)
Browse files Browse the repository at this point in the history
* Physics Prestep Types

* missing infos in collision events

* typo
  • Loading branch information
CedricGuillemet authored Jun 24, 2024
1 parent a6dc77a commit d33f487
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 15 deletions.
9 changes: 9 additions & 0 deletions packages/dev/core/src/Physics/v2/IPhysicsEnginePlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
Expand Down
41 changes: 28 additions & 13 deletions packages/dev/core/src/Physics/v2/Plugins/havokPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
PhysicsConstraintAxis,
PhysicsConstraintAxisLimitMode,
PhysicsEventType,
PhysicsPrestepType,
PhysicsActivationControl,
} from "../IPhysicsEnginePlugin";
import type {
Expand Down Expand Up @@ -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.");
}
}

Expand Down Expand Up @@ -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);
}
Expand All @@ -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),
};
Expand All @@ -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);
}
Expand All @@ -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),
};
Expand Down
28 changes: 26 additions & 2 deletions packages/dev/core/src/Physics/v2/physicsBody.ts
Original file line number Diff line number Diff line change
@@ -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";
Expand Down Expand Up @@ -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.
Expand All @@ -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.
Expand Down Expand Up @@ -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,
Expand Down

0 comments on commit d33f487

Please sign in to comment.