class ObjParser::Obj

Constants

VERTEX_BY_FACE

Attributes

faces[RW]
normals[RW]
normals_indexes[RW]
tangents[RW]
tangents_indexes[RW]
textures[RW]
textures_indexes[RW]
vertice[RW]
vertice_indexes[RW]

Public Class Methods

new() click to toggle source
# File lib/obj_parser/obj.rb, line 13
def initialize
  self.vertice = []
  self.normals = []
  self.textures = []
  self.tangents = []
  self.vertice_indexes = []
  self.normals_indexes = []
  self.textures_indexes = []
  self.tangents_indexes = []
end

Public Instance Methods

compute_tangents() click to toggle source
# File lib/obj_parser/obj.rb, line 37
def compute_tangents
    self.tangents = []
    self.tangents_indexes = []
  return if textures.count == 0 || normals.count == 0
  self.resolve_faces
    pindex = 0
    self.faces.each do |face|
    pindex += 1
            tangent_for_face = MathUtils::tangent_for_vertices_and_texures(face.vertice.map(&:data), face.textures.map(&:data))
            tangent_for_face = MathUtils::normalized_vector(tangent_for_face)
            #set the same tangent for the 3 vertex of current face
            #re-compute tangents for duplicates vertices to get tangent per face
            face.vertice.each_with_index do |vertex, index|
                    vertex.tangent.data = MathUtils::sum_vectors(vertex.tangent.data, tangent_for_face)
            end
  end
    
    #orthonormalize
    self.faces.each_with_index do |face,pindex|
      face.vertice.each_with_index do |vertex, index|
            vertex.tangent.data = MathUtils::orthogonalized_vector_with_vector(vertex.tangent.data, self.normals[self.normals_indexes[pindex * 3 + index]].data)
            vertex.tangent.data = MathUtils::normalized_vector(vertex.tangent.data)
     end
    end
    
    #binormal should be computed with per vertex tangent and summed for each vertex
    self.faces.each_with_index do |face,pindex|
            face.vertice.each_with_index do |vertex, index|
                    binormal = MathUtils::cross_product(self.normals[self.normals_indexes[pindex * 3 + index]].data, vertex.tangent.data)
                    vertex.binormal.data = MathUtils::sum_vectors(vertex.binormal.data, binormal)
            end
    end
    
    self.faces.each_with_index do |face,pindex|
      face.vertice.each_with_index do |vertex, index|
            vertex.binormal.data = MathUtils::normalized_vector(vertex.binormal.data)
            if(MathUtils::dot(MathUtils::cross_product(self.normals[self.normals_indexes[pindex * 3 + index]].data, vertex.tangent.data), vertex.binormal.data) < 0.0)
                    vertex.tangent.data[3] = -1.0 
            else
                    vertex.tangent.data[3] = 1.0 
            end
    end
  end

    self.faces.each_with_index do |face, index|
            self.tangents += face.vertice.map(&:tangent)
            point_index = index * 3
            self.tangents_indexes += [point_index, point_index + 1, point_index + 2]
    end
end
resolve_faces() click to toggle source
# File lib/obj_parser/obj.rb, line 24
def resolve_faces
  self.faces = (self.vertice_indexes.count / VERTEX_BY_FACE).times.map { Face.new }
  self.faces.each_with_index do |face, face_index|
    [:vertice, :normals, :textures, :tangents].each do |element|
      point_indexes = (self.send("#{element}_indexes")[face_index * VERTEX_BY_FACE..-1] || []).take(VERTEX_BY_FACE)
      points = point_indexes.map do |point_index|
        self.send(element)[point_index]
      end
      face.send("#{element}=", points)
    end
  end
end
tangents_self_check() click to toggle source
# File lib/obj_parser/obj.rb, line 88
def tangents_self_check
  self.resolve_faces
  result = self.faces.each_with_index.map do |face, index| 
            face.vertice.map do |vertex|
              ("%.2f" % MathUtils::dot(vertex.tangent.data[0..2], vertex.normal.data)).to_f
            end.reduce(&:+)
  end.reduce(&:+)
  puts "RESULT: tangents and normals are orthogonal -> [#{result == 0 ? "VALID" : "NOT VALID"}]"
  result == 0
end