Quake-III-Arena

Quake III Arena GPL Source Release
Log | Files | Refs

prtfile.c (6245B)


      1 /*
      2 ===========================================================================
      3 Copyright (C) 1999-2005 Id Software, Inc.
      4 
      5 This file is part of Quake III Arena source code.
      6 
      7 Quake III Arena source code is free software; you can redistribute it
      8 and/or modify it under the terms of the GNU General Public License as
      9 published by the Free Software Foundation; either version 2 of the License,
     10 or (at your option) any later version.
     11 
     12 Quake III Arena source code is distributed in the hope that it will be
     13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 GNU General Public License for more details.
     16 
     17 You should have received a copy of the GNU General Public License
     18 along with Foobar; if not, write to the Free Software
     19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     20 ===========================================================================
     21 */
     22 
     23 #include "qbsp.h"
     24 
     25 /*
     26 ==============================================================================
     27 
     28 PORTAL FILE GENERATION
     29 
     30 Save out name.prt for qvis to read
     31 ==============================================================================
     32 */
     33 
     34 
     35 #define	PORTALFILE	"PRT1"
     36 
     37 FILE	*pf;
     38 int		num_visclusters;				// clusters the player can be in
     39 int		num_visportals;
     40 
     41 void WriteFloat2 (FILE *f, vec_t v)
     42 {
     43 	if ( fabs(v - Q_rint(v)) < 0.001 )
     44 		fprintf (f,"%i ",(int)Q_rint(v));
     45 	else
     46 		fprintf (f,"%f ",v);
     47 }
     48 
     49 /*
     50 =================
     51 WritePortalFile_r
     52 =================
     53 */
     54 void WritePortalFile_r (node_t *node)
     55 {
     56 	int			i, s;	
     57 	portal_t	*p;
     58 	winding_t	*w;
     59 	vec3_t		normal;
     60 	vec_t		dist;
     61 
     62 	// decision node
     63 	if (node->planenum != PLANENUM_LEAF && !node->detail_seperator)
     64 	{
     65 		WritePortalFile_r (node->children[0]);
     66 		WritePortalFile_r (node->children[1]);
     67 		return;
     68 	}
     69 	
     70 	if (node->contents & CONTENTS_SOLID)
     71 		return;
     72 
     73 	for (p = node->portals ; p ; p=p->next[s])
     74 	{
     75 		w = p->winding;
     76 		s = (p->nodes[1] == node);
     77 		if (w && p->nodes[0] == node)
     78 		{
     79 			if (!Portal_VisFlood (p))
     80 				continue;
     81 		// write out to the file
     82 		
     83 		// sometimes planes get turned around when they are very near
     84 		// the changeover point between different axis.  interpret the
     85 		// plane the same way vis will, and flip the side orders if needed
     86 			// FIXME: is this still relevent?
     87 			WindingPlane (w, normal, &dist);
     88 			if ( DotProduct (p->plane.normal, normal) < 0.99 )
     89 			{	// backwards...
     90 				fprintf (pf,"%i %i %i ",w->numpoints, p->nodes[1]->cluster, p->nodes[0]->cluster);
     91 			}
     92 			else
     93 				fprintf (pf,"%i %i %i ",w->numpoints, p->nodes[0]->cluster, p->nodes[1]->cluster);
     94 			for (i=0 ; i<w->numpoints ; i++)
     95 			{
     96 				fprintf (pf,"(");
     97 				WriteFloat2 (pf, w->p[i][0]);
     98 				WriteFloat2 (pf, w->p[i][1]);
     99 				WriteFloat2 (pf, w->p[i][2]);
    100 				fprintf (pf,") ");
    101 			}
    102 			fprintf (pf,"\n");
    103 		}
    104 	}
    105 
    106 }
    107 
    108 /*
    109 ================
    110 FillLeafNumbers_r
    111 
    112 All of the leafs under node will have the same cluster
    113 ================
    114 */
    115 void FillLeafNumbers_r (node_t *node, int num)
    116 {
    117 	if (node->planenum == PLANENUM_LEAF)
    118 	{
    119 		if (node->contents & CONTENTS_SOLID)
    120 			node->cluster = -1;
    121 		else
    122 			node->cluster = num;
    123 		return;
    124 	}
    125 	node->cluster = num;
    126 	FillLeafNumbers_r (node->children[0], num);
    127 	FillLeafNumbers_r (node->children[1], num);
    128 }
    129 
    130 /*
    131 ================
    132 NumberLeafs_r
    133 ================
    134 */
    135 void NumberLeafs_r (node_t *node)
    136 {
    137 	portal_t	*p;
    138 
    139 	if (node->planenum != PLANENUM_LEAF && !node->detail_seperator)
    140 	{	// decision node
    141 		node->cluster = -99;
    142 		NumberLeafs_r (node->children[0]);
    143 		NumberLeafs_r (node->children[1]);
    144 		return;
    145 	}
    146 	
    147 	// either a leaf or a detail cluster
    148 
    149 	if ( node->contents & CONTENTS_SOLID )
    150 	{	// solid block, viewpoint never inside
    151 		node->cluster = -1;
    152 		return;
    153 	}
    154 
    155 	FillLeafNumbers_r (node, num_visclusters);
    156 	num_visclusters++;
    157 
    158 	// count the portals
    159 	for (p = node->portals ; p ; )
    160 	{
    161 		if (p->nodes[0] == node)		// only write out from first leaf
    162 		{
    163 			if (Portal_VisFlood (p))
    164 				num_visportals++;
    165 			p = p->next[0];
    166 		}
    167 		else
    168 			p = p->next[1];		
    169 	}
    170 
    171 }
    172 
    173 
    174 /*
    175 ================
    176 CreateVisPortals_r
    177 ================
    178 */
    179 void CreateVisPortals_r (node_t *node)
    180 {
    181 	// stop as soon as we get to a detail_seperator, which
    182 	// means that everything below is in a single cluster
    183 	if (node->planenum == PLANENUM_LEAF || node->detail_seperator )
    184 		return;
    185 
    186 	MakeNodePortal (node);
    187 	SplitNodePortals (node);
    188 
    189 	CreateVisPortals_r (node->children[0]);
    190 	CreateVisPortals_r (node->children[1]);
    191 }
    192 
    193 /*
    194 ================
    195 FinishVisPortals_r
    196 ================
    197 */
    198 void FinishVisPortals2_r (node_t *node)
    199 {
    200 	if (node->planenum == PLANENUM_LEAF)
    201 		return;
    202 
    203 	MakeNodePortal (node);
    204 	SplitNodePortals (node);
    205 
    206 	FinishVisPortals2_r (node->children[0]);
    207 	FinishVisPortals2_r (node->children[1]);
    208 }
    209 
    210 void FinishVisPortals_r (node_t *node)
    211 {
    212 	if (node->planenum == PLANENUM_LEAF)
    213 		return;
    214 
    215 	if (node->detail_seperator)
    216 	{
    217 		FinishVisPortals2_r (node);
    218 		return;
    219 	}
    220 
    221 	FinishVisPortals_r (node->children[0]);
    222 	FinishVisPortals_r (node->children[1]);
    223 }
    224 
    225 
    226 int		clusterleaf;
    227 void SaveClusters_r (node_t *node)
    228 {
    229 	if (node->planenum == PLANENUM_LEAF)
    230 	{
    231 		dleafs[clusterleaf++].cluster = node->cluster;
    232 		return;
    233 	}
    234 	SaveClusters_r (node->children[0]);
    235 	SaveClusters_r (node->children[1]);
    236 }
    237 
    238 /*
    239 ================
    240 WritePortalFile
    241 ================
    242 */
    243 void WritePortalFile (tree_t *tree)
    244 {
    245 	char	filename[1024];
    246 	node_t *headnode;
    247 
    248 	qprintf ("--- WritePortalFile ---\n");
    249 
    250 	headnode = tree->headnode;
    251 	num_visclusters = 0;
    252 	num_visportals = 0;
    253 
    254 	Tree_FreePortals_r (headnode);
    255 
    256 	MakeHeadnodePortals (tree);
    257 
    258 	CreateVisPortals_r (headnode);
    259 
    260 // set the cluster field in every leaf and count the total number of portals
    261 
    262 	NumberLeafs_r (headnode);
    263 	
    264 // write the file
    265 	sprintf (filename, "%s.prt", source);
    266 	printf ("writing %s\n", filename);
    267 	pf = fopen (filename, "w");
    268 	if (!pf)
    269 		Error ("Error opening %s", filename);
    270 		
    271 	fprintf (pf, "%s\n", PORTALFILE);
    272 	fprintf (pf, "%i\n", num_visclusters);
    273 	fprintf (pf, "%i\n", num_visportals);
    274 
    275 	qprintf ("%5i visclusters\n", num_visclusters);
    276 	qprintf ("%5i visportals\n", num_visportals);
    277 
    278 	WritePortalFile_r (headnode);
    279 
    280 	fclose (pf);
    281 
    282 	// we need to store the clusters out now because ordering
    283 	// issues made us do this after writebsp...
    284 	clusterleaf = 1;
    285 	SaveClusters_r (headnode);
    286 }
    287