/* 
 * intersect.c - This file contains code for CSG and intersection routines.
 *
 *  $Id: intersect.c,v 1.31 2000/09/05 03:52:48 johns Exp $
 */

#include "machine.h"
#include "types.h"
#include "intersect.h"

unsigned int new_objectid(scenedef * scene) {
  return scene->numobjects++; /* global used to generate unique object ID's */
}

unsigned int max_objectid(scenedef * scene) {
  return scene->numobjects;
}

void free_objects(object * start) {
  object * cur;
  object * next;

  cur=start; 
  while (cur != NULL) { 
    next=cur->nextobj;
    cur->methods->freeobj(cur);
    cur=next;
  }
}

void intersect_objects(ray * ry) {
  object * cur;
  object temp;

  temp.nextobj = ry->scene->obj; /* setup the initial object pointers.. */
  cur = &temp;                       /* ready, set, go!                     */

  while ((cur=cur->nextobj) != NULL)          
    cur->methods->intersect(cur, ry); 
}


/* Only keeps closest intersection, CSG-unsafe */
void add_regular_intersection(flt t, object * obj, ray * ry) {

  if (t > EPSILON) {
    /* if we hit something before maxdist update maxdist */
    if (t < ry->maxdist) {
      ry->maxdist = t;
      ry->intstruct.num=1;
      ry->intstruct.closest.obj = obj;
      ry->intstruct.closest.t = t;
    }
  }
}


int closest_intersection(flt * t, object ** obj, ray * ry) {
  if (ry->intstruct.num > 0) {
      *t = ry->intstruct.closest.t;
    *obj = ry->intstruct.closest.obj;
  } 

  return ry->intstruct.num;
}
/* End of CSG-unsafe */


/* Only meant for shadow rays, unsafe for anything else */
void add_shadow_intersection(flt t, object * obj, ray * ry) {
  if (t > EPSILON) {

    /* if we hit something before maxdist update maxdist */
    if (t < ry->maxdist) {

      /* if this object doesn't cast a shadow, quit out.. */
      if (obj->tex->shadowcast == 0) {
        return;
      }

      ry->maxdist = t;
      ry->intstruct.num=1;

      /* if we hit *anything* before maxdist, and we're firing a */
      /* shadow ray, then we are finished ray tracing the shadow */
      ry->flags |= RT_RAY_FINISHED;
    }
  }
}

int shadow_intersection(ray * ry) {
  if (ry->intstruct.num > 0) 
    return 1;

  return 0;
}



#if 0 /* NOT READY YET */

/* Keeps all intersections...  CSG-safe */
void add_csg_intersection(flt t, object * obj, ray * ry) {
  intersectstruct * intstruct = ry->intstruct;

  if (t > EPSILON) {

    /* if we hit something before maxdist update maxdist */
    if (t < ry->maxdist) {
      ry->maxdist = t;
    }

    intstruct->num++;
    intstruct->list[intstruct->num].obj = obj;
    intstruct->list[intstruct->num].t = t;
  }
}

int closest_csg_intersection(flt * t, object ** obj, intersectstruct * intstruct) {
  int i;
  *t=FHUGE;

  for (i=1; i<=intstruct->num; i++) {
    if (intstruct->list[i].t < *t) {
        *t=intstruct->list[i].t;
      *obj=intstruct->list[i].obj;
    }
  } 

  return intstruct->num;
}

/* End of CSG-safe intersection routines */

#endif
