For example: If i want detect collision with some trigger using Raycast, where i should call Physics.ray method for fps independent result?
If i call it in main update function then Raycast depends on framerate and sometimes collisions are not captured.
My point is 50 or 60 CPS for physics calculations (1 sec / 50 calc = 0.02 dt), so i need something like
where should be all physics operations which runs independently or inside MAIN UPDATE there should be some loop which calculate physics as much as needed per frame. for example if fps drop from 60 to 30, then physics should be calculated 2 times.
Is this good direction to reslove this problem? How add to esenthel something like fixed update function for physics calculations?
This sample app represent situation how raycast recording collisions when fps is 60 and 30 fps. Press SPACE to switch fps between 60 and ~30;
Code:
/***************************************************/
enum AG_ACTOR_GROUP
{
AG_TRIGGER = 1,
}
/***************************************************/
bool fps_limit = false;
Vec pos_startup = Vec(-7, 0.9, 0);
Vec cam_pos = Vec(0, 3, -5);
Actor ball,
collider;
int cycles_60fps = 0;
int cycles_30fps = 0;
int hit_60fps = 0;
int hit_30fps = 0;
bool colliding = false;
bool pause = false;
/***************************************************/
void collision()
{
if(pause)return;
// calculatye physics
Physics.startSimulation().stopSimulation();
if(ball.vel().xz().length() < 6.0)ball.vel(ball.vel() + Time.d() * Vec(20.0, 0, 0)); // set vel limit to 6.0 and add velocity to actor
// collision detection
PhysHit ph;
if(Physics.ray(ball.pos(), ball.matrix().y * 2.0, &ph, IndexToFlag(AG_TRIGGER)))
{
if(ph.group == AG_TRIGGER)
{
if(fps_limit)hit_30fps++;else hit_60fps++;
if(!colliding){ if(fps_limit)cycles_30fps++;else cycles_60fps++; } // incrase cycle when raycast leave collider
colliding = true;
}
}else colliding = false;
}
/***************************************************/
void InitPre()
{
EE_INIT();
Ms.hide();
Ms.clip(null, 1);
D.mode(1280, 720, false).sync(true);
}
/***************************************************/
bool Init()
{
// physics
Physics.create (EE_PHYSX_DLL_PATH);
Physics.gravity (Vec(0, -40.0, 0));
Physics.timestep(PHYS_TIMESTEP_NUM);
//Physics.timestep(PHYS_TIMESTEP_ROUND);
Physics.precision(60);
// ball actor
ball.create (Ball(0.4, pos_startup));
ball.freezeRot (true);
ball.freezePosZ (true);
ball.mass (50);
ball.group (AG_CONTROLLER);
ball.freezePosY (true);
// collider actor
collider.create (Box(1.0, 0.1, 3, Vec(0.0, 2.0, 0)));
collider.kinematic(true);
collider.trigger (true);
collider.group (AG_TRIGGER);
Physics.ignore(AG_TRIGGER, AG_TERRAIN);
return true;
}
/***************************************************/
void Shut(){}
/***************************************************/
bool Update()
{
if(fps_limit)Time.wait(1000.0 * 0.032);
// input
if(Kb.bp(KB_ESC ))return false;
if(Kb.bp(KB_P))pause = !pause;
if(Kb.bp(KB_SPACE))
{
ball.vel(VecZero);
ball.pos(pos_startup);
fps_limit = !fps_limit;
}
if(Kb.bp(KB_R ))
{
cycles_30fps = hit_30fps = 0;
cycles_60fps = hit_60fps = 0;
ball.vel(VecZero);
ball.pos(pos_startup);
}
// camera
Cam.setAngle(cam_pos, 0.0, -0.4).set();
// physics update
collision();
if(ball.pos().x > 7.0)ball.pos(pos_startup); // reset ball if exceed position limit
return true;
}
/***************************************************/
void Render()
{
Game.World.draw();
}
/***************************************************/
void Draw()
{
Renderer(Render);
Physics.draw();
TextStyle ts;
ts.align = Vec2(1,-1);
ts.size = Vec2(0.05, 0.05);
Flt h = 0.04f;
Flt v = 0.04f;
Flt px = -D.w()+ v;
Flt py = D.h(); py -=h;
Vec2 pos(px,py);
D.text(ts, px, py,S+ "Press [SPACE] to change FPS limit. FPS: " + Time.fps()); py -=h;
D.text(ts, px, py,S+ "Press [R] to reset statistics." ); py -=h;
D.text(ts, px, py,S+ "Press [P] to pause." ); py -=h; py -=h;
D.text(ts, px, py,S+ "[60FPS] cycle / ray collisions = " + cycles_60fps + " / " + hit_60fps); py -=h;
D.text(ts, px, py,S+ "[30FPS] cycle / ray collisions = " + cycles_30fps + " / " + hit_30fps); py -=h;
if(pause)D.text(ts, Vec2(0, -0.5), S+ "PAUSE");
// draw raycast
SetMatrix();
D.line(BLUE, ball.pos(), ball.pos() + ball.matrix().y);
}
/***************************************************/