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/polyint.h $
21  * $Revision: 1.8 $
22  * $Author: kevin $
23  * $Date: 1994/07/18 17:08:25 $
24  *
25  * Polygon scanning internal macros.
26  *
27 */
28 
29 #ifndef __POLYINT_H
30 #define __POLYINT_H
31 
32 #include "fix.h"
33 #include "grs.h"
34 #include "plytyp.h"
35 
36 #define poly_find_y_extrema(_y_min,_y_max,_p_left,_vpl,_n) \
37 do {                                      \
38    grs_vertex **pvp;                      \
39    int __y;                               \
40    _y_min = fix_cint(_vpl[0]->y);         \
41    _y_max = fix_cint(_vpl[0]->y);         \
42    _p_left = _vpl;                        \
43    for (pvp=_vpl+1; pvp<_vpl+_n; ++pvp) { \
44       __y=fix_cint((*pvp)->y);            \
45       if (__y < _y_min) {                 \
46          _y_min = __y;                    \
47          _p_left = pvp;                   \
48       }                                   \
49       if (__y > _y_max)                   \
50          _y_max = __y;                    \
51    }                                      \
52    if (_y_min == _y_max) return;          \
53 } while(0)
54 /*
55 #define poly_find_yw_extrema(_y_min,_y_max,_w_min,_w_max,_p_left,_vpl,_n) \
56 do {                                      \
57    grs_vertex **pvp;                      \
58    int y;                                 \
59    _p_left = _vpl;                        \
60    _y_min = fix_cint(_vpl[0]->y);         \
61    _y_max = fix_cint(_vpl[0]->y);         \
62    _w_min = _vpl[0]->w;                   \
63    _w_max = _vpl[0]->w;                   \
64    for (pvp=_vpl+1; pvp<_vpl+_n; ++pvp) { \
65       y=fix_cint((*pvp)->y);              \
66       if (y < _y_min) {                   \
67          _y_min = y;                      \
68          _w_min = (*pvp)->w;              \
69          _p_left = pvp;                   \
70       }                                   \
71       if (y > _y_max) {                   \
72          _y_max = y;                      \
73          _w_max = (*pvp)->w;              \
74       }                                   \
75    }                                      \
76    if (_y_min == _y_max) return;          \
77 } while(0)
78 */
79 #define poly_find_x_extrema(_x_min,_x_max,_p_top,_vpl,_n) \
80 do {                                      \
81    grs_vertex **pvp;                      \
82    int __x;                               \
83    _x_min = fix_cint(_vpl[0]->x);         \
84    _x_max = fix_cint(_vpl[0]->x);         \
85    _p_top = _vpl;                        \
86    for (pvp=_vpl+1; pvp<_vpl+_n; ++pvp) { \
87       __x=fix_cint((*pvp)->x);            \
88       if (__x < _x_min) {                 \
89          _x_min = __x;                    \
90          _p_top = pvp;                   \
91       }                                   \
92       if (__x > _x_max)                   \
93          _x_max = __x;                    \
94    }                                      \
95    if (_x_min == _x_max) return;          \
96 } while(0)
97 
98 #define poly_find_xw_extrema(_x_min,_x_max,_w_min,_w_max,_p_top,_vpl,_n) \
99 do {                                      \
100    grs_vertex **pvp;                      \
101    int __x;                               \
102    _x_min = fix_cint(_vpl[0]->x);         \
103    _x_max = fix_cint(_vpl[0]->x);         \
104    _w_min = _vpl[0]->w;                   \
105    _w_max = _vpl[0]->w;                   \
106    _p_top = _vpl;                         \
107    for (pvp=_vpl+1; pvp<_vpl+_n; ++pvp) { \
108       __x=fix_cint((*pvp)->x);            \
109       if (__x < _x_min) {                 \
110          _x_min = __x;                    \
111          _w_min = (*pvp)->w;              \
112          _p_top = pvp;                    \
113       }                                   \
114       if (__x > _x_max) {                 \
115          _w_max = (*pvp)->w;              \
116          _x_max = __x;                    \
117       }                                   \
118    }                                      \
119    if (_x_min == _x_max) return;          \
120 } while(0)
121 
122 #define poly_find_x_extrema_retval(_x_min,_x_max,_p_top,_vpl,_n,_retval) \
123 do {                                      \
124    grs_vertex **pvp;                      \
125    int __x;                               \
126    _x_min = fix_cint(_vpl[0]->x);         \
127    _x_max = fix_cint(_vpl[0]->x);         \
128    _p_top = _vpl;                         \
129    for (pvp=_vpl+1; pvp<_vpl+_n; ++pvp) { \
130       __x=fix_cint((*pvp)->x);            \
131       if (__x < _x_min) {                 \
132          _x_min = __x;                    \
133          _p_top = pvp;                    \
134       }                                   \
135       if (__x > _x_max)                   \
136          _x_max = __x;                    \
137    }                                      \
138    if (_x_min == _x_max) return _retval;  \
139 } while(0)
140 
141 
142 #define poly_do_left_edge(_p_left,_prev,_y_left,_y_prev,_y,_vpl,_n) \
143 do {                                            \
144    _y_left = (*_p_left)->y;                     \
145    do {                                         \
146       if (fix_cint(_y_left)==_y) _prev=*_p_left;\
147       if (--_p_left < _vpl)                     \
148          _p_left=_vpl+_n-1;                     \
149       _y_prev=_y_left;                          \
150       _y_left=(*_p_left)->y;                    \
151    } while (fix_cint(_y_left)<=_y);             \
152 } while (0)
153 
154 #define poly_do_top_edge(_p_top,_prev,_x_top,_x_prev,_x,_vpl,_n) \
155 do {                                          \
156    _x_top = (*_p_top)->x;                     \
157    do {                                       \
158       if (fix_cint(_x_top)==_x) _prev=*_p_top;\
159       if (++_p_top >= _vpl+n)                 \
160          _p_top=_vpl;                         \
161       _x_prev=_x_top;                         \
162       _x_top=(*_p_top)->x;                    \
163    } while (fix_cint(_x_top)<=_x);            \
164 } while (0)
165 
166 #define poly_do_right_edge(_p_right,_prev,_y_right,_y_prev,_y,_vpl,_n) \
167 do {                                               \
168    _y_right = (*_p_right)->y;                      \
169    do {                                            \
170       if (fix_cint(_y_right)==_y) _prev=*_p_right; \
171       if (++_p_right >= _vpl+_n)                   \
172          _p_right=_vpl;                            \
173       _y_prev=_y_right;                            \
174       _y_right=(*_p_right)->y;                     \
175    } while (fix_cint(_y_right)<=_y);               \
176 } while (0)
177 
178 #define poly_do_bot_edge(_p_bot,_prev,_x_bot,_x_prev,_x,_vpl,_n) \
179 do {                                          \
180    _x_bot = (*_p_bot)->x;                     \
181    do {                                       \
182       if (fix_cint(_x_bot)==_x) _prev=*_p_bot;\
183       if (--_p_bot < _vpl)                    \
184          _p_bot=_vpl+_n-1;                    \
185       _x_prev=_x_bot;                         \
186       _x_bot=(*_p_bot)->x;                    \
187    } while (fix_cint(_x_bot)<=_x);            \
188 } while (0)
189 
190 #define poly_do_x(p_next,_prev,y_next,_y_prev,_d,x0,dx) \
191 do {                                            \
192    _d = y_next-_y_prev;                         \
193    x0 = _prev->x;                               \
194    dx = fix_div((*p_next)->x-x0, _d);           \
195    x0 += fix_mul(dx,fix_ceil(_y_prev)-_y_prev); \
196 } while (0)
197 
198 #define poly_do_y_bot(p_next,_prev,x_next,_x_prev,_d,y0,dy) \
199 do {                                            \
200    _d = x_next-_x_prev;                         \
201    y0 = _prev->y;                               \
202    dy = fix_div((*p_next)->y-y0, _d);           \
203    y0 += fix_mul(dy,fix_ceil(_x_prev)-_x_prev); \
204    if (dy>0) y0++;                              \
205 } while (0)
206 
207 #define poly_do_y_top(p_next,_prev,x_next,_x_prev,_d,y0,dy) \
208 do {                                            \
209    _d = x_next-_x_prev;                         \
210    y0 = _prev->y;                               \
211    dy = fix_div((*p_next)->y-y0, _d);           \
212    y0 += fix_mul(dy,fix_ceil(_x_prev)-_x_prev); \
213    if (dy>0) y0++;                              \
214 } while (0)
215 
216 #define poly_do_uv(p_next,_prev,_d,u0,du,v0,dv) \
217 do {                                            \
218    u0 = (_prev->u);                             \
219    du = fix_div((*p_next)->u-u0, _d);           \
220    u0 += fix_mul(du,fix_ceil(_prev->y)-_prev->y);\
221    v0 = (_prev->v);                             \
222    dv = fix_div((*p_next)->v-v0, _d);           \
223    v0 += fix_mul(dv,fix_ceil(_prev->y)-_prev->y);\
224 } while (0)
225 
226 #define poly_do_rgb(p_next,_prev,_d,r0,dr,g0,dg,b0,db) \
227 do {                                            \
228    r0 = (_prev->u);                             \
229    dr = fix_div((*p_next)->u-r0, _d);           \
230    r0 += fix_mul(dr,fix_ceil(_prev->y)-_prev->y);\
231    g0 = (_prev->v);                             \
232    dg = fix_div((*p_next)->v-g0, _d);           \
233    g0 += fix_mul(dg,fix_ceil(_prev->y)-_prev->y);\
234    b0 = (_prev->w);                             \
235    db = fix_div((*p_next)->w-b0, _d);           \
236    b0 += fix_mul(db,fix_ceil(_prev->y)-_prev->y);\
237 } while (0)
238 
239 #define poly_do_uvw(p_next,_prev,_d,u0,du,v0,dv,w0,dw) \
240 do {                                                          \
241    w0 = _prev->w;                                             \
242    dw = fix_div((*p_next)->w-w0, _d);                         \
243    u0 = fix_mul(_prev->u,w0);                                 \
244    du = fix_div(fix_mul((*p_next)->u,(*p_next)->w) - u0, _d); \
245    u0 += fix_mul(du,fix_ceil(_prev->y)-_prev->y);              \
246    v0 = fix_mul(_prev->v,w0);                                 \
247    dv = fix_div(fix_mul((*p_next)->v,(*p_next)->w) - v0, _d); \
248    v0 += fix_mul(dv,fix_ceil(_prev->y)-_prev->y);              \
249 } while (0)
250 
251 #define poly_do_i(p_next,_prev,_d,i0,di) \
252 do {                                  \
253    i0 = _prev->i;                     \
254    di = fix_div((*p_next)->i-i0, _d); \
255    i0 += fix_mul(di,fix_ceil(_prev->y)-_prev->y);\
256 } while (0)
257 
258 #define poly_do_iw(p_next,_prev,_d,i0,di,w0) \
259 do {                                                         \
260    i0 = fix_mul(_prev->i,w0);                                \
261    di = fix_div(fix_mul((*p_next)->i,(*p_next)->w) - i0, _d);\
262    i0 += fix_mul(di,fix_ceil(_prev->y)-_prev->y);\
263 } while (0)
264 
265 #define poly_do_uv_vscan(p_next,_prev,_d,u0,du,v0,dv) \
266 do {                                            \
267    u0 = (_prev->u);                             \
268    du = fix_div((*p_next)->u-u0, _d);           \
269    u0 += fix_mul(du,fix_ceil(_prev->x)-_prev->x);\
270    v0 = (_prev->v);                             \
271    dv = fix_div((*p_next)->v-v0, _d);           \
272    v0 += fix_mul(dv,fix_ceil(_prev->x)-_prev->x);\
273 } while (0)
274 
275 #define poly_do_rgb_vscan(p_next,_prev,_d,r0,dr,g0,dg,b0,db) \
276 do {                                            \
277    r0 = (_prev->u);                             \
278    dr = fix_div((*p_next)->u-r0, _d);           \
279    r0 += fix_mul(dr,fix_ceil(_prev->x)-_prev->x);\
280    g0 = (_prev->v);                             \
281    dg = fix_div((*p_next)->v-g0, _d);           \
282    g0 += fix_mul(dg,fix_ceil(_prev->x)-_prev->x);\
283    b0 = (_prev->w);                             \
284    db = fix_div((*p_next)->w-b0, _d);           \
285    b0 += fix_mul(db,fix_ceil(_prev->x)-_prev->x);\
286 } while (0)
287 
288 #define poly_do_uvw_vscan(p_next,_prev,_d,u0,du,v0,dv,w0,dw) \
289 do {                                                          \
290    w0 = _prev->w;                                             \
291    dw = fix_div((*p_next)->w-w0, _d);                         \
292    u0 = fix_mul(_prev->u,w0);                                 \
293    du = fix_div(fix_mul((*p_next)->u,(*p_next)->w) - u0, _d); \
294    u0 += fix_mul(du,fix_ceil(_prev->x)-_prev->x);              \
295    v0 = fix_mul(_prev->v,w0);                                 \
296    dv = fix_div(fix_mul((*p_next)->v,(*p_next)->w) - v0, _d); \
297    v0 += fix_mul(dv,fix_ceil(_prev->x)-_prev->x);              \
298 } while (0)
299 
300 #define poly_do_i_vscan(p_next,_prev,_d,i0,di) \
301 do {                                  \
302    i0 = _prev->i;                     \
303    di = fix_div((*p_next)->i-i0, _d); \
304    i0 += fix_mul(di,fix_ceil(_prev->x)-_prev->x);\
305 } while (0)
306 
307 #define poly_do_iw_vscan(p_next,_prev,_d,i0,di,w0) \
308 do {                                                         \
309    i0 = fix_mul(_prev->i,w0);                                \
310    di = fix_div(fix_mul((*p_next)->i,(*p_next)->w) - i0, _d);\
311    i0 += fix_mul(di,fix_ceil(_prev->x)-_prev->x);\
312 } while (0)
313 #endif /* !__POLYINT_H */
314 
315 
316