123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235 |
- /*
- Copyright (C) 1996-1997 Id Software, Inc.
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License
- as published by the Free Software Foundation; either version 2
- of the License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
- // r_efrag.c
- #include "quakedef.h"
- mnode_t *r_pefragtopnode;
- //===========================================================================
- /*
- ===============================================================================
- ENTITY FRAGMENT FUNCTIONS
- ===============================================================================
- */
- efrag_t **lastlink;
- vec3_t r_emins, r_emaxs;
- entity_t *r_addent;
- /*
- ================
- R_RemoveEfrags
- Call when removing an object from the world or moving it to another position
- ================
- */
- void R_RemoveEfrags (entity_t *ent)
- {
- efrag_t *ef, *old, *walk, **prev;
-
- ef = ent->efrag;
-
- while (ef)
- {
- prev = &ef->leaf->efrags;
- while (1)
- {
- walk = *prev;
- if (!walk)
- break;
- if (walk == ef)
- { // remove this fragment
- *prev = ef->leafnext;
- break;
- }
- else
- prev = &walk->leafnext;
- }
-
- old = ef;
- ef = ef->entnext;
-
- // put it on the free list
- old->entnext = cl.free_efrags;
- cl.free_efrags = old;
- }
-
- ent->efrag = NULL;
- }
- /*
- ===================
- R_SplitEntityOnNode
- ===================
- */
- void R_SplitEntityOnNode (mnode_t *node)
- {
- efrag_t *ef;
- mplane_t *splitplane;
- mleaf_t *leaf;
- int sides;
-
- if (node->contents == CONTENTS_SOLID)
- {
- return;
- }
-
- // add an efrag if the node is a leaf
- if ( node->contents < 0)
- {
- if (!r_pefragtopnode)
- r_pefragtopnode = node;
- leaf = (mleaf_t *)node;
- // grab an efrag off the free list
- ef = cl.free_efrags;
- if (!ef)
- {
- Con_Printf ("Too many efrags!\n");
- return; // no free fragments...
- }
- cl.free_efrags = cl.free_efrags->entnext;
- ef->entity = r_addent;
-
- // add the entity link
- *lastlink = ef;
- lastlink = &ef->entnext;
- ef->entnext = NULL;
-
- // set the leaf links
- ef->leaf = leaf;
- ef->leafnext = leaf->efrags;
- leaf->efrags = ef;
-
- return;
- }
-
- // NODE_MIXED
- splitplane = node->plane;
- sides = BOX_ON_PLANE_SIDE(r_emins, r_emaxs, splitplane);
-
- if (sides == 3)
- {
- // split on this plane
- // if this is the first splitter of this bmodel, remember it
- if (!r_pefragtopnode)
- r_pefragtopnode = node;
- }
-
- // recurse down the contacted sides
- if (sides & 1)
- R_SplitEntityOnNode (node->children[0]);
-
- if (sides & 2)
- R_SplitEntityOnNode (node->children[1]);
- }
- /*
- ===========
- R_AddEfrags
- ===========
- */
- void R_AddEfrags (entity_t *ent)
- {
- model_t *entmodel;
- int i;
-
- if (!ent->model)
- return;
- r_addent = ent;
-
- lastlink = &ent->efrag;
- r_pefragtopnode = NULL;
-
- entmodel = ent->model;
- for (i=0 ; i<3 ; i++)
- {
- r_emins[i] = ent->origin[i] + entmodel->mins[i];
- r_emaxs[i] = ent->origin[i] + entmodel->maxs[i];
- }
- R_SplitEntityOnNode (cl.worldmodel->nodes);
- ent->topnode = r_pefragtopnode;
- }
- /*
- ================
- R_StoreEfrags
- // FIXME: a lot of this goes away with edge-based
- ================
- */
- void R_StoreEfrags (efrag_t **ppefrag)
- {
- entity_t *pent;
- model_t *clmodel;
- efrag_t *pefrag;
- while ((pefrag = *ppefrag) != NULL)
- {
- pent = pefrag->entity;
- clmodel = pent->model;
- switch (clmodel->type)
- {
- case mod_alias:
- case mod_brush:
- case mod_sprite:
- pent = pefrag->entity;
- if ((pent->visframe != r_framecount) &&
- (cl_numvisedicts < MAX_VISEDICTS))
- {
- cl_visedicts[cl_numvisedicts++] = *pent;
- // mark that we've recorded this entity for this frame
- pent->visframe = r_framecount;
- }
- ppefrag = &pefrag->leafnext;
- break;
- default:
- Sys_Error ("R_StoreEfrags: Bad entity type %d\n", clmodel->type);
- }
- }
- }
|