home *** CD-ROM | disk | FTP | other *** search
- /*
- 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);
- }
- }
- }
-
-
-