Is there a way for panda3d to reveal which side of the face a object collides during collision? (Solved)

I wanted to know if Panda3d’s collision handlers have a feature to show what side of the face (3d polygon) a object hit during collision, I know Panda3d knows that information for the pusher handler to work as you can go through the backside of any face even with collision applied to the object.

I have idea which can solve this issue with code, but I lack the mathematical knowhow to actually apply the idea, so I was looking for a practical way for me to solve this issue, anyway thank you to anyone willing to help.


PS: I will share the idea anyway just in case someone can help complete it for me, my idea takes the surface normal and contact point of the face you made contact with and the contact point is then subtracted from your current pos.

It’s to find out what direction you were moving in at collision by normalizing it as a vector, that vector is then compared to the surface normal, if that directional vector is 90 degrees within the surface normal, it would count as you hitting the backside, if out of range, you are hitting the front. the problem is I don’t know how to create a 90 degree range for vectors.

I know if it were degrees, I would use.

if (Point - 90.0) <= Node.getH() <= (Point + 90.0) or (Point - 90.0) <= Node.getP() <= (Point + 90.0) or (Point - 90.0) <= Node.getR() <= (Point + 90.0):

To create a 90 degree range for the point if using degrees but I don’t know how it would be like for a vector, anyway thanks

Panda’s collision polygons are single-sided for a good reason: if they didn’t work that way, then it would be far too easy to get “trapped” on the inside of objects, if for whatever reason a solid slips through a polygon.

Even for very thin walls, it is still recommended to add some thickness between the two faces, otherwise it is too easy to get glitches.

If you must have double-sided faces, you need to duplicate and flip the faces. If you put these duplicated faces in a separate CollisionNode with a different tag or name, you can then distinguish between the front and back face on this basis.

You can take the dot product between two (unit) vectors which will give you the cosine of the angle between them. If v1.dot(v2) == 0 then they are exactly 90° angle, if it <= 0 then the angle is greater than 90°.

1 Like

hmm, well, maybe I worded it wrong, if you say it’s single sided, I guess I am asking is there way to output the collide result if it hit that side or not

maybe it’s better to tell what I am doing, I am trying to determine weather the character is trough a water face (surface) or not.

Is the water-surface horizontal? If so, could you not just check whether the character is above or below the surface-height of the water? (Perhaps with some triggers to determine whether the character is in range of the water.)

If the above suggestion doesn’t work, then you could perhaps compare the object’s previous position relative to the surface with the surface normal, taking the dot product of the two: if the result is negative, then the object is moving from “in front of” the surface.

(That previous position being either stored by your own code, or, with Panda’s “rapidly-moving object” functionality active, returned by NodePath’s “getPrevTransform()” method).

Perhaps you could use a CollisionPlane instead? The problem with using polygons for this is that they are infinitely thin, in some sense. A CollisionPlane will very reliably detect if the character is below a certain level. However, this assumes the water is at the same height everywhere in the level.

Otherwise, I suggest using another shape with volume, such as CollisionBox.

1 Like

thanks rdb, the water I want is not even, think rapids, bouncing rivers, even bubbles of water suspended in mid air, ect, I am still working on your vector suggestion so I will get back to you with a update.

Thaumaturge: could you give a small code example of your second suggestion? once again I don’t how to create ranges for vectors.

Something like the following:

(I’m presuming that your object’s NodePath is kept in a class of your own making, which also stores the previous position of that NodePath.

As mentioned before, you can get the relevant data from Panda, but that means activating a particular mode and is slightly more complicated. For a single, slow-moving object, the approach given here should be simpler, I think.)

# I'm using the surface-position of the collision as an approximation
# of the nearest surface-point to the object's prior position.
# This likely isn't ideal, but might work.
#
# Also, it's possible that I have this subtraction the wrong way
# around--if you get reversed results, try flipping it.
difference = collisonEntry.getSurfacePoint(render) - myObj.lastPos
difference.normalize()

dotProd = entry.getSurfaceNormal(render).dot(difference)

if dotProd > 0:
    # The object approached from "behind"
elif dotProd < 0:
    # The object approached from "in front"

Note that this is untested, and may not work, or may have edge-cases that cause problems.

Another thought, by the way: if you just want to know whether the object is above or below the rapids, could you not use a vertical ray-cast and determine whether the collision’s surface-point is above or below the object in question?

For bubbles of water suspended in mid-air, I’d suggest using a CollisionSphere, and just using into- and out-of- events to determine whether the object is inside the bubble or not.

1 Like

huh, I forgot about the collision ray, I guess you can say I am looking for a all in one solution for any situation as I want the most creative freedom, and I want to simply state a object as a water object rather then adding other elements to it.

your code example looks like what rdb suggested but with some added details, thanks, you gave me a way how use this, I going to test it and update the both of you.

EDIT: I think it worked, I tested it in a box and as the character enters the box, she enters swimming mode, and when I leave the box she exits, so the dot vector solution works, thank you, both you rdb, and Thaumaturge.

EDIT 2: I forgot to mention I had to flip the difference and both of the if statements.

1 Like

One more thought, if I may:

If you want a universal solution, then rdb’s suggestion of using collision-volumes might be a good and fairly-simple solution.

While such volumes might not exactly model your rapids, they should come close–and an exact match is seldom important in these things, if I’m not much mistaken.

That way you can simply check for the relevant collision-events, and, with a bit of careful coding, should be able to reliably determine whether the character is in the water or not.

Are you talking about the collision face flipping (dual faces) he was suggesting? I use polyset to automate my collision solids for the scene, so, is there a automated way to do what you are suggesting?

No. I’m suggesting that, instead of using polygonal collision, you build up your collision-representation of the water using CollisionTubes, CollisionBoxes, CollisionSpheres, and the like.

The result, when viewed, might not look quite right. But then, your users likely won’t be viewing said result. As long as it broadly fits the volume being represented, and thus likely feels pretty much right, it should work.

And since these objects have volume, you can simply use in- and out-of events to detect the user moving into- and out-of- them–even if the objects are big enough that the user can fit within them entirely, and thus not touch their sides, I believe.

oh, okay, I heard of some games using objects like that for collision… uh, would it be calling me lazy if I said I would prefer clicking a single button to get instant collision, Eh heh heh heh (nervous laugh)

I mean, I think that many of us would like to have a “make game” button. :stuck_out_tongue:

And there are ways to make some of these things easier–that is, after all, what an engine does for us.

But yeah, it seems that you have fairly specific requirements for your collision, and I don’t see an easier way to implement them right now. ^^;

hah hah, yeah, that is why I am working on such code, so I can have a idea then implement it instantly and the code works out all issues for me, but thats cool, what you gave me works, thanks for the help once again.

1 Like