aboutsummaryrefslogtreecommitdiff
path: root/lib/camera.rb
blob: 6a3b1904b7a8ea3c247682d55f9bc94d012023a5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
class Camera
  def initialize(width = 100, aspect = 1.0, aliasing = 10, depth = 10)
    @width = width
    @aspect = aspect
    @aliasing = aliasing
    @depth = depth

    # Height
    @height = (@width / @aspect).to_i
    @height = @height < 1 ? 1 : @height

    # Camera
    c_focallength = 1.0
    @c_centre = Point.new(0,0,0)

    # Viewport
    @v_height = 2.0
    @v_width = @v_height * @width.to_f / @height
    v_u = Vec3.new(@v_width, 0, 0)
    v_v = Vec3.new(0, -@v_height, 0)

    # Pixel deltas
    @pd_u = v_u / @width
    @pd_v = v_v / @height

    # Upper left pixel
    v_upperleft = @c_centre - v_u / 2 - v_v / 2 -
                  Vec3.new(0, 0, c_focallength)
    @p00_loc = v_upperleft + (@pd_u + @pd_v) / 2
  end

  def render(world)
    start = Time.now.to_f

    puts "P3"
    puts "#{@width} #{@height}"
    puts "255"

    @height.times do |row|
      $stderr.print "Scanlines remaining: %4d" % (@height - row)
      @width.times do |col|
        p_colour = Colour.new
        @aliasing.times do
          p_colour += get_ray(row, col).colour(world, @depth)
        end
        puts (p_colour / @aliasing).to_ppm
      end
      puts
    end

    finish = Time.now.to_f
    took = finish - start

    $stderr.puts "Done. Took %4.2f seconds. " % took
  end

  def get_ray(row, col)
    p_sample = @p00_loc +
               @pd_u * (col + rand - 0.5) +
               @pd_v * (row + rand - 0.5)

    Ray.new(@c_centre, p_sample - @c_centre)
  end
end