Jump to content

  • Log In with Google      Sign In   
  • Create Account


#Actualrip-off

Posted 30 October 2012 - 06:49 AM

Very sorry, I am not exactly sure how to do that..

Instead of directly reading little chunks from the file pointer, read a large amount of data into a intermediate buffer, and then use memory operations like memcpy instead of fread and sscanf rather than scanf.

Sure, this the code I am using..


I'm confused. The file in your original post looks like some kind of text format. Your code appears to be trying to treat it as binary data. Have you pre-processed / compiled the file into a binary format?

If not, your code simply won't work. Your program will try to interpret the textual data as numeric, which will have very unexpected results. For example, one possibility is that the "numfacet" value is being incorrectly interpreted as a very high number, and your loop takes a very long time to complete. Try using your debugger to discover the value of "num" in your loop. On my system, trying the first few lines of your code gives a value of "808,525,944" for "num".

Regardless of whether the file is binary or text, you need to have a lot more error checking. Every call to fread() or scanf() should be testing the return value to ensure it is as you expect.

You might want to start with something like this first:
#include <stdio.h>
#include <stdlib.h>


struct Vertex {
	float coords[3];
};

struct Facet {
	struct Vertex normal;
	struct Vertex vertices[3];
};


void complain_and_exit(const char *message) {
	fprintf(stderr, "%s\n", message);
	exit(1);
}

int main(int argc, char* argv[]) {
	FILE *file = fopen("test.stl","r");
	if(!file) {
		complain_and_exit("The file could not be accessed. Are you sure of the location..?");
	}
  
	int count;
	if(fscanf(file, "solid %d\n", &count) != 1) {
		complain_and_exit("Failed to read header");
	}
	printf("Expecting %d facets\n", count);
  
	int i;
	for(i = 0 ; i < count ;++i) {
		struct Facet facet;
	  
		if(fscanf(file, "facet normal %f %f %f\n", &facet.normal.coords[0], &facet.normal.coords[1], &facet.normal.coords[2]) != 3) {
			complain_and_exit("Failed to read facet normal");
		}
		printf("Facets[%d] normal (%f, %f, %f)\n", i, facet.normal.coords[0], facet.normal.coords[1], facet.normal.coords[2]);
	  
		if(fscanf(file, "outer loop\n") != 0) {
			complain_and_exit("Failed to read \'outer loop\'");
		}
	  
		int j;
		for(j = 0 ; j < 3 ; ++j) {
			struct Vertex *vertex = &facet.vertices[j];
		  
			if(fscanf(file, "vertex %f %f %f\n", &vertex->coords[0],  &vertex->coords[1], &vertex->coords[2]) != 3) {
				complain_and_exit("Failed to read vertex");
			}
			printf("Facets[%d] vertex[%d] (%f, %f, %f)\n", i, j, vertex->coords[0], vertex->coords[1], vertex->coords[2]);
		}
	  
		if(fscanf(file, "endloop\n") != 0) {
			complain_and_exit("Failed to read \'endloop\'");
		}
	  
		if(fscanf(file, "endfacet\n") != 0) {
			complain_and_exit("Failed to read \'endfacet\'");
		}
	}
	fclose(file);
}
When you have it working, then we can see if it needs optimisation.

Also, while you're testing your program, try to start with a simpler mesh. For example, try to load a cube. This will be easier to verify and quicker to load.

#1rip-off

Posted 30 October 2012 - 06:49 AM

Very sorry, I am not exactly sure how to do that..

Instead of directly reading little chunks from the file pointer, read a large amount of data into a intermediate buffer, and then use memory operations like memcpy instead of fread and sscanf rather than scanf.

Sure, this the code I am using..


I'm confused. The file in your original post looks like some kind of text format. Your code appears to be trying to treat it as binary data. Have you pre-processed / compiled the file into a binary format?

If not, your code simply won't work. Your program will try to interpret the textual data as numeric, which will have very unexpected results. For example, one possibility is that the "numfacet" value is being incorrectly interpreted as a very high number, and your loop takes a very long time to complete. Try using your debugger to discover the value of "num" in your loop. On my system, trying the first few lines of your code gives a value of "808,525,944" for "num".

Regardless of whether the file is binary or text, you need to have a lot more error checking. Every call to fread() or scanf() should be testing the return value to ensure it is as you expect.

You might want to start with something like this first:
#include <stdio.h>
#include <stdlib.h>


struct Vertex {
    float coords[3];
};

struct Facet {
    struct Vertex normal;
    struct Vertex vertices[3];
};


void complain_and_exit(const char *message) {
    fprintf(stderr, "%s\n", message);
    exit(1);
}

int main(int argc, char* argv[]) {
    FILE *file = fopen("test.stl","r");
    if(!file) {
	    complain_and_exit("The file could not be accessed. Are you sure of the location..?");
    }
   
    int count;
    if(fscanf(file, "solid %d\n", &count) != 1) {
	    complain_and_exit("Failed to read header");
    }
    printf("Expecting %d facets\n", count);
   
    int i;
    for(i = 0 ; i < count ;++i) {
	    struct Facet facet;
	   
	    if(fscanf(file, "facet normal %f %f %f\n", &facet.normal.coords[0], &facet.normal.coords[1], &facet.normal.coords[2]) != 3) {
		    complain_and_exit("Failed to read facet normal");
	    }
	    printf("Facets[%d] normal (%f, %f, %f)\n", i, facet.normal.coords[0], facet.normal.coords[1], facet.normal.coords[2]);
	   
	    if(fscanf(file, "outer loop\n") != 0) {
		    complain_and_exit("Failed to read \'outer loop\'");
	    }
	   
	    int j;
	    for(j = 0 ; j < 3 ; ++j) {
		    struct Vertex *vertex = &facet.vertices[j];
		   
		    if(fscanf(file, "vertex %f %f %f\n", &vertex->coords[0],  &vertex->coords[1], &vertex->coords[2]) != 3) {
			    complain_and_exit("Failed to read vertex");
		    }
		    printf("Facets[%d] vertex[%d] (%f, %f, %f)\n", i, j, vertex->coords[0], vertex->coords[1], vertex->coords[2]);
	    }
	   
	    if(fscanf(file, "endloop\n") != 0) {
		    complain_and_exit("Failed to read \'endloop\'");
	    }
	   
	    if(fscanf(file, "endfacet\n") != 0) {
		    complain_and_exit("Failed to read \'endfacet\'");
	    }
    }
    return count;
}
When you have it working, then we can see if it needs optimisation.

Also, while you're testing your program, try to start with a simpler mesh. For example, try to load a cube. This will be easier to verify and quicker to load.

PARTNERS