Skip to content

Instantly share code, notes, and snippets.

@AayushSabharwal
Created October 11, 2022 13:33
Show Gist options
  • Select an option

  • Save AayushSabharwal/9c76640b960c6726072d42f7ea577e08 to your computer and use it in GitHub Desktop.

Select an option

Save AayushSabharwal/9c76640b960c6726072d42f7ea577e08 to your computer and use it in GitHub Desktop.
Collide.jl demo
using Collide
using PrimitiveCollisions
# using CairoMakie
using GLMakie
using Random
using StaticArrays
CurMakie = GLMakie
function glshape(c::PrimitiveCollisions.Circle)
return CurMakie.Circle(CurMakie.Point(0.0, 0.0), c.radius)
end
function glshape(r::PrimitiveCollisions.Rect)
return CurMakie.Rect((-r.half_ext)..., (2 .* r.half_ext)...)
end
function animate(sim::Collide.Simulation, world::Collide.World; tstep = 0.01, frames = 300)
bodies = Symbol[]
for name in keys(world.entities)
if !isnothing(world[name].shape) && !isinf(world[name].mass)
push!(bodies, name)
end
end
pos = Observable([world[e].position for e in bodies])
shapes = [glshape(world[e].shape) for e in bodies]
rots = Observable([world[e].rotation for e in bodies])
fig = Figure(resolution = (1200, 1200), backgroundcolor = RGBf(0.05, 0.05, 0.07))
ax = Axis(
fig[1, 1],
aspect = 1.0,
backgroundcolor = RGBf(0.11, 0.11, 0.15),
xgridvisible = false,
ygridvisible = false,
xticksvisible = false,
yticksvisible = false,
xticklabelsvisible = false,
yticklabelsvisible = false,
spinewidth = 0.0,
)
meshscatter!(
ax,
lift(x -> [x[1]], pos);
marker = shapes[1],
markersize = 1.0,
rotations = lift(x -> [x[1]], rots),
aspect = 1,
)
for i = 2:length(pos[])
meshscatter!(
ax,
lift(x -> [x[i]], pos);
marker = shapes[i],
markersize = 1.0,
rotations = lift(x -> [x[i]], rots),
)
end
xlims!(ax, -10.0, 10.0)
ylims!(ax, -10.0, 10.0)
record(fig, "render.mp4", 1:frames, framerate = floor(Int, 1 / tstep)) do frame
Collide.step!(sim, tstep, true)
pos[] = [
sim.integrator[getproperty(sim.callback.system, Symbol(e, "_pos"))] for e in bodies
]
rots[] =
[sim.integrator[getproperty(sim.callback.system, Symbol(e, "_θ"))] for e in bodies]
# @show pos rots
end
end
function manybody(circles::Int, rects::Int; seed = 42)
Random.seed!(seed)
w = Collide.World(:w)
push!(
w,
Collide.Entity(
name = :left,
shape = PrimitiveCollisions.Rect(SVector{2}(0.5, 10.0)),
position = SVector{2}(-10.5, 0.0),
mass = Inf,
inertia = Inf,
),
)
push!(
w,
Collide.Entity(
name = :right,
shape = PrimitiveCollisions.Rect(SVector{2}(0.5, 10.0)),
position = SVector{2}(10.5, 0.0),
mass = Inf,
inertia = Inf,
),
)
push!(
w,
Collide.Entity(
name = :top,
shape = PrimitiveCollisions.Rect(SVector{2}(10.0, 0.5)),
position = SVector{2}(0.0, 10.5),
mass = Inf,
inertia = Inf,
),
)
push!(
w,
Collide.Entity(
name = :bottom,
shape = PrimitiveCollisions.Rect(SVector{2}(10.0, 0.5)),
position = SVector{2}(0.0, -10.5),
mass = Inf,
inertia = Inf,
),
)
particles = Collide.Entity[]
rand_in_range(min, max) = rand() * (max - min) + min
rand_position() = SVector{2}(rand_in_range(-9.0, 9.0), rand_in_range(-9.0, 9.0))
rand_velocity() = SVector{2}(rand_in_range(-3.0, 3.0), rand_in_range(-3.0, 3.0))
function rand_circle(i)
rad = rand_in_range(0.2, 1.0 - eps(1.0))
return Collide.Entity(
name = Symbol(:c_, i),
shape = PrimitiveCollisions.Circle(rad),
position = rand_position(),
mass = π * rad * rad,
velocity = rand_velocity(),
bounce = 1.0,
linear_drag = 0.0,
angular_drag = 0.0,
)
end
function rand_rect(i)
dims = (rand_in_range(0.2, 1.0 - eps(1.0)), rand_in_range(0.2, 1.0 - eps(1.0)))
return Collide.Entity(
name = Symbol(:r_, i),
shape = PrimitiveCollisions.Rect(dims...),
position = rand_position(),
rotation = rand_in_range(0.0, 2π),
mass = dims[1] * dims[2],
velocity = rand_velocity(),
angular_velocity = rand_in_range(0.2, 3.0),
bounce = 1.0,
linear_drag = 0.0,
angular_drag = 0.0,
)
end
for i = 1:circles
entt = rand_circle(i)
while true
collides = false
for part in particles
if PrimitiveCollisions.check_collision(
entt.shape,
part.shape,
PrimitiveCollisions.State(
part.position - entt.position,
part.rotation - entt.rotation,
),
).separation <= 0.0
entt = rand_circle(i)
collides = true
break
end
end
if !collides
break
end
end
push!(particles, entt)
end
for i = 1:rects
entt = rand_rect(i)
while true
collides = false
for part in particles
if PrimitiveCollisions.check_collision(
entt.shape,
part.shape,
PrimitiveCollisions.State(
part.position - entt.position,
part.rotation - entt.rotation,
),
).separation <= 0.0
entt = rand_rect(i)
collides = true
break
end
end
if !collides
break
end
end
push!(particles, entt)
end
for part in particles
push!(w, part)
end
return Collide.Simulation(w, [0.0, 0.0]), w
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment