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