Sign in to follow this  
Gauge

classes overwriting data

Recommended Posts

Here is the scenario. I am loading a custom .obj file into a c++ class container. I can load as many non textured objects as I want. I can load a single textured object, however when loading 2 textured objects I get a segmentation fault. I've been staring at this for a couple of hours now and decided to post on here. It's only overwriting the vtIndex data, which also happens to be the only pointer(go figure) If you can please take a quick pass at this and if you see something let me know. I'm mostly concerned with taking in the vtIndex data and pushing it on to a vector.
void BaseObject::LoadData(string filename)
{
	string garbage2 = "";
	char garbage;
	point temp;
	uvPoint temp2;
     face tempFace;
	group tempGroup;
	materialIndex tempMat;

	tempMat.polyIndex = 0;
	tempGroup.groupRotation.x = 0;
	tempGroup.groupRotation.y = 0;
	tempGroup.groupRotation.z = 0;
     tempFace.vtIndex = NULL;

	ifstream infile, infile2;
	infile.open(filename.c_str());
	infile2.open(pivotLoc.c_str());

	while(infile)
	{
		infile >> garbage;
		if(garbage == '#')
		{
			getline(infile, garbage2);
		}
		else if(garbage == 'm')
		{
			infile >> garbage2;
			infile >> materialLoc;
		}
		else if(garbage == 'v')
		{
			infile >> garbage;
			if(garbage == 'n')
			{
				infile >> temp.x >> temp.y >> temp.z;
				vn.push_back(temp);
			}
			else if(garbage == 't')
			{
				infile >> temp2.x >> temp2.y;
				vt.push_back(temp2);
			}
			else
			{
				infile.unget();
				infile >> temp.x >> temp.y >> temp.z;
				v.push_back(temp);
			}
		}
		else if(garbage == 'g')
		{
			numGroups++;
			infile>> tempGroup.groupName;
			infile >> garbage;

			while(garbage == 'f' || garbage == 'u')
			{
				if(garbage == 'u')
				{
					infile >> garbage2;
					infile >> tempMat.materialName;
					infile >> garbage;
				}

				while(garbage == 'f')
				{	
					infile >> tempFace.vIndex[0] >> garbage;
					infile >> garbage;
					if(garbage != '/')
					{
						infile.unget();
                              tempFace.vtIndex = new int[3];
						infile >> tempFace.vtIndex[0] >> garbage >> tempFace.vnIndex[0];
						infile >> tempFace.vIndex[1] >> garbage >> tempFace.vtIndex[1] >> garbage >> tempFace.vnIndex[1];
						infile >> tempFace.vIndex[2] >> garbage >> tempFace.vtIndex[2] >> garbage >> tempFace.vnIndex[2];
                              tempGroup.faces.push_back(tempFace);
                              tempFace.vtIndex = NULL;
						tempMat.polyIndex++;
						infile >> garbage;
					}
					else
					{
						infile >> tempFace.vnIndex[0];
						infile >> tempFace.vIndex[1] >> garbage >> garbage >> tempFace.vnIndex[1];
						infile >> tempFace.vIndex[2] >> garbage >> garbage >> tempFace.vnIndex[2];
                              tempGroup.faces.push_back(tempFace);
						tempMat.polyIndex++;
						infile >> garbage;
					}
				}
				tempGroup.materials.push_back(tempMat);
			}
			infile.unget();

			infile2 >> garbage2;
			while(infile2)
			{
				if(garbage2 == "push")
				{
					infile2 >> garbage2;
					if(garbage2 == tempGroup.groupName)
					{
						infile2 >> tempGroup.pivotPoint.x >> tempGroup.pivotPoint.y >> tempGroup.pivotPoint.z;
					}
				}
				infile2 >> garbage2;
			}
			groups.push_back(tempGroup);
			tempGroup.groupName = "";
               tempGroup.faces.clear();
			tempGroup.materials.clear();
			tempGroup.pivotPoint.x = 0;
			tempGroup.pivotPoint.y = 0;
			tempGroup.pivotPoint.z = 0;
               tempMat.polyIndex = 0;	
		}
	}
	infile.close();
	infile2.close();
}

