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