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