Skip to main content
gamedev.net
🔒 Locked

Pointer Problem

Started by Projectgonewrong Mar 8, 2008 at 2:12 PM 10 replies 1.7k views
Original Post
Projectgonewrong
Projectgonewrong

typedef struct
{
	int vertices[3],
		normals[3],
		texcoors[3];
}OBJface;

typedef struct
{
	int numvertices,
		numnormals,
		numtexcoors,
		numfaces;
	
	OBJvertex  *vertex;
	OBJnormal  *normal;
	OBJtexcoor *texcoor;
	OBJface    *face;
	
}OBJ;

void loadobj()
{
      OBJ object;
      int x, y, z, f, loop;

	object.face[f].vertices[loop] = x;
	object.face[f].normals[loop] = y;
	object.face[f].texcoors[loop] = z;

}

Well that isn't all the code obviously since I just declared x, y, z then storing them but the point is that the "object.face[f].[loop]" part has something wrong with it, I'm not the greatest with pointers and this is probably a simple problem.
rip-off
rip-off
You are accessing an uninitialised pointer. Are you using C, or C++?
Projectgonewrong
Projectgonewrong
C++ (oh and it compiles fine it gets a segmentation fault when running though)
rip-off
rip-off
Just because your code compiles doesn't mean its anywhere near correct [smile].

In C++, we use different techniques.
#include <vector>struct Face{    int vertices[3], normals[3], texcoords[3];};struct Object{    std::vector<Vertex> vertices;    std::vector<Normal> normals;    std::vector<TextureCoordinate> texcoords;    std::vector<Face> faces;};


std::vector is a dynamic array, you can add any number of elements to it and it will make room for them. You can access existing elements like an array using [], and you can ask the vector for its current size using the size() member function.
Projectgonewrong
Projectgonewrong
How do initialize the pointer?

I have this: object.face = ( OBJface* )malloc( object.numfaces * sizeof(OBJface) );
rip-off
rip-off
Forget the pointer. Pointers are an implementation detail. What you want to do is store a collection of Faces, TextureCoordinates, Vertices and Normals. The simplest way to do this is to use std::vector. For example, say you are reading the information from a file. If your Face, TextureCoordinates
, Vertex and Normal structures support C++ stream reading operations, you could write it something like this:

#include <vector>#include <string>#include <sstream>#include <fstream>struct Face{    int vertices[3], normals[3], texcoords[3];};struct Object{    std::vector<Vertex> vertices;    std::vector<Normal> normals;    std::vector<TextureCoordinate> texcoords;    std::vector<Face> faces;};Object load( const std::string &name ){   Object object;   std::ifstream file(name.c_str());   // simple text based format of some kind, line by line   std::string input;   while(std::getline(file,input))   {       std::stringstream stream(input);       std::string type;       stream >> type;       if(type == "face")       {           Face face;           if(stream >> face)           {               object.faces.push_back(face);           }       }       else if(type == "texcoord")       {           TextureCoordinate tex;           if(stream >> tex)           {               object.texcoords.push_back(tex);           }       }       else if(type == "normal")       {           Normal normal;           if(stream >> normal)           {               object.normals.push_back(normal);           }       }       else if(type == "vertex")       {           Vertex vertex;           if(stream >> vertex)           {               object.vertices.push_back(vertex);           }       }   }   // you should really do some error checking here   // make sure that all the indices in the object.faces vector   // are inside the range of the other vectors   return object;}


