3d to 2d

I would like to create 2d highlight effect when the mouse does a “rollover” on 3d geometry. Any suggestions on how to translate the position of a 3d object to create 2d coordinates in the panda window? The cameras field of view will be changing, so this 2d highlight placement will need to be flexible towards that.


Try this:

def compute2dPosition(nodePath, point = Point3(0, 0, 0)):
    """ Computes a 3-d point, relative to the indicated node, into a
    2-d point as seen by the camera.  The range of the returned value
    is based on the len's current film size and film offset, which is
    (-1 .. 1) by default. """
    # Convert the point into the camera's coordinate space
    p3d = base.cam.getRelativePoint(nodePath, point)

    # Ask the lens to project the 3-d point to 2-d.
    p2d = Point2()
    if base.camLens.project(p3d, p2d):
        # Got it!
        return p2d

    # If project() returns false, it means the point was behind the
    # lens.
    return None


Thanks David, it works perfectly

Hmm… I’m trying to accomplish the opposite:

I have a 2D crosshair on the window and I need to find out the 3D
coordinates of the first collision node the trajectory passes through so I know
where to either make another player take damage or put a bullet mark
where it hit.

You need to create a CollisionRay that originates from your camera’s near plane at the (mx, my) point of your mouse, and continues through the camera’s far plane at the corresponding point. There is code in DirectSelection.py that does all this for you.

from direct.directtools import DirectSelection

selection = DirectSelection.SelectionRay()
selection.pick(render, (mx, my))

if selection.getNumEntries() > 0:
  entry = selection.getEntry(0)
  object = entry.getIntoNodePath()
  point3d = entry.getSurfacePoint(object)


Hmm… I have a bullet mark that I want to put where it hit, but I don’t want it to be facing the wrong way, is there a way to figure out which way a collision node is facing at a certain point?

You can also get the surface normal at the point of intersection:

normal = entry.getSurfaceNormal(object)

The direction of the normal will tell you which way the object was facing. You do have to be careful with your coordinate systems, though; both getSurfacePoint() and getSurfaceNormal() will return their results in whatever coordinate system (node) you specify, so you have to be sure you ask for it in the coordinate system you are working in.