Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rcamera methods? #91

Open
Xynonners opened this issue Sep 30, 2023 · 2 comments
Open

rcamera methods? #91

Xynonners opened this issue Sep 30, 2023 · 2 comments

Comments

@Xynonners
Copy link

Do these have an equivalent in naylib or is it not necessary?

@Xynonners
Copy link
Author

I just ported rcamera to nim using c2nim, and then manually editing it

not sure if it works but it compiles fine (hopefully no mistakes due to sleepyness lel)

@Xynonners
Copy link
Author

from math import nil
import raylib, raymath

const
  CAMERA_CULL_DISTANCE_NEAR* = 0.01
  CAMERA_CULL_DISTANCE_FAR* = 1000.0

##  raylib required functionality:
##  GetMouseDelta()
##  GetMouseWheelMove()
##  IsKeyDown()
##  IsKeyPressed()
##  GetFrameTime()
## ----------------------------------------------------------------------------------
##  Defines and Macros
## ----------------------------------------------------------------------------------
const
  CAMERA_MOVE_SPEED* = 0.09f
  CAMERA_ROTATION_SPEED* = 0.03f
  CAMERA_PAN_SPEED* = 0.2f
##  Camera mouse movement sensitivity
const
  CAMERA_MOUSE_MOVE_SENSITIVITY* = 0.003f
  CAMERA_MOUSE_SCROLL_SENSITIVITY* = 1.5f
  CAMERA_ORBITAL_SPEED* = 0.5f
  CAMERA_FIRST_PERSON_STEP_TRIGONOMETRIC_DIVIDER* = 8.0f
  CAMERA_FIRST_PERSON_STEP_DIVIDER* = 30.0f
  CAMERA_FIRST_PERSON_WAVING_DIVIDER* = 200.0f
##  PLAYER (used by camera)
const
  PLAYER_MOVEMENT_SENSITIVITY* = 20.0f
## ----------------------------------------------------------------------------------
##  Types and Structures Definition
## ----------------------------------------------------------------------------------
## ...
## ----------------------------------------------------------------------------------
##  Global Variables Definition
## ----------------------------------------------------------------------------------
## ...
## ----------------------------------------------------------------------------------
##  Module specific Functions Declaration
## ----------------------------------------------------------------------------------
## ...
## ----------------------------------------------------------------------------------
##  Module Functions Definition
## ----------------------------------------------------------------------------------
##  Returns the cameras forward vector (normalized)
proc getCameraForward*(camera: var Camera): Vector3 =
  return normalize(subtract(camera.target, camera.position))

##  Returns the cameras up vector (normalized)
##  Note: The up vector might not be perpendicular to the forward vector
proc getCameraUp*(camera: var Camera): Vector3 =
  return normalize(camera.up)

##  Returns the cameras right vector (normalized)
proc getCameraRight*(camera: var Camera): Vector3 =
  var forward: Vector3 = getCameraForward(camera)
  var up: Vector3 = getCameraUp(camera)
  return crossProduct(forward, up)

##  Moves the camera in its forward direction
proc cameraMoveForward*(camera: var Camera; distance: float; moveInWorldPlane: bool) =
  var forward: Vector3 = getCameraForward(camera)
  if moveInWorldPlane:
    ##  Project vector onto world plane
    forward.y = 0
    forward = normalize(forward)
  forward = scale(forward, distance)
  ##  Move position and target
  camera.position = add(camera.position, forward)
  camera.target = add(camera.target, forward)

##  Moves the camera in its up direction
proc cameraMoveUp*(camera: var Camera; distance: float) =
  var up: Vector3 = getCameraUp(camera)
  ##  Scale by distance
  up = scale(up, distance)
  ##  Move position and target
  camera.position = add(camera.position, up)
  camera.target = add(camera.target, up)

##  Moves the camera target in its current right direction
proc cameraMoveRight*(camera: var Camera; distance: float; moveInWorldPlane: bool) =
  var right: Vector3 = getCameraRight(camera)
  if moveInWorldPlane:
    ##  Project vector onto world plane
    right.y = 0
    right = normalize(right)
  right = scale(right, distance)
  ##  Move position and target
  camera.position = add(camera.position, right)
  camera.target = add(camera.target, right)

##  Moves the camera position closer/farther to/from the camera target
proc cameraMoveToTarget*(camera: var Camera; delta: float) =
  var distance: float = distance(camera.position, camera.target)
  ##  Apply delta
  distance += delta
  ##  Distance must be greater than 0
  if distance <= 0:
    distance = 0.001f
  var forward: Vector3 = getCameraForward(camera)
  camera.position = add(camera.target, scale(forward, -distance))

