Originally Posted By: txesmi
That workaround fails when the view ray is nearly parallel to a surface the camera ends close to and the c_trace did not collide to.

The only solution I know is the use of a dummy entity and USE_BOX in the trace.

Code:
action actCameraCollider () {
   proc_mode = PROC_LATE; // execute after player action
   my->flags |= INVISIBLE | PASSABLE | FAT | NARROW;
   vec_set(&my->max_x, vector(16, 16, 16)); // collision hull
   vec_set(&my->min_x, vector(-16, -16, -16));
   VECTOR vOffset;
   vec_set(&vOffset, vector(0, -7, 35));  // camera rotation center in player space
   var nCamDist = 200; // distance to the center
   ...
   vec_set(&my->x, &vOffset); // set the collider position in reference to the player position and orientation
   vec_rotate(&my->x, &player->pan);
   vec_add(&my->x, &player->x);
   VECTOR vDir;
   vec_for_angle(&vDir, &camera->pan); // compute the inverse of the view ray; the trace is backwards
   vec_scale(&vDir, -nCamDist);
   VECTOR vTarget; // compute the target position for c_trace
   vec_set(&vTarget, &my->x); // it is also the final camera position when the trace collides nothing
   vec_add(&vTarget, &vDir);
   you = player; 
   var nDist = c_trace(&my->x, &vTarget, IGNORE_YOU | IGNORE_PASSABLE | USE_BOX);
   if (nDist > 0) { // when it collides
      vec_normalize(&vDir, nDist); // enshort the view ray
      vec_set(&camera->x, &my->x); // and recompute the position of the camera
      vec_add(&camera->x, &vDir);
   } else { // when it does not collide
      vec_set(&camera->x, &vTarget); // set the already computed position of the camera
   }
   ...



Salud!

Hello Txesmi. Thank you for your help again. Believe it or not, I am kind of new to the idea of using a dummy entity. Does it go something like this?

Code:
action actCameraCollider() 
{
   proc_mode = PROC_LATE; // execute after player action
   
   my->flags |= INVISIBLE | PASSABLE | FAT | NARROW;
   
   vec_set(&my->max_x, vector(16, 16, 16)); // collision hull
   vec_set(&my->min_x, vector(-16, -16, -16));
   
   VECTOR vOffset;
   
   vec_set(&vOffset, vector(0, -7, 35));  // camera rotation center
                                          //    in player space
   
   var nCamDist = 200; // distance to the center
   
   vec_set(&my->x, &vOffset); // set the collider position in
                              //    reference to the player position
                              //    and orientation
   vec_rotate(&my->x, &player->pan);
   vec_add(&my->x, &player->x);
   
   VECTOR vDir;
   
   vec_for_angle(&vDir, &camera->pan); // compute the inverse of the
                                       //    view ray; the trace is
                                       //    backwards
   vec_scale(&vDir, -nCamDist);
   
   VECTOR vTarget; // compute the target position for c_trace
   
   vec_set(&vTarget, &my->x); // it is also the final camera position
                              //    when the trace collides nothing
   vec_add(&vTarget, &vDir);
   
   you = player; 
   
   var nDist = c_trace(&my->x, &vTarget, IGNORE_YOU | IGNORE_PASSABLE
                                                    | USE_BOX);
   
   if (nDist > 0) 
   { // when it collides
      vec_normalize(&vDir, nDist); // enshort the view ray
      vec_set(&camera->x, &my->x); // and recompute the position of
                                   //    the camera
      vec_add(&camera->x, &vDir);
   } 
   else 
   { // when it does not collide
      vec_set(&camera->x, &vTarget); // set the already computed
                                     //    position of the camera
   }
}

action cameraDummy()
{
   actCameraCollider();	
}

void _handle_cam_3rdperson()
{
   camDummy = ent_create(NULL,nullvector,cameraDummy);
}

action playerAction()
{ 
   ...

   _handle_cam_3rdperson();

   ...
}


Last edited by Ruben; 02/23/18 09:02.