The section I'm most concerned with is this.
while(garbage == 'f')
				{	
					infile >> tempFace.vIndex[0] >> garbage;
					infile >> garbage;
					if(garbage != '/')
					{
						infile.unget();
                              tempFace.vtIndex = new int[3];
						infile >> tempFace.vtIndex[0] >> garbage >> tempFace.vnIndex[0];
						infile >> tempFace.vIndex[1] >> garbage >> tempFace.vtIndex[1] >> garbage >> tempFace.vnIndex[1];
						infile >> tempFace.vIndex[2] >> garbage >> tempFace.vtIndex[2] >> garbage >> tempFace.vnIndex[2];
                              tempGroup.faces.push_back(tempFace);
                              tempFace.vtIndex = NULL;
						tempMat.polyIndex++;
						infile >> garbage;
					}
					else
					{
						infile >> tempFace.vnIndex[0];
						infile >> tempFace.vIndex[1] >> garbage >> garbage >> tempFace.vnIndex[1];
						infile >> tempFace.vIndex[2] >> garbage >> garbage >> tempFace.vnIndex[2];
                              tempGroup.faces.push_back(tempFace);
						tempMat.polyIndex++;
						infile >> garbage;
					}
				}

thanks in advance

Share this post


Link to post
Share on other sites
That isn't really enough to go on. Post the class definition, as well as the constructor(s). Also, since you're using pointers, I assume you've correctly defined a destructor, a copy constructor, and an assignment operator, right?

Share this post


Link to post
Share on other sites
I'm not sure if there's enough information there to determine what the problem is. Have you stepped through it with the debugger? Do you know which line of code appears to be triggering the segmentation fault?

It looks like there could be some ownership issues with vtIndex, which I imagine could be causing problems elsewhere in your code. Also, will vtIndex always have a size of 3? Or can its size vary?

Share this post


Link to post
Share on other sites
Yes vtIndex will always have 3 values. It's wierd that it works loading one object but not two. Anyways here is the beef.

here is the .C, also I'm always calling the 2 string constructor for now.


#include "BaseObject.h"

BaseObject::BaseObject()
{
materialLoc = pivotLoc = stateLoc = "";
numGroups = 0;
objectTranslation.x = 0.0;
objectTranslation.y = 0.0;
objectTranslation.z = 0.0;
objectRotation.x = 0.0;
objectRotation.y = 0.0;
objectRotation.z = 0.0;
oldObjectRotation.x = 0.0;
oldObjectRotation.y = 0.0;
oldObjectRotation.z = 0.0;
loaded = false;
}

BaseObject::BaseObject(string filename)
{
materialLoc = pivotLoc = stateLoc = "";
numGroups = 0;
objectTranslation.x = 0.0;
objectTranslation.y = 0.0;
objectTranslation.z = 0.0;
objectRotation.x = 0.0;
objectRotation.y = 0.0;
objectRotation.z = 0.0;
oldObjectRotation.x = 0.0;
oldObjectRotation.y = 0.0;
oldObjectRotation.z = 0.0;
LoadData(filename);
loaded = false;
}

BaseObject::BaseObject(string filename, string tempLoc)
{
materialLoc = stateLoc = "";
pivotLoc = tempLoc;
numGroups = 0;
objectTranslation.x = 0.0;
objectTranslation.y = 0.0;
objectTranslation.z = 0.0;
objectRotation.x = 0.0;
objectRotation.y = 0.0;
objectRotation.z = 0.0;
oldObjectRotation.x = 0.0;
oldObjectRotation.y = 0.0;
oldObjectRotation.z = 0.0;
LoadData(filename);
loaded = false;
}

BaseObject::BaseObject(string filename, string tempLoc, string tempState)
{
materialLoc = "";
pivotLoc = tempLoc;
stateLoc = tempState;
numGroups = 0;
objectTranslation.x = 0.0;
objectTranslation.y = 0.0;
objectTranslation.z = 0.0;
objectRotation.x = 0.0;
objectRotation.y = 0.0;
objectRotation.z = 0.0;
oldObjectRotation.x = 0.0;
oldObjectRotation.y = 0.0;
oldObjectRotation.z = 0.0;
LoadData(filename);
loaded = false;
}

