This is anytoucd.c in view mode; [Download] [Up]
/* File: anytoucd.c: Author: Charlie Gunn originally read a OOGL object on stdin, and write ucd format on stdout. */ #include "vec4.h" #include "geom.h" #include "3d.h" #include "polylistP.h" #include "plutil.h" #include <stdio.h> #include "time.h" extern Poly *getstack(); /* in stack.c */ #define MAXV 64 /* #define DEBUG */ #define CAVE 1 #define VEX 0 static int debug = 0; #define INSIDE(line, point) \ ((line.a*(point)->x + line.b*(point)->y + line.c) <= 0) #define INSIDE2(line, point) \ (line.a*(point)->x + line.b*(point)->y + line.c) struct polygon { int nv; unsigned int new:1; Vertex *vlist[MAXV]; HPoint3 vlistxy[MAXV]; short inout[MAXV]; Transform to_xy; } currpoly; struct line { float a,b,c,angle; }; typedef struct polygon polygon; typedef struct line line; void myconvert(CP, cp) Poly *CP; polygon *cp; { int i; cp->nv = CP->n_vertices; for (i=0; i<cp->nv; ++i) cp->vlist[i] = CP->v[i]; cp->new = 1; } polygon * chopup (pp, PP) polygon *pp; Poly *PP; { int oc, nc, n, i ; int cutcount = 0, convex, orient; line edges[MAXV]; Transform m; double tt, dangle, sum; polygon *newpoly; if (debug){ fprintf(stderr,"Entering chopup with %d vertices \n",pp->nv); for (i=0; i<pp->nv; ++i) fprintf(stderr,"%f %f %f \n",pp->vlist[i]->pt.x, pp->vlist[i]->pt.y, pp->vlist[i]->pt.z); } if (pp->nv <= 4 && pp->nv > 1) { PP->n_vertices = pp->nv; for (i=0; i<pp->nv; ++i) PP->v[i] = pp->vlist[i]; if (push(PP) == 0) OOGLError(1,"anytoucd: unable to push polygon\n"); return(NULL); } else if (pp->nv == 1) { return(NULL); } else { /* something to chop */ newpoly = OOGLNew(polygon); n = pp->nv; if (pp->new) { /* need to work in the x,y plane, so compute approp. tforms */ for (i=0; i<n; ++i) /* may need to hunt for independent vectors */ if (make_tform(&pp->vlist[i]->pt, &pp->vlist[(i+1)%n]->pt, &pp->vlist[(i+2)%n]->pt, pp->to_xy) >= 0) break;; TmInvert(pp->to_xy, pp->to_xy); for (i=0; i<pp->nv; ++i) HPt3Transform(pp->to_xy, &pp->vlist[i]->pt, &pp->vlistxy[i]); pp->new = 0; } { double dx, dy; for (i=0; i<pp->nv; ++i) { dx = pp->vlistxy[(i+1)%n].x - pp->vlistxy[i].x; dy = pp->vlistxy[(i+1)%n].y - pp->vlistxy[i].y; edges[i].a = dy; edges[i].b = -dx; edges[i].c = -(edges[i].a*pp->vlistxy[i].x+edges[i].b*pp->vlistxy[i].y); edges[i].angle = atan2(dy,dx); if (debug) fprintf(stderr,"edge %d: angle %f\n",i,edges[i].angle); } } /* armed with this info, identify concave and convex bndy pts*/ for (sum = 0.0, i=0; i<pp->nv; ++i) { dangle = edges[i].angle - edges[(i-1+n)%n].angle ; /* clip to (-PI, +PI) */ while (dangle < -PI) dangle += 2*PI; while (dangle > PI) dangle -= 2*PI; sum += dangle; if (dangle > 0) pp->inout[i] = VEX; else pp->inout[i] = CAVE; } if (debug) fprintf(stderr,"Total angle change is %f\n",sum); if (sum > 0 ) orient = 1; else orient = -1; for (convex = 1, i=0; i<pp->nv; ++i) { if (orient == -1) { pp->inout[i] = 1 - pp->inout[i]; edges[i].a *= -1; edges[i].b *= -1; edges[i].c *= -1; } if (pp->inout[i] == CAVE) convex = 0; } if (debug) if (convex) fprintf(stderr,"Polygon is convex\n"); /* next look for triangles to chop off */ { line cutcorner; double a,b,c,angle, dx, dy; int cutoff, j, jj,ni, pi, oc, nc; double d0, d1, d2; for (nc = 0, oc=0; oc<pp->nv-1; ++oc, ++nc) { /* copy out current vertex */ newpoly->vlist[nc] = pp->vlist[oc]; HPt3Copy(&pp->vlistxy[oc], &newpoly->vlistxy[nc]); if (pp->inout[(oc+1)%n] == VEX) { cutoff = 1; /* default is to cut if off */ if (!convex) { pi = oc; ni = (oc+2)%n; dx = pp->vlistxy[(oc+2)%n].x - pp->vlistxy[oc].x; dy = pp->vlistxy[(oc+2)%n].y - pp->vlistxy[oc].y; /* orient this line to run from v2 to v0, to agree with edges */ cutcorner.a = -dy*orient; cutcorner.b = dx*orient; cutcorner.c = -(cutcorner.a*pp->vlistxy[(oc+2)%n].x+cutcorner.b*pp->vlistxy[(oc+2)%n].y); cutcorner.angle = -atan2(dy,dx); /* check for concave pts inside this triangle */ /* don't check the vertices of this triangle */ for ( j=0, jj=oc+3; j<pp->nv-3 && cutoff; ++j,++jj) { if (jj == pp->nv) jj = 0; if ( pp->inout[jj] == CAVE ) { if (INSIDE(cutcorner,&pp->vlistxy[jj]) && INSIDE(edges[oc], &pp->vlistxy[jj]) && INSIDE(edges[(oc+1)%n], &pp->vlistxy[jj])) { if (debug) fprintf(stderr,"vertex %d is inside cutoff corner %d %d %d\n",jj, oc, oc+1, oc+2); cutoff = 0; } } } } if (cutoff) /* can cut this corner off */ { int iv0, iv1, iv2, iv3; if (convex & (oc < pp->nv-2 ) ) /* can cut off 4 vertices */ { iv0 = oc; iv1 = (oc+1)%n; iv2 = (oc+2)%n; iv3 = (oc+3)%n; PP->n_vertices = 4; PP->v[0] = pp->vlist[iv0]; PP->v[1] = pp->vlist[iv1]; PP->v[2] = pp->vlist[iv2]; PP->v[3] = pp->vlist[iv3]; if (push(PP) == 0) OOGLError(1,"anytoucd: unable to push polygon\n"); oc++; oc++; } else { iv0 = oc; iv1 = (oc+1)%n; iv2 = (oc+2)%n; PP->n_vertices = 3; PP->v[0] = pp->vlist[iv0]; PP->v[1] = pp->vlist[iv1]; PP->v[2] = pp->vlist[iv2]; if (push(PP) == 0) OOGLError(1,"anytoucd: unable to push polygon\n"); oc++; } } } } while (oc < pp->nv) { newpoly->vlist[nc] = pp->vlist[oc]; HPt3Copy(&pp->vlistxy[oc], &newpoly->vlistxy[nc]); oc++; nc++; } newpoly->new = 0; newpoly->nv = nc; /* if nothing got chopped, or if what's left * has only 1 or 2 vertices */ if (newpoly->nv == pp->nv || newpoly->nv <= 2) { /* fprintf(stderr,"chopup:Unable to cut a corner\n"); */ OOGLFree(newpoly); return(NULL); } else return(newpoly); } } } Poly *CP, thisPoly; main(argc, argv) int argc; char **argv; { register polygon *ncp, *cp, thispolygon; int i, nv, pcountold, pcountnew; char type[64]; HPoint3 vd; Geom *thisgeom; PolyList *thispl, *newpl; Vertex *vlist[4]; Transform id; TmIdentity(id); thisgeom = GeomFLoad(stdin,NULL); thispl = (PolyList*)AnyToPL(thisgeom, id); newpl = (PolyList*)GeomCopy((Geom*)thispl); if (initstack() == 0) OOGLError(1,"anytoucd: unable to init stack\n"); cp = OOGLNew(polygon); CP = &thisPoly; /* at most 4 vertices in each face */ for (pcountold = 0; pcountold < thispl->n_polys; ++pcountold) { myconvert(&thispl->p[pcountold], cp); bcopy(&thispl->p[pcountold], CP, sizeof(Poly)); CP->v = vlist; OOGLNew(polygon); while ( (ncp = chopup(cp, CP)) != NULL ) { if (debug) fprintf(stderr,"Chop up: calling again\n"); OOGLFree(cp); cp = ncp; } } /* now get the list of polygons from the stack */ thispl->n_polys = getsize(); thispl->p = getstack(); /* now print out the stuff in ucd format */ /* GeomFSave(thispl, stdout, NULL); */ { FILE *fp = stdout; int num_nodes, num_node_data_comp = 0, node_data_comp[2], num_cells, num_cell_data_comp = 0, total_node_comp = 0, total_cell_comp = 0, cell_data_comp[2], i,j,n; Poly *p; Vertex *v, **vp; num_nodes = thispl->n_verts; num_cells = thispl->n_polys; if (thispl->flags & PL_HASVCOL) { node_data_comp[0] = 4; /* ColorA's : 4 component */ num_node_data_comp += 1; total_node_comp += 4; } if (thispl->flags & PL_HASVN) { node_data_comp[num_node_data_comp] = 3; num_node_data_comp += 1; total_node_comp += 3; } #ifdef FOURD if (thispl->geomflags & VERT_4D) { node_data_comp[num_node_data_comp] = 1; /* ColorA's : 4 component */ num_node_data_comp += 1; total_node_comp += 1; } #endif if (thispl->flags & PL_HASPCOL) { cell_data_comp[0] = 4; /* ColorA's : 4 component */ num_cell_data_comp += 1; total_cell_comp += 4; } if (thispl->flags & PL_HASPN) { cell_data_comp[num_cell_data_comp] = 3; num_cell_data_comp += 1; total_cell_comp += 3; } { char *timestring; long mytime; time_t myt; myt = time(&mytime); timestring = ctime(&myt); fprintf(fp,"# Created by anytoucd on %s \n",timestring); } fprintf(fp,"%d %d %d %d 0\n",num_nodes, num_cells, total_node_comp, total_cell_comp); /* write out vertices */ /* what to do about 4D vertices? */ for (v = thispl->vl, i=0; i<thispl->n_verts; ++i, ++v) #ifdef FOURD fprintf(fp,"%d %g %g %g\n",i+1,v->pt.x, v->pt.y, v->pt.z); #else { float w = v->pt.w; if (w) w = 1.0/w; fprintf(fp,"%d %g %g %g\n",i+1,w*v->pt.x, w*v->pt.y, w*v->pt.z); } #endif /* write out faces */ for (i=0, p = thispl->p; i<thispl->n_polys; ++i, ++p) { fprintf(fp,"%d 1 ",i+1); n = p->n_vertices; if (n==2) fprintf(fp,"line "); /* is this right? */ else if (n==3) fprintf(fp,"tri "); else if (n==4) fprintf(fp, "quad "); /* else signal error */ else return; for(vp = p->v; --n >= 0; vp++) fprintf(fp, "%d ", (*vp) - thispl->vl + 1); fprintf(fp,"\n"); } if (num_node_data_comp) { fprintf(fp,"%d ", num_node_data_comp); for (i=0; i<num_node_data_comp; ++i) fprintf(fp,"%d ", node_data_comp[i]); fprintf(fp,"\n"); } if (thispl->flags & PL_HASVCOL) fprintf(fp,"rgba, NULL\n"); if (thispl->flags & PL_HASVN) fprintf(fp,"normal, NULL\n"); if (thispl->geomflags & VERT_4D) fprintf(fp,"w, NULL\n"); /* print vertex colors */ if (thispl->flags & PL_HASVCOL) { for (v = thispl->vl, i=0; i<thispl->n_verts; ++i, ++v) fprintf(fp,"%d %g %g %g %g\n", i+1, v->vcol.r, v->vcol.g, v->vcol.b, v->vcol.a); } /* print vertex normals */ if (thispl->flags & PL_HASVN) { for (v = thispl->vl, i=0; i<thispl->n_verts; ++i, ++v) fprintf(fp,"%d %g %g %g\n", i+1, v->vn.x, v->vn.y, v->vn.z); } #ifdef FOURD /* print fourth coordinate if present */ if (thispl->geomflags & VERT_4D) { for (v = thispl->vl, i=0; i<thispl->n_verts; ++i, ++v) fprintf(fp,"%d %g\n", i+1, v->pt.w); } #endif /* now process cell data */ if (num_cell_data_comp) { fprintf(fp,"%d ", num_cell_data_comp); for (i=0; i<num_cell_data_comp; ++i) fprintf(fp,"%d ", cell_data_comp[i]); fprintf(fp,"\n"); } /* print labels */ if (thispl->flags & PL_HASPCOL) fprintf(fp,"rgba, NULL\n"); if (thispl->flags & PL_HASPN) fprintf(fp,"normal, NULL\n"); /* print face colors */ if (thispl->flags & PL_HASPCOL) { for (p = thispl->p, i=0; i<thispl->n_polys; ++i, ++p) fprintf(fp,"%d %g %g %g %g\n", i+1, p->pcol.r, p->pcol.g, p->pcol.b, p->pcol.a); } /* print face normals */ if (thispl->flags & PL_HASPN) { for (p = thispl->p, i=0; i<thispl->n_polys; ++i, ++p) fprintf(fp,"%d %g %g %g\n", i+1, p->pn.x, p->pn.y, p->pn.z); } } }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.