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