Advertisement

MSVC++ Grammar issues?!?!

Started by December 05, 2004 11:31 PM
15 comments, last by adam17 19 years, 9 months ago
WOW!!! i never realized how f***ed up my code really was?!?! i took 2 compsci class 3 years ago and my teachers NEVER told us the importance behind using the right datatypes. on top of that i have had to teach myself traditional c like using printf instead of cout.

thank you guys SOOO much!

if any of you guys realize what i have going on in my function CalVertexNormals, and could offer any more optimization suggestions, PLEASE TELL ME!
Quote: Original post by Enigma
Another big problem that isn't causing your crash, plus the cause of your crash:
*** Source Snippet Removed ***
You're indexing into vert_face[y] even though vert_face[y] has not been resized. You're also calling the capacity() member function, when you should be using size() and you should be indexing with size() - 1 if you want the last element.

I'm going to rewrite your code for you in full C++ rather that the C with a little bit of C++ that you're using just so you can see how much cleaner it is.

Enigma


im a little lost here. im trying to fix it but i keep getting errors, im guessing with resizing the arrays...

for(x=0; x<mesh.NumVert; x++)	{		for(y=0; y<mesh.NumFace; y++)		{			if(mesh.Face[y].x == x)			{				vert_face.resize(vert_face.size()+1);				vert_face[y][vert_face.size()-1] = x;			}			if(mesh.Face[y].y == x)			{				vert_face.resize(vert_face.size()+1);				vert_face[y][vert_face.size()-1] = x;			}			if(mesh.Face[y].z == x)			{				vert_face.resize(vert_face.size()+1);				vert_face[y][vert_face.size()-1] = x;			}		}	}
Advertisement
I'm not entirely sure what you're doing in your CalVertexNormals function. The error is that you access vert_face[y][...] but you never actually resize vert_face[y], you only resize vert_face.

Here's what I came up with based on your code. Note that if I'd have been writing this I wouldn't have done it this way. I would probably have read the vertex, face, normal etc. data into arrays and then assembled polygons from them rather than trying to do the two at one. It's a little cludgy since it was hacked together with little design though. It's a little STL heavy, so have a reference handy (but be glad I couldn't get bind2nd and mem_fun to work in the accumulate call)!

A point class to replace your point3 struct. Note that I templated it since faces are a set of three integers instead of floats. If I'd have been writing this from scratch I would have gone for different names, since a normal and a face are not a point, but I wanted to keep it as close as possible to your original code.
#if !defined(POINT_HEADER)	#define POINT_HEADER	#include <cmath>	#include <ctype>	#include <iostream>template <typename TYPE>class Point3{	public:		Point3()			:			x(),			y(),			z()		{		}		TYPE x;		TYPE y;		TYPE z;};typedef Point3<float> Point3f;typedef Point3<int> Point3i;template <typename TYPE>std::istream& operator>>(std::istream& reader, Point3<TYPE>& point){	while (std::isspace(reader.peek()))	{		reader.ignore(1);	}	reader.ignore(1);	reader >> point.x;	reader.ignore(1);	reader >> point.y;	reader.ignore(1);	reader >> point.z;	reader.ignore(1);	return reader;}template <typename TYPE>std::ostream& operator<<(std::ostream& writer, const Point3<TYPE>& point){	writer << '[' << point.x << ", " << point.y << ", " << point.z << ']';	return writer;}template <typename TYPE>const Point3<TYPE>& operator+=(Point3<TYPE>& firstPoint, const Point3<TYPE>& secondPoint){	firstPoint.x += secondPoint.x;	firstPoint.y += secondPoint.y;	firstPoint.z += secondPoint.z;	return firstPoint;}template <typename TYPE>class Normalise{	public:		void operator()(TYPE& point)		{			float length = std::sqrt((point.x * point.x) + (point.y * point.y) + (point.z * point.z));			if (length < FLT_EPSILON)			{				length = 1;			}			point.x /= length;			point.y /= length;			point.z /= length;		}};#endif