BaseObject::~BaseObject()
{
for(int i = 0 ; i < groups.size() ; i++)
{
groups[i].materials.clear();
for(int x = 0 ; x < groups[i].faces.size() ; x++)
{
if(groups[i].faces[x].vtIndex != NULL)
{
delete groups[i].faces[x].vtIndex;
groups[i].faces[x].vtIndex = NULL;
}
}
groups[i].faces.clear();
}
groups.clear();
v.clear();
vn.clear();
vt.clear();
}

void BaseObject::ChangeLoadState(bool state)
{
loaded = state;
}

bool BaseObject::Loaded() const
{
return loaded;
}

void BaseObject::SetStateLoc(string tempState)
{
stateLoc = tempState;
}

void BaseObject::SetObjectRotation(float x, float y, float z)
{
objectRotation.x = x;
objectRotation.y = y;
objectRotation.z = z;
}

void BaseObject::SetObjectTranslation(float x, float y, float z)
{
objectTranslation.x = x;
objectTranslation.y = y;
objectTranslation.z = z;
}

void BaseObject::SetOldObjectRotation(float x, float y, float z)
{
oldObjectRotation.x = x;
oldObjectRotation.y = y;
oldObjectRotation.z = z;
}

rotation BaseObject::GetObjectRotation() const
{
return objectRotation;
}

rotation BaseObject::GetOldObjectRotation() const
{
return oldObjectRotation;
}

point BaseObject::GetObjectTranslation() const
{
return objectTranslation;
}

void BaseObject::SetPivotLoc(string tempLoc)
{
pivotLoc = tempLoc;
}

string BaseObject::GetPivotLoc() const
{
return pivotLoc;
}

string BaseObject::GetStateLoc() const
{
return stateLoc;
}

int BaseObject::NumGroups() const
{
return numGroups;
}

string BaseObject::GetMaterialLoc() const
{
return materialLoc;
}

vector<point>::iterator BaseObject::GetVBegin()
{
return v.begin();
}

vector<point>::iterator BaseObject::GetVEnd()
{
return v.end();
}

vector<uvPoint>::iterator BaseObject::GetVtBegin()
{
return vt.begin();
}
vector<uvPoint>::iterator BaseObject::GetVtEnd()
{
return vt.end();
}

vector<point>::iterator BaseObject::GetVnBegin()
{
return vn.begin();
}

vector<point>::iterator BaseObject::GetVnEnd()
{
return vn.end();
}

vector<group>::iterator BaseObject::GetGroupsBegin()
{
return groups.begin();
}

vector<group>::iterator BaseObject::GetGroupsEnd()
{
return groups.end();
}

void BaseObject::Print(ofstream& outfile)
{
for(int i = 0 ; i < groups.size() ; i++)
{
outfile << "GROUP " << groups[i].groupName << endl;
for(int x = 0 ; x < groups[i].faces.size() ; x++)
{
outfile << "f " << groups[i].faces[x].vIndex[0] << "/" <<groups[i].faces[x].vtIndex[0]<< "/" <<groups[i].faces[x].vnIndex[0] << " ";
outfile << groups[i].faces[x].vIndex[1] << "/" <<groups[i].faces[x].vtIndex[1]<< "/" <<groups[i].faces[x].vnIndex[1] << " ";
outfile << groups[i].faces[x].vIndex[2] << "/" <<groups[i].faces[x].vtIndex[2]<< "/" <<groups[i].faces[x].vnIndex[2] << endl;
}
}
}

