JuliaGL / GLVisualize.jl

Visualization library written in Julia and OpenGL
Other
248 stars 36 forks source link

how to update frame #78

Closed musm closed 8 years ago

musm commented 8 years ago

Hi Simon, I'm kinda struggling to figure how to use GLVisualize from the docs. I would like to display some points them update their position and update the frame after the position is updated. (Also how can I change the background color?)

I know this isn't really an issue but help is much appreciated

using GLVisualize, GeometryTypes

res = (800,600)
window = glscreen(resolution=res)

num = 100 # number of particles to simulate
# distribute particle x,y locations randomly on the screen
x = res[1]*1/8 + (res[1]*6/8)*rand(Float32,num)
y = res[2]*1/8 + (res[2]*6/8)*rand(Float32,num)

a = Point2f0[Point2f0(xi,yi) for (xi,yi) in zip(x,y)] 
points = visualize((Circle(Point2f0(0),5f0),a))
view(points, window)
@async renderloop(window)

s = rand(Float32,num)

for i in eachindex(x)
    velx = 0
    vely = 0
    for j in eachindex(y)
        dx = x[j] - x[i]
        dy = y[j] - x[i]
        distsq = dx*dx + dy*dy + 1
        velx = velx + dx/distsq
        vely = vely + dy/distsq
    end
    x[i] = x[i] + velx
    y[i] = y[i] + vely

    #  draw updated  ellipse/circle position
    a[i] = Point2f0(x[i],y[i])
    point = visualize((Circle(Point2f0(0),5f0),a))
    view(point, window)

end
SimonDanisch commented 8 years ago

Does the bouncy example help: http://www.glvisualize.com/examples/sprites/#bouncy ? Easiest way to animate is via signals. Usually, you should call view/visualize only one time per object, even if its animated! Be sure to also checkout the performance tips;)

Best, Simon On 19 Mar 2016 22:08, "musmo" notifications@github.com wrote:

Hi Simon, I'm kinda struggling to figure how to use GLVisualize from the docs. I would like to display some points them update their position and update the frame after the position is updated. (Also how can I change the background color?)

I know this isn't really an issue but help is much appreciated

using GLVisualize, GeometryTypes

res = (800,600) window = glscreen(resolution=res)

num = 100 x = res[1]_1/8 + (res[1]_6/8)_rand(Float32,num) y = res[2]_1/8 + (res[2]_6/8)_rand(Float32,num)

a = Point2f0[Point2f0(xi,yi) for (xi,yi) in zip(x,y)] points = visualize((Circle(Point2f0(0),5f0),a))view(points, window)@async renderloop(window)

s = rand(Float32,num) for i in eachindex(x) velx = 0 vely = 0 for j in eachindex(y) dx = x[j] - x[i] dy = y[j] - x[i] distsq = dx_dx + dy_dy + 1 velx = velx + dx/distsq vely = vely + dy/distsq end x[i] = x[i] + velx y[i] = y[i] + vely

# update and draw ellipse/circle
a[i] = Point2f0(x[i],y[i])
point = visualize((Circle(Point2f0(0),5f0),a))
view(point, window)

end

— You are receiving this because you are subscribed to this thread. Reply to this email directly or view it on GitHub https://github.com/JuliaGL/GLVisualize.jl/issues/78

musm commented 8 years ago

Thanks for the reference, following it I kinda have something that works, although not exactly what I envisioned.

using GLVisualize, GeometryTypes, Reactive, GLAbstraction, Colors

function main()
res = (800,600)
window = glscreen(resolution=res)
timesignal = loop(linspace(0, 1, 10))
num = 500

x = res[1]*1/10 + (res[1]*8/10)*rand(Float32,num)
y = (res[2]/2)*ones(Float32,num)
s = -1 + 2*rand(Float32,num)

