1 /* $Id: tmapflat.c,v 1.5 2003/02/18 20:15:48 btb 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  *
17  * Flat shader derived from texture mapper (a little slow)
18  *
19  * Old Log:
20  * Revision 1.13  1995/02/20  18:23:24  john
21  * Added new module for C versions of inner loops.
22  *
23  * Revision 1.12  1995/02/20  17:09:17  john
24  * Added code so that you can build the tmapper with no assembly!
25  *
26  * Revision 1.11  1994/11/30  00:58:01  mike
27  * optimizations.
28  *
29  * Revision 1.10  1994/11/28  13:34:32  mike
30  * optimizations.
31  *
32  * Revision 1.9  1994/11/19  15:21:46  mike
33  * rip out unused code.
34  *
35  * Revision 1.8  1994/11/12  16:41:41  mike
36  * *** empty log message ***
37  *
38  * Revision 1.7  1994/11/09  23:05:12  mike
39  * do lighting on texture maps which get flat shaded instead.
40  *
41  * Revision 1.6  1994/10/06  19:53:07  matt
42  * Added function that takes same parms as draw_tmap(), but renders flat
43  *
44  * Revision 1.5  1994/10/06  18:38:12  john
45  * Added the ability to fade a scanline by calling gr_upoly_tmap
46  * with Gr_scanline_darkening_level with a value < MAX_FADE_LEVELS.
47  *
48  * Revision 1.4  1994/05/25  18:46:32  matt
49  * Added gr_upoly_tmap_ylr(), which generates ylr's for a polygon
50  *
51  * Revision 1.3  1994/04/08  16:25:58  mike
52  * Comment out some includes (of header files)
53  * call init_interface_vars_to_assembler.
54  *
55  * Revision 1.2  1994/03/31  08:33:44  mike
56  * Fixup flat shading version of texture mapper (get it?)
57  * (Or maybe not, I admit to not testing my code...hahahah!)
58  *
59  * Revision 1.1  1993/09/08  17:29:10  mike
60  * Initial revision
61  *
62  *
63  */
64 
65 #ifdef HAVE_CONFIG_H
66 #include <conf.h>
67 #endif
68 
69 #include "fix.h"
70 #include "vecmat.h"
71 #include "gr.h"
72 #include "grdef.h"
73 #include "texmap.h"
74 #include "texmapl.h"
75 #include "scanline.h"
76 
77 //#include "tmapext.h"
78 
79 #ifndef OGL
80 
81 void (*scanline_func)(int,fix,fix);
82 
83 // -------------------------------------------------------------------------------------
84 //	Texture map current scanline.
85 //	Uses globals Du_dx and Dv_dx to incrementally compute u,v coordinates
86 // -------------------------------------------------------------------------------------
tmap_scanline_flat(int y,fix xleft,fix xright)87 void tmap_scanline_flat(int y, fix xleft, fix xright)
88 {
89 	if (xright < xleft)
90 		return;
91 
92 	// setup to call assembler scanline renderer
93 
94 	fx_y = y;
95 	fx_xleft = f2i(xleft);
96 	fx_xright = f2i(xright);
97 
98 	if ( Gr_scanline_darkening_level >= GR_FADE_LEVELS )
99 		cur_tmap_scanline_flat();
100 	else	{
101 		tmap_flat_shade_value = Gr_scanline_darkening_level;
102 		cur_tmap_scanline_shaded();
103 	}
104 }
105 
106 
107 //--unused-- void tmap_scanline_shaded(int y, fix xleft, fix xright)
108 //--unused-- {
109 //--unused-- 	fix	dx;
110 //--unused--
111 //--unused-- 	dx = xright - xleft;
112 //--unused--
113 //--unused-- 	// setup to call assembler scanline renderer
114 //--unused--
115 //--unused-- 	fx_y = y << 16;
116 //--unused-- 	fx_xleft = xleft;
117 //--unused-- 	fx_xright = xright;
118 //--unused--
119 //--unused-- 	asm_tmap_scanline_shaded();
120 //--unused-- }
121 
122 
123 // -------------------------------------------------------------------------------------
124 //	Render a texture map.
125 // Linear in outer loop, linear in inner loop.
126 // -------------------------------------------------------------------------------------
texture_map_flat(g3ds_tmap * t,int color)127 void texture_map_flat(g3ds_tmap *t, int color)
128 {
129 	int	vlt,vrt,vlb,vrb;	// vertex left top, vertex right top, vertex left bottom, vertex right bottom
130 	int	topy,boty,y, dy;
131 	fix	dx_dy_left,dx_dy_right;
132 	int	max_y_vertex;
133 	fix	xleft,xright;
134 	fix	recip_dy;
135 	g3ds_vertex *v3d;
136 
137 	v3d = t->verts;
138 
139 	tmap_flat_color = color;
140 
141 	// Determine top and bottom y coords.
142 	compute_y_bounds(t,&vlt,&vlb,&vrt,&vrb,&max_y_vertex);
143 
144 	// Set top and bottom (of entire texture map) y coordinates.
145 	topy = f2i(v3d[vlt].y2d);
146 	boty = f2i(v3d[max_y_vertex].y2d);
147 
148 	// Set amount to change x coordinate for each advance to next scanline.
149 	dy = f2i(t->verts[vlb].y2d) - f2i(t->verts[vlt].y2d);
150 	if (dy < FIX_RECIP_TABLE_SIZE)
151 		recip_dy = fix_recip[dy];
152 	else
153 		recip_dy = F1_0/dy;
154 
155 	dx_dy_left = compute_dx_dy(t,vlt,vlb, recip_dy);
156 
157 	dy = f2i(t->verts[vrb].y2d) - f2i(t->verts[vrt].y2d);
158 	if (dy < FIX_RECIP_TABLE_SIZE)
159 		recip_dy = fix_recip[dy];
160 	else
161 		recip_dy = F1_0/dy;
162 
163 	dx_dy_right = compute_dx_dy(t,vrt,vrb, recip_dy);
164 
165  	// Set initial values for x, u, v
166 	xleft = v3d[vlt].x2d;
167 	xright = v3d[vrt].x2d;
168 
169 	// scan all rows in texture map from top through first break.
170 	// @mk: Should we render the scanline for y==boty?  This violates Matt's spec.
171 
172 	for (y = topy; y < boty; y++) {
173 
174 		// See if we have reached the end of the current left edge, and if so, set
175 		// new values for dx_dy and x,u,v
176 		if (y == f2i(v3d[vlb].y2d)) {
177 			// Handle problem of double points.  Search until y coord is different.  Cannot get
178 			// hung in an infinite loop because we know there is a vertex with a lower y coordinate
179 			// because in the for loop, we don't scan all spanlines.
180 			while (y == f2i(v3d[vlb].y2d)) {
181 				vlt = vlb;
182 				vlb = prevmod(vlb,t->nv);
183 			}
184 			dy = f2i(t->verts[vlb].y2d) - f2i(t->verts[vlt].y2d);
185 			if (dy < FIX_RECIP_TABLE_SIZE)
186 				recip_dy = fix_recip[dy];
187 			else
188 				recip_dy = F1_0/dy;
189 
190 			dx_dy_left = compute_dx_dy(t,vlt,vlb, recip_dy);
191 
192 			xleft = v3d[vlt].x2d;
193 		}
194 
195 		// See if we have reached the end of the current left edge, and if so, set
196 		// new values for dx_dy and x.  Not necessary to set new values for u,v.
197 		if (y == f2i(v3d[vrb].y2d)) {
198 			while (y == f2i(v3d[vrb].y2d)) {
199 				vrt = vrb;
200 				vrb = succmod(vrb,t->nv);
201 			}
202 
203 			dy = f2i(t->verts[vrb].y2d) - f2i(t->verts[vrt].y2d);
204 			if (dy < FIX_RECIP_TABLE_SIZE)
205 				recip_dy = fix_recip[dy];
206 			else
207 				recip_dy = F1_0/dy;
208 
209 			dx_dy_right = compute_dx_dy(t,vrt,vrb, recip_dy);
210 
211 			xright = v3d[vrt].x2d;
212 
213 		}
214 
215 		//tmap_scanline_flat(y, xleft, xright);
216 		(*scanline_func)(y, xleft, xright);
217 
218 		xleft += dx_dy_left;
219 		xright += dx_dy_right;
220 
221 	}
222 	//tmap_scanline_flat(y, xleft, xright);
223 	(*scanline_func)(y, xleft, xright);
224 }
225 
226 
227 //	-----------------------------------------------------------------------------------------
228 //	This is the gr_upoly-like interface to the texture mapper which uses texture-mapper compatible
229 //	(ie, avoids cracking) edge/delta computation.
gr_upoly_tmap(int nverts,int * vert)230 void gr_upoly_tmap(int nverts, int *vert )
231 {
232 	gr_upoly_tmap_ylr(nverts, vert, tmap_scanline_flat);
233 }
234 
235 #include "3d.h"
236 #include "error.h"
237 
238 typedef struct pnt2d {
239 	fix x,y;
240 } pnt2d;
241 
242 #ifdef __WATCOMC__
243 #pragma off (unreferenced)		//bp not referenced
244 #endif
245 
246 //this takes the same partms as draw_tmap, but draws a flat-shaded polygon
draw_tmap_flat(grs_bitmap * bp,int nverts,g3s_point ** vertbuf)247 void draw_tmap_flat(grs_bitmap *bp,int nverts,g3s_point **vertbuf)
248 {
249 	pnt2d	points[MAX_TMAP_VERTS];
250 	int	i;
251 	fix	average_light;
252 	int	color;
253 
254 	Assert(nverts < MAX_TMAP_VERTS);
255 
256 	average_light = vertbuf[0]->p3_l;
257 	for (i=1; i<nverts; i++)
258 		average_light += vertbuf[i]->p3_l;
259 
260 	if (nverts == 4)
261 		average_light = f2i(average_light * NUM_LIGHTING_LEVELS/4);
262 	else
263 		average_light = f2i(average_light * NUM_LIGHTING_LEVELS/nverts);
264 
265 	if (average_light < 0)
266 		average_light = 0;
267 	else if (average_light > NUM_LIGHTING_LEVELS-1)
268 		average_light = NUM_LIGHTING_LEVELS-1;
269 
270 	color = gr_fade_table[average_light*256 + bp->avg_color];
271 	gr_setcolor(color);
272 
273 	for (i=0;i<nverts;i++) {
274 		points[i].x = vertbuf[i]->p3_sx;
275 		points[i].y = vertbuf[i]->p3_sy;
276 	}
277 
278 	gr_upoly_tmap(nverts,(int *) points);
279 
280 }
281 #ifdef __WATCOMC__
282 #pragma on (unreferenced)
283 #endif
284 
285 //	-----------------------------------------------------------------------------------------
286 //This is like gr_upoly_tmap() but instead of drawing, it calls the specified
287 //function with ylr values
gr_upoly_tmap_ylr(int nverts,int * vert,void (* ylr_func)(int,fix,fix))288 void gr_upoly_tmap_ylr(int nverts, int *vert, void (*ylr_func)(int,fix,fix) )
289 {
290 	g3ds_tmap	my_tmap;
291 	int			i;
292 
293 	//--now called from g3_start_frame-- init_interface_vars_to_assembler();
294 
295 	my_tmap.nv = nverts;
296 
297 	for (i=0; i<nverts; i++) {
298 		my_tmap.verts[i].x2d = *vert++;
299 		my_tmap.verts[i].y2d = *vert++;
300 	}
301 
302 	scanline_func = ylr_func;
303 
304 	texture_map_flat(&my_tmap, COLOR);
305 }
306 
307 #endif //!OGL
308