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);
}