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