I got it to work perfectly:
However, I’ve needed to make a change to the Panda3D source to allow this, since the bounds calculation currently assumes that only an affine transformation is used: (EDIT: the patch is no longer needed as of Panda3D 1.10.4+)
The way it works is that a node is created under the camera to hold the camera’s projection matrix. Then we simply ask Panda to get the bounds relative to that node. Here is the code, which will not work in Panda3D 1.10.3 without the above patch applied:
from panda3d.core import *
from direct.showbase.ShowBase import ShowBase
base = ShowBase()
base.trackball.node().set_pos(0, 100, 0)
model = loader.load_model("panda.egg")
model.reparent_to(base.render)
# Add a dummy node to the camera to hold the projection matrix
proj_dummy = base.cam.attach_new_node("proj-dummy")
# Set up a node in 2-D space to hold the drawn lines
line_node = GeomNode("lines")
line_path = base.render2d.attach_new_node(line_node)
def draw_box(task):
# Copy the projection matrix to the dummy
proj_mat = base.cam.node().get_lens().get_projection_mat_inv()
proj_dummy.set_transform(TransformState.make_mat(proj_mat))
# Calculate the box in projected (2D) space and draw lines in the 2D graph
min, max = model.get_tight_bounds(proj_dummy)
segs = LineSegs()
segs.move_to(min[0], 0, min[1])
segs.draw_to(min[0], 0, max[1])
segs.draw_to(max[0], 0, max[1])
segs.draw_to(max[0], 0, min[1])
segs.draw_to(min[0], 0, min[1])
line_node.remove_all_geoms()
segs.create(line_node)
return task.cont
base.taskMgr.add(draw_box, "draw-box")
base.run()
At this point, you have several options:
- Compile Panda from source with the patch applied (or I can get you a development build)
- Wait until I make a new 1.10.4 release with the patch included
- Make your own code to iterate over the vertices and calculate the bounds yourself. If you go this route, I’m happy to let you know how you can let Panda do the matrix math for you.