int BasisHitOrthoscopic()

in layer1/Basis.cpp [2027:2346]


int BasisHitOrthoscopic(BasisCallRec * BC)
{
  const float _0 = 0.0F, _1 = 1.0F;
  float oppSq, dist = _0, sph[3], vt[3], tri1, tri2;
  int a, b, c, h, *ip;
  int excl_trans_flag;
  int check_interior_flag;
  int *elist, local_iflag = false;
  float minusZ[3] = { 0.0F, 0.0F, -1.0F };

  CBasis *BI = BC->Basis;
  RayInfo *r = BC->rr;

  if(MapInsideXY(BI->Map, r->base, &a, &b, &c)) {
    int minIndex = -1;
    int v2p;
    int i, ii;
    int *xxtmp;
    int do_loop;
    int except1 = BC->except1;
    int except2 = BC->except2;
    int n_vert = BI->NVertex, n_eElem = BI->Map->NEElem;
    const int *vert2prim = BC->vert2prim;
    const float front = BC->front;
    const float back = BC->back;
    const float excl_trans = BC->excl_trans;
    const float BasisFudge0 = BC->fudge0;
    const float BasisFudge1 = BC->fudge1;

    MapCache *cache = &BC->cache;

    float r_tri1 = _0, r_tri2 = _0, r_dist = _0;        /* zero inits to suppress compiler warnings */
    float r_sphere0 = _0, r_sphere1 = _0, r_sphere2 = _0;
    CPrimitive *r_prim = NULL;

    check_interior_flag = BC->check_interior && (!BC->pass);

    /* assumption: always heading in the negative Z direction with our vector... */
    vt[0] = r->base[0];
    vt[1] = r->base[1];
    vt[2] = r->base[2] - front;

    if(except1 >= 0)
      except1 = vert2prim[except1];
    if(except2 >= 0)
      except2 = vert2prim[except2];

    excl_trans_flag = (excl_trans != _0);

    r_dist = MAXFLOAT;

    xxtmp = BI->Map->EHead + (a * BI->Map->D1D2) + (b * BI->Map->Dim[2]) + c;

    MapCacheReset(cache);

    elist = BI->Map->EList;

    while(c >= MapBorder) {
      h = *xxtmp;
      if((h > 0) && (h < n_eElem)) {
        ip = elist + h;
        i = *(ip++);
        do_loop = ((i >= 0) && (i < n_vert));
        while(do_loop) {
          ii = *(ip++);
          v2p = vert2prim[i];
          do_loop = ((ii >= 0) && (ii < n_vert));

          if((v2p != except1) && (v2p != except2) && (!MapCached(cache, v2p))) {
            CPrimitive *prm = BC->prim + v2p;
            MapCache(cache, v2p);

            switch (prm->type) {
            case cPrimTriangle:
            case cPrimCharacter:
              if(!prm->cull) {
                float *pre = BI->Precomp + BI->Vert2Normal[i] * 3;

                if(pre[6]) {
                  float *vert0 = BI->Vertex + prm->vert * 3;

                  float tvec0 = vt[0] - vert0[0];
                  float tvec1 = vt[1] - vert0[1];

                  tri1 = (tvec0 * pre[4] - tvec1 * pre[3]) * pre[7];
                  tri2 = -(tvec0 * pre[1] - tvec1 * pre[0]) * pre[7];

                  if(!((tri1 < BasisFudge0) || (tri2 < BasisFudge0) ||
                       (tri1 > BasisFudge1) || ((tri1 + tri2) > BasisFudge1))) {
                    dist = (r->base[2] - (tri1 * pre[2]) - (tri2 * pre[5]) - vert0[2]);

                    if((dist < r_dist) && (dist >= front) &&
                       (dist <= back) && (prm->trans != _1)) {
                      minIndex = prm->vert;
                      r_tri1 = tri1;
                      r_tri2 = tri2;
                      r_dist = dist;
                    }
                  }
                }
              }
              break;

            case cPrimSphere:
              oppSq = ZLineClipPoint(r->base, BI->Vertex + i * 3, &dist, BI->Radius[i]);
              if(oppSq <= BI->Radius2[i]) {
                dist = (float) (sqrt1f(dist) - sqrt1f((BI->Radius2[i] - oppSq)));

                if((dist < r_dist) && (prm->trans != _1)) {
                  if((dist >= front) && (dist <= back)) {
                    minIndex = prm->vert;
                    r_dist = dist;
                  } else if(check_interior_flag) {
                    if(diffsq3f(vt, BI->Vertex + i * 3) < BI->Radius2[i]) {
                      local_iflag = true;
                      r_prim = prm;
                      r_dist = front;
                      minIndex = prm->vert;
                    }
                  }
                }
              }
              break;
            case cPrimEllipsoid:
              oppSq = ZLineClipPoint(r->base, BI->Vertex + i * 3, &dist, BI->Radius[i]);
              if(oppSq <= BI->Radius2[i]) {

                dist = (float) (sqrt1f(dist) - sqrt1f((BI->Radius2[i] - oppSq)));

                if((dist < r_dist) && (prm->trans != _1)) {
                  float *n1 = BI->Normal + BI->Vert2Normal[i] * 3;
                  if(LineClipEllipsoidPoint(r->base, minusZ,
                                            BI->Vertex + i * 3, &dist,
                                            BI->Radius[i], BI->Radius2[i],
                                            prm->n0, n1, n1 + 3, n1 + 6)) {
                    if(dist < r_dist) {
                      if((dist >= _0) && (dist <= back)) {
                        minIndex = prm->vert;
                        r_dist = dist;
                      }
                    }
                  }
                }
              }
              break;

            case cPrimCylinder:
              if(ZLineToSphereCapped(r->base, BI->Vertex + i * 3,
                                     BI->Normal + BI->Vert2Normal[i] * 3,
                                     BI->Radius[i], prm->l1, sph, &tri1, prm->cap1,
                                     prm->cap2, BI->Precomp + BI->Vert2Normal[i] * 3)) {
                oppSq = ZLineClipPoint(r->base, sph, &dist, BI->Radius[i]);
                if(oppSq <= BI->Radius2[i]) {
                  dist = (float) (sqrt1f(dist) - sqrt1f((BI->Radius2[i] - oppSq)));

                  if((dist < r_dist) && (prm->trans != _1)) {
                    if((dist >= front) && (dist <= back)) {
                      if(prm->l1 > kR_SMALL4)
                        r_tri1 = tri1 / prm->l1;

                      r_sphere0 = sph[0];
                      r_sphere1 = sph[1];
                      r_sphere2 = sph[2];
                      minIndex = prm->vert;
                      r_dist = dist;
                    } else if(check_interior_flag) {
                      if(FrontToInteriorSphereCapped(vt,
                                                     BI->Vertex + i * 3,
                                                     BI->Normal + BI->Vert2Normal[i] * 3,
                                                     BI->Radius[i],
                                                     BI->Radius2[i],
                                                     prm->l1, prm->cap1, prm->cap2)) {
                        local_iflag = true;
                        r_prim = prm;
                        r_dist = front;
                        minIndex = prm->vert;
                      }
                    }
                  }
                }
              }
              break;
            case cPrimCone:
              {
                float sph_rad, sph_rad_sq;
                if(ConeLineToSphereCapped(r->base, minusZ, BI->Vertex + i * 3,
                                          BI->Normal + BI->Vert2Normal[i] * 3,
                                          BI->Radius[i], prm->r2, prm->l1, sph, &tri1,
                                          &sph_rad, &sph_rad_sq, prm->cap1, prm->cap2)) {

                  oppSq = ZLineClipPoint(r->base, sph, &dist, sph_rad);
                  if(oppSq <= sph_rad_sq) {
                    dist = (float) (sqrt1f(dist) - sqrt1f((sph_rad_sq - oppSq)));

                    if((dist < r_dist) && (prm->trans != _1)) {
                      if((dist >= front) && (dist <= back)) {
                        if(prm->l1 > kR_SMALL4)
                          r_tri1 = tri1 / prm->l1;

                        r_sphere0 = sph[0];
                        r_sphere1 = sph[1];
                        r_sphere2 = sph[2];
                        minIndex = prm->vert;
                        r_dist = dist;
                      } else if(check_interior_flag) {
                        if(FrontToInteriorSphereCapped(vt,
                                                       BI->Vertex + i * 3,
                                                       BI->Normal +
                                                       BI->Vert2Normal[i] * 3, sph_rad,
                                                       sph_rad_sq, prm->l1, prm->cap1,
                                                       prm->cap2)) {
                          local_iflag = true;
                          r_prim = prm;
                          r_dist = front;
                          minIndex = prm->vert;
                        }
                      }
                    }
                  }
                }
              }
              break;
            case cPrimSausage:
              if(ZLineToSphere
                 (r->base, BI->Vertex + i * 3, BI->Normal + BI->Vert2Normal[i] * 3,
                  BI->Radius[i], prm->l1, sph, &tri1,
                  BI->Precomp + BI->Vert2Normal[i] * 3)) {
                oppSq = ZLineClipPoint(r->base, sph, &dist, BI->Radius[i]);
                if(oppSq <= BI->Radius2[i]) {
                  int tmp_flag = false;

                  dist = (float) (sqrt1f(dist) - sqrt1f((BI->Radius2[i] - oppSq)));
                  if((dist < r_dist) && (prm->trans != _1)) {
                    if((dist >= front) && (dist <= back)) {
                      tmp_flag = true;
                      if(excl_trans_flag) {
                        if((prm->trans > _0) && (dist < excl_trans))
                          tmp_flag = false;
                      }
                      if(tmp_flag) {
                        if(prm->l1 > kR_SMALL4)
                          r_tri1 = tri1 / prm->l1;

                        r_sphere0 = sph[0];
                        r_sphere1 = sph[1];
                        r_sphere2 = sph[2];
                        minIndex = prm->vert;
                        r_dist = dist;
                      }
                    } else if(check_interior_flag) {
                      if(FrontToInteriorSphere
                         (vt, BI->Vertex + i * 3, BI->Normal + BI->Vert2Normal[i] * 3,
                          BI->Radius[i], BI->Radius2[i], prm->l1)) {
                        local_iflag = true;
                        r_prim = prm;
                        r_dist = front;
                        minIndex = prm->vert;
                      }
                    }
                  }
                }
              }
              break;
            }                   /* end of switch */
          }
          /* end of if */
          i = ii;

        }                       /* end of while */
      }

      /* and of course stop when we hit the edge of the map */

      if(local_iflag)
        break;

      /* we've processed all primitives associated with this voxel, 
         so if an intersection has been found which occurs in front of
         the next voxel, then we can stop */

      if(minIndex > -1) {
        int aa, bb, cc;

        vt[2] = r->base[2] - r_dist;
        MapLocus(BI->Map, vt, &aa, &bb, &cc);
        if(cc > c)
          break;
        else
          vt[2] = r->base[2] - front;
      }

      c--;
      xxtmp--;

    }                           /* end of while */

    if(minIndex > -1) {
      r_prim = BC->prim + vert2prim[minIndex];

      if((r_prim->type == cPrimSphere) || (r_prim->type == cPrimEllipsoid)) {
        const float *vv = BI->Vertex + minIndex * 3;
        r_sphere0 = vv[0];
        r_sphere1 = vv[1];
        r_sphere2 = vv[2];
      }
    }

    BC->interior_flag = local_iflag;
    r->tri1 = r_tri1;
    r->tri2 = r_tri2;
    r->prim = r_prim;
    r->dist = r_dist;
    r->sphere[0] = r_sphere0;
    r->sphere[1] = r_sphere1;
    r->sphere[2] = r_sphere2;
    return (minIndex);
  }                             /* end of if */
  BC->interior_flag = local_iflag;
  return (-1);
}