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 Quake III Arena source code; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 ===========================================================================
21 */
22
23 /*****************************************************************************
24 * name: be_aas_optimize.c
25 *
26 * desc: decreases the .aas file size after the reachabilities have
27 * been calculated, just dumps all the faces, edges and vertexes
28 *
29 * $Archive: /MissionPack/code/botlib/be_aas_optimize.c $
30 *
31 *****************************************************************************/
32
33 #include "../qcommon/q_shared.h"
34 #include "l_libvar.h"
35 #include "l_memory.h"
36 #include "l_script.h"
37 #include "l_precomp.h"
38 #include "l_struct.h"
39 #include "aasfile.h"
40 #include "botlib.h"
41 #include "be_aas.h"
42 #include "be_aas_funcs.h"
43 #include "be_interface.h"
44 #include "be_aas_def.h"
45
46 typedef struct optimized_s
47 {
48 //vertexes
49 int numvertexes;
50 aas_vertex_t *vertexes;
51 //edges
52 int numedges;
53 aas_edge_t *edges;
54 //edge index
55 int edgeindexsize;
56 aas_edgeindex_t *edgeindex;
57 //faces
58 int numfaces;
59 aas_face_t *faces;
60 //face index
61 int faceindexsize;
62 aas_faceindex_t *faceindex;
63 //convex areas
64 int numareas;
65 aas_area_t *areas;
66 //
67 int *vertexoptimizeindex;
68 int *edgeoptimizeindex;
69 int *faceoptimizeindex;
70 } optimized_t;
71
72 //===========================================================================
73 //
74 // Parameter: -
75 // Returns: -
76 // Changes Globals: -
77 //===========================================================================
AAS_KeepEdge(aas_edge_t * edge)78 int AAS_KeepEdge(aas_edge_t *edge)
79 {
80 return 1;
81 } //end of the function AAS_KeepFace
82 //===========================================================================
83 //
84 // Parameter: -
85 // Returns: -
86 // Changes Globals: -
87 //===========================================================================
AAS_OptimizeEdge(optimized_t * optimized,int edgenum)88 int AAS_OptimizeEdge(optimized_t *optimized, int edgenum)
89 {
90 int i, optedgenum;
91 aas_edge_t *edge, *optedge;
92
93 edge = &aasworld.edges[abs(edgenum)];
94 if (!AAS_KeepEdge(edge)) return 0;
95
96 optedgenum = optimized->edgeoptimizeindex[abs(edgenum)];
97 if (optedgenum)
98 {
99 //keep the edge reversed sign
100 if (edgenum > 0) return optedgenum;
101 else return -optedgenum;
102 } //end if
103
104 optedge = &optimized->edges[optimized->numedges];
105
106 for (i = 0; i < 2; i++)
107 {
108 if (optimized->vertexoptimizeindex[edge->v[i]])
109 {
110 optedge->v[i] = optimized->vertexoptimizeindex[edge->v[i]];
111 } //end if
112 else
113 {
114 VectorCopy(aasworld.vertexes[edge->v[i]], optimized->vertexes[optimized->numvertexes]);
115 optedge->v[i] = optimized->numvertexes;
116 optimized->vertexoptimizeindex[edge->v[i]] = optimized->numvertexes;
117 optimized->numvertexes++;
118 } //end else
119 } //end for
120 optimized->edgeoptimizeindex[abs(edgenum)] = optimized->numedges;
121 optedgenum = optimized->numedges;
122 optimized->numedges++;
123 //keep the edge reversed sign
124 if (edgenum > 0) return optedgenum;
125 else return -optedgenum;
126 } //end of the function AAS_OptimizeEdge
127 //===========================================================================
128 //
129 // Parameter: -
130 // Returns: -
131 // Changes Globals: -
132 //===========================================================================
AAS_KeepFace(aas_face_t * face)133 int AAS_KeepFace(aas_face_t *face)
134 {
135 if (!(face->faceflags & FACE_LADDER)) return 0;
136 else return 1;
137 } //end of the function AAS_KeepFace
138 //===========================================================================
139 //
140 // Parameter: -
141 // Returns: -
142 // Changes Globals: -
143 //===========================================================================
AAS_OptimizeFace(optimized_t * optimized,int facenum)144 int AAS_OptimizeFace(optimized_t *optimized, int facenum)
145 {
146 int i, edgenum, optedgenum, optfacenum;
147 aas_face_t *face, *optface;
148
149 face = &aasworld.faces[abs(facenum)];
150 if (!AAS_KeepFace(face)) return 0;
151
152 optfacenum = optimized->faceoptimizeindex[abs(facenum)];
153 if (optfacenum)
154 {
155 //keep the face side sign
156 if (facenum > 0) return optfacenum;
157 else return -optfacenum;
158 } //end if
159
160 optface = &optimized->faces[optimized->numfaces];
161 Com_Memcpy(optface, face, sizeof(aas_face_t));
162
163 optface->numedges = 0;
164 optface->firstedge = optimized->edgeindexsize;
165 for (i = 0; i < face->numedges; i++)
166 {
167 edgenum = aasworld.edgeindex[face->firstedge + i];
168 optedgenum = AAS_OptimizeEdge(optimized, edgenum);
169 if (optedgenum)
170 {
171 optimized->edgeindex[optface->firstedge + optface->numedges] = optedgenum;
172 optface->numedges++;
173 optimized->edgeindexsize++;
174 } //end if
175 } //end for
176 optimized->faceoptimizeindex[abs(facenum)] = optimized->numfaces;
177 optfacenum = optimized->numfaces;
178 optimized->numfaces++;
179 //keep the face side sign
180 if (facenum > 0) return optfacenum;
181 else return -optfacenum;
182 } //end of the function AAS_OptimizeFace
183 //===========================================================================
184 //
185 // Parameter: -
186 // Returns: -
187 // Changes Globals: -
188 //===========================================================================
AAS_OptimizeArea(optimized_t * optimized,int areanum)189 void AAS_OptimizeArea(optimized_t *optimized, int areanum)
190 {
191 int i, facenum, optfacenum;
192 aas_area_t *area, *optarea;
193
194 area = &aasworld.areas[areanum];
195 optarea = &optimized->areas[areanum];
196 Com_Memcpy(optarea, area, sizeof(aas_area_t));
197
198 optarea->numfaces = 0;
199 optarea->firstface = optimized->faceindexsize;
200 for (i = 0; i < area->numfaces; i++)
201 {
202 facenum = aasworld.faceindex[area->firstface + i];
203 optfacenum = AAS_OptimizeFace(optimized, facenum);
204 if (optfacenum)
205 {
206 optimized->faceindex[optarea->firstface + optarea->numfaces] = optfacenum;
207 optarea->numfaces++;
208 optimized->faceindexsize++;
209 } //end if
210 } //end for
211 } //end of the function AAS_OptimizeArea
212 //===========================================================================
213 //
214 // Parameter: -
215 // Returns: -
216 // Changes Globals: -
217 //===========================================================================
AAS_OptimizeAlloc(optimized_t * optimized)218 void AAS_OptimizeAlloc(optimized_t *optimized)
219 {
220 optimized->vertexes = (aas_vertex_t *) GetClearedMemory(aasworld.numvertexes * sizeof(aas_vertex_t));
221 optimized->numvertexes = 0;
222 optimized->edges = (aas_edge_t *) GetClearedMemory(aasworld.numedges * sizeof(aas_edge_t));
223 optimized->numedges = 1; //edge zero is a dummy
224 optimized->edgeindex = (aas_edgeindex_t *) GetClearedMemory(aasworld.edgeindexsize * sizeof(aas_edgeindex_t));
225 optimized->edgeindexsize = 0;
226 optimized->faces = (aas_face_t *) GetClearedMemory(aasworld.numfaces * sizeof(aas_face_t));
227 optimized->numfaces = 1; //face zero is a dummy
228 optimized->faceindex = (aas_faceindex_t *) GetClearedMemory(aasworld.faceindexsize * sizeof(aas_faceindex_t));
229 optimized->faceindexsize = 0;
230 optimized->areas = (aas_area_t *) GetClearedMemory(aasworld.numareas * sizeof(aas_area_t));
231 optimized->numareas = aasworld.numareas;
232 //
233 optimized->vertexoptimizeindex = (int *) GetClearedMemory(aasworld.numvertexes * sizeof(int));
234 optimized->edgeoptimizeindex = (int *) GetClearedMemory(aasworld.numedges * sizeof(int));
235 optimized->faceoptimizeindex = (int *) GetClearedMemory(aasworld.numfaces * sizeof(int));
236 } //end of the function AAS_OptimizeAlloc
237 //===========================================================================
238 //
239 // Parameter: -
240 // Returns: -
241 // Changes Globals: -
242 //===========================================================================
AAS_OptimizeStore(optimized_t * optimized)243 void AAS_OptimizeStore(optimized_t *optimized)
244 {
245 //store the optimized vertexes
246 if (aasworld.vertexes) FreeMemory(aasworld.vertexes);
247 aasworld.vertexes = optimized->vertexes;
248 aasworld.numvertexes = optimized->numvertexes;
249 //store the optimized edges
250 if (aasworld.edges) FreeMemory(aasworld.edges);
251 aasworld.edges = optimized->edges;
252 aasworld.numedges = optimized->numedges;
253 //store the optimized edge index
254 if (aasworld.edgeindex) FreeMemory(aasworld.edgeindex);
255 aasworld.edgeindex = optimized->edgeindex;
256 aasworld.edgeindexsize = optimized->edgeindexsize;
257 //store the optimized faces
258 if (aasworld.faces) FreeMemory(aasworld.faces);
259 aasworld.faces = optimized->faces;
260 aasworld.numfaces = optimized->numfaces;
261 //store the optimized face index
262 if (aasworld.faceindex) FreeMemory(aasworld.faceindex);
263 aasworld.faceindex = optimized->faceindex;
264 aasworld.faceindexsize = optimized->faceindexsize;
265 //store the optimized areas
266 if (aasworld.areas) FreeMemory(aasworld.areas);
267 aasworld.areas = optimized->areas;
268 aasworld.numareas = optimized->numareas;
269 //free optimize indexes
270 FreeMemory(optimized->vertexoptimizeindex);
271 FreeMemory(optimized->edgeoptimizeindex);
272 FreeMemory(optimized->faceoptimizeindex);
273 } //end of the function AAS_OptimizeStore
274 //===========================================================================
275 //
276 // Parameter: -
277 // Returns: -
278 // Changes Globals: -
279 //===========================================================================
AAS_Optimize(void)280 void AAS_Optimize(void)
281 {
282 int i, sign;
283 optimized_t optimized;
284
285 AAS_OptimizeAlloc(&optimized);
286 for (i = 1; i < aasworld.numareas; i++)
287 {
288 AAS_OptimizeArea(&optimized, i);
289 } //end for
290 //reset the reachability face pointers
291 for (i = 0; i < aasworld.reachabilitysize; i++)
292 {
293 //NOTE: for TRAVEL_ELEVATOR the facenum is the model number of
294 // the elevator
295 if ((aasworld.reachability[i].traveltype & TRAVELTYPE_MASK) == TRAVEL_ELEVATOR) continue;
296 //NOTE: for TRAVEL_JUMPPAD the facenum is the Z velocity and the edgenum is the hor velocity
297 if ((aasworld.reachability[i].traveltype & TRAVELTYPE_MASK) == TRAVEL_JUMPPAD) continue;
298 //NOTE: for TRAVEL_FUNCBOB the facenum and edgenum contain other coded information
299 if ((aasworld.reachability[i].traveltype & TRAVELTYPE_MASK) == TRAVEL_FUNCBOB) continue;
300 //
301 sign = aasworld.reachability[i].facenum;
302 aasworld.reachability[i].facenum = optimized.faceoptimizeindex[abs(aasworld.reachability[i].facenum)];
303 if (sign < 0) aasworld.reachability[i].facenum = -aasworld.reachability[i].facenum;
304 sign = aasworld.reachability[i].edgenum;
305 aasworld.reachability[i].edgenum = optimized.edgeoptimizeindex[abs(aasworld.reachability[i].edgenum)];
306 if (sign < 0) aasworld.reachability[i].edgenum = -aasworld.reachability[i].edgenum;
307 } //end for
308 //store the optimized AAS data into aasworld
309 AAS_OptimizeStore(&optimized);
310 //print some nice stuff :)
311 botimport.Print(PRT_MESSAGE, "AAS data optimized.\n");
312 } //end of the function AAS_Optimize
313