Can't draw lines

I managed to get the camera to work the way I’d like by replacing camera target in some lines. Now the camera is free to navigate the model, I only need to apply constraint so it remains on positive quadrant of X,Y,Z space.

from direct.showbase.DirectObject import DirectObject
from panda3d.core import Point3, Point2, Vec3, Plane


class CameraController:

    def __init__(self, showbase):

        self.showbase = showbase
        self.task_mgr = showbase.task_mgr
        self.mouse_watcher = showbase.mouseWatcherNode
        self.world = showbase.render
        self.cam = showbase.camera
        self.cam_lens = showbase.camLens
        self.cam_target = showbase.render.attach_new_node("camera_target")
        self.cam.reparent_to(self.cam_target)
        self.cam.set_y(-10.)
        self.mouse_prev = Point2()
        win_props = showbase.win.get_properties()
        w, h = win_props.get_x_size(), win_props.get_y_size()
        self.orbit_speed = (w * .15, h * .15)
        self.pan_start_pos = Point3()
        self.zoom_step_factor = 10  # additional zoom step multiplier
        self.listener = listener = DirectObject()
        listener.accept_once("mouse1", self.start_orbiting)
        listener.accept_once("mouse3", self.start_panning)
        listener.accept("wheel_up", self.zoom_step_in)
        listener.accept("wheel_down", self.zoom_step_out)
        listener.accept("control-wheel_up", self.zoom_step_in_const)
        listener.accept("control-wheel_down", self.zoom_step_out_const)
        listener.accept("-", self.decr_zoom_step_factor)
        listener.accept("--repeat", self.decr_zoom_step_factor)
        listener.accept("+", self.incr_zoom_step_factor)
        listener.accept("+-repeat", self.incr_zoom_step_factor)

    def stop_navigating(self):

        self.task_mgr.remove("transform_cam")
        self.listener.accept_once("mouse1", self.start_orbiting)
        self.listener.accept_once("mouse3", self.start_panning)

    def start_orbiting(self):

        win_props = self.showbase.win.get_properties()
        w, h = win_props.get_x_size(), win_props.get_y_size()
        self.orbit_speed = (w * .15, h * .15)
        self.mouse_prev = Point2(self.mouse_watcher.get_mouse())
        self.task_mgr.add(self.orbit, "transform_cam")
        self.listener.ignore("mouse3")
        self.listener.accept_once("mouse1-up", self.stop_navigating)

    def orbit(self, task):
        """
        Orbit the camera about its target point by offsetting the orientation
        of the target node with the mouse motion.

        """

        if self.mouse_watcher.has_mouse():
            mouse_pos = self.mouse_watcher.get_mouse()
            speed_x, speed_y = self.orbit_speed
            d_h, d_p = (mouse_pos - self.mouse_prev)
            d_h *= speed_x
            d_p *= speed_y
            target = self.cam
            target.set_hpr(target.get_h() - d_h, target.get_p() + d_p, 0.)
            self.mouse_prev = Point2(mouse_pos)

        return task.cont

    def zoom_step_in(self):
        """Translate the camera along its positive local Y-axis to zoom in"""

        target_dist = self.cam.get_y()
        self.cam.set_y(self.cam, -target_dist * .1)

    def zoom_step_out(self):
        """Translate the camera along its negative local Y-axis to zoom out"""

        target_dist = self.cam.get_y()
        self.cam.set_y(self.cam, target_dist * .1)

    def zoom_step_in_const(self):
        """Zoom in using a constant step value"""

        current_dist = self.cam.get_y()
        new_dist = current_dist + .1 * self.zoom_step_factor

        # Prevent the camera to move past its target node
        #if new_dist > -.01:
        #    new_dist = -.01

        self.print_status('zoom step in')

        self.cam.set_y(new_dist)


    def zoom_step_out_const(self):
        """Zoom out using a constant step value"""

        current_dist = self.cam.get_y()
        new_dist = current_dist - .5 * self.zoom_step_factor

        self.print_status('zoom step out')
        self.cam.set_y(new_dist)

    def decr_zoom_step_factor(self):
        """Decrease the value with which to multiply the zoom steps"""

        self.zoom_step_factor -= 1 # Or some value that you prefer

        # Prevent the multiplier from becoming too small
        if self.zoom_step_factor < .1:
            self.zoom_step_factor = .1

        print("self.zoom_step_factor:", self.zoom_step_factor)

    def incr_zoom_step_factor(self):
        """Increase the value with which to multiply the zoom steps"""

        self.zoom_step_factor += .1 # Or some value that you prefer
        print("self.zoom_step_factor:", self.zoom_step_factor)

    def __get_pan_pos(self, pos):

        if not self.mouse_watcher.has_mouse():
            return False

        target = self.cam_target
        target_pos = target.get_pos()
        normal = self.world.get_relative_vector(target, Vec3(0., 1., 0.))
        plane = Plane(normal, target_pos)
        m_pos = self.mouse_watcher.get_mouse()
        near_point = Point3()
        far_point = Point3()
        self.cam_lens.extrude(m_pos, near_point, far_point)
        near_point = self.world.get_relative_point(self.cam, near_point)
        far_point = self.world.get_relative_point(self.cam, far_point)
        plane.intersects_line(pos, near_point, far_point)

        return True

    def start_panning(self):

        if not self.mouse_watcher.has_mouse():
            return

        self.listener.ignore("mouse1")
        self.listener.accept_once("mouse3-up", self.stop_navigating)
        self.__get_pan_pos(self.pan_start_pos)
        self.task_mgr.add(self.pan, "transform_cam")

    def pan(self, task):

        pan_pos = Point3()

        if not self.__get_pan_pos(pan_pos):
            return task.cont

        self.cam.set_pos(self.cam.get_pos() + (self.pan_start_pos - pan_pos))
        self.print_status('pan')

        return task.cont

    def print_status(self,action=''):
        print(action,' - Camera :',self.cam.get_pos()," Target :",self.cam_target.getPos())

Another possibility is to implement dollying (moving the camera target backwards and forwards); perhaps this is what you’re really looking for, as its speed is usually constant anyway. In practice, the only real difference with zooming is that orbiting is affected, since the camera orbits about its target node.

Even if it’s not what you wanted, I’ve added it to the code in my previous post for the sake of completeness.
Press the up arrow to dolly forwards or the down arrow to dolly backwards.

2 Likes

I cannot repay your kindness. You are a wonderful human being towards we newbies.

1 Like

It’s my pleasure :slight_smile: ! And thank you for the praise, I feel honored–and motivated to keep helping when I can!

2 Likes