Class: Ra::World

Inherits:
Object
  • Object
show all
Defined in:
lib/ra/world.rb

Overview

A world is composed of objects (lights / cameras) and handles coloring of rays.

Instance Method Summary collapse

Constructor Details

#initialize(lights:, shapes:) ⇒ World

Returns a new instance of World.

Parameters:



8
9
10
11
# File 'lib/ra/world.rb', line 8

def initialize(lights:, shapes:)
  @lights = lights
  @shapes = shapes
end

Instance Method Details

#color(ray:, remaining: 4) ⇒ Ra::Color

Parameters:

Returns:



29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/ra/world.rb', line 29

def color(ray:, remaining: 4)
  intersection = intersection(ray:)
  return unless intersection

  surface = intersection.surface

  colors = @lights.map do |light|
    shadowed = shadowed?(point: surface.hpoint, light:)
    lighting = Lighting.new(light:, shadowed:, surface:)
    lighting.color
  end

  colors.reduce(&:+) + reflect(surface:, remaining:)
end

#intersect(ray:) ⇒ Array<Ra::Intersection>

Parameters:

Returns:



15
16
17
18
19
# File 'lib/ra/world.rb', line 15

def intersect(ray:)
  @shapes
    .map { |shape| shape.intersect(ray:) }
    .reduce(:concat) || []
end

#intersection(ray:) ⇒ Ra::Intersection?

Returns:



22
23
24
25
# File 'lib/ra/world.rb', line 22

def intersection(ray:)
  intersections = intersect(ray:)
  Intersection.hit(intersections:)
end

#reflect(surface:, remaining:) ⇒ Ra::Color

Parameters:

Returns:



47
48
49
50
51
52
53
54
55
56
57
# File 'lib/ra/world.rb', line 47

def reflect(surface:, remaining:)
  return if remaining.zero?

  material = surface.shape.material
  return unless material.reflective.positive?

  ray = Ray.new(origin: surface.hpoint, direction: surface.reflectv)

  color = color(ray:, remaining: remaining.pred)
  color * material.reflective if color
end

#shadowed?(light:, point:) ⇒ Boolean

Parameters:

Returns:

  • (Boolean)


61
62
63
64
65
66
67
68
# File 'lib/ra/world.rb', line 61

def shadowed?(light:, point:)
  vector = light.position - point
  distance = vector.magnitude
  direction = vector.normalize
  ray = Ray.new(origin: point, direction:)
  hit = intersection(ray:)
  hit && hit.t < distance
end