Home | History | Annotate | Download | only in client
      1 /*
      2 Copyright (C) 1996-1997 Id Software, Inc.
      3 
      4 This program is free software; you can redistribute it and/or
      5 modify it under the terms of the GNU General Public License
      6 as published by the Free Software Foundation; either version 2
      7 of the License, or (at your option) any later version.
      8 
      9 This program is distributed in the hope that it will be useful,
     10 but WITHOUT ANY WARRANTY; without even the implied warranty of
     11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
     12 
     13 See the GNU General Public License for more details.
     14 
     15 You should have received a copy of the GNU General Public License
     16 along with this program; if not, write to the Free Software
     17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
     18 
     19 */
     20 // r_efrag.c
     21 
     22 #include "quakedef.h"
     23 
     24 mnode_t	*r_pefragtopnode;
     25 
     26 
     27 //===========================================================================
     28 
     29 /*
     30 ===============================================================================
     31 
     32 					ENTITY FRAGMENT FUNCTIONS
     33 
     34 ===============================================================================
     35 */
     36 
     37 efrag_t		**lastlink;
     38 
     39 vec3_t		r_emins, r_emaxs;
     40 
     41 entity_t	*r_addent;
     42 
     43 
     44 /*
     45 ================
     46 R_RemoveEfrags
     47 
     48 Call when removing an object from the world or moving it to another position
     49 ================
     50 */
     51 void R_RemoveEfrags (entity_t *ent)
     52 {
     53 	efrag_t		*ef, *old, *walk, **prev;
     54 
     55 	ef = ent->efrag;
     56 
     57 	while (ef)
     58 	{
     59 		prev = &ef->leaf->efrags;
     60 		while (1)
     61 		{
     62 			walk = *prev;
     63 			if (!walk)
     64 				break;
     65 			if (walk == ef)
     66 			{	// remove this fragment
     67 				*prev = ef->leafnext;
     68 				break;
     69 			}
     70 			else
     71 				prev = &walk->leafnext;
     72 		}
     73 
     74 		old = ef;
     75 		ef = ef->entnext;
     76 
     77 	// put it on the free list
     78 		old->entnext = cl.free_efrags;
     79 		cl.free_efrags = old;
     80 	}
     81 
     82 	ent->efrag = NULL;
     83 }
     84 
     85 /*
     86 ===================
     87 R_SplitEntityOnNode
     88 ===================
     89 */
     90 void R_SplitEntityOnNode (mnode_t *node)
     91 {
     92 	efrag_t		*ef;
     93 	mplane_t	*splitplane;
     94 	mleaf_t		*leaf;
     95 	int			sides;
     96 
     97 	if (node->contents == CONTENTS_SOLID)
     98 	{
     99 		return;
    100 	}
    101 
    102 // add an efrag if the node is a leaf
    103 
    104 	if ( node->contents < 0)
    105 	{
    106 		if (!r_pefragtopnode)
    107 			r_pefragtopnode = node;
    108 
    109 		leaf = (mleaf_t *)node;
    110 
    111 // grab an efrag off the free list
    112 		ef = cl.free_efrags;
    113 		if (!ef)
    114 		{
    115 			Con_Printf ("Too many efrags!\n");
    116 			return;		// no free fragments...
    117 		}
    118 		cl.free_efrags = cl.free_efrags->entnext;
    119 
    120 		ef->entity = r_addent;
    121 
    122 // add the entity link
    123 		*lastlink = ef;
    124 		lastlink = &ef->entnext;
    125 		ef->entnext = NULL;
    126 
    127 // set the leaf links
    128 		ef->leaf = leaf;
    129 		ef->leafnext = leaf->efrags;
    130 		leaf->efrags = ef;
    131 
    132 		return;
    133 	}
    134 
    135 // NODE_MIXED
    136 
    137 	splitplane = node->plane;
    138 	sides = BOX_ON_PLANE_SIDE(r_emins, r_emaxs, splitplane);
    139 
    140 	if (sides == 3)
    141 	{
    142 	// split on this plane
    143 	// if this is the first splitter of this bmodel, remember it
    144 		if (!r_pefragtopnode)
    145 			r_pefragtopnode = node;
    146 	}
    147 
    148 // recurse down the contacted sides
    149 	if (sides & 1)
    150 		R_SplitEntityOnNode (node->children[0]);
    151 
    152 	if (sides & 2)
    153 		R_SplitEntityOnNode (node->children[1]);
    154 }
    155 
    156 
    157 
    158 /*
    159 ===========
    160 R_AddEfrags
    161 ===========
    162 */
    163 void R_AddEfrags (entity_t *ent)
    164 {
    165 	model_t		*entmodel;
    166 	int			i;
    167 
    168 	if (!ent->model)
    169 		return;
    170 
    171 	r_addent = ent;
    172 
    173 	lastlink = &ent->efrag;
    174 	r_pefragtopnode = NULL;
    175 
    176 	entmodel = ent->model;
    177 
    178 	for (i=0 ; i<3 ; i++)
    179 	{
    180 		r_emins[i] = ent->origin[i] + entmodel->mins[i];
    181 		r_emaxs[i] = ent->origin[i] + entmodel->maxs[i];
    182 	}
    183 
    184 	R_SplitEntityOnNode (cl.worldmodel->nodes);
    185 
    186 	ent->topnode = r_pefragtopnode;
    187 }
    188 
    189 
    190 /*
    191 ================
    192 R_StoreEfrags
    193 
    194 // FIXME: a lot of this goes away with edge-based
    195 ================
    196 */
    197 void R_StoreEfrags (efrag_t **ppefrag)
    198 {
    199 	entity_t	*pent;
    200 	model_t		*clmodel;
    201 	efrag_t		*pefrag;
    202 
    203 
    204 	while ((pefrag = *ppefrag) != NULL)
    205 	{
    206 		pent = pefrag->entity;
    207 		clmodel = pent->model;
    208 
    209 		switch (clmodel->type)
    210 		{
    211 		case mod_alias:
    212 		case mod_brush:
    213 		case mod_sprite:
    214 			pent = pefrag->entity;
    215 
    216 			if ((pent->visframe != r_framecount) &&
    217 				(cl_numvisedicts < MAX_VISEDICTS))
    218 			{
    219 				cl_visedicts[cl_numvisedicts++] = *pent;
    220 
    221 			// mark that we've recorded this entity for this frame
    222 				pent->visframe = r_framecount;
    223 			}
    224 
    225 			ppefrag = &pefrag->leafnext;
    226 			break;
    227 
    228 		default:
    229 			Sys_Error ("R_StoreEfrags: Bad entity type %d\n", clmodel->type);
    230 		}
    231 	}
    232 }
    233 
    234 
    235