Class: Simple3d::Mesh
- Inherits:
-
Object
- Object
- Simple3d::Mesh
- Defined in:
- lib/simple3d/mesh.rb
Instance Attribute Summary collapse
-
#indices ⇒ Object
Returns the value of attribute indices.
-
#vertices ⇒ Object
Returns the value of attribute vertices.
Class Method Summary collapse
Instance Method Summary collapse
- #add_face(points, reuse_existing_points = true) ⇒ Object
- #calculate_tangents! ⇒ Object
- #collapse_similar_vertices! ⇒ Object
- #find_similar_vertex(v) ⇒ Object
- #indices_for_triangle(i) ⇒ Object
-
#initialize(options = {}) ⇒ Mesh
constructor
A new instance of Mesh.
- #num_triangles ⇒ Object
- #renderable_vertices ⇒ Object
- #smooth_normals! ⇒ Object
- #triangle(i) ⇒ Object
- #vertices_for_triangle(i) ⇒ Object
Constructor Details
#initialize(options = {}) ⇒ Mesh
Returns a new instance of Mesh.
6 7 8 9 10 11 12 13 14 15 16 17 18 |
# File 'lib/simple3d/mesh.rb', line 6 def initialize = {} @indices = [:indices] if @indices.nil? && [:vertices] [:vertices].each_slice(3) do |points| add_face points, [:reuse_existing_points] end else @vertices = [:vertices] end @indices ||= [] @vertices ||= [] end |
Instance Attribute Details
#indices ⇒ Object
Returns the value of attribute indices.
3 4 5 |
# File 'lib/simple3d/mesh.rb', line 3 def indices @indices end |
#vertices ⇒ Object
Returns the value of attribute vertices.
4 5 6 |
# File 'lib/simple3d/mesh.rb', line 4 def vertices @vertices end |
Class Method Details
.from_file(filename) ⇒ Object
20 21 22 23 24 25 26 27 28 29 |
# File 'lib/simple3d/mesh.rb', line 20 def self.from_file filename m = self.new w = Wavefront::File.new filename w.compute_vertex_buffer.each_slice(3) do |slice| m.add_face slice.map{|wv| wv.position.to_a + [wv.tex.x, wv.tex.y] + wv.normal.to_a } end m end |
.unit_cube ⇒ Object
178 179 180 181 182 183 184 185 186 187 |
# File 'lib/simple3d/mesh.rb', line 178 def self.unit_cube cube = self.new cube.add_face [[1, -1, -1], [1, -1, 1], [-1, -1, 1], [-1, -1, -1]] cube.add_face [[1, 1, -1], [-1, 1, -1], [-1, 1, 1], [1, 1, 1]] cube.add_face [[1, -1, -1], [1, 1, -1], [1, 1, 1], [1, -1, 1]] cube.add_face [[1, -1, 1], [1, 1, 1], [-1, 1, 1], [-1, -1, 1]] cube.add_face [[-1, -1, 1], [-1, 1, 1], [-1, 1, -1], [-1, -1, -1]] cube.add_face [[1, 1, -1], [1, -1, -1], [-1, -1, -1], [-1, 1, -1]] cube end |
Instance Method Details
#add_face(points, reuse_existing_points = true) ⇒ Object
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
# File 'lib/simple3d/mesh.rb', line 31 def add_face points, reuse_existing_points = true if points.size > 4 raise "faces with more than four points currently not supported" elsif points.size == 4 add_face [points[0], points[1], points[3]] add_face [points[3], points[1], points[2]] else points.each do |pt| pt = Vertex.new *pt if pt.kind_of? Array similar_vertex_index = if reuse_existing_points find_similar_vertex pt else nil end if similar_vertex_index @indices << similar_vertex_index else @vertices << pt @indices << @vertices.size - 1 end end end end |
#calculate_tangents! ⇒ Object
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 |
# File 'lib/simple3d/mesh.rb', line 116 def calculate_tangents! tan1 = Array.new vertices.size tan2 = Array.new vertices.size for i in 0..vertices.size-1 tan1[i] = Geo3d::Vector.new tan2[i] = Geo3d::Vector.new end for a in 0..num_triangles-1 i1, i2, i3 = indices_for_triangle a v1 = vertices[i1].position v2 = vertices[i2].position v3 = vertices[i3].position w1 = vertices[i1].texcoord w2 = vertices[i2].texcoord w3 = vertices[i3].texcoord x1 = v2.x - v1.x x2 = v3.x - v1.x y1 = v2.y - v1.y y2 = v3.y - v1.y z1 = v2.z - v1.z z2 = v3.z - v1.z s1 = w2.x - w1.x s2 = w3.x - w1.x t1 = w2.y - w1.y t2 = w3.y - w1.y r = 1.0 / (s1 * t2 - s2 * t1) sdir = Geo3d::Vector.new (t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r tdir = Geo3d::Vector.new (s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r tan1[i1] += sdir tan1[i2] += sdir tan1[i3] += sdir tan2[i1] += tdir tan2[i2] += tdir tan2[i3] += tdir end for a in 0..vertices.size-1 n = vertices[a].normal t = tan1[a] puts "n is #{n.inspect}" puts "t is #{t.inspect}" # Gram-Schmidt orthogonalize vertices[a].tangent = (t - n * n.dot(t)).normalize # Calculate handedness # tangent(a).w = (Dot(Cross(n, t), tan2[a]) < 0.0F) ? -1.0F : 1.0F; vertices[a].tangent.w = n.cross(t).dot(tan2[a]) < 0.0 ? -1.0 : 1.0 end end |
#collapse_similar_vertices! ⇒ Object
63 64 65 66 67 68 69 70 71 |
# File 'lib/simple3d/mesh.rb', line 63 def collapse_similar_vertices! faces = indices.each_slice(3) old_vertices = @vertices old_indices = @indices @vertices = @indices = nil end |
#find_similar_vertex(v) ⇒ Object
56 57 58 59 60 61 |
# File 'lib/simple3d/mesh.rb', line 56 def find_similar_vertex v vertices.each_with_index do |vt, i| return i if vt.position == v.position && vt.texcoord == v.texcoord end nil end |
#indices_for_triangle(i) ⇒ Object
83 84 85 |
# File 'lib/simple3d/mesh.rb', line 83 def indices_for_triangle i [indices[i*3], indices[i*3+1], indices[i*3+2]] end |
#num_triangles ⇒ Object
73 74 75 |
# File 'lib/simple3d/mesh.rb', line 73 def num_triangles indices.size / 3 end |
#renderable_vertices ⇒ Object
77 78 79 80 81 |
# File 'lib/simple3d/mesh.rb', line 77 def renderable_vertices indices.map do |i| vertices[i] end end |
#smooth_normals! ⇒ Object
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 |
# File 'lib/simple3d/mesh.rb', line 96 def smooth_normals! indices_to_face_normals = Array.new vertices.size for i in 0..vertices.size-1 indices_to_face_normals[i] = [] end for a in 0..num_triangles-1 tri = triangle a indices_for_triangle(a).each do |vertex_index| face_normal = tri.normal indices_to_face_normals[vertex_index] << face_normal end end for i in 0..vertices.size-1 face_normals = indices_to_face_normals[i] vertices[i].normal = face_normals.inject(:+).normalize end end |
#triangle(i) ⇒ Object
91 92 93 |
# File 'lib/simple3d/mesh.rb', line 91 def triangle i Geo3d::Triangle.new *(vertices_for_triangle(i).map(&:position)) end |
#vertices_for_triangle(i) ⇒ Object
87 88 89 |
# File 'lib/simple3d/mesh.rb', line 87 def vertices_for_triangle i indices_for_triangle(i).map { |index| vertices[index] } end |