]> icculus.org git repositories - btb/d2x.git/blob - texmap/tmapflat.c
use the orientation parameter of g3_draw_bitmap
[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 /*
15  *
16  * Flat shader derived from texture mapper (a little slow)
17  *
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #include <conf.h>
22 #endif
23
24 #include "maths.h"
25 #include "gr.h"
26 #include "texmap.h"
27 #include "texmapl.h"
28 #include "scanline.h"
29
30 //#include "tmapext.h"
31
32
33 #ifndef OGL
34
35 void (*scanline_func)(int,fix,fix);
36
37 // -------------------------------------------------------------------------------------
38 //      Texture map current scanline.
39 //      Uses globals Du_dx and Dv_dx to incrementally compute u,v coordinates
40 // -------------------------------------------------------------------------------------
41 void tmap_scanline_flat(int y, fix xleft, fix xright)
42 {
43         if (xright < xleft)
44                 return;
45
46         // setup to call assembler scanline renderer
47
48         fx_y = y;
49         fx_xleft = xleft/F1_0;          // (xleft >> 16) != xleft/F1_0 for negative numbers, f2i caused random crashes
50         fx_xright = xright/F1_0;
51
52         if ( Gr_scanline_darkening_level >= GR_FADE_LEVELS )
53                 cur_tmap_scanline_flat();
54         else    {
55                 tmap_flat_shade_value = Gr_scanline_darkening_level;
56                 cur_tmap_scanline_shaded();
57         }       
58 }
59
60
61 //--unused-- void tmap_scanline_shaded(int y, fix xleft, fix xright)
62 //--unused-- {
63 //--unused--    fix     dx;
64 //--unused-- 
65 //--unused--    dx = xright - xleft;
66 //--unused-- 
67 //--unused--    // setup to call assembler scanline renderer
68 //--unused-- 
69 //--unused--    fx_y = y << 16;
70 //--unused--    fx_xleft = xleft;
71 //--unused--    fx_xright = xright;
72 //--unused-- 
73 //--unused--    asm_tmap_scanline_shaded();
74 //--unused-- }
75
76
77 // -------------------------------------------------------------------------------------
78 //      Render a texture map.
79 // Linear in outer loop, linear in inner loop.
80 // -------------------------------------------------------------------------------------
81 void texture_map_flat(g3ds_tmap *t, int color)
82 {
83         int     vlt,vrt,vlb,vrb;        // vertex left top, vertex right top, vertex left bottom, vertex right bottom
84         int     topy,boty,y, dy;
85         fix     dx_dy_left,dx_dy_right;
86         int     max_y_vertex;
87         fix     xleft,xright;
88         fix     recip_dy;
89         g3ds_vertex *v3d;
90
91         v3d = t->verts;
92
93         tmap_flat_color = color;
94
95         // Determine top and bottom y coords.
96         compute_y_bounds(t,&vlt,&vlb,&vrt,&vrb,&max_y_vertex);
97
98         // Set top and bottom (of entire texture map) y coordinates.
99         topy = f2i(v3d[vlt].y2d);
100         boty = f2i(v3d[max_y_vertex].y2d);
101
102         // Set amount to change x coordinate for each advance to next scanline.
103         dy = f2i(t->verts[vlb].y2d) - f2i(t->verts[vlt].y2d);
104         if (dy < FIX_RECIP_TABLE_SIZE)
105                 recip_dy = fix_recip[dy];
106         else
107                 recip_dy = F1_0/dy;
108
109         dx_dy_left = compute_dx_dy(t,vlt,vlb, recip_dy);
110
111         dy = f2i(t->verts[vrb].y2d) - f2i(t->verts[vrt].y2d);
112         if (dy < FIX_RECIP_TABLE_SIZE)
113                 recip_dy = fix_recip[dy];
114         else
115                 recip_dy = F1_0/dy;
116
117         dx_dy_right = compute_dx_dy(t,vrt,vrb, recip_dy);
118
119         // Set initial values for x, u, v
120         xleft = v3d[vlt].x2d;
121         xright = v3d[vrt].x2d;
122
123         // scan all rows in texture map from top through first break.
124         // @mk: Should we render the scanline for y==boty?  This violates Matt's spec.
125
126         for (y = topy; y < boty; y++) {
127
128                 // See if we have reached the end of the current left edge, and if so, set
129                 // new values for dx_dy and x,u,v
130                 if (y == f2i(v3d[vlb].y2d)) {
131                         // Handle problem of double points.  Search until y coord is different.  Cannot get
132                         // hung in an infinite loop because we know there is a vertex with a lower y coordinate
133                         // because in the for loop, we don't scan all spanlines.
134                         while (y == f2i(v3d[vlb].y2d)) {
135                                 vlt = vlb;
136                                 vlb = prevmod(vlb,t->nv);
137                         }
138                         dy = f2i(t->verts[vlb].y2d) - f2i(t->verts[vlt].y2d);
139                         if (dy < FIX_RECIP_TABLE_SIZE)
140                                 recip_dy = fix_recip[dy];
141                         else
142                                 recip_dy = F1_0/dy;
143
144                         dx_dy_left = compute_dx_dy(t,vlt,vlb, recip_dy);
145
146                         xleft = v3d[vlt].x2d;
147                 }
148
149                 // See if we have reached the end of the current left edge, and if so, set
150                 // new values for dx_dy and x.  Not necessary to set new values for u,v.
151                 if (y == f2i(v3d[vrb].y2d)) {
152                         while (y == f2i(v3d[vrb].y2d)) {
153                                 vrt = vrb;
154                                 vrb = succmod(vrb,t->nv);
155                         }
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                         xright = v3d[vrt].x2d;
166
167                 }
168
169                 //tmap_scanline_flat(y, xleft, xright);
170                 (*scanline_func)(y, xleft, xright);
171
172                 xleft += dx_dy_left;
173                 xright += dx_dy_right;
174
175         }
176         //tmap_scanline_flat(y, xleft, xright);
177         (*scanline_func)(y, xleft, xright);
178 }
179
180
181 //      -----------------------------------------------------------------------------------------
182 //      This is the gr_upoly-like interface to the texture mapper which uses texture-mapper compatible
183 //      (ie, avoids cracking) edge/delta computation.
184 void gr_upoly_tmap(int nverts, int *vert )
185 {
186         gr_upoly_tmap_ylr(nverts, vert, tmap_scanline_flat);
187 }
188
189 #include "3d.h"
190 #include "dxxerror.h"
191
192 typedef struct pnt2d {
193         fix x,y;
194 } pnt2d;
195
196 #ifdef __WATCOMC__
197 #pragma off (unreferenced)              //bp not referenced
198 #endif
199
200 //this takes the same partms as draw_tmap, but draws a flat-shaded polygon
201 void draw_tmap_flat(grs_bitmap *bp,int nverts,g3s_point **vertbuf)
202 {
203         pnt2d   points[MAX_TMAP_VERTS];
204         int     i;
205         fix     average_light;
206         int     color;
207
208         Assert(nverts < MAX_TMAP_VERTS);
209
210         average_light = vertbuf[0]->p3_l;
211         for (i=1; i<nverts; i++)
212                 average_light += vertbuf[i]->p3_l;
213
214         if (nverts == 4)
215                 average_light = f2i(average_light * NUM_LIGHTING_LEVELS/4);
216         else
217                 average_light = f2i(average_light * NUM_LIGHTING_LEVELS/nverts);
218
219         if (average_light < 0)
220                 average_light = 0;
221         else if (average_light > NUM_LIGHTING_LEVELS-1)
222                 average_light = NUM_LIGHTING_LEVELS-1;
223
224         color = gr_fade_table[average_light*256 + bp->avg_color];
225         gr_setcolor(color);
226
227         for (i=0;i<nverts;i++) {
228                 points[i].x = vertbuf[i]->p3_sx;
229                 points[i].y = vertbuf[i]->p3_sy;
230         }
231
232         gr_upoly_tmap(nverts,(int *) points);
233
234 }
235 #ifdef __WATCOMC__
236 #pragma on (unreferenced)
237 #endif
238
239 //      -----------------------------------------------------------------------------------------
240 //This is like gr_upoly_tmap() but instead of drawing, it calls the specified
241 //function with ylr values
242 void gr_upoly_tmap_ylr(int nverts, int *vert, void (*ylr_func)(int,fix,fix) )
243 {
244         g3ds_tmap       my_tmap;
245         int                     i;
246
247         //--now called from g3_start_frame-- init_interface_vars_to_assembler();
248
249         my_tmap.nv = nverts;
250
251         for (i=0; i<nverts; i++) {
252                 my_tmap.verts[i].x2d = *vert++;
253                 my_tmap.verts[i].y2d = *vert++;
254         }
255
256         scanline_func = ylr_func;
257
258         texture_map_flat(&my_tmap, COLOR);
259 }
260
261 #endif //!OGL