/* * This function calls a select search of the given array, * based on the provided index * * @param arrayToSort input as reference array to sort * @param startOfArray start of the array to sort * @param endOfArray end of the array to sort * @param index ith order element to find * @return int the value of the ith order index */ int Select(int arrayToSort[], int startOfArray, int endOfArray, int index) { int k = 0, q = 0; int medianValue = 0, pivot = 0; if (startOfArray == endOfArray) { return arrayToSort[endOfArray]; } medianValue = MedianOfMedians(arrayToSort, startOfArray, endOfArray); pivot = SelectPartition(arrayToSort, startOfArray, endOfArray, medianValue); if (pivot == (index - 1)) { return arrayToSort[pivot]; } else if (pivot > (index - 1)) { return Select(arrayToSort, startOfArray, pivot - 1, index); } else { return Select(arrayToSort, pivot + 1, endOfArray, index); } }
/* ================== PartitionSurfaces ================== */ static void PartitionSurfaces(surface_t *surfaces, node_t *node) { surface_t *split, *p, *next; surface_t *frontlist, *backlist; surface_t *frontfrag, *backfrag; plane_t *splitplane; split = SelectPartition(surfaces); if (!split) { // this is a leaf node node->planenum = PLANENUM_LEAF; LinkConvexFaces(surfaces, node); return; } splitnodes++; Message(msgPercent, splitnodes, csgmergefaces); node->faces = LinkNodeFaces(split); node->children[0] = AllocMem(NODE, 1, true); node->children[1] = AllocMem(NODE, 1, true); node->planenum = split->planenum; splitplane = &pPlanes[split->planenum]; DivideNodeBounds(node, splitplane); // multiple surfaces, so split all the polysurfaces into front and back lists frontlist = NULL; backlist = NULL; for (p = surfaces; p; p = next) { next = p->next; DividePlane(p, splitplane, &frontfrag, &backfrag); if (frontfrag && backfrag) { // the plane was split, which may expose oportunities to merge // adjacent faces into a single face // MergePlaneFaces (frontfrag); // MergePlaneFaces (backfrag); } if (frontfrag) { if (!frontfrag->faces) Message(msgError, errNoSurfaceFaces); frontfrag->next = frontlist; frontlist = frontfrag; } if (backfrag) { if (!backfrag->faces) Message(msgError, errNoSurfaceFaces); backfrag->next = backlist; backlist = backfrag; } } PartitionSurfaces(frontlist, node->children[0]); PartitionSurfaces(backlist, node->children[1]); }
/* ================== BuildBspTree_r ================== */ void BuildBspTree_r (node_t *node) { surface_t *split; qboolean midsplit; surface_t *allsurfs; midsplit = CalcNodeBounds (node); DrawSurfaces (node->surfaces); split = SelectPartition (node->surfaces, node, midsplit); if (!split) { // this is a leaf node node->planenum = PLANENUM_LEAF; LinkLeafFaces (node->surfaces, node); return; } // // these are final polygons // split->onnode = node; // can't use again allsurfs = node->surfaces; node->planenum = split->planenum; node->faces = NULL; CopyFacesToNode (node, split); c_splitnodes++; node->children[0] = AllocNode (); node->children[1] = AllocNode (); // // split all the polysurfaces into front and back lists // SplitNodeSurfaces (allsurfs, node); // // create the portal that seperates the two children // MakeNodePortal (node); // // carve the portals on the boundaries of the node // SplitNodePortals (node); // // recursively do the children // BuildBspTree_r (node->children[0]); BuildBspTree_r (node->children[1]); }