home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright 1991, 1992, 1993, 1994, Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
- * the contents of this file may not be disclosed to third parties, copied or
- * duplicated in any form, in whole or in part, without the prior written
- * permission of Silicon Graphics, Inc.
- *
- * RESTRICTED RIGHTS LEGEND:
- * Use, duplication or disclosure by the Government is subject to restrictions
- * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
- * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
- * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
- * rights reserved under the Copyright Laws of the United States.
- */
- /*
- bintoglob.c - Spin 3D object file format to glo_object file format
- converter.
-
- Tim Heidmann, Silicon Graphics
- June 26, 1991
- */
- #include <stdio.h>
- #include "fastobj.h"
- #include "glo_obj.h"
- #include "vect.h"
- #define TRUE 1
- #define FALSE 0
-
- void
- NoDups(glo_ObjPtr theObj, int nList, int nTriplets);
- int
- NoDegen(glo_ObjPtr theObj, int nList, int nTriplets);
-
- main(int argc, char *argv[]) {
- fastobj *myFObj;
- glo_ObjPtr myGLObj;
- int nTriplets, nQuads, nList, i, j, k, iTriplet;
- int *pList;
- float *pData;
- char *inFile, *outFile;
- int flipOrder;
-
- if (argc == 3) {
- flipOrder = FALSE;
- inFile = argv[1]; outFile = argv[2];
- } else if (argc == 4 && argv[1][0] == '-' && argv[1][1] == 'f') {
- flipOrder = TRUE;
- inFile = argv[2]; outFile = argv[3];
- } else {
- fprintf(stderr, "usage: %s [-f] <infile.bin> <outfile.glo>\n", argv[0]);
- exit(1);
- }
-
- /* Read a .bin file */
- myFObj = readfastobj(inFile);
- printf("%s: %d points (%d polygons)\n", inFile,
- myFObj->npoints, myFObj->npoints/4);
-
- /* Convert fastobj structure to glo_object */
- nTriplets = myFObj->npoints*2;
- nQuads = myFObj->npoints/4;
- if (myFObj->colors)
- /* Color per vertex. Ignore colors. */
- nList = 1 + (2 + 4) * nQuads + 1;
- else
- /* Normal per vertex. Use them. */
- nList = 1 + (2 + 4 + 4) * nQuads + 1;
-
- myGLObj = (glo_ObjPtr) malloc(sizeof(glo_ObjTyp));
- myGLObj->list = (int *) malloc(sizeof(int)*nList);
- myGLObj->t = (float (*)[3]) malloc(sizeof(float) * 3 * nTriplets);
-
- /* March through fastobj data, copying to vertex and command list */
- pList = myGLObj->list;
- pData = (float *) myFObj->data;
- iTriplet = 0;
- if (!myFObj->colors) {
- /* Normal per vertex, keep it all */
- printf("Normal per vertex\n");
- *pList++ = NPERV;
- for (i=0; i<nQuads; i++) {
- *pList++ = BGNPOLY;
- for (j=0; j<4; j++) {
- /* Normal */
- for (k=0; k<3; k++)
- myGLObj->t[iTriplet][k] = *pData++;
- pData++; /* fastobj keeps points as float[4]'s */
- pList[2 * (flipOrder ? 3-j : j)] = iTriplet++;
-
- /* Vertex */
- for (k=0; k<3; k++)
- myGLObj->t[iTriplet][k] = *pData++;
- pData++; /* fastobj keeps points as float[4]'s */
- pList[2 * (flipOrder ? 3-j : j) + 1] = iTriplet++;
- }
- pList += 8;
- *pList++ = ENDPOLY;
- }
- *pList++ = ENDLIST;
- } else {
- /* Ignore color per vertex info */
- printf("Color per vertex\n");
- *pList++ = NONORM;
- for (i=0; i<nQuads; i++) {
- *pList++ = BGNPOLY;
- for (j=0; j<4; j++) {
- pData += 4; /* Skip over color info */
-
- for (k=0; k<3; k++)
- myGLObj->t[iTriplet][k] = *pData++;
- pData++;
- pList[flipOrder ? 3-j : j] = iTriplet++;
- }
- pList += 4;
- *pList++ = ENDPOLY;
- }
- *pList++ = ENDLIST;
- }
-
- /* Remove duplicate triplets, and degenerate points and polys */
- nTriplets = NoDupTrips(myGLObj, nList, nTriplets);
- nList = NoDegen(myGLObj, nList, nTriplets);
-
- /* Write the .glo file */
- glo_WriteObj(myGLObj, outFile);
- }
-
- #define MARGIN 0.0005
-
- int
- NoDupTrips(glo_ObjPtr theObj, int nList, int nTriplets) {
- /* Step through triplet list, eliminating duplicates. */
- int i, iTrip, iList, iCheck, nDuplicates;
- int *pList;
- short *tripletMap, *uniqueFlag;
- float (*pTrip)[3], (*pCheck)[3], (*pNew)[3], (*newT)[3];
-
- /* Keep a map of old triplet indices to indices into the list
- with the duplicate values removed.
- Also keep a flag for each triplet for if it's unique and gets kept. */
- tripletMap = (short *) malloc(sizeof(short) * nTriplets);
- uniqueFlag = (short *) malloc(sizeof(short) * nTriplets);
-
- /* Check for duplicate triplets. Remember a mapping for each one */
- nDuplicates = 0;
- for (iTrip=0, pTrip=theObj->t; iTrip<nTriplets; iTrip++, pTrip++) {
- tripletMap[iTrip] = iTrip - nDuplicates;
- uniqueFlag[iTrip] = TRUE;
- for (iCheck=0, pCheck=theObj->t; iCheck<iTrip; iCheck++, pCheck++)
- if (fabs((*pTrip)[0] - (*pCheck)[0]) < MARGIN &&
- fabs((*pTrip)[1] - (*pCheck)[1]) < MARGIN &&
- fabs((*pTrip)[2] - (*pCheck)[2]) < MARGIN) {
- tripletMap[iTrip] = tripletMap[iCheck];
- uniqueFlag[iTrip] = FALSE;
- nDuplicates++;
- break;
- }
- }
-
- /* Condense the triplet list, keeping only unique values. */
- for (iTrip=0; iTrip<nTriplets && uniqueFlag[iTrip]; iTrip++) ;
- for (pNew = pTrip = theObj->t+iTrip; iTrip<nTriplets; iTrip++, pTrip++)
- if (uniqueFlag[iTrip]) {
- for (i=0; i<3; i++)
- (*pNew)[i] = (*pTrip)[i];
- pNew++;
- }
-
- /* Now reset indices in the list to point at the unique triplet */
- for (iList=0, pList=theObj->list; iList<nList; iList++, pList++)
- if (*pList >= 0) *pList = tripletMap[*pList];
-
- /* Finally, free working memory and return. */
- free(tripletMap);
- free(uniqueFlag);
- printf("%d duplicate triplets (out of %d)\n", nDuplicates, nTriplets);
- return nTriplets - nDuplicates;
- }
-
- int
- NoDegen(glo_ObjPtr theObj, int nList, int nTriplets) {
- /* Find and eliminate degenerate polygons and polygon edges */
- int nVertices, nDest, nThisDegenV, nDegenV, nDegenP;
- int done, leadingNormal, pervNormal;
- int firstVertex, firstNormal, lastVertex, lastNormal, thisVertex;
- int *pStart, *pDest, *pList;
-
- nDegenV = 0;
- nDegenP = 0;
- nDest = 0;
- for (done = FALSE, pDest = pList = theObj->list;; ) {
-
- /* Find the next element, copying commands, following mode changes */
- for (;*pList < 0; *pDest++ = *pList++) {
- nDest++;
- switch (*pList) {
- case NONORM: leadingNormal = FALSE; pervNormal = FALSE; break;
- case NPERV: leadingNormal = FALSE; pervNormal = TRUE ; break;
- case NPERP: leadingNormal = TRUE ; pervNormal = FALSE; break;
- case ENDLIST: done = TRUE; break;
- default: ;
- }
- }
- if (done) break;
-
- /* Remember start in case we need to undo this poly */
- pStart = pDest;
-
- /* Look at the first vertex */
- if (leadingNormal) *pDest++ = *pList++;
- if (pervNormal) firstNormal = lastNormal = *pList++;
- firstVertex = lastVertex = *pList++;
-
- /* Add each successive vertex, checking against the previous one */
- nVertices = 0;
- nThisDegenV = 0;
- while (*pList >= 0) {
- /* More vertices to check */
- if (pervNormal) {
- if (pList[1] != lastVertex) {
- *pDest++ = lastNormal;
- *pDest++ = lastVertex;
- lastNormal = *pList++;
- lastVertex = *pList++;
- nVertices++;
- }
- else {
- pList += 2;
- nThisDegenV++;
- }
- } else {
- if (pList[0] != lastVertex) {
- *pDest++ = lastVertex;
- lastVertex = *pList++;
- nVertices++;
- }
- else {
- pList++;
- nThisDegenV++;
- }
- }
- }
-
- /* That was the last vertex. Check against first before adding. */
- if (pervNormal) {
- if (lastVertex != firstVertex) {
- *pDest++ = lastNormal;
- *pDest++ = lastVertex;
- nVertices++;
- }
- else nThisDegenV++;
- } else {
- if (lastVertex != firstVertex) {
- *pDest++ = lastVertex;
- nVertices++;
- }
- else nThisDegenV++;
- }
-
- /* Check for and delete degenerate polygons */
- if (nVertices<3) {
- pDest = pStart - 1; /* Go back to before the BGN... */
- nDest--;
- pList++; /* And swallow the following END... */
- nDegenP++;
- }
- else {
- /* Good polygon, add to the tally */
- nDest += leadingNormal?1:0 + pervNormal?2*nVertices:nVertices;
- nDegenV += nThisDegenV;
- }
- }
-
- printf("%d degenerate vertices, %d degenerate polygons removed.\n",
- nDegenV, nDegenP);
- return nDest;
- }
-