|
|
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.