1 /*
2 
3 Copyright (C) 2015-2018 Night Dive Studios, LLC.
4 
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9 
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 
18 */
19 /*
20  * $Source: r:/prj/lib/src/2d/RCS/fl8tp.c $
21  * $Revision: 1.2 $
22  * $Author: kevin $
23  * $Date: 1994/08/16 12:57:22 $
24  *
25  * full perspective texture mapper.
26  * scanline processors.
27  *
28  */
29 
30 #include "cnvdat.h"
31 #include "fl8tmapdv.h"
32 #include "pertyp.h"
33 #include "plytyp.h"
34 
35 // prototypes
36 void gri_trans_per_umap_hscan_scanline(grs_per_info *pi, grs_bitmap *bm);
37 void gri_trans_per_umap_vscan_scanline(grs_per_info *pi, grs_bitmap *bm);
38 void gri_trans_per_umap_hscan_init(grs_bitmap *bm, grs_per_setup *ps);
39 void gri_trans_per_umap_vscan_init(grs_bitmap *bm, grs_per_setup *ps);
40 
gri_trans_per_umap_hscan_scanline(grs_per_info * pi,grs_bitmap * bm)41 void gri_trans_per_umap_hscan_scanline(grs_per_info *pi, grs_bitmap *bm) {
42     register int k, y_cint;
43     uchar *p, temp_pix;
44 
45     // locals used to speed PPC code
46     fix l_u, l_v, l_du, l_dv, l_y_fix, l_scan_slope, l_dtl, l_dxl, l_dyl, l_dtr, l_dyr;
47     int l_x, l_xl, l_xr, l_xr0, l_u_mask, l_v_mask, l_v_shift;
48     int gr_row, temp_y;
49     uchar *bm_bits;
50 
51     gr_row = grd_bm.row;
52     bm_bits = bm->bits;
53     l_dyr = pi->dyr;
54     l_dtr = pi->dtr;
55     l_dyl = pi->dyl;
56     l_dxl = pi->dxl;
57     l_dtl = pi->dtl;
58     l_scan_slope = pi->scan_slope;
59     l_y_fix = pi->y_fix;
60     l_v_shift = pi->v_shift;
61     l_v_mask = pi->v_mask;
62     l_u_mask = pi->u_mask;
63     l_xr0 = pi->xr0;
64     l_x = pi->x;
65     l_xl = pi->xl;
66     l_xr = pi->xr;
67     l_u = pi->u;
68     l_v = pi->v;
69     l_du = pi->du;
70     l_dv = pi->dv;
71 
72     l_y_fix = l_x * l_scan_slope + fix_make(pi->yp, 0xffff);
73 
74 #if InvDiv
75     k = fix_div(fix_make(1, 0), pi->denom);
76     l_u = pi->u0 + fix_mul_asm_safe(pi->unum, k);
77     l_v = pi->v0 + fix_mul_asm_safe(pi->vnum, k);
78     l_du = fix_mul_asm_safe(pi->dunum, k);
79     l_dv = fix_mul_asm_safe(pi->dvnum, k);
80 #else
81     l_u = pi->u0 + fix_div(pi->unum, pi->denom);
82     l_v = pi->v0 + fix_div(pi->vnum, pi->denom);
83     l_du = fix_div(pi->dunum, pi->denom);
84     l_dv = fix_div(pi->dvnum, pi->denom);
85 #endif
86 
87     l_u += l_x * l_du;
88     l_v += l_x * l_dv;
89 
90     y_cint = fix_int(l_y_fix);
91     if (l_scan_slope < 0)
92         gr_row = -gr_row;
93     p = grd_bm.bits + l_x + y_cint * grd_bm.row;
94     if (l_x < l_xl) {
95         fix test = l_x * l_dyl - y_cint * l_dxl + pi->cl;
96         for (; l_x < l_xl; l_x++) {
97             if (test <= 0) {
98                 int k = (l_u >> 16) & l_u_mask;
99                 k += (l_v >> l_v_shift) & l_v_mask;
100                 temp_pix = bm_bits[k];
101                 if (temp_pix != 0)
102                     *p = temp_pix; // gr_fill_upixel(bm_bits[k],l_x,y_cint);
103             }
104             temp_y = y_cint;
105             y_cint = fix_int(l_y_fix += l_scan_slope);
106             if (temp_y != y_cint) {
107                 p += gr_row;
108                 test += l_dtl;
109             } else
110                 test += l_dyl;
111 
112             p++;
113             l_u += l_du;
114             l_v += l_dv;
115         }
116     }
117 
118     for (; l_x < l_xr0; l_x++) {
119         int k = (l_u >> 16) & l_u_mask;
120         k += (l_v >> l_v_shift) & l_v_mask;
121         temp_pix = bm_bits[k];
122         if (temp_pix != 0)
123             *p = temp_pix; // gr_fill_upixel(bm_bits[k],l_x,y_cint);
124         temp_y = y_cint;
125         y_cint = fix_int(l_y_fix += l_scan_slope);
126         if (temp_y != y_cint)
127             p += gr_row;
128 
129         p++;
130         l_u += l_du;
131         l_v += l_dv;
132     }
133 
134     if (l_x < l_xr) {
135         fix test = l_x * l_dyr - y_cint * pi->dxr + pi->cr;
136         p = grd_bm.bits + l_x + y_cint * grd_bm.row;
137         for (; l_x < l_xr; l_x++) {
138             if (test >= 0) {
139                 int k = (l_u >> 16) & l_u_mask;
140                 k += (l_v >> l_v_shift) & l_v_mask;
141                 temp_pix = bm_bits[k];
142                 if (temp_pix != 0)
143                     *p = temp_pix; // gr_fill_upixel(bm_bits[k],l_x,y_cint);
144             }
145             temp_y = y_cint;
146             y_cint = fix_int(l_y_fix += l_scan_slope);
147             if (temp_y != y_cint) {
148                 p += gr_row;
149                 test += l_dtr;
150             } else
151                 test += l_dyr;
152 
153             p++;
154             l_u += l_du;
155             l_v += l_dv;
156         }
157     }
158 
159     pi->y_fix = l_y_fix;
160     pi->x = l_x;
161     pi->u = l_u;
162     pi->v = l_v;
163     pi->du = l_du;
164     pi->dv = l_dv;
165 }
166 
gri_trans_per_umap_vscan_scanline(grs_per_info * pi,grs_bitmap * bm)167 void gri_trans_per_umap_vscan_scanline(grs_per_info *pi, grs_bitmap *bm) {
168     register int k, x_cint;
169 
170     // locals used to speed PPC code
171     fix l_dxr, l_x_fix, l_u, l_v, l_du, l_dv, l_scan_slope, l_dtl, l_dxl, l_dyl, l_dtr, l_dyr;
172     int l_yl, l_yr0, l_yr, l_y, l_u_mask, l_v_mask, l_v_shift;
173     int gr_row, temp_x;
174     uchar *bm_bits;
175     uchar *p, temp_pix;
176 
177     gr_row = grd_bm.row;
178     bm_bits = bm->bits;
179     l_dxr = pi->dxr;
180     l_x_fix = pi->x_fix;
181     l_y = pi->y;
182     l_yr = pi->yr;
183     l_yr0 = pi->yr0;
184     l_yl = pi->yl;
185     l_dyr = pi->dyr;
186     l_dtr = pi->dtr;
187     l_dyl = pi->dyl;
188     l_dxl = pi->dxl;
189     l_dtl = pi->dtl;
190     l_scan_slope = pi->scan_slope;
191     l_v_shift = pi->v_shift;
192     l_v_mask = pi->v_mask;
193     l_u_mask = pi->u_mask;
194     l_u = pi->u;
195     l_v = pi->v;
196     l_du = pi->du;
197     l_dv = pi->dv;
198 
199     l_x_fix = l_y * l_scan_slope + fix_make(pi->xp, 0xffff);
200 
201 #if InvDiv
202     k = fix_div(fix_make(1, 0), pi->denom);
203     l_u = pi->u0 + fix_mul_asm_safe(pi->unum, k);
204     l_v = pi->v0 + fix_mul_asm_safe(pi->vnum, k);
205     l_du = fix_mul_asm_safe(pi->dunum, k);
206     l_dv = fix_mul_asm_safe(pi->dvnum, k);
207 #else
208     l_u = pi->u0 + fix_div(pi->unum, pi->denom);
209     l_v = pi->v0 + fix_div(pi->vnum, pi->denom);
210     l_du = fix_div(pi->dunum, pi->denom);
211     l_dv = fix_div(pi->dvnum, pi->denom);
212 #endif
213 
214     l_u += l_y * l_du;
215     l_v += l_y * l_dv;
216 
217     x_cint = fix_int(l_x_fix);
218     p = grd_bm.bits + x_cint + l_y * gr_row;
219     if (l_y < l_yl) {
220         fix test = l_y * l_dxl - x_cint * l_dyl + pi->cl;
221         for (; l_y < l_yl; l_y++) {
222             if (test <= 0) {
223                 int k = (l_u >> 16) & l_u_mask;
224                 k += (l_v >> l_v_shift) & l_v_mask;
225                 temp_pix = bm_bits[k];
226                 if (temp_pix != 0)
227                     *p = temp_pix; // gr_fill_upixel(bm_bits[k],x_cint,l_y);
228             }
229             temp_x = x_cint;
230             x_cint = fix_int(l_x_fix += l_scan_slope);
231             if (temp_x != x_cint) {
232                 test += l_dtl;
233                 p -= (temp_x - x_cint);
234             } else
235                 test += l_dxl;
236 
237             p += gr_row;
238             l_u += l_du;
239             l_v += l_dv;
240         }
241     }
242 
243     for (; l_y < l_yr0; l_y++) {
244         int k = (l_u >> 16) & l_u_mask;
245         k += (l_v >> l_v_shift) & l_v_mask;
246         temp_pix = bm_bits[k];
247         if (temp_pix != 0)
248             *p = temp_pix; // gr_fill_upixel(bm_bits[k],x_cint,l_y);
249 
250         temp_x = x_cint;
251         x_cint = fix_int(l_x_fix += l_scan_slope);
252         if (temp_x != x_cint)
253             p -= (temp_x - x_cint);
254 
255         p += gr_row;
256         l_u += l_du;
257         l_v += l_dv;
258     }
259 
260     if (l_y < l_yr) {
261         fix test = l_y * l_dxr - x_cint * l_dyr + pi->cr;
262         p = grd_bm.bits + x_cint + l_y * gr_row;
263         for (; l_y < l_yr; l_y++) {
264             if (test >= 0) {
265                 int k = (l_u >> 16) & l_u_mask;
266                 k += (l_v >> l_v_shift) & l_v_mask;
267                 temp_pix = bm_bits[k];
268                 if (temp_pix != 0)
269                     *p = temp_pix; // gr_fill_upixel(bm_bits[k],x_cint,l_y);
270             }
271 
272             temp_x = x_cint;
273             x_cint = fix_int(l_x_fix += l_scan_slope);
274             if (temp_x != x_cint) {
275                 test += l_dtr;
276                 p -= (temp_x - x_cint);
277             } else
278                 test += l_dxr;
279 
280             p += gr_row;
281             l_u += l_du;
282             l_v += l_dv;
283         }
284     }
285 
286     pi->x_fix = l_x_fix;
287     pi->y = l_y;
288     pi->u = l_u;
289     pi->v = l_v;
290     pi->du = l_du;
291     pi->dv = l_dv;
292 }
293 
294 extern void gri_per_umap_hscan(grs_bitmap *bm, int n, grs_vertex **vpl, grs_per_setup *ps);
295 extern void gri_per_umap_vscan(grs_bitmap *bm, int n, grs_vertex **vpl, grs_per_setup *ps);
296 
gri_trans_per_umap_hscan_init(grs_bitmap * bm,grs_per_setup * ps)297 void gri_trans_per_umap_hscan_init(grs_bitmap *bm, grs_per_setup *ps) {
298     ps->shell_func = (void (*)())gri_per_umap_hscan;
299     ps->scanline_func = (void (*)())gri_trans_per_umap_hscan_scanline;
300 }
301 
gri_trans_per_umap_vscan_init(grs_bitmap * bm,grs_per_setup * ps)302 void gri_trans_per_umap_vscan_init(grs_bitmap *bm, grs_per_setup *ps) {
303     ps->shell_func = (void (*)())gri_per_umap_vscan;
304     ps->scanline_func = (void (*)())gri_trans_per_umap_vscan_scanline;
305 }
306