function solve_particles(pos_vel, _)
    positions, velocity = pos_vel
    for i in eachindex(positions)       
        velx = 0
        vely = 0
        posi = positions[i]
        for j in eachindex(positions)
            posj = positions[j]
            dx = posj[1] - posi[1]
            dy = posj[2] - posi[2]
            distsq = dx*dx + dy*dy + 1
            velx = velx - s[j]*dy/distsq
            vely = vely + s[j]*dx/distsq
        end
        positions[i] = Point2f0(posi[1] + velx, posi[2] + vely)
    end
    positions, velocity
end

# t = const_lift(*, timesignal, 20f0)

# add some color
# color_ramp = colormap("Blues", 50)
# colors = RGBA{Float32}[color_ramp[rand(1:50)] for i=1:num]

start_position = Point2f0[Point2f0(xi,yi) for (xi,yi) in zip(x,y)]
position_velocity = foldp(solve_particles, (start_position, zeros(Float32,num)), timesignal)

circle = HyperSphere(Point2f0(0), 2f0)
vis = visualize((circle, map(first, position_velocity)))
view(vis, window, camera=:orthographic_pixel)

renderloop(window)
end

A couple of questions: (1) How to set the background color to black (2) How does timesignal work? Changing its parameters doesn't seem to have any effect... (3) Although this animates the particles, what I really wanted is for the each update to be drawn on screen, with the particles having some transparency; so that you can see the particle's streak.
(4) What's the recommended workflow? Right now I just call include("script.jl"); main() to test new ideas.
(5) I don't really understand why solve_particles needs an empty second argument. I tried without, but the line position_velocity = foldp(solve_particles, (start_position, zeros(Float32,num)), timesignal) keeps crashing if I didn't have it just in the bouncy example.

SimonDanisch commented 8 years ago

That looks pretty cool :) If you don't mind, can we add this as an example after we figured everything out?

Give me a second, I'll update your example to address 1-5 ;)

SimonDanisch commented 8 years ago

Okay here it is:

using GLVisualize, GeometryTypes, Reactive, GLAbstraction, Colors,GLWindow

# time is not needed for this simulation, but since Reactive calls
# it with the time parameter (in the foldp call in l49), we need to have this signature
function solve_particles(pos_vel_s, time)
    solve_particles(pos_vel_s)
end
function solve_particles(pos_vel_s)
    positions, velocity, s = pos_vel_s
    for i in eachindex(positions)
        velx = 0
        vely = 0
        posi = positions[i]
        for j in eachindex(positions)
            posj = positions[j]
            dx = posj[1] - posi[1]
            dy = posj[2] - posi[2]
            distsq = dx*dx + dy*dy + 1
            velx = velx - s[j]*dy/distsq*10f0
            vely = vely + s[j]*dx/distsq*10f0
        end
        positions[i] = Point2f0(posi[1] + velx, posi[2] + vely)
    end
    positions, velocity, s
end

"""
This code should be executed only one time per julia session!!
If you accidantly close the window, you can call this again.
"""
function init(res=(800,600))
    # giving the window a transparent background color makes it transparent to
    # the previous frame. It's arguable, if that's really how things should be,
    # but that's how it currently works ;)
    window = glscreen(resolution=res, background=RGBA(0,0,0,0))
    @async renderloop(window)
    window
end

function main(window)
    res = widths(window)
    # generates a signal which updates every 1/60s and samples a new value from linspace
    # if 1 is reached, it will start at 0 again.
    timesignal = loop(linspace(0, 1, 10))
    num = 500

    x = res[1]*1/10 + (res[1]*8/10)*rand(Float32,num)
    y = (res[2]/2)*ones(Float32,num)
    s = -1 + 2*rand(Float32,num)

    start_position = Point2f0[Point2f0(xi,yi) for (xi,yi) in zip(x,y)]
    # foldp calls solve_particles with the startvalue, v0, and the argument, timesignal, every time
    # time signal updates. https://github.com/JuliaLang/Reactive.jl/blob/master/doc/index.md
    # alternatively, you could call foldp like this:
    # foldp((v0, t) -> solve_particles(v0), startvalue, timesignal)
    position_velocity = foldp(solve_particles, (start_position, zeros(Float32,num), s), timesignal)

    circle = HyperSphere(Point2f0(0), 2f0)
    # boundingbox is still a very expensive operation, so if you don't need it
    # you can simply set it to nothing.
    vis = visualize(
        (circle, map(first, position_velocity)),
        boundingbox=nothing,
        color=RGBA{Float32}(1,1,1,0.5),
        stroke_color=RGBA{Float32}(0,0,0,0), # stroking with transparent black makes the white edge go away
        stroke_width=0.5f0
    )
    empty!(window.renderlist) # clears the renderlist from previous visualizations, so that you can call main() multiple times
    view(vis, window, camera=:orthographic_pixel)
