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