Getting a CollisionBox's constituent global points

Hi,
I’m attempting to get the points that make up a collisionBox in global space, from a collision entry like this:

for entri in self.blockQueue.getEntries():
    collSolid=entri.getInto()
    minimumPoint=collSolid.getMin()
    maximumPoint=collSolid.getMax()
    parentNp=entri.getIntoNodePath().getParent()
    bounds=parentNp.getTightBounds(render)
    print("collisionBox points: ",minimumPoint,maximumPoint)
    print("cube points: ",bounds[0],bounds[1])

Print results:

collisionBox points: LPoint3f(28, 0, 28) LPoint3f(36, 8, 36)
cube points: LPoint3f(67.4711, -51.2308, 59.335), LPoint3f(93.7808, -24.9212, 83.2956)

The collisionBox is created procedurally and is attached to a cube that has been created procedurally as well. What I need (for certain reasons),is that the points which make up the collisionBox to be returned as (or transformed into) global-space coordinates, i.e. I’d need the collisionBox points to match the cube points above, since the collisionBox properly encapsulates the cube it is ultimately parented to.

How would one go about doing that?

(Shouldn’t this be possible, since if a CollisionVisualizer is set on, it shows onscreen, at the least, the nearby collisionSolid(s) it is considering for intersection tests? So shouldn’t one be able to get the points in global-space that make up the collisionSolid(s) being highlighted by a CollisionVisualizer as well?)

Thanks in advance.

I don’t know how it’s done in the Collision Visualiser, but you should be able to do this via the “getRelativePoint” method of NodePath. This method converts a point from a given reference frame to that of the NodePath on which it’s called.

So, in your case, I’m guessing that the points are in the reference frame of the collision solid, as stored in “collSolid”. Presuming that I’m correct in that, and that I have the following correct, the resultant code should look something like this:

globalMinimum = render.getRelativePoint(collSolid, minimumPoint)
globalMaximum = render.getRelativePoint(collSolid, maximumPoint)
1 Like

Well, “collSolid” is the collisionBox returned by the call to “getInto()”:

collSolid=entri.getInto()#<-returns a collisionBox in this case.

“getRelativePoint” takes another nodepath as a reference, not a collisionSolid. However, upon calling “getRelativePoint” and passing in the parent of the collisionBox, a nodepath, it does return a transformed point that is approximately equal to the bounding-volume-box of the cube in question. Here is what is printed out when using your suggestion:

Print Results:

collisionBox points: LPoint3f(-36.6283, 86.1158, 33.1808) LPoint3f(-10.2732, 115.386, 61.0317)
cube points: LPoint3f(-38.0859, 86.1158, 33.1808), LPoint3f(-8.81557, 115.386, 61.0317)

So, thank you very much, it does look like it works :+1:! I’m however curious whether there’s another way to achieve something like this. I’m specifically curious as to whether one can get the exact points in global space that are shown onscreen by a collisionVisualizer for example.

1 Like

Then you could call getIntoNodePath instead, which returns a NodePath, as it says on the tin :wink: .

1 Like

I did?:

I got the parent of the collisionBox via entry.getIntoNodePath()…

Ah, I hadn’t noticed that you do indeed call that method in your code. But what I meant was that you can use its returned NodePath directly, instead of getting its parent and using that.

So to avoid any more misunderstandings, the idea was that your code could become something like this:

for entri in self.blockQueue.getEntries():
    collSolidNodePath=entri.getIntoNodePath()
    collSolid=collSolidNodePath.node().solids[0]
    minimumPoint=collSolid.getMin()
    maximumPoint=collSolid.getMax()
    globalMinimum = render.getRelativePoint(collSolidNodePath, minimumPoint)
    globalMaximum = render.getRelativePoint(collSolidNodePath, maximumPoint)
    print("collisionBox points: ",globalMinimum,globalMaximum)

Even in the original post, I already did get the parent, within the sample code I provided:

for entri in self.blockQueue.getEntries():
    collSolid=entri.getInto()
    minimumPoint=collSolid.getMin()
    maximumPoint=collSolid.getMax()
    parentNp=entri.getIntoNodePath().getParent()#<--getting the parentNp
    bounds=parentNp.getTightBounds(render)#<--getting the tightBounds from the gotten nodepath
    print("collisionBox points: ",minimumPoint,maximumPoint)
    print("cube points: ",bounds[0],bounds[1])

It’s how I even got the tight bounding box, to compare with the points gotten from the collisionBox, to post this question in the first place :crazy_face:.

Yes, I already acknowledged that I hadn’t read your original post thoroughly:

And I do understand that. But since you had already confirmed that Thaumaturge’s code worked for you, it seemed like you had no need for comparing anymore. That’s ultimately why I offered an alternative approach that doesn’t require that parent at all, because you can pass the NodePath that contains the collisionBox itself into getRelativePoint instead of its parent.

You’re welcome anyway.

Yeah, but you still might have misunderstood me, I always welcome and thoroughly appreciate your sagacity when it comes to Panda3D code, but I already did exactly what you wrote, even in the original post.

Thaumaturge pointing me to that method did work, I acknowledged that, however, I was simply curious as to whether there was another way of going about it, specifically, accessing the points that a collisionVisualizer would show onscreen. In any case I appreciate both your contributions.

No worries, what matters most is that you have a working solution to your issue now :slight_smile: !

As far as I can tell (and with my nonexistent C++ skills that might not be very far :grin:) when looking at the source code, is that the minimum and maximum values are transformed with the net transformation matrix of the CollisionNode to build the visualization model for the CollisionBox solid. Doing this in Python should also work, but is a much more roundabout (and therefore slower) way to get the same result as just calling getRelativePoint (which makes use of matrices under the hood as well), so I don’t really see a benefit of going this route.
At any rate, I don’t immediately see any convenience functions that the CollisionVisualizer is making use of, at least.

On a side note, I’d like to point out that your comparison with the parent’s bounds might fail, specifically when the parent is rotated relative to render. When calling parentNp.getTightBounds(render), this will not return the global coordinates of parentNp's local tight bounds; you will instead get the minimum and maximum points of the circumscribed, axis-aligned bounding box, which will be very different from parentNp's box model.

1 Like