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 |