About Store Forum Documentation Contact



Post Reply 
[SOLVED] Raycast fps independent
Author Message
Mardok Offline
Member

Post: #1
[SOLVED] Raycast fps independent
hi all,
i need your help and explanation

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 FIXED UPDATE FUNCTION 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);
            
}
/***************************************************/
(This post was last modified: 11-15-2016 01:50 PM by Mardok.)
11-14-2016 05:07 PM
Find all posts by this user Quote this message in a reply
Esenthel Offline
Administrator

Post: #2
RE: Raycast fps independent
Hi,

To get FPS independent results, please perform ray tests in new 'Physics.simulation_step_completed' callback, available in the next engine release (available in the next few days).
11-15-2016 12:19 AM
Find all posts by this user Quote this message in a reply
Mardok Offline
Member

Post: #3
RE: Raycast fps independent
Hi Grzegorz,

Thank you for really fast response.
Great news. I'll check this new method asap.

For all interest - there is simple article which can be helpfully for beginners to understanding how physics should be calculate correctly and independent of framerate.

http://kirillmuzykov.com/update-vs-fixed...n-cocos2d/
11-15-2016 02:17 AM
Find all posts by this user Quote this message in a reply
Post Reply