void BaseObject::LoadData(string filename)
{
string garbage2 = "";
char garbage;
point temp;
uvPoint temp2;
face tempFace;
group tempGroup;
materialIndex tempMat;

tempMat.polyIndex = 0;
tempGroup.groupRotation.x = 0;
tempGroup.groupRotation.y = 0;
tempGroup.groupRotation.z = 0;
tempFace.vtIndex = NULL;

ifstream infile, infile2;
infile.open(filename.c_str());
infile2.open(pivotLoc.c_str());

while(infile)
{
infile >> garbage;
if(garbage == '#')
{
getline(infile, garbage2);
}
else if(garbage == 'm')
{
infile >> garbage2;
infile >> materialLoc;
}
else if(garbage == 'v')
{
infile >> garbage;
if(garbage == 'n')
{
infile >> temp.x >> temp.y >> temp.z;
vn.push_back(temp);
}
else if(garbage == 't')
{
infile >> temp2.x >> temp2.y;
vt.push_back(temp2);
}
else
{
infile.unget();
infile >> temp.x >> temp.y >> temp.z;
v.push_back(temp);
}
}
else if(garbage == 'g')
{
numGroups++;
infile>> tempGroup.groupName;
infile >> garbage;

while(garbage == 'f' || garbage == 'u')
{
if(garbage == 'u')
{
infile >> garbage2;
infile >> tempMat.materialName;
infile >> garbage;
}

while(garbage == 'f')
{
infile >> tempFace.vIndex[0] >> garbage;
infile >> garbage;
if(garbage != '/')
{
infile.unget();
tempFace.vtIndex = new int[3];
infile >> tempFace.vtIndex[0] >> garbage >> tempFace.vnIndex[0];
infile >> tempFace.vIndex[1] >> garbage >> tempFace.vtIndex[1] >> garbage >> tempFace.vnIndex[1];
infile >> tempFace.vIndex[2] >> garbage >> tempFace.vtIndex[2] >> garbage >> tempFace.vnIndex[2];
tempGroup.faces.push_back(tempFace);
tempFace.vtIndex = NULL;
tempMat.polyIndex++;
infile >> garbage;
}
else
{
infile >> tempFace.vnIndex[0];
infile >> tempFace.vIndex[1] >> garbage >> garbage >> tempFace.vnIndex[1];
infile >> tempFace.vIndex[2] >> garbage >> garbage >> tempFace.vnIndex[2];
tempGroup.faces.push_back(tempFace);
tempMat.polyIndex++;
infile >> garbage;
}
}
tempGroup.materials.push_back(tempMat);
}
infile.unget();

infile2 >> garbage2;
while(infile2)
{
if(garbage2 == "push")
{
infile2 >> garbage2;
if(garbage2 == tempGroup.groupName)
{
infile2 >> tempGroup.pivotPoint.x >> tempGroup.pivotPoint.y >> tempGroup.pivotPoint.z;
}
}
infile2 >> garbage2;
}
groups.push_back(tempGroup);
tempGroup.groupName = "";
tempGroup.faces.clear();
tempGroup.materials.clear();
tempGroup.pivotPoint.x = 0;
tempGroup.pivotPoint.y = 0;
tempGroup.pivotPoint.z = 0;
tempMat.polyIndex = 0;
}
}
infile.close();
infile2.close();
}





here is the .h


#ifndef JESS_OBJ
#define JESS_OBJ 1337

#include <iostream>
#include <fstream>
#include <vector>
#include <map>
#include <string>
#include <cmath>
#include <gl/gl.h>
#include <gl/glu.h>
#include <gl/glut.h>
#include <gl/glext.h>
#include <sdl/sdl.h>
#include <sdl/SDL_opengl.h>

using namespace std;

struct uvPoint
{
float x, y;
};

struct point
{
float x, y, z;
};

struct face
{
int vIndex[3];
int vnIndex[3];
int* vtIndex;
};

struct rotation
{
float x, y, z;
};

struct materialIndex
{
string materialName;
int polyIndex;
};

struct group
{
string groupName;
vector<materialIndex> materials;
vector<face> faces;
point pivotPoint;
rotation groupRotation, oldGroupRotation;
GLuint groupCompileIndex;
};

class BaseObject
{
public:
BaseObject();
BaseObject(string);
BaseObject(string, string);
BaseObject(string, string, string);
~BaseObject();
void Print(ofstream&);
bool Loaded() const;
int NumGroups() const;
string GetMaterialLoc() const;
string GetPivotLoc() const;
string GetStateLoc() const;
void ChangeLoadState(bool);
void SetPivotLoc(string);
void SetStateLoc(string);
void SetObjectRotation(float, float, float);
void SetObjectTranslation(float, float, float);
void SetOldObjectRotation(float, float, float);
rotation GetObjectRotation() const;
rotation GetOldObjectRotation() const;
point GetObjectTranslation() const;
vector<point>::iterator GetVBegin();
vector<point>::iterator GetVEnd();
vector<uvPoint>::iterator GetVtBegin();
vector<uvPoint>::iterator GetVtEnd();
vector<point>::iterator GetVnBegin();
vector<point>::iterator GetVnEnd();
vector<group>::iterator GetGroupsBegin();
vector<group>::iterator GetGroupsEnd();
protected:
void LoadData(string);
private:
vector<point> v;
vector<point> vn;
vector<uvPoint> vt;
vector<group> groups;
rotation objectRotation, oldObjectRotation;
point objectTranslation;
string materialLoc, pivotLoc, stateLoc;
int numGroups;
bool loaded;
};

