8000 Support custom physX url by luzhuang · Pull Request #2672 · galacean/engine · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Support custom physX url #2672

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 15 commits into from
May 21, 2025
Merged
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
58 changes: 58 additions & 0 deletions e2e/.dev/physx.release.downgrade.js

Large diffs are not rendered by default.

21 changes: 21 additions & 0 deletions e2e/.dev/physx.release.js

Large diffs are not rendered by default.

Binary file added e2e/.dev/physx.release.wasm
Binary file not shown.
157 changes: 157 additions & 0 deletions e2e/case/physx-customUrl.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
/**
* @title PhysX Custom Url
* @category Physics
*/
import {
WebGLEngine,
SphereColliderShape,
DynamicCollider,
BoxColliderShape,
Vector3,
MeshRenderer,
PointLight,
PrimitiveMesh,
Camera,
Script,
StaticCollider,
ColliderShape,
PBRMaterial,
AmbientLight,
AssetType,
BlinnPhongMaterial,
Entity,
} from "@galacean/engine";
import { WireframeManager } from "@galacean/engine-toolkit";

import { PhysXPhysics, PhysXRuntimeMode } from "@galacean/engine-physics-physx";
import { initScreenshot, updateForE2E } from "./.mockForE2E";

function addBox(rootEntity: Entity, cubeSize: number, x: number, y: number, z: number, index: number) {
const boxEntity = rootEntity.createChild("BoxEntity");
boxEntity.transform.setPosition(x, y, z);
boxEntity.transform.setScale(-1, 1, 1);

const boxMtl = new PBRMaterial(rootEntity.engine);
const boxRenderer = boxEntity.addComponent(MeshRenderer);
boxMtl.baseColor.set(0.6, 0.3, 0.3, 1.0);
boxMtl.roughness = 0.5;
boxMtl.metallic = 0.0;
boxRenderer.mesh = PrimitiveMesh.createCuboid(rootEntity.engine, cubeSize, cubeSize, cubeSize);
boxRenderer.setMaterial(boxMtl);
if (index === 0) {
boxMtl.baseColor.set(1, 0, 0, 1.0);
} else {
boxMtl.baseColor.set(0, 1, 0, 1.0);
}

const physicsBox = new BoxColliderShape();
physicsBox.size = new Vector3(cubeSize, cubeSize, cubeSize);
physicsBox.material.staticFriction = 0.1;
physicsBox.material.dynamicFriction = 0.2;
physicsBox.material.bounciness = 1;
physicsBox.isTrigger = true;

const boxCollider = boxEntity.addComponent(StaticCollider);
boxCollider.addShape(physicsBox);
return boxEntity;
}

