Name Plates [SOLVED]

Most of us have seen them: A 2d looking object that hovers over or near a 3d object in 3d space. It might be character names, health bars, or something else. In most cases, it always stays the same size on the screen, regardless of how far away the object is from the camera. I call them name plates.

I want them.

I figure I have two options to generate this effect.

Option one, which is conceptually simple, is just to create the name plate as a billboard and scale it to the size I want, with it 1 unit away from the camera. Then I just scale it relative to itself based on the distance between it and the camera using something like the following:

def distToZero(self, point3):
  return( math.sqrt( math.pow(point3.getX(), 2) +
                     math.pow(point3.getY(), 2) +
                     math.pow(point3.getZ(), 2) ) )

def namePlateScaleTask(self, task):
  self.namePlate.setScale( self.namePlate, self.distToZero( self.namePlate.getPos( base.camera ) )
  return task.cont

Alternatively, I could make the name plate a child of render2d or aspect2d and find the correct location for it by projecting from the camera lens, like the following code I pulled from [url]render coord to aspect2d]:

def Update( renderNp, aspectNp ):
   
    # Convert the point to the 3-d space of the camera
    p3 = base.camera.getRelativePoint( render, renderNp.getPos() )
   
    # Convert it through the lens to render2d coordinates
    rp2 = Point2()
    if base.camLens.project( p3, rp2 ):
        ap2 = aspect2d.getRelativePoint( render2d, Point3(rp2[0], 0, rp2[1])  )
        aspectNp.setPos( ap2.x, 0, ap2.z )
   
    return Task.cont

My question is, which of these two methods puts the least amount of strain on the system, or are they about the same? I’m guessing the first option is less intensive, but I’d like confirmation.

why not use getDistance()? instead of the manual distance-calculation?

While I don’t think I can help much with which is more efficient, the first of the two methods could have the name plate end up behind another object, and not visible (unless you do something funky with the render order, which I believe is possible but I haven’t really touched on yet). With the second method, the name plate ought to be visible at all times without any extra trickery.

I don’t know how useful they will be, but there are a couple well-replied posts in the forum about health bars that were fun to read.

[url]Using DirectWaitBar as health bar.]
[url]Health Bars (using DirectGUI ?)]
[url]DirectWaitBar in render]
http://www.google.com/search?q=site:panda3d.org%2Fforums+health+bar

I honestly never noticed that method of NodePath before. I’m a little embarrassed about that.

This problem can be fixed pretty easily with a couple of calls I forgot to add, to make the name plate render last and ignore depth sorting.

self.namePlate.setBin("fixed", 0)
self.namePlate.setDepthWrite(False)
self.namePlate.setDepthTest(False)

By changing the value in the setBin call from 0 to something else I can control the order the name plates themselves render in as well.

These posts do have some interesting ideas as to how to implement health bars specifically. Thanks for that. No answer to my specific question in them, though.

Still, if anyone knows which of the two methods I originally posted is the most efficient, please let me know.

I think it amounts to about the same thing in terms of system impact.

David

I’ll stick with option one, then. It’s a bit easier to implement, in my opinion.