##  Rotates the camera around its up vector
##  Yaw is "looking left and right"
##  If rotateAroundTarget is false, the camera rotates around its position
##  Note: angle must be provided in radians
proc cameraYaw*(camera: var Camera; angle: float; rotateAroundTarget: bool) =
  ##  Rotation axis
  var up: Vector3 = getCameraUp(camera)
  ##  View vector
  var targetPosition: Vector3 = subtract(camera.target, camera.position)
  ##  Rotate view vector around up axis
  targetPosition = rotateByAxisAngle(targetPosition, up, angle)
  if rotateAroundTarget: ##  rotate around camera.position
    ##  Move position relative to target
    camera.position = subtract(camera.target, targetPosition)
  else:
    ##  Move target relative to position
    camera.target = add(camera.position, targetPosition)

##  Rotates the camera around its right vector, pitch is "looking up and down"
##   - lockView prevents camera overrotation (aka "somersaults")
##   - rotateAroundTarget defines if rotation is around target or around its position
##   - rotateUp rotates the up direction as well (typically only usefull in CAMERA_FREE)
##  NOTE: angle must be provided in radians
proc cameraPitch*(camera: var Camera; angle: sink float; lockView: bool; rotateAroundTarget: bool; rotateUp: bool) =
  ##  Up direction
  var up: Vector3 = getCameraUp(camera)
  ##  View vector
  var targetPosition: Vector3 = subtract(camera.target, camera.position)
  if lockView:
    ##  In these camera modes we clamp the Pitch angle
    ##  to allow only viewing straight up or down.
    ##  Clamp view up
    var maxAngleUp: float = angle(up, targetPosition)
    maxAngleUp -= 0.001f
    ##  avoid numerical errors
    if angle > maxAngleUp:
      angle = maxAngleUp
    var maxAngleDown: float = angle(negate(up), targetPosition)
    maxAngleDown = maxAngleDown * -1.0f
    ##  downwards angle is negative
    maxAngleDown += 0.001f
    ##  avoid numerical errors
    if angle < maxAngleDown:
      angle = maxAngleDown
  var right: Vector3 = getCameraRight(camera)
  ##  Rotate view vector around right axis
  targetPosition = rotateByAxisAngle(targetPosition, right, angle)
  if rotateAroundTarget: ##  rotate around camera.position
    ##  Move position relative to target
    camera.position = subtract(camera.target, targetPosition)
  else:
    ##  Move target relative to position
    camera.target = add(camera.position, targetPosition)
  if rotateUp:
    ##  Rotate up direction around right axis
    camera.up = rotateByAxisAngle(camera.up, right, angle)

##  Rotates the camera around its forward vector
##  Roll is "turning your head sideways to the left or right"
##  Note: angle must be provided in radians
proc cameraRoll*(camera: var Camera; angle: float) =
  ##  Rotation axis
  var forward: Vector3 = getCameraForward(camera)
  ##  Rotate up direction around forward axis
  camera.up = rotateByAxisAngle(camera.up, forward, angle)

##  Returns the camera view matrix
proc getCameraViewMatrix*(camera: var Camera): Matrix =
  return lookAt(camera.position, camera.target, camera.up)

##  Returns the camera projection matrix
proc getCameraProjectionMatrix*(camera: var Camera; aspect: float): Matrix =
  if camera.projection == Perspective:
    return perspective(math.degToRad(camera.fovy), aspect, CAMERA_CULL_DISTANCE_NEAR, CAMERA_CULL_DISTANCE_FAR)
  elif camera.projection == Orthographic:
    var top: float64 = camera.fovy/2.0f
    var right: float64 = top*aspect
    return ortho(-right, right, -top, top, CAMERA_CULL_DISTANCE_NEAR,
                      CAMERA_CULL_DISTANCE_FAR)
  return matrixIdentity()

