ftp.nice.ch/pub/next/graphics/3d/geomview.1.4.1.s.tar.gz#/Geomview/src/bin/geomutil/ucd/anytoucd.c

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.