1 /* -------------------------------------------------------------------------------
3 Copyright (C) 1999-2007 id Software, Inc. and contributors.
4 For a list of contributors, see the accompanying CONTRIBUTORS file.
6 This file is part of GtkRadiant.
8 GtkRadiant is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 GtkRadiant is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GtkRadiant; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 ----------------------------------------------------------------------------------
24 This code has been altered significantly from its original form, to support
25 several games based on the Quake III Arena engine, in the form of "Q3Map2."
27 ------------------------------------------------------------------------------- */
42 ==============================================================================
44 PORTAL FILE GENERATION
46 Save out name.prt for qvis to read
47 ==============================================================================
51 #define PORTALFILE "PRT1"
54 int num_visclusters; // clusters the player can be in
58 void WriteFloat( FILE *f, vec_t v ){
59 if ( fabs( v - Q_rint( v ) ) < 0.001 ) {
60 fprintf( f,"%i ",(int)Q_rint( v ) );
67 void CountVisportals_r( node_t *node ){
73 if ( node->planenum != PLANENUM_LEAF ) {
74 CountVisportals_r( node->children[0] );
75 CountVisportals_r( node->children[1] );
83 for ( p = node->portals ; p ; p = p->next[s] )
86 s = ( p->nodes[1] == node );
87 if ( w && p->nodes[0] == node ) {
88 if ( !PortalPassable( p ) ) {
91 if ( p->nodes[0]->cluster == p->nodes[1]->cluster ) {
104 void WritePortalFile_r( node_t *node ){
112 if ( node->planenum != PLANENUM_LEAF ) {
113 WritePortalFile_r( node->children[0] );
114 WritePortalFile_r( node->children[1] );
118 if ( node->opaque ) {
122 for ( p = node->portals ; p ; p = p->next[s] )
125 s = ( p->nodes[1] == node );
126 if ( w && p->nodes[0] == node ) {
127 if ( !PortalPassable( p ) ) {
130 if ( p->nodes[0]->cluster == p->nodes[1]->cluster ) {
134 // write out to the file
136 // sometimes planes get turned around when they are very near
137 // the changeover point between different axis. interpret the
138 // plane the same way vis will, and flip the side orders if needed
139 // FIXME: is this still relevent?
140 WindingPlane( w, normal, &dist );
142 if ( DotProduct( p->plane.normal, normal ) < 0.99 ) { // backwards...
143 fprintf( pf,"%i %i %i ",w->numpoints, p->nodes[1]->cluster, p->nodes[0]->cluster );
146 fprintf( pf,"%i %i %i ",w->numpoints, p->nodes[0]->cluster, p->nodes[1]->cluster );
151 /* ydnar: added this change to make antiportals work */
152 if( p->compileFlags & C_HINT ) {
156 /* divVerent: I want farplanedist to not kill skybox. So... */
157 if( p->compileFlags & C_SKY ) {
161 fprintf( pf, "%d ", flags );
163 /* write the winding */
164 for ( i = 0 ; i < w->numpoints ; i++ )
167 WriteFloat( pf, w->p[i][0] );
168 WriteFloat( pf, w->p[i][1] );
169 WriteFloat( pf, w->p[i][2] );
178 void CountSolidFaces_r( node_t *node ){
184 if ( node->planenum != PLANENUM_LEAF ) {
185 CountSolidFaces_r( node->children[0] );
186 CountSolidFaces_r( node->children[1] );
190 if ( node->opaque ) {
194 for ( p = node->portals ; p ; p = p->next[s] )
197 s = ( p->nodes[1] == node );
199 if ( PortalPassable( p ) ) {
202 if ( p->nodes[0]->cluster == p->nodes[1]->cluster ) {
205 // write out to the file
217 void WriteFaceFile_r( node_t *node ){
223 if ( node->planenum != PLANENUM_LEAF ) {
224 WriteFaceFile_r( node->children[0] );
225 WriteFaceFile_r( node->children[1] );
229 if ( node->opaque ) {
233 for ( p = node->portals ; p ; p = p->next[s] )
236 s = ( p->nodes[1] == node );
238 if ( PortalPassable( p ) ) {
241 if ( p->nodes[0]->cluster == p->nodes[1]->cluster ) {
244 // write out to the file
246 if ( p->nodes[0] == node ) {
247 fprintf( pf,"%i %i ",w->numpoints, p->nodes[0]->cluster );
248 for ( i = 0 ; i < w->numpoints ; i++ )
251 WriteFloat( pf, w->p[i][0] );
252 WriteFloat( pf, w->p[i][1] );
253 WriteFloat( pf, w->p[i][2] );
260 fprintf( pf,"%i %i ",w->numpoints, p->nodes[1]->cluster );
261 for ( i = w->numpoints - 1; i >= 0; i-- )
264 WriteFloat( pf, w->p[i][0] );
265 WriteFloat( pf, w->p[i][1] );
266 WriteFloat( pf, w->p[i][2] );
280 void NumberLeafs_r( node_t *node, int c ){
284 if ( node->planenum != PLANENUM_LEAF ) {
288 if ( node->has_structural_children ) {
291 Sys_FPrintf( SYS_ERR,"THIS CANNOT HAPPEN\n" );
294 NumberLeafs_r( node->children[0], c );
295 NumberLeafs_r( node->children[1], c );
300 c = num_visclusters++;
302 NumberLeafs_r( node->children[0], c );
303 NumberLeafs_r( node->children[1], c );
310 if ( node->opaque ) {
311 // solid block, viewpoint never inside
317 c = num_visclusters++;
324 for ( p = node->portals ; p ; )
326 if ( p->nodes[0] == node ) { // only write out from first leaf
327 if ( PortalPassable( p ) ) {
337 if ( !PortalPassable( p ) ) {
352 void NumberClusters( tree_t *tree ) {
357 Sys_FPrintf( SYS_VRB,"--- NumberClusters ---\n" );
359 // set the cluster field in every leaf and count the total number of portals
360 NumberLeafs_r( tree->headnode, -1 );
361 CountVisportals_r( tree->headnode );
362 CountSolidFaces_r( tree->headnode );
364 Sys_FPrintf( SYS_VRB, "%9d visclusters\n", num_visclusters );
365 Sys_FPrintf( SYS_VRB, "%9d visportals\n", num_visportals );
366 Sys_FPrintf( SYS_VRB, "%9d solidfaces\n", num_solidfaces );
374 void WritePortalFile( tree_t *tree, const char *portalFilePath ){
376 Sys_FPrintf( SYS_VRB,"--- WritePortalFile ---\n" );
379 Sys_Printf( "writing %s\n", portalFilePath );
380 pf = fopen( portalFilePath, "w" );
382 Error( "Error opening %s", portalFilePath );
385 fprintf( pf, "%s\n", PORTALFILE );
386 fprintf( pf, "%i\n", num_visclusters );
387 fprintf( pf, "%i\n", num_visportals );
388 fprintf( pf, "%i\n", num_solidfaces );
390 WritePortalFile_r( tree->headnode );
391 WriteFaceFile_r( tree->headnode );