physx-js-webidl
physx-js-webidl copied to clipboard
Active Actors API bug
Hey, i hope you are doing well
introduction
I was looking the physx official documentation and stumbled upon the active actors API, it creates a list of rigid bodies that moved in the last iteration, it is pretty handy and provides a slight performance improvement.
https://nvidia-omniverse.github.io/PhysX/physx/5.3.1/docs/RigidBodyDynamics.html?highlight=active%20actor#active-actors
problem
When consuming the api like this.
let activeActors = PhysX.SupportFunctions.prototype.PxScene_getActiveActors(scene);
And checking if there are any active actors like this.
console.log(activeActors.size())
It always returns 0 no matter what.
reproducible example
Here is the modified example scene to reflect this bug. I added some comments indicating changes and added a console.log for logging activeActors.size()
<!DOCTYPE html>
<head>
<title>PhysX Test</title>
<style>
html,
body,
canvas {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
}
canvas {
display: block;
}
</style>
</head>
<body>
<canvas></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gl-matrix/3.4.2/gl-matrix-min.js"
integrity="sha512-eV9ExyTa3b+YHr99IBTYpwk4wbgDMDlfW8uTxhywO8dWb810fGUSKDgHhEv1fAqmJT4jyYnt1iWWMW4FRxeQOQ=="
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="physx-js-webidl.js"></script>
<script>
PhysX().then(function (PhysX) {
var version = PhysX.PHYSICS_VERSION;
var allocator = new PhysX.PxDefaultAllocator();
var errorCb = new PhysX.PxDefaultErrorCallback();
var foundation = PhysX.CreateFoundation(version, allocator, errorCb);
var tolerances = new PhysX.PxTolerancesScale();
var physics = PhysX.CreatePhysics(version, foundation, tolerances);
var tmpVec = new PhysX.PxVec3(0, -9.81, 0);
var sceneDesc = new PhysX.PxSceneDesc(tolerances);
sceneDesc.set_gravity(tmpVec);
sceneDesc.set_cpuDispatcher(PhysX.DefaultCpuDispatcherCreate(0));
sceneDesc.set_filterShader(PhysX.DefaultFilterShader());
var scene = physics.createScene(sceneDesc);
///////////////////////// set flag ///////////////////////////////
scene.setFlag(PhysX.PxSceneFlagEnum.ENABLE_ACTIVE_ACTORS, true)
///////////////////////// set flag ///////////////////////////////
var material = physics.createMaterial(0.5, 0.5, 0.5);
var shapeFlags = new PhysX.PxShapeFlags(PhysX.PxShapeFlagEnum.eSCENE_QUERY_SHAPE | PhysX.PxShapeFlagEnum.eSIMULATION_SHAPE | PhysX.PxShapeFlagEnum.eVISUALIZATION);
var tmpPose = new PhysX.PxTransform(PhysX.PxIDENTITYEnum.PxIdentity);
var tmpFilterData = new PhysX.PxFilterData(1, 1, 0, 0);
var groundGeometry = new PhysX.PxBoxGeometry(10, 0.5, 10);
var groundShape = physics.createShape(groundGeometry, material, true, shapeFlags);
var ground = physics.createRigidStatic(tmpPose);
groundShape.setSimulationFilterData(tmpFilterData);
ground.attachShape(groundShape);
scene.addActor(ground);
var boxGeometry = new PhysX.PxBoxGeometry(0.5, 0.5, 0.5);
var lastBox = null;
for (var y = 0; y < 10; y++) {
tmpVec.set_x(0); tmpVec.set_y(y * 2 + 5); tmpVec.set_z(0);
tmpPose.set_p(tmpVec);
var boxShape = physics.createShape(boxGeometry, material, true, shapeFlags);
var box = physics.createRigidDynamic(tmpPose);
boxShape.setSimulationFilterData(tmpFilterData);
box.attachShape(boxShape);
scene.addActor(box);
lastBox = box;
}
PhysX.destroy(groundGeometry);
PhysX.destroy(boxGeometry);
PhysX.destroy(tmpFilterData);
PhysX.destroy(tmpPose);
PhysX.destroy(tmpVec);
PhysX.destroy(shapeFlags);
PhysX.destroy(sceneDesc);
PhysX.destroy(tolerances);
const {mat4, vec4, vec3} = glMatrix;
const viewMatrix = mat4.create();
const projectionMatrix = mat4.create();
const viewProjectionMatrix = mat4.create();
const tmpVec4 = vec4.create();
const canvas = document.querySelector('canvas');
const context = canvas.getContext('2d');
setupDebugDrawer(PhysX, scene);
simulationLoop();
function setupDebugDrawer() {
canvas.width = canvas.clientWidth;
canvas.height = canvas.clientHeight;
mat4.lookAt(viewMatrix, [12, 15, 20], [0, 0, 0], [0, 1, 0])
mat4.perspective(projectionMatrix, 45 * (Math.PI / 180), canvas.width / canvas.height, 0.01, 75);
mat4.multiply(viewProjectionMatrix, projectionMatrix, viewMatrix);
const context = canvas.getContext('2d');
scene.setVisualizationParameter(PhysX.eSCALE, 1);
scene.setVisualizationParameter(PhysX.eWORLD_AXES, 1);
scene.setVisualizationParameter(PhysX.eACTOR_AXES, 1);
scene.setVisualizationParameter(PhysX.eCOLLISION_SHAPES, 1);
}
///////////// check if there are active actors ///////////////
function logActiveActors() {
let activeActors = PhysX.SupportFunctions.prototype.PxScene_getActiveActors(scene);
console.log(activeActors.size())
}
///////////// check if there are active actors ///////////////
function simulationLoop() {
let lastFrame = 0;
requestAnimationFrame(function loop(hrTime) {
var timeStep = Math.min(0.03, (hrTime - lastFrame) / 1000);
scene.simulate(timeStep);
scene.fetchResults(true);
/////////// log active actors /////////////
logActiveActors()
/////////// log active actors /////////////
debugDraw(scene);
var lastBoxPos = lastBox.getGlobalPose().get_p();
lastFrame = hrTime;
requestAnimationFrame(loop);
});
}
function project(x, y, z) {
const result = vec4.transformMat4(tmpVec4, [x, y, z, 1], viewProjectionMatrix);
const clipX = (result[0] / result[3]);
const clipY = (result[1] / result[3]);
return [(canvas.width / 2) * (1 + clipX), (canvas.height / 2) * (1 - clipY)];
}
function drawLine(from, to, color) {
const [r, g, b] = color;
context.beginPath();
context.strokeStyle = `rgb(${255 * r}, ${255 * g}, ${255 * b})`;
context.moveTo(...from);
context.lineTo(...to);
context.stroke();
}
function debugDraw() {
canvas.width = canvas.width;
const rb = scene.getRenderBuffer();
for (let i = 0; i < rb.getNbLines(); i++) {
const line = PhysX.NativeArrayHelpers.prototype.getDebugLineAt(rb.getLines(), i);
const from = project(line.pos0.get_x(), line.pos0.get_y(), line.pos0.get_z());
const to = project(line.pos1.get_x(), line.pos1.get_y(), line.pos1.get_z());
drawLine(from, to, colors[line.get_color0()]);
}
}
const colors = {
[PhysX.PxDebugColorEnum.eARGB_BLACK]: [0, 0, 0],
[PhysX.PxDebugColorEnum.eARGB_RED]: [1, 0, 0],
[PhysX.PxDebugColorEnum.eARGB_GREEN]: [0, 1, 0],
[PhysX.PxDebugColorEnum.eARGB_BLUE]: [0, 0, 1],
[PhysX.PxDebugColorEnum.eARGB_YELLOW]: [1, 1, 0],
[PhysX.PxDebugColorEnum.eARGB_MAGENTA]: [1, 0, 1],
[PhysX.PxDebugColorEnum.eARGB_CYAN]: [0, 1, 1],
[PhysX.PxDebugColorEnum.eARGB_WHITE]: [1, 1, 1],
[PhysX.PxDebugColorEnum.eARGB_GREY]: [0.5, 0.5, 0.5],
[PhysX.PxDebugColorEnum.eARGB_DARKRED]: [0.5, 0, 0],
[PhysX.PxDebugColorEnum.eARGB_DARKGREEN]: [0, 0.5, 0],
[PhysX.PxDebugColorEnum.eARGB_DARKBLUE]: [0, 0, 0.5],
};
});
</script>
</body>
</html>
You made a typo :smile:
PhysX enum values are prefixed with a lower case 'e'. It has to be eENABLE_ACTIVE_ACTORS instead of ENABLE_ACTIVE_ACTORS:
scene.setFlag(PhysX.PxSceneFlagEnum.eENABLE_ACTIVE_ACTORS, true)
It's a bit odd that this is not an error. I assume the wasm runtime simply treats the undefined as a 0 and sets some other flag instead.
we have some faulty typescript types, here is the declaration in the physx-js-webidl.wasm.d.ts file.
enum PxSceneFlagEnum {
'ENABLE_ACTIVE_ACTORS',
[...]
}
and faulty me, should have researched a little bit more.
Thanks again for responding to my question, have a great day!
Did you generate the typescript bindings with the method given in the README.md?
The script isn't mine and I don't have any typescript experience at all, so unfortunately I won't be able to fix this :smiley: