Increment version number in preparation for release
[btb/d2x.git] / 3d / rod.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/rod.c,v $
15  * $Revision: 1.2 $
16  * $Author: bradleyb $
17  * $Date: 2001-01-31 15:17:48 $
18  * 
19  * Rod routines
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.2  1999/09/21 04:05:55  donut
26  * mostly complete OGL implementation (still needs bitmap handling (reticle), and door/fan textures are corrupt)
27  *
28  * Revision 1.1.1.1  1999/06/14 21:57:50  donut
29  * Import of d1x 1.37 source.
30  *
31  * Revision 1.2  1995/09/13  11:31:46  allender
32  * removed checkmuldiv in PPC implemenation
33  *
34  * Revision 1.1  1995/05/05  08:52:45  allender
35  * Initial revision
36  *
37  * Revision 1.1  1995/04/17  06:42:08  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: rod.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 grs_point blob_vertices[4];
58 g3s_point rod_points[4];
59 g3s_point *rod_point_list[] = {&rod_points[0],&rod_points[1],&rod_points[2],&rod_points[3]};
60
61 g3s_uvl uvl_list[4] = { { 0x0200,0x0200,0 },
62                                                                 { 0xfe00,0x0200,0 },
63                                                                 { 0xfe00,0xfe00,0 },
64                                                                 { 0x0200,0xfe00,0 }};
65
66 //compute the corners of a rod.  fills in vertbuf.
67 int calc_rod_corners(g3s_point *bot_point,fix bot_width,g3s_point *top_point,fix top_width)
68 {
69         vms_vector delta_vec,top,tempv,rod_norm;
70         ubyte codes_and;
71         int i;
72
73         //compute vector from one point to other, do cross product with vector
74         //from eye to get perpendiclar
75
76         vm_vec_sub(&delta_vec,&bot_point->p3_vec,&top_point->p3_vec);
77
78         //unscale for aspect
79
80         delta_vec.x = fixdiv(delta_vec.x,Matrix_scale.x);
81         delta_vec.y = fixdiv(delta_vec.y,Matrix_scale.y);
82
83         //calc perp vector
84
85         //do lots of normalizing to prevent overflowing.  When this code works,
86         //it should be optimized
87
88         vm_vec_normalize(&delta_vec);
89
90         vm_vec_copy_normalize(&top,&top_point->p3_vec);
91
92         vm_vec_cross(&rod_norm,&delta_vec,&top);
93
94         vm_vec_normalize(&rod_norm);
95
96         //scale for aspect
97
98         rod_norm.x = fixmul(rod_norm.x,Matrix_scale.x);
99         rod_norm.y = fixmul(rod_norm.y,Matrix_scale.y);
100
101         //now we have the usable edge.  generate four points
102
103         //top points
104
105         vm_vec_copy_scale(&tempv,&rod_norm,top_width);
106         tempv.z = 0;
107
108         vm_vec_add(&rod_points[0].p3_vec,&top_point->p3_vec,&tempv);
109         vm_vec_sub(&rod_points[1].p3_vec,&top_point->p3_vec,&tempv);
110
111         vm_vec_copy_scale(&tempv,&rod_norm,bot_width);
112         tempv.z = 0;
113
114         vm_vec_sub(&rod_points[2].p3_vec,&bot_point->p3_vec,&tempv);
115         vm_vec_add(&rod_points[3].p3_vec,&bot_point->p3_vec,&tempv);
116
117
118         //now code the four points
119
120         for (i=0,codes_and=0xff;i<4;i++)
121                 codes_and &= g3_code_point(&rod_points[i]);
122
123         if (codes_and)
124                 return 1;               //1 means off screen
125
126         //clear flags for new points (not projected)
127
128         for (i=0;i<4;i++)
129                 rod_points[i].p3_flags = 0;
130
131         return 0;
132 }
133
134 //draw a polygon that is always facing you
135 //returns 1 if off screen, 0 if drew
136 bool g3_draw_rod_flat(g3s_point *bot_point,fix bot_width,g3s_point *top_point,fix top_width)
137 {
138         if (calc_rod_corners(bot_point,bot_width,top_point,top_width))
139                 return 0;
140
141         return g3_draw_poly(4,rod_point_list);
142
143 }
144
145 //draw a bitmap object that is always facing you
146 //returns 1 if off screen, 0 if drew
147 bool g3_draw_rod_tmap(grs_bitmap *bitmap,g3s_point *bot_point,fix bot_width,g3s_point *top_point,fix top_width,fix light)
148 {
149         if (calc_rod_corners(bot_point,bot_width,top_point,top_width))
150                 return 0;
151
152         uvl_list[0].l = uvl_list[1].l = uvl_list[2].l = uvl_list[3].l = light;
153
154         return g3_draw_tmap(4,rod_point_list,uvl_list,bitmap);
155 }
156
157 #ifndef __powerc
158 int checkmuldiv(fix *r,fix a,fix b,fix c);
159 #endif
160
161 #if (!(defined(D1XD3D) || defined(OGL)))
162 //draws a bitmap with the specified 3d width & height 
163 //returns 1 if off screen, 0 if drew
164 bool g3_draw_bitmap(vms_vector *pos,fix width,fix height,grs_bitmap *bm, int orientation)
165 {
166 #ifndef __powerc
167         g3s_point pnt;
168         fix t,w,h;
169
170         if (g3_rotate_point(&pnt,pos) & CC_BEHIND)
171                 return 1;
172
173         g3_project_point(&pnt);
174
175         if (pnt.p3_flags & PF_OVERFLOW)
176                 return 1;
177
178         if (checkmuldiv(&t,width,Canv_w2,pnt.p3_z))
179                 w = fixmul(t,Matrix_scale.x);
180         else
181                 return 1;
182
183         if (checkmuldiv(&t,height,Canv_h2,pnt.p3_z))
184                 h = fixmul(t,Matrix_scale.y);
185         else
186                 return 1;
187
188         blob_vertices[0].x = pnt.p3_sx - w;
189         blob_vertices[0].y = blob_vertices[1].y = pnt.p3_sy - h;
190         blob_vertices[1].x = blob_vertices[2].x = pnt.p3_sx + w;
191         blob_vertices[2].y = pnt.p3_sy + h;
192
193         scale_bitmap(bm,blob_vertices,0);
194
195         return 0;
196 #else
197         g3s_point pnt;
198         fix w,h;
199         double fz;
200
201         if (g3_rotate_point(&pnt,pos) & CC_BEHIND)
202                 return 1;
203
204         g3_project_point(&pnt);
205
206         if (pnt.p3_flags & PF_OVERFLOW)
207                 return 1;
208
209         if (pnt.p3_z == 0)
210                 return 1;
211                 
212         fz = f2fl(pnt.p3_z);
213         w = fixmul(fl2f(((f2fl(width)*fCanv_w2) / fz)), Matrix_scale.x);
214         h = fixmul(fl2f(((f2fl(height)*fCanv_h2) / fz)), Matrix_scale.y);
215
216         blob_vertices[0].x = pnt.p3_sx - w;
217         blob_vertices[0].y = blob_vertices[1].y = pnt.p3_sy - h;
218         blob_vertices[1].x = blob_vertices[2].x = pnt.p3_sx + w;
219         blob_vertices[2].y = pnt.p3_sy + h;
220
221         scale_bitmap(bm,blob_vertices);
222
223         return 0;
224 #endif
225 }
226 #endif
227
228
229