Partial application of linux/alpha patch. Courtesy of Falk Hueffner <falk.hueffner...
[btb/d2x.git] / 3d / points.c
1 /*
2 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
3 SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
4 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
5 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
6 IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
7 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
8 FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
9 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
10 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.  
11 COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
12 */
13 /*
14  * $Source: /cvs/cvsroot/d2x/3d/points.c,v $
15  * $Revision: 1.2 $
16  * $Author: bradleyb $
17  * $Date: 2001-01-31 15:17:48 $
18  * 
19  * Routines for point definition, rotation, etc.
20  * 
21  * $Log: not supported by cvs2svn $
22  * Revision 1.1.1.1  2001/01/19 03:29:58  bradleyb
23  * Import of d2x-0.0.8
24  *
25  * Revision 1.1.1.1  1999/06/14 21:57:49  donut
26  * Import of d1x 1.37 source.
27  *
28  * Revision 1.3  1995/09/21  17:29:40  allender
29  * changed project_point to overflow if z <= 0
30  *
31  * Revision 1.2  1995/09/13  11:31:28  allender
32  * removed checkmuldiv from g3_project_point
33  *
34  * Revision 1.1  1995/05/05  08:52:35  allender
35  * Initial revision
36  *
37  * Revision 1.1  1995/04/17  04:32:25  matt
38  * Initial revision
39  * 
40  * 
41  */
42
43 #ifdef HAVE_CONFIG_H
44 #include <conf.h>
45 #endif
46
47 #ifdef RCS
48 static char rcsid[] = "$Id: points.c,v 1.2 2001-01-31 15:17:48 bradleyb Exp $";
49 #endif
50
51 #include "fix.h"
52 #include "vecmat.h"
53 #include "gr.h"
54 #include "3d.h"
55 #include "globvars.h"
56
57
58 //code a point.  fills in the p3_codes field of the point, and returns the codes
59 ubyte g3_code_point(g3s_point *p)
60 {
61         ubyte cc=0;
62
63         if (p->p3_x > p->p3_z)
64                 cc |= CC_OFF_RIGHT;
65
66         if (p->p3_y > p->p3_z)
67                 cc |= CC_OFF_TOP;
68
69         if (p->p3_x < -p->p3_z)
70                 cc |= CC_OFF_LEFT;
71
72         if (p->p3_y < -p->p3_z)
73                 cc |= CC_OFF_BOT;
74
75         if (p->p3_z < 0)
76                 cc |= CC_BEHIND;
77
78         return p->p3_codes = cc;
79
80 }
81
82 //rotates a point. returns codes.  does not check if already rotated
83 ubyte g3_rotate_point(g3s_point *dest,vms_vector *src)
84 {
85         vms_vector tempv;
86
87 #ifdef D1XD3D
88         dest->p3_orig = *src;
89 #endif
90
91         vm_vec_sub(&tempv,src,&View_position);
92
93         vm_vec_rotate(&dest->p3_vec,&tempv,&View_matrix);
94
95         dest->p3_flags = 0;     //no projected
96
97         return g3_code_point(dest);
98
99 }
100
101 //checks for overflow & divides if ok, fillig in r
102 //returns true if div is ok, else false
103 int checkmuldiv(fix *r,fix a,fix b,fix c)
104 {
105         quad q,qt;
106
107         q.low=q.high=0;
108         fixmulaccum(&q,a,b);
109
110         qt = q;
111         if (qt.high < 0)
112                 fixquadnegate(&qt);
113
114         qt.high *= 2;
115         if (qt.low > 0x7fff)
116                 qt.high++;
117
118         if (qt.high >= c)
119                 return 0;
120         else {
121                 *r = fixdivquadlong(q.low,q.high,c);
122                 return 1;
123         }
124 }
125
126 //projects a point
127 void g3_project_point(g3s_point *p)
128 {
129 #ifndef __powerc
130         fix tx,ty;
131
132         if (p->p3_flags & PF_PROJECTED || p->p3_codes & CC_BEHIND)
133                 return;
134
135         if (checkmuldiv(&tx,p->p3_x,Canv_w2,p->p3_z) && checkmuldiv(&ty,p->p3_y,Canv_h2,p->p3_z)) {
136                 p->p3_sx = Canv_w2 + tx;
137                 p->p3_sy = Canv_h2 - ty;
138                 p->p3_flags |= PF_PROJECTED;
139         }
140         else
141                 p->p3_flags |= PF_OVERFLOW;
142 #else
143         double fz;
144         
145         if ((p->p3_flags & PF_PROJECTED) || (p->p3_codes & CC_BEHIND))
146                 return;
147         
148         if ( p->p3_z <= 0 )     {
149                 p->p3_flags |= PF_OVERFLOW;
150                 return;
151         }
152
153         fz = f2fl(p->p3_z);
154         p->p3_sx = fl2f(fCanv_w2 + (f2fl(p->p3_x)*fCanv_w2 / fz));
155         p->p3_sy = fl2f(fCanv_h2 - (f2fl(p->p3_y)*fCanv_h2 / fz));
156
157         p->p3_flags |= PF_PROJECTED;
158 #endif
159 }
160
161 //from a 2d point, compute the vector through that point
162 void g3_point_2_vec(vms_vector *v,short sx,short sy)
163 {
164         vms_vector tempv;
165         vms_matrix tempm;
166
167         tempv.x =  fixmuldiv(fixdiv((sx<<16) - Canv_w2,Canv_w2),Matrix_scale.z,Matrix_scale.x);
168         tempv.y = -fixmuldiv(fixdiv((sy<<16) - Canv_h2,Canv_h2),Matrix_scale.z,Matrix_scale.y);
169         tempv.z = f1_0;
170
171         vm_vec_normalize(&tempv);
172
173         vm_copy_transpose_matrix(&tempm,&Unscaled_matrix);
174
175         vm_vec_rotate(v,&tempv,&tempm);
176
177 }
178
179 //delta rotation functions
180 vms_vector *g3_rotate_delta_x(vms_vector *dest,fix dx)
181 {
182         dest->x = fixmul(View_matrix.rvec.x,dx);
183         dest->y = fixmul(View_matrix.uvec.x,dx);
184         dest->z = fixmul(View_matrix.fvec.x,dx);
185
186         return dest;
187 }
188
189 vms_vector *g3_rotate_delta_y(vms_vector *dest,fix dy)
190 {
191         dest->x = fixmul(View_matrix.rvec.y,dy);
192         dest->y = fixmul(View_matrix.uvec.y,dy);
193         dest->z = fixmul(View_matrix.fvec.y,dy);
194
195         return dest;
196 }
197
198 vms_vector *g3_rotate_delta_z(vms_vector *dest,fix dz)
199 {
200         dest->x = fixmul(View_matrix.rvec.z,dz);
201         dest->y = fixmul(View_matrix.uvec.z,dz);
202         dest->z = fixmul(View_matrix.fvec.z,dz);
203
204         return dest;
205 }
206
207
208 vms_vector *g3_rotate_delta_vec(vms_vector *dest,vms_vector *src)
209 {
210         return vm_vec_rotate(dest,src,&View_matrix);
211 }
212
213 ubyte g3_add_delta_vec(g3s_point *dest,g3s_point *src,vms_vector *deltav)
214 {
215         vm_vec_add(&dest->p3_vec,&src->p3_vec,deltav);
216
217         dest->p3_flags = 0;             //not projected
218
219         return g3_code_point(dest);
220 }
221
222 //calculate the depth of a point - returns the z coord of the rotated point
223 fix g3_calc_point_depth(vms_vector *pnt)
224 {
225         quad q;
226
227         q.low=q.high=0;
228         fixmulaccum(&q,(pnt->x - View_position.x),View_matrix.fvec.x);
229         fixmulaccum(&q,(pnt->y - View_position.y),View_matrix.fvec.y);
230         fixmulaccum(&q,(pnt->z - View_position.z),View_matrix.fvec.z);
231
232         return fixquadadjust(&q);
233 }
234
235
236