2 * Copyright (C) Volition, Inc. 1999. All rights reserved.
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
10 * $Logfile: /Freespace2/code/Render/3dClipper.cpp $
15 * Polygon clipping functions
18 * Revision 1.3 2002/06/09 04:41:25 relnev
19 * added copyright header
21 * Revision 1.2 2002/05/03 13:34:33 theoddone33
24 * Revision 1.1.1.1 2002/05/03 03:28:10 root
28 * 2 10/07/98 10:53a Dave
31 * 1 10/07/98 10:51a Dave
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.
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.
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.
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.
52 * 9 9/09/97 3:39p Sandeep
53 * warning level 4 bugs
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.
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.
65 * 6 12/23/96 11:00a John
66 * Restructured POF stuff to support LOD in one pof.
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.
76 #include "3dinternal.h"
81 vertex temp_points[TMAP_MAX_VERTS];
82 vertex *free_points[TMAP_MAX_VERTS];
84 void init_free_points(void)
88 for (i=0;i<TMAP_MAX_VERTS;i++)
89 free_points[i] = &temp_points[i];
93 vertex *get_temp_point()
97 p = free_points[free_point_num++];
99 p->flags = PF_TEMP_POINT;
104 void free_temp_point(vertex *p)
106 Assert(p->flags & PF_TEMP_POINT);
108 free_points[--free_point_num] = p;
110 p->flags &= ~PF_TEMP_POINT;
113 //clips an edge against one plane.
114 vertex *clip_edge(int plane_flag,vertex *on_pnt,vertex *off_pnt, uint flags)
119 tmp = get_temp_point();
121 if ( plane_flag & CC_OFF_USER ) {
123 // Clip with user-defined plane
124 vector w, ray_direction;
127 vm_vec_sub(&ray_direction,(vector *)&off_pnt->x,(vector *)&on_pnt->x);
129 vm_vec_sub(&w,(vector *)&on_pnt->x,&G3_user_clip_point);
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
136 num = vm_vec_dot(&G3_user_clip_normal,&w);
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;
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
151 if (plane_flag & (CC_OFF_RIGHT | CC_OFF_LEFT)) {
160 if (plane_flag & (CC_OFF_LEFT | CC_OFF_BOT)) {
165 kn = a - on_pnt->z; //xs-zs
166 kd = kn - b + off_pnt->z; //xs-zs-xe+ze
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;
173 if (plane_flag & (CC_OFF_TOP|CC_OFF_BOT)) {
179 if (plane_flag & (CC_OFF_LEFT|CC_OFF_BOT))
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;
189 if (flags & TMAP_FLAG_GOURAUD ) {
190 if (flags & TMAP_FLAG_RAMP) {
194 on_b = i2fl(on_pnt->b);
195 off_b = i2fl(off_pnt->b);
197 tmp->b = ubyte(fl2i(on_b + (off_b-on_b) * ratio));
199 if (flags & TMAP_FLAG_RGB) {
200 float on_r, on_b, on_g;
201 float off_r, off_b, off_g;
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);
208 on_b = i2fl(on_pnt->b);
209 off_b = i2fl(off_pnt->b);
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));
217 if (flags & TMAP_FLAG_ALPHA) {
221 on_a = i2fl(on_pnt->a);
222 off_a = i2fl(off_pnt->a);
224 tmp->a = ubyte(fl2i(on_a + (off_a-on_a) * ratio));
232 //clips a line to the viewing pyramid.
233 void clip_line(vertex **p0,vertex **p1,ubyte codes_or, uint flags)
238 for (plane_flag=1;plane_flag<=CC_OFF_USER;plane_flag<<=1)
239 if (codes_or & plane_flag) {
241 if ((*p0)->codes & plane_flag)
242 {vertex *t=*p0; *p0=*p1; *p1=t;} //swap!
246 *p1 = clip_edge(plane_flag,*p0,*p1,flags);
247 codes_or = (unsigned char)((*p0)->codes | (*p1)->codes); //get new codes
249 if (old_p1->flags & PF_TEMP_POINT)
250 free_temp_point(old_p1);
255 int clip_plane(int plane_flag,vertex **src,vertex **dest,int *nv,ccodes *cc,uint flags)
258 vertex **save_dest=dest;
260 //copy first two verts to end
264 cc->vand = 0xff; cc->vor = 0;
266 for (i=1;i<=*nv;i++) {
268 if (src[i]->codes & plane_flag) { //cur point off?
270 if (! (src[i-1]->codes & plane_flag)) { //prev not off?
272 *dest = clip_edge(plane_flag,src[i-1],src[i],flags);
273 cc->vor |= (*dest)->codes;
274 cc->vand &= (*dest)->codes;
278 if (! (src[i+1]->codes & plane_flag)) {
280 *dest = clip_edge(plane_flag,src[i+1],src[i],flags);
281 cc->vor |= (*dest)->codes;
282 cc->vand &= (*dest)->codes;
286 //see if must free discarded point
288 if (src[i]->flags & PF_TEMP_POINT)
289 free_temp_point(src[i]);
291 else { //cur not off, copy to dest buffer
295 cc->vor |= src[i]->codes;
296 cc->vand &= src[i]->codes;
300 return (dest-save_dest);
304 vertex **clip_polygon(vertex **src,vertex **dest,int *nv,ccodes *cc,uint flags)
309 for (plane_flag=1;plane_flag<=CC_OFF_USER;plane_flag<<=1)
311 if (cc->vor & plane_flag) {
313 *nv = clip_plane(plane_flag,src,dest,nv,cc,flags);
315 if (cc->vand) //clipped away
318 t = src; src = dest; dest = t;
322 return src; //we swapped after we copied