Class: Engine::TangentCalculator

Inherits:
Object
  • Object
show all
Defined in:
lib/engine/tangent_calculator.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(vertices, normals, texture_coords) ⇒ TangentCalculator

Returns a new instance of TangentCalculator.



7
8
9
10
11
# File 'lib/engine/tangent_calculator.rb', line 7

def initialize(vertices, normals, texture_coords)
  @vertices = vertices
  @normals = normals
  @texture_coords = texture_coords
end

Instance Attribute Details

#normalsObject (readonly)

Returns the value of attribute normals.



5
6
7
# File 'lib/engine/tangent_calculator.rb', line 5

def normals
  @normals
end

#texture_coordsObject (readonly)

Returns the value of attribute texture_coords.



5
6
7
# File 'lib/engine/tangent_calculator.rb', line 5

def texture_coords
  @texture_coords
end

#verticesObject (readonly)

Returns the value of attribute vertices.



5
6
7
# File 'lib/engine/tangent_calculator.rb', line 5

def vertices
  @vertices
end

Instance Method Details

#calculate_tangentsObject



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
# File 'lib/engine/tangent_calculator.rb', line 13

def calculate_tangents
  delta_pos1 = @vertices[1] - @vertices[0]
  delta_pos2 = @vertices[2] - @vertices[0]

  delta_uv1 = @texture_coords[1] - @texture_coords[0]
  delta_uv2 = @texture_coords[2] - @texture_coords[0]

  if delta_uv1[0] * delta_uv2[1] - delta_uv1[1] * delta_uv2[0] == 0
    return normals.map { |normal| Vector[0, 0, 0] }
  end

  uv_matrix = Matrix[
    [delta_uv1[0], delta_uv1[1]],
    [delta_uv2[0], delta_uv2[1]]
  ]

  world_matrix = Matrix[
    [delta_pos1[0], delta_pos1[1], delta_pos1[2]],
    [delta_pos2[0], delta_pos2[1], delta_pos2[2]]
  ]

  tangent_matrix = uv_matrix.inv * world_matrix

  flat_tangent = Vector[tangent_matrix[0, 0], tangent_matrix[0, 1], tangent_matrix[0, 2]]
  bitangents = normals.map { |normal| normal.cross(flat_tangent).normalize }

  normals.map { |normal| bitangents[0].cross(normal).normalize }
end