##  Update camera position for selected mode
##  Camera mode: CAMERA_FREE, CAMERA_FIRST_PERSON, CAMERA_THIRD_PERSON, CAMERA_ORBITAL or CUSTOM
proc updateCamera*(camera: var Camera; mode: CameraMode) =
  var mousePositionDelta: Vector2 = getMouseDelta()
  var moveInWorldPlane: bool = if (mode == FirstPerson or mode == ThirdPerson): true else: false
  var rotateAroundTarget: bool = if (mode == ThirdPerson or mode == Orbital): true else: false
  var lockView: bool = if (mode == FirstPerson or mode == ThirdPerson or mode == Orbital): true else: false
  var rotateUp: bool = false
  if mode == Orbital:
    ##  Orbital can just orbit
    var rotation: Matrix = rotate(getCameraUp(camera), CAMERA_ORBITAL_SPEED*getFrameTime())
    var view: Vector3 = subtract(camera.position, camera.target)
    view = transform(view, rotation)
    camera.position = add(camera.target, view)
  else:
    ##  Camera rotation
    if isKeyDown(Down):
      cameraPitch(camera, -CAMERA_ROTATION_SPEED, lockView, rotateAroundTarget, rotateUp)
    if isKeyDown(Up):
      cameraPitch(camera, CAMERA_ROTATION_SPEED, lockView, rotateAroundTarget, rotateUp)
    if isKeyDown(Right):
      cameraYaw(camera, -CAMERA_ROTATION_SPEED, rotateAroundTarget)
    if isKeyDown(Left):
      cameraYaw(camera, CAMERA_ROTATION_SPEED, rotateAroundTarget)
    if isKeyDown(Q):
      cameraRoll(camera, -CAMERA_ROTATION_SPEED)
    if isKeyDown(E):
      cameraRoll(camera, CAMERA_ROTATION_SPEED)
    if not isGamepadAvailable(0):
      ##  Camera pan (for CAMERA_FREE)
      if (mode == Free) and (isMouseButtonDown(Middle)):
        let mouseDelta: Vector2 = getMouseDelta()
        if mouseDelta.x > 0.0f:
          cameraMoveRight(camera, CAMERA_PAN_SPEED, moveInWorldPlane)
        if mouseDelta.x < 0.0f:
          cameraMoveRight(camera, -CAMERA_PAN_SPEED, moveInWorldPlane)
        if mouseDelta.y > 0.0f:
          cameraMoveUp(camera, -CAMERA_PAN_SPEED)
        if mouseDelta.y < 0.0f:
          cameraMoveUp(camera, CAMERA_PAN_SPEED)
      else:
        ##  Mouse support
        cameraYaw(camera, -(mousePositionDelta.x * CAMERA_MOUSE_MOVE_SENSITIVITY), rotateAroundTarget)
        cameraPitch(camera, -(mousePositionDelta.y * CAMERA_MOUSE_MOVE_SENSITIVITY), lockView, rotateAroundTarget, rotateUp)
      ##  Keyboard support
      if isKeyDown(W):
        cameraMoveForward(camera, CAMERA_MOVE_SPEED, moveInWorldPlane)
      if isKeyDown(A):
        cameraMoveRight(camera, -CAMERA_MOVE_SPEED, moveInWorldPlane)
      if isKeyDown(S):
        cameraMoveForward(camera, -CAMERA_MOVE_SPEED, moveInWorldPlane)
      if isKeyDown(D):
        cameraMoveRight(camera, CAMERA_MOVE_SPEED, moveInWorldPlane)
    else:
      ##  Gamepad controller support
      cameraYaw(camera, -((getGamepadAxisMovement(0, RightX) * 2) * CAMERA_MOUSE_MOVE_SENSITIVITY), rotateAroundTarget)
      cameraPitch(camera, -((getGamepadAxisMovement(0, RightY) * 2) * CAMERA_MOUSE_MOVE_SENSITIVITY), lockView, rotateAroundTarget, rotateUp)
      if getGamepadAxisMovement(0, LeftY) <= -0.25f:
        cameraMoveForward(camera, CAMERA_MOVE_SPEED, moveInWorldPlane)
      if getGamepadAxisMovement(0, LeftX) <= -0.25f:
        cameraMoveRight(camera, -CAMERA_MOVE_SPEED, moveInWorldPlane)
      if getGamepadAxisMovement(0, LeftY) >= 0.25f:
        cameraMoveForward(camera, -CAMERA_MOVE_SPEED, moveInWorldPlane)
      if getGamepadAxisMovement(0, LeftX) >= 0.25f:
        cameraMoveRight(camera, CAMERA_MOVE_SPEED, moveInWorldPlane)
    if mode == Free:
      if isKeyDown(Space):
        cameraMoveUp(camera, CAMERA_MOVE_SPEED)
      if isKeyDown(LeftControl):
        cameraMoveUp(camera, -CAMERA_MOVE_SPEED)
  if (mode == ThirdPerson) or (mode == Orbital) or (mode == Free):
    ##  Zoom target distance
    cameraMoveToTarget(camera, -getMouseWheelMove())
    if isKeyPressed(KpSubtract):
      cameraMoveToTarget(camera, 2.0f)
    if isKeyPressed(KpAdd):
      cameraMoveToTarget(camera, -2.0f)

##  Update camera movement, movement/rotation values should be provided by user
proc updateCameraPro*(camera: var Camera; movement: Vector3; rotation: Vector3; zoom: float) =
  ##  Required values
  ##  movement.x - Move forward/backward
  ##  movement.y - Move right/left
  ##  movement.z - Move up/down
  ##  rotation.x - yaw
  ##  rotation.y - pitch
  ##  rotation.z - roll
  ##  zoom - Move towards target
  var lockView: bool = true
  var rotateAroundTarget: bool = false
  var rotateUp: bool = false
  var moveInWorldPlane: bool = true
  ##  Camera rotation
  cameraPitch(camera, -(math.degToRad(rotation.y)), lockView, rotateAroundTarget,
              rotateUp)
  cameraYaw(camera, -(math.degToRad(rotation.x)), rotateAroundTarget)
  cameraRoll(camera, math.degToRad(rotation.z))
  ##  Camera movement
  cameraMoveForward(camera, movement.x, moveInWorldPlane)
  cameraMoveRight(camera, movement.y, moveInWorldPlane)
  cameraMoveUp(camera, movement.z)
  ##  Zoom target distance
  cameraMoveToTarget(camera, zoom)

Here's the port, there may be mistakes dunno

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant