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

CharacterContactListener: add OnContactPersisted and OnContactRemoved (Reopen) #1427

Open
bryanedds opened this issue Dec 30, 2024 · 7 comments

Comments

@bryanedds
Copy link

bryanedds commented Dec 30, 2024

This issue was closed by the original requesting user here -

#1027

...but I think it might warrant additional consideration. I'd like to explore the addition of this feature. If the user can avoid this sort of manual bookkeeping (and the bugs that might come with it), it might be better to add these as a built-in feature for jolt character contact listeners.

(Apologies for the new issue - I tried to reopen the closed one but github provided no UI for it.)

@bryanedds
Copy link
Author

bryanedds commented Dec 30, 2024

Until we have this feature built-in, could someone give me a quick idea of how to do the character contact tracking myself? I'm using the JoltPhysicsSharp wrapper, btw.

EDIT: turns out the the JoltPhysicsSharp wrapper doesn't expose CharacterVirtual.GetActiveContacts, so I don't have a way to implement this feature myself in this case.

@jrouwe
Copy link
Owner

jrouwe commented Dec 30, 2024

An implementation on your side would be as simple as:

MyListener::OnContactAdded(...)
{
  bool found = false;
  for (Contact c : previous contacts)
    if (mBodyB and mSubShapeIDB are the same as the contact being passed in)
    {
      found = true;
      mark c as persisted
      break
    }

  if (found)
    it's a persistent contact
  else
    it's a new contact
}

and in the update:

my_listener->SetPreviousContacts(character->GetActiveContacts())
character->ExtendedUpdate(...)
for (Contact c : my_listener->previous contacts)
  if (persisted flag not set on c)
    my_listener->OnContactRemoved(...)

@bryanedds
Copy link
Author

Alright, I'm giving the implementation a shot by way of the JoltPhysicsSharp .NET wrapper. I'll let you know how it proceeds!

@bryanedds
Copy link
Author

bryanedds commented Jan 1, 2025

I think I've added the needed additional bookkeeping to surface these events myself -

https://github.com/bryanedds/Nu/blob/e3837db5f160daf4b175a8863684baee01ad17e1/Nu/Nu/Physics/PhysicsEngineJolt.fs?plain=1#L390-L418

...tho I'm still not high-confidence on the implementation yet.

However, a new critical question has arisen -

How do I create add contact and remove contact events between two characters?

Currently, I can recover the information needed to expose add and remove contact events between characters and non-character bodies like so -

https://github.com/bryanedds/Nu/blob/e3837db5f160daf4b175a8863684baee01ad17e1/Nu/Nu/Physics/PhysicsEngineJolt.fs?plain=1#L701C1-L744C58

...but I don't see how I would have enough information from the jolt API to recover a character / Nu body ID from a Jolt BodyID. The only body identification information exposed by Jolt API is InternalBody, AFAICT, which I don't think is relevant.

Please advise as I am worried this might be a blocking issue for us. Cheers!

@jrouwe
Copy link
Owner

jrouwe commented Jan 1, 2025

Sorry, I've never worked with F# so the code is quite alien to me and I can't tell you if the code is correct.

To track character contacts you basically use the same algorithm, but instead of checking that inBodyID2 == mBodyB and inSubShapeID2 == mSubShapeIDB in OnContactAdded, you check inOtherCharacter == mCharacterB and inSubShapeID2 == mSubShapeIDB in OnCharacterContactAdded.

@bryanedds
Copy link
Author

I guess I see part of my confusion - Jolt Physics Sharp doesn't expose OnCharacterContactAdded, so I was supposing I would need to somehow recover the other character information using only OnContactAdded. I'll see if I can get the author to surface that behavior as well and proceed with that approach.

@bryanedds
Copy link
Author

bryanedds commented Jan 1, 2025

F# so the code is quite alien to me and I can't tell you if the code is correct.

I think this does return us to the crux of the discussion. I think it might not be F#'s fault that the code is so opaque, even for someone unfamiliar with F#. I've been doing F# intensely for over a decade, and I still find this particular code quite messy and unsatisfying. I think the issue may instead be all the complexity that's being forced on the end-user, necessitating them to provide all this extra algorithmic behavior, bookkeeping, and implicit state coordination. The emergent behavior required here has to, by nature, have its implementation shotgun-sprayed around multiple parts of the file. This behavior is going to be rather hard to understand for anyone coming into our Jolt integration code file that doesn't have an existing understanding of Jolt's particulars. The added code bulk and state makes everything else around this additional code that much harder to understand. Considering that all this has to be done through a wrapper API that doesn't yet even expose what's needed to get the basic job done, we might say the implementation and its maintenance is not as simple as was initially supposed.

If there does turn out to be a good way for Jolt to directly provide the functionality I'm emulating here, I think it should be considered. If there truly isn't a good way... then I wonder if a deeper design issue in Jolt is at hand? Barring that possibility as well, we would just accept it as is, and perhaps provide a bit more explicit documentation to ease the user into the Jolt integration process.

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

2 participants