EPhysics: allow user to configure simulation

Required to fine tunning performance or avoid objects going throught
others.



SVN revision: 74659
This commit is contained in:
Bruno Dilly 2012-07-31 19:55:52 +00:00
parent 6dd9396d6f
commit ca3e40782a
3 changed files with 130 additions and 3 deletions

View File

@ -115,7 +115,7 @@ test_collision_speed(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *e
speed_data->bt = bt;
sp = elm_spinner_add(speed_data->base.win);
elm_spinner_min_max_set(sp, 0, 500);
elm_spinner_min_max_set(sp, 0, 300);
elm_spinner_step_set(sp, 5);
elm_spinner_value_set(sp, 100);
elm_object_style_set(sp, "ephysics-test");
@ -124,6 +124,7 @@ test_collision_speed(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *e
world = ephysics_world_new();
ephysics_world_render_geometry_set(world, 50, 40, WIDTH - 100, FLOOR_Y - 40);
ephysics_world_simulation_set(world, 1/260.f, 5);
speed_data->base.world = world;
boundary = ephysics_body_bottom_boundary_add(world);

View File

@ -950,6 +950,86 @@ EAPI void ephysics_world_bodies_outside_left_autodel_set(EPhysics_World *world,
*/
EAPI Eina_Bool ephysics_world_bodies_outside_left_autodel_get(const EPhysics_World *world);
/**
* @brief
* Set world simulation's fixed time step and max number of sub steps
* configuration.
*
* It's important that time step is always less than
* @p max_sub_steps * @p fixed_time_step, otherwise you are losing time.
* Mathematically:
*
* time step < @p max_sub_steps * @p fixed_time_step;
*
* If you're a using a very large time step
* [say, five times the size of the fixed internal time step],
* then you must increase the number of max sub steps to compensate for this,
* otherwise your simulation is losing time.
*
* The time step may vary. Simulation ticks are called by an animator,
* so, by default, time step is @c 1/30 secs. If you're using elementary,
* default FPS configuration is 60 fps, i.e. time step is @c 1/60 secs.
* You can change that setting a
* different time with ecore_animator_frametime_set().
*
* Also, keep in mind
* that if you're using CPU intense calculations maybe this framerate won't
* be achieved, so the time step will be bigger. You need to define
* what range of frames per secons you need to support and configure
* @p max_sub_steps and @p fixed_time_step according to this.
*
* By decreasing the size of @p fixed_time_step, you are increasing the
* resolution of the simulation.
*
* If you are finding that your objects are moving very fast and escaping
* from your walls instead of colliding with them, then one way to help fix
* this problem is by decreasing @p fixed_time_step. If you do this,
* then you will need to increase @p max_sub_steps to ensure the equation
* listed above is still satisfied.
*
* The issue with this is that each internal tick takes an amount of
* computation. More of them means your CPU will be spending more time on
* physics and therefore less time on other stuff. Say you want twice the
* resolution, you'll need twice the @p max_sub_steps, which could chew up
* twice as much CPU for the same amount of simulation time.
*
* When you pass @p max_sub_steps > 1, it will interpolate movement for you.
* This means that if your @p fixed_time_step is 3 units, and you pass
* a timeStep of 4, then it will do exactly one tick, and estimate the
* remaining movement by 1/3. This saves you having to do interpolation
* yourself, but keep in mind that maxSubSteps needs to be greater than 1.
*
* By default @p fixed_time_step is 1/60 seconds and @p max_sub_steps is 3.
*
* @param world The physics world.
* @param fixed_time_step size of the internal simulation step, in seconds.
* @param max_sub_steps maximum number of steps that simulation is allowed
* to take at each simulation tick.
*
* @note The unit used for time is seconds.
*
* @see ephysics_world_simulation_get().
*
* @ingroup EPhysics_World
*/
EAPI void ephysics_world_simulation_set(EPhysics_World *world, double fixed_time_step, int max_sub_steps);
/**
* @brief
* Get world simulation's fixed time step and max number of sub steps
* configuration.
*
* @param world The physics world.
* @param fixed_time_step size of the internal simulation step, in seconds.
* @param max_sub_steps maximum number of steps that simulation is allowed
* to take at each simulation tick.
*
* @see ephysics_world_simulation_set() for details.
*
* @ingroup EPhysics_World
*/
EAPI void ephysics_world_simulation_get(const EPhysics_World *world, double *fixed_time_step, int *max_sub_steps);
/**
* @}
*/

View File

@ -31,8 +31,10 @@ struct _EPhysics_World {
Evas_Coord x, y, w, h;
Eina_Inlist *callbacks;
Eina_List *bodies;
int max_sub_steps;
double last_update;
double rate;
double fixed_time_step;
Eina_Bool running:1;
Eina_Bool active:1;
Eina_Bool outside_autodel:1;
@ -141,7 +143,8 @@ _simulate_worlds(void *data)
world->last_update = time_now;
gDeactivationTime = world->max_sleeping_time;
world->dynamics_world->stepSimulation(delta, 1, 1/40.f);
world->dynamics_world->stepSimulation(delta, world->max_sub_steps,
world->fixed_time_step);
}
return EINA_TRUE;
@ -342,6 +345,8 @@ ephysics_world_new(void)
world->dynamics_world->getPairCache()->setOverlapFilterCallback(filter_cb);
world->rate = 30;
world->max_sub_steps = 3;
world->fixed_time_step = 1/60.f;
world->dynamics_world->setInternalTickCallback(_ephysics_world_tick_cb,
(void *) world);
@ -927,7 +932,7 @@ ephysics_world_bodies_outside_right_autodel_get(const EPhysics_World *world)
return world->outside_right;
}
Eina_Bool
EAPI Eina_Bool
ephysics_world_bodies_outside_autodel_get(const EPhysics_World *world)
{
if (!world)
@ -939,6 +944,47 @@ ephysics_world_bodies_outside_autodel_get(const EPhysics_World *world)
return world->outside_autodel;
}
EAPI void
ephysics_world_simulation_set(EPhysics_World *world, double fixed_time_step, int max_sub_steps)
{
if (!world)
{
ERR("Can't set simulation, no world provided.");
return;
}
if (max_sub_steps < 1)
{
ERR("At least one sub step for simulation is required.");
return;
}
if (ecore_animator_frametime_get() >= max_sub_steps * fixed_time_step)
{
ERR("Assure frametime < max sub steps * fixed time step.");
return;
}
world->max_sub_steps = max_sub_steps;
world->fixed_time_step = fixed_time_step;
DBG("World %p simulation set to fixed time step: %lf, max substeps:%i.",
world, fixed_time_step, max_sub_steps);
}
EAPI void
ephysics_world_simulation_get(const EPhysics_World *world, double *fixed_time_step, int *max_sub_steps)
{
if (!world)
{
ERR("No world, can't get simulation configuration.");
return;
}
if (fixed_time_step) *fixed_time_step = world->fixed_time_step;
if (max_sub_steps) *max_sub_steps = world->max_sub_steps;
}
#ifdef __cplusplus
}
#endif