Class: Ra::Camera
Overview
A camera produces rays used to generate pixels. By convention, the camera is positioned at the point <x=0,y=0,z=0>. The rays target an imaginary screen that exists at z=-1. The x,y values visible on the screen depend on the FOV and the width / height of the desired image.
A FOV represents the angel of the world visible to the camera. A default FOV is 90 degrees. This results in 2.0 by 2.0 of the world visible at z=-1.
A bigger FOV increases what in the world is visible to the camera. When FOV is 120 degrees then ~3.5 by ~3.5 world view visible through z=-1.
A smaller FOV decreases what in the world is visible to the camera. When FOV is 60 degrees then ~1.2 by ~1.2 world view is visible through z=-1.
The visible world view is then split into pixels bsaed on the l / w of the desired screen. The pixel size is calculated using these l / w dimensions. The pixels are defined to be evenly spaced within the visible world.
An example of a default 90 degree FOV and w=5 / h=4 results in pixels that are of size 0.4 (the greater of 2.0 / w=5 and 2.0 / h=4). With these dimensions rays are cast to the center of pixels evenly distrubted across the screen.
Constant Summary collapse
- DEFAULT_W =
1280
- DEFAULT_H =
1024
- DEFAULT_FOV =
Math::PI / 3
Instance Attribute Summary collapse
Instance Method Summary collapse
- #each {|y, x, ray| ... } ⇒ Object
- #half_h ⇒ Float
- #half_view ⇒ Float
- #half_w ⇒ Float
-
#initialize(transform: Transform::IDENTITY, h: DEFAULT_H, w: DEFAULT_W, fov: DEFAULT_FOV) ⇒ Camera
constructor
A new instance of Camera.
- #p_size ⇒ Float
- #ray(x:, y:) ⇒ Ra::Ray
Constructor Details
#initialize(transform: Transform::IDENTITY, h: DEFAULT_H, w: DEFAULT_W, fov: DEFAULT_FOV) ⇒ Camera
Returns a new instance of Camera.
53 54 55 56 57 58 |
# File 'lib/ra/camera.rb', line 53 def initialize(transform: Transform::IDENTITY, h: DEFAULT_H, w: DEFAULT_W, fov: DEFAULT_FOV) @transform = transform @h = h @w = w @fov = fov end |
Instance Attribute Details
#fov ⇒ Numeric
39 40 41 |
# File 'lib/ra/camera.rb', line 39 def fov @fov end |
#h ⇒ Integer
31 32 33 |
# File 'lib/ra/camera.rb', line 31 def h @h end |
#w ⇒ Integer
35 36 37 |
# File 'lib/ra/camera.rb', line 35 def w @w end |
Instance Method Details
#each {|y, x, ray| ... } ⇒ Object
64 65 66 67 68 69 70 71 72 73 74 |
# File 'lib/ra/camera.rb', line 64 def each @h.times do |y| @w.times do |x| ray = ray( y:, x:, ) yield(y, x, ray) end end end |
#half_h ⇒ Float
104 105 106 |
# File 'lib/ra/camera.rb', line 104 def half_h @half_h ||= @h < @w ? (half_view * @h / @w) : half_view end |
#half_view ⇒ Float
94 95 96 |
# File 'lib/ra/camera.rb', line 94 def half_view @half_view ||= Math.tan(@fov / 2) end |
#half_w ⇒ Float
99 100 101 |
# File 'lib/ra/camera.rb', line 99 def half_w @half_w ||= @w < @h ? (half_view * @w / @h) : half_view end |
#p_size ⇒ Float
89 90 91 |
# File 'lib/ra/camera.rb', line 89 def p_size @p_size ||= half_w * 2 / w end |
#ray(x:, y:) ⇒ Ra::Ray
79 80 81 82 83 84 85 86 |
# File 'lib/ra/camera.rb', line 79 def ray(x:, y:) pixel = transform.inverse * Vector[world_x(x:), world_y(y:), -1, Tuple::POINT] origin = transform.inverse * Vector[0, 0, 0, Tuple::POINT] direction = (pixel - origin).normalize Ray.new(origin:, direction:) end |