#ドット描画型 class Draw_3d_1 attr_accessor :viewport #初期化 def initialize(width = 640, height = 480) @width = width @height = height @viewport = Viewport.new(0,0,@width, @height) @sprite = Sprite.new(@viewport) @sprite.bitmap = Bitmap.new(@width, @height) @vanish_x = @width / 2 @vanish_y = @height / 2 @vanish_z = -1*[@width, @height].max @color = Color.new(255,255,255,255) @dotmap = Array.new @rights = Hash.new @check = false end #更新 def update return unless @check @check = false @sprite.bitmap.clear @dotmap.each{|num| next if num == nil num.each{|pos| next if pos[2] > -@vanish_z - 1 tx = (@vanish_x - pos[0]) * pos[2] / (@vanish_z + pos[2]) + pos[0] ty = (@vanish_y - pos[1]) * pos[2] / (@vanish_z + pos[2]) + pos[1] key = tx*1000+ty next if tx < 0 || tx > @width || ty < 0 || ty > @height next if @rights.has_key?(key) && @rights[key] > pos[2] @rights[key] = pos[2] @sprite.bitmap.set_pixel(tx, ty, pos[3]) } } @rights.clear end #点描画 def point(x, y, z, number = 0, color = @color) if @dotmap[number] == nil @dotmap[number] = Array.new end @dotmap[number].push [x,y,z,color] @check = true end #線描画 def line(x, y, z, tx, ty, tz, number = 0, color = @color) sx = (tx-x) sy = (ty-y) sz = (tz-z) max = [sx.abs, sy.abs, sz.abs].max +1 for i in 0...max point(x+sx*i/max, y+sy*i/max, z+sz*i/max, number, color) end end #三角形描画 def triangle(x0,y0,z0, x1,y1,z1, x2,y2,z2, number=0,color=@color) line(x0, y0, z0, x1, y1, z1, number, color) line(x0, y0, z0, x2, y2, z2, number, color) line(x1, y1, z1, x2, y2, z2, number, color) end #四角形描画 def square(x0,y0,z0, x1,y1,z1, x2,y2,z2, x3,y3,z3,number=0,color=@color) line(x0, y0, z0, x1, y1, z1, number, color) line(x0, y0, z0, x2, y2, z2, number, color) line(x1, y1, z1, x3, y3, z3, number, color) line(x2, y2, z2, x3, y3, z3, number, color) end #矩形描画 def rectangle(x0,y0,z0, width, height, number = 0, color = @color) x1, y1 = x0 + width, y0 + height line(x0, y0, z0, x1, y0, z0, number, color) line(x0, y0, z0, x0, y1, z0, number, color) line(x1, y1, z0, x1, y0, z0, number, color) line(x1, y1, z0, x0, y1, z0, number, color) end #立方体描画 def solidness(x0,y0,z0, width, height, depth, number = 0, color = @color) x1, y1 , z1 = x0 + width, y0 + height, z0 + depth line(x0, y0, z0, x1, y0, z0, number, color) line(x0, y0, z0, x0, y1, z0, number, color) line(x0, y0, z0, x0, y0, z1, number, color) line(x1, y0, z0, x1, y0, z1, number, color) line(x1, y0, z0, x1, y1, z0, number, color) line(x0, y1, z0, x0, y1, z1, number, color) line(x0, y1, z0, x1, y1, z0, number, color) line(x0, y0, z1, x0, y1, z1, number, color) line(x0, y0, z1, x1, y0, z1, number, color) line(x1, y1, z0, x1, y1, z1, number, color) line(x1, y0, z1, x1, y1, z1, number, color) line(x0, y1, z1, x1, y1, z1, number, color) end #文字転写 def text(x, y, z, text, number = 0, size =22, color = @color) bitmap = Bitmap.new(1,1) bitmap.font.size = size text_size = bitmap.text_size(text) width = text_size.width height = text_size.height bitmap = Bitmap.new(width, height) bitmap.font.size = size bitmap.font.color = color bitmap.draw_text(0, 0, width, height, text) picture(x, y, z, bitmap, number) end #画像転写 def picture(x, y, z, bitmap, number = 0) width = bitmap.width height = bitmap.height for sx in 0...width for sy in 0...height color = bitmap.get_pixel(sx, sy) if color.alpha != 0 point(sx+x-bitmap.width/2,sy+y-bitmap.height/2,z, number,color) end end end end #ドット消去 def clear(number = nil) if number == nil @dotmap.clear else @dotmap[number].clear end @check = true end #グループの統合 def join(number1, number2) @dotmap[number2] += @dotmap[number1].clone clear(number1) end #点移動 def move_point(vx, vy, vz, number = 0, pos = 0) x = @dotmap[number][pos][0] += vx y = @dotmap[number][pos][1] += vy z = @dotmap[number][pos][2] += vz color = @dotmap[number][pos][3] @dotmap[number][pos] = [x,y,z,color] @check = true end #線移動 def move(vx, vy, vz, number = 0, pos = 0) for i in 0...@dotmap[number].size move_point(vx, vy, vz, number, pos + i) end end #直接移動 def direct_move(vx, vy, vz, number = 0, pos = 0) color = @dotmap[number][pos][3] @dotmap[number][pos] = [vx,vy,vz,color] @check = true end #X軸回転 def roll_x(rad, number = 0, ox = nil, oy = nil, oz = nil) return if @dotmap[number].size < 2 pos = 0 oy = @dotmap[number][0][1] if oy==nil oz = @dotmap[number][0][2] if oz==nil rad = rad * Math::PI / 180 for i in 0...@dotmap[number].size a = @dotmap[number][i][1] - oy b = @dotmap[number][i][2] - oz vx = @dotmap[number][i][0] vy = a*Math.cos(rad) + b*Math.sin(rad) + oy vz = -a*Math.sin(rad) + b*Math.cos(rad) + oz direct_move(vx, vy, vz, number, pos + i) end end #Y軸回転 def roll_y(rad, number = 0, ox = nil, oy = nil, oz = nil) return if @dotmap[number].size < 2 pos = 0 ox = @dotmap[number][0][0] if ox==nil oz = @dotmap[number][0][2] if oz==nil rad = rad * Math::PI / 180 for i in 0...@dotmap[number].size a = @dotmap[number][i][0] - ox b = @dotmap[number][i][2] - oz vx = a*Math.cos(rad) + b*Math.sin(rad) + ox vy = @dotmap[number][i][1] vz = -a*Math.sin(rad) + b*Math.cos(rad) + oz direct_move(vx, vy, vz, number, pos + i) end end #Z軸回転 def roll_z(rad, number = 0, ox = nil, oy = nil, oz = nil) return if @dotmap[number].size < 2 pos = 0 ox = @dotmap[number][0][0] if ox==nil oy = @dotmap[number][0][1] if oy==nil rad = rad *Math::PI / 180 for i in 0...@dotmap[number].size a = @dotmap[number][i][0] - ox b = @dotmap[number][i][1] - oy vx = a*Math.cos(rad) + b*Math.sin(rad) + ox vy = -a*Math.sin(rad) + b*Math.cos(rad) + oy vz = @dotmap[number][i][2] direct_move(vx, vy, vz, number, pos + i) end end end