Class: Quake::Camera

Inherits:
Object
  • Object
show all
Defined in:
lib/quake/camera.rb

Constant Summary collapse

SPEED =

units per second (Quake run speed)

320.0
SENSITIVITY =

degrees per pixel

0.15
MAX_MOUSE_DELTA =

clamp insane deltas (e.g. first frame warp)

50

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(position: Math::Vec3::ORIGIN, yaw: 0.0, pitch: 0.0, fov: 90.0, near: 4.0, far: 4096.0) ⇒ Camera

Returns a new instance of Camera.



15
16
17
18
19
20
21
22
23
24
# File 'lib/quake/camera.rb', line 15

def initialize(position: Math::Vec3::ORIGIN, yaw: 0.0, pitch: 0.0,
               fov: 90.0, near: 4.0, far: 4096.0)
  @position = position
  @yaw = yaw
  @pitch = pitch
  @fov = fov
  @near = near
  @far = far
  @ignore_mouse = 2  # skip first N motion events (SDL warp artifacts)
end

Instance Attribute Details

#farObject (readonly)

Returns the value of attribute far.



9
10
11
# File 'lib/quake/camera.rb', line 9

def far
  @far
end

#fovObject (readonly)

Returns the value of attribute fov.



9
10
11
# File 'lib/quake/camera.rb', line 9

def fov
  @fov
end

#nearObject (readonly)

Returns the value of attribute near.



9
10
11
# File 'lib/quake/camera.rb', line 9

def near
  @near
end

#pitchObject

Returns the value of attribute pitch.



8
9
10
# File 'lib/quake/camera.rb', line 8

def pitch
  @pitch
end

#positionObject

Returns the value of attribute position.



8
9
10
# File 'lib/quake/camera.rb', line 8

def position
  @position
end

#yawObject

Returns the value of attribute yaw.



8
9
10
# File 'lib/quake/camera.rb', line 8

def yaw
  @yaw
end

Instance Method Details

#apply_glObject



78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/quake/camera.rb', line 78

def apply_gl
  GL.MatrixMode(GL::MODELVIEW)
  GL.LoadIdentity

  # Quake coords (X-forward, Y-left, Z-up) -> GL coords (X-right, Y-up, Z-backward)
  # Rotate -90 around X to convert Z-up to Y-up
  # Rotate 90 around Z to convert X-forward to -Z-backward
  GL.Rotatef(-90.0, 1.0, 0.0, 0.0)  # Z-up -> Y-up
  GL.Rotatef(90.0, 0.0, 0.0, 1.0)   # X-forward -> GL

  GL.Rotatef(-@pitch, 0.0, 1.0, 0.0)
  GL.Rotatef(-@yaw, 0.0, 0.0, 1.0)
  GL.Translatef(-@position.x, -@position.y, -@position.z)
end

#apply_projection_gl(aspect) ⇒ Object



72
73
74
75
76
# File 'lib/quake/camera.rb', line 72

def apply_projection_gl(aspect)
  GL.MatrixMode(GL::PROJECTION)
  GL.LoadIdentity
  GLU.Perspective(@fov, aspect, @near, @far)
end

#forwardObject



26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/quake/camera.rb', line 26

def forward
  # Quake: X = forward, Y = left, Z = up
  # yaw rotates around Z, pitch rotates around Y
  ry = deg2rad(@yaw)
  rp = deg2rad(@pitch)
  cp = ::Math.cos(rp)
  Math::Vec3.new(
    ::Math.cos(ry) * cp,
    ::Math.sin(ry) * cp,
    -::Math.sin(rp)
  )
end

#move_forward(dt) ⇒ Object



48
49
50
# File 'lib/quake/camera.rb', line 48

def move_forward(dt)
  @position = @position + forward * (SPEED * dt)
end

#move_right(dt) ⇒ Object



52
53
54
# File 'lib/quake/camera.rb', line 52

def move_right(dt)
  @position = @position + right * (SPEED * dt)
end

#move_up(dt) ⇒ Object



56
57
58
# File 'lib/quake/camera.rb', line 56

def move_up(dt)
  @position = @position + up * (SPEED * dt)
end

#rightObject



39
40
41
42
# File 'lib/quake/camera.rb', line 39

def right
  ry = deg2rad(@yaw - 90.0)
  Math::Vec3.new(::Math.cos(ry), ::Math.sin(ry), 0.0)
end

#rotate(dx, dy) ⇒ Object



60
61
62
63
64
65
66
67
68
69
70
# File 'lib/quake/camera.rb', line 60

def rotate(dx, dy)
  if @ignore_mouse > 0
    @ignore_mouse -= 1
    return
  end
  dx = dx.clamp(-MAX_MOUSE_DELTA, MAX_MOUSE_DELTA)
  dy = dy.clamp(-MAX_MOUSE_DELTA, MAX_MOUSE_DELTA)
  @yaw -= dx * SENSITIVITY
  @pitch += dy * SENSITIVITY
  @pitch = @pitch.clamp(-89.0, 89.0)
end

#upObject



44
45
46
# File 'lib/quake/camera.rb', line 44

def up
  Math::Vec3.new(0.0, 0.0, 1.0)
end