Tapping into physics updates

edited February 2015 in Help request
Hi, I've been running my soft-body physics engine on top of Orx for a while, and my integration so far could be regarded at best as a proof-of-concept. You can see a screenshot of that integration here:
pancar_screenshot.png

Now that the concept has been proven, I would like to sink my teeth deeper into Orx :)

Right now, the physics simulation is handled completely detached from Orx; In my main update function, I check the system time, and simulate my world for the duration that has passed since the last update. Additionally, it has no integration with Box2D whatsoever. As far as Orx is concerned, my entire soft-body physics world is an object that does some special rendering through the orxRender_DrawMesh function.

Now, one of the first things I want to do, is to get my soft bodies to play nicely with Box2D bodies. I want them to physically interact, and the two simulation worlds should be in sync (They're out of sync now, since I use the system time to determine how long to simulate). By sync, I also mean that if the simulation can't keep up with real time, the slow-down should be in-sync with the rest of the engine.

As I've said, right now, I'm doing my calculations on the main update function, and I should obviously move them to some kind of physics update handler. I can see that the [Physics] main config section has an entry called "IterationsPerStep". Ideally, I should move my calculations right before each of these iterations, so that I can calculate a force for each Box2D body to be applied during that iteration.

Digging through the source code I could find that the physics update function is registered to this clock:
(/code/plugins/Physics/Box2D/orxPhysics.cpp:2767)
pstClock = orxClock_FindFirst(orx2F(-1.0f), orxCLOCK_TYPE_CORE);

I don't understand which clock this function call returns exactly. Do I have any control over which one that is?

I can see that the orxPhysics_Box2D_Update is registered to this clock with priority orxCLOCK_PRIORITY_LOWER, does that mean I can register my physics update to the same clock with priority LOWEST (or NORMAL) to make sure that it gets called before orxPhysics_Box2D_Update?

I can also see in the source code that the simulation step is called this way:

(/code/plugins/Physics/Box2D/orxPhysics.cpp:946)
sstPhysics.poWorld->Step(orxPhysics::sfMaxDT, sstPhysics.u32Iterations, sstPhysics.u32Iterations >> 1);

That means the iterations take place inside Box2D, and that I can't really run anything between them. I can think of two solutions to this:
1. Increase the physics clock frequency 10 folds, so that I can get away with an "IterationsPerStep" value of 1.
2. Find a way to bypass Orx and register a callback to Box2D itself.

What do you think? Am I on the right track? I'd really be glad if you could point me in the right direction.

Thanks

Comments

  • edited February 2015
    enobayram wrote:
    Hi, I've been running my soft-body physics engine on top of Orx for a while, and my integration so far could be regarded at best as a proof-of-concept. You can see a screenshot of that integration here:
    pancar_screenshot.png

    Now that the concept has been proven, I would like to sink my teeth deeper into Orx :)

    Nice work! :)
    Digging through the source code I could find that the physics update function is registered to this clock:
    (/code/plugins/Physics/Box2D/orxPhysics.cpp:2767)
    pstClock = orxClock_FindFirst(orx2F(-1.0f), orxCLOCK_TYPE_CORE);

    I don't understand which clock this function call returns exactly. Do I have any control over which one that is?

    It's retrieving the first core clock (should only be one anyway).
    I can see that the orxPhysics_Box2D_Update is registered to this clock with priority orxCLOCK_PRIORITY_LOWER, does that mean I can register my physics update to the same clock with priority LOWEST (or NORMAL) to make sure that it gets called before orxPhysics_Box2D_Update?

    If you want to get called *before* the physics update, you need to pick a higher priority. orxCLOCK_PRIORITY_LOW should do the trick.
    I can also see in the source code that the simulation step is called this way:

    (/code/plugins/Physics/Box2D/orxPhysics.cpp:946)
    sstPhysics.poWorld->Step(orxPhysics::sfMaxDT, sstPhysics.u32Iterations, sstPhysics.u32Iterations >> 1);

    That means the iterations take place inside Box2D, and that I can't really run anything between them. I can think of two solutions to this:
    1. Increase the physics clock frequency 10 folds, so that I can get away with an "IterationsPerStep" value of 1.
    2. Find a way to bypass Orx and register a callback to Box2D itself.

    I don't think #1 would work. That would also mean your whole engine would run 10 times faster, which would require quite a lot of processing power. Not mentioning that if VSync is on, you're most likely going to be stuck with 60Hz anyway.
    For #2, there might be something inside Box2D, but I don't have knowledge of it. I guess you could also hack it to add a hook yourself (I did hack it to support of couple of things, so it's not like it's still a vanilla version anyway).
    I could also add an event hook for you when I do the calls to Box2D, but that is probably not good enough for your requirements.
    What do you think? Am I on the right track? I'd really be glad if you could point me in the right direction.

    Thanks

    I'm definitely no expert, but I feel like this road might turn up to be more difficult and windy than you'd expect.
    I don't know how your custom soft body simulation is working, but wouldn't trying to "fake" it with Box2D itself work?

    Maybe something like: http://www.uchidacoonga.com/2012/03/29/soft-body-physics-with-box2d-and-cocos2d-part-14/

    Orx does support Box2D distance joints (though they've been renamed to Spring Joints, because, you know, that's actually what they are ;)).

    What do you think?
  • edited February 2015
    iarwain wrote:
    Nice work! :)

    Thanks :)
    I don't think #1 would work. That would also mean your whole engine would run 10 times faster, which would require quite a lot of processing power. Not mentioning that if VSync is on, you're most likely going to be stuck with 60Hz anyway.

    I see, so Box2D is always occupying the same queue as the render calls. Does that mean it's impossible to have a game where heavy physics calculations doesn't slow down the UI?

    Do you think it would somehow be possible to tightly couple the clock to some heavy processing, so that the clock maintains a given callback rate, but increments the clock time based on how much the process could progress within the given time frame? Or is there a much simpler solution to this that I'm missing?
    For #2, there might be something inside Box2D, but I don't have knowledge of it. I guess you could also hack it to add a hook yourself (I did hack it to support of couple of things, so it's not like it's still a vanilla version anyway).

    I'm a bit reluctant to modify (and maintain a modified version of) Orx and its dependencies, and would try to avoid it if possible. I'm a bit obsessed with a clean and platform-independent build setup. (Actually, once I get this project running on all Orx target platforms, I'm planning to write a tutorial on my cross-platform repository layout and cmake-based build configuration)

    For #2, my hope was to register myself to an existing Box2D event hook without recompiling anything.
    I could also add an event hook for you when I do the calls to Box2D, but that is probably not good enough for your requirements.

    It might actually be, if you could split the Box2D iterations. So, instead of calling Box2D.step(10 iterations), you could do for(10 times) { Send_Event(); Box2D.step(once);}. I imagine that this could not be very efficient, so an alternative could be:

    for(n times) { Send_Event(); Box2D.step(m times);}, where n defaults to 1 and m is the current IterationsPerStep.
    I'm definitely no expert, but I feel like this road might turn up to be more difficult and windy than you'd expect.
    I don't know how your custom soft body simulation is working, but wouldn't trying to "fake" it with Box2D itself work?

    Maybe something like: http://www.uchidacoonga.com/2012/03/29/soft-body-physics-with-box2d-and-cocos2d-part-14/

    Orx does support Box2D distance joints (though they've been renamed to Spring Joints, because, you know, that's actually what they are ;)).

    What do you think?

    I think the biggest problem with that would be efficiency and performance. My particles are much more light-weight compared to Box2D bodies. Besides, I'm planning to use some advanced ODE solvers with adaptive non-homogeneous time-steps, I might even drop the concept of a "force" and simply use potential energy fields to improve stability at low sampling rates. Nature doesn't have the notion of forces anyway, it just tries to find a lower energy configuration.

    The rendering of the body is also highly customized and can not be expressed as a collection of rigid bodies.

    All of these points will be even stronger, once I introduce liquids.

    Thanks for all the help :) I'm afraid of appearing too needy, but I'm just trying to explore the possibilities. I could for instance settle down for interacting with static bodies only, or forget about maintaining FPS under physics load and adjust my load carefully (which, I will have to do anyway).
  • edited February 2015
    I see, so Box2D is always occupying the same queue as the render calls. Does that mean it's impossible to have a game where heavy physics calculations doesn't slow down the UI?

    You'd need to move your draw calls on a separate thread, but for now that's what would happen yes as world rendering and UI rendering are the same thing.
    Do you think it would somehow be possible to tightly couple the clock to some heavy processing, so that the clock maintains a given callback rate, but increments the clock time based on how much the process could progress within the given time frame? Or is there a much simpler solution to this that I'm missing?

    I'm not sure I understand this correctly. For the callback to happen, a task has to give the control back to the clock module, there's no pre-emption. That being said, any DT manipulation is possible, yes.
    For #2, my hope was to register myself to an existing Box2D event hook without recompiling anything.

    It might or might not be the case, I haven't looked at it. :)
    It might actually be, if you could split the Box2D iterations. So, instead of calling Box2D.step(10 iterations), you could do for(10 times) { Send_Event(); Box2D.step(once);}. I imagine that this could not be very efficient, so an alternative could be:

    for(n times) { Send_Event(); Box2D.step(m times);}, where n defaults to 1 and m is the current IterationsPerStep.

    That wouldn't really work. Iteration are not about in how many chunks are cut a time slice but refined the computations happened within the that time slice will be. So having N calls of simulation with 1 iteration will give very bad results compared to 1 call of simulation with N iterations.
    I think the biggest problem with that would be efficiency and performance. My particles are much more light-weight compared to Box2D bodies. Besides, I'm planning to use some advanced ODE solvers with adaptive non-homogeneous time-steps, I might even drop the concept of a "force" and simply use potential energy fields to improve stability at low sampling rates. Nature doesn't have the notion of forces anyway, it just tries to find a lower energy configuration.

    Efficiency might be a problem, I don't know, I haven't tested that myself. However some people think that it might not be the case. Actually someone wrote a liquid/soft body simulation on top of Box2D called LiquidFun: http://google.github.io/liquidfun/

    Someone else added his own simulation code for liquid physics while still deferring rigid body to Box2D (which does sound similar to what you'd like to achieve, I believe): http://www.quantumyeti.com/blog/box2d-fluid-part-1

    Here's a video showcasing the results he obtained:
    The rendering of the body is also highly customized and can not be expressed as a collection of rigid bodies.

    Well rigid bodies are only for the physics simulation, their center is then used as a single vertex of the actual "soft" mesh, which usually gives rather convincing results.
    All of these points will be even stronger, once I introduce liquids.

    Then you might be interested in both links I just posted. ;)
    Even integrating LiquidFun instead of Box2D itself as a separate physics plugin could be a viable option. I'd be happy to help with that process if need be.
    Thanks for all the help :) I'm afraid of appearing too needy, but I'm just trying to explore the possibilities. I could for instance settle down for interacting with static bodies only, or forget about maintaining FPS under physics load and adjust my load carefully (which, I will have to do anyway).

    No worries, sorry that it's not as easy as it could have been.
    I've never been too much into physics-based games and that's definitely not something I focused on too much when developing orx. :)
  • edited February 2015
    iarwain wrote:
    I'm not sure I understand this correctly. For the callback to happen, a task has to give the control back to the clock module, there's no pre-emption. That being said, any DT manipulation is possible, yes.

    Let me explain; right now, the Box2D step call looks like this:
    simulated_amount = 0;
    while( simulated_amount < clock_period) {
       simulation_step = Box2D.simulate_a_bit();
       simulated_amount += simulation_step;
    }
    

    I was thinking, maybe one could do this instead:
    start_time = now(); // real time
    while(   simulated_amount < clock_period 
          && (now() - start_time) < (clock_period - some_tolerance) ) {
       simulation_step = Box2D.simulate_a_bit();
       simulated_amount += simulation_step;
    }
    set_clock_dt(simulated_amount);
    

    I guess one should also be able to make sure that this happens before everything else.
    That wouldn't really work. Iteration are not about in how many chunks are cut a time slice but refined the computations happened within the that time slice will be. So having N calls of simulation with 1 iteration will give very bad results compared to 1 call of simulation with N iterations.

    How about having N calls of simulation with 1 iteration for a time step of 1/N each? Isn't that what Box2D does inside anyway?
    Efficiency might be a problem, I don't know, I haven't tested that myself. However some people think that it might not be the case. Actually someone wrote a liquid/soft body simulation on top of Box2D called LiquidFun: http://google.github.io/liquidfun/

    Someone else added his own simulation code for liquid physics while still deferring rigid body to Box2D (which does sound similar to what you'd like to achieve, I believe): http://www.quantumyeti.com/blog/box2d-fluid-part-1

    Here's a video showcasing the results he obtained:

    Thanks for the links, I didn't know about these projects. They look really nice. I'll probably stick to my current implementation though, I'm hoping to be able to do some wacky things :)
    Then you might be interested in both links I just posted. ;)

    indeed :)
    Even integrating LiquidFun instead of Box2D itself as a separate physics plugin could be a viable option. I'd be happy to help with that process if need be.

    Thanks for the offer, I'd love to do something like that, but my to-do list is already quite long. As I've mentioned I'll try to stick to my custom implementation for now. In any case, I'm planning to eventually contribute it back to the community, and it'll hopefully have been very well integrated by then.
    No worries, sorry that it's not as easy as it could have been.
    I've never been too much into physics-based games and that's definitely not something I focused on too much when developing orx. :)

    As I've mentioned on another thread, Orx has been quite cooperative so far :) I'm sure there'll be a not-so-intrusive way of achieving what I want.
  • edited February 2015
    Let me explain; right now, the Box2D step call looks like this:
    simulated_amount = 0;
    while( simulated_amount < clock_period) {
       simulation_step = Box2D.simulate_a_bit();
       simulated_amount += simulation_step;
    }
    

    I was thinking, maybe one could do this instead:
    start_time = now(); // real time
    while(   simulated_amount < clock_period 
          && (now() - start_time) < (clock_period - some_tolerance) ) {
       simulation_step = Box2D.simulate_a_bit();
       simulated_amount += simulation_step;
    }
    set_clock_dt(simulated_amount);
    

    Thanks for the details. Well this will happen automatically for the next frame (as we always use the previous frame time for simulation), the clock will reflect the time spent and adapt the DT if need be, taking in account the time distortion if any is applied.
    How about having N calls of simulation with 1 iteration for a time step of 1/N each? Isn't that what Box2D does inside anyway?

    Not exactly, the steps, both for velocity and position constraint solving, will be iterations but over the same time slice and only the constraints are computed, nothing else. For example velocity integration would then yield different results when chunked externally. Also by truncating the time slice into too many pieces, one might run into problematic precision issues as computations are all made in single precision.
    Thanks for the links, I didn't know about these projects. They look really nice. I'll probably stick to my current implementation though, I'm hoping to be able to do some wacky things :)

    Yep, that's totally fine and the second link might help to give hints on how to integrate with Box2D without altering it or being too intrusive, from what I understood (but I didn't read it in depth, I admit).
    Thanks for the offer, I'd love to do something like that, but my to-do list is already quite long. As I've mentioned I'll try to stick to my custom implementation for now. In any case, I'm planning to eventually contribute it back to the community, and it'll hopefully have been very well integrated by then.

    Sound good!
    As I've mentioned on another thread, Orx has been quite cooperative so far :) I'm sure there'll be a not-so-intrusive way of achieving what I want.

    Hopefully that will be the case. :)
  • edited February 2015
    iarwain wrote:
    Well this will happen automatically for the next frame (as we always use the previous frame time for simulation), the clock will reflect the time spent and adapt the DT if need be, taking in account the time distortion if any is applied.
    Ahh, so you mean if the simulation takes 20ms inside a clock update whose DT is 10ms, the clock will adjust the DT to 5ms at the next frame, so that it can keep up with its configured frequency? Or did I get this completely wrong?
    Not exactly, the steps, both for velocity and position constraint solving, will be iterations but over the same time slice and only the constraints are computed, nothing else. For example velocity integration would then yield different results when chunked externally. Also by truncating the time slice into too many pieces, one might run into problematic precision issues as computations are all made in single precision.
    Thanks a lot for the explanation, I'll study Box2D deeper to find a way then.
  • edited February 2015
    just to let you know guys, I'm currently working on replacing Box2D with LiquidFun.

    basic integration is almost done
    iarwain and I will discuss on how to add soft body support in orx.
  • edited February 2015
    lydesik, is this the complete removal of box2d from orx? Will the current methods remain untouched?
  • edited February 2015
    Ahh, so you mean if the simulation takes 20ms inside a clock update whose DT is 10ms, the clock will adjust the DT to 5ms at the next frame, so that it can keep up with its configured frequency? Or did I get this completely wrong?

    That would be the other way around. Assuming there's no DT modifier applied on the clock (ie. no multiplier or limiter), with a clock of 100Hz, you'll get:

    - Frame 1: DT = 10ms, however actual complete frame processing time is 20ms
    - Frame 2: DT = 20ms, this time the frame processing time took 8ms
    - Frame 3: delay 2ms to resync, then back to original DT = 10ms

    Sausage: no, Lydesik is adding it as an alternate plugin. The actual API should only get extended in the end, not modified.
  • edited February 2015
    Cool thanks no worries. It wouldn't have been a problem, but it would mean regression testing all physics in existing work as the physics could be just a little different.

    I am interested to see what LiquidFun is like. Might be *Fun.
  • edited February 2015
    iarwain wrote:
    - Frame 1: DT = 10ms, however actual complete frame processing time is 20ms
    - Frame 2: DT = 20ms, this time the frame processing time took 8ms
    - Frame 3: delay 2ms to resync, then back to original DT = 10ms

    This is actually what I'm trying to avoid; I think a problem with this scheme is that, if, say, there's an explosion in the game, and the engine is stressed for a second, the following is what would happen:

    - Frame 1: DT = 10ms, however actual complete frame processing time is 20ms
    - Frame 2: DT = 20ms, this time the frame processing time took 40ms
    - Frame 3: DT = 40ms, and the processing takes 80ms

    ...

    So the user would see increasing periods of freeze, the last one lasting 1 second. I guess the freezes could be mitigated using ModifierType:capped, but that wouldn't eliminate the FPS drop.

    If one could manipulate the DT based on the physics load, allowing time stretching, the stressful period could appear to the user as a smooth slow-motion. Is there any way to manipulate the current frame's DT, without breaking anything? Or would you suggest ModifierType:multiply and adjusting the modifier value for the next frame, allowing a single-frame glitch (or even eliminate that by simulating one frame ahead)?
  • edited February 2015
    This is actually what I'm trying to avoid; I think a problem with this scheme is that, if, say, there's an explosion in the game, and the engine is stressed for a second, the following is what would happen:

    - Frame 1: DT = 10ms, however actual complete frame processing time is 20ms
    - Frame 2: DT = 20ms, this time the frame processing time took 40ms
    - Frame 3: DT = 40ms, and the processing takes 80ms

    This is an unlikely scenario though, the processing time is related to the number of objects x number of iterations, not to the length of the DT (which is only used to initially integrates positions/rotations). It has a greater impact when using continuous physics (ie. for bullet-flagged objects), but it shouldn't still lead in a computation explosion in most cases.
    So the user would see increasing periods of freeze, the last one lasting 1 second. I guess the freezes could be mitigated using ModifierType:capped, but that wouldn't eliminate the FPS drop.

    If it were to happen, that would be what the user would experience. However shrinking down the DT artificially would slow down time, ie. the user would see things getting much slower than they actually are. In some cases such as online games, for example, that's not really an option.
    If one could manipulate the DT based on the physics load, allowing time stretching, the stressful period could appear to the user as a smooth slow-motion. Is there any way to manipulate the current frame's DT, without breaking anything? Or would you suggest ModifierType:multiply and adjusting the modifier value for the next frame, allowing a single-frame glitch (or even eliminate that by simulating one frame ahead)?

    Applying a modifier is definitely an option if you need it. I'd recommend against modifying the tick size itself, at least for the core clock, as it's what actually determines the calling rate of the clock callbacks. The DT is a read only value determined by both the modifier and the tick size (as well as the actual time that elapsed).

    With some more advanced physics engines, another option would be to multi-thread the update, but as far as I know, it's not an option for Box2D.
  • edited February 2015
    Thanks a lot for the links Lydesik, I had no idea about them.

    iarwain wrote:
    This is an unlikely scenario though, the processing time is related to the number of objects x number of iterations, not to the length of the DT (which is only used to initially integrates positions/rotations). It has a greater impact when using continuous physics (ie. for bullet-flagged objects), but it shouldn't still lead in a computation explosion in most cases.

    I see, in my soft body physics engine, I update the world with constant time steps, which is chosen to keep the simulation stable, regardless of the display frequency. So, the time it takes for me to simulate the world is linearly proportional to the amount that I simulate. That means the scenario is quite likely in my case.
    If it were to happen, that would be what the user would experience. However shrinking down the DT artificially would slow down time, ie. the user would see things getting much slower than they actually are. In some cases such as online games, for example, that's not really an option.

    As I said, in my case, a slowdown is inevitable, since throttling physics is not an option. So, my objective is to at least keep a smooth presentation.
    Applying a modifier is definitely an option if you need it. I'd recommend against modifying the tick size itself, at least for the core clock, as it's what actually determines the calling rate of the clock callbacks. The DT is a read only value determined by both the modifier and the tick size (as well as the actual time that elapsed).
    Great, modifier it is then :) thanks for the help.
Sign In or Register to comment.