123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606 |
- #include <vector>
- #include "loadModel.h"
- #include "vec3.h"
- #include <stdio.h>
- #include <string.h>
- #include <errno.h>
- #include <stdlib.h>
- bool loadOBJ( const char *path, std::vector<vec3> &out_vertices, vec3 *bound,
- unsigned char mirror)
- {
- //Open file
- FILE *file = fopen(path, "r");
- //Failed to open file
- if (!file)
- {
- printf("Error opening file: %s\n", path);
- return false;
- }
- //Vector for vertices - Here will be saved all vertices by index (from file)
- std::vector<vec3> temp_vertices;
- //Buffer
- char lineHeader[100];
- //Read each word
- while (fscanf(file, "%s", lineHeader) != EOF)
- {
- //Found comment
- if ( lineHeader[0] == '#' )
- //Skip line
- fscanf(file, "%*[^\n]"); else
- //Found vertex
- if ( lineHeader[0] == 'v' )
- {
- //Create new vertex and get it's coordinates
- vec3 vertex;
- fscanf(file, "%f %f %f", &vertex.x, &vertex.y, &vertex.z);
- //Apply mirroring (if exists)
- if ( mirror == 1 )
- vertex.x = -vertex.x;
- if ( mirror == 2 )
- vertex.y = -vertex.y;
- if ( mirror == 4 )
- vertex.z = -vertex.z;
- //Save to vertices by index
- temp_vertices.push_back(vertex);
- //vec3 is passes for bound
- if (bound)
- {
- //This saves bound from center to positive axis
- // it isn't the best way, but for now it works
- if (bound->x < vertex.x) bound->x = vertex.x;
- if (bound->y < vertex.y) bound->y = vertex.y;
- if (bound->z < vertex.z) bound->z = vertex.z;
- }
- } else
- //Found face
- if ( lineHeader[0] == 'f' )
- {
- //Check the next three numbers
- unsigned int j;
- for (j = 0; j < 3; j++)
- {
- //Get index to vertex (from temp_vertices)
- unsigned int index;
- fscanf(file, "%d", &index);
- //Push vertex to final array. -1 because indexes start from 1 in .obj
- out_vertices.push_back(temp_vertices[ index-1 ]);
- }
- }
- } //While loop
- //Close file
- fclose(file);
- //Success!
- return true;
- }
- /* Opens file, reads header,
- * parses vertices (3 floats - position, 3 bytes - color) and faces (triangles only).
- * Toy parser only, it doesn't support all .ply files (probably)
- */
- bool loadPLY(
- const char *path,
- std::vector<vec3> &out_vertices,
- std::vector<vec3> &out_color,
- vec3 *bound,
- unsigned char mirror
- )
- {
- //Open file
- FILE *file = fopen(path, "r");
- //Failed to open file
- if (!file)
- {
- printf("Error opening file: %s\n", path);
- return false;
- }
- //Vector for vertices - save vertices/colors by index (from file)
- std::vector<vec3> temp_vertices, temp_color;
- //How many vertices and faces to expect (from PLY header)
- unsigned int vertices = 0, faces = 0;
- //Read each line (limited to 100 chars - I should change that sometime)
- char lineHeader[100];
- //Read words until end of file or end of header
- while ( fscanf(file, "%s", lineHeader) != EOF
- && strcmp(lineHeader, "end_header") != 0 )
- {
- //Found comment - Skip line
- if ( strcmp(lineHeader, "comment") == 0 )
- fscanf(file, "%*[^\n]"); else
- //Found an element
- if ( strcmp(lineHeader, "element") == 0 )
- {
- //Get next word
- fscanf(file, "%s", lineHeader);
- //Found vertices - save number of vertices
- if ( strcmp(lineHeader, "vertex") == 0 )
- fscanf(file, "%d", &vertices); else
- //Found faces - save number of faces
- if ( strcmp(lineHeader, "face") == 0 )
- fscanf(file, "%d", &faces);
- }
- }
- //Read vertices
- unsigned int i;
- for (i = 0; i < vertices; i++)
- {
- //New vertex
- vec3 vertex;
- //RGB values (0-255)
- unsigned char r, g, b;
- //Read vertex and colors values
- fscanf(file, "%f %f %f %hhu %hhu %hhu",
- &vertex.x, &vertex.y, &vertex.z,
- &r, &g, &b);
- //Create color and convert 0-255 to 0.0-1.0
- vec3 color(r /255.0f, g /255.0f, b /255.0f);
- //Apply mirroring (if exists)
- if ( mirror == 1 )
- vertex.x = -vertex.x;
- if ( mirror == 2 )
- vertex.y = -vertex.y;
- if ( mirror == 4)
- vertex.z = -vertex.z;
- //Add new vertex and color to temporary vectors
- temp_vertices.push_back(vertex);
- temp_color .push_back(color );
- //Calculate boundbox (if exists)
- if (bound)
- {
- if (bound->x < vertex.x) bound->x = vertex.x;
- if (bound->y < vertex.y) bound->y = vertex.y;
- if (bound->z < vertex.z) bound->z = vertex.z;
- }
- }
- //For each face
- for (i = 0; i < faces; i++)
- {
- //Faces number
- int fn;
- fscanf(file, "%d", &fn);
- //Get all faces
- int temp[fn];
- int j;
- for (j = 0; j < fn; j++)
- fscanf(file, "%d", temp+j);
- //Apply first face
- out_vertices.push_back( temp_vertices[ temp[0] ]);
- out_vertices.push_back( temp_vertices[ temp[1] ]);
- out_vertices.push_back( temp_vertices[ temp[2] ]);
- if (&out_color)
- {
- out_color.push_back( temp_color[ temp[0] ]);
- out_color.push_back( temp_color[ temp[1] ]);
- out_color.push_back( temp_color[ temp[2] ]);
- }
- //For each extra face
- j = 2;
- while (j < fn-1)
- {
- //More than 1 extra vertices
- if (fn-1 -j > 1)
- {
- out_vertices.push_back( temp_vertices[ temp[j ] ]);
- out_vertices.push_back( temp_vertices[ temp[j+1] ]);
- out_vertices.push_back( temp_vertices[ temp[j+2] ]);
- if (&out_color)
- {
- out_color.push_back( temp_color[ temp[j ] ]);
- out_color.push_back( temp_color[ temp[j+1] ]);
- out_color.push_back( temp_color[ temp[j+2] ]);
- }
- }
- //Only 1 extra vertex - finish shape
- else
- {
- out_vertices.push_back( temp_vertices[ temp[j ] ]);
- out_vertices.push_back( temp_vertices[ temp[j+1] ]);
- out_vertices.push_back( temp_vertices[ temp[ 0 ] ]);
- if (&out_color)
- {
- out_color.push_back( temp_color[ temp[j ] ]);
- out_color.push_back( temp_color[ temp[j+1] ]);
- out_color.push_back( temp_color[ temp[ 0 ] ]);
- }
- }
-
- //Advance counter
- j += 2;
- }
- }
- //Close file
- fclose(file);
- //Success!
- return true;
- }
- // So far parses vertex xyz and colors rgb
- mesh_data *loadPly(const char *path, int flags)
- {
- //File
- FILE *f;
- if ( !(f = fopen(path, "r")) )
- {
- fprintf(stderr, "loadPly: failed to open file: %s: %s\n",
- path, strerror(errno));
- return 0;
- }
- //Buffer
- char *buff = (char*)malloc(sizeof(char) *100);
-
- //Data
- unsigned int vertices = 0, faces = 0;
- std::vector<property> vert_prop;
- unsigned char face_ind_form, vert_ind_form;
- //Struct to return
- mesh_data *obj = new mesh_data;
- /* Check ply magic number:
- * Get 3 first chars. (ignore anything on the rest of the line)
- * Add terminating byte.
- * Compare with "ply".
- */
- if ( fscanf(f, "%3c%*[^\n]%*1c", buff) == EOF )
- goto error;
- buff[3] = '\0';
- if ( strcmp(buff, "ply") != 0 )
- goto error;
- /* Check format
- * Get first word.
- * Compare with "format".
- * Get rest of line
- * Compare with "ascii 1.0" | "binary_little_endian 1.0"
- | "binary_big_endian 1.0"
- * Set `format` accordingly.
- */
- char format;
- if ( fscanf(f, "%s", buff) == EOF )
- goto error;
- //Check format
- if ( strcmp(buff, "format") == 0 )
- {
- //Get actual format
- if ( fscanf(f, "%*c%[^\n]", buff) == EOF)
- goto error;
- //Ascii
- if ( strcmp(buff, "ascii 1.0") == 0 )
- format = 'a'; else
- //Little endian
- if ( strcmp(buff, "binary_little_endian 1.0") == 0 )
- format = 'l'; else
- //Big endian
- if ( strcmp(buff, "binary_big_endian 1.0") == 0 )
- format = 'b';
- //Error
- else goto error;
- }
- else goto error;
- /* What this parser reads:
- * element vertex
- property x
- property y
- property z
- property red
- property green
- property blue
- * element face
- property vertex_indices
- */
- /* Get elements
- * Read word-by-word.
- * Compare with "element"
- * Read next word.
- * Compare with "vertex"
- * Read next word as number of vertices to expect.
- * Compare with "faces"
- * Read mext wprd as number of faces to expect.
- * Compare with "property"
- * Read next word.
- * Compare with "list"
- * Read next word.
- * Get type amount of values from it.
- * Read next word.
- * Get type of actual values from it.
- * Read next word.
- * Hope that it's "vertex_indices"
- * else
- * Get property type (int, float, etc.)
- * Read next word.
- * Compare with x/y/z - red/green/blue
- */
- //Read word by word
- while ( fscanf(f, "%s", buff) != EOF
- && strcmp(buff, "end_header") != 0 )
- {
- //Found an element
- if ( strcmp(buff, "element") == 0 )
- {
- //This parser only reads vertices and faces
- if ( fscanf(f, "%s", buff) == EOF )
- goto error;
- //Vertex
- if ( strcmp(buff, "vertex") == 0 )
- {
- //Get vertex number
- if ( fscanf(f, "%u", &vertices) == EOF )
- goto error;
- } else
- //Face
- if ( strcmp(buff, "face") == 0 )
- {
- if ( fscanf(f, "%u", &faces) == EOF )
- goto error;
- }
- //Unsupported element - ignore
- else continue;
- } else
- //Found property
- if ( strcmp(buff, "property") == 0 )
- {
- //Face's property
- /* if ( faces != 0 )
- {
- //Get property type
- if (fscanf(f, "%s", buff) == EOF)
- goto error;
- //Ignore anything that is not a list
- if (strcmp(buff, "list") != 0)
- {
- if (fscanf(f, "%*[^\n]") == EOF)
- goto error;
- continue;
- }
- //Get face indices and vertex indices formats
- if (fscanf(f, "%s", buff) == EOF) goto error;
- face_ind_form = form_to_num(buff);
- if (fscanf(f, "%s", buff) == EOF) goto error;
- vert_ind_form = form_to_num(buff);
- //Get flag
- if (fscanf(f, "%s", buff) == EOF)
- goto error;
- //Property was vertex_indices - stop looking
- if (strcmp(buff, "vertex_indices") == 0)
- break;
- //Skip line
- if (fscanf(f, "%[^\n]", buff) == EOF)
- goto error;
- } else*/
- //Vertex's property
- if ( vertices != 0 )
- {
- //Init property
- property pr;
- //Get format
- if ( fscanf(f, "%s", buff) == EOF )
- goto error;
- pr.format = form_to_num( buff );
- //Get flag
- if ( fscanf(f, "%s", buff) == EOF )
- goto error;
- pr.flag = flag_to_num( buff );
- //Add property to vertex properties
- vert_prop.push_back(pr);
- //Skip line
- if ( fscanf(f, "%*[^\n]") == EOF )
- goto error;
- }
- }
- //Ignore unknown line (including comments)
- else
- {
- if ( fscanf(f, "%[^\n]", buff) == EOF )
- {
- printf("Ignored: %s\n", buff);
- goto error;
- }
- }
- } //Finished header
- printf("Parser is going to search for:\n");
- for (int i = 0; i < vert_prop.size(); i++)
- {
- printf("%s (%s)\n", flagstr(vert_prop[i].flag), formatstr(vert_prop[i].format));
- }
-
- return NULL;
- if (true)
- {
- char test[100] = "something";
- void *p;
- if ( ( p = malloc( sizeof(void*) *vert_prop.size() ) ) == NULL)
- goto error;
- unsigned int j;
- for (j = 0; j < vert_prop.size(); j++)
- {
- switch (vert_prop[j].flag)
- {
- //case FLG_V_POS_X:
- // p[j] = &mesh_data.pos;
- }
- switch (vert_prop[j].format)
- {
- case PLY_CHAR:
- strcat(test, "%s");
- }
- }
- printf("Search string: %s\n", test);
- }
- //float *temp_vertices;
- //if (temp_vertices = malloc() == NULL)
- // goto error;
- //Print all data gatheres so far
- unsigned int i;
- for (i = 0; i < vert_prop.size(); i++)
- {
- printf("Vertex property: %d\n", i);
- printf("format: %d | flag: %d\n", vert_prop[i].format, vert_prop[i].flag);
- }
- printf("Face indices format: %d\n" , face_ind_form);
- printf("Vertex indices format: %d\n", vert_ind_form);
- //Close file
- fclose(f);
- return obj;
- //Error
- error:
- if (ferror(f))
- fprintf(stderr, "loadPly: error while parsing: %s: %s\n", path,
- strerror(errno)); else
- if (feof(f))
- printf("loadPly: unexpected end of file: %s\n", path);
- else
- printf("loadPly: unexpected error: %s\n", path);
- fclose(f);
- return 0;
- }
- //Turns the read format to a number (specified by defines on loadModel.h)
- unsigned char form_to_num( char *format )
- {
- if (strcmp(format, "char") == 0
- || strcmp(format, "int8") == 0 )
- return PLY_CHAR;
- if (strcmp(format, "uchar") == 0
- || strcmp(format, "uint8") == 0 )
- return PLY_UCHAR;
- if (strcmp(format, "short") == 0
- || strcmp(format, "int16") == 0 )
- return PLY_SHORT;
- if (strcmp(format, "ushort") == 0
- || strcmp(format, "uint16") == 0 )
- return PLY_USHORT;
- if (strcmp(format, "int" ) == 0
- || strcmp(format, "int32") == 0 )
- return PLY_INT;
- if (strcmp(format, "uint" ) == 0
- || strcmp(format, "uint32") == 0 )
- return PLY_UINT;
- if (strcmp(format, "float" ) == 0
- || strcmp(format, "float32") == 0 )
- return PLY_FLOAT;
- if (strcmp(format, "double" ) == 0
- || strcmp(format, "float64") == 0 )
- return PLY_DOUBLE;
- return PLY_UNSUPPORTED;
- }
- unsigned int flag_to_num( char *flag )
- {
- if (strcmp(flag, "x") == 0)
- return FLG_V_POS_X;
- if (strcmp(flag, "y") == 0)
- return FLG_V_POS_Y;
- if (strcmp(flag, "z") == 0)
- return FLG_V_POS_Z;
- if (strcmp(flag, "red") == 0)
- return FLG_V_COL_R;
- if (strcmp(flag, "green") == 0)
- return FLG_V_COL_G;
- if (strcmp(flag, "blue") == 0)
- return FLG_V_COL_B;
- return 0;
- }
- char *flagstr( unsigned int flag )
- {
- switch (flag)
- {
- case FLG_V_POS_X: return "vertex position x";
- case FLG_V_POS_Y: return "vertex position y";
- case FLG_V_POS_Z: return "vertex position z";
- case FLG_V_COL_R: return "vertex color red";
- case FLG_V_COL_G: return "vertex color green";
- case FLG_V_COL_B: return "vertex color blue";
- case FLG_F_VINDICES: return "vertex indices";
- }
- return "Nothingness";
- }
- char *formatstr( char format )
- {
- switch (format)
- {
- case PLY_CHAR: return "char";
- case PLY_UCHAR: return "unsigned char";
- case PLY_SHORT: return "short";
- case PLY_USHORT: return "unsigned short";
- case PLY_INT: return "int";
- case PLY_UINT: return "unsigned int";
- case PLY_FLOAT: return "float";
- case PLY_DOUBLE: return "double";
- }
- return "Unsupported";
- }
|