Header file for a Polygon class. This is pretty poorly designed since it's just a set of getters/setters. This again is because I was trying to make it as close to your code as possible.
#if !defined(POLYGON_HEADER)	#define POLYGON_HEADER	#include <iosfwd>	#include "Point.h"class Polygon{	public:		Polygon();		Point3f getFaceNormal() const;		int getSmoothingGroup() const;		void print(std::ostream& writer) const;		void setMaterial(int materialId);		void setNormal(Point3f normal);		void setSmoothingGroup(int smoothingGroup);		void setVertices(Point3f vertex1, Point3f vertex2, Point3f vertex3);		void setVertexNormals(Point3f vertex1, Point3f vertex2, Point3f vertex3);	private:		Point3f vertices_[3];		Point3f faceNormal_;		Point3f vertexNormals_[3];		int materialId_;		int smoothingGroup_;};std::ostream& operator<<(std::ostream& writer, const Polygon& polygon);#endif


Implementation for the polygon. Note how I don't have a single comment in the source. This is not due to lack of time or lazyness - it doesn't need comments because the variable and function names, in their context, tell you all you need to know.
#if !defined(POLYGON_IMPLEMENTATION)	#define POLYGON_IMPLEMENTATION	#include <iostream>	#include "Polygon.h"Polygon::Polygon()	:	materialId_(-1),	smoothingGroup_(-1){}Point3f Polygon::getFaceNormal() const{	return faceNormal_;}int Polygon::getSmoothingGroup() const{	return smoothingGroup_;}void Polygon::print(std::ostream& writer) const{	writer << "Vertices:\n" << '\t' << vertices_[0] << "\n\t" << vertices_[1] << "\n\t" << vertices_[2] << '\n';	writer << "Normal: " << faceNormal_ << '\n';	writer << "Vertex Normals:\n" << '\t' << vertexNormals_[0] << "\n\t" << vertexNormals_[1] << "\n\t" << vertexNormals_[2] << '\n';	writer << "Material ID: " << materialId_ << '\n';	writer << "Smoothing Group: " << smoothingGroup_ << '\n';}void Polygon::setMaterial(int materialId){	materialId_ = materialId;}void Polygon::setNormal(Point3f normal){	faceNormal_ = normal;}void Polygon::setSmoothingGroup(int smoothingGroup){	smoothingGroup_ = smoothingGroup;}void Polygon::setVertices(Point3f vertex1, Point3f vertex2, Point3f vertex3){	vertices_[0] = vertex1;	vertices_[1] = vertex2;	vertices_[2] = vertex3;}void Polygon::setVertexNormals(Point3f normal1, Point3f normal2, Point3f normal3){	vertexNormals_[0] = normal1;	vertexNormals_[1] = normal2;	vertexNormals_[2] = normal3;}std::ostream& operator<<(std::ostream& writer, const Polygon& polygon){	polygon.print(writer);	return writer;}#endif


Header file for the mesh.
#if !defined(MESH_HEADER)	#define MESH_HEADER	#include <iosfwd>	#include <vector>	#include "Point.h"	#include "Polygon.h"class Mesh{	public:		void calculateVertexNormals();		void print(std::ostream& writer) const;		void read(std::istream& reader);	private:		void readFaces(std::istream& reader);		void readMaterials(std::istream& reader);		void readNormals(std::istream& reader);		void readSmoothingGroups(std::istream& reader);		void readVertices(std::istream& reader);		std::vector<Point3f> vertices;		std::vector<Point3i> faces;		std::vector<Polygon> polygons;};std::istream& operator>>(std::istream& reader, Mesh& mesh);std::ostream& operator<<(std::ostream& writer, const Mesh& mesh);#endif


