Skip to content
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

Simulation Event Callback #7

Open
lucas-jones opened this issue Jun 15, 2021 · 18 comments
Open

Simulation Event Callback #7

lucas-jones opened this issue Jun 15, 2021 · 18 comments

Comments

@lucas-jones
Copy link
Contributor

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);
@lucas-jones
Copy link
Contributor Author

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

@fabmax
Copy link
Owner

fabmax commented Jun 17, 2021

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.

@lucas-jones
Copy link
Contributor Author

Thank you for explaining :)

@lucas-jones
Copy link
Contributor Author

@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

@lucas-jones lucas-jones reopened this Jun 25, 2021
@fabmax
Copy link
Owner

fabmax commented Jun 25, 2021

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.

@trinhhuyit
Copy link

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!
image

@lo-th
Copy link

lo-th commented Jan 25, 2022

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

@lo-th
Copy link

lo-th commented Jan 25, 2022

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

@lucas-jones
Copy link
Contributor Author

@lo-th I've posted a little snippet of code that will 'fix' Enums in JS

#5 (comment)

This should allow you to do

let triggerPair = typeHelpers.getTriggerPairAt(pairs, 0);
let isTrigger = triggerPair.status == PhysX.PxPairFlagEnum.NOTIFY_TOUCH_FOUND;

@lo-th
Copy link

lo-th commented Jan 25, 2022

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 ?

@fabmax
Copy link
Owner

fabmax commented Jan 25, 2022

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.

@lo-th
Copy link

lo-th commented Jan 26, 2022

yes that work !
for the moment all i test work very well ( all body, & joint )
next is ray and articulation test

@uoissvd
Copy link

uoissvd commented Mar 12, 2023

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,

@uoissvd
Copy link

uoissvd commented Mar 13, 2023

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.

@fabmax
Copy link
Owner

fabmax commented Mar 13, 2023

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.

@lo-th
Copy link

lo-th commented Mar 20, 2023

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

@lo-th
Copy link

lo-th commented Mar 20, 2023

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
	}
    }
}

@fabmax
Copy link
Owner

fabmax commented Mar 21, 2023

yes I think that is how I do it

@ghost ghost mentioned this issue Mar 9, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants