1 /*
2 ===========================================================================
3 
4 Return to Castle Wolfenstein multiplayer GPL Source Code
5 Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
6 
7 This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (“RTCW MP Source Code”).
8 
9 RTCW MP Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13 
14 RTCW MP Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with RTCW MP Source Code.  If not, see <http://www.gnu.org/licenses/>.
21 
22 In addition, the RTCW MP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW MP Source Code.  If not, please request a copy in writing from id Software at the address below.
23 
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
25 
26 ===========================================================================
27 */
28 
29 
30 /*****************************************************************************
31  * name:		be_aas_optimize.c
32  *
33  * desc:		decreases the .aas file size after the reachabilities have
34  *				been calculated, just dumps all the faces, edges and vertexes
35  *
36  *
37  *****************************************************************************/
38 
39 #include "../qcommon/q_shared.h"
40 #include "l_libvar.h"
41 //#include "l_utils.h"
42 #include "l_memory.h"
43 #include "l_script.h"
44 #include "l_precomp.h"
45 #include "l_struct.h"
46 #include "aasfile.h"
47 #include "botlib.h"
48 #include "be_aas.h"
49 #include "be_aas_funcs.h"
50 #include "be_interface.h"
51 #include "be_aas_def.h"
52 
53 typedef struct optimized_s
54 {
55 	//vertixes
56 	int numvertexes;
57 	aas_vertex_t *vertexes;
58 	//edges
59 	int numedges;
60 	aas_edge_t *edges;
61 	//edge index
62 	int edgeindexsize;
63 	aas_edgeindex_t *edgeindex;
64 	//faces
65 	int numfaces;
66 	aas_face_t *faces;
67 	//face index
68 	int faceindexsize;
69 	aas_faceindex_t *faceindex;
70 	//convex areas
71 	int numareas;
72 	aas_area_t *areas;
73 	//
74 	int *vertexoptimizeindex;
75 	int *edgeoptimizeindex;
76 	int *faceoptimizeindex;
77 } optimized_t;
78 
79 //===========================================================================
80 //
81 // Parameter:				-
82 // Returns:					-
83 // Changes Globals:		-
84 //===========================================================================
AAS_KeepEdge(aas_edge_t * edge)85 int AAS_KeepEdge( aas_edge_t *edge ) {
86 	return 1;
87 } //end of the function AAS_KeepFace
88 //===========================================================================
89 //
90 // Parameter:				-
91 // Returns:					-
92 // Changes Globals:		-
93 //===========================================================================
AAS_OptimizeEdge(optimized_t * optimized,int edgenum)94 int AAS_OptimizeEdge( optimized_t *optimized, int edgenum ) {
95 	int i, optedgenum;
96 	aas_edge_t *edge, *optedge;
97 
98 	edge = &( *aasworld ).edges[abs( edgenum )];
99 	if ( !AAS_KeepEdge( edge ) ) {
100 		return 0;
101 	}
102 
103 	optedgenum = optimized->edgeoptimizeindex[abs( edgenum )];
104 	if ( optedgenum ) {
105 		//keep the edge reversed sign
106 		if ( edgenum > 0 ) {
107 			return optedgenum;
108 		} else { return -optedgenum;}
109 	} //end if
110 
111 	optedge = &optimized->edges[optimized->numedges];
112 
113 	for ( i = 0; i < 2; i++ )
114 	{
115 		if ( optimized->vertexoptimizeindex[edge->v[i]] ) {
116 			optedge->v[i] = optimized->vertexoptimizeindex[edge->v[i]];
117 		} //end if
118 		else
119 		{
120 			VectorCopy( ( *aasworld ).vertexes[edge->v[i]], optimized->vertexes[optimized->numvertexes] );
121 			optedge->v[i] = optimized->numvertexes;
122 			optimized->vertexoptimizeindex[edge->v[i]] = optimized->numvertexes;
123 			optimized->numvertexes++;
124 		} //end else
125 	} //end for
126 	optimized->edgeoptimizeindex[abs( edgenum )] = optimized->numedges;
127 	optedgenum = optimized->numedges;
128 	optimized->numedges++;
129 	//keep the edge reversed sign
130 	if ( edgenum > 0 ) {
131 		return optedgenum;
132 	} else { return -optedgenum;}
133 } //end of the function AAS_OptimizeEdge
134 //===========================================================================
135 //
136 // Parameter:				-
137 // Returns:					-
138 // Changes Globals:		-
139 //===========================================================================
AAS_KeepFace(aas_face_t * face)140 int AAS_KeepFace( aas_face_t *face ) {
141 	if ( !( face->faceflags & FACE_LADDER ) ) {
142 		return 0;
143 	} else { return 1;}
144 } //end of the function AAS_KeepFace
145 //===========================================================================
146 //
147 // Parameter:				-
148 // Returns:					-
149 // Changes Globals:		-
150 //===========================================================================
AAS_OptimizeFace(optimized_t * optimized,int facenum)151 int AAS_OptimizeFace( optimized_t *optimized, int facenum ) {
152 	int i, edgenum, optedgenum, optfacenum;
153 	aas_face_t *face, *optface;
154 
155 	face = &( *aasworld ).faces[abs( facenum )];
156 	if ( !AAS_KeepFace( face ) ) {
157 		return 0;
158 	}
159 
160 	optfacenum = optimized->faceoptimizeindex[abs( facenum )];
161 	if ( optfacenum ) {
162 		//keep the face side sign
163 		if ( facenum > 0 ) {
164 			return optfacenum;
165 		} else { return -optfacenum;}
166 	} //end if
167 
168 	optface = &optimized->faces[optimized->numfaces];
169 	memcpy( optface, face, sizeof( aas_face_t ) );
170 
171 	optface->numedges = 0;
172 	optface->firstedge = optimized->edgeindexsize;
173 	for ( i = 0; i < face->numedges; i++ )
174 	{
175 		edgenum = ( *aasworld ).edgeindex[face->firstedge + i];
176 		optedgenum = AAS_OptimizeEdge( optimized, edgenum );
177 		if ( optedgenum ) {
178 			optimized->edgeindex[optface->firstedge + optface->numedges] = optedgenum;
179 			optface->numedges++;
180 			optimized->edgeindexsize++;
181 		} //end if
182 	} //end for
183 	optimized->faceoptimizeindex[abs( facenum )] = optimized->numfaces;
184 	optfacenum = optimized->numfaces;
185 	optimized->numfaces++;
186 	//keep the face side sign
187 	if ( facenum > 0 ) {
188 		return optfacenum;
189 	} else { return -optfacenum;}
190 } //end of the function AAS_OptimizeFace
191 //===========================================================================
192 //
193 // Parameter:				-
194 // Returns:					-
195 // Changes Globals:		-
196 //===========================================================================
AAS_OptimizeArea(optimized_t * optimized,int areanum)197 void AAS_OptimizeArea( optimized_t *optimized, int areanum ) {
198 	int i, facenum, optfacenum;
199 	aas_area_t *area, *optarea;
200 
201 	area = &( *aasworld ).areas[areanum];
202 	optarea = &optimized->areas[areanum];
203 	memcpy( optarea, area, sizeof( aas_area_t ) );
204 
205 	optarea->numfaces = 0;
206 	optarea->firstface = optimized->faceindexsize;
207 	for ( i = 0; i < area->numfaces; i++ )
208 	{
209 		facenum = ( *aasworld ).faceindex[area->firstface + i];
210 		optfacenum = AAS_OptimizeFace( optimized, facenum );
211 		if ( optfacenum ) {
212 			optimized->faceindex[optarea->firstface + optarea->numfaces] = optfacenum;
213 			optarea->numfaces++;
214 			optimized->faceindexsize++;
215 		} //end if
216 	} //end for
217 } //end of the function AAS_OptimizeArea
218 //===========================================================================
219 //
220 // Parameter:				-
221 // Returns:					-
222 // Changes Globals:		-
223 //===========================================================================
AAS_OptimizeAlloc(optimized_t * optimized)224 void AAS_OptimizeAlloc( optimized_t *optimized ) {
225 	optimized->vertexes = (aas_vertex_t *) GetClearedMemory( ( *aasworld ).numvertexes * sizeof( aas_vertex_t ) );
226 	optimized->numvertexes = 0;
227 	optimized->edges = (aas_edge_t *) GetClearedMemory( ( *aasworld ).numedges * sizeof( aas_edge_t ) );
228 	optimized->numedges = 1; //edge zero is a dummy
229 	optimized->edgeindex = (aas_edgeindex_t *) GetClearedMemory( ( *aasworld ).edgeindexsize * sizeof( aas_edgeindex_t ) );
230 	optimized->edgeindexsize = 0;
231 	optimized->faces = (aas_face_t *) GetClearedMemory( ( *aasworld ).numfaces * sizeof( aas_face_t ) );
232 	optimized->numfaces = 1; //face zero is a dummy
233 	optimized->faceindex = (aas_faceindex_t *) GetClearedMemory( ( *aasworld ).faceindexsize * sizeof( aas_faceindex_t ) );
234 	optimized->faceindexsize = 0;
235 	optimized->areas = (aas_area_t *) GetClearedMemory( ( *aasworld ).numareas * sizeof( aas_area_t ) );
236 	optimized->numareas = ( *aasworld ).numareas;
237 	//
238 	optimized->vertexoptimizeindex = (int *) GetClearedMemory( ( *aasworld ).numvertexes * sizeof( int ) );
239 	optimized->edgeoptimizeindex = (int *) GetClearedMemory( ( *aasworld ).numedges * sizeof( int ) );
240 	optimized->faceoptimizeindex = (int *) GetClearedMemory( ( *aasworld ).numfaces * sizeof( int ) );
241 } //end of the function AAS_OptimizeAlloc
242 //===========================================================================
243 //
244 // Parameter:				-
245 // Returns:					-
246 // Changes Globals:		-
247 //===========================================================================
AAS_OptimizeStore(optimized_t * optimized)248 void AAS_OptimizeStore( optimized_t *optimized ) {
249 	//store the optimized vertexes
250 	if ( ( *aasworld ).vertexes ) {
251 		FreeMemory( ( *aasworld ).vertexes );
252 	}
253 	( *aasworld ).vertexes = optimized->vertexes;
254 	( *aasworld ).numvertexes = optimized->numvertexes;
255 	//store the optimized edges
256 	if ( ( *aasworld ).edges ) {
257 		FreeMemory( ( *aasworld ).edges );
258 	}
259 	( *aasworld ).edges = optimized->edges;
260 	( *aasworld ).numedges = optimized->numedges;
261 	//store the optimized edge index
262 	if ( ( *aasworld ).edgeindex ) {
263 		FreeMemory( ( *aasworld ).edgeindex );
264 	}
265 	( *aasworld ).edgeindex = optimized->edgeindex;
266 	( *aasworld ).edgeindexsize = optimized->edgeindexsize;
267 	//store the optimized faces
268 	if ( ( *aasworld ).faces ) {
269 		FreeMemory( ( *aasworld ).faces );
270 	}
271 	( *aasworld ).faces = optimized->faces;
272 	( *aasworld ).numfaces = optimized->numfaces;
273 	//store the optimized face index
274 	if ( ( *aasworld ).faceindex ) {
275 		FreeMemory( ( *aasworld ).faceindex );
276 	}
277 	( *aasworld ).faceindex = optimized->faceindex;
278 	( *aasworld ).faceindexsize = optimized->faceindexsize;
279 	//store the optimized areas
280 	if ( ( *aasworld ).areas ) {
281 		FreeMemory( ( *aasworld ).areas );
282 	}
283 	( *aasworld ).areas = optimized->areas;
284 	( *aasworld ).numareas = optimized->numareas;
285 	//free optimize indexes
286 	FreeMemory( optimized->vertexoptimizeindex );
287 	FreeMemory( optimized->edgeoptimizeindex );
288 	FreeMemory( optimized->faceoptimizeindex );
289 } //end of the function AAS_OptimizeStore
290 //===========================================================================
291 //
292 // Parameter:				-
293 // Returns:					-
294 // Changes Globals:		-
295 //===========================================================================
AAS_Optimize(void)296 void AAS_Optimize( void ) {
297 	int i, sign;
298 	optimized_t optimized;
299 
300 	AAS_OptimizeAlloc( &optimized );
301 	for ( i = 1; i < ( *aasworld ).numareas; i++ )
302 	{
303 		AAS_OptimizeArea( &optimized, i );
304 	} //end for
305 	  //reset the reachability face pointers
306 	for ( i = 0; i < ( *aasworld ).reachabilitysize; i++ )
307 	{
308 		//NOTE: for TRAVEL_ELEVATOR the facenum is the model number of
309 		//		the elevator
310 		if ( ( *aasworld ).reachability[i].traveltype == TRAVEL_ELEVATOR ) {
311 			continue;
312 		}
313 		//NOTE: for TRAVEL_JUMPPAD the facenum is the Z velocity and the edgenum is the hor velocity
314 		if ( ( *aasworld ).reachability[i].traveltype == TRAVEL_JUMPPAD ) {
315 			continue;
316 		}
317 		//NOTE: for TRAVEL_FUNCBOB the facenum and edgenum contain other coded information
318 		if ( ( *aasworld ).reachability[i].traveltype == TRAVEL_FUNCBOB ) {
319 			continue;
320 		}
321 		//
322 		sign = ( *aasworld ).reachability[i].facenum;
323 		( *aasworld ).reachability[i].facenum = optimized.faceoptimizeindex[abs( ( *aasworld ).reachability[i].facenum )];
324 		if ( sign < 0 ) {
325 			( *aasworld ).reachability[i].facenum = -( *aasworld ).reachability[i].facenum;
326 		}
327 		sign = ( *aasworld ).reachability[i].edgenum;
328 		( *aasworld ).reachability[i].edgenum = optimized.edgeoptimizeindex[abs( ( *aasworld ).reachability[i].edgenum )];
329 		if ( sign < 0 ) {
330 			( *aasworld ).reachability[i].edgenum = -( *aasworld ).reachability[i].edgenum;
331 		}
332 	} //end for
333 	  //store the optimized AAS data into (*aasworld)
334 	AAS_OptimizeStore( &optimized );
335 	//print some nice stuff :)
336 	botimport.Print( PRT_MESSAGE, "AAS data optimized.\n" );
337 } //end of the function AAS_Optimize
338