-
Notifications
You must be signed in to change notification settings - Fork 9
Feature/add ply support #9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -454,3 +454,148 @@ struct model *model_load_from_obj(const char *fname, bool color_support) | |
| model_validate_idxs(model); | ||
| return model; | ||
| } | ||
|
|
||
| struct model *model_load_from_ply(const char *fname) | ||
| { | ||
| FILE *fp = fopen(fname, "r"); | ||
| if (!fp) | ||
| { | ||
| fprintf(stderr, "ERROR: failed to load file \"%s\".\n", fname); | ||
| return NULL; | ||
| } | ||
|
|
||
| // Create a new model | ||
| struct model *model = model_init(); | ||
|
|
||
| // Read each line of the file | ||
| char buffer[256]; | ||
|
|
||
| int vertex_count = 0; | ||
| int face_count = 0; | ||
|
|
||
| while (fgets(buffer, sizeof(buffer), fp)) | ||
| { | ||
| char *p = buffer; | ||
| while (*p) | ||
| { | ||
| if (*p == '\n' || *p == '\r') | ||
| *p = '\0'; | ||
| if (*p == '\t') | ||
| *p = ' '; | ||
| p++; | ||
| } | ||
|
|
||
| char *bufferp = buffer; | ||
| char *instr = str_chop_skip_empty(&bufferp, " "); | ||
|
|
||
| if (!instr) | ||
| continue; | ||
|
|
||
| if (strcmp(instr, "element") == 0) | ||
| { | ||
| char *type = str_chop_skip_empty(&bufferp, " "); | ||
| int count = 0; | ||
| parse_int(&bufferp, &count); | ||
|
|
||
| if (strcmp(type, "vertex") == 0) | ||
| { | ||
| vertex_count = count; | ||
| } | ||
| else if (strcmp(type, "face") == 0) | ||
| { | ||
| face_count = count; | ||
| } | ||
| } | ||
| else if (strcmp(instr, "property") == 0) | ||
| { | ||
| // Skip property declarations | ||
| } | ||
| else if (strcmp(instr, "end_header") == 0) | ||
| { | ||
| // End of header, start reading data | ||
| break; | ||
| } | ||
| } | ||
|
|
||
| for (int i = 0; i < vertex_count; i++) | ||
| { | ||
| float f1, f2, f3; | ||
|
|
||
| if (!fgets(buffer, sizeof(buffer), fp)) | ||
| { | ||
| fprintf(stderr, "ERROR: could not read vertex data.\n"); | ||
| fclose(fp); | ||
| model_free(model); | ||
| return NULL; | ||
| } | ||
| char *bufferp = buffer; | ||
|
|
||
| if (!parse_float(&bufferp, &f1) || !parse_float(&bufferp, &f2) || !parse_float(&bufferp, &f3)) | ||
| { | ||
| fprintf(stderr, "ERROR: unexpected vertex data format.\n"); | ||
| fclose(fp); | ||
| model_free(model); | ||
| return NULL; | ||
| } | ||
|
|
||
| vec3 vec; | ||
| vec.x = f1; | ||
| vec.y = f2; | ||
| vec.z = f3; | ||
|
Comment on lines
+542
to
+544
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I noticed that the models appear rotated so probably this is not the correct ordering for the axis. Perhaps vec.y should be f3 and vec.z should be f2 ?
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually, the ordering of the axes came inconsistent between the models PLY models. So the teapot.ply and the airplane.py had the wrong orientation. Perhaps we should stick to the axes ordering used by blender when exporting .PLY files. |
||
|
|
||
| model_add_vertex(model, vec); | ||
| } | ||
|
|
||
| for (int i = 0; i < face_count; i++) | ||
| { | ||
| int list_length; | ||
| int i1, i2, i3; | ||
|
|
||
| if (!fgets(buffer, sizeof(buffer), fp)) | ||
| { | ||
| fprintf(stderr, "ERROR: could not read face data.\n"); | ||
| fclose(fp); | ||
| model_free(model); | ||
| return NULL; | ||
| } | ||
| char *bufferp = buffer; | ||
|
|
||
| if (!parse_int(&bufferp, &list_length)) | ||
| { | ||
| fprintf(stderr, "ERROR: unexpected face data format.\n"); | ||
| fclose(fp); | ||
| model_free(model); | ||
| return NULL; | ||
| } | ||
|
|
||
| if (list_length >= 3) | ||
| { | ||
| if (!parse_int(&bufferp, &i1) || !parse_int(&bufferp, &i2)) | ||
| { | ||
| fprintf(stderr, "ERROR: unexpected face data format.\n"); | ||
| fclose(fp); | ||
| model_free(model); | ||
| return NULL; | ||
| } | ||
| } | ||
|
|
||
| for (int k = 2; k < list_length; ++k) | ||
| { | ||
| if (!parse_int(&bufferp, &i3)) | ||
| { | ||
| fprintf(stderr, "ERROR: unexpected face data format.\n"); | ||
| fclose(fp); | ||
| model_free(model); | ||
| return NULL; | ||
| } | ||
|
|
||
| model_add_face(model, i1, i2, i3, -1); | ||
| // Shift for possible new triangular face | ||
| i2 = i3; | ||
| } | ||
| } | ||
| fclose(fp); | ||
|
|
||
| model_validate_idxs(model); | ||
| return model; | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My understanding is that all PLY files start with a
plyline. I think we should check for that and throw an exit(1) printing "invalid format" to stderr if it is missing.Also, I read that there are both a binary PLY format and a text PLY format. How can we check that this is indeed a text PLY file?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is still pending, but we should check for a line with
in the header.