end

#=
workflow in Julia REPL:
> include("simulation.jl")
> window = init()
> main(window)
> redefine main/solve_particles
> include("simulation.jl") # if you have the changes in the file
> main() # call again! If you only changed solve_particles, you don't even have to call main again
=#

for it to work you need to be on master, which involves checking out a few other packages:

Pkg.checkout("GLVisualize")
Pkg.checkout("GLAbstraction")
Pkg.checkout("GLWindow")
Pkg.checkout("GeometryTypes")

As you can see in the bouncy and billboard example, you can use arbitrary Arrays of colors (Images) as particles ;)

SimonDanisch commented 8 years ago

By the way, if you have feedback about the API and how signals work, feel free to criticize anything. Nothing is really set in stone yet and I'm always looking forward to improve things!

musm commented 8 years ago

Hi, thanks very much Simon! It doesn't look bad. I was hoping to update the docs (I can add this example and rearrange the docs to make things easier sometime this week). I have been trying to better understand and learn the API by translating processing codes. To me a lot of things are annoying/confusing at the moment. (e.g. having to specify Float32 in certain places to make them work and the names of objects are kinda criptic: Point2f0 e.g. although this just needs better documentation and clarification on how all the packages work together in harmony and their conventions).

(1) It looks like you set the background to be transparent and that is the only reason why after each update the particles from the previous time remain on screen. For this reason also the line: empty!(window.renderlist) doesn't actually clear the screen when running main(window) multiple times (unless you resize the window). Thus the original question remains "Although this animates the particles, what I really wanted is for the each update to be drawn on screen, with the particles having some transparency; so that you can see the particle's streak." This makes in it impossible to have a background color (e.g. red,gray,blue).

(2) can you explain what you mean here

 # generates a signal which updates every 1/60s and samples a new value from linspace
 # if 1 is reached, it will start at 0 again.
 timesignal = loop(linspace(0, 1, 10)) 

you create a linspace from 0 to 1 using 10 points, how does this translate to 1/60s ? I have tried changing the parameters here and observing their effect, but I wasn't really able to determine how it changes the simulation frame rate and time scale and such...

(3) How can I poll for keypresses?

    if  window.inputs[:buttons_pressed] == :s 
        @show "yay"
         # save .jpg of current frame
    end

(4) Which settings do you reccomend to get good quality/and good performance image image

Depending on which settings I choose the simulation can be faster/slower. (For 1000 particles, it can be slow surprisingly)

(unrelated) (4) None of the Gadfly examples work. (I get libpango not defined..)

using GLVisualize, GeometryTypes, Reactive, GLAbstraction, Colors, GLWindow

function solve_particles(pos_vel_s, time)
    solve_particles(pos_vel_s)
end
function solve_particles(pos_vel_s)
    positions, velocity, s = pos_vel_s
    for i in eachindex(positions)
        velx = 0.0
        vely = 0.0
        posi = positions[i]
        for j in eachindex(positions)
            posj = positions[j]
            dx = posj[1] - posi[1]
            dy = posj[2] - posi[2]
            distsq = dx*dx + dy*dy + 1.0
            velx = velx - s[j]*dy/distsq
            vely = vely + s[j]*dx/distsq
        end
        positions[i] = Point2f0(posi[1] + velx, posi[2] + vely)
    end
    positions, velocity, s
end

function init(res=(800,600))
    window = glscreen("vortex",resolution=res, background=Gray(0.2))
    @async renderloop(window)
    window
