amd64 fixes
[btb/d2x.git] / 3d / rod.c
1 /* $Id: rod.c,v 1.7 2005-08-02 06:14:48 chris 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  * Rod routines
17  * 
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #include <conf.h>
22 #endif
23
24 #ifdef RCS
25 static char rcsid[] = "$Id: rod.c,v 1.7 2005-08-02 06:14:48 chris Exp $";
26 #endif
27
28 #include "3d.h"
29 #include "globvars.h"
30 #include "fix.h"
31
32 grs_point blob_vertices[4];
33 g3s_point rod_points[4];
34 g3s_point *rod_point_list[] = {&rod_points[0],&rod_points[1],&rod_points[2],&rod_points[3]};
35
36 g3s_uvl uvl_list[4] = { { 0x0200,0x0200,0 },
37                                                                 { 0xfe00,0x0200,0 },
38                                                                 { 0xfe00,0xfe00,0 },
39                                                                 { 0x0200,0xfe00,0 }};
40
41 //compute the corners of a rod.  fills in vertbuf.
42 int calc_rod_corners(g3s_point *bot_point,fix bot_width,g3s_point *top_point,fix top_width)
43 {
44         vms_vector delta_vec,top,tempv,rod_norm;
45         ubyte codes_and;
46         int i;
47
48         //compute vector from one point to other, do cross product with vector
49         //from eye to get perpendiclar
50
51         vm_vec_sub(&delta_vec,&bot_point->p3_vec,&top_point->p3_vec);
52
53         //unscale for aspect
54
55         delta_vec.x = fixdiv(delta_vec.x,Matrix_scale.x);
56         delta_vec.y = fixdiv(delta_vec.y,Matrix_scale.y);
57
58         //calc perp vector
59
60         //do lots of normalizing to prevent overflowing.  When this code works,
61         //it should be optimized
62
63         vm_vec_normalize(&delta_vec);
64
65         vm_vec_copy_normalize(&top,&top_point->p3_vec);
66
67         vm_vec_cross(&rod_norm,&delta_vec,&top);
68
69         vm_vec_normalize(&rod_norm);
70
71         //scale for aspect
72
73         rod_norm.x = fixmul(rod_norm.x,Matrix_scale.x);
74         rod_norm.y = fixmul(rod_norm.y,Matrix_scale.y);
75
76         //now we have the usable edge.  generate four points
77
78         //top points
79
80         vm_vec_copy_scale(&tempv,&rod_norm,top_width);
81         tempv.z = 0;
82
83         vm_vec_add(&rod_points[0].p3_vec,&top_point->p3_vec,&tempv);
84         vm_vec_sub(&rod_points[1].p3_vec,&top_point->p3_vec,&tempv);
85
86         vm_vec_copy_scale(&tempv,&rod_norm,bot_width);
87         tempv.z = 0;
88
89         vm_vec_sub(&rod_points[2].p3_vec,&bot_point->p3_vec,&tempv);
90         vm_vec_add(&rod_points[3].p3_vec,&bot_point->p3_vec,&tempv);
91
92
93         //now code the four points
94
95         for (i=0,codes_and=0xff;i<4;i++)
96                 codes_and &= g3_code_point(&rod_points[i]);
97
98         if (codes_and)
99                 return 1;               //1 means off screen
100
101         //clear flags for new points (not projected)
102
103         for (i=0;i<4;i++)
104                 rod_points[i].p3_flags = 0;
105
106         return 0;
107 }
108
109 //draw a polygon that is always facing you
110 //returns 1 if off screen, 0 if drew
111 bool g3_draw_rod_flat(g3s_point *bot_point,fix bot_width,g3s_point *top_point,fix top_width)
112 {
113         if (calc_rod_corners(bot_point,bot_width,top_point,top_width))
114                 return 0;
115
116         return g3_draw_poly(4,rod_point_list);
117
118 }
119
120 //draw a bitmap object that is always facing you
121 //returns 1 if off screen, 0 if drew
122 bool g3_draw_rod_tmap(grs_bitmap *bitmap,g3s_point *bot_point,fix bot_width,g3s_point *top_point,fix top_width,fix light)
123 {
124         if (calc_rod_corners(bot_point,bot_width,top_point,top_width))
125                 return 0;
126
127         uvl_list[0].l = uvl_list[1].l = uvl_list[2].l = uvl_list[3].l = light;
128
129         return g3_draw_tmap(4,rod_point_list,uvl_list,bitmap);
130 }
131
132 #ifndef __powerc
133 int checkmuldiv(fix *r,fix a,fix b,fix c);
134 #endif
135
136 #ifndef OGL
137 //draws a bitmap with the specified 3d width & height 
138 //returns 1 if off screen, 0 if drew
139 bool g3_draw_bitmap(vms_vector *pos,fix width,fix height,grs_bitmap *bm, int orientation)
140 {
141 #ifndef __powerc
142         g3s_point pnt;
143         fix t,w,h;
144
145         if (g3_rotate_point(&pnt,pos) & CC_BEHIND)
146                 return 1;
147
148         g3_project_point(&pnt);
149
150         if (pnt.p3_flags & PF_OVERFLOW)
151                 return 1;
152
153         if (checkmuldiv(&t,width,Canv_w2,pnt.p3_z))
154                 w = fixmul(t,Matrix_scale.x);
155         else
156                 return 1;
157
158         if (checkmuldiv(&t,height,Canv_h2,pnt.p3_z))
159                 h = fixmul(t,Matrix_scale.y);
160         else
161                 return 1;
162
163         blob_vertices[0].x = pnt.p3_sx - w;
164         blob_vertices[0].y = blob_vertices[1].y = pnt.p3_sy - h;
165         blob_vertices[1].x = blob_vertices[2].x = pnt.p3_sx + w;
166         blob_vertices[2].y = pnt.p3_sy + h;
167
168         scale_bitmap(bm,blob_vertices,0);
169
170         return 0;
171 #else
172         g3s_point pnt;
173         fix w,h;
174         double fz;
175
176         if (g3_rotate_point(&pnt,pos) & CC_BEHIND)
177                 return 1;
178
179         g3_project_point(&pnt);
180
181         if (pnt.p3_flags & PF_OVERFLOW)
182                 return 1;
183
184         if (pnt.p3_z == 0)
185                 return 1;
186                 
187         fz = f2fl(pnt.p3_z);
188         w = fixmul(fl2f(((f2fl(width)*fCanv_w2) / fz)), Matrix_scale.x);
189         h = fixmul(fl2f(((f2fl(height)*fCanv_h2) / fz)), Matrix_scale.y);
190
191         blob_vertices[0].x = pnt.p3_sx - w;
192         blob_vertices[0].y = blob_vertices[1].y = pnt.p3_sy - h;
193         blob_vertices[1].x = blob_vertices[2].x = pnt.p3_sx + w;
194         blob_vertices[2].y = pnt.p3_sy + h;
195
196         scale_bitmap(bm, blob_vertices, 0);
197
198         return 0;
199 #endif
200 }
201 #endif
202
203
204