1 /* $Id: clipper.c,v 1.5 2002-10-03 03:46:34 btb Exp $ */
3 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
4 SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
5 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
6 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
7 IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
8 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
9 FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
10 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS
11 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
12 COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
26 g3s_point temp_points[MAX_POINTS_IN_POLY];
27 g3s_point *free_points[MAX_POINTS_IN_POLY];
29 void init_free_points(void)
33 for (i=0;i<MAX_POINTS_IN_POLY;i++)
34 free_points[i] = &temp_points[i];
38 g3s_point *get_temp_point()
42 Assert (free_point_num < MAX_POINTS_IN_POLY );
43 p = free_points[free_point_num++];
45 p->p3_flags = PF_TEMP_POINT;
50 void free_temp_point(g3s_point *p)
52 Assert(p->p3_flags & PF_TEMP_POINT);
54 free_points[--free_point_num] = p;
56 p->p3_flags &= ~PF_TEMP_POINT;
59 //clips an edge against one plane.
60 g3s_point *clip_edge(int plane_flag,g3s_point *on_pnt,g3s_point *off_pnt)
66 //compute clipping value k = (xs-zs) / (xs-xe-zs+ze)
67 //use x or y as appropriate, and negate x/y value as appropriate
69 if (plane_flag & (CC_OFF_RIGHT | CC_OFF_LEFT)) {
78 if (plane_flag & (CC_OFF_LEFT | CC_OFF_BOT)) {
83 kn = a - on_pnt->p3_z; //xs-zs
84 kd = kn - b + off_pnt->p3_z; //xs-zs-xe+ze
86 tmp = get_temp_point();
88 psx_ratio = fixdiv( kn, kd );
92 // tmp->p3_x = on_pnt->p3_x + fixmuldiv(off_pnt->p3_x-on_pnt->p3_x,kn,kd);
93 // tmp->p3_y = on_pnt->p3_y + fixmuldiv(off_pnt->p3_y-on_pnt->p3_y,kn,kd);
95 tmp->p3_x = on_pnt->p3_x + fixmul( (off_pnt->p3_x-on_pnt->p3_x), psx_ratio);
96 tmp->p3_y = on_pnt->p3_y + fixmul( (off_pnt->p3_y-on_pnt->p3_y), psx_ratio);
98 if (plane_flag & (CC_OFF_TOP|CC_OFF_BOT))
99 tmp->p3_z = tmp->p3_y;
101 tmp->p3_z = tmp->p3_x;
103 if (plane_flag & (CC_OFF_LEFT|CC_OFF_BOT))
104 tmp->p3_z = -tmp->p3_z;
106 if (on_pnt->p3_flags & PF_UVS) {
108 // tmp->p3_u = on_pnt->p3_u + fixmuldiv(off_pnt->p3_u-on_pnt->p3_u,kn,kd);
109 // tmp->p3_v = on_pnt->p3_v + fixmuldiv(off_pnt->p3_v-on_pnt->p3_v,kn,kd);
110 tmp->p3_u = on_pnt->p3_u + fixmul((off_pnt->p3_u-on_pnt->p3_u), psx_ratio);
111 tmp->p3_v = on_pnt->p3_v + fixmul((off_pnt->p3_v-on_pnt->p3_v), psx_ratio);
113 tmp->p3_flags |= PF_UVS;
116 if (on_pnt->p3_flags & PF_LS) {
118 // tmp->p3_r = on_pnt->p3_r + fixmuldiv(off_pnt->p3_r-on_pnt->p3_r,kn,kd);
119 // tmp->p3_g = on_pnt->p3_g + fixmuldiv(off_pnt->p3_g-on_pnt->p3_g,kn,kd);
120 // tmp->p3_b = on_pnt->p3_b + fixmuldiv(off_pnt->p3_b-on_pnt->p3_b,kn,kd);
122 tmp->p3_l = on_pnt->p3_l + fixmul((off_pnt->p3_l-on_pnt->p3_l), psx_ratio);
124 tmp->p3_flags |= PF_LS;
132 //clips a line to the viewing pyramid.
133 void clip_line(g3s_point **p0,g3s_point **p1,ubyte codes_or)
138 //might have these left over
139 (*p0)->p3_flags &= ~(PF_UVS|PF_LS);
140 (*p1)->p3_flags &= ~(PF_UVS|PF_LS);
142 for (plane_flag=1;plane_flag<16;plane_flag<<=1)
143 if (codes_or & plane_flag) {
145 if ((*p0)->p3_codes & plane_flag)
146 {g3s_point *t=*p0; *p0=*p1; *p1=t;} //swap!
150 *p1 = clip_edge(plane_flag,*p0,*p1);
152 if (old_p1->p3_flags & PF_TEMP_POINT)
153 free_temp_point(old_p1);
159 int clip_plane(int plane_flag,g3s_point **src,g3s_point **dest,int *nv,g3s_codes *cc)
162 g3s_point **save_dest=dest;
164 //copy first two verts to end
168 cc->and = 0xff; cc->or = 0;
170 for (i=1;i<=*nv;i++) {
172 if (src[i]->p3_codes & plane_flag) { //cur point off?
174 if (! (src[i-1]->p3_codes & plane_flag)) { //prev not off?
176 *dest = clip_edge(plane_flag,src[i-1],src[i]);
177 cc->or |= (*dest)->p3_codes;
178 cc->and &= (*dest)->p3_codes;
182 if (! (src[i+1]->p3_codes & plane_flag)) {
184 *dest = clip_edge(plane_flag,src[i+1],src[i]);
185 cc->or |= (*dest)->p3_codes;
186 cc->and &= (*dest)->p3_codes;
190 //see if must free discarded point
192 if (src[i]->p3_flags & PF_TEMP_POINT)
193 free_temp_point(src[i]);
195 else { //cur not off, copy to dest buffer
199 cc->or |= src[i]->p3_codes;
200 cc->and &= src[i]->p3_codes;
204 return (dest-save_dest);
208 g3s_point **clip_polygon(g3s_point **src,g3s_point **dest,int *nv,g3s_codes *cc)
213 for (plane_flag=1;plane_flag<16;plane_flag<<=1)
215 if (cc->or & plane_flag) {
217 *nv = clip_plane(plane_flag,src,dest,nv,cc);
219 if (cc->and) //clipped away
222 t = src; src = dest; dest = t;
226 return src; //we swapped after we copied