예제 #1
0
static void fcylinder_intersect(cylinder * cyl, ray * ry) {
  vector rc, n, O, hit, tmp2, ctmp4;
  flt t, s, tin, tout, ln, d, tmp, tmp3;
 
  rc.x = ry->o.x - cyl->ctr.x;  
  rc.y = ry->o.y - cyl->ctr.y;
  rc.z = ry->o.z - cyl->ctr.z;
 
  VCross(&ry->d, &cyl->axis, &n);
 
  VDOT(ln, n, n);
  ln=sqrt(ln);    /* finish length calculation */
 
  if (ln == 0.0) {  /* ray is parallel to the cylinder.. */
    return;       /* in this case, we want to miss or go through the "hole" */
  }
 
  VNorm(&n);
  VDOT(d, rc, n);
  d = fabs(d);
 
  if (d <= cyl->rad) {  /* ray intersects cylinder.. */
    VCross(&rc, &cyl->axis, &O);
    VDOT(t, O, n);
    t = - t / ln;
    VCross(&n, &cyl->axis, &O);
    VNorm(&O);
    VDOT(s, ry->d, O);
    s = fabs(sqrt(cyl->rad*cyl->rad - d*d) / s);
    tin = t - s;

    RAYPNT(hit, (*ry), tin); 

    ctmp4=cyl->axis;
    VNorm(&ctmp4);

    tmp2.x = hit.x - cyl->ctr.x;   
    tmp2.y = hit.y - cyl->ctr.y;   
    tmp2.z = hit.z - cyl->ctr.z;   

    VDOT(tmp,  tmp2, ctmp4);
    VDOT(tmp3, cyl->axis, cyl->axis);

    if ((tmp > 0.0) && (tmp < sqrt(tmp3))) 
      add_intersection(tin, (object *) cyl, ry);
    tout = t + s;

    RAYPNT(hit, (*ry), tout); 

    tmp2.x = hit.x - cyl->ctr.x;   
    tmp2.y = hit.y - cyl->ctr.y;   
    tmp2.z = hit.z - cyl->ctr.z;   

    VDOT(tmp,  tmp2, ctmp4); 
    VDOT(tmp3, cyl->axis, cyl->axis);

    if ((tmp > 0.0) && (tmp < sqrt(tmp3))) 
      add_intersection(tout, (object *) cyl, ry);
  }
}
예제 #2
0
static void bndbox_intersect(bndbox * bx, ray * ry) {
  flt a, tx1, tx2, ty1, ty2, tz1, tz2;
  flt tnear, tfar;
  object * obj;
  ray newray; 

  /* eliminate bounded rays whose bounds do not intersect  */
  /* the bounds of the box..                               */
  if (ry->flags & RT_RAY_BOUNDED) {
    if ((ry->s.x > bx->max.x) && (ry->e.x > bx->max.x)) return;
    if ((ry->s.x < bx->min.x) && (ry->e.x < bx->min.x)) return;
  
    if ((ry->s.y > bx->max.y) && (ry->e.y > bx->max.y)) return;
    if ((ry->s.y < bx->min.y) && (ry->e.y < bx->min.y)) return;

    if ((ry->s.z > bx->max.z) && (ry->e.z > bx->max.z)) return;
    if ((ry->s.z < bx->min.z) && (ry->e.z < bx->min.z)) return;
  }

  tnear= -FHUGE;
  tfar= FHUGE;

  if (ry->d.x == 0.0) {
    if ((ry->o.x < bx->min.x) || (ry->o.x > bx->max.x)) return;
  }
  else { 
    tx1 = (bx->min.x - ry->o.x) / ry->d.x;
    tx2 = (bx->max.x - ry->o.x) / ry->d.x;
    if (tx1 > tx2) { a=tx1; tx1=tx2; tx2=a; } 
    if (tx1 > tnear) tnear=tx1;   
    if (tx2 < tfar)   tfar=tx2;   
  }  
  if (tnear > tfar) return; 
  if (tfar < 0.0) return;
  
  if (ry->d.y == 0.0) { 
    if ((ry->o.y < bx->min.y) || (ry->o.y > bx->max.y)) return;
  }
  else { 
    ty1 = (bx->min.y - ry->o.y) / ry->d.y;
    ty2 = (bx->max.y - ry->o.y) / ry->d.y;
    if (ty1 > ty2) { a=ty1; ty1=ty2; ty2=a; } 
    if (ty1 > tnear) tnear=ty1;   
    if (ty2 < tfar)   tfar=ty2;   
  } 
  if (tnear > tfar) return; 
  if (tfar < 0.0) return;
 
  if (ry->d.z == 0.0) { 
    if ((ry->o.z < bx->min.z) || (ry->o.z > bx->max.z)) return;
  }
  else { 
    tz1 = (bx->min.z - ry->o.z) / ry->d.z;
    tz2 = (bx->max.z - ry->o.z) / ry->d.z;
    if (tz1 > tz2) { a=tz1; tz1=tz2; tz2=a; } 
    if (tz1 > tnear) tnear=tz1;   
    if (tz2 < tfar)   tfar=tz2;   
  } 
  if (tnear > tfar) return; 
  if (tfar < 0.0) return;


  /* intersect all of the enclosed objects */
  newray=*ry;
  newray.flags |= RT_RAY_BOUNDED;

  RAYPNT(newray.s , (*ry) , tnear); 
  RAYPNT(newray.e , (*ry) , (tfar + EPSILON)); 
 
  obj = bx->objlist;
  while (obj != NULL) {
    obj->methods->intersect(obj, &newray); 
    obj = (object *)obj->nextobj;
  }
}
예제 #3
0
파일: shade.cpp 프로젝트: RRIE/to3ds
color shader(ray * incident) {
  color col, diffuse, phongcol; 
  vector N, L, hit;
  ray shadowray;
  flt inten, t, Llen;
  object * obj;
  int numints, i;
  point_light * li;


  numints=closest_intersection(&t, &obj, incident->intstruct);  
		/* find the number of intersections */
                /* and return the closest one.      */

  if (numints < 1) {         
    /* if there weren't any object intersections then return the */
    /* background color for the pixel color.                     */
    return incident->scene->background;
  }

  if (obj->tex->islight) {  /* if the current object is a light, then we  */
    return obj->tex->col;   /* will only use the objects ambient color    */
  }

  RAYPNT(hit, (*incident), t)       /* find the point of intersection from t */ 
  obj->methods->normal(obj, &hit, incident, &N);  /* find the surface normal */

  /* execute the object's texture function */
  col = obj->tex->texfunc(&hit, obj->tex, incident); 

  diffuse.r = 0.0; 
  diffuse.g = 0.0; 
  diffuse.b = 0.0; 
  phongcol = diffuse;

  if ((obj->tex->diffuse > 0.0) || (obj->tex->phong > 0.0)) {  
    for (i=0; i<numlights; i++) {   /* loop for light contributions */
      li=lightlist[i];              /* set li=to the current light  */
      VSUB(li->ctr, hit, L)         /* find the light vector        */

      /* calculate the distance to the light from the hit point */
      Llen = sqrt(L.x*L.x + L.y*L.y + L.z*L.z) + EPSILON;

      L.x /= Llen; /* normalize the light direction vector */
      L.y /= Llen;
      L.z /= Llen;

      VDOT(inten, N, L)             /* light intensity              */

      /* add in diffuse lighting for this light if we're facing it */ 
      if (inten > 0.0) {            
        /* test for a shadow */
        shadowray.intstruct = incident->intstruct;
        shadowray.flags = RT_RAY_SHADOW | RT_RAY_BOUNDED; 
        incident->serial++;
        shadowray.serial = incident->serial;
        shadowray.mbox = incident->mbox;
        shadowray.o   = hit;
        shadowray.d   = L;      
        shadowray.maxdist = Llen;
        shadowray.s   = hit;
        shadowray.e = li->ctr;
        shadowray.scene = incident->scene;
        reset_intersection(incident->intstruct);
        intersect_objects(&shadowray);

        if (!shadow_intersection(incident->intstruct, Llen)) {
          /* XXX now that opacity is in the code, have to be more careful */
          ColorAddS(&diffuse, &li->tex->col, inten);

          /* phong type specular highlights */
          if (obj->tex->phong > 0.0) {
            flt phongval;
            phongval = shade_phong(incident, &hit, &N, &L, obj->tex->phongexp); 
            if (obj->tex->phongtype) 
              ColorAddS(&phongcol, &col, phongval);
            else
              ColorAddS(&phongcol, &(li->tex->col), phongval);
          }
        }
      }  
    } 
  }

  ColorScale(&diffuse, obj->tex->diffuse);

  col.r *= (diffuse.r + obj->tex->ambient); /* do a product of the */
  col.g *= (diffuse.g + obj->tex->ambient); /* diffuse intensity with  */
  col.b *= (diffuse.b + obj->tex->ambient); /* object color + ambient  */

  if (obj->tex->phong > 0.0) {
    ColorAccum(&col, &phongcol);
  }

  /* spawn reflection rays if necessary */
  /* note: this will overwrite the old intersection list */
  if (obj->tex->specular > 0.0) {    
    color specol;
    specol = shade_reflection(incident, &hit, &N, obj->tex->specular);
    ColorAccum(&col, &specol);
  }

  /* spawn transmission rays / refraction */
  /* note: this will overwrite the old intersection list */
  if (obj->tex->opacity < 1.0) {      
    color transcol;
    transcol = shade_transmission(incident, &hit, 1.0 - obj->tex->opacity);
    ColorAccum(&col, &transcol);
  }

  return col;    /* return the color of the shaded pixel... */
}