X
X/* copy texture vertices */
X
Xif(verbflg>4) {
X    fprintf(stderr,"app_obj: copy %d texture vertices\n",
X        srcobj->size.notverts);
X    }
X
Xfor(tvcount=1;tvcount<srcobj->size.notverts;tvcount++) {
X    if(verbflg>9) {
X        fprintf(stderr,"app_obj: otvindx=%d\n",otvindx);
X        }
X    dstobj->texver[otvindx]->u=srcobj->texver[tvcount]->u;
X    dstobj->texver[otvindx]->v=srcobj->texver[tvcount]->v;
X    dstobj->texver[otvindx]->w=srcobj->texver[tvcount]->w;
X    if((++otvindx)>=dstobj->alloc.notverts) {
X        fprintf(stderr,
X            "app_obj: too many texture vertices %d in object '%s'",
X            otvindx,dstobj->size.objname);
X        fprintf(stderr," -- reallocating\n");
X        /* double allocation for texture vertices */
X        apalloc->notverts=apalloc->notverts*2;
X        dstobj=realc_obj(dstobj,apalloc);
X        }
X    }
X
X/* copy lines */
X
Xif(verbflg>4) {
X    fprintf(stderr,"app_obj: copying %d lines\n",srcobj->size.nolines);
X    }
X
Xfor(lcount=0;lcount<srcobj->size.nolines;lcount++) {
X    if(verbflg>10) {
X        fprintf(stderr,"app_obj: line %d: %d vertices\n",lcount,
X            srcobj->line[lcount]->vertc);
X        }
X    for(lvcnt=0;lvcnt<srcobj->line[lcount]->vertc;lvcnt++) {
X        vindx=srcobj->line[lcount]->vertno[lvcnt];
X        dstobj->line[olindx]->vertno[lvcnt]=vindx+ovoffset;
X        }
X    dstobj->line[olindx]->vertc=srcobj->line[lcount]->vertc;
X    if(lvcnt > dstobj->size.nolverts) {
X        dstobj->size.nolverts = lvcnt + 1;
X        }
X    /* copy material pointers */
X    mtlindx=srcobj->line[lcount]->mtl;
X    if(verbflg>10) {
X        fprintf(stderr,
X            "app_obj: old mtl = %d, mtlptr[%d] = %d\n",
X            mtlindx,mtlindx,mtlptr[mtlindx]);
X        }
X    dstobj->line[olindx]->mtl=mtlptr[mtlindx];
X    /* copy and re-index group pointers */
X    if(appgrp > -1) {
X        gindx=appgrp;
X        glindx=dstobj->group[appgrp]->nolines;
X        }
X    else {
X        gindx=srcobj->line[lcount]->group;
X        if(verbflg>10) {
X            fprintf(stderr,
X                "app_obj: old group = %d, grpptr[%d] = %d\n",
X                gindx,gindx,grpptr[mtlindx]);
X            }
X        gindx=grpptr[gindx];
X        glindx=dstobj->group[gindx]->nolines;
X        }
X    if(verbflg>10) {
X        fprintf(stderr,"app_obj: group %d, glindx = %d\n",gindx,glindx);
X        }
X    dstobj->line[olindx]->group=gindx;
X    dstobj->group[gindx]->lineno[glindx]=olindx;
X    if((++glindx)>=dstobj->alloc.noglines) {
X        fprintf(stderr,
X            "app_obj: too many lines %d, group '%s', object '%s'",
X            olindx,dstobj->group[gindx]->grpnam,
X            dstobj->size.objname);
X        fprintf(stderr," -- reallocating\n");
X        /* double allocation for group lines */
X        apalloc->noglines=apalloc->noglines*2;
X        dstobj=realc_obj(dstobj,apalloc);
X        }
X    dstobj->group[gindx]->nolines=glindx;
X    if((++olindx)>=dstobj->alloc.nolines) {
X        fprintf(stderr,
X            "app_obj: too many lines %d in object '%s'",
X            olindx,dstobj->size.objname);
X        fprintf(stderr," -- reallocating\n");
X        /* double allocation for lines */
X        apalloc->nolines=apalloc->nolines*2;
X        dstobj=realc_obj(dstobj,apalloc);
X        }
X    }
X
X
X
X
X/* copy points */
X
Xif(verbflg>4) {
X    fprintf(stderr,"app_obj: copying %d points\n",srcobj->size.nopoints);
X    }
X
Xfor(pcount=0;pcount<srcobj->size.nopoints;pcount++) {
X    for(pvcnt=0;pvcnt<srcobj->point[pcount]->vertc;pvcnt++) {
X        vindx=srcobj->point[pcount]->vertno[pvcnt];
X        dstobj->point[opindx]->vertno[pvcnt]=vindx+ovoffset;
X        }
X    dstobj->point[opindx]->vertc=srcobj->point[pcount]->vertc;
X    if(pvcnt > dstobj->size.nopverts) {
X        dstobj->size.nopverts = pvcnt + 1;
X        }
X    /* copy group pointers */
X    if(appgrp > -1) {
X        gindx=appgrp;
X        gpindx=dstobj->group[appgrp]->nopoints;
X        }
X    else {
X        gindx=srcobj->point[pcount]->group;
X        gindx=grpptr[gindx];
X        gpindx=dstobj->group[gindx]->nopoints;
X        }
X    dstobj->point[opindx]->group=gindx;
X    dstobj->group[gindx]->pointno[gpindx]=opindx;
X    if((++gpindx)>=dstobj->alloc.nogpoints) {
X        fprintf(stderr,
X            "app_obj: too many points %d, group '%s', object '%s'",
X            opindx,dstobj->group[gindx]->grpnam,
X            dstobj->size.objname);
X        fprintf(stderr," -- reallocating\n");
X        /* double allocation for group pointses */
X        apalloc->nogpoints=apalloc->nogpoints*2;
X        dstobj=realc_obj(dstobj,apalloc);
X        }
X    dstobj->group[gindx]->nopoints=gpindx;
X    if((++opindx)>=dstobj->alloc.nopoints) {
X        fprintf(stderr,
X            "app_obj: too many pointses %d in object '%s'",
X            opindx,dstobj->size.objname);
X        fprintf(stderr," -- reallocating\n");
X        /* double allocation for pointses */
X        apalloc->nopoints=apalloc->nopoints*2;
X        dstobj=realc_obj(dstobj,apalloc);
X        }
X    }
X
X
X/* copy faces */
X
Xif(verbflg>9) {
X    fprintf(stderr,"app_obj: copy faces\n");
X    }
X
Xfor(fcount=0;fcount<srcobj->size.nofaces;fcount++) {
X    dstobj->face[ofindx]->smooth=srcobj->face[fcount]->smooth;
X    dstobj->face[ofindx]->bevel=srcobj->face[fcount]->bevel;
X    dstobj->face[ofindx]->mapflg=srcobj->face[fcount]->mapflg;
X    mapindx=srcobj->face[fcount]->map;
X    for(fvcnt=0;fvcnt<srcobj->face[fcount]->vertc;fvcnt++) {
X        /* copy geometrical vertex pointers */
X        vindx=srcobj->face[fcount]->vertno[fvcnt];
X        dstobj->face[ofindx]->vertno[fvcnt]=vindx+ovoffset;
X        if(mapindx>(-1)) {
X            /* copy texture vertex pointers */
X            tvindx=srcobj->face[fcount]->tvertno[fvcnt];
X            dstobj->face[ofindx]->tvertno[fvcnt]=tvindx+otvofset;
X            }
X        }
X    dstobj->face[ofindx]->vertc=srcobj->face[fcount]->vertc;
X    if(fvcnt > dstobj->size.nofverts) {
X        dstobj->size.nofverts = fvcnt + 1;
X        }
X    /* copy material pointers */
X    mtlindx=srcobj->face[fcount]->mtl;
X    dstobj->face[ofindx]->mtl=mtlptr[mtlindx];
X    /* copy texture map pointers */
X    if(mapindx>(-1)) {
X        dstobj->face[ofindx]->map=mapptr[mapindx];
X        }
X    else {
X        dstobj->face[ofindx]->map=(-1);
X        }
X    /* copy group pointers */
X    if(appgrp > -1) {
X        gindx=appgrp;
X        gfindx=dstobj->group[appgrp]->nofaces;
X        }
X    else {
X        gindx=srcobj->face[fcount]->group;
X        gindx=grpptr[gindx];
X        gfindx=dstobj->group[gindx]->nofaces;
X        }
X    dstobj->face[ofindx]->group=gindx;
X    dstobj->group[gindx]->faceno[gfindx]=ofindx;
X    if((++gfindx)>=dstobj->alloc.nogfaces) {
X        fprintf(stderr,
X            "app_obj: too many faces %d, group '%s', object '%s'",
X            gfindx,dstobj->group[grpptr[gindx]]->grpnam,
X            dstobj->size.objname);
X        fprintf(stderr," -- reallocating\n");
X        /* double allocation for group faces */
X        apalloc->nogfaces=apalloc->nogfaces*2;
X        dstobj=realc_obj(dstobj,apalloc);
X        }
X    dstobj->group[gindx]->nofaces=gfindx;
X    if((++ofindx)>=dstobj->alloc.nofaces) {
X        fprintf(stderr,
X            "app_obj: too many faces %d, object '%s'",
X            ofindx, dstobj->size.objname);
X        fprintf(stderr," -- reallocating\n");
X        /* double allocation for faces */
X        apalloc->nofaces=apalloc->nofaces*2;
X        dstobj=realc_obj(dstobj,apalloc);
X        }
X    }
X
X/* copy bicubic patches */
Xfor(bicuct = 0; bicuct < srcobj->size.noptchs; bicuct++) {
X
X    mapindx=srcobj->bicub[bicuct]->map;
X     /* copy vertex pointers */
X    for(row = 0; row < 4; row++) {
X        for(col = 0; col < 4; col++) {
X            vindx = srcobj->bicub[bicuct]->vertno[row][col];
X            dstobj->bicub[obpndx]->vertno[row][col] = vindx + ovoffset;
X            if(mapindx>(-1)) {
X                tvindx = srcobj->bicub[bicuct]->tvertno[row][col];
X                dstobj->bicub[obpndx]->tvertno[row][col] = tvindx + otvofset;
X                }
X            }
X        }
X        /* copy element attributes */
X    dstobj->bicub[obpndx]->type=srcobj->bicub[bicuct]->type;
X    dstobj->bicub[obpndx]->u_res=srcobj->bicub[bicuct]->u_res;
X    dstobj->bicub[obpndx]->v_res=srcobj->bicub[bicuct]->v_res;
X    dstobj->bicub[obpndx]->smooth=srcobj->bicub[bicuct]->smooth;
X        /* copy material pointers */
X    mtlindx=srcobj->bicub[bicuct]->mtl;
X    dstobj->bicub[obpndx]->mtl=mtlptr[mtlindx];
X        /* copy texture map pointers */
X    if(mapindx>(-1)) {
X        dstobj->bicub[obpndx]->map=mapptr[mapindx];
X        }
X    else {
X        dstobj->bicub[obpndx]->map=(-1);
X        }
X    /* copy group pointers */
X    if(appgrp > -1) {
X        gindx=appgrp;
X        gbindx=dstobj->group[appgrp]->noptchs;
X        }
X    else {
X        gindx=srcobj->bicub[bicuct]->group;
X        gindx=grpptr[gindx];
X        gbindx=dstobj->group[gindx]->noptchs;
X        }
X    dstobj->bicub[obpndx]->group=gindx;
X    dstobj->group[gindx]->ptchno[gbindx]=obpndx;
X    if((++gbindx) >= dstobj->alloc.nogptchs) {
X        fprintf(stderr,
X            "app_obj: too many patches %d, group '%s', object '%s'",
X            gbindx,dstobj->group[grpptr[gindx]]->grpnam,
X            dstobj->size.objname);
X        fprintf(stderr," -- reallocating\n");
X        /* double allocation for group patches */
X        apalloc->nogptchs = apalloc->nogptchs * 2;
X        dstobj=realc_obj(dstobj,apalloc);
X        }
X    dstobj->group[gindx]->noptchs=gbindx;
X    if(++obpndx >= dstobj->alloc.noptchs) {
X        fprintf(stderr,
X            "app_obj: too many bicubic patches %d",
X            obpndx);
X        fprintf(stderr," in object '%s' - reallocating\n",
X            dstobj->size.objname);
X        /* double allocation for bicubic patches */
X        apalloc->noptchs = apalloc->noptchs * 2;
X        dstobj=realc_obj(dstobj,apalloc);
X        }
X    }
X
X/* if flag is set, copy meta elements */
Xif(metaflg=='m') {
X    /* copy circles */
X    for(circnt=0;circnt<srcobj->size.nocircs;circnt++) {
X        vindx = srcobj->circl[circnt]->vertno;
X        dstobj->circl[ocindx]->vertno = vindx + ovoffset;
X        dstobj->circl[ocindx]->rad=srcobj->circl[circnt]->rad;
X        dstobj->circl[ocindx]->res=srcobj->circl[circnt]->res;
X        if(++ocindx>=dstobj->alloc.nocircs) {
X            fprintf(stderr,
X                "app_obj: too many circles %d in object '%s'",
X                ocindx,dstobj->size.objname);
X        fprintf(stderr," -- reallocating\n");
X            /* double allocation for circles */
X            apalloc->nocircs=apalloc->nocircs*2;
X            dstobj=realc_obj(dstobj,apalloc);
X            }
X        }
X    /* copy spheres */
X    for(sphcnt=0;sphcnt<srcobj->size.nosphrs;sphcnt++) {
X        vindx = srcobj->spher[sphcnt]->vertno;
X        dstobj->spher[ospndx]->vertno = vindx + ovoffset;
X        dstobj->spher[ospndx]->rad=srcobj->spher[sphcnt]->rad;
X        dstobj->spher[ospndx]->res=srcobj->spher[sphcnt]->res;
X        dstobj->spher[ospndx]->smooth=srcobj->spher[sphcnt]->smooth;
X        /* copy material pointers */
X        mtlindx=srcobj->spher[sphcnt]->mtl;
X        dstobj->spher[ospndx]->mtl=mtlptr[mtlindx];
X        /* copy texture map pointers if defined */
X        mapindx=srcobj->spher[sphcnt]->map;
X        if(mapindx>(-1)) {
X            dstobj->spher[ospndx]->map=mapptr[mapindx];
X            }
X        else {
X            dstobj->spher[ospndx]->map=(-1);
X            }
X        if(++ospndx>=dstobj->alloc.nosphrs) {
X            fprintf(stderr,
X                "app_obj: too many spheres %d in object '%s'",
X                ospndx,dstobj->size.objname);
X        fprintf(stderr," -- reallocating\n");
X            /* double allocation for spheres */
X            apalloc->nosphrs=apalloc->nosphrs*2;
X            dstobj=realc_obj(dstobj,apalloc);
X            }
X        }
X    dstobj->size.nocircs=ocindx;
X    dstobj->size.nosphrs=ospndx;
X    }
Xdstobj->size.noptchs=obpndx;
Xdstobj->size.noverts=ovindx;
Xdstobj->size.notverts=otvindx;
Xdstobj->size.nosgrps=dstobj->size.nosgrps + srcobj->size.nosgrps;
Xdstobj->size.nofaces=ofindx;
Xdstobj->size.nopoints=opindx;
Xdstobj->size.nolines=olindx;
Xdstobj->size.nocalls=ocalindx;
X
X/* free memory allocated in this function */
Xfree(apalloc);
Xapalloc = NULL;
X
Xif(verbflg>1) {
X    fprintf(stderr,
X        "app_obj: '%s', %d verts %d tverts %d lines %d faces %d patches\n",
X        dstobj->size.objname,ovindx,otvindx,olindx,ofindx,obpndx);
X    }
X
Xreturn(dstobj);
X}
X
X
X
X
X
X
X
X
X
X/* function: add_group
X
X   description: adds a group name to an object.  Returns the index of the
X                group.  If the group name already exists, the index of that
X                group is returned.
X
X   author: Stewart Dickson
X*/
X
X
Xint add_group(AG_dstobj,group_name)
Xstruct topology *AG_dstobj;
Xchar *group_name;
X{
Xextern int verbflg;
Xstruct topology *realc_obj();
Xstruct sizes *dstalloc;
Xint gcount;
Xdstalloc = NULL;
X
Xif(AG_dstobj == NULL) {
X    fprintf(stderr,"add_group: ERROR - NULL object pointer received\n");
X    exit(-1);
X    }
X
Xif(group_name == NULL) {
X    fprintf(stderr,"add_group: ERROR - NULL group name string received\n");
X    exit(-1);
X    }
X
Xif(verbflg > 1) {
X    fprintf(stderr,"entering add_group(%s,%s)\n",
X        AG_dstobj->size.objname,group_name);
X    }
X
Xfor(gcount = 0; gcount < AG_dstobj->size.nogroups; gcount++) {
X    /* determine if copied group is unique */
X    if(!strcmp(group_name, AG_dstobj->group[gcount]->grpnam)) {
X        break;
X        }
X    }
Xif(gcount >= AG_dstobj->size.nogroups) {
X        /* if it is unique */
X
X    if(verbflg>9) {
X        fprintf(stderr,
X            "add_group: adding group %d, '%s'\n", gcount, group_name);
X        }
X
X    /* check allocation */
X    if(gcount >= AG_dstobj->alloc.nogroups) {
X        /* allocate storage for object size parameter struct */
X        dstalloc = copy_alc(AG_dstobj,dstalloc);
X
X        fprintf(stderr,
X            "add_group: too many groups %d", gcount);
X        fprintf(stderr,
X            " in object '%s' -- reallocating\n", AG_dstobj->size.objname);
X
X        /* double allocation for groups */
X        dstalloc->nogroups = dstalloc->nogroups * 2;
X        AG_dstobj = realc_obj(AG_dstobj,dstalloc);
X
X        /* free storage allocated in this module */
X        free(dstalloc);
X        dstalloc = NULL;
X        }
X    /* add a new group name */
X    strcpy(AG_dstobj->group[gcount]->grpnam, group_name);
X    AG_dstobj->size.nogroups = gcount + 1;
X
X    }
X
X
Xif(verbflg > 1) {
X    fprintf(stderr,"add_group: done\n");
X    }
X
Xreturn(gcount);
X}
X
X
X
X
X
X
X
X/* function: add_lib()
X
X   description: Add a library name to the object.  Returns the index to the
X                new library.  If the library name already exists, that indes
X                is returned.
X
X   author: Stewart Dickson
X*/
X
X
Xint add_lib(AL_dstobj,lib_name)
Xstruct topology *AL_dstobj;
Xchar *lib_name;
X{
Xextern int verbflg;
Xstruct sizes *dstalloc = NULL, *copy_alc();
Xint libcount;
X
Xif(AL_dstobj == NULL) {
X    fprintf(stderr,"add_lib: ERROR - NULL object pointer received\n");
X    exit(-1);
X    }
X
Xif(lib_name == NULL) {
X    fprintf(stderr,"add_lib: ERROR - NULL library name string received\n");
X    exit(-1);
X    }
X
Xif(verbflg > 1) {
X    fprintf(stderr,
X        "entering add_lib(%s,%s)\n",AL_dstobj->size.objname,lib_name);
X    }
X
X/* there is always 1 library, if library 0 is set to a default */
Xif(!strcmp(AL_dstobj->lib[0]->libnam,"# no libraries used")) {
X    /* record new library name in dest object */
X    strcpy(AL_dstobj->lib[0]->libnam,lib_name);
X    AL_dstobj->size.nolibs = 1;
X    return(0);
X    }
X
Xfor(libcount = 0; libcount < AL_dstobj->size.nolibs; libcount++) {
X    /* determine if copied library is unique */
X    if(!strcmp(AL_dstobj->lib[libcount]->libnam,lib_name)) {
X        break;
X        }
X    }
X
Xif(libcount >= AL_dstobj->size.nolibs) {
X    /* if it is unique */
X    
X    if(verbflg>9) {
X        fprintf(stderr,
X            "add_lib: adding library %d, '%s'\n", libcount, lib_name);
X        }
X
X    /* check allocation and re-allocate if necessary */
X    if(libcount >= AL_dstobj->alloc.nolibs) {
X
X        /* allocate storage for object size parameter struct */
X        dstalloc = copy_alc(AL_dstobj,dstalloc);
X
X        fprintf(stderr, "add_lib: too many libraries %d", libcount);
X        fprintf(stderr, " in object '%s' -- reallocating\n",
X            AL_dstobj->size.objname);
X
X        /* double allocation for libraries */
X        dstalloc->nolibs = dstalloc->nolibs * 2;
X        AL_dstobj=realc_obj(AL_dstobj,dstalloc);
X
X        /* free memory allocated in this module */
X        free(dstalloc);
X        dstalloc = NULL;
X        }
X    /* record new library name in dest object */
X    strcpy(AL_dstobj->lib[libcount]->libnam,lib_name);
X    AL_dstobj->size.nolibs = libcount + 1;
X
X    }
X
Xif(verbflg > 1) {
X    fprintf(stderr,"add_lib: done\n");
X    }
X
Xreturn(libcount);
X}
X
X
X
X
X
X
X
X/* function: add_map
X
X   description:  Adds a texture map name to an object.  Returns the index to
X                 the new texture map.  If the map name already exists, the
X                 index to the existing map is returned.
X
X   author: Stewart Dickson
X*/
X
Xint add_map(AM_dstobj,map_name)
Xstruct topology *AM_dstobj;
Xchar *map_name;
X{
Xint mapcount;
Xstruct sizes *dstalloc, *copy_alc();
X
Xif(AM_dstobj == NULL) {
X    fprintf(stderr,"add_map: ERROR - NULL object pointer received\n");
X    exit(-1);
X    }
X
Xif(map_name == NULL) {
X    fprintf(stderr,"add_map: ERROR - NULL texture map name string received\n");
X    exit(-1);
X    }
X
Xif(verbflg > 1) {
X    fprintf(stderr,
X        "entering add_map(%s,%s)\n",AM_dstobj->size.objname,map_name);
X    }
X
X/* if map 0 is set to a default */
Xif(!strcmp(AM_dstobj->map[0]->mapnam,"# no mappings used")) {
X        strcpy(AM_dstobj->map[mapcount]->mapnam,map_name);
X        AM_dstobj->size.nomaps = 1;
X        return(0);
X        }
X
Xfor(mapcount=0; mapcount < AM_dstobj->size.nomaps; mapcount++) {
X    /* determine if copied mapping is unique */
X    if(strcmp(AM_dstobj->map[mapcount]->mapnam,map_name)) {
X        break;
X        }
X    }
X
Xif(mapcount >= AM_dstobj->size.nomaps) {
X    /* if it is unique */
X
X    if(verbflg>9) {
X        fprintf(stderr,"add_map: adding texture map %d, %s\n",mapcount,
X            map_name);
X        }
X
X    /* check allocation */
X    if(mapcount >= AM_dstobj->alloc.nomaps) {
X
X        /* allocate storage for object size parameter struct */
X        dstalloc = copy_alc(AM_dstobj,dstalloc);
X
X        fprintf(stderr, "add_map: too many mappings %d", mapcount);
X        fprintf(stderr, " in object '%s' -- reallocating\n",
X            AM_dstobj->size.objname);
X
X        /* double allocation for texture names */
X        dstalloc->nomaps = dstalloc->nomaps * 2;
X        AM_dstobj = realc_obj(AM_dstobj,dstalloc);
X
X        /* free memory allocated in this module */
X        free(dstalloc);
X        dstalloc = NULL;
X        }
X
X    /* record new material in object */
X    strcpy(AM_dstobj->map[mapcount]->mapnam,map_name);
X    AM_dstobj->size.nomaps = mapcount;
X
X    }
X
Xif(verbflg > 1) {
X    fprintf(stderr,"add_map: done\n");
X    }
X
Xreturn(mapcount);
X}
X
X
X
X
X
X
X
X/* function: add_mtl
X
X   description:  Adds a material name to an object.  Returns the index to
X                 the new material.  If the material name already exists, the
X                 index to the existing material is returned.
X
X   author: Stewart Dickson
X*/
X
Xint add_mtl(AM_dstobj,mtl_name)
Xstruct topology *AM_dstobj;
Xchar *mtl_name;
X{
Xextern int verbflg;
Xstruct sizes *dstalloc = NULL, *copy_alc();
Xint mtlcount;
X
Xif(AM_dstobj == NULL) {
X    fprintf(stderr,"add_mtl: ERROR - NULL object pointer received\n");
X    exit(-1);
X    }
X
Xif(mtl_name == NULL) {
X    fprintf(stderr,"add_mtl: ERROR - NULL material name string received\n");
X    exit(-1);
X    }
X
Xif(verbflg > 1) {
X    fprintf(stderr,
X        "entering add_mtl(%s,%s)\n",AM_dstobj->size.objname,mtl_name);
X    }
X
X/* there is always 1 material, if material 0 is set to a default */
Xif(!strcmp(AM_dstobj->mtl[0]->mtlnam,"# no materials used")) {
X    /* record new material name in dest object */
X    strcpy(AM_dstobj->mtl[0]->mtlnam,mtl_name);
X    AM_dstobj->size.nomtls = 1;
X    return(0);
X    }
X
Xfor(mtlcount = 0; mtlcount < AM_dstobj->size.nomtls; mtlcount++) {
X    /* determine if copied material is unique */
X    if(!strcmp(AM_dstobj->mtl[mtlcount]->mtlnam,mtl_name)) {
X        break;
X        }
X    }
Xif(mtlcount >= AM_dstobj->size.nomtls) {
X    /* if it is unique */
X    
X    if(verbflg>9) {
X        fprintf(stderr,
X            "add_mtl: adding material %d, '%s'\n",mtlcount, mtl_name);
X        }
X
X    /* check allocation and re-allocate if necessary */
X    if(mtlcount >= AM_dstobj->alloc.nomtls) {
X        /* allocate storage for object size parameter struct */
X        dstalloc = copy_alc(AM_dstobj,dstalloc);
X
X        fprintf(stderr, "add_mtl: too many materials %d", mtlcount);
X        fprintf(stderr, "in object '%s' -- reallocating\n",
X            AM_dstobj->size.objname);
X
X        /* double allocation for materials */
X        dstalloc->nomtls = dstalloc->nomtls * 2;
X        AM_dstobj = realc_obj(AM_dstobj,dstalloc);
X
X        /* free memory allocated in this module */
X        free(dstalloc);
X        dstalloc = NULL;
X        }
X    /* record new material name */
X    strcpy(AM_dstobj->mtl[mtlcount]->mtlnam,mtl_name);
X    AM_dstobj->size.nomtls = mtlcount + 1;
X
X    }
X
Xif(verbflg > 1) {
X    fprintf(stderr,"add_mtl: done\n");
X    }
X
Xreturn(mtlcount);
X}
X
X
X
X
X
X
X
X
X/* function: copy_obj
X
X   description: copies an object structure, destroying original contents
X        of destination structure.
X
X   parameters:    srcobj - object structure containing copy
X        elemflg - designation of type of information to copy
X              valid values are:
X                'e' - copy simple elements only
X                'm' - copy meta elements and simple elements
X                'h' - copy material header information only
X
X   return:  dstobj - object structure to receive copy
X
X   author: Stewart Dickson
X*/
X
X
Xstruct topology *copy_obj(dstobj,srcobj,elemflg)
Xstruct topology *dstobj, *srcobj;
Xchar elemflg;
X{
Xextern int verbflg;
Xstruct topology *alloc_obj(),*realc_obj();
Xstruct sizes *CPalloc=NULL,*copy_alc(),*copy_siz();
Xint lcount=0,lvcnt=0;
Xint fcount=0,fvcnt=0;
Xint circnt=0,sphcnt=0,bicuct=0;
Xint row,col;
Xint tvcount=1,vcount=1,pcount=0,pvcnt=0;
Xint sindx=(-1),mtlindx,mapindx,calindx,libindx,gindx,geindx;
Xint vindx,tvindx;
Xlcount=0;lvcnt=0;
Xfcount=0;fvcnt=0;
Xtvcount=1;vcount=1;pcount=0;
X
Xif(srcobj==NULL) {
X    fprintf(stderr,"copy_obj: ERROR - NULL source object received\n");
X    exit(-1);
X    }
X
Xif(verbflg>1) {
X    fprintf(stderr,"entering copy_obj('%c')\n",elemflg);
X    }
X
Xif(dstobj==NULL) {
X    fprintf(stderr,
X        "copy_obj: NULL destination object received -- allocating\n");
X    /* copy allocation parameters from source object */
X    CPalloc=copy_alc(srcobj,CPalloc);
X    /* allocate an object of identical size to input object */
X    dstobj=alloc_obj(CPalloc);
X    }
Xelse {
X    /* copy size parameters from source object for internal use */
X    if(elemflg == 'h') { /* only use header params form srcobj */
X        CPalloc=copy_alc(dstobj,CPalloc);
X        /* copy header params if we're ony copying header */
X        CPalloc->nocalls = srcobj->size.nocalls;
X        CPalloc->nolibs = srcobj->size.nolibs;
X        CPalloc->nomaps = srcobj->size.nomaps;
X        CPalloc->nomtls = srcobj->size.nomtls;
X        }
X    else { /* copy everything */
X        CPalloc=copy_alc(srcobj,CPalloc);
X        }
X    /* reallocate to ensure we have at least the sizes of input object */
X    dstobj=realc_obj(dstobj,CPalloc);
X    }
X
Xif(verbflg>0) {
X    fprintf(stderr,"copy_obj: copying object '%s' to '%s'\n",
X        srcobj->size.objname,dstobj->size.objname);    
X    }
X
X/* copy 'call' directives */
Xfor(calindx=0;calindx<srcobj->size.nocalls;calindx++) {
X    if(verbflg>9) {
X        fprintf(stderr,"%s\n",srcobj->call[calindx]->filnam);    
X        }
X    strcpy(dstobj->call[calindx]->filnam,srcobj->call[calindx]->filnam);
X    }
X
X/* copy 'mtllib/maplib' directives */
Xfor(libindx=0;libindx<srcobj->size.nolibs;libindx++) {
X    if(verbflg>9) {
X        fprintf(stderr,"%s\n",srcobj->lib[libindx]->libnam);    
X        }
X    strcpy(dstobj->lib[libindx]->libnam,srcobj->lib[libindx]->libnam);
X    }
X
X/* copy materials */
Xif(verbflg>4) {
X    fprintf(stderr,"copy_obj: copying %d materials\n",srcobj->size.nomtls);
X    }
Xfor(mtlindx=0;mtlindx<srcobj->size.nomtls;mtlindx++) {
X    if(verbflg>9) {
X        fprintf(stderr,"%s\n",srcobj->mtl[mtlindx]->mtlnam);
X        }
X    strcpy(dstobj->mtl[mtlindx]->mtlnam,srcobj->mtl[mtlindx]->mtlnam);
X    }
X
X/* copy texture maps */
Xif(verbflg>4) {
X    fprintf(stderr,"copy_obj: copying %d texture maps\n",
X        srcobj->size.nomaps);
X        }
X
Xfor(mapindx=0;mapindx<srcobj->size.nomaps;mapindx++) {
X    if(verbflg>9) {
X        fprintf(stderr,"%s\n",srcobj->map[mapindx]->mapnam);
X        }
X    strcpy(dstobj->map[mapindx]->mapnam,srcobj->map[mapindx]->mapnam);
X    }
X
X/* copy groups */
Xif(verbflg>4) {
X    fprintf(stderr,"copy_obj: copying %d groups\n",
X        srcobj->size.nogroups);
X        }
Xfor(gindx=0;gindx<srcobj->size.nogroups;gindx++) {
X    if(verbflg>9) {
X        fprintf(stderr,"copy_obj: %s ",srcobj->group[gindx]->grpnam);
X        }
X    /* copy group name */
X    strcpy(dstobj->group[gindx]->grpnam,srcobj->group[gindx]->grpnam);
X        /* copy group vertices */
X    for(geindx=0;geindx<srcobj->group[gindx]->noverts;geindx++) {
X        dstobj->group[gindx]->vertno[geindx] =
X            srcobj->group[gindx]->vertno[geindx];
X                }
X    dstobj->group[gindx]->noverts =
X        srcobj->group[gindx]->noverts;
X    /* copy group elements */
X    if(verbflg > 9) {
X        fprintf(stderr,"%d pointses ",srcobj->group[gindx]->nopoints);
X        }
X    for(geindx=0;geindx<srcobj->group[gindx]->nopoints;geindx++) {
X        dstobj->group[gindx]->pointno[geindx] =
X            srcobj->group[gindx]->pointno[geindx];
X        }
X    dstobj->group[gindx]->nopoints =
X        srcobj->group[gindx]->nopoints;
X    if(verbflg > 9) {
X        fprintf(stderr,"%d lines ",srcobj->group[gindx]->nolines);
X        }
X    for(geindx=0;geindx<srcobj->group[gindx]->nolines;geindx++) {
X        dstobj->group[gindx]->lineno[geindx] =
X            srcobj->group[gindx]->lineno[geindx];
X        }
X    dstobj->group[gindx]->nolines =
X        srcobj->group[gindx]->nolines;
X    if(verbflg > 9) {
X        fprintf(stderr,"%d faces ",srcobj->group[gindx]->nofaces);
X        }
X    for(geindx=0;geindx<srcobj->group[gindx]->nofaces;geindx++) {
X        dstobj->group[gindx]->faceno[geindx] =
X            srcobj->group[gindx]->faceno[geindx];
X        }
X    dstobj->group[gindx]->nofaces =
X        srcobj->group[gindx]->nofaces;
X    if(verbflg > 9) {
X        fprintf(stderr,"%d circles ",srcobj->group[gindx]->nocircs);
X        }
X    for(geindx=0;geindx<srcobj->group[gindx]->nocircs;geindx++) {
X        dstobj->group[gindx]->circno[geindx] =
X            srcobj->group[gindx]->circno[geindx];
X        }
X    dstobj->group[gindx]->nocircs =
X        srcobj->group[gindx]->nocircs;
X    if(verbflg > 9) {
X        fprintf(stderr,"%d spheres ",srcobj->group[gindx]->nosphrs);
X        }
X    for(geindx=0;geindx<srcobj->group[gindx]->nosphrs;geindx++) {
X        dstobj->group[gindx]->sphrno[geindx] =
X            srcobj->group[gindx]->sphrno[geindx];
X        }
X    dstobj->group[gindx]->nosphrs =
X        srcobj->group[gindx]->nosphrs;
X    if(verbflg > 9) {
X        fprintf(stderr,"%d patches\n",srcobj->group[gindx]->noptchs);
X        }
X    for(geindx=0;geindx<srcobj->group[gindx]->noptchs;geindx++) {
X        dstobj->group[gindx]->ptchno[geindx] =
X            srcobj->group[gindx]->ptchno[geindx];
X        }
X    dstobj->group[gindx]->noptchs =
X        srcobj->group[gindx]->noptchs;
X    }
X
Xif(elemflg=='e' || elemflg=='m') {
X    if(verbflg > 9) {
X        fprintf(stderr,"copy_obj: %d vertices ",
X            srcobj->size.noverts);
X        }
X    /* copy vertices */
X    for(vcount=1;vcount<srcobj->size.noverts;vcount++) {
X        dstobj->vertex[vcount]->mtl=srcobj->vertex[vcount]->mtl;
X        dstobj->vertex[vcount]->x=srcobj->vertex[vcount]->x;
X        dstobj->vertex[vcount]->y=srcobj->vertex[vcount]->y;
X        dstobj->vertex[vcount]->z=srcobj->vertex[vcount]->z;
X        }
X    
X    if(verbflg > 9) {
X        fprintf(stderr,"%d texture vertices ",srcobj->size.notverts);
X        }
X    /* copy texture vertices */
X    for(tvcount=1;tvcount<srcobj->size.notverts;tvcount++) {
X        dstobj->texver[tvcount]->u=srcobj->texver[tvcount]->u;
X        dstobj->texver[tvcount]->v=srcobj->texver[tvcount]->v;
X        dstobj->texver[tvcount]->w=srcobj->texver[tvcount]->w;
X        }
X    
X    if(verbflg > 9) {
X        fprintf(stderr,"%d lines ",srcobj->size.nolines);
X        }
X    /* copy lines */
X    for(lcount=0;lcount<srcobj->size.nolines;lcount++) {
X        for(lvcnt=0;lvcnt<srcobj->line[lcount]->vertc;lvcnt++) {
X            vindx=srcobj->line[lcount]->vertno[lvcnt];
X            dstobj->line[lcount]->vertno[lvcnt]=vindx;
X            }
X                if(lvcnt > dstobj->size.nolverts) {
X                    dstobj->size.nolverts = lvcnt + 1;
X            }
X        dstobj->line[lcount]->vertc=srcobj->line[lcount]->vertc;
X        dstobj->line[lcount]->mtl=srcobj->line[lcount]->mtl;
X        dstobj->line[lcount]->group=srcobj->line[lcount]->group;
X        }
X    
X    if(verbflg > 9) {
X        fprintf(stderr,"%d pointses ",srcobj->size.nopoints);
X        }
X    /* copy points */
X    for(pcount=0;pcount<srcobj->size.nopoints;pcount++) {
X        for(pvcnt=0;pvcnt<srcobj->point[pcount]->vertc;pvcnt++) {
X            vindx=srcobj->point[pcount]->vertno[pvcnt];
X            dstobj->point[pcount]->vertno[pvcnt]=vindx;
X            }
X                if(pvcnt > dstobj->size.nopverts) {
X                    dstobj->size.nopverts = pvcnt + 1;
X            }
X        dstobj->point[pcount]->vertc=srcobj->point[pcount]->vertc;
X        dstobj->point[pcount]->group=srcobj->point[pcount]->group;
X        }
X    
X    if(verbflg > 9) {
X        fprintf(stderr,"%d faces\n",srcobj->size.nofaces);
X        }
X    /* copy faces */
X    for(fcount=0;fcount<srcobj->size.nofaces;fcount++) {
X        dstobj->face[fcount]->smooth=srcobj->face[fcount]->smooth;
X        dstobj->face[fcount]->bevel=srcobj->face[fcount]->bevel;
X        dstobj->face[fcount]->mapflg=srcobj->face[fcount]->mapflg;
X        for(fvcnt=0;fvcnt<srcobj->face[fcount]->vertc;fvcnt++) {
X            vindx=srcobj->face[fcount]->vertno[fvcnt];
X            dstobj->face[fcount]->vertno[fvcnt]=vindx;
X            if(srcobj->face[fcount]->map>(-1)) {
X                tvindx=srcobj->face[fcount]->tvertno[fvcnt];
X                dstobj->face[fcount]->vertno[fvcnt]=tvindx;
X                }
X            }
X                if(fvcnt > dstobj->size.nofverts) {
X                    dstobj->size.nofverts = fvcnt + 1;
X            }
X        dstobj->face[fcount]->vertc=srcobj->face[fcount]->vertc;
X        dstobj->face[fcount]->mtl=srcobj->face[fcount]->mtl;
X        dstobj->face[fcount]->map=srcobj->face[fcount]->map;
X        dstobj->face[fcount]->group=srcobj->face[fcount]->group;
X        }
X
X    if(verbflg > 9) {
X        fprintf(stderr,"%d patches\n",srcobj->size.noptchs);
X        }
X    /* copy bicubic patches */
X    for(bicuct=0;bicuct<srcobj->size.noptchs;bicuct++) {
X        for(row=0;row<4;row++) {
X            for(col=0;col<4;col++) {
X                dstobj->bicub[bicuct]->vertno[row][col] =
X                    srcobj->bicub[bicuct]->vertno[row][col];
X                dstobj->bicub[bicuct]->tvertno[row][col] =
X                    srcobj->bicub[bicuct]->tvertno[row][col];
X                }
X            }
X        dstobj->bicub[bicuct]->type=srcobj->bicub[bicuct]->type;
X        dstobj->bicub[bicuct]->v_res=srcobj->bicub[bicuct]->v_res;
X        dstobj->bicub[bicuct]->u_res=srcobj->bicub[bicuct]->u_res;
X        dstobj->bicub[bicuct]->mtl=srcobj->bicub[bicuct]->mtl;
X        dstobj->bicub[bicuct]->map=srcobj->bicub[bicuct]->map;
X        dstobj->bicub[bicuct]->smooth=srcobj->bicub[bicuct]->smooth;
X        dstobj->bicub[bicuct]->group=srcobj->bicub[bicuct]->group;
X        }
X
X    dstobj->size.noverts=vcount;
X    dstobj->size.notverts=tvcount;
X    dstobj->size.nosgrps=srcobj->size.nosgrps;
X    dstobj->size.nofaces=fcount;
X    dstobj->size.nopoints=pcount;
X    dstobj->size.nolines=lcount;
X    dstobj->size.noptchs=bicuct;
X    }
X
X/* if flag is set, copy meta elements */
Xif(elemflg=='m') {
X    if(verbflg > 9) {
X        fprintf(stderr,"copy_obj: %d circles ",
X            srcobj->size.nocircs);
X        }
X    /* copy circles */
X    for(circnt=0;circnt<srcobj->size.nocircs;circnt++) {
X        dstobj->circl[circnt]->vertno=srcobj->circl[circnt]->vertno;
X        dstobj->circl[circnt]->rad=srcobj->circl[circnt]->rad;
X        dstobj->circl[circnt]->res=srcobj->circl[circnt]->res;
X        dstobj->circl[circnt]->group=srcobj->circl[circnt]->group;
X        }
X    if(verbflg > 9) {
X        fprintf(stderr,"%d spheres ",srcobj->size.nosphrs);
X        }
X    /* copy spheres */
X    for(sphcnt=0;sphcnt<srcobj->size.nosphrs;sphcnt++) {
X        dstobj->spher[sphcnt]->vertno=srcobj->spher[sphcnt]->vertno;
X        dstobj->spher[sphcnt]->rad=srcobj->spher[sphcnt]->rad;
X        dstobj->spher[sphcnt]->res=srcobj->spher[sphcnt]->res;
X        dstobj->spher[sphcnt]->mtl=srcobj->spher[sphcnt]->mtl;
X        dstobj->spher[sphcnt]->map=srcobj->spher[sphcnt]->map;
X        dstobj->spher[sphcnt]->smooth=srcobj->spher[sphcnt]->smooth;
X        dstobj->spher[sphcnt]->group=srcobj->spher[sphcnt]->group;
X        }
X
X    dstobj->size.nocircs=circnt;
X    dstobj->size.nosphrs=sphcnt;
X    }
Xdstobj->size.nomtls=mtlindx;
Xdstobj->size.nomaps=mapindx;
Xdstobj->size.nolibs=libindx;
Xdstobj->size.nocalls=calindx;
Xdstobj->size.nogroups=gindx;
X
X/* free memory allocated in this function */
Xfree(CPalloc);
XCPalloc = NULL;
X
Xif(verbflg > 1) {
X    fprintf(stderr,"copy_obj: done\n");
X    }
X
Xreturn(dstobj);
X}
!EOR!
echo extracting src/obj_lib/rd_poly.c
echo mkdir ./src
mkdir ./src
echo mkdir ./src/obj_lib
mkdir ./src/obj_lib
sed 's/^X//' > src/obj_lib/rd_poly.c << '!EOR!' 
X/* file: rd_poly.c
X
X   description: Reads an ASCII geometrical object description of the type
X                used in Andrew Humes database of regular polyhedra.
X                See poly(5).
X
X   author: Stewart Dickson
X*/
X
X#include <stdio.h>
X#include <topology.h>
X
X#define NUMBER 0
X#define NAME 1
X#define SYMBOL 2
X#define DUAL 3
X#define VERTICES 4
X#define SVERTICES 5
X#define NET 6
X#define SFACES 7
X#define HINGES 8
X#define SOLID 9
X#define DIHEDRAL 10
X#define END_OF_FILE 11
X#define NO_LABELS 12
X
Xchar header[NO_LABELS][80] = {
X    "number", "name", "symbol", "dual", "vertices", "svertices", "net",
X    "sfaces", "hinges", "solid", "dihedral", "EOF"
X    };
X
Xstruct topology *rd_poly(dst_obj, src_file)
Xstruct topology *dst_obj;
XFILE *src_file;
X{
Xextern int verbflg;
Xstruct sizes *alloc = NULL, *null_parms();
Xstruct topology *alloc_hdr(), *alloc_verts(), *alloc_faces(), *alloc_edges();
Xstruct topology *realc_obj();
Xint lchar, lcount, lindx, nolines;
Xint add_group(), grp_index, net_group, solid_group;
Xint tot_verts, net_verts, net_faces, solid_faces;
Xint vindx, eindx, findx, fvindx, ofindx, noverts, nofverts, noedges;
Xfloat vert_x, vert_y, vert_z, dihedral;
Xchar key_word[128], line[128], new_string[128];
X
Xif(verbflg > 0) {
X    fprintf(stderr,"entering rd_poly\n");
X    }
X
X/* allocate local object parameter struct - set to all zeroes */
Xalloc = null_parms(alloc);
Xalloc->nomtls = 1;
Xalloc->nomaps = 1;
Xalloc->nogroups = 3;
X
Xofindx = 0;
Xlcount =  1;
Xwhile(fscanf(src_file,":%s",key_word) != EOF) {
X    /* read newline(s) */
X    while((lchar = fgetc(src_file)) == '\n') lcount++;
X    ungetc(lchar,src_file);
X    switch(parse(key_word)) {
X        case NUMBER: { /* plug into object name */
X            fscanf(src_file,"%[^\n]",line);
X            sprintf(new_string,"Hume's number: %s, ",line);
X            if(strlen(alloc->objname) + strlen(new_string) < 128) {
X                strcat(alloc->objname,new_string);
X                }
X            if(verbflg > 0) {
X                fprintf(stderr,
X                    "rd_poly: line %d, NUMBER '%s'\n",lcount,line);
X                }
X            /* read newline(s) */
X            while((lchar = fgetc(src_file)) == '\n') lcount++;
X            ungetc(lchar,src_file);
X            break;
X            }
X        case NAME: { /* plug into object name */
X            fscanf(src_file,"%[^\n]",line);
X            sprintf(new_string,"Polyhedron name: %s, ",line);
X            if(strlen(alloc->objname) + strlen(new_string) < 128) {
X                strcat(alloc->objname,new_string);
X                }
X            if(verbflg > 0) {
X                fprintf(stderr,
X                    "rd_poly: line %d, NAME '%s'\n",lcount,line);
X                }
X            /* read newline(s) */
X            while((lchar = fgetc(src_file)) == '\n') lcount++;
X            ungetc(lchar,src_file);
X            break;
X            }
X        case SYMBOL: { /* plug into object name */
X            fscanf(src_file,"%[^\n]",line);
X            sprintf(new_string,"Symbol: %s, ",line);
X            if(strlen(alloc->objname) + strlen(new_string) < 128) {
X                strcat(alloc->objname,new_string);
X                }
X            if(verbflg > 0) {
X                fprintf(stderr,
X                    "rd_poly: line %d, SYMBOL '%s'\n",lcount,line);
X                }
X            /* read newline(s) */
X            while((lchar = fgetc(src_file)) == '\n') lcount++;
X            ungetc(lchar,src_file);
X            break;
X            }
X        case DUAL: { /* plug into object name */
X            fscanf(src_file,"%[^\n]",line);
X            sprintf(new_string,"Dual: %s, ",line);
X            if(strlen(alloc->objname) + strlen(new_string) < 128) {
X                strcat(alloc->objname,new_string);
X                }
X            if(verbflg > 0) {
X                fprintf(stderr,
X                    "rd_poly: line %d, DUAL '%s'\n",lcount, line);
X                }
X            /* read newline(s) */
X            while((lchar = fgetc(src_file)) == '\n') lcount++;
X            ungetc(lchar,src_file);
X            break;
X            }
X        case VERTICES: {
X            /* first line following header is number of vertices */
X            fscanf(src_file,"%d", &tot_verts);
X            /* there is an optional number of vertices
X               depicting the planar net */
X            if((lchar = fgetc(src_file)) == ' ') {
X                fscanf(src_file,"%d", &net_verts);
X                }
X            else { /* newline */
X                net_verts = 0;
X                ungetc(lchar,src_file);
X                }
X            if(tot_verts < 5) { /* bad # vertices */
X                fprintf(stderr,
X                    "rd_poly: line %d: bad number of vertices: %d\n",
X                    lcount, tot_verts);
X                exit(-1);
X                }
X            if(verbflg > 1) {
X                fprintf(stderr,
X                    "rd_poly: line %d, reading %d vertices\n",
X                    lcount, tot_verts);
X                }
X            alloc->noverts = tot_verts + 1;
X            alloc->nogverts = alloc->noverts;
X            if(dst_obj == NULL) { /* We're going to allocate as we go */
X                dst_obj = alloc_hdr(alloc);
X                }
X            else if(dst_obj->vertex == NULL) { /* allocate vertices */
X                dst_obj = alloc_verts(dst_obj,alloc);
X                }
X            else { /* we already have an object and vertices, reallocate */
X                dst_obj = realc_obj(dst_obj,alloc);
X                }
X            /* read newline(s) */
X            while((lchar = fgetc(src_file)) == '\n') lcount++;
X            ungetc(lchar,src_file);
X            /* read vertices */
X            for(vindx = 1; vindx < alloc->noverts; vindx++) {
X                if(verbflg > 1) {
X                    fprintf(stderr,
X                        "rd_poly: line %d, reading vertex %d\n",
X                        lcount, vindx);
X                    }
X                if(vindx <= net_verts) {
X                    grp_index = add_group(dst_obj,"net");
X                    }
X                else {
X                    grp_index = add_group(dst_obj,"solid");
X                    }
X                fscanf(src_file,"%f",&vert_x);
X                /* if next char is '[', expect expression form of vertex
X                   coordinate */
X                if((lchar = fgetc(src_file)) == '[') {
X                    /* skip this for now */
X                    while((lchar = fgetc(src_file)) != ']');
X                    }
X                else if(lchar != ' ') {
X                    ungetc(lchar,src_file);
X                    }
X                /* assign value to vertex coordinate */
X                dst_obj->vertex[vindx]->x = vert_x;
X                /* read next coordinate */
X                fscanf(src_file,"%f",&vert_y);
X                /* if next char is '[', expect expression form of vertex
X                   coordinate */
X                if((lchar = fgetc(src_file)) == '[') {
X                    /* skip this for now */
X                    while((lchar = fgetc(src_file)) != ']');
X                    }
X                else if(lchar != ' ') {
X                    ungetc(lchar,src_file);
X                    }
X                /* assign value to vertex coordinate */
X                dst_obj->vertex[vindx]->y = vert_y;
X                /* read next coordinate */
X                fscanf(src_file,"%f",&vert_z);
X                /* if next char is '[', expect expression form of vertex
X                   coordinate */
X                if((lchar = fgetc(src_file)) == '[') {
X                    /* skip this for now */
X                    while((lchar = fgetc(src_file)) != ']');
X                    }
X                else if(lchar != ' ') {
X                    ungetc(lchar,src_file);
X                    }
X                /* assign value to vertex coordinate */
X                dst_obj->vertex[vindx]->z = vert_z;
X                /* set material */
X                dst_obj->vertex[vindx]->mtl = 0;
X                dst_obj->vertex[vindx]->group = grp_index;
X                /* read newline(s) */
X                while((lchar = fgetc(src_file)) == '\n') lcount++;
X                ungetc(lchar,src_file);
X                }
X            /* set vertex population of object */
X            dst_obj->size.noverts = alloc->noverts;
X            break;
X            }
X        case SVERTICES: { /* ??? */
X            /* don't know what this is - throw away */
X            /* read newline(s) */
X            while((lchar = fgetc(src_file)) == '\n') lcount++;
X            ungetc(lchar,src_file);
X            /* read up to next newline */
X            while((lchar = fgetc(src_file)) != '\n');
X            ungetc(lchar,src_file);
X            /* read newline(s) */
X            while((lchar = fgetc(src_file)) == '\n') lcount++;
X            ungetc(lchar,src_file);
X            break;
X            }
X        case NET: { /* planar net - stereographic projection */
X            /* first line is number of faces and max. vertices in a face */
X            if(fscanf(src_file,"%d ",&net_faces) < 1) { /* missing # faces */
X                fprintf(stderr, "rd_poly: line %d: missing number of faces\n",
X                    lcount);
X                exit(-1);
X                }
X            if(fscanf(src_file,"%d",&nofverts) < 1) {
X                /* missing # vertices/face */
X                fprintf(stderr,
X                    "rd_poly: line %d: missing number of vertices per face\n",
X                    lcount);
X                exit(-1);
X                }
X            if(alloc->nofaces == 0) { /* no faces have been read */
X                alloc->nofaces = net_faces;
X                alloc->nofverts = nofverts;
X                if(dst_obj == NULL) { /* We're going to allocate as we go */
X                    dst_obj = alloc_hdr(alloc);
X                    }
X                if(dst_obj->face == NULL) { /* allocate faces */
X                    dst_obj = alloc_faces(dst_obj,alloc);
X                    }
X                }
X            else { /* some faces have been read, reallocate */
X                alloc->nofaces = alloc->nofaces + net_faces;
X                if(alloc->nofverts < nofverts) {
X                    alloc->nofverts = nofverts;
X                    }
X                dst_obj = realc_obj(dst_obj,alloc);
X                }
X            /* read newline(s) */
X            while((lchar = fgetc(src_file)) == '\n') lcount++;
X            ungetc(lchar,src_file);
X            /* add an object element group 'net' */
X            grp_index = add_group(dst_obj,"net");
X            net_group = grp_index;
X            /* remaining lines consist of vertex count and vertex indices */
X            for(findx = 0; findx < net_faces; findx++) {
X                if(verbflg > 1) {
X                    fprintf(stderr,
X                        "rd_poly: line %d, reading net face %d, abs. face %d\n",
X                        lcount, findx, ofindx);
X                    }
X                /* first field is number of vertices */
X                if(fscanf(src_file,"%d",&noverts) < 1) { /* missing # verts */
X                    fprintf(stderr,
X                        "rd_poly: line %d: polygon %d, missing # of verts\n",
X                        lcount, findx);
X                    exit(-1);
X                    }
X                dst_obj->face[ofindx]->vertc = noverts;
X                dst_obj->face[ofindx]->mtl = 0;
X                dst_obj->face[ofindx]->map = -1;
X                dst_obj->face[ofindx]->mapflg = 0;
X                dst_obj->face[ofindx]->group = grp_index;
X                dst_obj->face[ofindx]->bevel = 0;
X                dst_obj->face[ofindx]->smooth = -1;
X                for(fvindx = 0; fvindx < noverts; fvindx++) {
X                    /* remaining fields are vertex indices */
X                    if(fscanf(src_file, " %d", &vindx) < 1) {
X                        fprintf(stderr,
X                            "rd_poly: line %d: polygon %d, missing vertex %d\n",
X                            lcount, ofindx, fvindx);
X                        exit(-1);
X                        }
X                    dst_obj->face[ofindx]->vertno[fvindx] = vindx + 1;
X                    }
X                ofindx++;
X                /* read newline(s) */
X                while((lchar = fgetc(src_file)) == '\n') lcount++;
X                ungetc(lchar,src_file);
X                }
X            dst_obj->size.nofaces = alloc->nofaces;
X            dst_obj->size.nofverts = alloc->nofverts;
X            break;
X            }
X        case SFACES: {
X            /* know what this is, but don't know what to do with it -
X               throw away */
X            /* read newline(s) */
X            while((lchar = fgetc(src_file)) == '\n') lcount++;
X            ungetc(lchar,src_file);
X            /* read up to next newline */
X            while((lchar = fgetc(src_file)) != '\n');
X            ungetc(lchar,src_file);
X            /* read newline(s) */
X            while((lchar = fgetc(src_file)) == '\n') lcount++;
X            ungetc(lchar,src_file);
X            break;
X            }
X        case HINGES: {
X            /* first line is number of edges */
X            if(fscanf(src_file,"%d",&noedges) < 1) { /* missing # edges */
X                fprintf(stderr, "rd_poly: line %d: missing number of edges\n",
X                    lcount);
X                exit(-1);
X                }
X            alloc->noedges = noedges;
X
X            if(dst_obj == NULL) { /* We're going to allocate as we go */
X                dst_obj = alloc_hdr(alloc);
X                }
X            else if(dst_obj->edge == NULL) { /* allocate edges */
X                dst_obj = alloc_edges(dst_obj,alloc);
X                }
X            else { /* reallocate */
X                dst_obj = realc_obj(dst_obj,alloc);
X                }
X
X            /* read newline(s) */
X            while((lchar = fgetc(src_file)) == '\n') lcount++;
X            ungetc(lchar,src_file);
X
X            /* remaining lines consist of face-edge pairs */
X            for(eindx = 0; eindx < noedges; eindx++) {
X                if(verbflg > 1) {
X                    fprintf(stderr,"rd_poly: line %d, reading edge %d\n",
X                        lcount, eindx);
X                    }
X                /* first field is face 0 */
X                if(fscanf(src_file,"%d ",&findx) < 1) { /* missing face # */
X                    fprintf(stderr,
X                        "rd_poly: line %d: edge %d, missing face #\n",
X                        lcount, eindx);
X                    exit(-1);
X                    }
X                dst_obj->edge[eindx]->faceno[0] = findx;
X
X                /* second field is side of face 0 */
X                if(fscanf(src_file,"%d ",&fvindx) < 1) {
X                    /* missing face side */
X                    fprintf(stderr,
X                        "rd_poly: line %d: edge %d, missing face side #\n",
X                        lcount, eindx);
X                    exit(-1);
X                    }
X
X                /* assign vertices to edge from face vertex list */
X                vindx = dst_obj->face[findx]->vertno[fvindx];
X                dst_obj->edge[eindx]->vertno[0] = vindx;
X                vindx = dst_obj->face[findx]->vertno[fvindx + 1];
X                dst_obj->edge[eindx]->vertno[1] = vindx;
X
X                /* third field is face 1 */
X                if(fscanf(src_file,"%d ",&findx) < 1) { /* missing face # */
X                    fprintf(stderr,
X                        "rd_poly: line %d: edge %d, missing face #\n",
X                        lcount, eindx);
X                    exit(-1);
X                    }
X                dst_obj->edge[eindx]->faceno[1] = findx;
X
X                /* fourth field is side of face 1 */
X                if(fscanf(src_file,"%d ",&fvindx) < 1) { /* missing face side */
X                    fprintf(stderr,
X                        "rd_poly: line %d: edge %d, missing face side #\n",
X                        lcount, eindx);
X                    exit(-1);
X                    }
X
X                /* verify vertices from face vertex list with edge */
X                vindx = dst_obj->face[findx]->vertno[fvindx];
X                if(dst_obj->edge[eindx]->vertno[1] != vindx) {
X                    /* flag inconsistencies */
X                    fprintf(stderr,
X                        "rd_poly: WARNING: edge %d vertex mismatch\n",eindx);
X                    fprintf(stderr,
X                        "\tedge vertex %d, face vertex %d\n",
X                        dst_obj->edge[eindx]->vertno[1], vindx);
X                    }
X                vindx = dst_obj->face[findx]->vertno[fvindx + 1];
X                if(dst_obj->edge[eindx]->vertno[0] != vindx) {
X                    /* flag inconsistencies */
X                    fprintf(stderr,
X                        "rd_poly: WARNING: edge %d vertex mismatch\n",eindx);
X                    fprintf(stderr,
X                        "\tedge vertex %d, face vertex %d\n",
X                        dst_obj->edge[eindx]->vertno[0], vindx);
X                    }
X
X                /* fifth field is angle */
X                fscanf(src_file,"%f",&dihedral);
X                /* if next char is '[', expect expression form of vertex
X                   coordinate */
X                if((lchar = fgetc(src_file)) == '[') {
X                    /* skip this for now */
X                    while((lchar = fgetc(src_file)) != ']');
X                    }
X                else if(lchar != ' ') {
X                    ungetc(lchar,src_file);
X                    }
X                /* assign angle to object */
X                dst_obj->edge[eindx]->theta = dihedral;
X
X                /* read newline(s) */
X                while((lchar = fgetc(src_file)) == '\n') lcount++;
X                ungetc(lchar,src_file);
X                }
X            dst_obj->size.noedges = alloc->noedges;
X            break;
X            }
X        case SOLID: { /* polyhedron */
X            /* first line is number of faces and max. vertices in a face */
X            if(fscanf(src_file,"%d ",&solid_faces) < 1) { /* missing # faces */
X                fprintf(stderr, "rd_poly: line %d: missing number of faces\n",
X                    lcount);
X                exit(-1);
X                }
X            if(fscanf(src_file,"%d",&nofverts) < 1) {
X                /* missing # vertices/face */
X                fprintf(stderr,
X                    "rd_poly: line %d: missing number of vertices per face\n",
X                    lcount);
X                exit(-1);
X                }
X            if(alloc->nofaces == 0) { /* no faces have been read */
X                alloc->nofaces = solid_faces;
X                alloc->nofverts = nofverts;
X                if(dst_obj == NULL) { /* We're going to allocate as we go */
X                    dst_obj = alloc_hdr(alloc);
X                    }
X                if(dst_obj->face == NULL) { /* allocate faces */
X                    dst_obj = alloc_faces(dst_obj,alloc);
X                    }
X                }
X            else { /* faces have been read - reallocate */
X                alloc->nofaces = alloc->nofaces + solid_faces;
X                if(alloc->nofverts < nofverts) {
X                    alloc->nofverts = nofverts;
X                    }
X                dst_obj = realc_obj(dst_obj,alloc);
X                }
X            /* read newline(s) */
X            while((lchar = fgetc(src_file)) == '\n') lcount++;
X            ungetc(lchar,src_file);
X            /* add an object element group 'net' */
X            grp_index = add_group(dst_obj,"solid");
X            solid_group = grp_index;
X            /* remaining lines consist of vertex count and vertex indices */
X            for(findx = 0; findx < solid_faces; findx++) {
X                if(verbflg > 1) {
X                    fprintf(stderr,
X                        "rd_poly: line %d, reading solid face %d abs. face %d\n",
X                        lcount, findx, ofindx);
X                    }
X                /* first field is number of vertices */
X                if(fscanf(src_file,"%d",&noverts) < 1) { /* missing # verts */
X                    fprintf(stderr,
X                        "rd_poly: line %d: polygon %d, missing # of verts\n",
X                        lcount, findx);
X                    exit(-1);
X                    }
X                dst_obj->face[ofindx]->vertc = noverts;
X                dst_obj->face[ofindx]->mtl = 0;
X                dst_obj->face[ofindx]->map = -1;
X                dst_obj->face[ofindx]->mapflg = 0;
X                dst_obj->face[ofindx]->group = grp_index;
X                dst_obj->face[ofindx]->bevel = 0;
X                dst_obj->face[ofindx]->smooth = -1;
X                for(fvindx = 0; fvindx < noverts; fvindx++) {
X                    /* remaining fields are vertex indices */
X                    if(fscanf(src_file, " %d", &vindx) < 1) {
X                        fprintf(stderr,
X                            "rd_poly: line %d: polygon %d, missing vertex %d\n",
X                            lcount, ofindx, fvindx);
X                        exit(-1);
X                        }
X                    dst_obj->face[ofindx]->vertno[fvindx] = vindx + 1;
X                    }
X                ofindx++;
X                /* read newline(s) */
X                while((lchar = fgetc(src_file)) == '\n') lcount++;
X                ungetc(lchar,src_file);
X                }
X            dst_obj->size.nofaces = alloc->nofaces;
X            dst_obj->size.nofverts = alloc->nofverts;
X            break;
X            }
X        case DIHEDRAL: {
X            /* know what this is, but don't know what to do with it -
X               throw away */
X            /* first line contains number of distinct dihedrals */
X            fscanf(src_file,"%[^\n]",line);
X            lcount++;
X            if((nolines = atoi(line)) < 0) { /* bad # dihedrals */
X                fprintf(stderr,
X                    "rd_poly: line %d, bad number of dihedral angles '%s'\n",
X                    lcount, line);
X                exit(-1);
X                }
X            /* read newline(s) */
X            while((lchar = fgetc(src_file)) == '\n') lcount++;
X            ungetc(lchar,src_file);
X            /* remaining lines contain dihedral angles */
X            for(lindx = 0; lindx < nolines; lindx++) {
X                /* read lines */
X                fscanf(src_file,"%[^\n]",line);
X                /* read newline(s) */
X                while((lchar = fgetc(src_file)) == '\n') lcount++;
X                ungetc(lchar,src_file);
X                }
X            break;
X            }
X        case END_OF_FILE: {
X            /* read newline(s) */
X            while((lchar = fgetc(src_file)) == '\n') lcount++;
X            ungetc(lchar,src_file);
X            break;
X            }
X
X        }
X    }
X
X/* free memory allocated in this module */
Xfree(alloc);
X
Xif(verbflg > 0) {
X    fprintf(stderr,"rd_poly: done\n");
X    }
X
Xreturn(dst_obj);
X
X}
X
X
X
X
X/* function: parse
X
X   description: Returns the index to a #define'd label matching the input
X                string.
X
X   author: Stewart Dickson
X*/
X
Xint parse(string)
Xchar *string;
X{
Xextern int verbflg;
Xint index;
X
Xfor(index = 0; index < NO_LABELS; index++) {
X    if(!strncmp(string,header[index],3)) {
X        break;
X        }
X    }
X
Xif(verbflg > 1) {
X    fprintf(stderr,"parse: reading '%s'\n",header[index]);
X    }
X
X/* re-set string to a NULL */
Xstrcat(string,"\0");
X
Xreturn(index);
X}
!EOR!
echo extracting src/obj_lib/wt_obj.c
echo mkdir ./src
mkdir ./src
echo mkdir ./src/obj_lib
mkdir ./src/obj_lib
sed 's/^X//' > src/obj_lib/wt_obj.c << '!EOR!' 
X/*
X
Xfunction: wt_obj()
X
Xdescription: writes a Wavefront ".obj" ASCII object description file from
X    a data structure in core.
X    Has been modified to include graphical 'meta-elements' circle,
X    sphere and user-defined object meta-elements.
X
Xinputs: outfildes -- file descriptor of file opened for writing.
X    wtobj    -- pointer to structure containing object description.
X
Xreturns: none
X
Xauthor: Stewart Dickson
X*/
X
X#include <time.h>
X#include <stdio.h>
X#include <topology.h>
X
X
X
Xvoid wt_obj(outfildes,wtobj)
XFILE *outfildes;
Xstruct topology *wtobj;
X{
Xextern int verbflg;
X
Xchar date[30];
Xint lcount=0;
Xshort lvcnt=0;
Xint fcount=0;
Xshort fvcnt=0;
Xint vcount=1,tvcount=1,pcount=0;
Xshort pvcnt=0;
Xint circnt=0,sphcnt=0,bicuct=0;
Xshort libcnt,calcnt;
Xint row,col,u_res = 4,v_res = 4;
Xshort grpindx=0,bindx=0,sindx=(-1),mtlindx=(-1),mapindx=(-1);
Xlong secs,time();
X
Xif(outfildes==NULL) {
X    fprintf(stderr,"wt_obj: ERROR - NULL file pointer received\n");
X    exit();
X    }
X
Xif(wtobj==NULL) {
X    fprintf(stderr,"wt_obj: ERROR - NULL object pointer received\n");
X    exit();
X    }
X
Xfprintf(stderr,"wt_obj: writing object '%s'\n",wtobj->size.objname);    
X
Xif(verbflg>1) {
X    fprintf(stderr,"wt_obj: writing identification message\n");
X    }
X
X/* output object identification message */
X
Xsecs=time((long *)0);
Xstrcpy(date,asctime(localtime(&secs))); 
X
Xfprintf(outfildes,
X    "\# %s %s\n",wtobj->size.objname,date);
Xfprintf(outfildes,
X    "\# This is a Stewart Dickson object description file\n");
Xfprintf(outfildes,
X    "\# made from a Stewart Dickson object-generating program.\n");
Xfprintf(outfildes,
X    "\# It may contain 'meta-elements' which must be expanded\n");
Xfprintf(outfildes,
X    "\# to be compatible with Wavefront Technologies software.\n\#\n\#\n");
X
X/* output "mtllib/maplib" directives */
X
Xif(verbflg>1) {
X    fprintf(stderr,"wt_obj: writing %d 'mtllib/maplib' directives\n",
X        wtobj->size.nolibs);
X    }
X
Xfor(libcnt=0;libcnt<wtobj->size.nolibs;libcnt++) {
X    if(verbflg>10) {
X        fprintf(stderr,"%s\n",wtobj->lib[libcnt]->libnam);
X        }
X
X    fprintf(outfildes,"%s\n",wtobj->lib[libcnt]->libnam);
X    }
X
X/* output "call" directives */
X
Xif(verbflg>1) {
X    fprintf(stderr,"wt_obj: writing %d 'call' directives\n",
X        wtobj->size.nocalls);
X    }
X
Xfor(calcnt=0;calcnt<wtobj->size.nocalls;calcnt++) {
X    if(verbflg>10) {
X        fprintf(stderr,"%s\n",wtobj->call[calcnt]->filnam);
X        }
X
X    fprintf(outfildes,"%s\n\n",wtobj->call[calcnt]->filnam);
X    }
X
X/* output vertices */
X
Xif(verbflg>1) {
X    fprintf(stderr,"wt_obj: writing %d vertices\n",wtobj->size.noverts - 1);
X    }
X
Xfprintf(outfildes,"\n! vertices %d\n",wtobj->size.noverts);
Xfor(vcount=1;vcount<wtobj->size.noverts;vcount++) {
X    if(verbflg>10) {
X        fprintf(stderr,"wt_obj: vertex mtl = %d, current mtl = %d\n",
X            wtobj->vertex[vcount]->mtl,mtlindx);
X        fprintf(stderr,"v %3.6f %3.6f %3.6f # vertex %d\n",
X            wtobj->vertex[vcount]->x,
X            wtobj->vertex[vcount]->y,
X            wtobj->vertex[vcount]->z,vcount);
X        }
X    /* see if vertex material is current material */
X    if(wtobj->vertex[vcount]->mtl!=mtlindx) {
X        /* if not, change current mtl and ouput new "usemtl" */
X        mtlindx=wtobj->vertex[vcount]->mtl;
X        if(!strcmp(wtobj->mtl[mtlindx]->mtlnam,"# no materials used")) {
X            if(verbflg>10) {
X                fprintf(stderr,"%s\n",wtobj->mtl[mtlindx]->mtlnam);
X                }
X            fprintf(outfildes,"%s\n",wtobj->mtl[mtlindx]->mtlnam);
X            }
X        else {
X            if(verbflg>10) {
X                fprintf(stderr,"usemtl %s\n",wtobj->mtl[mtlindx]->mtlnam);
X                }
X            fprintf(outfildes,"usemtl %s\n",wtobj->mtl[mtlindx]->mtlnam);
X            }
X        }
X    fprintf(outfildes,"v %3.6f %3.6f %3.6f\n",
X        wtobj->vertex[vcount]->x,
X        wtobj->vertex[vcount]->y,
X        wtobj->vertex[vcount]->z);
X    }
Xfprintf(outfildes,"\n\# %d vertices\n\n",wtobj->size.noverts - 1);
X
X/* output texture vertices */
X
Xif(verbflg>1) {
X    fprintf(stderr,"wt_obj: writing %d texture vertices\n",
X        wtobj->size.notverts - 1);
X    }
X
Xfprintf(outfildes,"\n! tverts %d\n",wtobj->size.notverts);
Xfor(tvcount=1;tvcount<wtobj->size.notverts;tvcount++) {
X    fprintf(outfildes,"vt %3.6f %3.6f %3.6f\n",
X        wtobj->texver[tvcount]->u,
X        wtobj->texver[tvcount]->v,
X        wtobj->texver[tvcount]->w);
X    }
Xfprintf(outfildes,"\n\# %d texture vertices\n\n",wtobj->size.notverts - 1);
X
X
X
X/* output lines */
X
Xif(verbflg>1) {
X    fprintf(stderr,"wt_obj: writing %d lines\n",wtobj->size.nolines);
X    }
X
Xfprintf(outfildes,"\n! lverts %d\n",wtobj->size.nolverts);
Xfprintf(outfildes,"\n! lines %d\n",wtobj->size.nolines);
Xfor(lcount=0;lcount<wtobj->size.nolines;lcount++) {
X    /* don't output a line with less than two vertices */
X    if(wtobj->line[lcount]->vertc>1) {
X        /* see if line group is current group */
X        if(wtobj->line[lcount]->group!=grpindx) {
X            /* if not, change current group and ouput new group */
X            grpindx=wtobj->line[lcount]->group;
X            if(verbflg>9) {
X                fprintf(stderr, "g %s\n",wtobj->group[grpindx]->grpnam);    
X                }
X            fprintf(outfildes, "g %s\n",wtobj->group[grpindx]->grpnam);
X            }
X        /* see if line material is current material */
X        if(wtobj->line[lcount]->mtl!=mtlindx) {
X            /* if not, change current mtl and ouput new "usemtl" */
X            mtlindx=wtobj->line[lcount]->mtl;
X            if(!strcmp(wtobj->mtl[mtlindx]->mtlnam,"# no materials used")) {
X                if(verbflg>9) {
X                    fprintf(stderr, "%s\n",wtobj->mtl[mtlindx]->mtlnam);    
X                    }
X                fprintf(outfildes,"%s\n",wtobj->mtl[mtlindx]->mtlnam);
X                }
X            else {
X                if(verbflg>9) {
X                    fprintf(stderr,
X                        "usemtl %s\n",wtobj->mtl[mtlindx]->mtlnam);    
X                    }
X                fprintf(outfildes,"usemtl %s\n",wtobj->mtl[mtlindx]->mtlnam);
X                }
X            }
X        fprintf(outfildes,"l");
X        for(lvcnt=0;lvcnt<wtobj->line[lcount]->vertc;lvcnt++) {
X            fprintf(outfildes," %d", wtobj->line[lcount]->vertno[lvcnt]);
X            }
X        fprintf(outfildes,"\n");
X        }
X    }
X
X/* output meta-elements of type 'circle' */
X
Xif(verbflg>1) {
X    fprintf(stderr,"wt_obj: writing %d meta-elements of type 'circle'\n",
X        wtobj->size.nocircs);
X    }
X
Xfprintf(outfildes,"\n! circles %d\n",wtobj->size.nocircs);
Xfor(circnt=0;circnt<wtobj->size.nocircs;circnt++) {
X    /* see if circle group is current group */
X    if(wtobj->circl[circnt]->group!=grpindx) {
X        /* if not, change current group and ouput new group */
X        grpindx=wtobj->circl[circnt]->group;
X        if(verbflg>9) {
X            fprintf(stderr,
X                "g %s\n",wtobj->group[grpindx]->grpnam);    
X            }
X        fprintf(outfildes,
X            "g %s\n",wtobj->group[grpindx]->grpnam);
X        }
X    fprintf(outfildes,"*c %d %3.6f %d\n",
X        wtobj->circl[circnt]->vertno,
X        wtobj->circl[circnt]->rad,
X        wtobj->circl[circnt]->res);
X    }
X
Xfprintf(outfildes,"\n\# %d circles\n",wtobj->size.nocircs);
X
X/* output points */
X
Xif(verbflg>1) {
X    fprintf(stderr,"wt_obj: writing %d points\n",wtobj->size.nopoints);
X    }
X
Xfprintf(outfildes,"\n! pverts %d\n",wtobj->size.nopverts);
Xfprintf(outfildes,"\n! points %d\n",wtobj->size.nopoints);
Xfor(pcount=0;pcount<wtobj->size.nopoints;pcount++) {
X    /* don't output a point with less than one vertex */
X    if(wtobj->point[pcount]->vertc>0) {
X        /* see if point group is current group */
X        if(wtobj->point[pcount]->group!=grpindx) {
X            /* if not, change current group and ouput new group */
X            grpindx=wtobj->point[pcount]->group;
X            if(verbflg>9) {
X                fprintf(stderr, "g %s\n",wtobj->group[grpindx]->grpnam);    
X                }
X            fprintf(outfildes, "g %s\n",wtobj->group[grpindx]->grpnam);
X            }
X        if(verbflg>9) {
X            fprintf(stderr,"point %d: p",pcount);
X            }
X        fprintf(outfildes,"p");
X        for(pvcnt=0;pvcnt<wtobj->point[pcount]->vertc;pvcnt++) {
X            if(verbflg>9) {
X                fprintf(stderr," %d",
X                    wtobj->point[pcount]->vertno[pvcnt]);
X                }
X            fprintf(outfildes," %d",
X                wtobj->point[pcount]->vertno[pvcnt]);
X            }
X        if(verbflg>9) {
X            fprintf(stderr,"\n");
X            }
X        fprintf(outfildes,"\n");
X        }
X    }
X
Xfprintf(outfildes,"\n\# %d points\n",wtobj->size.nopoints);
X
X/* output faces */
X
Xif(verbflg>1) {
X    fprintf(stderr,"wt_obj: writing %d faces\n",wtobj->size.nofaces);
X    }
X
Xfprintf(outfildes,"\n! fverts %d\n",wtobj->size.nofverts);
Xfprintf(outfildes,"\n! faces %d\n",wtobj->size.nofaces);
Xfor(fcount=0;fcount<wtobj->size.nofaces;fcount++) {
X    if(verbflg>9) {
X        fprintf(stderr,
X            "wt_obj: face %d, %d vertices\n",
X            fcount,wtobj->face[fcount]->vertc);
X        }
X    /* don't output a face with less than three vertices */
X    if(wtobj->face[fcount]->vertc>2) {
X        /* see if face group is current group */
X        if(wtobj->face[fcount]->group!=grpindx) {
X            /* if not, change current group and ouput new group */
X            grpindx=wtobj->face[fcount]->group;
X            if(verbflg>9) {
X                fprintf(stderr, "g %s\n",wtobj->group[grpindx]->grpnam);    
X                }
X            fprintf(outfildes, "g %s\n",wtobj->group[grpindx]->grpnam);
X            }
X        /* see if face smoothing group is current smoothing group */
X        if(wtobj->face[fcount]->smooth!=sindx) {
X            /* if not, change current smoothing group */
X            sindx=wtobj->face[fcount]->smooth;
X            /* and output smoothing directive */
X            if(sindx<=(-1)) {
X                if(verbflg>9) {
X                    fprintf(stderr,"s off\n");
X                    }
X                fprintf(outfildes,"s off\n");
X                }
X            else {
X                if(verbflg>9) {
X                    fprintf(stderr,"s %d\n",
X                        wtobj->face[fcount]->smooth);
X                    }
X                fprintf(outfildes,"s %d\n",
X                    wtobj->face[fcount]->smooth);
X                }
X            }
X        /* see if face bevel interp state is same as current state */