]> icculus.org git repositories - taylor/freespace2.git/blob - src/render/3dclipper.cpp
use a better multi_sw_ok_to_commit() check
[taylor/freespace2.git] / src / render / 3dclipper.cpp
1 /*
2  * Copyright (C) Volition, Inc. 1999.  All rights reserved.
3  *
4  * All source code herein is the property of Volition, Inc. You may not sell 
5  * or otherwise commercially exploit the source or things you created based on
6  * the source.
7  */
8
9 /*
10  * $Logfile: /Freespace2/code/Render/3dClipper.cpp $
11  * $Revision$
12  * $Date$
13  * $Author$
14  *
15  * Polygon clipping functions
16  *
17  * $Log$
18  * Revision 1.3  2002/06/09 04:41:25  relnev
19  * added copyright header
20  *
21  * Revision 1.2  2002/05/03 13:34:33  theoddone33
22  * More stuff compiles
23  *
24  * Revision 1.1.1.1  2002/05/03 03:28:10  root
25  * Initial import.
26  *
27  * 
28  * 2     10/07/98 10:53a Dave
29  * Initial checkin.
30  * 
31  * 1     10/07/98 10:51a Dave
32  * 
33  * 13    4/10/98 5:20p John
34  * Changed RGB in lighting structure to be ubytes.  Removed old
35  * not-necessary 24 bpp software stuff.
36  * 
37  * 12    3/23/98 5:00p John
38  * Improved missile trails.  Made smooth alpha under hardware.  Made end
39  * taper.  Made trail touch weapon.
40  * 
41  * 11    3/16/98 4:51p John
42  * Added low-level code to clip all polygons against an arbritary plane.
43  * Took out all old model_interp_zclip and used this new method instead.  
44  * 
45  * 10    1/23/98 5:08p John
46  * Took L out of vertex structure used B (blue) instead.   Took all small
47  * fireballs out of fireball types and used particles instead.  Fixed some
48  * debris explosion things.  Restructured fireball code.   Restructured
49  * some lighting code.   Made dynamic lighting on by default. Made groups
50  * of lasers only cast one light.  Made fireballs not cast light.
51  * 
52  * 9     9/09/97 3:39p Sandeep
53  * warning level 4 bugs
54  * 
55  * 8     3/10/97 5:20p John
56  * Differentiated between Gouraud and Flat shading.  Since we only do flat
57  * shading as of now, we don't need to interpolate L in the outer loop.
58  * This should save a few percent.
59  * 
60  * 7     3/10/97 2:25p John
61  * Made pofview zbuffer.   Made textest work with new model code.  Took
62  * out some unnecessary Asserts in the 3d clipper.
63  * 
64  * 
65  * 6     12/23/96 11:00a John
66  * Restructured POF stuff to support LOD in one pof.
67  * 
68  * 5     11/06/96 2:33p John
69  * Added more asserts for checking that non-tiled UV's are between 0 and
70  * 1.0.    Put code in the model_init code that checks for polys that have
71  * a vertex duplicated and throws them out.
72  *
73  * $NoKeywords: $
74  */
75
76 #include "3dinternal.h"
77 #include "tmapper.h"
78
79 int free_point_num=0;
80
81 vertex temp_points[TMAP_MAX_VERTS];
82 vertex *free_points[TMAP_MAX_VERTS];
83
84 void init_free_points(void)
85 {
86         int i;
87
88         for (i=0;i<TMAP_MAX_VERTS;i++)
89                 free_points[i] = &temp_points[i];
90 }
91
92
93 vertex *get_temp_point()
94 {
95         vertex *p;
96
97         p = free_points[free_point_num++];
98
99         p->flags = PF_TEMP_POINT;
100
101         return p;
102 }
103
104 void free_temp_point(vertex *p)
105 {
106         SDL_assert(p->flags & PF_TEMP_POINT);
107
108         free_points[--free_point_num] = p;
109
110         p->flags &= ~PF_TEMP_POINT;
111 }
112
113 //clips an edge against one plane.
114 vertex *clip_edge(int plane_flag,vertex *on_pnt,vertex *off_pnt, uint flags)
115 {
116         float ratio;
117         vertex *tmp;
118
119         tmp = get_temp_point();
120
121         if ( plane_flag & CC_OFF_USER ) {
122
123                 // Clip with user-defined plane
124                 vector w, ray_direction;
125                 float num,den;
126
127                 vm_vec_sub(&ray_direction,(vector *)&off_pnt->x,(vector *)&on_pnt->x);
128                         
129                 vm_vec_sub(&w,(vector *)&on_pnt->x,&G3_user_clip_point);
130         
131                 den = -vm_vec_dot(&G3_user_clip_normal,&ray_direction);
132                 if ( den == 0.0f ) {    // Ray & plane are parallel, so there is no intersection
133                         Int3(); // Get John
134                         ratio = 1.0f;
135                 } else {
136                         num =  vm_vec_dot(&G3_user_clip_normal,&w);
137         
138                         ratio = num / den;
139                 }
140
141                 tmp->x = on_pnt->x + (off_pnt->x-on_pnt->x) * ratio;
142                 tmp->y = on_pnt->y + (off_pnt->y-on_pnt->y) * ratio;
143                 tmp->z = on_pnt->z + (off_pnt->z-on_pnt->z) * ratio;
144
145         } else {
146                 float a,b,kn,kd;
147
148                 //compute clipping value k = (xs-zs) / (xs-xe-zs+ze)
149                 //use x or y as appropriate, and negate x/y value as appropriate
150
151                 if (plane_flag & (CC_OFF_RIGHT | CC_OFF_LEFT)) {
152                         a = on_pnt->x;
153                         b = off_pnt->x;
154                 }
155                 else {
156                         a = on_pnt->y;
157                         b = off_pnt->y;
158                 }
159
160                 if (plane_flag & (CC_OFF_LEFT | CC_OFF_BOT)) {
161                         a = -a;
162                         b = -b;
163                 }
164
165                 kn = a - on_pnt->z;                                             //xs-zs
166                 kd = kn - b + off_pnt->z;                               //xs-zs-xe+ze
167
168                 ratio = kn / kd;
169
170                 tmp->x = on_pnt->x + (off_pnt->x-on_pnt->x) * ratio;
171                 tmp->y = on_pnt->y + (off_pnt->y-on_pnt->y) * ratio;
172
173                 if (plane_flag & (CC_OFF_TOP|CC_OFF_BOT))       {
174                         tmp->z = tmp->y;
175                 } else {
176                         tmp->z = tmp->x;
177                 }
178
179                 if (plane_flag & (CC_OFF_LEFT|CC_OFF_BOT))
180                         tmp->z = -tmp->z;
181
182         }
183
184         if (flags & TMAP_FLAG_TEXTURED) {
185                 tmp->u = on_pnt->u + (off_pnt->u-on_pnt->u) * ratio;
186                 tmp->v = on_pnt->v + (off_pnt->v-on_pnt->v) * ratio;
187         }
188
189         if (flags & TMAP_FLAG_GOURAUD ) {
190                 if (flags & TMAP_FLAG_RAMP) {
191
192                         float on_b, off_b;
193
194                         on_b = i2fl(on_pnt->b);
195                         off_b = i2fl(off_pnt->b);
196
197                         tmp->b = ubyte(fl2i(on_b + (off_b-on_b) * ratio));
198                 }
199                 if (flags & TMAP_FLAG_RGB) {
200                         float on_r, on_b, on_g;
201                         float off_r, off_b, off_g;
202
203                         on_r = i2fl(on_pnt->r);
204                         off_r = i2fl(off_pnt->r);
205                         on_g = i2fl(on_pnt->g);
206                         off_g = i2fl(off_pnt->g);
207
208                         on_b = i2fl(on_pnt->b);
209                         off_b = i2fl(off_pnt->b);
210
211                         tmp->r = ubyte(fl2i(on_r + (off_r-on_r) * ratio));
212                         tmp->g = ubyte(fl2i(on_g + (off_g-on_g) * ratio));
213                         tmp->b = ubyte(fl2i(on_b + (off_b-on_b) * ratio));
214                 }
215         }
216
217         if (flags & TMAP_FLAG_ALPHA) {
218
219                 float on_a, off_a;
220
221                 on_a = i2fl(on_pnt->a);
222                 off_a = i2fl(off_pnt->a);
223
224                 tmp->a = ubyte(fl2i(on_a + (off_a-on_a) * ratio));
225         }
226
227         g3_code_vertex(tmp);
228
229         return tmp;     
230 }
231
232 //clips a line to the viewing pyramid.
233 void clip_line(vertex **p0,vertex **p1,ubyte codes_or, uint flags)
234 {
235         int plane_flag;
236         vertex *old_p1;
237
238         for (plane_flag=1;plane_flag<=CC_OFF_USER;plane_flag<<=1)
239                 if (codes_or & plane_flag) {
240
241                         if ((*p0)->codes & plane_flag)
242                                 {vertex *t=*p0; *p0=*p1; *p1=t;}        //swap!
243
244                         old_p1 = *p1;
245
246                         *p1 = clip_edge(plane_flag,*p0,*p1,flags);
247                         codes_or = (unsigned char)((*p0)->codes | (*p1)->codes);        //get new codes
248
249                         if (old_p1->flags & PF_TEMP_POINT)
250                                 free_temp_point(old_p1);
251                 }
252
253 }
254
255 int clip_plane(int plane_flag,vertex **src,vertex **dest,int *nv,ccodes *cc,uint flags)
256 {
257         int i;
258         vertex **save_dest=dest;
259
260         //copy first two verts to end
261         src[*nv] = src[0];
262         src[*nv+1] = src[1];
263
264         cc->vand = 0xff; cc->vor = 0;
265
266         for (i=1;i<=*nv;i++) {
267
268                 if (src[i]->codes & plane_flag) {                               //cur point off?
269
270                         if (! (src[i-1]->codes & plane_flag)) { //prev not off?
271
272                                 *dest = clip_edge(plane_flag,src[i-1],src[i],flags);
273                                 cc->vor  |= (*dest)->codes;
274                                 cc->vand &= (*dest)->codes;
275                                 dest++;
276                         }
277
278                         if (! (src[i+1]->codes & plane_flag)) {
279
280                                 *dest = clip_edge(plane_flag,src[i+1],src[i],flags);
281                                 cc->vor  |= (*dest)->codes;
282                                 cc->vand &= (*dest)->codes;
283                                 dest++;
284                         }
285
286                         //see if must free discarded point
287
288                         if (src[i]->flags & PF_TEMP_POINT)
289                                 free_temp_point(src[i]);
290                 }
291                 else {                  //cur not off, copy to dest buffer
292
293                         *dest++ = src[i];
294
295                         cc->vor  |= src[i]->codes;
296                         cc->vand &= src[i]->codes;
297                 }
298         }
299
300         return (dest-save_dest);
301 }
302
303
304 vertex **clip_polygon(vertex **src,vertex **dest,int *nv,ccodes *cc,uint flags)
305 {
306         int plane_flag;
307         vertex **t;
308
309         for (plane_flag=1;plane_flag<=CC_OFF_USER;plane_flag<<=1)
310
311                 if (cc->vor & plane_flag) {
312
313                         *nv = clip_plane(plane_flag,src,dest,nv,cc,flags);
314
315                         if (cc->vand)           //clipped away
316                                 return dest;
317
318                         t = src; src = dest; dest = t;
319
320                 }
321
322         return src;             //we swapped after we copied
323 }
324