Implementation for the mesh. Have an STL reference handy!
#if !defined(MESH_IMPLEMENTATION)	#define MESH_IMPLEMENTATION	#include <algorithm>	#include <iostream>	#include <iterator>	#include <numeric>	#include "Mesh.h"class FindMaximumSmoothingGroup{	public:		int operator()(int maximumSmoothingGroup, Polygon& polygon)		{			return std::max(maximumSmoothingGroup, polygon.getSmoothingGroup());		}};void Mesh::calculateVertexNormals(){	// find out how many smoothing groups there are	int maximumSmoothingGroup = std::accumulate(polygons.begin(), polygons.end(), 0, FindMaximumSmoothingGroup());	// for each smoothing group	for (int smoothingGroupNumber = 0; smoothingGroupNumber < maximumSmoothingGroup + 1; ++smoothingGroupNumber)	{		// set up a set of vertex normals for this smoothing group		std::vector<Point3f> vertexNormals(vertices.size());		// for each polygon		for (unsigned int polygonNumber = 0; polygonNumber < polygons.size(); ++polygonNumber)		{			// if this polygon is in the current smoothing group			if (polygons[polygonNumber].getSmoothingGroup() == smoothingGroupNumber)			{				// set the polygon vertices				polygons[polygonNumber].setVertices(vertices[faces[polygonNumber].x], vertices[faces[polygonNumber].y], vertices[faces[polygonNumber].z]);				// sum the polgon normal into the vertex normals for this smoothing group				vertexNormals[faces[polygonNumber].x] += polygons[polygonNumber].getFaceNormal();				vertexNormals[faces[polygonNumber].y] += polygons[polygonNumber].getFaceNormal();				vertexNormals[faces[polygonNumber].z] += polygons[polygonNumber].getFaceNormal();			}		}		// normalise the vertex normals for this smoothing group		std::for_each(vertexNormals.begin(), vertexNormals.end(), Normalise<Point3f>());		// for each polygon		for (unsigned int polygonNumber = 0; polygonNumber < polygons.size(); ++polygonNumber)		{			// if this polygon is in the current smoothing group then copy the calculated vertex normals into it			if (polygons[polygonNumber].getSmoothingGroup() == smoothingGroupNumber)			{				polygons[polygonNumber].setVertexNormals(vertexNormals[faces[polygonNumber].x], vertexNormals[faces[polygonNumber].y], vertexNormals[faces[polygonNumber].z]);			}		}	}}void Mesh::print(std::ostream& writer) const{	writer << "vertices:\n";	std::copy(vertices.begin(), vertices.end(), std::ostream_iterator<Point3f>(writer, "\n"));	writer << "\nfaces:\n";	std::copy(faces.begin(), faces.end(), std::ostream_iterator<Point3i>(writer, "\n"));	writer << "\npolygons:\n";	std::copy(polygons.begin(), polygons.end(), std::ostream_iterator<Polygon>(writer, "\n"));}void Mesh::read(std::istream& reader){	int numberOfVertices;	reader >> numberOfVertices;	vertices.resize(numberOfVertices);	int numberOfFaces;	reader >> numberOfFaces;	faces.resize(numberOfFaces);	polygons.resize(numberOfFaces);	bool verticesRead = false;	bool facesRead = false;	while (!reader.eof())	{		while (std::isspace(reader.peek()))		{			reader.ignore(1);		}		char dataType = reader.get();		if (dataType == 'v')		{			readVertices(reader);			verticesRead = true;		}		else if (dataType == 'f')		{			readFaces(reader);			facesRead = true;		}		else if (dataType == 'n')		{			if (!verticesRead || !facesRead)			{				throw std::string("Need vertex & face information before faces");			}			readNormals(reader);		}		else if (dataType == 'm')		{			if (!verticesRead || !facesRead)			{				throw std::string("Need vertex & face information before materials");			}			readMaterials(reader);		}		else if (dataType == 's')		{			if (!verticesRead || !facesRead)			{				throw std::string("Need vertex & face information before smoothing groups");			}			readSmoothingGroups(reader);		}	}}void Mesh::readVertices(std::istream& reader){	for (unsigned int vertexNumber = 0; vertexNumber < vertices.size(); ++vertexNumber)	{		Point3f vertex;		reader >> vertex;		vertices[vertexNumber] = vertex;	}}void Mesh::readFaces(std::istream& reader){	for (unsigned int faceNumber = 0; faceNumber < faces.size(); ++faceNumber)	{		Point3i face;		reader >> face;		face.x -= 1;		face.y -= 1;		face.z -= 1;		faces[faceNumber] = face;	}}void Mesh::readNormals(std::istream& reader){	for (unsigned int polygonNumber = 0; polygonNumber < faces.size(); ++polygonNumber)	{		Point3f normal;		reader >> normal;		polygons[polygonNumber].setNormal(normal);	}}void Mesh::readMaterials(std::istream& reader){	for (unsigned int polygonNumber = 0; polygonNumber < faces.size(); ++polygonNumber)	{		int materialId;		while (std::isspace(reader.peek()))		{			reader.ignore(1);		}		reader >> materialId;		polygons[polygonNumber].setMaterial(materialId);	}}void Mesh::readSmoothingGroups(std::istream& reader){	for (unsigned int polygonNumber = 0; polygonNumber < faces.size(); ++polygonNumber)	{		int smoothingGroup;		while (std::isspace(reader.peek()))		{			reader.ignore(1);		}		// ignore the #( and ) around the value		reader.ignore(2);		reader >> smoothingGroup;		reader.ignore(1);		polygons[polygonNumber].setSmoothingGroup(smoothingGroup);	}}std::istream& operator>>(std::istream& reader, Mesh& mesh){	mesh.read(reader);	return reader;}std::ostream& operator<<(std::ostream& writer, const Mesh& mesh){	mesh.print(writer);	return writer;}#endif


