Quake-III-Arena

Quake III Arena GPL Source Release
Log | Files | Refs

prtfile.c (5821B)


      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 int		num_solidfaces;
     41 
     42 void WriteFloat (FILE *f, vec_t v)
     43 {
     44 	if ( fabs(v - Q_rint(v)) < 0.001 )
     45 		fprintf (f,"%i ",(int)Q_rint(v));
     46 	else
     47 		fprintf (f,"%f ",v);
     48 }
     49 
     50 /*
     51 =================
     52 WritePortalFile_r
     53 =================
     54 */
     55 void WritePortalFile_r (node_t *node)
     56 {
     57 	int			i, s;	
     58 	portal_t	*p;
     59 	winding_t	*w;
     60 	vec3_t		normal;
     61 	vec_t		dist;
     62 
     63 	// decision node
     64 	if (node->planenum != PLANENUM_LEAF) {
     65 		WritePortalFile_r (node->children[0]);
     66 		WritePortalFile_r (node->children[1]);
     67 		return;
     68 	}
     69 	
     70 	if (node->opaque) {
     71 		return;
     72 	}
     73 
     74 	for (p = node->portals ; p ; p=p->next[s])
     75 	{
     76 		w = p->winding;
     77 		s = (p->nodes[1] == node);
     78 		if (w && p->nodes[0] == node)
     79 		{
     80 			if (!Portal_Passable(p))
     81 				continue;
     82 			// write out to the file
     83 			
     84 			// sometimes planes get turned around when they are very near
     85 			// the changeover point between different axis.  interpret the
     86 			// plane the same way vis will, and flip the side orders if needed
     87 			// FIXME: is this still relevent?
     88 			WindingPlane (w, normal, &dist);
     89 			if ( DotProduct (p->plane.normal, normal) < 0.99 )
     90 			{	// backwards...
     91 				fprintf (pf,"%i %i %i ",w->numpoints, p->nodes[1]->cluster, p->nodes[0]->cluster);
     92 			}
     93 			else
     94 				fprintf (pf,"%i %i %i ",w->numpoints, p->nodes[0]->cluster, p->nodes[1]->cluster);
     95 			if (p->hint)
     96 				fprintf (pf, "1 ");
     97 			else
     98 				fprintf (pf, "0 ");
     99 			for (i=0 ; i<w->numpoints ; i++)
    100 			{
    101 				fprintf (pf,"(");
    102 				WriteFloat (pf, w->p[i][0]);
    103 				WriteFloat (pf, w->p[i][1]);
    104 				WriteFloat (pf, w->p[i][2]);
    105 				fprintf (pf,") ");
    106 			}
    107 			fprintf (pf,"\n");
    108 		}
    109 	}
    110 
    111 }
    112 
    113 /*
    114 =================
    115 WriteFaceFile_r
    116 =================
    117 */
    118 void WriteFaceFile_r (node_t *node)
    119 {
    120 	int			i, s;	
    121 	portal_t	*p;
    122 	winding_t	*w;
    123 
    124 	// decision node
    125 	if (node->planenum != PLANENUM_LEAF) {
    126 		WriteFaceFile_r (node->children[0]);
    127 		WriteFaceFile_r (node->children[1]);
    128 		return;
    129 	}
    130 	
    131 	if (node->opaque) {
    132 		return;
    133 	}
    134 
    135 	for (p = node->portals ; p ; p=p->next[s])
    136 	{
    137 		w = p->winding;
    138 		s = (p->nodes[1] == node);
    139 		if (w)
    140 		{
    141 			if (Portal_Passable(p))
    142 				continue;
    143 			// write out to the file
    144 
    145 			if (p->nodes[0] == node)
    146 			{
    147 				fprintf (pf,"%i %i ",w->numpoints, p->nodes[0]->cluster);
    148 				for (i=0 ; i<w->numpoints ; i++)
    149 				{
    150 					fprintf (pf,"(");
    151 					WriteFloat (pf, w->p[i][0]);
    152 					WriteFloat (pf, w->p[i][1]);
    153 					WriteFloat (pf, w->p[i][2]);
    154 					fprintf (pf,") ");
    155 				}
    156 				fprintf (pf,"\n");
    157 			}
    158 			else
    159 			{
    160 				fprintf (pf,"%i %i ",w->numpoints, p->nodes[1]->cluster);
    161 				for (i = w->numpoints-1; i >= 0; i--)
    162 				{
    163 					fprintf (pf,"(");
    164 					WriteFloat (pf, w->p[i][0]);
    165 					WriteFloat (pf, w->p[i][1]);
    166 					WriteFloat (pf, w->p[i][2]);
    167 					fprintf (pf,") ");
    168 				}
    169 				fprintf (pf,"\n");
    170 			}
    171 		}
    172 	}
    173 }
    174 
    175 /*
    176 ================
    177 NumberLeafs_r
    178 ================
    179 */
    180 void NumberLeafs_r (node_t *node)
    181 {
    182 	portal_t	*p;
    183 
    184 	if ( node->planenum != PLANENUM_LEAF ) {
    185 		// decision node
    186 		node->cluster = -99;
    187 		NumberLeafs_r (node->children[0]);
    188 		NumberLeafs_r (node->children[1]);
    189 		return;
    190 	}
    191 	
    192 	node->area = -1;
    193 
    194 	if ( node->opaque ) {
    195 		// solid block, viewpoint never inside
    196 		node->cluster = -1;
    197 		return;
    198 	}
    199 
    200 	node->cluster = num_visclusters;
    201 	num_visclusters++;
    202 
    203 	// count the portals
    204 	for (p = node->portals ; p ; )
    205 	{
    206 		if (p->nodes[0] == node)		// only write out from first leaf
    207 		{
    208 			if (Portal_Passable(p))
    209 				num_visportals++;
    210 			else
    211 				num_solidfaces++;
    212 			p = p->next[0];
    213 		}
    214 		else
    215 		{
    216 			if (!Portal_Passable(p))
    217 				num_solidfaces++;
    218 			p = p->next[1];		
    219 		}
    220 	}
    221 }
    222 
    223 
    224 /*
    225 ================
    226 NumberClusters
    227 ================
    228 */
    229 void NumberClusters(tree_t *tree) {
    230 	num_visclusters = 0;
    231 	num_visportals = 0;
    232 	num_solidfaces = 0;
    233 
    234 	qprintf ("--- NumberClusters ---\n");
    235 	
    236 	// set the cluster field in every leaf and count the total number of portals
    237 	NumberLeafs_r (tree->headnode);
    238 
    239 	qprintf ("%5i visclusters\n", num_visclusters);
    240 	qprintf ("%5i visportals\n", num_visportals);
    241 	qprintf ("%5i solidfaces\n", num_solidfaces);
    242 }
    243 
    244 /*
    245 ================
    246 WritePortalFile
    247 ================
    248 */
    249 void WritePortalFile (tree_t *tree)
    250 {
    251 	char	filename[1024];
    252 
    253 	qprintf ("--- WritePortalFile ---\n");
    254 	
    255 	// write the file
    256 	sprintf (filename, "%s.prt", source);
    257 	_printf ("writing %s\n", filename);
    258 	pf = fopen (filename, "w");
    259 	if (!pf)
    260 		Error ("Error opening %s", filename);
    261 		
    262 	fprintf (pf, "%s\n", PORTALFILE);
    263 	fprintf (pf, "%i\n", num_visclusters);
    264 	fprintf (pf, "%i\n", num_visportals);
    265 	fprintf (pf, "%i\n", num_solidfaces);
    266 
    267 	WritePortalFile_r(tree->headnode);
    268 	WriteFaceFile_r(tree->headnode);
    269 
    270 	fclose (pf);
    271 }
    272