1 /*
2 ===========================================================================
3
4 Doom 3 GPL Source Code
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
6
7 This file is part of the Doom 3 GPL Source Code ("Doom 3 Source Code").
8
9 Doom 3 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 Doom 3 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 Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
21
22 In addition, the Doom 3 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 Doom 3 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 #include "sys/platform.h"
30
31 #include "tools/compilers/dmap/dmap.h"
32
33 /*
34
35 All triangle list functions should behave reasonably with NULL lists.
36
37 */
38
39 /*
40 ===============
41 AllocTri
42 ===============
43 */
AllocTri(void)44 mapTri_t *AllocTri( void ) {
45 mapTri_t *tri;
46
47 tri = (mapTri_t *)Mem_Alloc( sizeof( *tri ) );
48 memset( tri, 0, sizeof( *tri ) );
49 return tri;
50 }
51
52 /*
53 ===============
54 FreeTri
55 ===============
56 */
FreeTri(mapTri_t * tri)57 void FreeTri( mapTri_t *tri ) {
58 Mem_Free( tri );
59 }
60
61
62 /*
63 ===============
64 MergeTriLists
65
66 This does not copy any tris, it just relinks them
67 ===============
68 */
MergeTriLists(mapTri_t * a,mapTri_t * b)69 mapTri_t *MergeTriLists( mapTri_t *a, mapTri_t *b ) {
70 mapTri_t **prev;
71
72 prev = &a;
73 while ( *prev ) {
74 prev = &(*prev)->next;
75 }
76
77 *prev = b;
78
79 return a;
80 }
81
82
83 /*
84 ===============
85 FreeTriList
86 ===============
87 */
FreeTriList(mapTri_t * a)88 void FreeTriList( mapTri_t *a ) {
89 mapTri_t *next;
90
91 for ( ; a ; a = next ) {
92 next = a->next;
93 Mem_Free( a );
94 }
95 }
96
97 /*
98 ===============
99 CopyTriList
100 ===============
101 */
CopyTriList(const mapTri_t * a)102 mapTri_t *CopyTriList( const mapTri_t *a ) {
103 mapTri_t *testList;
104 const mapTri_t *tri;
105
106 testList = NULL;
107 for ( tri = a ; tri ; tri = tri->next ) {
108 mapTri_t *copy;
109
110 copy = CopyMapTri( tri );
111 copy ->next = testList;
112 testList = copy;
113 }
114
115 return testList;
116 }
117
118
119 /*
120 =============
121 CountTriList
122 =============
123 */
CountTriList(const mapTri_t * tri)124 int CountTriList( const mapTri_t *tri ) {
125 int c;
126
127 c = 0;
128 while ( tri ) {
129 c++;
130 tri = tri->next;
131 }
132
133 return c;
134 }
135
136
137 /*
138 ===============
139 CopyMapTri
140 ===============
141 */
CopyMapTri(const mapTri_t * tri)142 mapTri_t *CopyMapTri( const mapTri_t *tri ) {
143 mapTri_t *t;
144
145 t = (mapTri_t *)Mem_Alloc( sizeof( *t ) );
146 *t = *tri;
147
148 return t;
149 }
150
151 /*
152 ===============
153 MapTriArea
154 ===============
155 */
MapTriArea(const mapTri_t * tri)156 float MapTriArea( const mapTri_t *tri ) {
157 return idWinding::TriangleArea( tri->v[0].xyz, tri->v[1].xyz, tri->v[2].xyz );
158 }
159
160 /*
161 ===============
162 RemoveBadTris
163
164 Return a new list with any zero or negative area triangles removed
165 ===============
166 */
RemoveBadTris(const mapTri_t * list)167 mapTri_t *RemoveBadTris( const mapTri_t *list ) {
168 mapTri_t *newList;
169 mapTri_t *copy;
170 const mapTri_t *tri;
171
172 newList = NULL;
173
174 for ( tri = list ; tri ; tri = tri->next ) {
175 if ( MapTriArea( tri ) > 0 ) {
176 copy = CopyMapTri( tri );
177 copy->next = newList;
178 newList = copy;
179 }
180 }
181
182 return newList;
183 }
184
185 /*
186 ================
187 BoundTriList
188 ================
189 */
BoundTriList(const mapTri_t * list,idBounds & b)190 void BoundTriList( const mapTri_t *list, idBounds &b ) {
191 b.Clear();
192 for ( ; list ; list = list->next ) {
193 b.AddPoint( list->v[0].xyz );
194 b.AddPoint( list->v[1].xyz );
195 b.AddPoint( list->v[2].xyz );
196 }
197 }
198
199 /*
200 ================
201 DrawTri
202 ================
203 */
DrawTri(const mapTri_t * tri)204 void DrawTri( const mapTri_t *tri ) {
205 idWinding w;
206
207 w.SetNumPoints( 3 );
208 VectorCopy( tri->v[0].xyz, w[0] );
209 VectorCopy( tri->v[1].xyz, w[1] );
210 VectorCopy( tri->v[2].xyz, w[2] );
211 DrawWinding( &w );
212 }
213
214
215 /*
216 ================
217 FlipTriList
218
219 Swaps the vertex order
220 ================
221 */
FlipTriList(mapTri_t * tris)222 void FlipTriList( mapTri_t *tris ) {
223 mapTri_t *tri;
224
225 for ( tri = tris ; tri ; tri = tri->next ) {
226 idDrawVert v;
227 const struct hashVert_s *hv;
228 struct optVertex_s *ov;
229
230 v = tri->v[0];
231 tri->v[0] = tri->v[2];
232 tri->v[2] = v;
233
234 hv = tri->hashVert[0];
235 tri->hashVert[0] = tri->hashVert[2];
236 tri->hashVert[2] = hv;
237
238 ov = tri->optVert[0];
239 tri->optVert[0] = tri->optVert[2];
240 tri->optVert[2] = ov;
241 }
242 }
243
244 /*
245 ================
246 WindingForTri
247 ================
248 */
WindingForTri(const mapTri_t * tri)249 idWinding *WindingForTri( const mapTri_t *tri ) {
250 idWinding *w;
251
252 w = new idWinding( 3 );
253 w->SetNumPoints( 3 );
254 VectorCopy( tri->v[0].xyz, (*w)[0] );
255 VectorCopy( tri->v[1].xyz, (*w)[1] );
256 VectorCopy( tri->v[2].xyz, (*w)[2] );
257
258 return w;
259 }
260
261 /*
262 ================
263 TriVertsFromOriginal
264
265 Regenerate the texcoords and colors on a fragmented tri from the plane equations
266 ================
267 */
TriVertsFromOriginal(mapTri_t * tri,const mapTri_t * original)268 void TriVertsFromOriginal( mapTri_t *tri, const mapTri_t *original ) {
269 int i, j;
270 float denom;
271
272 denom = idWinding::TriangleArea( original->v[0].xyz, original->v[1].xyz, original->v[2].xyz );
273 if ( denom == 0 ) {
274 return; // original was degenerate, so it doesn't matter
275 }
276
277 for ( i = 0 ; i < 3 ; i++ ) {
278 float a, b, c;
279
280 // find the barycentric coordinates
281 a = idWinding::TriangleArea( tri->v[i].xyz, original->v[1].xyz, original->v[2].xyz ) / denom;
282 b = idWinding::TriangleArea( tri->v[i].xyz, original->v[2].xyz, original->v[0].xyz ) / denom;
283 c = idWinding::TriangleArea( tri->v[i].xyz, original->v[0].xyz, original->v[1].xyz ) / denom;
284
285 // regenerate the interpolated values
286 tri->v[i].st[0] = a * original->v[0].st[0]
287 + b * original->v[1].st[0] + c * original->v[2].st[0];
288 tri->v[i].st[1] = a * original->v[0].st[1]
289 + b * original->v[1].st[1] + c * original->v[2].st[1];
290
291 for ( j = 0 ; j < 3 ; j++ ) {
292 tri->v[i].normal[j] = a * original->v[0].normal[j]
293 + b * original->v[1].normal[j] + c * original->v[2].normal[j];
294 }
295 tri->v[i].normal.Normalize();
296 }
297 }
298
299 /*
300 ================
301 WindingToTriList
302
303 Generates a new list of triangles with proper texcoords from a winding
304 created by clipping the originalTri
305
306 OriginalTri can be NULL if you don't care about texCoords
307 ================
308 */
WindingToTriList(const idWinding * w,const mapTri_t * originalTri)309 mapTri_t *WindingToTriList( const idWinding *w, const mapTri_t *originalTri ) {
310 mapTri_t *tri;
311 mapTri_t *triList;
312 int i, j;
313 const idVec3 *vec;
314
315 if ( !w ) {
316 return NULL;
317 }
318
319 triList = NULL;
320 for ( i = 2 ; i < w->GetNumPoints() ; i++ ) {
321 tri = AllocTri();
322 if ( !originalTri ) {
323 memset( tri, 0, sizeof( *tri ) );
324 } else {
325 *tri = *originalTri;
326 }
327 tri->next = triList;
328 triList = tri;
329
330 for ( j = 0 ; j < 3 ; j++ ) {
331 if ( j == 0 ) {
332 vec = &((*w)[0]).ToVec3();
333 } else if ( j == 1 ) {
334 vec = &((*w)[i-1]).ToVec3();
335 } else {
336 vec = &((*w)[i]).ToVec3();
337 }
338
339 VectorCopy( *vec, tri->v[j].xyz );
340 }
341 if ( originalTri ) {
342 TriVertsFromOriginal( tri, originalTri );
343 }
344 }
345
346 return triList;
347 }
348
349
350 /*
351 ==================
352 ClipTriList
353 ==================
354 */
ClipTriList(const mapTri_t * list,const idPlane & plane,float epsilon,mapTri_t ** front,mapTri_t ** back)355 void ClipTriList( const mapTri_t *list, const idPlane &plane, float epsilon,
356 mapTri_t **front, mapTri_t **back ) {
357 const mapTri_t *tri;
358 mapTri_t *newList;
359 idWinding *w, *frontW, *backW;
360
361 *front = NULL;
362 *back = NULL;
363
364 for ( tri = list ; tri ; tri = tri->next ) {
365 w = WindingForTri( tri );
366 w->Split( plane, epsilon, &frontW, &backW );
367
368 newList = WindingToTriList( frontW, tri );
369 *front = MergeTriLists( *front, newList );
370
371 newList = WindingToTriList( backW, tri );
372 *back = MergeTriLists( *back, newList );
373
374 delete w;
375 }
376
377 }
378
379 /*
380 ==================
381 PlaneForTri
382 ==================
383 */
PlaneForTri(const mapTri_t * tri,idPlane & plane)384 void PlaneForTri( const mapTri_t *tri, idPlane &plane ) {
385 plane.FromPoints( tri->v[0].xyz, tri->v[1].xyz, tri->v[2].xyz );
386 }
387