/************************************************************************** * * 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 #include using namespace std; /***************************** 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 initDecompression(); void DecompressConnectivity(int c); bool CheckHandle(int c); void Zip(int c); void DecompressVertices(int c); Vertex DecodeDelta(int c); /***************************** Variables *********************************/ //Input arguments static char sInputDirectory[MAX_SIZE]; static char sOutFileName[MAX_SIZE]; static MeshType eMeshType = MANIFOLD; static FileFormat eFileFormat = ASKII; //File Input 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 nNumOfTriangles; //Number of Triangles static int nNumOfVertices; //Number of Vertices static int* O = NULL; //Output Opposite table static int* V = NULL; //Output Vertex indices table static Vertex* G = NULL; //Output Geometry table //Compression variables static int T = 0; //triangles count static int N = 0; //vertices count static int I = 0; //number of triangles on first vertex static int A = 0; //handles count static int *M = NULL; //Vetex marking array static int *U = NULL; //Triangles marking array //Handle corners array static vector H; //Clers array static vector C; //Geometry array static vector G_in; /****************************** 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 != 4) { printf("Wrong number of agruments.\n\n" "EBDecompression InputFileDir OutFileName FileFormat\n\n"); exit(0); } strcpy(sInputDirectory, argv[1]); strcpy(sOutFileName, argv[2]); char sFileFormat[MAX_SIZE]; strcpy(sFileFormat, argv[3]); //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 OpenInputFiles() { char sTempStr[MAX_SIZE]; strcpy(sTempStr, sInputDirectory); strcat(sTempStr, "\\"); strcat(sTempStr, "clers.txt"); fclers = fopen(sTempStr, "rt"); if (fclers == NULL) PrintErrorAndQuit("Can not open clers file\n"); strcpy(sTempStr, sInputDirectory); strcat(sTempStr, "\\"); strcat(sTempStr, "vertices.txt"); fvertices = fopen(sTempStr, "rt"); if (fvertices == NULL) PrintErrorAndQuit("Can not open vertices file\n"); strcpy(sTempStr, sInputDirectory); strcat(sTempStr, "\\"); strcat(sTempStr, "handles.txt"); fhandles = fopen(sTempStr, "rt"); if (fhandles == NULL) PrintErrorAndQuit("Can not open handles file\n"); } //Write OV TAble. void WriteVOTableFile(char* sFileName) { int i = 0; int nNumOfTriangles = C.size() + 1; int nNumOfVertices = G_in.size(); FILE* pOutFile = fopen(sFileName, "w+t"); if (pOutFile == NULL) PrintErrorAndQuit("Can not open output file\n"); //Write the number of vertices to the file if (!fprintf(pOutFile, "%d\n", nNumOfTriangles)) PrintErrorAndQuit("Error writing to the file\n"); //Write VO TAble from the file for (i = 0; i= 0) return; break; case 'E': //E: left and right edges are free O[c] = -2; O[NextEdge(c)] = -2; //check for handles on the right CheckHandle(c); //check for handles on the left, if non, try to zip if (!CheckHandle(NextEdge(c))) Zip(NextEdge(c)); //pop return; break; } }while(true); } bool CheckHandle(int c) { //check if this is a handle //if (A < H.size() && c == H[A+1]) if (A >= H.size() || c != H[A+1]) return false; else { //link opposite corners O[c] = H[A]; O[H[A]] = c; //find corner of next free edge if any int a = PrevEdge(c); while( (O[a] >=0) && (a != H[A]) ) a = PrevEdge(O[a]); //zip if found cw edge if (O[a] == -2) Zip(a); //find corner of next free edge if any a = PrevEdge(O[c]); while( (O[a] >=0) && (a != c) ) a = PrevEdge(O[a]); //zip if found cw edge if (O[a] == -2) Zip(a); //next handle A+=2; return true; } } void Zip(int c) { //tries to zip free edges opposite c int b = NextEdge(c); //search clockwise for free edge while(O[b] >= 0 && O[b] != c) { b = NextEdge(O[b]); } //pop if no zip possible if (O[b] != -1) { return; } //link opposite corners O[c] = b; O[b] = c; //assign co-incident corners int a = NextEdge(c); V[NextEdge(a)]=V[NextEdge(b)]; while(O[a]>=0 && a!=b) { a = NextEdge(O[a]); V[NextEdge(a)]=V[NextEdge(b)]; } //find corner of next free edge on right c=PrevEdge(c); while(O[c] >=0 && c!= b) { c=PrevEdge(O[c]); } //try to zip again if (O[c] == -2) Zip(c); } void DecompressVertices(int c) { //start traversal for triangle tree do { //mark the triangle as visited U[E2T(c)] = 1; //test whether tip vertex was visited if (M[V[c]] == 0) { //update new vertex N++; G[N] = DecodeDelta(c); //mark tip vertex as visited M[V[c]] = 1; //continue with the right neighbor c = RightTri(c, O); } else //test whether right triangle was visited if (U[E2T(RightTri(c, O))] == 1) { //test whether left triangle was visited if (U[E2T(LeftTri(c, O))] == 1) { //E, pop return; } else { //R,move to left triangle c = LeftTri(c, O); } } else //test whether left triangle was visited if (U[E2T(LeftTri(c, O))] == 1) { //L, move to right triangle c = RightTri(c, O); } else { //S, recursive call to visit right branch first DecompressVertices(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); } /******************* 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 assume vertices was not encoded using any prediction * It just reads the next vertex */ Vertex DecodeNoPrediction(int c) { return G_in[V[c]]; } Vertex DecodeWithPrediction(int c) { static int EBVcount = 0; Vertex vPred; Vector delta = G_in[EBVcount]; EBVcount++; if (M[V[O[c]]] > 0 && M[V[PrevEdge(c)]] > 0) { vPred = VPlus(G[V[NextEdge(c)]], G[V[PrevEdge(c)]]); vPred = VMinus(vPred, G[V[O[c]]]); vPred = VPlus(delta, vPred); return vPred; } if (M[V[O[c]]] > 0) { vPred = VMult(G[V[NextEdge(c)]], 2); vPred = VMinus(vPred, G[V[O[c]]]); vPred = VPlus(delta, vPred); return vPred; } if (M[V[NextEdge(c)]] > 0 && M[V[PrevEdge(c)]] > 0) { vPred = VPlus(G[V[NextEdge(c)]], G[V[PrevEdge(c)]]); vPred = VMult(vPred, 0.5f); vPred = VPlus(delta, vPred); return vPred; } if (M[V[NextEdge(c)]] > 0) { vPred = G[V[NextEdge(c)]]; vPred = VPlus(delta, vPred); return vPred; } else if (M[V[PrevEdge(c)]] > 0) { vPred = G[V[PrevEdge(c)]]; vPred = VPlus(delta, vPred); return vPred; } else { vPred = delta; return vPred; } } Vertex DecodeDelta(int c) { return DecodeNoPrediction(c); //return DecodeWithPrediction(c); }