remove some redundancy by not needing to do SoundSlots[i].playing = 0; in addition...
[btb/d2x.git] / texmap / tmapflat.c
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 // -------------------------------------------------------------------------------------
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 // -------------------------------------------------------------------------------------
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.
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
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
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