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