end

function main(window)
    res = widths(window)
    timesignal = bounce(linspace(0, 1, 2))
    num = 1000

    x = res[1]*1/10 + (res[1]*8/10)*rand(num)
    y = (res[2]/2)*ones(num)
    s = 4*(-1 + 2*rand(num))

    start_position = Point2f0[Point2f0(xi,yi) for (xi,yi) in zip(x,y)]
    position_velocity = foldp(solve_particles, (start_position, zeros(Float32,num), s), timesignal)

    circle = HyperSphere(Point2f0(0), 2f0)
    # boundingbox is still a very expensive operation, so if you don't need it
    # you can simply set it to nothing.
    vis = visualize(
        (circle, map(first, position_velocity)),
        boundingbox=nothing,
        color=RGBA(1,1,1,0.75)
    )
    empty!(window.renderlist) # clears the renderlist from previous visualizations, so that you can call main() multiple times
    view(vis, window, camera=:orthographic_pixel)
end
SimonDanisch commented 8 years ago

(1)

silly me, of course this doesn't work as you expect it... Will work on a fix tomorrow!

(2) can you explain what you mean here

You can't really change the speed there. What you can do though is this:

timesignal = Input(0)
while ...
    push!(timesignal, new_value)
    render_frame(window)
    sleep(as_long_as_you_want)
end

(3) How can I poll for keypresses?

map(window.inputs[:unicode_input]) do key
    if key == 's'
        screenshot(window, path="x.png")
    end
end

(4) Which settings do you reccomend to get good quality/and good performance

What kind of quality problems do you have? You shouldn't fix them over these settings, as they shouldn't really influence the quality notably. As you notice, they can heavily influence your performance though. Since I do the anti-aliasing of the particles for every pixel with a non trivial formula, setting hardware anti-aliasing to 8x (which sort of means having 8 times as many pixels per calculation) can make this calculation much much slower.

I'm still a bit surprised, since 1000 particles should always render just fine on a decent gpu... Have you set boundingbox=nothing ?

(5)

I'm not sure what's going on with Gadfly. This is not my issue and hasn't been fixed for ages...

musm commented 8 years ago

Thank you! Actually if key == 's' doesn't work since key is an array. I modified it to:

    map(window.inputs[:unicode_input]) do key
        if 's' in key
            screenshot(window, path="x.jpg")
            println("saving screenshow")
        end
    end

