0

I am quite happy with the progress that I have made thus far on my 3D Camera, but I feel it is missing scroll wheel zoom-in zoom-out functionality.

I have been attempting to program a cam_zoom() function for some time now and I am confused with how I can implement it.


Before I can implement the Zoom functionality, I need to consider my pre-existing code.

There are several ways the camera can currently be rotated and translated with the current setup.

The camera is translated when the player rotates. which can either be performed with WSAD or by holding/dragging the right mouse button.

player_rotate()

func player_rotate(delta, dir):
        #rot can be adjusted to make rotation faster
        var rot = deg2rad(dir*90)*delta 
        #Forward is changed every time turning happens. 
        forward=forward.rotated(Vector3(0,1,0),rot)
        player.rotate(Vector3(0,1,0),rot)

cam_rotate()

func cam_rotate(delta, dir):
        #rot can be adjusted to make rotation faster
        var rot = deg2rad(dir*90)*delta 
        #Forward is changed every time turning happens. 
        cam.rotate(Vector3(0,1,0),rot)

If A is pressed

# IF A (no mouse)
if Input.is_action_pressed("move_left") and !Input.is_action_pressed("right_mouse") and !Input.is_action_pressed("left_mouse"):
    #cam_reset(delta)
    camlock.UNLOCKED
    player_rotate(delta, 1)
    cam_rotate(delta, 1)

cam_reset()

func cam_reset(delta):
    #return behind player if the camera is LOCKED
    
        target_location = player.translation
        target_rotation = player.rotation 
        rotation_lerp = 0.0
        rotation_speed = 8.0
        
        if rotation_lerp < 1:
            rotation_lerp += delta * rotation_speed
        elif rotation_lerp > 1:
            rotation_lerp = 1
        cam.transform.basis = cam.transform.basis.slerp(target_rotation, rotation_lerp).orthonormalized()

the camera can be rotated freely around the player (with clamps) when the left mouse button is held down.

#if only left mouse is pressed
    if Input.is_action_pressed("left_mouse") and !Input.is_action_pressed("right_mouse"):
        print("left")
        state=movementstate.ONLYCAMERA
        backupMouse=lastmouse
        Input.set_mouse_mode(Input.MOUSE_MODE_HIDDEN)
        
    if state==movementstate.FULL:
        #last mouse will always contain the last position your mouse has moved to
        #we do this with _input
        #The world has to stay rotating even if the pointer would go out of bounds
        #that's why it's always reset to (500,500) < this should not be hardcoded btw but probably be 
        #half of the width/height of your current view
        var R=Vector2(500,500)-lastmouse#R contains the amount of pixels the mouse moved since last pass of _physics_process
        Input.warp_mouse_position(Vector2(500,500))
        
        #rot can be adjusted to make rotation faster
        var rot = deg2rad(R.x*90)*delta 
        #Forward is changed every time turning happens. 
        forward=forward.rotated(Vector3(0,1,0),rot)
        player.rotate(Vector3(0,1,0),rot)
        cam.rotate(Vector3(0,1,0),rot)

The current problem is that any mouse scroll functionality implemented would need to take the left mouse rotation into account. I feel that the camera might need to have a "forward" vector which would be aware of what the new "forward" is POST rotation.

Current cam_zoom()

func cam_zoom(delta):
    if zoom_dir != 0:
        target_location = Vector3(cam.translation.x, cam.translation.y, cam.translation.z)
        cam.translation =  target_location + forward * 0.2 * zoom_dir
        
        
    zoom_dir = 0

Here is a link to my working godot project: https://gofile.io/d/T9TAop

[update] still haven't been able to work this out! would appreciate any help.

Intro verb
  • 13
  • 3

1 Answers1

0

For camera forward, you can take the z axis of the basis of the transform of the camera.

However, I would suggest to implement your camera differently. In the shared code, you have two axis of rotation controlled by the mouse:

cam.rotation_degrees.x -= event.relative.y * V_LOOK_SENS
cam.rotation_degrees.x = clamp(cam.rotation_degrees.x, -90, 10)
cam.rotation_degrees.y -= event.relative.x * H_LOOK_SENS

Aside from the rotation, what else do you need to know to place the camera? Well, it should be looking at the avatar, and it should be at some distance.

So make an identity transform, translate it along the z axis the distance, then rotate it according to the camera rotation you want, and then multiply the transform of the avatar by it. It should give you the transform for the camera.

I don't know why you made your camera a kinematic body. move_and_slide makes no sense without a collision. Just set the transform.

Theraot
  • 31,890
  • 5
  • 57
  • 86