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