Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions packages/core/src/physics/DynamicCollider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export class DynamicCollider extends Collider {
private _collisionDetectionMode: CollisionDetectionMode = CollisionDetectionMode.Discrete;
private _kinematicTransformSyncMode: DynamicColliderKinematicTransformSyncMode =
DynamicColliderKinematicTransformSyncMode.Target;
private _sleepThreshold = 5e-3;
private _sleepThreshold: number | undefined;
private _automaticCenterOfMass = true;
private _automaticInertiaTensor = true;

Expand Down Expand Up @@ -225,7 +225,7 @@ export class DynamicCollider extends Collider {
* The mass-normalized energy threshold, below which objects start going to sleep.
*/
get sleepThreshold(): number {
return this._sleepThreshold;
return this._sleepThreshold ?? Engine._nativePhysics?.getDefaultSleepThreshold?.() ?? 5e-3;
}

set sleepThreshold(value: number) {
Expand Down Expand Up @@ -532,7 +532,9 @@ export class DynamicCollider extends Collider {
}
(<IDynamicCollider>this._nativeCollider).setMaxAngularVelocity(this._maxAngularVelocity);
(<IDynamicCollider>this._nativeCollider).setMaxDepenetrationVelocity(this._maxDepenetrationVelocity);
(<IDynamicCollider>this._nativeCollider).setSleepThreshold(this._sleepThreshold);
if (this._sleepThreshold !== undefined) {
(<IDynamicCollider>this._nativeCollider).setSleepThreshold(this._sleepThreshold);
}
(<IDynamicCollider>this._nativeCollider).setSolverIterations(this._solverIterations);
(<IDynamicCollider>this._nativeCollider).setUseGravity(this._useGravity);
(<IDynamicCollider>this._nativeCollider).setIsKinematic(this._isKinematic);
Expand Down
25 changes: 23 additions & 2 deletions packages/core/src/physics/PhysicsMaterial.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { IPhysicsMaterial } from "@galacean/engine-design";
import { Engine } from "../Engine";
import { PhysicsMaterialCombineMode } from "./enums/PhysicsMaterialCombineMode";
import { ignoreClone } from "../clone/CloneManager";

/**
* Material class to represent a set of surface properties.
Expand All @@ -14,15 +15,16 @@ export class PhysicsMaterial {
private _destroyed: boolean;

/** @internal */
@ignoreClone
_nativeMaterial: IPhysicsMaterial;

constructor() {
this._nativeMaterial = Engine._nativePhysics.createPhysicsMaterial(
this._staticFriction,
this._dynamicFriction,
this._bounciness,
this._bounceCombine,
this._frictionCombine
this._frictionCombine,
this._bounceCombine
);
}

Expand Down Expand Up @@ -103,4 +105,23 @@ export class PhysicsMaterial {
!this._destroyed && this._nativeMaterial.destroy();
this._destroyed = true;
}

/**
* @internal
*/
_cloneTo(target: PhysicsMaterial): void {
target._syncNative();
}

/**
* @internal
*/
_syncNative(): void {
const nativeMaterial = this._nativeMaterial;
nativeMaterial.setStaticFriction(this._staticFriction);
nativeMaterial.setDynamicFriction(this._dynamicFriction);
nativeMaterial.setBounciness(this._bounciness);
nativeMaterial.setFrictionCombine(this._frictionCombine);
nativeMaterial.setBounceCombine(this._bounceCombine);
}
}
8 changes: 5 additions & 3 deletions packages/core/src/physics/shape/ColliderShape.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export abstract class ColliderShape implements ICustomClone {
private _rotation: Vector3 = new Vector3();
@deepClone
private _position: Vector3 = new Vector3();
private _contactOffset: number = 0.02;
private _contactOffset: number | undefined;

/**
* @internal
Expand Down Expand Up @@ -55,7 +55,7 @@ export abstract class ColliderShape implements ICustomClone {
* @defaultValue 0.02
*/
get contactOffset(): number {
return this._contactOffset;
return this._contactOffset ?? Engine._nativePhysics?.getDefaultContactOffset?.() ?? 0.02;
}

set contactOffset(value: number) {
Expand Down Expand Up @@ -183,7 +183,9 @@ export abstract class ColliderShape implements ICustomClone {
if (!this._nativeShape) return;
this._nativeShape.setPosition(this._position);
this._nativeShape.setRotation(this._rotation);
this._nativeShape.setContactOffset(this._contactOffset);
if (this._contactOffset !== undefined) {
this._nativeShape.setContactOffset(this._contactOffset);
}
this._nativeShape.setIsTrigger(this._isTrigger);
this._nativeShape.setMaterial(this._material._nativeMaterial);

Expand Down
55 changes: 43 additions & 12 deletions packages/core/src/physics/shape/MeshColliderShape.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,12 @@ export class MeshColliderShape extends ColliderShape {

set cookingFlags(value: MeshColliderShapeCookingFlag) {
if (this._cookingFlags !== value) {
const previousValue = this._cookingFlags;
this._cookingFlags = value;
if (this._nativeShape) {
this._updateNativeShapeData();
if (!this._updateNativeShapeData()) {
this._cookingFlags = previousValue;
}
} else if (this._mesh && this._extractMeshData(this._mesh)) {
this._createNativeShape();
}
Expand Down Expand Up @@ -71,14 +74,29 @@ export class MeshColliderShape extends ColliderShape {

set mesh(value: ModelMesh) {
if (this._mesh !== value) {
const previousMesh = this._mesh;
const previousPositions = this._positions;
const previousIndices = this._indices;
this._mesh?._addReferCount(-1);
value?._addReferCount(1);
this._mesh = value;
if (value && this._extractMeshData(value)) {
if (this._nativeShape) {
this._updateNativeShapeData();
if (value) {
if (this._extractMeshData(value)) {
if (this._nativeShape) {
if (!this._updateNativeShapeData()) {
value?._addReferCount(-1);
previousMesh?._addReferCount(1);
this._mesh = previousMesh;
this._positions = previousPositions;
this._indices = previousIndices;
}
} else {
this._createNativeShape();
}
} else {
this._createNativeShape();
// Mesh data extraction cannot recover without assigning a new mesh.
this._destroyNativeShape();
this._clearMeshData();
}
} else {
this._destroyNativeShape();
Expand Down Expand Up @@ -152,7 +170,7 @@ export class MeshColliderShape extends ColliderShape {
return true;
}

private _updateNativeShapeData(): void {
private _updateNativeShapeData(): boolean {
if (
(<IMeshColliderShape>this._nativeShape).setMeshData(
this._positions,
Expand All @@ -161,13 +179,12 @@ export class MeshColliderShape extends ColliderShape {
this._cookingFlags
)
) {
// Re-add to collider if previously removed due to cooking failure
if (this._collider && !this._isShapeAttached) {
this._attachToCollider();
}
} else if (this._isShapeAttached) {
this._detachFromCollider();
return true;
}
return false;
}

private _detachFromCollider(): void {
Expand All @@ -180,11 +197,11 @@ export class MeshColliderShape extends ColliderShape {
this._isShapeAttached = true;
}

private _createNativeShape(): void {
private _createNativeShape(): boolean {
// Non-convex MeshColliderShape is only supported on StaticCollider or kinematic DynamicCollider
if (!this._isConvex && this._collider instanceof DynamicCollider && !this._collider.isKinematic) {
console.error("MeshColliderShape: Non-convex mesh is not supported on non-kinematic DynamicCollider.");
return;
return false;
}

const nativeShape = Engine._nativePhysics.createMeshColliderShape(
Expand All @@ -197,7 +214,7 @@ export class MeshColliderShape extends ColliderShape {
);

if (!nativeShape) {
return;
return false;
}

this._nativeShape = nativeShape;
Expand All @@ -210,5 +227,19 @@ export class MeshColliderShape extends ColliderShape {
nativeShape.setWorldScale(this._collider.entity.transform.lossyWorldScale);
this._attachToCollider();
}
return true;
}

/**
* @internal
* After CloneManager deep-copies `_positions` / `_indices` / `_mesh` and remaps `_collider`,
* the cloned shape still has no native PhysX shape because `_nativeShape` is `@ignoreClone`.
* Cook a fresh native shape now using the already-cloned vertex/index buffers.
*/
override _cloneTo(target: MeshColliderShape): void {
super._cloneTo(target);
if (target._positions) {
target._createNativeShape();
}
}
}
10 changes: 10 additions & 0 deletions packages/design/src/physics/IPhysics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,16 @@ export interface IPhysics {
*/
createPhysicsScene(physicsManager: IPhysicsManager): IPhysicsScene;

/**
* Get the default contact offset for collider shapes.
*/
getDefaultContactOffset?(): number;

/**
* Get the default sleep threshold for dynamic colliders.
*/
getDefaultSleepThreshold?(): number;

/**
* Create dynamic collider.
* @param position - The global position
Expand Down
24 changes: 19 additions & 5 deletions packages/physics-lite/src/LitePhysicsMaterial.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,16 @@ import { IPhysicsMaterial } from "@galacean/engine-design";

/**
* Physics material describes how to handle colliding objects (friction, bounciness).
*
* Physics-lite does not implement material effects; setters are no-ops (matching
* the convention used by `LiteColliderShape.setMaterial/setContactOffset/setIsTrigger`).
* This lets engine-side state changes (including clone `_syncNative` re-writes) flow
* through without crashing while still leaving a one-time hint via console.log on
* the first write so users notice the limitation.
*/
export class LitePhysicsMaterial implements IPhysicsMaterial {
private static _warned = false;

constructor(
staticFriction: number,
dynamicFriction: number,
Expand All @@ -16,39 +24,45 @@ export class LitePhysicsMaterial implements IPhysicsMaterial {
* {@inheritDoc IPhysicsMaterial.setBounciness }
*/
setBounciness(value: number): void {
throw "Physics-lite don't support physics material. Use Physics-PhysX instead!";
LitePhysicsMaterial._warnOnce();
}

/**
* {@inheritDoc IPhysicsMaterial.setDynamicFriction }
*/
setDynamicFriction(value: number): void {
throw "Physics-lite don't support physics material. Use Physics-PhysX instead!";
LitePhysicsMaterial._warnOnce();
}

/**
* {@inheritDoc IPhysicsMaterial.setStaticFriction }
*/
setStaticFriction(value: number): void {
throw "Physics-lite don't support physics material. Use Physics-PhysX instead!";
LitePhysicsMaterial._warnOnce();
}

/**
* {@inheritDoc IPhysicsMaterial.setBounceCombine }
*/
setBounceCombine(value: number): void {
throw "Physics-lite don't support physics material. Use Physics-PhysX instead!";
LitePhysicsMaterial._warnOnce();
}

/**
* {@inheritDoc IPhysicsMaterial.setFrictionCombine }
*/
setFrictionCombine(value: number): void {
throw "Physics-lite don't support physics material. Use Physics-PhysX instead!";
LitePhysicsMaterial._warnOnce();
}

/**
* {@inheritDoc IPhysicsMaterial.destroy }
*/
destroy(): void {}

private static _warnOnce(): void {
if (LitePhysicsMaterial._warned) return;
LitePhysicsMaterial._warned = true;
console.log("Physics-lite don't support physics material. Use Physics-PhysX instead!");
}
}
2 changes: 1 addition & 1 deletion packages/physics-physx/src/PhysXCharacterController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ export class PhysXCharacterController implements ICharacterController {
this._pxManager && this._createPXController(this._pxManager, shape);
this._shape = shape;
shape._controllers.add(this);
this._pxController?.setContactOffset(shape._contractOffset);
this._pxController?.setContactOffset(shape._contactOffset);
this._scene?._addColliderShape(shape._id);
}

Expand Down
Loading
Loading