Sha256: a41a88f78dbdcffb2a1134155e8d86c3d0196e039d675c64b8163d6ccd8fe207

Contents?: true

Size: 1.2 KB

Versions: 3

Compression:

Stored size: 1.2 KB

Contents

# frozen_string_literal: true

module Engine
  class TangentCalculator
    attr_reader :vertices, :normals, :texture_coords

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

    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
  end
end

Version data entries

3 entries across 3 versions & 1 rubygems

Version Path
ruby_rpg-0.0.4 lib/engine/tangent_calculator.rb
ruby_rpg-0.0.3 lib/engine/tangent_calculator.rb
ruby_rpg-0.0.2 lib/engine/tangent_calculator.rb