Literate Camera for JRubyArt
Using kamera to provide a literate camera in JRubyArt
Here is another toxiclibs
example sketch, which features a dynamic camera. The center tracks the car in this sketch (mesh.centroid
as a TVec3D
). Here we make use use JRubyArt kamera
method, which provides a more literate version of processings camera. Because kamera
is a ruby method TVec3D and the custom Vect below are both acceptable values (owing to ruby duck-typing). Further the argument order is not important, even though we maintain the original processing order here:-
require 'toxiclibs'
attr_reader :gfx, :physics, :mesh
Vect = Struct.new(:x, :y, :z)
UP = Vect.new(0, 1, 0)
EYE = Vect.new(-100, -50, 80)
def settings
size(680, 382, P3D)
end
def setup
sketch_title 'Crash Test'
@gfx = Gfx::ToxiclibsSupport.new(self)
init_physics
end
def draw
physics.update
# update mesh vertices based on the current particle positions
mesh.vertices.values.each do |v|
v.set(physics.particles.get(v.id))
end
# update mesh normals
mesh.compute_face_normals
# setup lighting
background(51)
lights
directional_light(255, 255, 255, -200, 1000, 500)
specular(255)
shininess(16)
# point camera at mesh centroid (ruby can duck-type)
kamera(
eye: EYE,
center: mesh.compute_centroid,
up: UP
)
# draw coordinate system
gfx.origin(TVec3D.new, 50)
# draw physics bounding box
stroke(255, 80)
no_fill
gfx.box(physics.get_world_bounds)
# draw car
fill(160)
no_stroke
gfx.mesh(mesh, false, 0)
end
def init_physics
@physics = Physics::VerletPhysics3D.new
@mesh = WETriangleMesh.new.addMesh(
STLReader.new.load_binary(
create_input('audi.stl'),
'car',
STLReader::WEMESH
)
)
# properly orient and scale mesh
mesh.rotate_x(HALF_PI)
mesh.scale(8)
# adjust physics bounding box based on car (but bigger)
# and align car with bottom of the new box
bounds = mesh.get_bounding_box
ext = bounds.get_extent
min = bounds.sub(ext.scale(4, 3, 2))
max = bounds.add(ext.scale(4, 3, 2))
physics.set_world_bounds(AABB.from_min_max(min, max))
mesh.translate(TVec3D.new(ext.scale(3, 2, 0)))
# set gravity along negative X axis with slight downward
physics.add_behavior(
Physics::GravityBehavior3D.new(TVec3D.new(-0.1, 0.001, 0))
)
# turn mesh vertices into physics particles
mesh.vertices.values.each do |v|
physics.add_particle(Physics::VerletParticle3D.new(v))
end
# turn mesh edges into springs
mesh.edges.values.each do |e|
a = physics.particles.get(e.a.id)
b = physics.particles.get(e.b.id)
physics.add_spring(Physics::VerletSpring3D.new(a, b, a.distance_to(b), 1))
end
end
def key_pressed
return unless key == 'r'
init_physics
end