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