#=
For this example you need to checkout this package:
Pkg.clone("https://github.com/dpsanders/BilliardModels.jl")
Pkg.checkout("BilliardModels", "time_step")
=#
using GLAbstraction, MeshIO, Colors
using GLVisualize, GeometryTypes, Reactive, ColorTypes
window = glscreen()
const interactive_example = true
using BilliardModels
# create the billiard table
const table = Sinai_billiard(0.1)
const max_particles = 8_000
# function that steps through the simulation
function BilliardModels.step!(particles, table, _)
for particle in particles
BilliardModels.step!(particle, table, 0.01)
end
particles
end
# convert a particle to a point
function to_points(data, particles)
@inbounds for (i,p) in enumerate(particles)
data[i] = to_points(p)
end
data
end
to_points(p::BilliardModels.Particle) = Point3f0(p.x.x*2pi, p.x.y*2pi, atan2(p.v.x, p.v.y))
# color lookup table
const colorramp = map(RGBA{Float32}, colormap("RdBu", 100))
function to_color(p::BilliardModels.Particle)
l = (atan2(p.v.x, p.v.y) + pi) / 2pi
colorramp[round(Int, clamp(l, 0, 1) * (length(colorramp)-1))+1]
end
function to_color(data, particles)
@inbounds for (i,p) in enumerate(particles)
data[i] = to_color(p)
end
data
end
cubecamera(window)
x0 = Vector2D(0.3, 0.1)
particles = [BilliardModels.Particle(x0, Vector2D(1.0, 0.001*i)) for i=1:max_particles]
colors = RGBA{Float32}[RGBA{Float32}(1., 0.1, clamp(0.001*i, 0.0, 1.0), 1.0) for i=1:max_particles]
particle_stream = const_lift(BilliardModels.step!, particles, table, bounce(1:10))
v0 = map(to_points, particles)
vc0 = map(to_color, particles)
colors = const_lift(to_color, vc0, particle_stream)
pointstream = const_lift(to_points, v0, particle_stream)
primitive = Circle(Point2f0(0), 0.05f0)
# we know that the particles will only be in this range
boundingbox = AABB{Float32}(Vec3f0(-pi), Vec3f0(2pi))
particles = visualize(
(primitive, pointstream),
color=colors, # set color array. This is per particle
billboard=true, # set billboard to true, making the particles always face the camera
boundingbox=Signal(boundingbox) # set boundingbox, to avoid bb re-calculation when particles update( is expensive)
)
# visualize the boundingbox
boundingbox = visualize(boundingbox, :lines)
# view them (add them to the windows render list)
view(particles, window, camera=:perspective)
view(boundingbox, window, camera=:perspective)
renderloop(window)
Camera
using GLVisualize, GLAbstraction, FileIO, GeometryTypes, Reactive, GLWindow, Colors
window = glscreen()
timesignal = bounce(linspace(0f0,1f0,360))
const interactive_example = true
"""
functions to halve some rectangle
"""
xhalf(r) = SimpleRectangle(r.x, r.y, r.w÷2, r.h)
xhalf2(r) = SimpleRectangle(r.w÷2, r.y, r.w÷2, r.h)
"""
Makes a spiral
"""
function spiral(i, start_radius, offset)
Point3f0(sin(i), cos(i), i/10f0) * (start_radius + ((i/2pi)*offset))
end
# 2D particles
curve_data(i, N) = Point3f0[spiral(i+x/20f0, 1, (i/20)+1) for x=1:N]
# create a spiraling camera path
const camera_path = curve_data(1f0, 360)
# create first screen for the camera
camera_screen = Screen(
window, name=:camera_screen,
area=const_lift(xhalf2, window.area)
)
# create second screen to view the scene
scene_screen = Screen(
window, name=:scene_screen,
area=const_lift(xhalf, window.area)
)
# create an camera eyeposition signal, which follows the path
eyeposition = map(timesignal) do t
len = length(camera_path)
index = round(Int, (t*(len-1))+1) # mod1, just to be on the save side
Vec3f0(camera_path[index])
end
# create the camera lookat and up vector
lookatposition = Signal(Vec3f0(0))
upvector = Signal(Vec3f0(0,0,1))
# create a camera from these
cam = PerspectiveCamera(camera_screen.area, eyeposition, lookatposition, upvector)
"""
Simple visualization of a camera (this could be moved to GLVisualize)
"""
function GLVisualize.visualize(cam::PerspectiveCamera, style, keyword_args)
lookvec, posvec, upvec = map(f->cam.(f), (:lookat, :eyeposition, :up))
positions = map((a,b) -> Point3f0[a,b], lookvec, posvec)
lines = map(lookvec, posvec, upvec) do l,p,u
dir = p-l
right = normalize(cross(dir,u))
Point3f0[
l,p,
p, p+u,
p, p+right
]
end
colors = RGBA{Float32}[
RGBA{Float32}(1,0,0,1),
RGBA{Float32}(1,0,0,1),
RGBA{Float32}(0,1,0,1),
RGBA{Float32}(0,1,0,1),
RGBA{Float32}(0,0,1,1),
RGBA{Float32}(0,0,1,1),
]
poses = visualize((Sphere(Point3f0(0), 0.05f0), positions))
lines = visualize(lines, :linesegment, color=colors)
Context(poses, lines)
end
# add the camera to the camera screen as the perspective camera
camera_screen.cameras[:perspective] = cam
# something to look at
cat = visualize(GLNormalMesh(loadasset("cat.obj")))
# visualize the camera path
camera_points = visualize(
(Circle(Point2f0(0), 0.03f0), camera_path),
color=RGBA{Float32}((Vec3f0(0,206,209)/256)..., 1f0), billboard=true
)
camera_path_line = visualize(camera_path, :lines)
# view everything on the appropriate screen.
# we need to copy the cat, because view inserts the camera into the
# actual render object. this is sub optimal and will get changed!
# Note, that this is a shallow copy, so the actual data won't be copied,
# just the data structure that holds the camera
view(copy(cat), camera_screen, camera=:perspective)
view(copy(cat), scene_screen, camera=:perspective)
view(visualize(cam), scene_screen, camera=:perspective)
view(camera_points, scene_screen, camera=:perspective)
view(camera_path_line, scene_screen, camera=:perspective)
renderloop(window)
Search
From here you can search these documents. Enter
your search terms below.