The next release of ruby-processing will likely be version 2.5.0 (current release 2.4.4 using jruby-1.7.12). The reason why this will not be a minor release is that I intend to incorporate my pre-compiled vecmath and fastmath libraries as developed on

JRubyArt. Both these libraries have been created as jruby extensions (they are written in java, but can be loaded into the jruby runtime as ruby). Apart from the possible efficiency gains of using pre-compiled code, the compiled version of vecmath greatly simplifies the use of my ArcBall utility (only one line of code is required to include ArcBall functionality in a sketch). What I propose to do is to roll back ruby processing commits to the 2.4.4 release, and set that as the stable branch (for the foreseeable future). I see no compelling reasons to issue anymore 2.4 point releases (eg to bump to jruby-1.7.13, and there seems no likelihood of any further processing 2.0 releases, now development has switched up to

version 3.0).

JRubyArt has been using the much heralded jruby-9000, but that will only be at a preview release this summer, see tweet:-

Drawolver featuring new libraries, degree precision look up tables, and to_vertex utility for Vec3D:-

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:

load_library :vecmath
attr_reader :pg, :trefoil
def setup
size(1024, 768, P3D)
texture_mode(NORMAL)
noStroke
@pg = create_graphics(32, 512, P3D)
pg.begin_draw
pg.background(0, 0)
pg.noStroke
pg.fill(255, 0, 0, 200)
pg.end_draw
@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
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)
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)
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
def eval_normal(u, v)
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!
end
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
qvn = Vec3D.new(q.y, -q.x, 0).normalize!
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