and I added to to the end of main() (It doesn't work if I add this to init()) Is there a way to get just the key not the array?

In any case I have some imagemagick errors I need to fix julia> WARNING: ErrorException("no encode delegate for this image formatMIFF' @ error/constitute.c/WriteImage/1167") in error at C:\Users\Mustafa.julia\v0.4\ImageMagick\src\libmagickwand.jl:153 in writeimage at C:\Users\Mustafa.julia\v0.4\ImageMagick\src\libmagickwand.jl:250`

Sorry for the slew of questions!

SimonDanisch commented 8 years ago

You can use:

map(window.inputs[:keyboard_buttons]) do kam
    key, action, mods = kam
    if key = GLFW.KEY_S
        ...
    end
end

callback: https://github.com/JuliaGL/GLWindow.jl/blob/master/src/callbacks.jl#L51 glfw key: https://github.com/JuliaGL/GLFW.jl/blob/master/src/glfw3.jl#L50

ImageMagick is a bit annoying.. You might have some luck with this PR: https://github.com/JuliaIO/ImageMagick.jl/pull/28 Just check it out with git and rebuild with Pkg.build("ImageMagick")

SimonDanisch commented 8 years ago

by the way, you need to wrap a preserver(signal) around signals that are not used and go out of scope (e.g, when you do the map(window.inputs[:keyboard_buttons]) in init)

musm commented 8 years ago

Regarding (5) turning on FXAA greatly reduced all the jagged edges in the 3D examples. However, the animation is not smooth for this 2D example, with 1000 particles, the particles stutter a bit as they are simulated (it should be buttery smooth for 1000 particles)

Also if you wrap a preserver(signal) and println() is used inside I think this hangs up the repl...

Not too sure how to apply this in the current example...

timesignal = Input(0)
while ...
    push!(timesignal, new_value)
    render_frame(window)
    sleep(as_long_as_you_want)
end
SimonDanisch commented 8 years ago

Regarding (5) turning on FXAA greatly reduced all the jagged edges in the 3D examples.

Yeah 3D is quite the different case. I'm quite that the quality is so bad, but some decisions made it impossible to activate hardware aliasing and other solutions also don't work that well currently. I have different ideas on how to fix it and at some point I should really get it over with!

Also if you wrap a preserver(signal) and println() is used inside I think this hangs up the repl...

That shouldn't be related, but println inside signals is still quite problematic :( Or do you have a reproducible example, where println only hangs, when preserve is used? I actually wrote SignalView to better debug signals!

You can do something like this:

# main stays as is

function init(res=(800,600))
    # giving the window a transparent background color makes it transparent to
    # the previous frame. It's arguable, if that's really how things should be,
    # but that's how it currently works ;)
    window = glscreen(resolution=res, background=RGBA(0,0,0,0))
    timesignal = Signal(0)
    speed = Signal(1/60)
    @async while isopen(window)
        push!(timesignal, 0) # value doesn't matter
        render_frame(window)
        sleep(value(speed))
    end
    window, timesignal, speed
end

#workflow in Julia REPL:
#=
include("simulation.jl")
window, t, speed = init()
main(window, t)
#redefine main/solve_particles
include("simulation.jl") # if you have the changes in the file
main() # call again! If you only changed solve_particles, you don't even have to call main again
push!(speed, 1/20) # change speed
=#
SimonDanisch commented 8 years ago

Here's the frame cleaning code:

using GLVisualize, GeometryTypes, Reactive, GLAbstraction, Colors,GLWindow, ModernGL

# time is not needed for this simulation, but since Reactive calls
# it with the time parameter (in the foldp call in l49), we need to have this signature
function solve_particles(pos_vel_s, time)
    solve_particles(pos_vel_s)
end
function solve_particles(pos_vel_s)
    positions, velocity, s = pos_vel_s
    for i in eachindex(positions)
        velx = 0.0
        vely = 0.0
        posi = positions[i]
        for j in eachindex(positions)
            posj = positions[j]
            dx = posj[1] - posi[1]
            dy = posj[2] - posi[2]
            distsq = dx*dx + dy*dy + 1.0
            velx = velx - s[j]*dy/distsq
            vely = vely + s[j]*dx/distsq
        end
        positions[i] = Point2f0(posi[1] + velx, posi[2] + vely)
    end
    positions, velocity, s
end

"""
Clears the image of the window to `color`
"""
function clear_frame!(window, color=RGB(1,0,0))
    # this works with every color, even hsl
    glClearColor(red(color), green(color), blue(color), 1)
    GLWindow.clear_all!(window)
end

"""
Resets the state of a window
"""
function reset!(window, color=RGB(1,0,0))
    clear_frame!(window, color)
    empty!(window.renderlist)
end
"""
This code should be executed only one time per julia session!!
If you accidantly close the window, you can call this again.
"""
function init(res=(800,600))
    # giving the window a transparent background color makes it transparent to
    # the previous frame. It's arguable, if that's really how things should be,
    # but that's how it currently works ;)
    window = glscreen(resolution=res, background=RGBA(0,0,0,0))
    timesignal = Signal(0)
    speed = Signal(1/60)

    glClear(GL_COLOR_BUFFER_BIT)
    @async while isopen(window)
        push!(timesignal, 0) # value doesn't matter
        render_frame(window)
        sleep(value(speed))
    end
    window, timesignal, speed
end

function main(window, timesignal)
    res = widths(window)
    # generates a signal which updates every 1/60s and samples a new value from linspace
    # if 1 is reached, it will start at 0 again.
    timesignal = loop(linspace(0, 1, 10))
    num = 500

    x = res[1]*1/10 + (res[1]*8/10)*rand(Float32,num)
    y = (res[2]/2)*ones(Float32,num)
    s = -1 + 2*rand(Float32,num)

    start_position = Point2f0[Point2f0(xi,yi) for (xi,yi) in zip(x,y)]
    # foldp calls solve_particles with the startvalue, v0, and the argument, timesignal, every time
    # time signal updates. https://github.com/JuliaLang/Reactive.jl/blob/master/doc/index.md
    # alternatively, you could call foldp like this:
    # foldp((v0, t) -> solve_particles(v0), startvalue, timesignal)
    position_velocity = foldp(solve_particles, (start_position, zeros(Float32,num), s), timesignal)

    circle = HyperSphere(Point2f0(0), 2f0)
    # boundingbox is still a very expensive operation, so if you don't need it
    # you can simply set it to nothing.
    vis = visualize(
        (circle, map(first, position_velocity)),
        boundingbox=nothing,
        color=RGBA{Float32}(1,1,1,0.5),
        stroke_color=RGBA{Float32}(0,0,0,0), # stroking with transparent black makes the white edge go away
        stroke_width=0.5f0
    )
    # clears the renderlist from previous visualizations, so that you can call main() multiple times
    reset!(window)
    view(vis, window, camera=:orthographic_pixel)
end

#workflow in Julia REPL:
#=
include("simulation.jl")
window, t, speed = init()
main(window, t)
#redefine main/solve_particles
include("simulation.jl") # if you have the changes in the file
main() # call again! If you only changed solve_particles, you don't even have to call main again
push!(speed, 1/20) # change speed
=#
SimonDanisch commented 8 years ago

You might need Pkg.checkout("GLWindow")

musm commented 8 years ago

Great thank you!

My comments are as follow: (resizing the screen or zooming messes up everything, the tranparancy kinda screws things up)

Regarding the println issues

    @async while isopen(window)
        push!(timesignal, 0) # value doesn't matter
        render_frame(window)
        sleep(value(speed))
    end

    # preserve(map(window.inputs[:keyboard_buttons]) do kam
    #         if kam == GLFW.KEY_S
    #             println("saving screenshot")
    #             screenshot(window, path="x.jpg")
    #         end
    #     end
    # )

The first works, but if you type s the repl doesn't go back to julia> . The second commented out version doesn't work.

Regarding

function clear_frame!(window, color=RGB(0.2,0.2,0.2))
    # this works with every color, even hsl

What do you mean that it works for every color? I tried using color=Gray(0.2) for example at this won't work since red(), green(),blue() only work for RGB and glClearColor only accepts this for its signature. I think I misunderstood.

BTW how are you creating the GIFS for the docs?

Check out the simulation now :)

using GLVisualize, GeometryTypes, Reactive, GLAbstraction, Colors, GLWindow, ModernGL

# time is not needed for this simulation, but since Reactive calls
# it with the time parameter (in the foldp call in l49), we need to have this signature
function solve_particles(pos_vel_s)
    dt = 1.0f0

    positions, velocity, s = pos_vel_s
    for i in eachindex(positions)
        velx = 0.0f0
        vely = 0.0f0
        posi = positions[i]
        for j in eachindex(positions)
            posj = positions[j]
            dx = posj[1] - posi[1]
            dy = posj[2] - posi[2]
            distsq = dx*dx + dy*dy + 1f0
            velx = velx - s[j]*dy/distsq
            vely = vely + s[j]*dx/distsq
        end
        positions[i] = Point2f0(posi[1] + dt*velx, posi[2] + dt*vely)
    end
    positions, velocity, s
end
"""
Clears the image of the window to `color`
"""
function clear_frame!(window, color=RGB(0.2,0.2,0.2))
    # this works with every color, even hsl
    glClearColor(red(color), green(color), blue(color), 1)
    GLWindow.clear_all!(window)
end

"""
Resets the state of a window
"""
function reset!(window, color=RGB(0.2,0.2,0.2))
    clear_frame!(window, color)
    empty!(window.renderlist)
end

"""
This code should be executed only one time per julia session!!
If you accidantly close the window, you can call this again.
"""
function init(res=(800,600))
    # giving the window a transparent background color makes it transparent to
    # the previous frame. It's arguable, if that's really how things should be,
    # but that's how it currently works ;)
    window = glscreen("vortex",resolution=res, background=RGBA(0,0,0,0))
    timesignal = Signal(0)
    speed = Signal(1/30)

    glClear(GL_COLOR_BUFFER_BIT)

    @async while isopen(window)
        push!(timesignal, 0) # value doesn't matter
        render_frame(window)
        sleep(value(speed))
    end

    # preserve(map(window.inputs[:keyboard_buttons]) do kam
    #         if kam == GLFW.KEY_S
    #             println("saving screenshot")
    #             screenshot(window, path="x.jpg")
    #         end
    #     end
    # )
    preserve(map(window.inputs[:unicode_input]) do key
            if 's' in key
                println("saving screenshot")
                screenshot(window, path="x.jpg")
            end
        end
    )

    window, timesignal, speed
end

function main(window, timesignal)
    res = widths(window)
    const num = 1000

    x = Float32[(res[1]/2.0) + (res[2]/3.5) * sin(i*2*pi/num) for i=0:num-1]
    y = Float32[(res[2]/2.0) + (res[2]/3.5) * cos(i*2*pi/num) for i=0:num-1]
    # x = res[1]*1/10 + (res[1]*8/10)*rand(Float32,num)
    # y = (res[2]/2)*ones(Float32,num)
    s = (-1 + 2*rand(Float32,num))

    start_position = Point2f0[Point2f0(xi,yi) for (xi,yi) in zip(x,y)]
    # foldp calls solve_particles with the startvalue, v0, and the argument, timesignal, every time
        # time signal updates. https://github.com/JuliaLang/Reactive.jl/blob/master/doc/index.md
        # alternatively, you could call foldp like this:
        # foldp((v0, t) -> solve_particles(v0), startvalue, timesignal)
    position_velocity = foldp((v0,t) -> solve_particles(v0), (start_position, zeros(Float32,num), s), timesignal)

    circle = HyperSphere(Point2f0(0), 1f0)
    # boundingbox is still a very expensive operation, so if you don't need it
    # you can simply set it to nothing.
    vis = visualize(
        (circle, map(first, position_velocity)),
        boundingbox=nothing,
        color=RGBA(1,1,1,0.05)
    )
    reset!(window)
    view(vis, window, camera=:orthographic_pixel)
end
SimonDanisch commented 8 years ago

It looks awesome!! I've added it to the examples: http://www.glvisualize.com/examples/sprites/#simulation

If you want to add more comments for other GLVisualize beginners, please just edit this file: https://github.com/JuliaGL/GLVisualize.jl/blob/master/examples/sprites/simulation.jl

My comments are as follow: (resizing the screen or zooming messes up everything, the tranparancy kinda screws things up)

That is sort of to be expected, when rendering to a frame and never clearing it but then re-sizing it. Is this handled better by other frameworks? I guess it wouldn't be the hardest thing in the world to handle it a bit better ;)

I tried using color=Gray(0.2) for example at this won't work since red(), green(),blue() only work for RGB

Sorry, you're right! Seems I overestimated Colors capabilities a bit :( Should be easy to add though!

BTW how are you creating the GIFS for the docs?

With this: https://github.com/JuliaGL/GLVisualize.jl/blob/master/src/videotool.jl#L6

usage:

frames = []
while isopen(window)
render_frame(window)
push!(frames, screenbuffer(window)) # frames will become pretty big, but otherwise things will stutter
end
create_video(frames, "test.webm", "")

you'll need png2yuv and vpxenc... they medium easy to get on windows... Just search for precompiled binaries for them ;)

musm commented 8 years ago

Thanks a lot! I hope to be working/playing around with GLVisualize and improving the docs soon.

SimonDanisch commented 8 years ago

Awesome! I'll help where I can!