static int puttri( /* convert a triangle */ char *v1, char *v2, char *v3 ) { VNDX v1i, v2i, v3i; RREAL *v1c, *v2c, *v3c; RREAL *v1n, *v2n, *v3n; if (!cvtndx(v1i, v1) || !cvtndx(v2i, v2) || !cvtndx(v3i, v3)) { error(WARNING, "bad vertex reference"); return(0); } if (v1i[1]>=0 && v2i[1]>=0 && v3i[1]>=0) { v1c = vtlist[v1i[1]]; v2c = vtlist[v2i[1]]; v3c = vtlist[v3i[1]]; } else v1c = v2c = v3c = NULL; if (v1i[2]>=0 && v2i[2]>=0 && v3i[2]>=0) { v1n = vnlist[v1i[2]]; v2n = vnlist[v2i[2]]; v3n = vnlist[v3i[2]]; } else v1n = v2n = v3n = NULL; return(cvtri(getmod(), vlist[v1i[0]], vlist[v2i[0]], vlist[v3i[0]], v1n, v2n, v3n, v1c, v2c, v3c) >= 0); }
int nonplanar( /* are vertices non-planar? */ int ac, char **av ) { VNDX vi; RREAL *p0, *p1; FVECT v1, v2, nsum, newn; double d; int i; if (!cvtndx(vi, av[0])) return(0); if (!flatten && vi[2] >= 0) return(1); /* has interpolated normals */ if (ac < 4) return(0); /* it's a triangle! */ /* set up */ p0 = vlist[vi[0]]; if (!cvtndx(vi, av[1])) return(0); /* error gets caught later */ nsum[0] = nsum[1] = nsum[2] = 0.; p1 = vlist[vi[0]]; fvsum(v2, p1, p0, -1.0); for (i = 2; i < ac; i++) { VCOPY(v1, v2); if (!cvtndx(vi, av[i])) return(0); p1 = vlist[vi[0]]; fvsum(v2, p1, p0, -1.0); fcross(newn, v1, v2); if (normalize(newn) == 0.0) { if (i < 3) return(1); /* can't deal with this */ fvsum(nsum, nsum, nsum, 1./(i-2)); continue; } d = fdot(newn,nsum); if (d >= 0) { if (d < (1.0-FTINY)*(i-2)) return(1); fvsum(nsum, nsum, newn, 1.0); } else { if (d > -(1.0-FTINY)*(i-2)) return(1); fvsum(nsum, nsum, newn, -1.0); } } return(0); }
int putface( /* put out an N-sided polygon */ int ac, char **av ) { VNDX vi; char *cp; int i; if (nonplanar(ac, av)) { /* break into triangles */ while (ac > 2) { if (!puttri(av[0], av[1], av[2])) return(0); ac--; /* remove vertex & rotate */ cp = av[0]; for (i = 0; i < ac-1; i++) av[i] = av[i+2]; av[i] = cp; } return(1); } if ((cp = getmtl()) == NULL) return(-1); printf("\n%s polygon %s.%d\n", cp, getonm(), faceno); printf("0\n0\n%d\n", 3*ac); for (i = 0; i < ac; i++) { if (!cvtndx(vi, av[i])) return(0); pvect(vlist[vi[0]]); } return(1); }
/* determine dominant axis for triangle */ static int dominant_axis(char *v1, char *v2, char *v3) { VNDX v1i, v2i, v3i; FVECT e1, e2, vn; int i, imax; if (!cvtndx(v1i, v1) || !cvtndx(v2i, v2) || !cvtndx(v3i, v3)) return(-1); VSUB(e1, vlist[v2i[0]], vlist[v1i[0]]); VSUB(e2, vlist[v3i[0]], vlist[v2i[0]]); VCROSS(vn, e1, e2); for (i = imax = 2; i--; ) if (vn[i]*vn[i] > vn[imax]*vn[imax]) imax = i; return(vn[imax]*vn[imax] > FTINY*FTINY ? imax : -1); }
static int putface( /* put out an N-sided polygon */ int ac, char **av ) { Vert2_list *poly = polyAlloc(ac); int i, ax, ay; if (poly == NULL) return(0); poly->p = (void *)av; for (i = ac-3; i >= 0; i--) /* identify dominant axis */ if ((ax = dominant_axis(av[i], av[i+1], av[i+2])) >= 0) break; if (ax < 0) return(1); /* ignore degenerate face */ if (++ax >= 3) ax = 0; ay = ax; if (++ay >= 3) ay = 0; for (i = 0; i < ac; i++) { /* convert to 2-D polygon */ VNDX vi; if (!cvtndx(vi, av[i])) { error(WARNING, "bad vertex reference"); polyFree(poly); return(0); } poly->v[i].mX = vlist[vi[0]][ax]; poly->v[i].mY = vlist[vi[0]][ay]; } /* break into triangles & output */ if (!polyTriangulate(poly, &tri_out)) { sprintf(errmsg, "self-intersecting face with %d vertices", ac); error(WARNING, errmsg); } polyFree(poly); return(1); }
int puttri( /* put out a triangle */ char *v1, char *v2, char *v3 ) { char *mod; VNDX v1i, v2i, v3i; BARYCCM bvecs; RREAL bcoor[3][3]; int texOK = 0, patOK; int flatness; int i; if ((mod = getmtl()) == NULL) return(-1); if (!cvtndx(v1i, v1) || !cvtndx(v2i, v2) || !cvtndx(v3i, v3)) return(0); /* compute barycentric coordinates */ if (v1i[2]>=0 && v2i[2]>=0 && v3i[2]>=0) flatness = flat_tri(vlist[v1i[0]], vlist[v2i[0]], vlist[v3i[0]], vnlist[v1i[2]], vnlist[v2i[2]], vnlist[v3i[2]]); else flatness = ISFLAT; switch (flatness) { case DEGEN: /* zero area */ ndegen++; return(-1); case RVFLAT: /* reversed normals, but flat */ case ISFLAT: /* smoothing unnecessary */ texOK = 0; break; case RVBENT: /* reversed normals with smoothing */ case ISBENT: /* proper smoothing */ texOK = 1; break; } if (flatten) texOK = 0; #ifdef TEXMAPS patOK = mapname[0] && (v1i[1]>=0 && v2i[1]>=0 && v3i[1]>=0); #else patOK = 0; #endif if (texOK | patOK) if (comp_baryc(&bvecs, vlist[v1i[0]], vlist[v2i[0]], vlist[v3i[0]]) < 0) texOK = patOK = 0; /* put out texture (if any) */ if (texOK) { printf("\n%s texfunc %s\n", mod, TEXNAME); mod = TEXNAME; printf("4 dx dy dz %s\n", TCALNAME); printf("0\n"); for (i = 0; i < 3; i++) { bcoor[i][0] = vnlist[v1i[2]][i]; bcoor[i][1] = vnlist[v2i[2]][i]; bcoor[i][2] = vnlist[v3i[2]][i]; } put_baryc(&bvecs, bcoor, 3); } #ifdef TEXMAPS /* put out pattern (if any) */ if (patOK) { printf("\n%s colorpict %s\n", mod, PATNAME); mod = PATNAME; printf("7 noneg noneg noneg %s %s u v\n", mapname, TCALNAME); printf("0\n"); for (i = 0; i < 2; i++) { bcoor[i][0] = vtlist[v1i[1]][i]; bcoor[i][1] = vtlist[v2i[1]][i]; bcoor[i][2] = vtlist[v3i[1]][i]; } put_baryc(&bvecs, bcoor, 2); } #endif /* put out (reversed) triangle */ printf("\n%s polygon %s.%d\n", mod, getonm(), faceno); printf("0\n0\n9\n"); if (flatness == RVFLAT || flatness == RVBENT) { pvect(vlist[v3i[0]]); pvect(vlist[v2i[0]]); pvect(vlist[v1i[0]]); } else { pvect(vlist[v1i[0]]); pvect(vlist[v2i[0]]); pvect(vlist[v3i[0]]); } return(1); }