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