Main application file. Note that by having classes with appropriate behaviour the high level view of the application is completely trivial.
#include <fstream>#include <iostream>#include <string>#include "Mesh.h"Mesh importLdm(std::string filename){	std::ifstream reader(filename.c_str());	if (!reader)	{		throw std::string("File not found");	}	// natural reusable syntax for reading meshes.	Mesh mesh;	reader >> mesh;	std::cout << mesh;	mesh.calculateVertexNormals();	std::cout << mesh;	return mesh;}int main(){	// no buffer overflow bugs	std::string filename;	std::cout << "input a filename with extension...\n";	std::getline(std::cin, filename);	try	{		Mesh mesh = importLdm(filename);	}	catch (std::string& exception)	{		std::cout << "Error: " << exception << '\n';	}}


Hope this helps. One final comment I would make: The two most important things in C++ are whitespace and function/variable names. Source code is a communication medium - use it as such.

Enigma
DUDE! u didnt have to rewrite all of my code, but thanks anyway! im not gonna just copy and paste it into my program. i wont learn anything that way. i never learned templates or much about STL stuff. u have given me ALOT of ideas and im going to give my code a serious overhaul and revamp it.

also how would you guys recommend me setting up my different classes and structures? i need something for vertex indices, face indices, normals, vertex normals, smoothing groups, material IDs, etc. tell me what you think of the changes i made to my structures...

are they too nested?
too many?
do i need better variable names?