You can then render the object by using array access:
void draw(const Object &object){    for(int i = 0 ; i < object.faces.size() ; ++i )    {        Face &face = object.faces;                // use face indices to lookup the object data        // send to your graphics API of choice    }}

This is all off the top of my head, nothing is compiled or tested.
Darragh
Darragh
Quote:
Original post by Projectgonewrong
How do initialize the pointer?

I have this: object.face = ( OBJface* )malloc( object.numfaces * sizeof(OBJface) );


That will do it. For correctness though be sure to check if the pointer returned from malloc is '0' or null before attempting to use it. You might possibly get a null pointer if your program has run out of heap space / dynamic memory.

e.g if ( object.face != 0 ) { // do something if valid pointer }
rip-off
rip-off
You might as well write in C if you are not going to take advantage of the features C++ gives you. You should at the very least use the allocation method of choice in C++, new (and new []) paired with delete (and delete []). Of course, std::vector is an extremely useful wrapper around the array allocation primitives.
Projectgonewrong
Projectgonewrong
Well I hate to past 132 lines of code but I don't know what the problem is.

#include <iostream>#include <fstream>#include <string>#include <stdio.h>#include <vector>using namespace std;struct OBJvertex{	float   x,			y,			z;};struct OBJnormal{	float   x,			y,			z;};struct OBJtexcoor{	float   u,			v;};struct OBJface{	int vertices[3],		normals[3],		texcoors[3];};struct OBJ{	vector<OBJvertex>   vertex;	vector<OBJnormal>   normal;	vector<OBJtexcoor>  texcoor;	vector<OBJface>     face;	};void load_obj(const char *filename){	OBJ object;	int n=0,t=0,v=0,f=0,loop,count,pos;	float a,x,y,z;	string line, str;	bool normals, tex;	char b;		ifstream load(filename);		while(! load.eof())	{		load >> line;				if( line == "v" )		{			load >> x >> y >> z;			object.vertex[v].x = x;			object.vertex[v].y = y;			object.vertex[v].z = z;			++v;		}				else if( line == "vt" )		{			load >> x >> y;			object.texcoor[t].u = x;			object.texcoor[t].v = y;			++t;		}				else if( line == "vn" )		{			load >> x >> y >> z;			object.normal[n].x = x;			object.normal[n].y = y;			object.normal[n].z = z;			++n;		}				else if( line == "f" )		{			pos = load.tellg();			load >> str;			for( loop=0; loop < (str.size()- 1); ++loop )			{				if( str[loop]=='/')					tex=true;				if( str[loop]=='/' && str[loop+1]=='/' )					normals=false;			}			load.clear();			load.seekg(pos);						for(loop=0; loop<3; ++loop)			{							if( normals == true && tex == true )			{				load >> x >> b >> y >> b >> z;				object.face[f].vertices[loop] = x;				object.face[f].normals[loop] =  y;				object.face[f].texcoors[loop] = z;			}						if( tex == false )			{				load >> x >> b >> b >> z;				object.face[f].vertices[loop] = x;				object.face[f].texcoors[loop] = z;			}							}			++f;		} 	}}int main(){	load_obj("car.obj");return 0;}	
rip-off
rip-off
First of all, you must tell us what isn't working. Is it compiling? If not, post the error. Is it running? If not, post any error. If the logic is failing, post what *is* happening compared with what you *expected* to happen.

From a quick skim of your code, it would appear that you never push_back or resize the vectors. Vectors start empty (unless you tell it otherwise), and can only grow if you call push_back (or certain other functions).

Compare my code and yours, you will note that I add elements using push_back. Also, you don't need to keep a separate count of the number of elements in each vector, you can simply say vector.size() and it will tell you.
i_luv_cplusplus
i_luv_cplusplus
you can't put anything in a vector until you resize it... to resize it one at time I suggest push_back, for example:

if( line == "v" )		{			load >> x >> y >> z;                        OBJvertex vert;			vert.x = x;			vert.y = y;			vert.z = z;                        vertex.push_back(vert); 			++v;		}
OpenGL fanboy.
Projectgonewrong
Projectgonewrong
Now when I run the executable I get this error. (Compiling fine)

terminate called after throwing an instance of 'std::bad_alloc'
what(): std::bad_alloc
Aborted (core dumped)


EDIT: Found the problem for some reason it looped in the "if(line=="f")" part so I just added f="a" in the brackets so it doesn't make a million Faces.

[Edited by - Projectgonewrong on March 8, 2008 9:29:31 PM]

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.