📄 be_aas_sample.c
字号:
tstack_p = tracestack;
//we start with the whole line on the stack
VectorCopy(start, tstack_p->start);
VectorCopy(end, tstack_p->end);
tstack_p->planenum = 0;
//start with node 1 because node zero is a dummy for a solid leaf
tstack_p->nodenum = 1; //starting at the root of the tree
tstack_p++;
while (1)
{
//pop up the stack
tstack_p--;
//if the trace stack is empty (ended up with a piece of the
//line to be traced in an area)
if (tstack_p < tracestack)
{
tstack_p++;
//nothing was hit
trace.startsolid = qfalse;
trace.fraction = 1.0;
//endpos is the end of the line
VectorCopy(end, trace.endpos);
//nothing hit
trace.ent = 0;
trace.area = 0;
trace.planenum = 0;
return trace;
} //end if
//number of the current node to test the line against
nodenum = tstack_p->nodenum;
//if it is an area
if (nodenum < 0)
{
#ifdef AAS_SAMPLE_DEBUG
if (-nodenum > aasworld.numareasettings)
{
botimport.Print(PRT_ERROR, "AAS_TraceBoundingBox: -nodenum out of range\n");
return trace;
} //end if
#endif //AAS_SAMPLE_DEBUG
//botimport.Print(PRT_MESSAGE, "areanum = %d, must be %d\n", -nodenum, AAS_PointAreaNum(start));
//if can't enter the area because it hasn't got the right presence type
if (!(aasworld.areasettings[-nodenum].presencetype & presencetype))
{
//if the start point is still the initial start point
//NOTE: no need for epsilons because the points will be
//exactly the same when they're both the start point
if (tstack_p->start[0] == start[0] &&
tstack_p->start[1] == start[1] &&
tstack_p->start[2] == start[2])
{
trace.startsolid = qtrue;
trace.fraction = 0.0;
VectorClear(v1);
} //end if
else
{
trace.startsolid = qfalse;
VectorSubtract(end, start, v1);
VectorSubtract(tstack_p->start, start, v2);
trace.fraction = VectorLength(v2) / VectorNormalize(v1);
VectorMA(tstack_p->start, -0.125, v1, tstack_p->start);
} //end else
VectorCopy(tstack_p->start, trace.endpos);
trace.ent = 0;
trace.area = -nodenum;
// VectorSubtract(end, start, v1);
trace.planenum = tstack_p->planenum;
//always take the plane with normal facing towards the trace start
plane = &aasworld.planes[trace.planenum];
if (DotProduct(v1, plane->normal) > 0) trace.planenum ^= 1;
return trace;
} //end if
else
{
if (passent >= 0)
{
if (AAS_AreaEntityCollision(-nodenum, tstack_p->start,
tstack_p->end, presencetype, passent,
&trace))
{
if (!trace.startsolid)
{
VectorSubtract(end, start, v1);
VectorSubtract(trace.endpos, start, v2);
trace.fraction = VectorLength(v2) / VectorLength(v1);
} //end if
return trace;
} //end if
} //end if
} //end else
trace.lastarea = -nodenum;
continue;
} //end if
//if it is a solid leaf
if (!nodenum)
{
//if the start point is still the initial start point
//NOTE: no need for epsilons because the points will be
//exactly the same when they're both the start point
if (tstack_p->start[0] == start[0] &&
tstack_p->start[1] == start[1] &&
tstack_p->start[2] == start[2])
{
trace.startsolid = qtrue;
trace.fraction = 0.0;
VectorClear(v1);
} //end if
else
{
trace.startsolid = qfalse;
VectorSubtract(end, start, v1);
VectorSubtract(tstack_p->start, start, v2);
trace.fraction = VectorLength(v2) / VectorNormalize(v1);
VectorMA(tstack_p->start, -0.125, v1, tstack_p->start);
} //end else
VectorCopy(tstack_p->start, trace.endpos);
trace.ent = 0;
trace.area = 0; //hit solid leaf
// VectorSubtract(end, start, v1);
trace.planenum = tstack_p->planenum;
//always take the plane with normal facing towards the trace start
plane = &aasworld.planes[trace.planenum];
if (DotProduct(v1, plane->normal) > 0) trace.planenum ^= 1;
return trace;
} //end if
#ifdef AAS_SAMPLE_DEBUG
if (nodenum > aasworld.numnodes)
{
botimport.Print(PRT_ERROR, "AAS_TraceBoundingBox: nodenum out of range\n");
return trace;
} //end if
#endif //AAS_SAMPLE_DEBUG
//the node to test against
aasnode = &aasworld.nodes[nodenum];
//start point of current line to test against node
VectorCopy(tstack_p->start, cur_start);
//end point of the current line to test against node
VectorCopy(tstack_p->end, cur_end);
//the current node plane
plane = &aasworld.planes[aasnode->planenum];
switch(plane->type)
{/*FIXME: wtf doesn't this work? obviously the axial node planes aren't always facing positive!!!
//check for axial planes
case PLANE_X:
{
front = cur_start[0] - plane->dist;
back = cur_end[0] - plane->dist;
break;
} //end case
case PLANE_Y:
{
front = cur_start[1] - plane->dist;
back = cur_end[1] - plane->dist;
break;
} //end case
case PLANE_Z:
{
front = cur_start[2] - plane->dist;
back = cur_end[2] - plane->dist;
break;
} //end case*/
default: //gee it's not an axial plane
{
front = DotProduct(cur_start, plane->normal) - plane->dist;
back = DotProduct(cur_end, plane->normal) - plane->dist;
break;
} //end default
} //end switch
// bk010221 - old location of FPE hack and divide by zero expression
//if the whole to be traced line is totally at the front of this node
//only go down the tree with the front child
if ((front >= -ON_EPSILON && back >= -ON_EPSILON))
{
//keep the current start and end point on the stack
//and go down the tree with the front child
tstack_p->nodenum = aasnode->children[0];
tstack_p++;
if (tstack_p >= &tracestack[127])
{
botimport.Print(PRT_ERROR, "AAS_TraceBoundingBox: stack overflow\n");
return trace;
} //end if
} //end if
//if the whole to be traced line is totally at the back of this node
//only go down the tree with the back child
else if ((front < ON_EPSILON && back < ON_EPSILON))
{
//keep the current start and end point on the stack
//and go down the tree with the back child
tstack_p->nodenum = aasnode->children[1];
tstack_p++;
if (tstack_p >= &tracestack[127])
{
botimport.Print(PRT_ERROR, "AAS_TraceBoundingBox: stack overflow\n");
return trace;
} //end if
} //end if
//go down the tree both at the front and back of the node
else
{
tmpplanenum = tstack_p->planenum;
// bk010221 - new location of divide by zero (see above)
if ( front == back ) front -= 0.001f; // bk0101022 - hack/FPE
//calculate the hitpoint with the node (split point of the line)
//put the crosspoint TRACEPLANE_EPSILON pixels on the near side
if (front < 0) frac = (front + TRACEPLANE_EPSILON)/(front-back);
else frac = (front - TRACEPLANE_EPSILON)/(front-back); // bk010221
//
if (frac < 0)
frac = 0.001f; //0
else if (frac > 1)
frac = 0.999f; //1
//frac = front / (front-back);
//
cur_mid[0] = cur_start[0] + (cur_end[0] - cur_start[0]) * frac;
cur_mid[1] = cur_start[1] + (cur_end[1] - cur_start[1]) * frac;
cur_mid[2] = cur_start[2] + (cur_end[2] - cur_start[2]) * frac;
// AAS_DrawPlaneCross(cur_mid, plane->normal, plane->dist, plane->type, LINECOLOR_RED);
//side the front part of the line is on
side = front < 0;
//first put the end part of the line on the stack (back side)
VectorCopy(cur_mid, tstack_p->start);
//not necesary to store because still on stack
//VectorCopy(cur_end, tstack_p->end);
tstack_p->planenum = aasnode->planenum;
tstack_p->nodenum = aasnode->children[!side];
tstack_p++;
if (tstack_p >= &tracestack[127])
{
botimport.Print(PRT_ERROR, "AAS_TraceBoundingBox: stack overflow\n");
return trace;
} //end if
//now put the part near the start of the line on the stack so we will
//continue with thats part first. This way we'll find the first
//hit of the bbox
VectorCopy(cur_start, tstack_p->start);
VectorCopy(cur_mid, tstack_p->end);
tstack_p->planenum = tmpplanenum;
tstack_p->nodenum = aasnode->children[side];
tstack_p++;
if (tstack_p >= &tracestack[127])
{
botimport.Print(PRT_ERROR, "AAS_TraceBoundingBox: stack overflow\n");
return trace;
} //end if
} //end else
} //end while
// return trace;
} //end of the function AAS_TraceClientBBox
//===========================================================================
// recursive subdivision of the line by the BSP tree.
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int AAS_TraceAreas(vec3_t start, vec3_t end, int *areas, vec3_t *points, int maxareas)
{
int side, nodenum, tmpplanenum;
int numareas;
float front, back, frac;
vec3_t cur_start, cur_end, cur_mid;
aas_tracestack_t tracestack[127];
aas_tracestack_t *tstack_p;
aas_node_t *aasnode;
aas_plane_t *plane;
numareas = 0;
areas[0] = 0;
if (!aasworld.loaded) return numareas;
tstack_p = tracestack;
//we start with the whole line on the stack
VectorCopy(start, tstack_p->start);
VectorCopy(end, tstack_p->end);
tstack_p->planenum = 0;
//start with node 1 because node zero is a dummy for a solid leaf
tstack_p->nodenum = 1; //starting at the root of the tree
tstack_p++;
while (1)
{
//pop up the stack
tstack_p--;
//if the trace stack is empty (ended up with a piece of the
//line to be traced in an area)
if (tstack_p < tracestack)
{
return numareas;
} //end if
//number of the current node to test the line against
nodenum = tstack_p->nodenum;
//if it is an area
if (nodenum < 0)
{
#ifdef AAS_SAMPLE_DEBUG
if (-nodenum > aasworld.numareasettings)
{
botimport.Print(PRT_ERROR, "AAS_TraceAreas: -nodenum = %d out of range\n", -nodenum);
return numareas;
} //end if
#endif //AAS_SAMPLE_DEBUG
//botimport.Print(PRT_MESSAGE, "areanum = %d, must be %d\n", -nodenum, AAS_PointAreaNum(start));
areas[numareas] = -nodenum;
if (points) VectorCopy(tstack_p->start, points[numareas]);
numareas++;
if (numareas >= maxareas) return numareas;
continue;
} //end if
//if it is a solid leaf
if (!nodenum)
{
continue;
} //end if
#ifdef AAS_SAMPLE_DEBUG
if (nodenum > aasworld.numnodes)
{
botimport.Print(PRT_ERROR, "AAS_TraceAreas: nodenum out of range\n");
return numareas;
} //end if
#endif //AAS_SAMPLE_DEBUG
//the node to test against
aasnode = &aasworld.nodes[nodenum];
//start point of current line to test against node
VectorCopy(tstack_p->start, cur_start);
//end point of the current line to test against node
VectorCopy(tstack_p->end, cur_end);
//the current node plane
plane = &aasworld.planes[aasnode->planenum];
switch(plane->type)
{/*FIXME: wtf doesn't this work? obviously the node planes aren't always facing positive!!!
//check for axial planes
case PLANE_X:
{
front = cur_start[0] - plane->dist;
back = cur_end[0] - plane->dist;
break;
} //end case
case PLANE_Y:
{
front = cur_start[1] - plane->dist;
back = cur_end[1] - plane->dist;
break;
} //end case
case PLANE_Z:
{
front = cur_start[2] - plane->dist;
back = cur_end[2] - plane->dist;
break;
} //end case*/
default: //gee it's not an axial plane
{
front = DotProduct(cur_start, plane->normal) - plane->dist;
back = DotProduct(cur_end, plane->normal) - plane->dist;
break;
} //end default
} //end switch
//if the whole to be traced line is totally at the front of this node
//only go down the tree with the front child
if (front > 0 && back > 0)
{
//keep the current start and end point on the stack
//and go down the tree with the front child
tstack_p->nodenum = aasnode->children[0];
tstack_p++;
if (tstack_p >= &tracestack[127])
{
botimport.Print(PRT_ERROR, "AAS_TraceAreas: stack overflow\n");
return numareas;
} //end if
} //end if
//if the whole to be traced line is totally at the back of this node
//only go down the tree with the back child
else if (front <= 0 && back <= 0)
{
//keep the current start and end point on the stack
//and go down the tree with the back child
tstack_p->nodenum = aasnode->children[1];
tstack_p++;
if (tstack_p >= &tracestack[127])
{
botimport.Print(PRT_ERROR, "AAS_TraceAreas: stack overflow\n");
return numareas;
} //end if
} //end if
//go down the tree both at the front and back of the node
else
{
tmpplanenum = tstack_p->planenum;
//calculate the hitpoint with the node (split point of the line)
//put the crosspoint TRACEPLANE_EPSILON pixels on the near side
if (front < 0) frac = (front)/(front-back);
else frac = (front)/(front-back);
if (frac < 0) frac = 0;
else if (frac > 1) frac = 1;
//frac = front / (front-back);
//
cur_mid[0] = cur_start[0] + (cur_end[0] - cur_start[0]) * frac;
cur_mid[1] = cur_start[1] + (cur_end[1] - cur_start[1]) * frac;
cur_mid[2] = cur_start[2] + (cur_end[2] - cur_start[2]) * frac;
// AAS_DrawPlaneCross(cur_mid, plane->normal, plane->dist, plane->type, LINECOLOR_RED);
//side the front part of the line is on
side = front < 0;
//first put the end part of the line on the stack (back side)
VectorCopy(cur_mid, tstack_p->start);
//not necesary to store because still on stack
//VectorCopy(cur_end, tstack_p->end);
tstack_p->planenum = aasnode->planenum;
tstack_p->nodenum = aasnode->children[!side];
tstack_p++;
if (tstack_p >= &tracestack[127])
{
botimport.Print(PRT_ERROR, "AAS_TraceAreas: stack overflow\n");
return numareas;
} //end if
//now put the part near the start of the line on the stack so we will
//continue with thats part first. This way we'll find the first
//hit of the bbox
VectorCopy(cur_start, tstack_p->start);
VectorCopy(cur_mid, tstack_p->end);
tstack_p->planenum = tmpplanenum;
tstack_p->nodenum = aasnode->children[side];
tstack_p++;
if (tstack_p >= &tracestack[127])
{
botimport.Print(PRT_ERROR, "AAS_TraceAreas: stack overflow\n");
return numareas;
} //end if
} //end else
} //end while
// return numareas;
} //end of the function AAS_TraceAreas
//===========================================================================
// a simple cross product
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
// void AAS_OrthogonalToVectors(vec3_t v1, vec3_t v2, vec3_t res)
#define AAS_OrthogonalToVectors(v1, v2, res) \
(res)[0] = ((v1)[1] * (v2)[2]) - ((v1)[2] * (v2)[1]);\
(res)[1] = ((v1)[2] * (v2)[0]) - ((v1)[0] * (v2)[2]);\
(res)[2] = ((v1)[0] * (v2)[1]) - ((v1)[1] * (v2)[0]);
//===========================================================================
// tests if the given point is within the face boundaries
//
// Parameter: face : face to test if the point is in it
// pnormal : normal of the plane to use for the face
// point : point to test if inside face boundaries
// Returns: qtrue if the point is within the face boundaries
// Changes Globals: -
//===========================================================================
qboolean AAS_InsideFace(aas_face_t *face, vec3_t pnormal, vec3_t point, float epsilon)
{
int i, firstvertex, edgenum;
vec3_t v0;
vec3_t edgevec, pointvec, sepnormal;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -