/* * =============================================================================== * * Trace through the spatial subdivision * * =============================================================================== */ /* * ================ * idCollisionModelManagerLocal::TraceTrmThroughNode * ================ */ void idCollisionModelManagerLocal::TraceTrmThroughNode(cm_traceWork_t *tw, cm_node_t *node) { cm_polygonRef_t *pref; cm_brushRef_t * bref; // position test if (tw->positionTest) { // if already stuck in solid if (tw->trace.fraction == 0.0f) { return; } // test if any of the trm vertices is inside a brush for (bref = node->brushes; bref; bref = bref->next) { if (idCollisionModelManagerLocal::TestTrmVertsInBrush(tw, bref->b)) { return; } } // if just testing a point we're done if (tw->pointTrace) { return; } // test if the trm is stuck in any polygons for (pref = node->polygons; pref; pref = pref->next) { if (idCollisionModelManagerLocal::TestTrmInPolygon(tw, pref->p)) { return; } } } else if (tw->rotation) { // rotate through all polygons in this leaf for (pref = node->polygons; pref; pref = pref->next) { if (idCollisionModelManagerLocal::RotateTrmThroughPolygon(tw, pref->p)) { return; } } } else { // trace through all polygons in this leaf for (pref = node->polygons; pref; pref = pref->next) { if (idCollisionModelManagerLocal::TranslateTrmThroughPolygon(tw, pref->p)) { return; } } } }
/* * ================ * idCollisionModelManagerLocal::WriteNodes * ================ */ void idCollisionModelManagerLocal::WriteNodes(idFile *fp, cm_node_t *node) { fp->WriteFloatString("\t( %d %f )\n", node->planeType, node->planeDist); if (node->planeType != -1) { WriteNodes(fp, node->children[0]); WriteNodes(fp, node->children[1]); } }
/* * ================ * idCollisionModelManagerLocal::TraceThroughAxialBSPTree_r * ================ */ //#define NO_SPATIAL_SUBDIVISION void idCollisionModelManagerLocal::TraceThroughAxialBSPTree_r(cm_traceWork_t *tw, cm_node_t *node, float p1f, float p2f, idVec3&p1, idVec3&p2) { float t1, t2, offset; float frac, frac2; float idist; idVec3 mid; int side; float midf; if (!node) { return; } if (tw->quickExit) { return; // stop immediately } if (tw->trace.fraction <= p1f) { return; // already hit something nearer } // if we need to test this node for collisions if (node->polygons || (tw->positionTest && node->brushes)) { // trace through node with collision data idCollisionModelManagerLocal::TraceTrmThroughNode(tw, node); } // if already stuck in solid if (tw->positionTest && tw->trace.fraction == 0.0f) { return; } // if this is a leaf node if (node->planeType == -1) { return; } #ifdef NO_SPATIAL_SUBDIVISION idCollisionModelManagerLocal::TraceThroughAxialBSPTree_r(tw, node->children[0], p1f, p2f, p1, p2); idCollisionModelManagerLocal::TraceThroughAxialBSPTree_r(tw, node->children[1], p1f, p2f, p1, p2); return; #endif // distance from plane for trace start and end t1 = p1[node->planeType] - node->planeDist; t2 = p2[node->planeType] - node->planeDist; // adjust the plane distance appropriately for mins/maxs offset = tw->extents[node->planeType]; // see which sides we need to consider if (t1 >= offset && t2 >= offset) { idCollisionModelManagerLocal::TraceThroughAxialBSPTree_r(tw, node->children[0], p1f, p2f, p1, p2); return; } if (t1 < -offset && t2 < -offset) { idCollisionModelManagerLocal::TraceThroughAxialBSPTree_r(tw, node->children[1], p1f, p2f, p1, p2); return; } if (t1 < t2) { idist = 1.0f / (t1 - t2); side = 1; frac2 = (t1 + offset) * idist; frac = (t1 - offset) * idist; } else if (t1 > t2) { idist = 1.0f / (t1 - t2); side = 0; frac2 = (t1 - offset) * idist; frac = (t1 + offset) * idist; } else { side = 0; frac = 1.0f; frac2 = 0.0f; } // move up to the node if (frac < 0.0f) { frac = 0.0f; } else if (frac > 1.0f) { frac = 1.0f; } midf = p1f + (p2f - p1f) * frac; mid[0] = p1[0] + frac * (p2[0] - p1[0]); mid[1] = p1[1] + frac * (p2[1] - p1[1]); mid[2] = p1[2] + frac * (p2[2] - p1[2]); idCollisionModelManagerLocal::TraceThroughAxialBSPTree_r(tw, node->children[side], p1f, midf, p1, mid); // go past the node if (frac2 < 0.0f) { frac2 = 0.0f; } else if (frac2 > 1.0f) { frac2 = 1.0f; } midf = p1f + (p2f - p1f) * frac2; mid[0] = p1[0] + frac2 * (p2[0] - p1[0]); mid[1] = p1[1] + frac2 * (p2[1] - p1[1]); mid[2] = p1[2] + frac2 * (p2[2] - p1[2]); idCollisionModelManagerLocal::TraceThroughAxialBSPTree_r(tw, node->children[side ^ 1], midf, p2f, mid, p2); }
/* * ================ * idCollisionModelManagerLocal::CountPolygonMemory * ================ */ int idCollisionModelManagerLocal::CountPolygonMemory(cm_node_t *node) const
int CM_GetNodeContents(cm_node_t *node);
/* * =============================================================================== * * Writing of collision model file * * =============================================================================== */ void CM_GetNodeBounds(idBounds *bounds, cm_node_t *node);