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