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