sparc/sunos support: rename quad to quadint. courtesy of Martin Schaffner <maschaffne...
[btb/d2x.git] / 3d / points.c
1 /* $Id: points.c,v 1.5 2002-10-28 19:49:15 btb Exp $ */
2 /*
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.
13 */
14 /*
15  * 
16  * Routines for point definition, rotation, etc.
17  * 
18  * Old Log:
19  *
20  * Revision 1.3  1995/09/21  17:29:40  allender
21  * changed project_point to overflow if z <= 0
22  *
23  * Revision 1.2  1995/09/13  11:31:28  allender
24  * removed checkmuldiv from g3_project_point
25  *
26  * Revision 1.1  1995/05/05  08:52:35  allender
27  * Initial revision
28  *
29  * Revision 1.1  1995/04/17  04:32:25  matt
30  * Initial revision
31  * 
32  * 
33  */
34
35 #ifdef HAVE_CONFIG_H
36 #include <conf.h>
37 #endif
38
39 #ifdef RCS
40 static char rcsid[] = "$Id: points.c,v 1.5 2002-10-28 19:49:15 btb Exp $";
41 #endif
42
43 #include "3d.h"
44 #include "globvars.h"
45
46
47 //code a point.  fills in the p3_codes field of the point, and returns the codes
48 ubyte g3_code_point(g3s_point *p)
49 {
50         ubyte cc=0;
51
52         if (p->p3_x > p->p3_z)
53                 cc |= CC_OFF_RIGHT;
54
55         if (p->p3_y > p->p3_z)
56                 cc |= CC_OFF_TOP;
57
58         if (p->p3_x < -p->p3_z)
59                 cc |= CC_OFF_LEFT;
60
61         if (p->p3_y < -p->p3_z)
62                 cc |= CC_OFF_BOT;
63
64         if (p->p3_z < 0)
65                 cc |= CC_BEHIND;
66
67         return p->p3_codes = cc;
68
69 }
70
71 //rotates a point. returns codes.  does not check if already rotated
72 ubyte g3_rotate_point(g3s_point *dest,vms_vector *src)
73 {
74         vms_vector tempv;
75
76 #ifdef D1XD3D
77         dest->p3_orig = *src;
78 #endif
79
80         vm_vec_sub(&tempv,src,&View_position);
81
82         vm_vec_rotate(&dest->p3_vec,&tempv,&View_matrix);
83
84         dest->p3_flags = 0;     //no projected
85
86         return g3_code_point(dest);
87
88 }
89
90 //checks for overflow & divides if ok, fillig in r
91 //returns true if div is ok, else false
92 int checkmuldiv(fix *r,fix a,fix b,fix c)
93 {
94         quadint q,qt;
95
96         q.low=q.high=0;
97         fixmulaccum(&q,a,b);
98
99         qt = q;
100         if (qt.high < 0)
101                 fixquadnegate(&qt);
102
103         qt.high *= 2;
104         if (qt.low > 0x7fff)
105                 qt.high++;
106
107         if (qt.high >= c)
108                 return 0;
109         else {
110                 *r = fixdivquadlong(q.low,q.high,c);
111                 return 1;
112         }
113 }
114
115 //projects a point
116 void g3_project_point(g3s_point *p)
117 {
118 #ifndef __powerc
119         fix tx,ty;
120
121         if (p->p3_flags & PF_PROJECTED || p->p3_codes & CC_BEHIND)
122                 return;
123
124         if (checkmuldiv(&tx,p->p3_x,Canv_w2,p->p3_z) && checkmuldiv(&ty,p->p3_y,Canv_h2,p->p3_z)) {
125                 p->p3_sx = Canv_w2 + tx;
126                 p->p3_sy = Canv_h2 - ty;
127                 p->p3_flags |= PF_PROJECTED;
128         }
129         else
130                 p->p3_flags |= PF_OVERFLOW;
131 #else
132         double fz;
133         
134         if ((p->p3_flags & PF_PROJECTED) || (p->p3_codes & CC_BEHIND))
135                 return;
136         
137         if ( p->p3_z <= 0 )     {
138                 p->p3_flags |= PF_OVERFLOW;
139                 return;
140         }
141
142         fz = f2fl(p->p3_z);
143         p->p3_sx = fl2f(fCanv_w2 + (f2fl(p->p3_x)*fCanv_w2 / fz));
144         p->p3_sy = fl2f(fCanv_h2 - (f2fl(p->p3_y)*fCanv_h2 / fz));
145
146         p->p3_flags |= PF_PROJECTED;
147 #endif
148 }
149
150 //from a 2d point, compute the vector through that point
151 void g3_point_2_vec(vms_vector *v,short sx,short sy)
152 {
153         vms_vector tempv;
154         vms_matrix tempm;
155
156         tempv.x =  fixmuldiv(fixdiv((sx<<16) - Canv_w2,Canv_w2),Matrix_scale.z,Matrix_scale.x);
157         tempv.y = -fixmuldiv(fixdiv((sy<<16) - Canv_h2,Canv_h2),Matrix_scale.z,Matrix_scale.y);
158         tempv.z = f1_0;
159
160         vm_vec_normalize(&tempv);
161
162         vm_copy_transpose_matrix(&tempm,&Unscaled_matrix);
163
164         vm_vec_rotate(v,&tempv,&tempm);
165
166 }
167
168 //delta rotation functions
169 vms_vector *g3_rotate_delta_x(vms_vector *dest,fix dx)
170 {
171         dest->x = fixmul(View_matrix.rvec.x,dx);
172         dest->y = fixmul(View_matrix.uvec.x,dx);
173         dest->z = fixmul(View_matrix.fvec.x,dx);
174
175         return dest;
176 }
177
178 vms_vector *g3_rotate_delta_y(vms_vector *dest,fix dy)
179 {
180         dest->x = fixmul(View_matrix.rvec.y,dy);
181         dest->y = fixmul(View_matrix.uvec.y,dy);
182         dest->z = fixmul(View_matrix.fvec.y,dy);
183
184         return dest;
185 }
186
187 vms_vector *g3_rotate_delta_z(vms_vector *dest,fix dz)
188 {
189         dest->x = fixmul(View_matrix.rvec.z,dz);
190         dest->y = fixmul(View_matrix.uvec.z,dz);
191         dest->z = fixmul(View_matrix.fvec.z,dz);
192
193         return dest;
194 }
195
196
197 vms_vector *g3_rotate_delta_vec(vms_vector *dest,vms_vector *src)
198 {
199         return vm_vec_rotate(dest,src,&View_matrix);
200 }
201
202 ubyte g3_add_delta_vec(g3s_point *dest,g3s_point *src,vms_vector *deltav)
203 {
204         vm_vec_add(&dest->p3_vec,&src->p3_vec,deltav);
205
206         dest->p3_flags = 0;             //not projected
207
208         return g3_code_point(dest);
209 }
210
211 //calculate the depth of a point - returns the z coord of the rotated point
212 fix g3_calc_point_depth(vms_vector *pnt)
213 {
214         quadint q;
215
216         q.low=q.high=0;
217         fixmulaccum(&q,(pnt->x - View_position.x),View_matrix.fvec.x);
218         fixmulaccum(&q,(pnt->y - View_position.y),View_matrix.fvec.y);
219         fixmulaccum(&q,(pnt->z - View_position.z),View_matrix.fvec.z);
220
221         return fixquadadjust(&q);
222 }
223
224
225