template <typename TYPE> class tVector3{	public: 		tVector3(): x(), y(), z() {}		  TYPE x;		  TYPE y;		  TYPE z;};typedef tVector3<float> Vector3f;typedef tVector3<int> Vector3i;struct tVertex{	Vector3f Vertex3f;	vector<int> neighbor;};typedef struct _polygon{	tVertex		vertex[3];		//vertex values	Vector3f	fNormal3f;		//face normal	Vector3f	vNormal3f[3];	//vertex normals	int		matid;	int		smoothgroup;} polygon;struct _mesh{	int		NumVert;	int		NumFace;	vector<tVertex>		Vert;	//TEMPORARILY stores all of the vertex information	vector<Vector3i>	Face;	//TEMPORARILY stores all of the face winding info	vector<polygon>		polys;} mesh;


[Edited by - adam17 on December 6, 2004 2:53:24 PM]
If I was going to write a simple loader for that file format from scratch I would probably use something like:
template <typename TYPE>class Vector3{	public:		Vector3()		{		}		Vector3(TYPE initialiser)			:			x(initialiser),			y(initialiser),			z(initialiser)		{		}		TYPE x;		TYPE y;		TYPE z;};typedef float GeometricType;typedef Vector3<GeometricType> GeometicVector;class Material{	public:		// member functions	private:		// member functions & variables};class Polygon{	public:		// member functions	private:		// member functions & variables		GeometricVector vertices_[3];		GeometricVector normals_[3];		Material& material_;};class Mesh{	public:		// member functions	private:		// member functions & variables		std::deque<Polygon> polygons_;		typedef unsigned short VertexIndexType;		class FaceVertices		{			public:				FaceVertices(VertexIndexType faceVertex1, VertexIndexType faceVertex2, VertexIndexType faceVertex3)					:					vertex1(faceVertex1),					vertex2(faceVertex2),					vertex3(faceVertex3)				{				}				VertexIndexType vertex1;				VertexIndexType vertex2;				VertexIndexType vertex3;		};};

And then load using something like:
std::deque<GeometicVector> vertices;std::deque<FaceVertices> faces;std::deque<GeometicVector> faceNormals;std::deque<Material&> faceMaterials;typedef unsigned short SmoothingGroupType;std::deque<SmoothingGroupType> smoothingGroups;load(vertices, faces, faceNormals, faceMaterials, smoothingGroups);std::deque<GeometricVector> vertexNormals = calculateVertexNormals(faces, faceNormals, smoothingGroups);polygons_ = buildPolygons(vertices, faces, faceMaterials, vertexNormals);


This is just pseudo-code of course and my actual function calls would look nothing like that.

A bit of explanation:
I use std::deque instead of std::vector since contiguous storage is not required. std::deque may have better performance than std::vector.
I use typedefs for types that I might want to change later. For example GeometicType. In the example above this is just a typedef for float. It at a later date I decide I need extra precision and want to use doubles I only have to change one line.
It makes no sense for the set of vertices that make up a face to be named x, y and z. Therefore instead of reusing my templated vector class I create a new class. Faces are an implementation detail of a mesh, so I make it a private class in Mesh.
I hold references to materials. This assumes that I am either able to load materials beforehand or I have a std::deque<Material> and populate it as faces require materials. The actual material properties would then be set to a default and then updated to the correct values when the material was actually read.
Only the persistent key properties are kept as variables in the main classes. Temporary storage is moved to local variables in functions or helper classes.

Enigma
enigma

when u start making templates and start putting classes inside of other classes, doesnt that slow down your program when u access some of the deepest elements?
Advertisement
Templates and nested classes are purely compile-time constructs. They incur no run-time penalty what-so-ever. Regardless, it is much better to write code clearly and with good encapsulation as it speeds up the writing and testing of the code, giving you more time to concentrate on optimising the bottlenecks in your program rather than spending a month writing the most optimised physics engine possible, only to find you were fillrate limited all along.

Enigma
ok here is what i have done to my code. im not entirely done with it though.

#include <iomanip>#include <conio.h>#include <cstdio>#include <cstdlib>#include <fstream>#include <vector>using namespace std;bool ImportLDM(char* filename);FILE* infile;//////////////////////////////////////////////////////////////////////////MESH DEFINITIONS///////////////////////////////////////////////////////////////////////////template <typename TYPE> class tVector3{	public: 		tVector3(): x(), y(), z() {}		  TYPE x;		  TYPE y;		  TYPE z;};typedef tVector3<float> Vector3f;typedef tVector3<int> Vector3i;struct tVertex{	float x, y, z;	vector<int> neighbor;};struct tFace{	float x, y, z;};typedef struct _polygon{	Vector3i	vert_face_ind;	//which vertices the face uses	tVertex		v1, v2, v3;		//vertex values	Vector3f	fNormal3f;		//face normal	Vector3f	vNormal3f[3];	//vertex normals	int		matid;	int		smoothgroup;} polygon;struct _mesh{	int		NumVert;	int		NumFace;	vector<polygon>		polys;} mesh;//////////////////////////////////////////////////////////////////////////MESH DEFINITIONS///////////////////////////////////////////////////////////////////////////int main(int argc, char** argv){	char filename[256];	printf("input a filename with extension...\n");	scanf("%s", filename);	if(ImportLDM(filename) == false)		printf("file not found!\n");		return 0;}void CalVertexNormals(){	int x=0, y=0, array_len=0, count=0;	printf("\ncalculating vertex normals...\n");	for(x=0; x<mesh.NumVert; x++)	{		for(y=0; y<mesh.NumFace; y++)		{			if(mesh.polys[y].vert_face_ind.x == x)			{				//printf("%i found\n", count++);				array_len = mesh.polys[y].v1.neighbor.size();				mesh.polys[y].v1.neighbor.resize(mesh.polys[y].v1.neighbor.size()+1);				mesh.polys[y].v1.neighbor[array_len] = x;			}			if(mesh.polys[y].vert_face_ind.y == x)			{				//printf("%i found\n", count++);				array_len = mesh.polys[y].v1.neighbor.size();				mesh.polys[y].v2.neighbor.resize(mesh.polys[y].v2.neighbor.size()+1);				mesh.polys[y].v2.neighbor[array_len] = x;			}			if(mesh.polys[y].vert_face_ind.z == x)			{				//printf("%i found\n", count++);				array_len = mesh.polys[y].v1.neighbor.size();				mesh.polys[y].v3.neighbor.resize(mesh.polys[y].v3.neighbor.size()+1);				mesh.polys[y].v3.neighbor[array_len] = x;			}		}	}        printf("finished calculating normals...\n");}bool ImportLDM(char* filename){	char sdummy[256];	char cdummy;	int mode = 0; //0-vertex 1-face 2-normal 3-material ID 4-smoothgroup	int count = 0;		vector<tVertex>		Vert;	//TEMPORARILY stores all of the vertex information	//vector<Vector3i>	Face;	//TEMPORARILY stores all of the face winding info	infile = fopen(filename, "r");	if(infile == false)		return false;		fseek(infile, 0L, SEEK_SET);	fscanf(infile, "%i %i", &mesh.NumVert, &mesh.NumFace);	fscanf(infile, "%s", &sdummy);	Vert.resize(mesh.NumVert);	mesh.polys.resize(mesh.NumFace);		while(!feof(infile))	{		cdummy = fgetc(infile);		switch(cdummy)		{			/***set modes for reading data***/			/*******and reset counter********/			case 'v' : mode=0; count=0; break;			case 'f' : mode=1; count=0; break;			case 'n' : mode=2; count=0; mesh.polys.resize(mesh.NumFace); break;			case 'm' : mode=3; count=0; mesh.polys.resize(mesh.NumFace); break;			case 's' : mode=4; count=0; mesh.polys.resize(mesh.NumFace); break;			/********************************/			case '[' : 				switch(mode)				{					case 0:	fscanf(infile, "%f,%f,%f]", 								&Vert[count].x, 								&Vert[count].y, 								&Vert[count].z);							count++;							break;					case 1:	fscanf(infile, "%i,%i,%i]", 								&mesh.polys[count].vert_face_ind.x, 								&mesh.polys[count].vert_face_ind.y, 								&mesh.polys[count].vert_face_ind.z);							mesh.polys[count].vert_face_ind.x--; 							mesh.polys[count].vert_face_ind.y--; 							mesh.polys[count].vert_face_ind.z--;							count++;							break;					case 2:	fscanf(infile, "%f,%f,%f]", 								&mesh.polys[count].fNormal3f.x, 								&mesh.polys[count].fNormal3f.y, 								&mesh.polys[count].fNormal3f.z);							count++;							break;									}				break;			case '#' :				if(mode == 4)				{					fscanf(infile, "{%i}", &mesh.polys[count].smoothgroup);					mesh.polys[count].smoothgroup--;					count++;				}				break;			default:				switch(mode)				{					case 3:	fscanf(infile, "%i", &mesh.polys[count].matid);							mesh.polys[count].matid--;							count++;							break;				}		}	}	int x=0;	for(x=0; x<mesh.NumFace; x++)	{		mesh.polys[x].v1.x = Vert[mesh.polys[x].vert_face_ind.x].x;		mesh.polys[x].v1.y = Vert[mesh.polys[x].vert_face_ind.x].y;		mesh.polys[x].v1.z = Vert[mesh.polys[x].vert_face_ind.x].z;		mesh.polys[x].v2.x = Vert[mesh.polys[x].vert_face_ind.x].x;		mesh.polys[x].v2.y = Vert[mesh.polys[x].vert_face_ind.x].y;		mesh.polys[x].v2.z = Vert[mesh.polys[x].vert_face_ind.x].z;		mesh.polys[x].v3.x = Vert[mesh.polys[x].vert_face_ind.x].x;		mesh.polys[x].v3.y = Vert[mesh.polys[x].vert_face_ind.x].y;		mesh.polys[x].v3.z = Vert[mesh.polys[x].vert_face_ind.x].z;	}	/*printf("vertices:\n");	for(x=0; x<mesh.NumVert; x++)		printf("%f %f %f\n", Vert[x].Vertex3f.x, Vert[x].Vertex3f.y, Vert[x].Vertex3f.z);	printf("indices:\n");	for(x=0; x<mesh.NumFace; x++)		printf("%i %i %i\n", Face[x].x, Face[x].y, Face[x].z);	printf("face normals:\n");	for(x=0; x<mesh.NumFace; x++)		printf("%f %f %f\n", mesh.polys[x].fNormal3f.x, mesh.polys[x].fNormal3f.y, mesh.polys[x].fNormal3f.z);	printf("matid:\n");	for(x=0; x<mesh.NumFace; x++)		printf("%i ", mesh.polys[x].matid);	printf("\nsmoothgroups:\n");	for(x=0; x<mesh.NumFace; x++)		printf("%i ", mesh.polys[x].smoothgroup);	printf("\n");*/	fclose(infile);	CalVertexNormals();	return true;}


im having a bit of a problem with it too. when i run the program it goes through the entire thing but crashes on exit. any ideas? could it just be my compiler? a corrupt file somewhere?

enigma:
i tried the templates and they work, im just not big on having to type out and entire sentence to get to a fwe bytes of data.

This topic is closed to new replies.

Advertisement