/************************************************************************** * * Any use of this code or of the ideas it embodies should be acknowledged * in writing in all publications describing the resulting product or * research contribution as follows: "This solution is based on the * Edgebreaker compression technique and software developed by Prof. * Rossignac and his colleagues at Georgia Institute of Technology." * * * Software developed by: Alla Safonova at Georgia Tech * Last modified: 05/11/20001 * **************************************************************************/ //Include #include #include #include #include #include /***************************** Types *************************************/ struct Coord3D { float x; float y; float z; }; typedef Coord3D Vertex; typedef Coord3D Vector; #define MAX_SIZE 256 enum MeshType {MANIFOLD, TPATCH}; enum FileFormat {BINARY, ASKII}; void initCompression(int c, MeshType eMeshType); void Compress(int c); void CheckHandle(int c); void EncodeDelta(int c); /***************************** Variables *********************************/ //Input arguments static char sOVTable[MAX_SIZE]; static MeshType eMeshType = MANIFOLD; static FileFormat eFileFormat = ASKII; static int nStartCorner = 0; //File Output static FILE* fclers = NULL; //clers file (See File Formats for detais) static FILE* fvertices = NULL; //vertices (See File Formats for detais) static FILE* fhandles = NULL; //handles pairs (See File Formats for detais) //Variables for storing Input OVTable and geometry static int* O = NULL; //Input Opposite table static int* V = NULL; //Input Vertex indices table static Vertex* G = NULL; //Input Geometry table static Vertex* G_est = NULL; //Input Geometry table //Compression variables static int T = 0; //triangles count static int N = 0; //vertices count static int *M = NULL; //Vetex marking array static int *U = NULL; //Triangles marking array /****************************** Main Block *******************************/ void ClearMemoryAndFiles() { //close files if (fclers != NULL) fclose(fclers); if (fvertices != NULL) fclose(fvertices); if (fhandles != NULL) fclose(fhandles); //disallocate memory if (O != NULL) delete [] O; if (V != NULL) delete [] V; if (G != NULL) delete [] G; if (U != NULL) delete [] U; if (M != NULL) delete [] M; } //Print Error string and exit. void PrintErrorAndQuit(char* sErrorString) { printf(sErrorString); ClearMemoryAndFiles(); exit(0); } void ProcessArguments(int argc, char* argv[]) { if (argc != 5) { printf("Wrong number of agruments.\n\n" "Usage: EBCompression OVTable MeshType FileFormat\n\n"); exit(0); } char sMeshType[MAX_SIZE]; char sFileFormat[MAX_SIZE]; char sStartCorner[MAX_SIZE]; strcpy(sOVTable, argv[1]); strcpy(sMeshType, argv[2]); strcpy(sStartCorner, argv[3]); strcpy(sFileFormat, argv[4]); //get mesh type if (strcmp("MANIFOLD", sMeshType)==0) { eMeshType = MANIFOLD; printf("MeshType - MANIFOLD\n"); } else if (strcmp("TPATCH", sMeshType)==0) { eMeshType = TPATCH; printf("MeshType - TPATCH\n"); } else PrintErrorAndQuit("Not supported mesh type\n"); //get start corner nStartCorner = atoi(sStartCorner); //get output file format if (strcmp("BINARY", sFileFormat)==0) { eFileFormat = BINARY; printf("FileFormat - BINARY\n"); } else if (strcmp("ASKII", sFileFormat)==0) { eFileFormat = ASKII; printf("FileFormat - ASKII\n"); } else PrintErrorAndQuit("Not supported file format\n"); } //Open filr for storing clers, geometry and handles void OpenOutputFiles() { fclers = fopen("clers.txt", "w+t"); if (fclers == NULL) PrintErrorAndQuit("Can not open clers file\n"); fvertices = fopen("vertices.txt", "w+t"); if (fvertices == NULL) PrintErrorAndQuit("Can not open vertices file\n"); fhandles = fopen("handles.txt", "w+t"); if (fhandles == NULL) PrintErrorAndQuit("Can not open handles file\n"); } //Process input file and build Vertex and Triangle Arrays. void ProcessInputFile(char* sFileName) { int i = 0; FILE* pInFile = NULL; //Number of Triangles int nNumOfTriangles; //Number of Vertices int nNumOfVertices; //Open the file. pInFile = fopen(sFileName, "rt"); if (pInFile == NULL) PrintErrorAndQuit("Can not open input file\n"); //Read number of triangles from the file if (fscanf(pInFile, "%d", &nNumOfTriangles) == -1) PrintErrorAndQuit("Error reading file\n"); //Allocate memory for V Table V = new int [nNumOfTriangles*3]; //Allocate memory for O Table O = new int [nNumOfTriangles*3]; //Read VO TAble from the file for (i = 0; i 0) { //test whether left triangle was visited if (U[E2T(LeftTri(c, O))] > 0) { //append code for E and pop fprintf(fclers, "%c\n", 'E'); return; } else { //append code for R, move to left triangle fprintf(fclers, "%c\n", 'R'); c = LeftTri(c, O); } } else //test whether left triangle was visited if (U[E2T(LeftTri(c, O))] > 0) { //append code for L, move to right triangle fprintf(fclers, "%c\n", 'L'); c = RightTri(c, O); } else { //store corner number in decompression, to support handles U[E2T(c)] = T*3+2; //append code for S fprintf(fclers, "%c\n", 'S'); //recursive call to visit right branch first Compress(RightTri(c, O)); //move to left triangle c = LeftTri(c, O); //if the triangle to the left was visited, then return if (U[E2T(c)]>0) return; } }while(true); } void CheckHandle(int c) { //check for handles from the right if (U[E2T(O[NextEdge(c)])] >1) { //write opposite corners for handle triangles into file fprintf(fhandles, "%d %d\n", U[E2T(O[NextEdge(c)])], T*3+1); } //check for handles from the left if (U[E2T(O[PrevEdge(c)])] >1) { //write opposite corners for handle triangles into file fprintf(fhandles, "%d %d\n", U[E2T(O[PrevEdge(c)])], T*3+2); } } /******************* Vector Operations for Estimate functions ************/ //Returns v1 - v2 Vector VMinus(Vertex v1, Vertex v2) { Vector tempVector; tempVector.x = v1.x - v2.x; tempVector.y = v1.y - v2.y; tempVector.z = v1.z - v2.z; return tempVector; } //Returns v1 + v2 Vector VPlus(Vertex v1, Vector v2) { Vector tempVector; tempVector.x = v2.x + v1.x; tempVector.y = v2.y + v1.y; tempVector.z = v2.z + v1.z; return tempVector; } //Returns v1*k Vector VMult(Vertex v1, float k) { Vector tempVector; tempVector.x = v1.x*k; tempVector.y = v1.y*k; tempVector.z = v1.z*k; return tempVector; } /***************************** Estimate functions ************************/ /* * This function does not do any prediction, it just writes vertices into array */ void EncodeNoPrediction(int c) { //Store vertex coordinates into file fprintf(fvertices, "%f %f %f\n", G[V[c]].x, G[V[c]].y, G[V[c]].z); } void EncodeWithPrediction(int c) { Vector vPred, delta; Vertex zeroV = {0.0, 0.0, 0.0}; if (M[V[O[c]]] > 0 && M[V[PrevEdge(c)]] > 0) { vPred = VPlus(G_est[V[NextEdge(c)]], G_est[V[PrevEdge(c)]]); vPred = VMinus(vPred, G_est[V[O[c]]]); delta = VMinus(G[V[c]], vPred); //return vPred; } else if (M[V[O[c]]] > 0) { vPred = VMult(G_est[V[NextEdge(c)]], 2); vPred = VMinus(vPred, G_est[V[O[c]]]); delta = VMinus(G[V[c]], vPred); //return vPred; } else if (M[V[NextEdge(c)]] > 0 && M[V[PrevEdge(c)]] > 0) { vPred = VPlus(G_est[V[NextEdge(c)]], G_est[V[PrevEdge(c)]]); vPred = VMult(vPred, 0.5f); delta = VMinus(G[V[c]], vPred); //return vPred; } else if (M[V[NextEdge(c)]] > 0) { vPred = G_est[V[NextEdge(c)]]; delta = VMinus(G[V[c]], vPred); //return vPred; } else if (M[V[PrevEdge(c)]] > 0) { vPred = G_est[V[PrevEdge(c)]]; delta = VMinus(G[V[c]], vPred); //return vPred; } else { vPred = zeroV; delta = VMinus(G[V[c]], vPred); } G_est[V[c]] = VPlus(delta, vPred); fprintf(fvertices, "%f %f %f\n", delta.x, delta.y, delta.z); } void EncodeDelta(int c) { EncodeNoPrediction(c); //EncodeWithPrediction(c); }