JRubyArt has been using the much heralded jruby-9000, but that will only be at a preview release this summer, see tweet:-
@williamthurston We always said "summer 2014"...but we need a bit more for a final version. Preview for August.
— Charles Nutter (@headius) July 7, 2014
Drawolver featuring new libraries, degree precision look up tables, and to_vertex utility for Vec3D:-
# Drawolver: draw 2D & revolve 3D # Example shows how to use the vecmath library, including AppRender utility. # On the ruby side features the use each_cons, a possibly a rare use for this # ruby Enumerable method? # 2010-03-22 - fjenett (somewhat revised by Martin Prout 2014-07-06) load_library :vecmath, :fastmath attr_reader :drawing_mode, :points, :rot_x, :rot_y, :vertices, :renderer def setup size 1024, 768, P3D @renderer = Java::ProcessingVecmath::AppRender.new(self) frame_rate 30 reset_scene end def draw background 0 if (!drawing_mode) translate(width/2, height/2) rotate_x rot_x rotate_y rot_y @rot_x += 0.01 @rot_y += 0.02 translate(-width/2, -height/2) end no_fill stroke 255 points.each_cons(2) { |ps, pe| line ps.x, ps.y, pe.x, pe.y} if (!drawing_mode) stroke 125 fill 120 lights ambient_light 120, 120, 120 vertices.each_cons(2) do |r1, r2| begin_shape(TRIANGLE_STRIP) r1.zip(r2).each { |v1, v2| v1.to_vertex(renderer); v2.to_vertex(renderer)} end_shape end end end def reset_scene @drawing_mode = true @points = [] @rot_x = 0.0 @rot_y = 0.0 end def mouse_pressed reset_scene points << Vec3D.new(mouse_x, mouse_y) end def mouse_dragged points << Vec3D.new(mouse_x, mouse_y) end def mouse_released points << Vec3D.new(mouse_x, mouse_y) recalculate_shape end def recalculate_shape @vertices = [] points.each_cons(2) do |ps, pe| b = (points.last - points.first).normalize! a = ps - points.first dot_product = a.dot b b *= dot_product normal = points.first + b c = ps - normal vertices << [] (0..360).step(12) do |ang| e = normal + c * DegLut.cos(ang) e.z = c.mag * DegLut.sin(ang) vertices.last << e end end @drawing_mode = false end
Sketch demonstrating use of ShapeRender (ShapeRender and AppRender both implement the Render interface which is used by Vec3D (and Vec2D) to_vertex, to_vertex_uv and to_normal methods, see here for earlier version without using ShapeRender, NB: the FastMath of that version has not survived:
# Trefoil, by Andres Colubri # A parametric surface is textured procedurally # by drawing on an offscreen PGraphics surface. # # Features (Vec3D).to_normal(renderer) and (Vec3D).to_vertex_uv(renderer, u, v) # see line 62 for inititialization of renderer where obj is an instance of PShape # renderer = Java::ProcessingVecmath::ShapeRender.new(obj) load_library :vecmath attr_reader :pg, :trefoil def setup size(1024, 768, P3D) texture_mode(NORMAL) noStroke # Creating offscreen surface for 3D rendering. @pg = create_graphics(32, 512, P3D) pg.begin_draw pg.background(0, 0) pg.noStroke pg.fill(255, 0, 0, 200) pg.end_draw # Saving trefoil surface into a PShape3D object @trefoil = create_trefoil(350, 60, 15, pg) end def draw background(0) pg.begin_draw pg.ellipse(rand(0.0 .. pg.width), rand(0.0 .. pg.height), 4, 4) pg.end_draw ambient(250, 250, 250) pointLight(255, 255, 255, 0, 0, 200) push_matrix translate(width/2, height/2, -200) rotate_x(frame_count * PI / 500) rotate_y(frame_count * PI / 500) shape(trefoil) pop_matrix end # Code to draw a trefoil knot surface, with normals and texture # coordinates. Makes of the Vec3D Render interface (uses ShapeRender here). # Adapted from the parametric equations example by Philip Rideout: # http://iphone-3d-programming.labs.oreilly.com/ch03.html # This function draws a trefoil knot surface as a triangle mesh derived # from its parametric equation. def create_trefoil(s, ny, nx, tex) obj = create_shape() obj.begin_shape(TRIANGLES) obj.texture(tex) renderer = Java::ProcessingVecmath::ShapeRender.new(obj) (0 ... nx).each do |j| u0 = j.to_f / nx u1 = (j + 1).to_f / nx (0 ... ny).each do |i| v0 = i.to_f / ny v1 = (i + 1).to_f / ny p0 = eval_point(u0, v0) n0 = eval_normal(u0, v0) p1 = eval_point(u0, v1) n1 = eval_normal(u0, v1) p2 = eval_point(u1, v1) n2 = eval_normal(u1, v1) # Triangle p0-p1-p2 n0.to_normal(renderer) (p0 * s).to_vertex_uv(renderer, u0, v0) n1.to_normal(renderer) (p1 * s).to_vertex_uv(renderer, u0, v1) n2.to_normal(renderer) (p2 * s).to_vertex_uv(renderer, u1, v1) p1 = eval_point(u1, v0) n1 = eval_normal(u1, v0) # Triangle p0-p2-p1 n0.to_normal(renderer) (p0 * s).to_vertex_uv(renderer, u0, v0) n2.to_normal(renderer) (p2 * s).to_vertex_uv(renderer, u1, v1) n1.to_normal(renderer) (p1 * s).to_vertex_uv(renderer, u1, v0) end end obj.end_shape return obj end # Evaluates the surface normal corresponding to normalized # parameters (u, v) def eval_normal(u, v) # Compute the tangents and their cross product. p = eval_point(u, v) tangU = eval_point(u + 0.01, v) tangV = eval_point(u, v + 0.01) tangU -= p tangV -= p tangV.cross(tangU).normalize! # it is easy to chain Vec3D operations end # Evaluates the surface point corresponding to normalized # parameters (u, v) def eval_point(u, v) a = 0.5 b = 0.3 c = 0.5 d = 0.1 s = TAU * u t = (TAU * (1 - v)) * 2 sint = sin(t) cost = cos(t) sint15 = sin(1.5 * t) cost15 = cos(1.5 * t) r = a + b * cost15 x = r * cost y = r * sint z = c * sint15 dv = Vec3D.new( -1.5 * b * sint15 * cost - y, -1.5 * b * sint15 * sint + x, 1.5 * c * cost15) q = dv.normalize # regular normalize creates a new Vec3D for us qvn = Vec3D.new(q.y, -q.x, 0).normalize! # chained Vec3D operations ww = q.cross(qvn) coss = cos(s) sins = sin(s) Vec3D.new( x + d * (qvn.x * coss + ww.x * sins), y + d * (qvn.y * coss + ww.y * sins), z + d * ww.z * sins) end
Sketch demonstrating new ArcBall utility, all that's needed to allow mousewheel zoom, and mouse drag to rotate the cube (this form uses camera 'under the hood' to centralize the cube in sketch viewpane, alternative form translates the sketch to provided coordinates):-
load_library :vecmath attr_reader :my_cube def setup size(600, 600, P3D) smooth(16) ArcBall.init(self) @my_cube = create_shape(BOX, 300, 300, 300) my_cube.set_fill(color(100, 10, 100)) end def draw background(50, 50, 100) define_lights lights stroke(0) shape(my_cube) end def define_lights ambient(20, 20, 20) ambient_light(50, 50, 50) point_light(30, 30, 30, 200, -150, 0) directional_light(0, 30, 50, 1, 0, 0) spot_light(30, 30, 30, 0, 40, 200, 0, -0.5, -0.5, PI / 2, 2) end
No comments:
Post a Comment