#include "compat.h" #define PI 3.141592653589793 typedef struct { float x, y; } point2d; typedef struct { float x, y, z; } point3d; typedef struct { float x, y, z; int32_t n; } kgln_t; typedef struct { int32_t w, s; } vertlist_t; typedef struct { float x, y; int32_t n, ns, nw; } wall_t; typedef struct { float z[2]; point2d grad[2]; wall_t *wall; int32_t n; } sect_t; static int32_t numsects; static sect_t *sec; //Build1 format variables: typedef struct { int16_t picnum, heinum; int8_t shade; uint8_t pal, xpanning, ypanning; } build7surf_t; typedef struct { int16_t wallptr, wallnum; int32_t z[2]; int16_t stat[2]; build7surf_t surf[2]; uint8_t visibility, filler; int16_t lotag, hitag, extra; } build7sect_t; typedef struct { int32_t x, y; int16_t point2, nextwall, nextsect, cstat, picnum, overpicnum; int8_t shade; uint8_t pal, xrepeat, yrepeat, xpanning, ypanning; int16_t lotag, hitag, extra; } build7wall_t; static build7sect_t b7sec; static build7wall_t b7wal; static void checknextwalls (void) { float x0, y0, x1, y1; int32_t s0, w0, w0n, s1, w1, w1n; //Clear all nextsect/nextwalls for (s0=0;s0>1);g;g>>=1) for (i=0;i=0)&&(a[j]>a[j+g]);j-=g) { t = a[j]; a[j] = a[j+g]; a[j+g] = t; } } static float getslopez (sect_t *s, int32_t i, float x, float y) { wall_t *wal = s->wall; return (wal[0].x-x)*s->grad[i].x + (wal[0].y-y)*s->grad[i].y + s->z[i]; } typedef struct { float x[4], y[2]; wall_t * pwal[2]; } zoid_t; static int32_t sect2trap (wall_t *wal, int32_t n, zoid_t **retzoids, int32_t *retnzoids) { zoid_t *zoids = 0; float f, x0, y0, x1, y1, sy0, sy1, cury, *secy = NULL, *trapx0 = NULL, *trapx1 = NULL; int32_t i, j, g, s, secn, ntrap, tot, zoidalloc; wall_t * k; wall_t ** pwal = NULL; (*retzoids) = 0; (*retnzoids) = 0; if (n < 3) return 0; secy = (float *)malloc(n*sizeof(secy[0])); if (!secy) goto badret; trapx0 = (float *)malloc(n*sizeof(trapx0[0])); if (!trapx0) goto badret; trapx1 = (float *)malloc(n*sizeof(trapx1[0])); if (!trapx1) goto badret; pwal = (wall_t **)malloc(n*sizeof(pwal[0])); if (!pwal) goto badret; for (i=n-1;i>=0;i--) secy[i] = wal[i].y; shellsrt(secy,n); for (i=0,secn=0,cury=-1e32f;i cury) { secy[secn++] = cury = secy[i]; } zoidalloc = secn*2; //just a guess (not guaranteed to fit) zoids = (zoid_t *)malloc(zoidalloc*sizeof(zoid_t)); if (!zoids) goto badret; tot = 0; for (s=0;s y1) { f = x0; x0 = x1; x1 = f; f = y0; y0 = y1; y1 = f; } if ((y0 >= sy1) || (y1 <= sy0)) continue; if (y0 < sy0) x0 = (sy0-wal[i].y)*(wal[j].x-wal[i].x)/(wal[j].y-wal[i].y) + wal[i].x; if (y1 > sy1) x1 = (sy1-wal[i].y)*(wal[j].x-wal[i].x)/(wal[j].y-wal[i].y) + wal[i].x; trapx0[ntrap] = x0; trapx1[ntrap] = x1; pwal[ntrap] = &wal[i]; ntrap++; } for (g=(ntrap>>1);g;g>>=1) for (i=0;i=0;j-=g) { if (trapx0[j]+trapx1[j] <= trapx0[j+g]+trapx1[j+g]) break; f = trapx0[j]; trapx0[j] = trapx0[j+g]; trapx0[j+g] = f; f = trapx1[j]; trapx1[j] = trapx1[j+g]; trapx1[j+g] = f; k = pwal[j]; pwal[j] = pwal[j+g]; pwal[j+g] = k; } if (tot+ntrap > zoidalloc) { zoidalloc <<= 1; if (tot+ntrap > zoidalloc) zoidalloc = tot+ntrap; zoids = (zoid_t *)realloc(zoids,zoidalloc*sizeof(zoid_t)); if (!zoids) goto badret; } for (i=0;i= (unsigned)numsects) return 0; vn = 0; nw = wal[w].n+w; bw = wal[w].nw; do { wal2 = sec[bs].wall; i = wal2[bw].n+bw; //Make sure it's an opposite wall if ((wal[w].x == wal2[i].x) && (wal[nw].x == wal2[bw].x) && (wal[w].y == wal2[i].y) && (wal[nw].y == wal2[bw].y)) { if (vn < maxverts) { ver[vn].s = bs; ver[vn].w = bw; vn++; } } bs = wal2[bw].ns; bw = wal2[bw].nw; } while (bs != s); //Sort next sects by order of height in middle of wall (crap sort) fx = (wal[w].x+wal[nw].x)*.5f; fy = (wal[w].y+wal[nw].y)*.5f; for (k=1;k getslopez(&sec[ver[k].s],0,fx,fy) + getslopez(&sec[ver[k].s],1,fx,fy)) { tver = ver[j]; ver[j] = ver[k]; ver[k] = tver; } return(vn); } static int32_t wallclip (kgln_t *pol, kgln_t *npol) { float f, dz0, dz1; dz0 = pol[3].z-pol[0].z; dz1 = pol[2].z-pol[1].z; if (dz0 > 0.0) //do not include null case for rendering { npol[0] = pol[0]; if (dz1 > 0.0) //do not include null case for rendering { npol[1] = pol[1]; npol[2] = pol[2]; npol[3] = pol[3]; npol[0].n = npol[1].n = npol[2].n = 1; npol[3].n = -3; return 4; } else { f = dz0/(dz0-dz1); npol[1].x = (pol[1].x-pol[0].x)*f + pol[0].x; npol[1].y = (pol[1].y-pol[0].y)*f + pol[0].y; npol[1].z = (pol[1].z-pol[0].z)*f + pol[0].z; npol[2] = pol[3]; npol[0].n = npol[1].n = 1; npol[2].n = -2; return 3; } } if (dz1 <= 0.0) return 0; //do not include null case for rendering f = dz0/(dz0-dz1); npol[0].x = (pol[1].x-pol[0].x)*f + pol[0].x; npol[0].y = (pol[1].y-pol[0].y)*f + pol[0].y; npol[0].z = (pol[1].z-pol[0].z)*f + pol[0].z; npol[1] = pol[1]; npol[2] = pol[2]; npol[0].n = npol[1].n = 1; npol[2].n = -2; return 3; } // //STL binary format: //char filler[80]; //uint32_t numtris; //for (i=0;i>1]; if ((!n) || (pol[n].x != pol[n-1].x) || (pol[n].y != pol[n-1].y)) { pol[n].z = (wal[0].x-pol[n].x)*grad->x + (wal[0].y-pol[n].y)*grad->y + fz; pol[n].n = 1; n++; } } if (n < 3) continue; pol[n-1].n = 1-n; fp[0].x = pol[0].x; fp[0].y = pol[0].y; fp[0].z = pol[0].z; for (j=2;j 0.f) f = -1.f/sqrtf(f); fp2.x *= f; fp2.y *= f; fp2.z *= f; fwrite(&fp2,4*3,1,fil); fwrite(fp,4*3*3,1,fil); fwrite(tbuf,2,1,fil); //2 bytes of filler numtris++; } } free(zoids); } wal = sec[s].wall; wn = sec[s].n; for (w=0;w 0) { s0 = verts[k-1].s; cf0 = 1; } else { s0 = s; cf0 = 0; } if (k < vn) { s1 = verts[k ].s; cf1 = 0; } else { s1 = s; cf1 = 1; } pol[0].z = getslopez(&sec[s0],cf0,pol[0].x,pol[0].y); pol[1].z = getslopez(&sec[s0],cf0,pol[1].x,pol[1].y); pol[2].z = getslopez(&sec[s1],cf1,pol[2].x,pol[2].y); pol[3].z = getslopez(&sec[s1],cf1,pol[3].x,pol[3].y); i = wallclip(pol,npol); if (!i) continue; fp[0].x = npol[0].x; fp[0].y = npol[0].y; fp[0].z = npol[0].z; for (j=2;j 0.f) f = -1.f/sqrtf(f); fp2.x *= f; fp2.y *= f; fp2.z *= f; fwrite(&fp2,4*3,1,fil); fwrite(fp,4*3*3,1,fil); fwrite(tbuf,2,1,fil); //2 bytes of filler numtris++; } } } } i = ftell(fil); fseek(fil,80,SEEK_SET); fwrite(&numtris,4,1,fil); fseek(fil,i,SEEK_SET); fclose(fil); } static int32_t loadmap (char *filnam) { float f, fx, fy; int32_t i, j, k; int16_t s; FILE *fil; fil = fopen(filnam,"rb"); if (!fil) return 0; fread(&i,4,1,fil); if (i != 0x00000007) return 0; //not Build1 .MAP format 7 fseek(fil,20,SEEK_SET); fread(&s,2,1,fil); numsects = (int32_t)s; sec = (sect_t *)malloc(numsects*sizeof(sect_t)); memset(sec,0,numsects*sizeof(sect_t)); for (i=0;i 0.f) f = 1.f/sqrtf(f); fx *= f; fy *= f; for (j=0;j<2;j++) { sec[i].grad[j].x = fx*sec[i].grad[j].y; sec[i].grad[j].y = fy*sec[i].grad[j].y; } } checknextwalls(); fclose(fil); return 1; } int main (int argc, char **argv) { if (argc != 3) { printf("map2stl [in:Build .MAP (v7)] [out:STL file] by Ken Silverman (05/15/2009)"); return 1; } if (!loadmap(argv[1])) { printf("error loading map\n"); return 2; } saveasstl(argv[2]); return 0; }