-
-
Notifications
You must be signed in to change notification settings - Fork 303
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Model/View relevance when drawing interactions between parts of the model #244
Comments
Hey it's a little hard to tell without a code example but I think what you are looking for is a way to write to a draw buffer in the update function. This is something we a currently working on and will be apart of the v0.9 release. That way you could just add the particles into a buffer during your double loop and it will be displayed when the frame is drawn. |
I see what you are saying. In Nannou we conceptually treat the update where you model is updated and the view function where you display the current state of the model. Although it might be nice, and easier and quicker sometimes to just have a mutable reference to model in the view function... This can quickly create confusion as to where state is being modified in large programs. The idea behind our approach is that no matter how large the program gets you always know that the state is being updated inside the event functions and that the view function is simply where everything is drawn. @freesig is correct however if you wanted to draw into a framebuffer, you could do this in the update function and then draw that framebuffer to the screen in the view function.. although this isn't currently supported yet until 0.9 is released. @MacTuitui would you be able to share a striped back Nannou example file demonstrating the technique your mentioning. This way we can suggest the most idiomatic way of approaching this in nannou 👍 |
Thanks for the comments! I'm glad you guys also seem to be in the same time zone (JST for me)! Sorry for not attaching this before but here is a simple version of what I am doing now: Gist There are three points I'm sure there are smarter ways to tackle:
(disclosure: I'm still a complete rust beginner, so there might be simple ways to use iterators there) On my machine I can't really get to simulate a thousand of points, so obviously I'm doing it wrong :) |
I would use just indices and not references. Like this |
Here are some tips that might be handy re your specific points:
Indices is one approach, but in some cases it might also be useful to divide up the
I think the nested loop that you currently have is a fine approach. You shouldn't run into any ownership issues here as you don't need mutable access to the slice in order to read the positions from it and calculate the distances. Some other related functions you might find useful are
For this you might be able to use
Out of curiosity, are you using One thing I'd like to add to assist with huge numbers of points is an easy to use "mesh" type. The W.r.t performance of the |
Also, like @freesig mentioned you might be interested in checking out the |
Just to add to what @JoshuaBatty and @freesig have mentioned, nannou tries to make a clear distinction between the updating of application state and the presentation of application state in order to encourage a more modular coding approach. That said, like you have mentioned there are some cases in graphical/drawing pipelines where you really want to cache a bit of draw state to avoid redoing some work, and updating that cache might involve mutating a collection of some sort, even though it doesn't really directly relate to your actual application state. In these cases, you might find As a side note (if you're not already aware of the technique!) I'd recommend checking out quadtrees as a potentially big performance boost for the particle distance calculations - Dan Shiffman has a really nice video series on them solving exactly this problem. |
Thanks a lot for the thorough responses! I threw away a pretty heavy collection of helpers/custom libraries (that did include quadtrees) to start afresh in nannou/rust, so given my framework of doing a new animation per day, I'm slowly building up things again, but until I understand how things work, I'll be fighting a lot against the borrow checker (at least that's my main issue now). I've been so much spoiled by the forgiving nature of processing/java that it's actually far more rewarding now when I actually get it working with no complains from the compiler. Thanks again for putting this framework to the level where it can deal with users like me and taking the time to answer. Regarding the decision to not have a mutable reference to the model in the draw function while I agree with your approach I would argue that it might be a choice that could be offered to the user, like you have right now the choice between a sketch (with no model) and an app (with a model), you could also have a "processing-like" app with a draw function (with a mutable model) where I could not need to compute the same distances (actually since the particles move the distances are different but that's another issue) in both event and draw functions. But again I'm not pushing for this (especially if I can eventually go around the restriction if/when I know what I'm doing). As for the performance aspect of multiple draw calls, I'll do what @mitchmindtree is proposing. On ellipses I've already played with the resolution but there was another issue at play because it did not really change things. I'll try to get a simple example for profiling if I think I'm doing it right (that might be a recurring theme for me this year). I'm not sure however that I'll manage to get the 0.9 branch running giving my lack of knowledge of the rust ecosystem... While I'm not at the technical level to contribute to the core of nannou, I'm more than willing to provide examples if you find them useful for newcomers to understand the framework and also work on the documentation as I go along the beginner route. For example I think a "use nannou-new to create a empty app/sketch" in the getting started part of the docs might be useful: I did not find obvious for someone not used to cargo that building nannou (and running the examples) is not related at all to building your app/sketch. Or you could have the empty app/sketch directly as a github repo that you would clone then let cargo do its magic. The plan would be to continue to get familiar with the language and the framework, and hopefully be ready to contribute soon! |
@MacTuitui, @JoshuaBatty and I were just looking at some of your sketches on your twitter feed - awesome stuff! Are you using nannou for any of these? We'd love to have a proper chat with you about nannou sometime if you're interested? It would be great to get your thoughts on things like our short-term goals (speeding up compilation with sccache, a render graph API on top of vulkan, etc), long-term goals (travelling with workshops, courses at universities, gantz and the GUI editor), what you'd like to get out of nannou, the things you miss coming from Processing, how your experience has been in general, any rust Qs you might have, etc! If you're interested, feel free to send us an email at |
The title might not be very clear, but I don't know how to do this (efficiently) in nannou.
Let's say I have a particle system stored in my model (as a vec for example) and I am doing a standard "particles interact when closer than a threshold", so I need to compute the distance between two different elements of the vector. (Such kind of systems might be found for example is Casey Reas' Process series.). So far so good, I just loop once from 0 to n and then from i+1 to n over the vec and use split_at_mut to tell the borrow checker that I'll play nice and not try to modify two elements of the same vector. I'm not sure that is the best way to do this, but that's the only one I found right now...
As far as I've understood the architecture that nannou applies, the modification of the particles is happening in the event function (on a update event) because that's the only way to get a mutable reference to the model.
The problem I have is that I want to display that the interaction is happening: in the draw function, I then need to do the same distance computation. And by doing so, I'm suffering a pretty heavy penalty that makes any thing I do look painfully slow compared to the same thing coded in Processing for example, where I would update and draw the particles in the same loop.
I don't think that memoizing which pairs of particles must be drawn is an pretty solution (and I'm not doing it) but I'm sure there is a smarter way to do this.
There is the obvious (at least for me) solution of allowing ViewFn to take a mutable reference to the model, but this might go against the design guidelines of the project.
What would be the preferred approach to deal with such system?
(For reference, I've been doing generative animations every day for two years and I switched to nannou for 2019. I'm still struggling with the language and the framework, but I'm starting to get it!)
The text was updated successfully, but these errors were encountered: