-
Notifications
You must be signed in to change notification settings - Fork 11
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
Changed List to Array, elm-linear-algebra for vecs, and animationframe for time #1
base: master
Are you sure you want to change the base?
Conversation
Where appropriate, inside the engine, lists were replaced by arrays and the previously defined Vec2 type was replaced by elm-linear-algebra's Vec2. No algorithmic changes were made to the engine. Result: * 2x performance gain for the example * new instabilities uncovered/introduced by the change Todo : * Reduce reliance on pattern matching which causes numerous useless conversions to tuples and back * Find cause of stability issues
Example now reaches 30fps regularly.
Cool! Thanks for becoming involved. I will probably review and try the changes in the next few days and merge them. If you'd like to work on more extensive improvements I'd be happy to work with you. Thanks for the detailed comments on your changes, too. I see that the linear algebra package now uses native functions. That probably improves the performance, and is a good case for replacing the included functions. I have to say I'm far from an expert on physics engines. This was made from laboriously translating a C++ tutorial into functional style ;) |
I have to commend you on porting C++ code to Elm. I tried the other day to hook up box2d to Elm because I wanted to try to make a small platformer example and didn't feel like writing a physics engine. I thought that it would be just as simple as writing a native wrapper on top of box2d and call the functions from Elm, but, it turns out that Box2d is inherently too stateful. As in, suddenly my code had nonsense and my variables (which I thought were immutable) became mutable. And, no matter how many tricks I tried playing, Box2d keeps a strong internal state so it just seemed to hard. Which is why I decided to google around and bumped into your engine. I think it that a physics engine where everything is just immutable values and pure functions is a promising thing. I mean, it becomes trivial to just rewind time or serialize your entire gamestate (including the position of every physics body and particle). Also, I'm in still in the early learning phase of functional programming and I wonder how far you can push functional programming. Especially with something as computationally demanding as a physics engine. |
So, I'll take up your offer on collaborating on the project. I think it would be cool if we can get to the point where we have a demo where there's an explosion and particles fly everywhere, and then you hit the pause button, and pull the slider, and the particles fall back in place. I think that that would blow people's minds and we'd be like, "uh...nah...nothing to it. it's super easy" So, I've been looking around for the kinds of improvements you see in popular physics engines and I think that the following is a list I'm considering pursuing:
|
I did consider adapting Box2d, but essentially I figured I'd have a lot of those problems you mentioned. The functional style makes a lot of sense for physics engines in my opinion. When viewing time as discrete steps, a function of the previous point in time is the natural way to model it for me. I think the code turned out a lot cleaner than the C++ version too :) Elm as a language is probably not optimized enough yet to do serious physics, but we can probably get at least a usable engine for basic games. I like your suggestions. Perhaps we can start with adding the missing functionality listed under "it doesn't do", along with the collision prediction, since a lot of it is necessary for use beyond simple animations. I'm a bit busy the next 2 weeks or so, but lets keep in touch. If you're on Twitter, I am @ebenwert there. |
Possibly for reference: https://github.com/sebcrozet/nphysics |
Cool! The library is awesome. I see that they divided up into several libraries (physics and collision detection). I think it would be nice to do the same. I think there are great opportunities for reuse (even with other applications like graphics or just web development). If I understand well what they're doing in nphysics, they define different constraints (like, the bodies can't interpenetrate and so on...) and then they apply a solver (in nphysics's case, they use Gauss Seidel... I quickly googled around and it seems like it's a standard algorithm used). In theory, again, if I understand all of this correctly, this would allow use different constraints to create different kinds of physical interaction. something like so: type alias Constraint = Body -> Body -> Bool
-- this constraint says that two bodies may not interpenetrate
cannotInterpenetrate : Constraint
-- solve takes a list of constraints and two bodies and
-- figures out what those bodies must become given the constraints
solve : List Constraint -> Body -> Body -> (Body, Body) But, to not get too much ahead of ourselves, I think it'll be great to stea...(cough)...take inspiration from the algorithms used in nphysics. Plus, it's much easier to adapt rust code to c++. It reads way more nicely. I think between nphysics and ncollide, there's a lot of work that could be done. I'm gonna try and hack a few things together and see if that'll work. But, like you said, first let's start incrementally and add the features that are currently missing under the todo list. I think the big one to add would be to switch from infinite mass to using static vs dynamic body types. This would solve your immovable object vs unstoppable force problem. Then, we can add arbitrary polygons and allow for rotation. I think once we do these things, we'll have a clearer picture on how the engine will evolve |
Oh, and by the way, I'm also on Twitter @TheSeaMouse. I rarely use it but I do get the notifications, so if you send me a message I'll see it. |
Oh okay. Do you use any instant messenger? |
Any progress here? This package is wonderful by the way. |
Thanks, David! |
Hey there,
First of all, I'd like to say that your physics engine is really cool. I hope you don't mind if I hacked into it a little bit.
I made a couple of changes which, at least on my machine (5 yr old macbook pro), have made the example run around twice as fast. Basically, on chrome, I get a consistent 30fps and it takes a while before the fan kicks in.
The changes I've made:
I've noticed that each of these changes made the example run faster (although, you should probably try it yourself) and together the example ran about twice as fast.
I do have to note that in order to switch from using lists to arrays, and since I don't fully understand the internals of the algorithms used (I'm not an expert on physics engines by any means), I did change one small bit.
Basically, if you look at
src/BoxesAndBubblesEngine.elm
, I changed slightly how thecollide
function works. Instead of modifying both bodies when resolving the collision, I'm only modifying one of them. That's mainly because of my limitations as a programmer and all the pattern-matching on lists made me go "huh?". Also, in order to get the "tail recursion", I make use of trampolines. So, you'll notice that thecollide
function callstrampoline
. This did make the code easier but perhaps not completely faithful to the original. The simulation does compute different values, but it doesn't seem to be significantly more "right" or more "wrong".Also, I have to note, that if you switch from
Animation.frame
toTime.fps
, you'll start noticing tunnelling. Small objects will just fall off the ground if they move too fast. I think it has more to do with the fact that collision doesn't look ahead in time for potential future collisions rather than because I switch from updating just one of the bodies rather than both. So, havingAnimation.frame
makes things both faster and hides this artifact in the example. (I consider that a win to some extent... a hack to be sure... but a winning hack nonetheless :D )Aside from that, note that I haven't changed a single function. I just switched the types of vectors and lists. I tried to make the new code look as much as the old code as possible so as not to confuse you.
I don't know if you're interested in this pull request or even accept them, but I'll just put it here in any case.
Awesome engine btw,
Hassan Hayat