WebGLEngine.create({ canvas: "canvas", physics: new PhysXPhysics(PhysXRuntimeMode.Auto, {
physXUrl: "../physx.release.js"
}) }).then((engine) => {
engine.canvas.resizeByClientSize();
const scene = engine.sceneManager.activeScene;
const rootEntity = scene.createRootEntity("root");

scene.ambientLight.diffuseSolidColor.set(1, 1, 1, 1);
scene.ambientLight.diffuseIntensity = 1.2;

// init camera
const cameraEntity = rootEntity.createChild("camera");
const camera = cameraEntity.addComponent(Camera);
cameraEntity.transform.setPosition(-5, 0, 20);

// init point light
const light = rootEntity.createChild("light");
light.transform.setPosition(0, 3, 0);
light.addComponent(PointLight);

// create box test entity
const boxEntity1 = addBox(rootEntity, 2, 0, 0, 0, 0);
const boxEntity2 = addBox(rootEntity, 2, -10, 0, 0, 1);

// create sphere test entity
const radius = 1.25;
const sphereEntity = rootEntity.createChild("SphereEntity");
sphereEntity.transform.setPosition(-2, 0, 0);

const sphereMtl = new PBRMaterial(engine);
const sphereRenderer = sphereEntity.addComponent(MeshRenderer);
sphereMtl.baseColor.set(Math.random(), Math.random(), Math.random(), 1.0);
sphereMtl.metallic = 0.0;
sphereMtl.roughness = 0.5;
sphereRenderer.mesh = PrimitiveMesh.createSphere(engine, radius);
sphereRenderer.setMaterial(sphereMtl);

const physicsSphere = new SphereColliderShape();
physicsSphere.radius = radius;
physicsSphere.material.staticFriction = 0.1;
physicsSphere.material.dynamicFriction = 0.2;
physicsSphere.material.bounciness = 1;

const sphereCollider = sphereEntity.addComponent(DynamicCollider);
sphereCollider.isKinematic = true;
sphereCollider.addShape(physicsSphere);

rootEntity.addComponent(MeshRenderer);
const wireframe = rootEntity.addComponent(WireframeManager); // debug draw
wireframe.addEntityWireframe(sphereEntity);
wireframe.addEntityWireframe(boxEntity1);
wireframe.addEntityWireframe(boxEntity2);

class MoveScript extends Script {
pos: number = -5;
vel: number = 0.05;
velSign: number = -1;

onPhysicsUpdate() {
if (this.pos >= 5) {
this.velSign = -1;
}
if (this.pos <= -15) {
this.velSign = 1;
}
this.pos += this.vel * this.velSign;
this.entity.transform.worldPosition.set(this.pos, 0, 0);
}
}

// Collision Detection
class CollisionScript extends Script {
onTriggerExit(other: ColliderShape) {
(<BlinnPhongMaterial>sphereRenderer.getMaterial()).baseColor.set(1, 1, 1, 1.0);
}

onTriggerEnter(other: ColliderShape) {
(sphereRenderer.getMaterial() as BlinnPhongMaterial).baseColor = (
other.collider.entity.getComponent(MeshRenderer)?.getMaterial() as PBRMaterial
).baseColor;
}

onTriggerStay(other: ColliderShape) {}
}
Comment on lines +130 to +142
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Inconsistent material types and empty method.

There's a mismatch in material types and an empty method that could be improved.

 class CollisionScript extends Script {
   onTriggerExit(other: ColliderShape) {
-    (<BlinnPhongMaterial>sphereRenderer.getMaterial()).baseColor.set(1, 1, 1, 1.0);
+    const material = sphereRenderer.getMaterial() as PBRMaterial;
+    material.baseColor.set(1, 1, 1, 1.0);
   }

   onTriggerEnter(other: ColliderShape) {
-    (sphereRenderer.getMaterial() as BlinnPhongMaterial).baseColor = (
-      other.collider.entity.getComponent(MeshRenderer)?.getMaterial() as PBRMaterial
-    ).baseColor;
+    const sphereMaterial = sphereRenderer.getMaterial() as PBRMaterial;
+    const otherRenderer = other.collider.entity.getComponent(MeshRenderer);
+    if (otherRenderer) {
+      const otherMaterial = otherRenderer.getMaterial() as PBRMaterial;
+      sphereMaterial.baseColor.copyFrom(otherMaterial.baseColor);
+    }
   }

-  onTriggerStay(other: ColliderShape) {}
+  // No need for empty method, can be removed if not required
}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
class CollisionScript extends Script {
onTriggerExit(other: ColliderShape) {
(<BlinnPhongMaterial>sphereRenderer.getMaterial()).baseColor.set(1, 1, 1, 1.0);
}
onTriggerEnter(other: ColliderShape) {
(sphereRenderer.getMaterial() as BlinnPhongMaterial).baseColor = (
other.collider.entity.getComponent(MeshRenderer)?.getMaterial() as PBRMaterial
).baseColor;
}
onTriggerStay(other: ColliderShape) {}
}
class CollisionScript extends Script {
onTriggerExit(other: ColliderShape) {
- (<BlinnPhongMaterial>sphereRenderer.getMaterial()).baseColor.set(1, 1, 1, 1.0);
+ const material = sphereRenderer.getMaterial() as PBRMaterial;
+ material.baseColor.set(1, 1, 1, 1.0);
}
onTriggerEnter(other: ColliderShape) {
- (sphereRenderer.getMaterial() as BlinnPhongMaterial).baseColor = (
- other.collider.entity.getComponent(MeshRenderer)?.getMaterial() as PBRMaterial
- ).baseColor;
+ const sphereMaterial = sphereRenderer.getMaterial() as PBRMaterial;
+ const otherRenderer = other.collider.entity.getComponent(MeshRenderer);
+ if (otherRenderer) {
+ const otherMaterial = otherRenderer.getMaterial() as PBRMaterial;
+ sphereMaterial.baseColor.copyFrom(otherMaterial.baseColor);
+ }
}
- onTriggerStay(other: ColliderShape) {}
+ // No need for empty method, can be removed if not required
}
🤖 Prompt for AI Agents
In e2e/case/physx-customUrl.ts around lines 130 to 142, the onTriggerEnter
method assigns baseColor directly which may cause type inconsistencies between
BlinnPhongMaterial and PBRMaterial. Refactor to consistently use the same
material type or properly convert colors to avoid type mismatch. Also, remove or
implement the empty onTriggerStay method to avoid unused code.


sphereEntity.addComponent(CollisionScript);
sphereEntity.addComponent(MoveScript);

engine.resourceManager
.load<AmbientLight>({
type: AssetType.Env,
url: "https://gw.alipayobjects.com/os/bmw-prod/89c54544-1184-45a1-b0f5-c0b17e5c3e68.bin"
})
.then((ambientLight) => {
scene.ambientLight = ambientLight;
updateForE2E(engine, 95);
initScreenshot(engine, camera);
});
});
5 changes: 5 additions & 0 deletions e2e/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,11 @@ export const E2E_CONFIG = {
category: "Physics",
caseFileName: "physx-collision-group",
threshold: 0.1
},
"PhysXPhysics Custom Url": {
category: "Physics",
caseFileName: "physx-customUrl",
threshold: 0.1
}
},
Particle: {
Expand Down
3 changes: 3 additions & 0 deletions e2e/fixtures/originImage/Physics_physx-customUrl.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
29 changes: 24 additions & 5 deletions packages/physics-physx/src/PhysXPhysics.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { Quaternion, Vector3, Layer } from "@galacean/engine";
import { Quaternion, Vector3 } from "@galacean/engine";
import {
IBoxColliderShape,
ICapsuleColliderShape,
ICharacterController,
ICollider,
ICollision,
IDynamicCollider,
IFixedJoint,
Expand Down Expand Up @@ -51,9 +50,22 @@ export class PhysXPhysics implements IPhysics {
private _defaultErrorCallback: any;
private _allocator: any;
private _tolerancesScale: any;
private _wasmModeUrl: string;
private _downgradeModeUrl: string;

constructor(runtimeMode: PhysXRuntimeMode = PhysXRuntimeMode.Auto) {
/**
* Create a PhysXPhysics instance.
* @param runtimeMode - Runtime use WebAssembly mode or downgrade JavaScript mode, `Auto` prefers webAssembly mode if supported @see {@link PhysXRuntimeMode}
* @param runtimeUrls - Manually specify the `PhysXRuntimeMode.WebAssembly` mode and `PhysXRuntimeMode.JavaScript` mode URL
*/
constructor(runtimeMode: PhysXRuntimeMode = PhysXRuntimeMode.Auto, runtimeUrls?: PhysXRuntimeUrls) {
this._runTimeMode = runtimeMode;
this._wasmModeUrl =
runtimeUrls?.wasmModeUrl ??
"https://mdn.alipayobjects.com/rms/afts/file/A*nL1PSrCPoZ0AAAAAAAAAAAAAARQnAQ/physx.release.js";
this._downgradeModeUrl =
runtimeUrls?.javaScriptModeUrl ??
&qu 997B ot;https://mdn.alipayobjects.com/rms/afts/file/A*ROBqQJEjZXAAAAAAAAAAAAAAARQnAQ/physx.release.downgrade.js";
}

/**
Expand Down Expand Up @@ -94,9 +106,9 @@ export class PhysXPhysics implements IPhysics {
}

if (runtimeMode == PhysXRuntimeMode.JavaScript) {
script.src = `https://mdn.alipayobjects.com/rms/afts/file/A*V4pqRqM65UMAAAAAAAAAAAAAARQnAQ/physx.release.downgrade.js`;
script.src = this._downgradeModeUrl;
} else if (runtimeMode == PhysXRuntimeMode.WebAssembly) {
script.src = `https://mdn.alipayobjects.com/rms/afts/file/A*nL1PSrCPoZ0AAAAAAAAAAAAAARQnAQ/physx.release.js`;
script.src = this._wasmModeUrl;
}
});

Expand Down Expand Up @@ -289,3 +301,10 @@ enum InitializeState {
Initializing,
Initialized
}

interface PhysXRuntimeUrls {
/*** The URL of `PhysXRuntimeMode.WebAssembly` mode. */
wasmModeUrl?: string;
/*** The URL of `PhysXRuntimeMode.JavaScript` mode. */
javaScriptModeUrl?: string;
}
Loading
0