physx-js-webidl
physx-js-webidl copied to clipboard
Simulation Event Callback
I'm having an issue where my simulationEventCallback / JavaSimulationEventCallback doesn't seem to be called on collisions...
Setup:
const sceneDesc = new PhysX.PxSceneDesc(scale);
sceneDesc.gravity = new PhysX.PxVec3(this.state.gravity.x, this.state.gravity.y, this.state.gravity.z);
sceneDesc.cpuDispatcher = PhysX.PxTopLevelFunctions.DefaultCpuDispatcherCreate(0);
sceneDesc.filterShader = PhysX.PxTopLevelFunctions.DefaultFilterShader();
const eventCallback = new PhysX.JavaSimulationEventCallback();
eventCallback.onWake = (_a, _b) => console.log('wake');
eventCallback.onSleep = (_a, _b) => console.log('onSleep');
eventCallback.onContact = (_a, _b, _c) => console.log('onContact');
eventCallback.onTrigger = (pairs: PhysX.PxTriggerPair, count: number) => console.log('onTrigger');
sceneDesc.simulationEventCallback = eventCallback;
this.state.scene = this.state.physics.createScene(sceneDesc);
Ahh... I think it's to do with defaultFilterShader not including physx::PxPairFlag::eNOTIFY_TOUCH_FOUND | physx::PxPairFlag::eNOTIFY_TOUCH_LOST;
I'll comment with my findings
You are right, I did not include those flags by default because invoking JS / Java callbacks from native code is rather expensive and the touch notification function can be called an awful lot of times per simulation step (depending on the scene). So enabling them, without actually needing them wastes a lot of performance.
However, the defaultFilterShader also contains this line:
pairFlags |= physx::PxPairFlags(physx::PxU16(filterData0.word2 | filterData1.word2));
meaning that you can pass additional custom flags in by setting them in word2 of the shapes's simulationFilterData field.
So you should be able to set the eNOTIFY_TOUCH_FOUND and eNOTIFY_TOUCH_LOST flags in the simulationFilterData objects of your collision shapes and get notified when they participate in a collision. Moreover it should be possible to do this for only a few bodies of particular interest, to save the overhead of calling the callback function all the time for all bodies.
Thank you for explaining :)
@fabmax I'm trying to pull both shapes & actors out of an onContact callback. But it seems my pair.shapes is just an instance of Physx.PxShape not an array. And then pairHeader is just a number - I assume just a pointer - would that mean we need to add a PhysX.TypeHelpers.getPxContactPairHeaderAt?
Code:
eventCallback .onContact = (pairHeader: PhysX.PxContactPairHeader, pairs: PhysX.PxContactPair, nbPairs: number) => {
for (let index = 0; index < nbPairs; index++) {
const pair = PhysX.TypeHelpers.getContactPairAt(pairs, index);
console.log('Contact begin');
console.log(pair.shapes);
console.log(pairHeader);
}
};
Output:
Contact begin
index.js:69159 PxShape {ptr: 7146400}
index.js:69160 5452888
Hmm, I would say you are doing it right. It's a bit odd that pairHeader is only a number. In native code it's passed in by reference and the WebIDL definition also looks right. So it should be an object... You can try what happens if you put that number into some PhysX.TypeHelpers.getPxContactPairHeaderAt - it sure looks like a pointer.
The shapes field being a simple instance instead of a field is because array support of emscripten / WebIDL binder is very limited (and always a pain). I guess the easiest thing here would be yet another type helper function: PhysX.TypeHelpers.getShapeAt. The same thing would probably apply to the actors field in the PxContactPairHeader.
Hello everyone
So in the end what should I do with JS so this code can work? I want to get the Shape and later the Actor to write my logic.
It will be a big thanks if anyone can help me!

well getPxContactPairHeaderAt return actors is a array so
let p = typeHelpers.getContactPairHeaderAt(pairs, 0)
let b1 = typeHelpers.getActorAt( p.actors, 0)
let b2 = typeHelpers.getActorAt( p.actors, 1)
my question is how find original PxRigidDynamic from this pxActor ? is not same ptr
ok i find so for trigger is
let p = typeHelpers.getTriggerPairAt(pairs, 0)
let g1 = p.triggerActor
let g2 = p.otherActor
let s = p.status
if(s===4) contact = true
if(s===16) contact = false
now i have good ptr so i can find good name
@lo-th I've posted a little snippet of code that will 'fix' Enums in JS
https://github.com/fabmax/physx-js-webidl/issues/5#issuecomment-1021481070
This should allow you to do
let triggerPair = typeHelpers.getTriggerPairAt(pairs, 0);
let isTrigger = triggerPair.status == PhysX.PxPairFlagEnum.NOTIFY_TOUCH_FOUND;
i have problem on shape = typeHelpers.getShapeAt(body, i) return shape is good but i can't change flag if useful for activate contact shape.setSimulationFilterData( queryFilter ); shape.setQueryFilterData( queryFilter ); filter should be [ 1, -1, 4|5|11, 0]// i use -1 for all
contact work but actor2 not good ?
let head = typeHelpers.getContactPairHeaderAt(header, 0)
let bb1 = typeHelpers.getActorAt( head.actors, 0) // is good
let bb2 = typeHelpers.getActorAt( head.actors, 1) // not good ptr ?
There is another function you have to use here:
let bb1 = PhysX.SupportFunctions.prototype.PxContactPairHeader_getActor(head, 0)
let bb2 = PhysX.SupportFunctions.prototype.PxContactPairHeader_getActor(head, 1)
I know the API is not self-explanatory here. The problem here is that getActorAt expects an array of values, while the actors field is an array of pointers.
yes that work ! for the moment all i test work very well ( all body, & joint ) next is ray and articulation test
Hi,
I am trying get both actors from contact pair header. I'm doing:
eventCallback.onContact = (pairHeader, pairs, nbPairs) => {
var head = PhysX.NativeArrayHelpers.prototype.getContactPairHeaderAt(pairHeader);
var a0 = PhysX.NativeArrayHelpers.prototype.getActorAt(head.actors, 0);
var a1 = PhysX.NativeArrayHelpers.prototype.getActorAt(head.actors, 1);
Just like @lo-th did and I can get the first actor but the second actor is invalid.
I tried to use PhysX.SupportFunctions.prototype.PxContactPairHeader_getActor(head, 1) as you mentioned in your last comment but that binding does not seem to exist.
It would be great if you can give me a guide/hint on the issue. I'm very new to using physics engines and wasm codes.
Thanks,
I just tried:
var a0 = head.get_actors(0);
var a1 = head.get_actors(1);
and it seems to return valid Actors. Hope this is the correct way to retrieve them.
I tried to use PhysX.SupportFunctions.prototype.PxContactPairHeader_getActor(head, 1) as you mentioned in your last comment but that binding does not seem to exist.
Ah yes I removed that because there is now the get_actors() function you just found. In generell emscripten now generates get_[member](arrayIndex) functions for array members. I'm not sure if that always was the case and I simply missed these or if that comes from the newer emscripten version I now use.
hi i need get contact point info do you have methode ? i need pair.extractContacts but how use function(userBuffer, bufferSize)
note: i activate the good flag to report point
maybe like that
const contactPoints = new PhysX.Vector_PxContactPairPoint(64)
and in onContact loop
let j = pair.extractContacts( contactPoints.data(), 64 );
if(j>0){
while( j-- ){
p = contactPoints.at(j);
result = {
distance: p.separation,,
pos: p.position,
normal: p.normal,
impulse: p.impulse,
hit: p.separation < 0
}
}
}
yes I think that is how I do it