forked from enlightenment/efl
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:
parent
6dd9396d6f
commit
ca3e40782a
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue