Last active
January 31, 2018 05:33
-
-
Save hakanai/f78b211147ff524c7bd2f565a6e1e205 to your computer and use it in GitHub Desktop.
Quick and dirty .obj/.mtl generation in Ruby
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
require_relative 'obj' | |
obj = Obj.build('cube') do | |
# More about material properties here: | |
# https://en.wikipedia.org/wiki/Wavefront_.obj_file | |
# http://www.fileformat.info/format/material/ | |
material = material('cube', | |
'Ns' => '10.0000', # specular exponent (0 - 1000) | |
'Ni' => '1.5000', # illumination exponent? | |
'd' => '1.0000', # opacity (0.0 = transparent, 1.0 = opaque) | |
'Tr' => '0.0000', # transparency (0.0 = opaque, 1.0 = transparent) | |
'Tf' => '1.0000 1.0000 1.0000', # transmission filter (r,g,b) | |
'illum' => '2', # illumination model | |
# 0. Color on and Ambient off | |
# 1. Color on and Ambient on | |
# 2. Highlight on | |
# 3. Reflection on and Ray trace on | |
# 4. Transparency: Glass on, Reflection: Ray trace on | |
# 5. Reflection: Fresnel on and Ray trace on | |
# 6. Transparency: Refraction on, Reflection: Fresnel off and Ray trace on | |
# 7. Transparency: Refraction on, Reflection: Fresnel on and Ray trace on | |
# 8. Reflection on and Ray trace off | |
# 9. Transparency: Glass on, Reflection: Ray trace off | |
# 10. Casts shadows onto invisible surfaces | |
'Ka' => '0.0000 0.0000 0.0000', # ambient colour (r,g,b) | |
'Kd' => '0.5880 0.5880 0.5880', # diffuse colour (r,g,b) | |
'Ks' => '0.0000 0.0000 0.0000', # specular colour (r,g,b) | |
'Ke' => '0.0000 0.0000 0.0000', # emissive colour (r,g,b) | |
'map_Ka' => 'cube.png', # ambient colour texture map | |
'map_Kd' => 'cube.png') # diffuse colour texture map | |
# map_Ks = specular colour texture map | |
# map_Ns = specular highlight component | |
# map_d = alpha texture map | |
# map_bump / bump = bump map | |
# disp = displacement map | |
# decal = stencil decal texture | |
# refl = spherical reflection map | |
v1 = vertex(-0.5, -0.5, 0.5) | |
v2 = vertex( 0.5, -0.5, 0.5) | |
v3 = vertex(-0.5, 0.5, 0.5) | |
v4 = vertex( 0.5, 0.5, 0.5) | |
v5 = vertex(-0.5, 0.5, -0.5) | |
v6 = vertex( 0.5, 0.5, -0.5) | |
v7 = vertex(-0.5, -0.5, -0.5) | |
v8 = vertex( 0.5, -0.5, -0.5) | |
vt1 = vertex_texture(0.0, 0.0) | |
vt2 = vertex_texture(1.0, 0.0) | |
vt3 = vertex_texture(0.0, 1.0) | |
vt4 = vertex_texture(1.0, 1.0) | |
vn1 = vertex_normal( 0.0, 0.0, 1.0) | |
vn2 = vertex_normal( 0.0, 1.0, 0.0) | |
vn3 = vertex_normal( 0.0, 0.0, -1.0) | |
vn4 = vertex_normal( 0.0, -1.0, 0.0) | |
vn5 = vertex_normal( 1.0, 0.0, 0.0) | |
vn6 = vertex_normal(-1.0, 0.0, 0.0) | |
group('cube', material) do |group| | |
group.face([v1,vt1,vn1], [v2,vt2,vn1], [v4,vt4,vn1], [v3,vt3,vn1]) | |
group.face([v3,vt1,vn2], [v4,vt2,vn2], [v6,vt4,vn2], [v5,vt3,vn2]) | |
group.face([v5,vt4,vn3], [v6,vt3,vn3], [v8,vt1,vn3], [v7,vt2,vn3]) | |
group.face([v7,vt1,vn4], [v8,vt2,vn4], [v2,vt4,vn4], [v1,vt3,vn4]) | |
group.face([v2,vt1,vn5], [v8,vt2,vn5], [v6,vt4,vn5], [v4,vt3,vn5]) | |
group.face([v7,vt1,vn6], [v1,vt2,vn6], [v3,vt4,vn6], [v5,vt3,vn6]) | |
end | |
end | |
obj.save('cube') | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
require_relative 'obj' | |
obj = Obj.build('hair_accessory') do | |
# Materials might be completely wrong because nothing I have here seems to render materials. | |
frame_material = material('frame', | |
'Ns' => '10.0000', # specular exponent (0 - 1000) | |
'Ni' => '1.5000', # illumination exponent? | |
'illum' => '2', | |
'Ka' => '0.0 0.0 0.0', | |
'Kd' => '0.0 0.0 0.0', | |
'Ks' => '0.0 0.0 0.0', | |
'Ke' => '0.0 0.0 0.0') | |
glow_material = material('glow', | |
'Ns' => '10.0000', # specular exponent (0 - 1000) | |
'Ni' => '1.5000', # illumination exponent? | |
'illum' => '2', | |
'Ka' => '0.0 0.0 0.0', | |
'Kd' => '1.0 0.0 0.25', | |
'Ks' => '0.0 0.0 0.0', | |
'Ke' => '1.0 0.0 0.25') | |
inner_width = 8 | |
inner_height = 8 | |
outer_width = 10 | |
outer_height = 10 | |
slice_thickness = 0.4 | |
glow_inset = 0.2 | |
inset_width = outer_width - glow_inset * 2 | |
inset_height = outer_height - glow_inset * 2 | |
z_front = slice_thickness * 3 / 2 | |
z_back = -z_front | |
z_front_rim = slice_thickness / 2 | |
z_back_rim = -z_front_rim | |
v_front1 = vertex(-outer_width/2, outer_height/2, z_front) | |
v_front2 = vertex( outer_width/2, outer_height/2, z_front) | |
v_front3 = vertex(-outer_width/2, inner_height/2, z_front) | |
v_front4 = vertex(-inner_width/2, inner_height/2, z_front) | |
v_front5 = vertex( inner_width/2, inner_height/2, z_front) | |
v_front6 = vertex( outer_width/2, inner_height/2, z_front) | |
v_front7 = vertex(-outer_width/2, -inner_height/2, z_front) | |
v_front8 = vertex(-inner_width/2, -inner_height/2, z_front) | |
v_front9 = vertex( inner_width/2, -inner_height/2, z_front) | |
v_front10 = vertex( outer_width/2, -inner_height/2, z_front) | |
v_front11 = vertex(-outer_width/2, -outer_height/2, z_front) | |
v_front12 = vertex( outer_width/2, -outer_height/2, z_front) | |
v_back1 = vertex(-outer_width/2, outer_height/2, z_back) | |
v_back2 = vertex( outer_width/2, outer_height/2, z_back) | |
v_back3 = vertex(-outer_width/2, inner_height/2, z_back) | |
v_back4 = vertex(-inner_width/2, inner_height/2, z_back) | |
v_back5 = vertex( inner_width/2, inner_height/2, z_back) | |
v_back6 = vertex( outer_width/2, inner_height/2, z_back) | |
v_back7 = vertex(-outer_width/2, -inner_height/2, z_back) | |
v_back8 = vertex(-inner_width/2, -inner_height/2, z_back) | |
v_back9 = vertex( inner_width/2, -inner_height/2, z_back) | |
v_back10 = vertex( outer_width/2, -inner_height/2, z_back) | |
v_back11 = vertex(-outer_width/2, -outer_height/2, z_back) | |
v_back12 = vertex( outer_width/2, -outer_height/2, z_back) | |
v_front_rim1 = vertex(-outer_width/2, outer_height/2, z_front_rim) | |
v_front_rim2 = vertex( outer_width/2, outer_height/2, z_front_rim) | |
v_front_rim3 = vertex(-outer_width/2, inset_height/2, z_front_rim) | |
v_front_rim4 = vertex(-inset_width/2, inset_height/2, z_front_rim) | |
v_front_rim5 = vertex( inset_width/2, inset_height/2, z_front_rim) | |
v_front_rim6 = vertex( outer_width/2, inset_height/2, z_front_rim) | |
v_front_rim7 = vertex(-outer_width/2, -inset_height/2, z_front_rim) | |
v_front_rim8 = vertex(-inset_width/2, -inset_height/2, z_front_rim) | |
v_front_rim9 = vertex( inset_width/2, -inset_height/2, z_front_rim) | |
v_front_rim10 = vertex( outer_width/2, -inset_height/2, z_front_rim) | |
v_front_rim11 = vertex(-outer_width/2, -outer_height/2, z_front_rim) | |
v_front_rim12 = vertex( outer_width/2, -outer_height/2, z_front_rim) | |
v_back_rim1 = vertex(-outer_width/2, outer_height/2, z_back_rim) | |
v_back_rim2 = vertex( outer_width/2, outer_height/2, z_back_rim) | |
v_back_rim3 = vertex(-outer_width/2, inset_height/2, z_back_rim) | |
v_back_rim4 = vertex(-inset_width/2, inset_height/2, z_back_rim) | |
v_back_rim5 = vertex( inset_width/2, inset_height/2, z_back_rim) | |
v_back_rim6 = vertex( outer_width/2, inset_height/2, z_back_rim) | |
v_back_rim7 = vertex(-outer_width/2, -inset_height/2, z_back_rim) | |
v_back_rim8 = vertex(-inset_width/2, -inset_height/2, z_back_rim) | |
v_back_rim9 = vertex( inset_width/2, -inset_height/2, z_back_rim) | |
v_back_rim10 = vertex( outer_width/2, -inset_height/2, z_back_rim) | |
v_back_rim11 = vertex(-outer_width/2, -outer_height/2, z_back_rim) | |
v_back_rim12 = vertex( outer_width/2, -outer_height/2, z_back_rim) | |
vt1 = vertex_texture(0.0, 0.0) | |
vt2 = vertex_texture(1.0, 0.0) | |
vt3 = vertex_texture(0.0, 1.0) | |
vt4 = vertex_texture(1.0, 1.0) | |
vn1 = vertex_normal( 0.0, 0.0, 1.0) | |
vn2 = vertex_normal( 0.0, 1.0, 0.0) | |
vn3 = vertex_normal( 0.0, 0.0, -1.0) | |
vn4 = vertex_normal( 0.0, -1.0, 0.0) | |
vn5 = vertex_normal( 1.0, 0.0, 0.0) | |
vn6 = vertex_normal(-1.0, 0.0, 0.0) | |
group('frame', frame_material) do | |
# facing forwards | |
face([v_front2, vt1,vn1], [v_front1, vt2,vn1], [v_front3, vt4,vn1], [v_front6, vt3,vn1]) # front face, top panel | |
face([v_front10, vt1,vn1], [v_front7, vt2,vn1], [v_front11, vt4,vn1], [v_front12, vt3,vn1]) # front face, bottom panel | |
face([v_front4, vt1,vn1], [v_front3, vt2,vn1], [v_front7, vt4,vn1], [v_front8, vt3,vn1]) # front face, left panel | |
face([v_front6, vt1,vn1], [v_front5, vt2,vn1], [v_front9, vt4,vn1], [v_front10, vt3,vn1]) # front face, right panel | |
face([v_back_rim2, vt1,vn1], [v_back_rim1, vt2,vn1], [v_back_rim3, vt4,vn1], [v_back_rim6, vt3,vn1]) # back of inset, top panel | |
face([v_back_rim10, vt1,vn1], [v_back_rim7, vt2,vn1], [v_back_rim11, vt4,vn1], [v_back_rim12, vt3,vn1]) # back of inset, bottom panel | |
face([v_back_rim4, vt1,vn1], [v_back_rim3, vt2,vn1], [v_back_rim7, vt4,vn1], [v_back_rim8, vt3,vn1]) # back of inset, left panel | |
face([v_back_rim6, vt1,vn1], [v_back_rim5, vt2,vn1], [v_back_rim9, vt4,vn1], [v_back_rim10, vt3,vn1]) # back of inset, right panel | |
# facing backwards | |
face([v_back1, vt1,vn3], [v_back2, vt2,vn3], [v_back6, vt4,vn3], [v_back3, vt3,vn3]) # back face, top panel | |
face([v_back7, vt1,vn3], [v_back10, vt2,vn3], [v_back12, vt4,vn3], [v_back11, vt3,vn3]) # back face, bottom panel | |
face([v_back3, vt1,vn3], [v_back4, vt2,vn3], [v_back8, vt4,vn3], [v_back7, vt3,vn3]) # back face, left panel | |
face([v_back5, vt1,vn3], [v_back6, vt2,vn3], [v_back10, vt4,vn3], [v_back9, vt3,vn3]) # back face, right panel | |
face([v_front_rim1, vt1,vn3], [v_front_rim2, vt2,vn3], [v_front_rim6, vt4,vn3], [v_front_rim3, vt3,vn3]) # front of inset, top panel | |
face([v_front_rim7, vt1,vn3], [v_front_rim10,vt2,vn3], [v_front_rim12, vt4,vn3], [v_front_rim11, vt3,vn3]) # front of inset, bottom panel | |
face([v_front_rim3, vt1,vn3], [v_front_rim4, vt2,vn3], [v_front_rim8, vt4,vn3], [v_front_rim7, vt3,vn3]) # front of inset, left panel | |
face([v_front_rim5, vt1,vn3], [v_front_rim6, vt2,vn3], [v_front_rim10, vt4,vn3], [v_front_rim9, vt3,vn3]) # front of inset, right panel | |
# facing upwards | |
face([v_front1, vt1,vn2], [v_front2, vt2,vn2], [v_front_rim2, vt3,vn2], [v_front_rim1, vt4,vn2]) # top edge, front rim | |
face([v_back_rim1, vt1,vn2], [v_back_rim2, vt2,vn2], [v_back2, vt3,vn2], [v_back1, vt4,vn2]) # top edge, back rim | |
face([v_front8, vt1,vn2], [v_front9, vt2,vn2], [v_back9, vt3,vn2], [v_back8, vt4,vn2]) # inside edge, bottom | |
# facing downwards | |
face([v_front12, vt1,vn4], [v_front11, vt2,vn4], [v_front_rim11, vt3,vn4], [v_front_rim12, vt4,vn4]) # bottom edge, front rim | |
face([v_back_rim12, vt1,vn4], [v_back_rim11, vt2,vn4], [v_back11, vt3,vn4], [v_back12, vt4,vn4]) # bottom edge, back rim | |
face([v_front5, vt1,vn4], [v_front4, vt2,vn4], [v_back4, vt3,vn4], [v_back5, vt4,vn4]) # inside edge, top | |
# facing leftwards | |
face([v_front1, vt1,vn6], [v_front_rim1, vt2,vn6], [v_front_rim11, vt3,vn6], [v_front11, vt2,vn6]) # left edge, front rim | |
face([v_back_rim1, vt1,vn6], [v_back1, vt2,vn6], [v_back11, vt3,vn6], [v_back_rim11, vt2,vn6]) # left edge, front rim | |
face([v_back4, vt1,vn6], [v_front4, vt2,vn6], [v_front8, vt3,vn6], [v_back8, vt2,vn6]) # inside edge, left | |
# facing rightwards | |
face([v_front_rim2, vt1,vn5], [v_front2, vt2,vn5], [v_front12, vt3,vn5], [v_front_rim12, vt2,vn5]) # right edge, front rim | |
face([v_back2, vt1,vn5], [v_back_rim2, vt2,vn5], [v_back_rim12, vt3,vn5], [v_back12, vt2,vn5]) # right edge, front rim | |
face([v_front5, vt1,vn5], [v_back5, vt2,vn5], [v_back9, vt3,vn5], [v_front9, vt2,vn5]) # inside edge, left | |
end | |
group('glow', glow_material) do | |
face([v_back_rim5, vt1,vn2], [v_back_rim4, vt2,vn2], [v_front_rim4, vt3,vn2], [v_front_rim5, vt4,vn2]) # top | |
face([v_front_rim9, vt1,vn4], [v_front_rim8, vt2,vn4], [v_back_rim8, vt3,vn4], [v_back_rim9, vt4,vn4]) # bottom | |
face([v_front_rim8, vt1,vn6], [v_front_rim4, vt2,vn6], [v_back_rim4, vt3,vn6], [v_back_rim8, vt4,vn6]) # left | |
face([v_back_rim9, vt1,vn5], [v_back_rim5, vt2,vn5], [v_front_rim5, vt3,vn5], [v_front_rim9, vt4,vn5]) # right | |
end | |
end | |
obj.save('hair_accessory') | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
require_relative 'obj' | |
['Mask', 'Material'].each do |type| | |
obj = Obj.build("Stencil#{type}Scanner") do | |
frame_material = material('StencilScannerFrame', | |
'Ns' => '10.0000', | |
'Ni' => '1.5000', | |
'illum' => '2', | |
'Ka' => '0.0 0.0 0.0', | |
'Kd' => '0.0 0.0 0.0', | |
'Ks' => '0.0 0.0 0.0', | |
'Ke' => '0.0 0.0 0.0') | |
pane_materials = (0..255).map do |i| | |
material("StencilScanner#{type}#{i}", | |
'Ns' => '10.0000', | |
'Ni' => '1.5000', | |
'd' => 0.0, | |
'Tr' => 1.0, | |
'illum' => '4', | |
'Ka' => '0.0 0.0 0.0', | |
'Kd' => '0.9 0.9 0.9', | |
'Ks' => '0.0 0.0 0.0', | |
'Ke' => '0.0 0.0 0.0', | |
'Tf' => '1.0 1.0 1.0', | |
'map_Ka' => '../Textures/StencilScannerGrid.png', | |
'map_Kd' => '../Textures/StencilScannerGrid.png') | |
end | |
pane_size = 0.01 | |
frame_thickness = 0.002 | |
vertex_holder = self | |
vt = (0..16).map{|i| (0..16).map{|j| vertex_texture(i/16.0, (16-j)/16.0)}} | |
vn_front = vertex_normal( 0.0, 0.0, 1.0) | |
vn_back = vertex_normal( 0.0, 0.0, -1.0) | |
vn_right = vertex_normal( 1.0, 0.0, 0.0) | |
vn_left = vertex_normal(-1.0, 0.0, 0.0) | |
vn_top = vertex_normal( 0.0, 1.0, 0.0) | |
vn_bottom = vertex_normal( 0.0, -1.0, 0.0) | |
# panes | |
(0..15).each do |row| | |
(0..15).each do |column| | |
pane_number = row * 16 + column | |
group("StencilScannerPane#{pane_number}", pane_materials[pane_number]) do | |
pane_x1 = pane_size * column | |
pane_x2 = pane_size * (column + 1) | |
pane_y1 = pane_size * (15 - row) | |
pane_y2 = pane_size * (15 - row + 1) | |
pane_v1 = vertex_holder.vertex(pane_x1, pane_y1, 0) | |
pane_v2 = vertex_holder.vertex(pane_x1, pane_y2, 0) | |
pane_v3 = vertex_holder.vertex(pane_x2, pane_y2, 0) | |
pane_v4 = vertex_holder.vertex(pane_x2, pane_y1, 0) | |
vt1 = vt[column][row+1] | |
vt2 = vt[column][row] | |
vt3 = vt[column+1][row] | |
vt4 = vt[column+1][row+1] | |
face([pane_v1,vt1,vn_front], [pane_v2,vt2,vn_front], [pane_v3,vt3,vn_front], [pane_v4,vt4,vn_front]) | |
face([pane_v4,vt4,vn_back], [pane_v3,vt3,vn_back], [pane_v2,vt2,vn_back], [pane_v1,vt1,vn_back]) | |
end | |
end | |
end | |
# frame | |
group('StencilScannerFrame', frame_material) do | |
frame_x = (0..16).map{|column| pane_size * column} | |
frame_y = (0..16).map{|row| pane_size * row} | |
half_frame_thickness = frame_thickness/2 | |
self.define_singleton_method(:cube) do |x1, x2, y1, y2, z1, z2| | |
left_bottom_back = vertex_holder.vertex(x1, y1, z1) | |
left_bottom_front = vertex_holder.vertex(x1, y1, z2) | |
left_top_back = vertex_holder.vertex(x1, y2, z1) | |
left_top_front = vertex_holder.vertex(x1, y2, z2) | |
right_bottom_back = vertex_holder.vertex(x2, y1, z1) | |
right_bottom_front = vertex_holder.vertex(x2, y1, z2) | |
right_top_back = vertex_holder.vertex(x2, y2, z1) | |
right_top_front = vertex_holder.vertex(x2, y2, z2) | |
vt1 = vt2 = vt3 = vt4 = vt[0][0] | |
face([left_bottom_front, vt1,vn_front ], [right_bottom_front,vt2,vn_front ], [right_top_front, vt3,vn_front ], [left_top_front, vt4,vn_front ]) | |
face([right_bottom_back, vt1,vn_back ], [left_bottom_back, vt2,vn_back ], [left_top_back, vt3,vn_back ], [right_top_back, vt4,vn_back ]) | |
face([right_bottom_front,vt1,vn_right ], [right_bottom_back, vt2,vn_right ], [right_top_back, vt3,vn_right ], [right_top_front, vt4,vn_right ]) | |
face([left_bottom_back ,vt1,vn_left ], [left_bottom_front, vt2,vn_left ], [left_top_front, vt3,vn_left ], [left_top_back, vt4,vn_left ]) | |
face([left_top_front ,vt1,vn_top ], [right_top_front ,vt2,vn_top ], [right_top_back, vt3,vn_top ], [left_top_back, vt4,vn_top ]) | |
face([right_bottom_front,vt1,vn_bottom], [left_bottom_front ,vt2,vn_bottom], [left_bottom_back,vt3,vn_bottom], [right_bottom_back,vt4,vn_bottom]) | |
end | |
frame_x.each do |x| | |
cube(x-half_frame_thickness, x+half_frame_thickness, | |
frame_y[0]-half_frame_thickness, frame_y[16]+half_frame_thickness, | |
-half_frame_thickness, half_frame_thickness) | |
end | |
frame_y.each do |y| | |
cube(frame_x[0]-half_frame_thickness, frame_x[16]+half_frame_thickness, | |
y-half_frame_thickness, y+half_frame_thickness, | |
-half_frame_thickness, half_frame_thickness) | |
end | |
end | |
end | |
obj.save("Stencil#{type}Scanner") | |
end | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Obj | |
attr_reader :object_name | |
# name => material info | |
attr_reader :materials | |
attr_reader :vertices | |
attr_reader :vertex_textures | |
attr_reader :vertex_normals | |
attr_reader :groups | |
def initialize(object_name) | |
@object_name = object_name | |
@materials = {} | |
@vertices = [] | |
@vertex_textures = [] | |
@vertex_normals = [] | |
@groups = [] | |
end | |
def self.build(object_name, &block) | |
obj = Obj.new(object_name) | |
obj.instance_eval(&block) | |
obj | |
end | |
def material(name, material_info) | |
@materials[name] = material_info | |
name | |
end | |
def vertex(x, y, z) | |
@vertices << [x,y,z] | |
@vertices.size | |
end | |
def vertex_texture(u, v) | |
@vertex_textures << [u, v] | |
@vertex_textures.size | |
end | |
def vertex_normal(x, y, z) | |
@vertex_normals << [x, y, z] | |
@vertex_normals.size | |
end | |
def group(name, material_name, &block) | |
group = Group.new(name, material_name) | |
@groups << group | |
group.instance_eval(&block) | |
end | |
def save(base_path) | |
obj_path = base_path + '.obj' | |
mtl_path = base_path + '.mtl' | |
mtl_name = File.basename(mtl_path) | |
File.open(obj_path, 'w') do |io| | |
io.puts("o #{@object_name}") | |
io.puts("mtllib #{mtl_name}") | |
@vertices.each do |x,y,z| | |
io.puts("v #{x} #{y} #{z}") | |
end | |
@vertex_textures.each do |u,v| | |
io.puts("vt #{u} #{v}") | |
end | |
@vertex_normals.each do |x,y,z| | |
io.puts("vn #{x} #{y} #{z}") | |
end | |
@groups.each do |group| | |
io.puts("g #{group.name}") | |
io.puts("usemtl #{group.material_name}") | |
group.smoothing_groups.each_with_index do |smoothing_group, index| | |
io.puts("s #{index + 1}") | |
smoothing_group.faces.each do |face_info| | |
face_info_str = face_info.map{|el| el.join('/')}.join(' ') | |
io.puts("f #{face_info_str}") | |
end | |
end | |
end | |
end | |
File.open(mtl_path, 'w') do |io| | |
@materials.each_pair do |name, material_info| | |
io.puts("newmtl #{name}") | |
material_info.each_pair do |key, value| | |
io.puts(" #{key} #{value}") | |
end | |
end | |
end | |
end | |
class Group | |
attr_reader :name | |
attr_reader :material_name | |
attr_reader :smoothing_groups | |
def initialize(name, material_name) | |
@name = name | |
@material_name = material_name | |
@smoothing_groups = [] | |
end | |
def smoothing_group(&block) | |
smoothing_group = SmoothingGroup.new | |
@smoothing_groups << smoothing_group | |
smoothing_group.instance_eval(&block) | |
end | |
# Convenience method allowing omitting the explicit call to `smoothing_group` when there is only one face in the group. | |
# Automatically creates a smoothing group for the single face. | |
def face(*face_info) | |
smoothing_group do | |
face(*face_info) | |
end | |
end | |
end | |
class SmoothingGroup | |
attr_reader :faces | |
def initialize | |
@faces = [] | |
end | |
def face(*face_info) | |
@faces << face_info | |
nil | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment