Unable to get 3D text to start out in front of camera, no matter what position / hpr I set

Here is an MWE:

from direct.showbase.ShowBase import ShowBase
from panda3d.core import (GeomVertexFormat, GeomVertexData, GeomVertexWriter, 
                          Geom, GeomNode, GeomLines, NodePath, TextNode)
from direct.task import Task
from math import pi, sin, cos

class Object3D(NodePath):
    Out, In = range(2)
    
    def __init__(self, geom_node):
        super().__init__(geom_node)
        
        self._arrows = ([], [])
        
    def add_arrow(self, arrow, inout=0):
        self._arrows[inout].append(arrow)

        from object3d import Object3D
        from panda3d.core import TextNode
        
    def setPos(self, x, y, z):
        for inout in range(2):
            for arrow in self._arrows[inout]:
                arrow.set_endpoint_pos(inout, x, y, z)
               
        super().setPos(x, y, z)        
        

class Arrow3D(Object3D):        
    def __init__(self, text:str, dom, cod):
        format = GeomVertexFormat.getV3()
        data = GeomVertexData("Data", format, Geom.UHStatic)
        vertices = GeomVertexWriter(data, "vertex")

        vertices.addData3f(*dom.getPos())
        print (*dom.getPos())
        vertices.addData3f(*cod.getPos())

        arrow = GeomLines(Geom.UHStatic)
        arrow.addVertices(0, 1)
        
        geom = Geom(data)
        geom.addPrimitive(arrow)

        arrow = GeomNode(text)
        arrow.addGeom(geom)
        
        super().__init__(arrow)
        
        self.setBillboardAxis()
        self.setColor(0.0, 1.0, 0.0)
        self.setScale(5.0)
        self.setPos(-50, 200, 0)   
        
        self._dom = dom
        self._cod = cod
        

class Text3D(Object3D):        
    def __init__(self, text:str):
        text3d = TextNode(text)
        text3d.setText(text)
        
        super().__init__(text3d)
        
        self.setBillboardAxis()
        self.setColor(0.0, 1.0, 0.0)     

from text3d import Text3D
from direct.showbase.ShowBase import ShowBase
from arrow3d import Arrow3D
        
        
class App(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)
        
        p = self.render.attachNewNode("Dummy")
                
        A = self.text('Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', parent=p)
        B = self.text('B', parent=p)

        a = self.arrow('a', A, B, parent=p)
        self.render.setScale(1.0)
        
        #B.setPos(50, 0, 0)
        self.camera.setPos(10000.0, 0.0, 10000)
        p.setScale(1.0)   
        # Add the spinCameraTask procedure to the task manager.
        self.camera.setHpr(180, 0, 0)
        self.camera.setPos(100, -10000000, 0)
        
    def text(self, text:str, parent=None):
        text = Text3D(text)
        self.set_parent(text, parent)
        return text
    
    def arrow(self, text:str, dom, cod, parent=None):
        arrow = Arrow3D(text, dom, cod)
        self.set_parent(arrow, parent)
        return arrow
    
    def set_parent(self, node_path, parent=None):
        if parent is None:
            parent = self.render
        
        node_path.reparentTo(parent)             


if __name__ == '__main__':
    app = App()
    app.run()        

Right-press + drag to zoom out and the text zooms into view, but no matter what camera position / hpr initially set, the text won’t just start out in front of the camera.

I’m missing something!

You didn’t say what you were trying to achieve. So it will work.

A.setPos(0, 5, 0)
B.setPos(0, 5, 0)

For the camera position to work, you either need to write your own camera controller. By disabling the base camera.

self.disableMouse()

Or, set the position for the trackball.

self.trackball.node().set_pos(0, 5, 0)
1 Like