--- ray/src/cv/mgflib/parser.c 1994/06/22 15:33:47 1.2 +++ ray/src/cv/mgflib/parser.c 1994/06/24 16:28:18 1.6 @@ -59,8 +59,11 @@ static int e_any_toss(), /* discard unneeded entity * e_ies(), /* IES luminaire file */ e_include(), /* include file */ e_sph(), /* sphere */ + e_cmix(), /* color mixtures */ + e_cspec(), /* color spectra */ e_cyl(), /* cylinder */ e_cone(), /* cone */ + e_prism(), /* prism */ e_ring(), /* ring */ e_torus(); /* torus */ @@ -103,15 +106,31 @@ mg_init() /* initialize alternate entity handlers */ ineed |= 1<n[0]==0. && cv->n[1]==0. && cv->n[2]==0.) + if (is0vect(cv->n)) return(MG_EILL); if (!isflt(av[2]) || !isflt(av[3])) return(MG_ETYPE); minrad = atof(av[2]); + round0(minrad); maxrad = atof(av[3]); /* check orientation */ if (minrad > 0.) @@ -629,11 +657,12 @@ char **av; return(MG_EARGC); if ((cv = c_getvert(av[1])) == NULL) return(MG_EUNDEF); - if (cv->n[0]==0. && cv->n[1]==0. && cv->n[2]==0.) + if (is0vect(cv->n)) return(MG_EILL); if (!isflt(av[2]) || !isflt(av[3])) return(MG_ETYPE); minrad = atof(av[2]); + round0(minrad); maxrad = atof(av[3]); if (minrad < 0. || maxrad <= minrad) return(MG_EILL); @@ -659,7 +688,7 @@ char **av; sprintf(p3[j], FLTFMT, cv->p[j] + maxrad*u[j]*cos(theta) + maxrad*v[j]*sin(theta)); - if ((rv = handle_it(MG_E_VERTEX, 3, v3ent)) != MG_OK) + if ((rv = handle_it(MG_E_VERTEX, 2, v3ent)) != MG_OK) return(rv); if ((rv = handle_it(MG_E_POINT, 4, p3ent)) != MG_OK) return(rv); @@ -685,11 +714,11 @@ char **av; sprintf(p3[j], FLTFMT, cv->p[j] + maxrad*d); sprintf(p4[j], FLTFMT, cv->p[j] + minrad*d); } - if ((rv = handle_it(MG_E_VERTEX, 3, v3ent)) != MG_OK) + if ((rv = handle_it(MG_E_VERTEX, 2, v3ent)) != MG_OK) return(rv); if ((rv = handle_it(MG_E_POINT, 4, p3ent)) != MG_OK) return(rv); - if ((rv = handle_it(MG_E_VERTEX, 3, v4ent)) != MG_OK) + if ((rv = handle_it(MG_E_VERTEX, 2, v4ent)) != MG_OK) return(rv); if ((rv = handle_it(MG_E_POINT, 4, p4ent)) != MG_OK) return(rv); @@ -734,7 +763,9 @@ char **av; if (!isflt(av[2]) || !isflt(av[4])) return(MG_ETYPE); rad1 = atof(av[2]); + round0(rad1); rad2 = atof(av[4]); + round0(rad2); if (rad1 == 0.) { if (rad2 == 0.) return(MG_EILL); @@ -758,13 +789,20 @@ char **av; if ((d = normalize(w)) == 0.) return(MG_EILL); n1off = n2off = (rad2 - rad1)/d; - if (warpconends) /* hack for e_sph and e_torus */ - n2off = tan(atan(n2off)-(PI/4)/mg_nqcdivs); - n2off = sgn*n2off; + if (warpconends) { /* hack for e_sph and e_torus */ + d = atan(n2off) - (PI/4)/mg_nqcdivs; + if (d <= -PI/2+FTINY) + n2off = -FHUGE; + else + n2off = tan(d); + } make_axes(u, v, w); for (j = 0; j < 3; j++) { sprintf(p3[j], FLTFMT, cv2->p[j] + rad2*u[j]); - sprintf(n3[j], FLTFMT, u[j] + w[j]*n2off); + if (n2off <= -FHUGE) + sprintf(n3[j], FLTFMT, -w[j]); + else + sprintf(n3[j], FLTFMT, u[j] + w[j]*n2off); } if ((rv = handle_it(MG_E_VERTEX, 3, v3ent)) != MG_OK) return(rv); @@ -787,25 +825,34 @@ char **av; for (j = 0; j < 3; j++) { d = u[j]*cos(theta) + v[j]*sin(theta); sprintf(p3[j], FLTFMT, cv2->p[j] + rad2*d); - sprintf(n3[j], FLTFMT, d + w[j]*n2off); + if (n2off > -FHUGE) + sprintf(n3[j], FLTFMT, d + w[j]*n2off); } - if ((rv = handle_it(MG_E_VERTEX, 3, v3ent)) != MG_OK) + if ((rv = handle_it(MG_E_VERTEX, 2, v3ent)) != MG_OK) return(rv); if ((rv = handle_it(MG_E_POINT, 4, p3ent)) != MG_OK) return(rv); - if ((rv = handle_it(MG_E_NORMAL, 4, n3ent)) != MG_OK) + if (n2off > -FHUGE && + (rv = handle_it(MG_E_NORMAL, 4, n3ent)) != MG_OK) return(rv); if ((rv = handle_it(MG_E_FACE, 4, fent)) != MG_OK) return(rv); } } else { /* quads */ v1ent[3] = "_cv4"; - if (warpconends) /* hack for e_sph and e_torus */ - n1off = tan(atan(n1off)+(PI/4)/mg_nqcdivs); - n1off = sgn*n1off; + if (warpconends) { /* hack for e_sph and e_torus */ + d = atan(n1off) + (PI/4)/mg_nqcdivs; + if (d >= PI/2-FTINY) + n1off = FHUGE; + else + n1off = tan(atan(n1off)+(PI/4)/mg_nqcdivs); + } for (j = 0; j < 3; j++) { sprintf(p4[j], FLTFMT, cv1->p[j] + rad1*u[j]); - sprintf(n4[j], FLTFMT, u[j] + w[j]*n1off); + if (n1off >= FHUGE) + sprintf(n4[j], FLTFMT, w[j]); + else + sprintf(n4[j], FLTFMT, u[j] + w[j]*n1off); } if ((rv = handle_it(MG_E_VERTEX, 3, v4ent)) != MG_OK) return(rv); @@ -822,25 +869,183 @@ char **av; for (j = 0; j < 3; j++) { d = u[j]*cos(theta) + v[j]*sin(theta); sprintf(p3[j], FLTFMT, cv2->p[j] + rad2*d); - sprintf(n3[j], FLTFMT, d + w[j]*n2off); + if (n2off > -FHUGE) + sprintf(n3[j], FLTFMT, d + w[j]*n2off); sprintf(p4[j], FLTFMT, cv1->p[j] + rad1*d); - sprintf(n4[j], FLTFMT, d + w[j]*n1off); + if (n1off < FHUGE) + sprintf(n4[j], FLTFMT, d + w[j]*n1off); } - if ((rv = handle_it(MG_E_VERTEX, 3, v3ent)) != MG_OK) + if ((rv = handle_it(MG_E_VERTEX, 2, v3ent)) != MG_OK) return(rv); if ((rv = handle_it(MG_E_POINT, 4, p3ent)) != MG_OK) return(rv); - if ((rv = handle_it(MG_E_NORMAL, 4, n3ent)) != MG_OK) + if (n2off > -FHUGE && + (rv = handle_it(MG_E_NORMAL, 4, n3ent)) != MG_OK) return(rv); - if ((rv = handle_it(MG_E_VERTEX, 3, v4ent)) != MG_OK) + if ((rv = handle_it(MG_E_VERTEX, 2, v4ent)) != MG_OK) return(rv); if ((rv = handle_it(MG_E_POINT, 4, p4ent)) != MG_OK) return(rv); - if ((rv = handle_it(MG_E_NORMAL, 4, n4ent)) != MG_OK) + if (n1off < FHUGE && + (rv = handle_it(MG_E_NORMAL, 4, n4ent)) != MG_OK) return(rv); if ((rv = handle_it(MG_E_FACE, 5, fent)) != MG_OK) return(rv); } + } + return(MG_OK); +} + + +static int +e_prism(ac, av) /* turn a prism into polygons */ +int ac; +char **av; +{ + static char p[3][24]; + static char *vent[4] = {mg_ename[MG_E_VERTEX],NULL,"="}; + static char *pent[5] = {mg_ename[MG_E_POINT],p[0],p[1],p[2]}; + char *newav[MG_MAXARGC], nvn[MG_MAXARGC-1][8]; + double length; + FVECT v1, v2, v3, norm; + register C_VERTEX *cv; + C_VERTEX *cv0; + int rv; + register int i, j; + + if (ac < 5) + return(MG_EARGC); + if (!isflt(av[ac-1])) + return(MG_ETYPE); + length = atof(av[ac-1]); + if (length <= FTINY && length >= -FTINY) + return(MG_EILL); + /* do bottom face */ + newav[0] = mg_ename[MG_E_FACE]; + for (i = 1; i < ac-1; i++) + newav[i] = av[i]; + newav[i] = NULL; + if ((rv = handle_it(MG_E_FACE, i, newav)) != MG_OK) + return(rv); + /* compute face normal */ + if ((cv0 = c_getvert(av[2])) == NULL) + return(MG_EUNDEF); + norm[0] = norm[1] = norm[2] = 0.; + v1[0] = v1[1] = v1[2] = 0.; + for (i = 2; i < ac-1; i++) { + if ((cv = c_getvert(av[i])) == NULL) + return(MG_EUNDEF); + v2[0] = cv->p[0] - cv0->p[0]; + v2[1] = cv->p[1] - cv0->p[1]; + v2[2] = cv->p[2] - cv0->p[2]; + fcross(v3, v1, v2); + norm[0] += v3[0]; + norm[1] += v3[1]; + norm[2] += v3[2]; + VCOPY(v1, v2); + } + if (normalize(norm) == 0.) + return(MG_EILL); + /* create moved vertices */ + for (i = 1; i < ac-1; i++) { + sprintf(nvn[i-1], "_pv%d", i); + vent[1] = nvn[i-1]; + if ((rv = handle_it(MG_E_VERTEX, 3, vent)) != MG_OK) + return(rv); + cv = c_getvert(av[i]); /* checked above */ + for (j = 0; j < 3; j++) + sprintf(p[j], FLTFMT, cv->p[j] - length*norm[j]); + if ((rv = handle_it(MG_E_POINT, 4, pent)) != MG_OK) + return(rv); + newav[ac-1-i] = nvn[i-1]; /* reverse */ + } + /* do top face */ + if ((rv = handle_it(MG_E_FACE, ac-1, newav)) != MG_OK) + return(rv); + /* do the side faces */ + newav[5] = NULL; + newav[3] = av[ac-2]; + newav[4] = nvn[ac-3]; + for (i = 1; i < ac-1; i++) { + newav[1] = nvn[i-1]; + newav[2] = av[i]; + if ((rv = handle_it(MG_E_FACE, 5, newav)) != MG_OK) + return(rv); + newav[3] = newav[2]; + newav[4] = newav[1]; + } + return(MG_OK); +} + + +static int +e_cspec(ac, av) /* handle spectral color */ +int ac; +char **av; +{ + static char xbuf[24], ybuf[24]; + static char *ccom[4] = {mg_ename[MG_E_CXY], xbuf, ybuf}; + int rv; + + c_ccvt(c_ccolor, C_CSXY); + /* if it's really their handler, use it */ + if (mg_ehand[MG_E_CXY] != c_hcolor) { + sprintf(xbuf, "%.4f", c_ccolor->cx); + sprintf(ybuf, "%.4f", c_ccolor->cy); + if ((rv = handle_it(MG_E_CXY, 3, ccom)) != MG_OK) + return(rv); + } + return(MG_OK); +} + + +static int +e_cmix(ac, av) /* handle mixing of colors */ +int ac; +char **av; +{ + char wl[2][6], vbuf[C_CNSS][24]; + char *newav[C_CNSS+4]; + int rv; + register int i; + /* + * Contorted logic works as follows: + * 1. the colors are already mixed in c_hcolor() support function + * 2. if we would handle a spectral result, make sure it's not + * 3. if c_hcolor() would handle a spectral result, don't bother + * 4. otherwise, make cspec entity and pass it to their handler + * 5. if we have only xy results, handle it as c_spec() would + */ + if (mg_ehand[MG_E_CSPEC] == e_cspec) + c_ccvt(c_ccolor, C_CSXY); + else if (c_ccolor->flags & C_CDSPEC) { + if (mg_ehand[MG_E_CSPEC] != c_hcolor) { + sprintf(wl[0], "%d", C_CMINWL); + sprintf(wl[1], "%d", C_CMAXWL); + newav[0] = mg_ename[MG_E_CSPEC]; + newav[1] = wl[0]; + newav[2] = wl[1]; + for (i = 0; i < C_CNSS; i++) { + sprintf(vbuf[i], "%.6f", + (double)c_ccolor->ssamp[i] / + c_ccolor->ssum); + newav[i+3] = vbuf[i]; + } + newav[C_CNSS+3] = NULL; + if ((rv = handle_it(MG_E_CSPEC, C_CNSS+3, newav)) != MG_OK) + return(rv); + } + return(MG_OK); + } + if (mg_ehand[MG_E_CXY] != c_hcolor) { + sprintf(vbuf[0], "%.4f", c_ccolor->cx); + sprintf(vbuf[1], "%.4f", c_ccolor->cy); + newav[0] = mg_ename[MG_E_CXY]; + newav[1] = vbuf[0]; + newav[2] = vbuf[1]; + newav[3] = NULL; + if ((rv = handle_it(MG_E_CXY, 3, newav)) != MG_OK) + return(rv); } return(MG_OK); }