Subversion Repositories Games.Descent

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 pmbaty 1
/*
2
 * Portions of this file are copyright Rebirth contributors and licensed as
3
 * described in COPYING.txt.
4
 * Portions of this file are copyright Parallax Software and licensed
5
 * according to the Parallax license below.
6
 * See COPYING.txt for license details.
7
 
8
THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
9
SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
10
END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
11
ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
12
IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
13
SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
14
FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
15
CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
16
AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
17
COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
18
*/
19
 
20
/*
21
 *
22
 * Flat shader derived from texture mapper (a little slow)
23
 *
24
 */
25
 
26
#include "maths.h"
27
#include "vecmat.h"
28
#include "gr.h"
29
#include "grdef.h"
30
#include "texmap.h"
31
#include "texmapl.h"
32
#include "scanline.h"
33
 
34
#include "compiler-range_for.h"
35
#include "partial_range.h"
36
 
37
//#include "tmapext.h"
38
 
39
#if !DXX_USE_OGL
40
#include "3d.h"
41
#include "dxxerror.h"
42
 
43
#include "3d.h"
44
#include "dxxerror.h"
45
 
46
namespace dcx {
47
 
48
static void gr_upoly_tmap_ylr(grs_canvas &, uint_fast32_t nverts, const int *vert, uint8_t color);
49
 
50
// -------------------------------------------------------------------------------------
51
//      Texture map current scanline.
52
//      Uses globals Du_dx and Dv_dx to incrementally compute u,v coordinates
53
// -------------------------------------------------------------------------------------
54
static void tmap_scanline_flat(grs_canvas &canvas, int y, fix xleft, fix xright)
55
{
56
        if (xright < xleft)
57
                return;
58
 
59
        // setup to call assembler scanline renderer
60
 
61
        fx_y = y;
62
        fx_xleft = xleft/F1_0;          // (xleft >> 16) != xleft/F1_0 for negative numbers, f2i caused random crashes
63
        fx_xright = xright/F1_0;
64
 
65
        if (canvas.cv_fade_level >= GR_FADE_OFF)
66
                cur_tmap_scanline_flat();
67
        else    {
68
                cur_tmap_scanline_shaded(canvas.cv_fade_level);
69
        }      
70
}
71
 
72
 
73
//--unused-- void tmap_scanline_shaded(int y, fix xleft, fix xright)
74
//--unused-- {
75
//--unused--    fix     dx;
76
//--unused-- 
77
//--unused--    dx = xright - xleft;
78
//--unused-- 
79
//--unused--    // setup to call assembler scanline renderer
80
//--unused-- 
81
//--unused--    fx_y = y << 16;
82
//--unused--    fx_xleft = xleft;
83
//--unused--    fx_xright = xright;
84
//--unused-- 
85
//--unused--    asm_tmap_scanline_shaded();
86
//--unused-- }
87
 
88
 
89
// -------------------------------------------------------------------------------------
90
//      Render a texture map.
91
// Linear in outer loop, linear in inner loop.
92
// -------------------------------------------------------------------------------------
93
static void texture_map_flat(grs_canvas &canvas, const g3ds_tmap &t, int color)
94
{
95
        int     vlt,vrt,vlb,vrb;        // vertex left top, vertex right top, vertex left bottom, vertex right bottom
96
        int     topy,boty,dy;
97
        fix     dx_dy_left,dx_dy_right;
98
        int     max_y_vertex;
99
        fix     xleft,xright;
100
        fix     recip_dy;
101
        auto &v3d = t.verts;
102
 
103
        tmap_flat_color = color;
104
 
105
        // Determine top and bottom y coords.
106
        compute_y_bounds(t,vlt,vlb,vrt,vrb,max_y_vertex);
107
 
108
        // Set top and bottom (of entire texture map) y coordinates.
109
        topy = f2i(v3d[vlt].y2d);
110
        boty = f2i(v3d[max_y_vertex].y2d);
111
 
112
        // Set amount to change x coordinate for each advance to next scanline.
113
        dy = f2i(t.verts[vlb].y2d) - f2i(t.verts[vlt].y2d);
114
        recip_dy = fix_recip(dy);
115
 
116
        dx_dy_left = compute_dx_dy(t,vlt,vlb, recip_dy);
117
 
118
        dy = f2i(t.verts[vrb].y2d) - f2i(t.verts[vrt].y2d);
119
        recip_dy = fix_recip(dy);
120
 
121
        dx_dy_right = compute_dx_dy(t,vrt,vrb, recip_dy);
122
 
123
        // Set initial values for x, u, v
124
        xleft = v3d[vlt].x2d;
125
        xright = v3d[vrt].x2d;
126
 
127
        // scan all rows in texture map from top through first break.
128
        // @mk: Should we render the scanline for y==boty?  This violates Matt's spec.
129
 
130
        for (int y = topy; y < boty; y++) {
131
 
132
                // See if we have reached the end of the current left edge, and if so, set
133
                // new values for dx_dy and x,u,v
134
                if (y == f2i(v3d[vlb].y2d)) {
135
                        // Handle problem of double points.  Search until y coord is different.  Cannot get
136
                        // hung in an infinite loop because we know there is a vertex with a lower y coordinate
137
                        // because in the for loop, we don't scan all spanlines.
138
                        while (y == f2i(v3d[vlb].y2d)) {
139
                                vlt = vlb;
140
                                vlb = prevmod(vlb,t.nv);
141
                        }
142
                        dy = f2i(t.verts[vlb].y2d) - f2i(t.verts[vlt].y2d);
143
                        recip_dy = fix_recip(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
                        recip_dy = fix_recip(dy);
160
 
161
                        dx_dy_right = compute_dx_dy(t,vrt,vrb, recip_dy);
162
 
163
                        xright = v3d[vrt].x2d;
164
 
165
                }
166
                tmap_scanline_flat(canvas, y, xleft, xright);
167
 
168
                xleft += dx_dy_left;
169
                xright += dx_dy_right;
170
 
171
        }
172
        tmap_scanline_flat(canvas, boty, xleft, xright);
173
}
174
 
175
//      -----------------------------------------------------------------------------------------
176
//      This is the gr_upoly-like interface to the texture mapper which uses texture-mapper compatible
177
//      (ie, avoids cracking) edge/delta computation.
178
void gr_upoly_tmap(grs_canvas &canvas, uint_fast32_t nverts, const std::array<fix, MAX_POINTS_IN_POLY * 2> &vert, const uint8_t color)
179
{
180
        gr_upoly_tmap_ylr(canvas, nverts, vert.data(), color);
181
}
182
 
183
struct pnt2d {
184
        fix x,y;
185
};
186
 
187
//this takes the same partms as draw_tmap, but draws a flat-shaded polygon
188
void draw_tmap_flat(grs_canvas &canvas, const grs_bitmap &bp, uint_fast32_t nverts, const g3s_point *const *vertbuf)
189
{
190
        union {
191
                std::array<pnt2d, MAX_TMAP_VERTS> points;
192
                std::array<int, MAX_TMAP_VERTS * (sizeof(pnt2d) / sizeof(int))> ipoints;
193
        };
194
        static_assert(sizeof(points) == sizeof(ipoints), "array size mismatch");
195
        fix     average_light;
196
        Assert(nverts < MAX_TMAP_VERTS);
197
        average_light = vertbuf[0]->p3_l;
198
        for (int i=1; i<nverts; i++)
199
                average_light += vertbuf[i]->p3_l;
200
 
201
        if (nverts == 4)
202
                average_light = f2i(average_light * NUM_LIGHTING_LEVELS/4);
203
        else
204
                average_light = f2i(average_light * NUM_LIGHTING_LEVELS/nverts);
205
 
206
        if (average_light < 0)
207
                average_light = 0;
208
        else if (average_light > NUM_LIGHTING_LEVELS-1)
209
                average_light = NUM_LIGHTING_LEVELS-1;
210
 
211
        color_t color = gr_fade_table[average_light][bp.avg_color];
212
 
213
        for (int i=0;i<nverts;i++) {
214
                points[i].x = vertbuf[i]->p3_sx;
215
                points[i].y = vertbuf[i]->p3_sy;
216
        }
217
        gr_upoly_tmap_ylr(canvas, nverts, ipoints.data(), color);
218
}
219
 
220
//      -----------------------------------------------------------------------------------------
221
//This is like gr_upoly_tmap() but instead of drawing, it calls the specified
222
//function with ylr values
223
static void gr_upoly_tmap_ylr(grs_canvas &canvas, uint_fast32_t nverts, const int *vert, const uint8_t color)
224
{
225
        g3ds_tmap       my_tmap;
226
        my_tmap.nv = nverts;
227
 
228
        range_for (auto &i, partial_range(my_tmap.verts, nverts))
229
        {
230
                i.x2d = *vert++;
231
                i.y2d = *vert++;
232
        }
233
        texture_map_flat(canvas, my_tmap, color);
234
}
235
 
236
}
237
#endif //!OGL