2 * This program is free software: you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation, either version 3 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "gameglobals.h"
22 #include "sincostab.c"
26 static FILE *fdump
= NULL
;
29 typedef struct PolyPoint
{
37 static int polyPointPoolSize
= 0;
38 static int polyPointPoolPos
= 0;
39 static PolyPoint
*polyPointPool
= NULL
;
40 static int polyScans
[200]; // index of the first point of each scan; -1: none
41 static int firstX
, firstY
;
42 static int lastX
, lastY
;
43 static int pofsx
, pofsy
;
49 void polymodInitialize (void) {
50 for (int f
= 0; f
< 200; ++f
) polyScans
[f
] = -1;
52 polyPointPoolSize
= 0;
58 void polymodDeinitialize (void) {
59 if (polyPointPool
!= NULL
) free(polyPointPool
);
61 polyPointPoolSize
= 0;
67 static inline int allocPolyPoint (int x
, int next
, int dy
) {
68 if (polyPointPoolPos
+1 > polyPointPoolSize
) {
69 int newsz
= polyPointPoolSize
+8192;
70 PolyPoint
*nn
= realloc(polyPointPool
, sizeof(PolyPoint
)*newsz
);
72 if (nn
== NULL
) fatal("out of memory in polymod");
74 polyPointPoolSize
= newsz
;
76 polyPointPool
[polyPointPoolPos
].x
= x
;
77 polyPointPool
[polyPointPoolPos
].next
= next
;
78 polyPointPool
[polyPointPoolPos
].dy
= dy
;
79 polyPointPool
[polyPointPoolPos
].vertexnum
= vertexnum
;
80 return polyPointPoolPos
++;
84 static inline void insertPoint (int x
, int y
, int dy
) {
85 if (y
>= 0 && y
< 200) {
88 if ((n
= polyScans
[y
]) != -1) {
91 for (p
= -1; n
!= -1 && x
> polyPointPool
[n
].x
; p
= n
, n
= polyPointPool
[n
].next
) ;
93 // this is new first point
94 polyScans
[y
] = allocPolyPoint(x
, n
, dy
);
96 // insert new point after p; n is the next point
97 polyPointPool
[p
].next
= allocPolyPoint(x
, n
, dy
);
101 polyScans
[y
] = allocPolyPoint(x
, -1, dy
);
108 static inline void rotate (int *x, int *y) {
109 int64_t tx = (int64_t)(*x)*pscale/POLYFIX_BASE;
110 int64_t ty = (int64_t)(*y)*pscale/POLYFIX_BASE;
111 *x = (tx*costab[pangle]-ty*sintab[pangle])/POLYFIX_BASE+pofsx;
112 *y = (tx*sintab[pangle]+ty*costab[pangle])/POLYFIX_BASE+pofsy;
115 #define rotate(x, y) do { \
116 int64_t tx = (int64_t)(x)*pscale/POLYFIX_BASE; \
117 int64_t ty = (int64_t)(y)*pscale/POLYFIX_BASE; \
118 (x) = (tx*costab[pangle]-ty*sintab[pangle])/POLYFIX_BASE+pofsx; \
119 (y) = (tx*sintab[pangle]+ty*costab[pangle])/POLYFIX_BASE+pofsy; \
123 static void lineDDA (int x0
, int y0
, int x1
, int y1
) {
133 if (fdump
) fprintf(fdump
, "%d: (%d,%d)-(%d,%d)\n", vertexnum
, x0
, y0
, x1
, y1
);
135 if (y0
== y1
) return; // horizontal line
137 //fprintf(stderr, "*(%d,%d)-(%d,%d)\n", x0, y0, x1, y1);
138 if ((y0
< 0 && y1
< 0) || (y0
> 199 && y1
> 199)) return; // out-of-screen lines aren't interesting
141 // straight vertical line
143 for (; y0
< y1
; ++y0
) insertPoint(x0
, y0
, 1);
145 for (--y0
; y0
>= y1
; --y0
) insertPoint(x0
, y0
, -1);
151 dx
= (double)(x1
-x0
)/(double)(y1
-y0
);
152 for (; y0
< y1
; ++y0
) { insertPoint(x
+0.5, y0
, 1); x
+= dx
; }
154 dx
= (double)(x1
-x0
)/(double)(y0
-y1
);
155 for (--y0
; y0
>= y1
; --y0
) { insertPoint(x
+0.5, y0
, -1); x
+= dx
; }
161 void polymodStart (int ofsx
, int ofsy
, int scale
, int angle
) {
162 for (int f
= 0; f
< 200; ++f
) polyScans
[f
] = -1;
163 polyPointPoolPos
= 0;
167 while (angle
< 0) angle
+= 360; // hehe
170 fdump
= fopen("zdump.txt", "w");
176 void polymodAddPoint (int x
, int y
) {
179 lineDDA(lastX
, lastY
, x
, y
);
189 void polymodEnd (void) {
190 if (vertexnum
>= 3) {
192 lineDDA(lastX
, lastY
, firstX
, firstY
);
194 for (int f
= 0; f
< 200; ++f
) polyScans
[f
] = -1;
199 void polymodFill (SDL_Surface
*frame
, Uint8 color
, Uint8 alpha
) {
201 fprintf(fdump
, "=========================\n");
202 for (int y
= 0; y
< 200; ++y
) {
203 int p
= polyScans
[y
], cnt
= 0;
206 fprintf(fdump
, "y: %d\n", y
);
208 fprintf(fdump
, " x: %d (%d) [%d]\n", polyPointPool
[p
].x
, polyPointPool
[p
].dy
, polyPointPool
[p
].vertexnum
);
209 p
= polyPointPool
[p
].next
;
212 if (cnt
%2) fprintf(fdump
, " ***\n");
215 for (int y
= 0; y
< 200; ++y
) {
216 int p
= polyScans
[y
];
219 int wind
= polyPointPool
[p
].dy
, x
= polyPointPool
[p
].x
;
221 for (p
= polyPointPool
[p
].next
; p
!= -1; p
= polyPointPool
[p
].next
) {
222 int ex
= polyPointPool
[p
].x
;
225 while (x
++ < ex
) putPixelA2x(frame
, x
, y
, color
, alpha
);
229 if (polyPointPool
[p
].dy
< 0) putPixelA2x(frame
, x
, y
, color
, alpha
);
230 wind
+= polyPointPool
[p
].dy
;
235 if (fdump
!= NULL
) fclose(fdump
);