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 );
149 /* ydnar: added this change to make antiportals work */
150 if ( p->compileFlags & C_HINT ) {
157 /* write the winding */
158 for ( i = 0 ; i < w->numpoints ; i++ )
161 WriteFloat( pf, w->p[i][0] );
162 WriteFloat( pf, w->p[i][1] );
163 WriteFloat( pf, w->p[i][2] );
172 void CountSolidFaces_r( node_t *node ){
178 if ( node->planenum != PLANENUM_LEAF ) {
179 CountSolidFaces_r( node->children[0] );
180 CountSolidFaces_r( node->children[1] );
184 if ( node->opaque ) {
188 for ( p = node->portals ; p ; p = p->next[s] )
191 s = ( p->nodes[1] == node );
193 if ( PortalPassable( p ) ) {
196 if ( p->nodes[0]->cluster == p->nodes[1]->cluster ) {
199 // write out to the file
211 void WriteFaceFile_r( node_t *node ){
217 if ( node->planenum != PLANENUM_LEAF ) {
218 WriteFaceFile_r( node->children[0] );
219 WriteFaceFile_r( node->children[1] );
223 if ( node->opaque ) {
227 for ( p = node->portals ; p ; p = p->next[s] )
230 s = ( p->nodes[1] == node );
232 if ( PortalPassable( p ) ) {
235 if ( p->nodes[0]->cluster == p->nodes[1]->cluster ) {
238 // write out to the file
240 if ( p->nodes[0] == node ) {
241 fprintf( pf,"%i %i ",w->numpoints, p->nodes[0]->cluster );
242 for ( i = 0 ; i < w->numpoints ; i++ )
245 WriteFloat( pf, w->p[i][0] );
246 WriteFloat( pf, w->p[i][1] );
247 WriteFloat( pf, w->p[i][2] );
254 fprintf( pf,"%i %i ",w->numpoints, p->nodes[1]->cluster );
255 for ( i = w->numpoints - 1; i >= 0; i-- )
258 WriteFloat( pf, w->p[i][0] );
259 WriteFloat( pf, w->p[i][1] );
260 WriteFloat( pf, w->p[i][2] );
274 void NumberLeafs_r( node_t *node, int c ){
278 if ( node->planenum != PLANENUM_LEAF ) {
282 if ( node->has_structural_children ) {
285 Sys_FPrintf( SYS_ERR,"THIS CANNOT HAPPEN\n" );
288 NumberLeafs_r( node->children[0], c );
289 NumberLeafs_r( node->children[1], c );
294 c = num_visclusters++;
296 NumberLeafs_r( node->children[0], c );
297 NumberLeafs_r( node->children[1], c );
304 if ( node->opaque ) {
305 // solid block, viewpoint never inside
311 c = num_visclusters++;
318 for ( p = node->portals ; p ; )
320 if ( p->nodes[0] == node ) { // only write out from first leaf
321 if ( PortalPassable( p ) ) {
331 if ( !PortalPassable( p ) ) {
346 void NumberClusters( tree_t *tree ) {
351 Sys_FPrintf( SYS_VRB,"--- NumberClusters ---\n" );
353 // set the cluster field in every leaf and count the total number of portals
354 NumberLeafs_r( tree->headnode, -1 );
355 CountVisportals_r( tree->headnode );
356 CountSolidFaces_r( tree->headnode );
358 Sys_FPrintf( SYS_VRB, "%9d visclusters\n", num_visclusters );
359 Sys_FPrintf( SYS_VRB, "%9d visportals\n", num_visportals );
360 Sys_FPrintf( SYS_VRB, "%9d solidfaces\n", num_solidfaces );
368 void WritePortalFile( tree_t *tree ){
371 Sys_FPrintf( SYS_VRB,"--- WritePortalFile ---\n" );
374 sprintf( filename, "%s.prt", source );
375 Sys_Printf( "writing %s\n", filename );
376 pf = fopen( filename, "w" );
378 Error( "Error opening %s", filename );
381 fprintf( pf, "%s\n", PORTALFILE );
382 fprintf( pf, "%i\n", num_visclusters );
383 fprintf( pf, "%i\n", num_visportals );
384 fprintf( pf, "%i\n", num_solidfaces );
386 WritePortalFile_r( tree->headnode );
387 WriteFaceFile_r( tree->headnode );