Sketch also makes use of AppRender to make for direct conversion from Vec3D to vertex/normal.
# bezier patch By Marius Watz: # http://www.openprocessing.org/sketch/57709 # Normal calculation added by Andres Colubri # Direct port of sample code by Paul Bourke. # Original code: http://paulbourke.net/geometry/bezier/ # # hit "spacebar" to generate a new shape and save current # NI = 4 NJ = 5 RESI = NI * 10 RESJ = NJ * 10 attr_accessor :outp, :inp, :normp, :auto_normals, :renderer def setup sketch_title 'Bezier Patch' ArcBall.init(self) @auto_normals = false @renderer = AppRender.new(self) build end def draw background(255) smooth(8) lights no_stroke fill(192, 192, 192) define_lights lights (0...RESI - 1).each do |i| begin_shape(QUAD_STRIP) (0...RESJ).each do |j| normp[i][j].to_normal(renderer) unless auto_normals outp[i][j].to_vertex(renderer) outp[i + 1][j].to_vertex(renderer) end end_shape end end def settings size(1024, 768, P3D) end def define_lights ambient_light(60, 60, 60) point_light(30, 30, 30, 0, 0, 0) directional_light(40, 40, 50, 1, 0, 0) spot_light(30, 30, 30, 0, 40, 200, 0, -0.5, 0.5, PI / 2, 2) end def key_pressed return unless key == ' ' save_frame('bez_patch.png') build end def build @outp = [] @normp = [] @inp = [] uitang = Vec3D.new ujtang = Vec3D.new (0...NI).each do |i| row = [] (0...NJ).each do |j| row << Vec3D.new(i, j, (rand * 6) - 3) end inp << row end (0...RESI).each do |i| mui = i.fdiv(RESI - 1) row = [] row_n = [] (0...RESJ).each do |j| muj = j.fdiv(RESJ - 1) vect = Vec3D.new uitang = Vec3D.new ujtang = Vec3D.new (0...NI).each do |ki| bi = bezier_blend(ki, mui, NI) dbi = d_bezier_blend(ki, mui, NI) (0...NJ).each do |kj| bj = bezier_blend(kj, muj, NJ) dbj = d_bezier_blend(kj, muj, NJ) vect.x += (inp[ki][kj].x * bi * bj) vect.y += (inp[ki][kj].y * bi * bj) vect.z += (inp[ki][kj].z * bi * bj) uitang.x += (inp[ki][kj].x * dbi * bj) uitang.y += (inp[ki][kj].y * dbi * bj) uitang.z += (inp[ki][kj].z * dbi * bj) ujtang.x += (inp[ki][kj].x * bi * dbj) ujtang.y += (inp[ki][kj].y * bi * dbj) ujtang.z += (inp[ki][kj].z * bi * dbj) end end vect += Vec3D.new(-NI / 2, -NJ / 2, 0) vect *= 100 row << vect uitang.normalize! row_n << uitang.cross(ujtang.normalize) end @outp << row @normp << row_n end end def bezier_blend(k, mu, n) blend = 1.0 nn = n kn = k nkn = n - k while (nn >= 1) blend *= nn nn -= 1 if kn > 1 blend = blend.fdiv(kn) kn -= 1 end if nkn > 1 blend = blend.fdiv(nkn) nkn -= 1 end end blend *= mu**k.to_f if k > 0 return blend * (1 - mu)**(n - k).to_f if n - k > 0 blend end def d_bezier_blend(k, mu, n) dblendf = 1.0 nn = n kn = k nkn = n - k while (nn >= 1) dblendf *= nn nn -= 1 if kn > 1 dblendf = dblendf.fdiv(kn) kn -= 1 end if nkn > 1 dblendf = dblendf.fdiv(nkn) nkn -= 1 end end fk = 1 dk = 0 fnk = 1 dnk = 0 if k > 0 fk = mu**k.to_f dk = k * mu**(k - 1).to_f end if n - k > 0 fnk = (1 - mu)**(n - k).to_f dnk = (k - n) * (1 - mu)**(n - k - 1).to_f end dblendf * (dk * fnk + fk * dnk) end
No comments:
Post a Comment