Collision's SurfacePoint and InteriorPoint strange behavior

Hi, I use a collision ray for line-of-sight, and I’d really like to use the SurfacePoint from the CollsionEntry. However, I seem to have run into some weird behavior: the SurfacePoint seems to get mixed up with the InteriorPoint (which in turn behaves more like an ExitPoint). See little screenshot below… my ray runs from bottom left to upper right in this shot, and it shows the white dot (InteriorPoint, according to the source) as the first entry and the SurfacePoint behaving as expected later on. It’s not just this particular spot or angle, the ray moves around and keeps mixing up the surface/interior/exit points.

What could be wrong?

Which solid types are you using? And which version of Panda?

I’m using Panda 1.10.6.

Line-of-sight ray is setup as:

        # collisions
        self.pq = CollisionHandlerQueue()
        self.pickerRay = CollisionSegment()
        self.pickerRay.setPointA(self.parent.np.getPos() + self.parent.firePos)
        self.pickerRay.setPointB(Vec3(0, 0, 0))
        # picker nodepath
        self.pickerNP = base.world.np.attachNewNode(CollisionNode('losRay'))
        self.pickerNP.node().addSolid(self.pickerRay)
        self.pickerNP.node().setIntoCollideMask(BitMask32.allOff())
        self.pickerNP.node().setFromCollideMask(COLL_BITMASK_LOS)
        self.pickerNP.show()
        # add solid to picker
        base.collTraverser.addCollider(self.pickerNP, self.pq)
        base.collTraverser.showCollisions(render)

Into solids are setup as:

                # collisions
                box = CollisionBox(Vec3(0, 0, 0), 0.5, 0.5, 0.5)
                cnode = CollisionNode('Mountain')
                cnode.setIntoCollideMask(COLL_BITMASK_LOS)
                cnode.setFromCollideMask(COLL_BITMASK_NONE)
                self.cnodePath = cube.attachNewNode(cnode)
                self.cnodePath.node().addSolid(box)

Collision traverser is:

self.collTraverser = CollisionTraverser()

Which traverses in a 1/60 second doMethodLater task.

(the COLL_BITMASK_* constants are just shortcuts to Bitmask32 bits)

To be complete: scaling of boxes is done on the main nodepath (self.np), which is a procedurally generated EggPrimitive. Some boxes may rotate during runtime, but that doesn’t seem to effect this weird behavior (i.e. InteriorPoint behaving as either exit or entry point and SurfacePoint mixed up). Again: it doesn’t do this on EVERY cube…

Is the red dot shown in the above image the “surface point” from the same collision-entry as produces the “interior point” shown in the image?

In addition, does this behaviour change if you remove any scaling applied to the boxes (even if that scaling is inherited from a parent-node)?

Finally, it occurs to me that I’m not sure that there is a particularly logical definition of an “interior point” for a ray-collision. After all, it has no end, and thus continues on past any finite collision-object that it may encounter. So perhaps in the case of a ray-collision the reported “interior point” is indeed the “surface point”?

I tested not scaling the boxes, but that doesn’t change anything. See screenshot below, ray again traverses from bottom left to upper right. The first box it hits has its SurfacePoint on the exit, not on the entry. To make sure, I also removed the model the ray originates from, but again… no difference.

About the InteriorPoint: the source code comments:

        // Draw a small red point at the surface point, and a smaller white
        // point at the interior point.

API documentation says:

Returns the 3-D point, within the interior of the “into” object, that represents the depth to which the “from” object has penetrated.

From this, I guess InteriorPoint could be understood to be some kind of ExitPoint. I really do not need this point at the moment, but it seems to be the white dot that signifies exit, and not entry of the collision shape.

I tried something else, which puzzles me even more: switching the start and end point for my ‘ray’ in this code:

        self.pickerRay = CollisionSegment()
        self.pickerRay.setPointB(self.parent.np.getPos() + self.parent.firePos)
        self.pickerRay.setPointA(Vec3(0, 0, 0))

Doesn’t change a thing either. Which is weird, because I’d expect the behavior the be reversed.

This makes me think I’m doing something terribly wrong, but what?

Hm, fair enough.

Ah, good point–that would be a sensible definition of the “interior point” here indeed. My mistake!

Very curious!

Hmm… Would you try something for me, please? Would you try using a CollisionRay instead of a CollisionSegment? A quick experiment on my side seemed to indicate that I was seeing what one might expect when using a CollisionRay, and I’m wondering whether the issue isn’t perhaps in the code of CollisionSegment, then…

Allright, I modified my ray to be a ‘normal’ CollisionRay, and now it behaves as expected. The problem seems to be in the CollisionSegment I used. Using a CollisionRay I see a red SurfacePoint where it was to be expected, and no white dot anywhere.

1 Like

Hi Thaumaturge, hahaha… I just posted this, I tried the CollisionRay and that one works as it should. Problem seems to be with the CollisionSegment (again, switching point A and B was also weird).

I will use the CollisionRay. It works just as well, I guess, I just didn’t want to test for more collisions than necessary (seeing my ray is a line-of-sight that has a certain range).

1 Like

Hah, great minds think alike, it seems! :wink:

Well, would you be willing to file an entry for this over at the issue-tracker, please? This seems like something that might call for seeing to!

Link:

I filed an issue, thanks you for your help!

Thank you, and the other great people who support and work on Panda3D. I love what you guys did and are doing.

1 Like

For my part it’s my pleasure! :slight_smile:

To be fair, I’m not one of Panda devs myself–just a community member and game-dev who uses the engine. :slight_smile:

1 Like