#endif





Some things I tested. I just added that print function and it isn't anything I'm doing. It is the action of loading them that is screwing it up. All I did was start a basic c++ program and load 2 objects and the firsts vtIndex was messed up and the second one wasn't. It's strange.

Thanks for taking a look guys. I'm in iraq so I don't have as much time as I would like to debug :P

EDIT: also sry about the tabs, I've been cross platform coding for this, so the tabbing in kwrite and dev c++ is different. I remedied the situation bye making a tab 5 spaces on both but have not had time to go back and fix the old ones.

EDIT AGAIN: Yes i'm aware of the rule of three. For now I'm trying to solve this. No where am I making an object from another one, or assigning an object to another one. The only pertinent one is the destructor, which I have, but which would also not mess with the data.

Share this post


Link to post
Share on other sites
Quote:
Yes vtIndex will always have 3 values. It's wierd that it works loading one object but not two. Anyways here is the beef.
If vtIndex will always have three values, why allocate memory for it dynamically? Why not just make it a fixed-sized array with three elements?

Share this post


Link to post
Share on other sites
Quote:
Original post by jyk
Quote:
Yes vtIndex will always have 3 values. It's wierd that it works loading one object but not two. Anyways here is the beef.
If vtIndex will always have three values, why allocate memory for it dynamically? Why not just make it a fixed-sized array with three elements?


I knew someone would ask this lol. Because not every face will have texture map data. I did this to save space. This is for a rendering engine that will be drawing buttloads of faces, so space will be an issue.

Share this post


Link to post
Share on other sites
Quote:
Original post by Gauge
I knew someone would ask this lol. Because not every face will have texture map data. I did this to save space. This is for a rendering engine that will be drawing buttloads of faces, so space will be an issue.
If you are rendering large meshes, you need to be using a vertex buffer system (details differ between DirectX and OpenGL), rather than rendering face-by-face, as you must be currently. OBJ is a very antiquated format, and not a good example to base your render structures on.

Share this post


Link to post
Share on other sites
Quote:
Original post by Gauge
No where am I making an object from another one, or assigning an object to another one. The only pertinent one is the destructor, which I have, but which would also not mess with the data.


Not that you're aware of; but it happens behind the scenes when you put the instances in a vector. In particular, you dynamically allocate memory in the 'face' and then put them in the 'faces' vector member of a 'group'. And anyway, the whole point of the Rule of Three is that the fact that you have written a destructor points to the likely need to write the other two. Because, you know, Copying Happens (TM) in a language with default value semantics.

Share this post


Link to post
Share on other sites
Quote:
Original post by Zahlman
Not that you're aware of; but it happens behind the scenes when you put the instances in a vector. In particular, you dynamically allocate memory in the 'face' and then put them in the 'faces' vector member of a 'group'. And anyway, the whole point of the Rule of Three is that the fact that you have written a destructor points to the likely need to write the other two. Because, you know, Copying Happens (TM) in a language with default value semantics.


As I was writing I realized something. This is my code to set up my object list.
BaseObject one(string, string2)
pushback one
baseobject two(samestring, samestring2)
pushback two
so yeah I I now feel retarded. I'll write both the assignment and copy, but for reference which one is happening on a vector pushback?

Also wierd it works for one object but not two. I'll test the print functions before and after pushbacks.

Share this post


Link to post
Share on other sites
Quote:
Original post by Gauge
I'll write both the assignment and copy, but for reference which one is happening on a vector pushback?
Copy constructor. STL containers use copy construction whenever they have to move things around.

Share this post


Link to post
Share on other sites
Btw, use the one true operator=(tm) by default:

class example {
public:
void swap(example& other); // does a swap!
example(const example& other); // a copy construct
example& operator=( const example& other ) {
example tmp = other;
this->swap(tmp);
return *this;
}
}

Assuming a functioning swap (which is easy to write -- just call swap on _every_ field in your object) and a functioning constructor (which you will be running alot if you are using std::vectors), this generates a functioning operator= that is exception safe and generally all happy-happy joy-joy.

And it looks exactly the same in every single class.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this