/* Reads the contents of the file pointed to by stl->fp into the stl structure, starting at facet first_facet. The second argument says if it's our first time running this for the stl and therefore we should reset our max and min stats. */ void stl_read(stl_file *stl, int first_facet, int first) { stl_facet facet; int i; if (stl->error) return; if(stl->stats.type == binary) { fseek(stl->fp, HEADER_SIZE, SEEK_SET); } else { rewind(stl->fp); } for(i = first_facet; i < stl->stats.number_of_facets; i++) { if(stl->stats.type == binary) /* Read a single facet from a binary .STL file */ { /* we assume little-endian architecture! */ if (fread(&facet.normal, sizeof(stl_normal), 1, stl->fp) \ + fread(&facet.vertex, sizeof(stl_vertex), 3, stl->fp) \ + fread(&facet.extra, sizeof(char), 2, stl->fp) != 6) { perror("Cannot read facet"); stl->error = 1; return; } } else /* Read a single facet from an ASCII .STL file */ { // skip solid/endsolid // (in this order, otherwise it won't work when they are paired in the middle of a file) fscanf(stl->fp, "endsolid\n"); fscanf(stl->fp, "solid%*[^\n]\n"); // name might contain spaces so %*s doesn't work and it also can be empty (just "solid") if((fscanf(stl->fp, " facet normal %f %f %f\n", &facet.normal.x, &facet.normal.y, &facet.normal.z) + \ fscanf(stl->fp, " outer loop\n") + \ fscanf(stl->fp, " vertex %f %f %f\n", &facet.vertex[0].x, &facet.vertex[0].y, &facet.vertex[0].z) + \ fscanf(stl->fp, " vertex %f %f %f\n", &facet.vertex[1].x, &facet.vertex[1].y, &facet.vertex[1].z) + \ fscanf(stl->fp, " vertex %f %f %f\n", &facet.vertex[2].x, &facet.vertex[2].y, &facet.vertex[2].z) + \ fscanf(stl->fp, " endloop\n") + \ fscanf(stl->fp, " endfacet\n")) != 12) { perror("Something is syntactically very wrong with this ASCII STL!"); stl->error = 1; return; } } /* Write the facet into memory. */ stl->facet_start[i] = facet; stl_facet_stats(stl, facet, first); first = 0; } stl->stats.size.x = stl->stats.max.x - stl->stats.min.x; stl->stats.size.y = stl->stats.max.y - stl->stats.min.y; stl->stats.size.z = stl->stats.max.z - stl->stats.min.z; stl->stats.bounding_diameter = sqrt( stl->stats.size.x * stl->stats.size.x + stl->stats.size.y * stl->stats.size.y + stl->stats.size.z * stl->stats.size.z ); }
/* Reads the contents of the file pointed to by stl->fp into the stl structure, starting at facet first_facet. The second argument says if it's our first time running this for the stl and therefore we should reset our max and min stats. */ void stl_read(stl_file *stl, int first_facet, int first) { stl_facet facet; int i; if (stl->error) return; if(stl->stats.type == binary) { fseek(stl->fp, HEADER_SIZE, SEEK_SET); } else { rewind(stl->fp); /* Skip the first line of the file */ while(getc(stl->fp) != '\n'); } for(i = first_facet; i < stl->stats.number_of_facets; i++) { if(stl->stats.type == binary) /* Read a single facet from a binary .STL file */ { /* we assume little-endian architecture! */ if (fread(&facet.normal, sizeof(stl_normal), 1, stl->fp) \ + fread(&facet.vertex, sizeof(stl_vertex), 3, stl->fp) \ + fread(&facet.extra, sizeof(char), 2, stl->fp) != 6) { perror("Cannot read facet"); stl->error = 1; return; } } else /* Read a single facet from an ASCII .STL file */ { if((fscanf(stl->fp, "%*s %*s %f %f %f\n", &facet.normal.x, &facet.normal.y, &facet.normal.z) + \ fscanf(stl->fp, "%*s %*s") + \ fscanf(stl->fp, "%*s %f %f %f\n", &facet.vertex[0].x, &facet.vertex[0].y, &facet.vertex[0].z) + \ fscanf(stl->fp, "%*s %f %f %f\n", &facet.vertex[1].x, &facet.vertex[1].y, &facet.vertex[1].z) + \ fscanf(stl->fp, "%*s %f %f %f\n", &facet.vertex[2].x, &facet.vertex[2].y, &facet.vertex[2].z) + \ fscanf(stl->fp, "%*s") + \ fscanf(stl->fp, "%*s")) != 12) { perror("Something is syntactically very wrong with this ASCII STL!"); stl->error = 1; return; } } /* Write the facet into memory. */ stl->facet_start[i] = facet; stl_facet_stats(stl, facet, first); first = 0; } stl->stats.size.x = stl->stats.max.x - stl->stats.min.x; stl->stats.size.y = stl->stats.max.y - stl->stats.min.y; stl->stats.size.z = stl->stats.max.z - stl->stats.min.z; stl->stats.bounding_diameter = sqrt( stl->stats.size.x * stl->stats.size.x + stl->stats.size.y * stl->stats.size.y + stl->stats.size.z * stl->stats.size.z ); }
static void stl_read(stl_file *stl, int first_facet, int first) { stl_facet facet; int i; if(stl->stats.type == binary) { fseek(stl->fp, HEADER_SIZE, SEEK_SET); } else { rewind(stl->fp); /* Skip the first line of the file */ while(getc(stl->fp) != '\n'); } for(i = first_facet; i < stl->stats.number_of_facets; i++) { if(stl->stats.type == binary) /* Read a single facet from a binary .STL file */ { facet.normal.x = stl_get_little_float(stl->fp); facet.normal.y = stl_get_little_float(stl->fp); facet.normal.z = stl_get_little_float(stl->fp); facet.vertex[0].x = stl_get_little_float(stl->fp); facet.vertex[0].y = stl_get_little_float(stl->fp); facet.vertex[0].z = stl_get_little_float(stl->fp); facet.vertex[1].x = stl_get_little_float(stl->fp); facet.vertex[1].y = stl_get_little_float(stl->fp); facet.vertex[1].z = stl_get_little_float(stl->fp); facet.vertex[2].x = stl_get_little_float(stl->fp); facet.vertex[2].y = stl_get_little_float(stl->fp); facet.vertex[2].z = stl_get_little_float(stl->fp); facet.extra[0] = fgetc(stl->fp); facet.extra[1] = fgetc(stl->fp); } else /* Read a single facet from an ASCII .STL file */ { fscanf(stl->fp, "%*s %*s %f %f %f\n", &facet.normal.x, &facet.normal.y, &facet.normal.z); fscanf(stl->fp, "%*s %*s"); fscanf(stl->fp, "%*s %f %f %f\n", &facet.vertex[0].x, &facet.vertex[0].y, &facet.vertex[0].z); fscanf(stl->fp, "%*s %f %f %f\n", &facet.vertex[1].x, &facet.vertex[1].y, &facet.vertex[1].z); fscanf(stl->fp, "%*s %f %f %f\n", &facet.vertex[2].x, &facet.vertex[2].y, &facet.vertex[2].z); fscanf(stl->fp, "%*s"); fscanf(stl->fp, "%*s"); } /* Write the facet into memory. */ stl->facet_start[i] = facet; stl_facet_stats(stl, facet, first); first = 0; } stl->stats.size.x = stl->stats.max.x - stl->stats.min.x; stl->stats.size.y = stl->stats.max.y - stl->stats.min.y; stl->stats.size.z = stl->stats.max.z - stl->stats.min.z; stl->stats.bounding_diameter = sqrt( stl->stats.size.x * stl->stats.size.x + stl->stats.size.y * stl->stats.size.y + stl->stats.size.z * stl->stats.size.z ); }
/* Reads the contents of the file pointed to by stl->fp into the stl structure, starting at facet first_facet. The second argument says if it's our first time running this for the stl and therefore we should reset our max and min stats. */ void stl_read(stl_file *stl, int first_facet, int first) { stl_facet facet; int i; if (stl->error) return; if(stl->stats.type == binary) { fseek(stl->fp, HEADER_SIZE, SEEK_SET); } else { rewind(stl->fp); } for(i = first_facet; i < stl->stats.number_of_facets; i++) { if(stl->stats.type == binary) /* Read a single facet from a binary .STL file */ { /* we assume little-endian architecture! */ if (fread(&facet, 1, SIZEOF_STL_FACET, stl->fp) != SIZEOF_STL_FACET) { stl->error = 1; return; } } else /* Read a single facet from an ASCII .STL file */ { // skip solid/endsolid // (in this order, otherwise it won't work when they are paired in the middle of a file) fscanf(stl->fp, "endsolid\n"); fscanf(stl->fp, "solid%*[^\n]\n"); // name might contain spaces so %*s doesn't work and it also can be empty (just "solid") if((fscanf(stl->fp, " facet normal %f %f %f\n", &facet.normal.x, &facet.normal.y, &facet.normal.z) + \ fscanf(stl->fp, " outer loop\n") + \ fscanf(stl->fp, " vertex %f %f %f\n", &facet.vertex[0].x, &facet.vertex[0].y, &facet.vertex[0].z) + \ fscanf(stl->fp, " vertex %f %f %f\n", &facet.vertex[1].x, &facet.vertex[1].y, &facet.vertex[1].z) + \ fscanf(stl->fp, " vertex %f %f %f\n", &facet.vertex[2].x, &facet.vertex[2].y, &facet.vertex[2].z) + \ fscanf(stl->fp, " endloop\n") + \ fscanf(stl->fp, " endfacet\n")) != 12) { perror("Something is syntactically very wrong with this ASCII STL!"); stl->error = 1; return; } } #if 0 // Report close to zero vertex coordinates. Due to the nature of the floating point numbers, // close to zero values may be represented with singificantly higher precision than the rest of the vertices. // It may be worth to round these numbers to zero during loading to reduce the number of errors reported // during the STL import. for (size_t j = 0; j < 3; ++ j) { if (facet.vertex[j].x > -1e-12f && facet.vertex[j].x < 1e-12f) printf("stl_read: facet %d.x = %e\r\n", j, facet.vertex[j].x); if (facet.vertex[j].y > -1e-12f && facet.vertex[j].y < 1e-12f) printf("stl_read: facet %d.y = %e\r\n", j, facet.vertex[j].y); if (facet.vertex[j].z > -1e-12f && facet.vertex[j].z < 1e-12f) printf("stl_read: facet %d.z = %e\r\n", j, facet.vertex[j].z); } #endif #if 1 { // Positive and negative zeros are possible in the floats, which are considered equal by the FP unit. // When using a memcmp on raw floats, those numbers report to be different. // Unify all +0 and -0 to +0 to make the floats equal under memcmp. uint32_t *f = (uint32_t*)&facet; for (int j = 0; j < 12; ++ j, ++ f) // 3x vertex + normal: 4x3 = 12 floats if (*f == 0x80000000) // Negative zero, switch to positive zero. *f = 0; } #else { // Due to the nature of the floating point numbers, close to zero values may be represented with singificantly higher precision // than the rest of the vertices. Round them to zero. float *f = (float*)&facet; for (int j = 0; j < 12; ++ j, ++ f) // 3x vertex + normal: 4x3 = 12 floats if (*f > -1e-12f && *f < 1e-12f) // Negative zero, switch to positive zero. *f = 0; } #endif /* Write the facet into memory. */ memcpy(stl->facet_start+i, &facet, SIZEOF_STL_FACET); stl_facet_stats(stl, facet, first); first = 0; } stl->stats.size.x = stl->stats.max.x - stl->stats.min.x; stl->stats.size.y = stl->stats.max.y - stl->stats.min.y; stl->stats.size.z = stl->stats.max.z - stl->stats.min.z; stl->stats.bounding_diameter = sqrt( stl->stats.size.x * stl->stats.size.x + stl->stats.size.y * stl->stats.size.y + stl->stats.size.z * stl->stats.size.z ); }