class Vec3 def initialize(x = 0, y = 0, z = 0) @x = x.to_f @y = y.to_f @z = z.to_f end attr_reader :x, :y, :z def +(oth) self.class.new(@x + oth.x, @y + oth.y, @z + oth.z) end def -@ self.class.new(-@x, -@y, -@z) end def -(oth) self + -oth end def *(oth) if oth.is_a?(Vec3) self.class.new(@x * oth.x, @y * oth.y, @z * oth.z) else self.class.new(@x * oth, @y * oth, @z * oth) end end def /(oth) self * (1.0 / oth) end def dot(oth) v = self * oth v.x + v.y + v.z end def cross(oth) self.class.new( @y * oth.z - @z * oth.y, @z * oth.x - @x * oth.z, @x * oth.y - @y * oth.x ) end def mag_sqr @x ** 2 + @y ** 2 + @z ** 2 end def mag mag_sqr ** 0.5 end def unit self / mag end def to_s "{#{@x}, #{@y}, #{@z}}" end end class Point < Vec3; end class Colour < Vec3 def r; @x; end def g; @y; end def b; @z; end def to_ppm "%3d %3d %3d" % [(r * 255.999).to_i, (g * 255.999).to_i, (b * 255.999).to_i] end end