Created October 11, 2022 13:33
-
-
Save AayushSabharwal/9c76640b960c6726072d42f7ea577e08 to your computer and use it in GitHub Desktop.
Collide.jl demo
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
| 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