|
|
1.1 ! root 1: // r_efrag.c ! 2: ! 3: #include "quakedef.h" ! 4: #include "r_local.h" ! 5: ! 6: mnode_t *r_pefragtopnode; ! 7: ! 8: ! 9: //=========================================================================== ! 10: ! 11: /* ! 12: =============================================================================== ! 13: ! 14: ENTITY FRAGMENT FUNCTIONS ! 15: ! 16: =============================================================================== ! 17: */ ! 18: ! 19: efrag_t **lastlink; ! 20: ! 21: vec3_t r_emins, r_emaxs; ! 22: ! 23: entity_t *r_addent; ! 24: ! 25: ! 26: /* ! 27: ================ ! 28: R_RemoveEfrags ! 29: ! 30: Call when removing an object from the world or moving it to another position ! 31: ================ ! 32: */ ! 33: void R_RemoveEfrags (entity_t *ent) ! 34: { ! 35: efrag_t *ef, *old, *walk, **prev; ! 36: ! 37: ef = ent->efrag; ! 38: ! 39: while (ef) ! 40: { ! 41: prev = &ef->leaf->efrags; ! 42: while (1) ! 43: { ! 44: walk = *prev; ! 45: if (!walk) ! 46: break; ! 47: if (walk == ef) ! 48: { // remove this fragment ! 49: *prev = ef->leafnext; ! 50: break; ! 51: } ! 52: else ! 53: prev = &walk->leafnext; ! 54: } ! 55: ! 56: old = ef; ! 57: ef = ef->entnext; ! 58: ! 59: // put it on the free list ! 60: old->entnext = cl.free_efrags; ! 61: cl.free_efrags = old; ! 62: } ! 63: ! 64: ent->efrag = NULL; ! 65: } ! 66: ! 67: /* ! 68: =================== ! 69: R_SplitEntityOnNode ! 70: =================== ! 71: */ ! 72: void R_SplitEntityOnNode (mnode_t *node) ! 73: { ! 74: efrag_t *ef; ! 75: mplane_t *splitplane; ! 76: mleaf_t *leaf; ! 77: int sides; ! 78: ! 79: if (node->contents == CONTENTS_SOLID) ! 80: { ! 81: return; ! 82: } ! 83: ! 84: // add an efrag if the node is a leaf ! 85: ! 86: if ( node->contents < 0) ! 87: { ! 88: if (!r_pefragtopnode) ! 89: r_pefragtopnode = node; ! 90: ! 91: leaf = (mleaf_t *)node; ! 92: ! 93: // grab an efrag off the free list ! 94: ef = cl.free_efrags; ! 95: if (!ef) ! 96: { ! 97: Con_Printf ("Too many efrags!\n"); ! 98: return; // no free fragments... ! 99: } ! 100: cl.free_efrags = cl.free_efrags->entnext; ! 101: ! 102: ef->entity = r_addent; ! 103: ! 104: // add the entity link ! 105: *lastlink = ef; ! 106: lastlink = &ef->entnext; ! 107: ef->entnext = NULL; ! 108: ! 109: // set the leaf links ! 110: ef->leaf = leaf; ! 111: ef->leafnext = leaf->efrags; ! 112: leaf->efrags = ef; ! 113: ! 114: return; ! 115: } ! 116: ! 117: // NODE_MIXED ! 118: ! 119: splitplane = node->plane; ! 120: sides = BOX_ON_PLANE_SIDE(r_emins, r_emaxs, splitplane); ! 121: ! 122: if (sides == 3) ! 123: { ! 124: // split on this plane ! 125: // if this is the first splitter of this bmodel, remember it ! 126: if (!r_pefragtopnode) ! 127: r_pefragtopnode = node; ! 128: } ! 129: ! 130: // recurse down the contacted sides ! 131: if (sides & 1) ! 132: R_SplitEntityOnNode (node->children[0]); ! 133: ! 134: if (sides & 2) ! 135: R_SplitEntityOnNode (node->children[1]); ! 136: } ! 137: ! 138: ! 139: /* ! 140: =================== ! 141: R_SplitEntityOnNode2 ! 142: =================== ! 143: */ ! 144: void R_SplitEntityOnNode2 (mnode_t *node) ! 145: { ! 146: mplane_t *splitplane; ! 147: int sides; ! 148: ! 149: if (node->visframe != r_visframecount) ! 150: return; ! 151: ! 152: if (node->contents < 0) ! 153: { ! 154: if (node->contents != CONTENTS_SOLID) ! 155: r_pefragtopnode = node; // we've reached a non-solid leaf, so it's ! 156: // visible and not BSP clipped ! 157: return; ! 158: } ! 159: ! 160: splitplane = node->plane; ! 161: sides = BOX_ON_PLANE_SIDE(r_emins, r_emaxs, splitplane); ! 162: ! 163: if (sides == 3) ! 164: { ! 165: // remember first splitter ! 166: r_pefragtopnode = node; ! 167: return; ! 168: } ! 169: ! 170: // not split yet; recurse down the contacted side ! 171: if (sides & 1) ! 172: R_SplitEntityOnNode2 (node->children[0]); ! 173: else ! 174: R_SplitEntityOnNode2 (node->children[1]); ! 175: } ! 176: ! 177: ! 178: /* ! 179: =========== ! 180: R_AddEfrags ! 181: =========== ! 182: */ ! 183: void R_AddEfrags (entity_t *ent) ! 184: { ! 185: model_t *entmodel; ! 186: int i; ! 187: ! 188: if (!ent->model) ! 189: return; ! 190: ! 191: if (ent == cl_entities) ! 192: return; // never add the world ! 193: ! 194: r_addent = ent; ! 195: ! 196: lastlink = &ent->efrag; ! 197: r_pefragtopnode = NULL; ! 198: ! 199: entmodel = ent->model; ! 200: ! 201: for (i=0 ; i<3 ; i++) ! 202: { ! 203: r_emins[i] = ent->origin[i] + entmodel->mins[i]; ! 204: r_emaxs[i] = ent->origin[i] + entmodel->maxs[i]; ! 205: } ! 206: ! 207: R_SplitEntityOnNode (cl.worldmodel->nodes); ! 208: ! 209: ent->topnode = r_pefragtopnode; ! 210: } ! 211: ! 212: ! 213: /* ! 214: ================ ! 215: R_StoreEfrags ! 216: ! 217: // FIXME: a lot of this goes away with edge-based ! 218: ================ ! 219: */ ! 220: void R_StoreEfrags (efrag_t **ppefrag) ! 221: { ! 222: entity_t *pent; ! 223: model_t *clmodel; ! 224: efrag_t *pefrag; ! 225: ! 226: ! 227: while ((pefrag = *ppefrag) != NULL) ! 228: { ! 229: pent = pefrag->entity; ! 230: clmodel = pent->model; ! 231: ! 232: switch (clmodel->type) ! 233: { ! 234: case mod_alias: ! 235: case mod_brush: ! 236: case mod_sprite: ! 237: pent = pefrag->entity; ! 238: ! 239: if ((pent->visframe != r_framecount) && ! 240: (cl_numvisedicts < MAX_VISEDICTS)) ! 241: { ! 242: cl_visedicts[cl_numvisedicts++] = pent; ! 243: ! 244: // mark that we've recorded this entity for this frame ! 245: pent->visframe = r_framecount; ! 246: } ! 247: ! 248: ppefrag = &pefrag->leafnext; ! 249: break; ! 250: ! 251: default: ! 252: Sys_Error ("R_StoreEfrags: Bad entity type %d\n", clmodel->type); ! 253: } ! 254: } ! 255: } ! 256: ! 257:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.