Rendering model from .ase file

Started by
7 comments, last by Porthos 15 years, 10 months ago
Hi, I have been working on a class that handles loading, building and then rendering a 3d model that is exported from 3dstudio max in an ase format. Now for the last couple of day I have been banging my head against a wall because there still is some small drawing issues, and I've narrowed it down to the building function. Heres the class:

#ifndef _OBJECT_HG_
#define _OBJECT_HG_

#include <windows.h>
#include <GL/glut.h>
#include <vector>
#include <stdio.h>
#include <string>
#include <fstream>

#include "Vector.h"


using std::vector;
using std::string;
using std::ifstream;

class Object
{	
private:
	vector< CVector* > lstVertices;					
	vector< int >	lstIndicies;					
	vector< bool >	lstDrawLine;						
	Vector*			Vertex;						
        int Indicie;						
	bool DrawLine;
	int Scale;						
	int DisplayList;
	bool IsAlive;
        float Location;
        float Orientation;

	Object( bool UsingModel, bool IsAlive, int Scale ):
		UsingModel( UsingModel ), IsAlive( IsAlive ), Scale( Scale )
        {
        }

	~Object()
        {
	     if( glIsList( DisplayList ) )
	     {
		   glDeleteLists( DisplayList, 1 );
	     }
	     DisplayList = NULL;
        }
	void getModelInfo()
	{
	vector< Vector* >::iterator  itVertices = lstVertices.begin();
	vector< int >::iterator itIndicies = lstIndicies.begin();
	vector< bool >::iterator itDrawLine = lstDrawLine.begin();

	cout << "Vertex: " << endl;
	while( itVertices != lstVertices.end() )
	{
		cout << "Index: " << (*itVertices)->Index <<  "	x: " << (*itVertices)->x << "		y: " << (*itVertices)->y << "		z: " << (*itVertices)->z << endl;	
		++itVertices;
	}

	cout << endl << endl;
	cout << "Index: " << endl;
	while( itIndicies != lstIndicies.end() )
	{
		for( int i = 0; i < 3; ++i )
		{
			cout << (*itIndicies) << "	";
				
			++itIndicies;
		}
		cout << endl;
		
	}
	cout << endl << endl;
	cout << "Connections: " << endl;
	while( itDrawLine != lstDrawLine.end() )
	{
		for( int i = 0; i < 3; ++i )
		{
			cout << (*itDrawLine) << "  ";

			++itDrawLine;
		}
		cout << endl;
	}

	

}
	void loadModel( string fileName )
	{
	ifstream fileReader( fileName.c_str() );
	string keyWord;

	while( !fileReader.eof() )
	{	
		fileReader >> keyWord;
		
		if( keyWord == "*MESH_VERTEX" )
		{	
			Vertex = new CVector();
			
			fileReader >> Vertex->nIndex;
			fileReader >> Vertex->fx;
			fileReader >> Vertex->fy;
			fileReader >> Vertex->fz;
			
			lstVertices.push_back( Vertex );
			
		}
		if( keyWord == "*MESH_FACE" )
		{
			int Index = 0;
			string Point;

			fileReader >> Index;
			fileReader >> Point;
			for( int i = 0; i < 3; ++i )
			{
				fileReader >> Point;
				fileReader >> Indicie;
				lstIndicies.push_back( Indicie );
			}
			for( int i = 0; i < 3; ++i )
			{
				fileReader >> Point;
				fileReader >> DrawLine;
				lstDrawLine.push_back( DrawLine );
			}
				
		}

	}
}
	void Render()	
{
vector< CVector* >::iterator itVertices = lstVertices.begin();
			vector< int >::iterator itIndicies = lstIndicies.begin();

			glPushMatrix();
				
				float Angle = Orientation.y * 180.0f / 3.14159f;
				Angle += 90;
				glTranslatef( Location.x, Location.y, Location.z );

				glRotatef( Angle, 0.0f, 1.0f, 0.0f );
				
				glCallList( DisplayList );
							
			glPopMatrix();
}
	void buildModel()
{
vector< int >::iterator itIndicies = lstIndicies.begin();
	vector< bool >::iterator itDrawLine = lstDrawLine.begin();

	DisplayList = glGenLists( 1 );
	glNewList( DisplayList, GL_COMPILE );
	{
		while( itIndicies != lstIndicies.end() )
		{
			glBegin( GL_TRIANGLE_STRIP );
			glVertex3f(	getVertex( (*itIndicies) ).x*Scale,	getVertex( (*itIndicies) ).yScale,	getVertex( (*itIndicies) ).z*Scale );
			if( (*itDrawLine) == 0 )
			{
				glEnd();
			}
			++itIndicies;
			++itDrawLine;
		}

	}
	glEndList();
{
	CVector getVertex( const int& Index )
{
	vector< CVector* >::iterator itVertices = lstVertices.begin();
	
	while( itVertices != lstVertices.end() )
	{
		if( (*itVertices)->Index == Index )
		{
			Vector Vec( (*itVertices)->x, (*itVertices)->y, (*itVertices)->z );
			return Vec;
		}
		else
		{
			++itVertices;
		}
		
	}

	delete (*itVertices);
	return 0;	
}
	
};

#endif






So how this works is that in your main game loop in the init function I create the object so Player = new Object( true, true, 5); (the constructor is true - am I using my own model, true - is the object alive, and 5 for the scale of the model) then I load my model in the init function like so Player->loadModel( sub ); and then I do Player->buildModel(); so it would make it and store it in the class's display list. Now when I load in simple files from the ase file like a cube or a triangle there are no problems but as soon as I have a little more of a complex item there are issues and I'm pretty sure that it has to do with how I'm building the model into the displaylist. heres an image with the problems and how it looks like inside 3dstudio max: Note: I have highlighted the problem areas with red arrows Image that has problems loading. Heres another model that I tried loading in with similar problems (thats suppos to be a sub =P and heres a sextion of the ase file

*MESH_FACE_LIST {
			*MESH_FACE    0:    A:  363 B:    0 C:  360 AB:    1 BC:    1 CA:    0	 *MESH_SMOOTHING 1 	*MESH_MTLID 0
			*MESH_FACE    1:    A:  360 B:  359 C:  363 AB:    1 BC:    1 CA:    0	 *MESH_SMOOTHING 1 	*MESH_MTLID 0
			*MESH_FACE    2:    A:    2 B:  362 C:  364 AB:    1 BC:    1 CA:    0	 *MESH_SMOOTHING 1 	*MESH_MTLID 0
			*MESH_FACE    3:    A:  364 B:  368 C:    2 AB:    1 BC:    1 CA:    0	 *MESH_SMOOTHING 1 	*MESH_MTLID 0
			*MESH_FACE    4:    A:   46 B:   45 C:   47 AB:    1 BC:    1 CA:    0	 *MESH_SMOOTHING 1 	*MESH_MTLID 0
			*MESH_FACE    5:    A:   47 B:   48 C:   46 AB:    1 BC:    1 CA:    0	 *MESH_SMOOTHING 1 	*MESH_MTLID 0
			*MESH_FACE    6:    A:  373 B:    6 C:  370 AB:    1 BC:    1 CA:    0	 *MESH_SMOOTHING 1 	*MESH_MTLID 0
			*MESH_FACE    7:    A:  370 B:  369 C:  373 AB:    1 BC:    1 CA:    0	 *MESH_SMOOTHING 1 	*MESH_MTLID 0
			*MESH_FACE    8:    A:  382 B:   17 C:  375 AB:    1 BC:    1 CA:    0	 *MESH_SMOOTHING 1 	*MESH_MTLID 0
			*MESH_FACE    9:    A:  375 B:  374 C:  382 AB:    1 BC:    1 CA:    0	 *MESH_SMOOTHING 1 	*MESH_MTLID 0
			*MESH_FACE   10:    A:  391 B:   20 C:  384 AB:    1 BC:    1 CA:    0	 *MESH_SMOOTHING 1 	*MESH_MTLID 0
			*MESH_FACE   11:    A:  384 B:  383 C:  391 AB:    1 BC:    1 CA:    0	 *MESH_SMOOTHING 1 	*MESH_MTLID 0
			*MESH_FACE   12:    A:  396 B:    1 C:  372 AB:    1 BC:    1 CA:    0	 *MESH_SMOOTHING 1 	*MESH_MTLID 0
			*MESH_FACE   13:    A:  372 B:  392 C:  396 AB:    1 BC:    1 CA:    0	 *MESH_SMOOTHING 1 	*MESH_MTLID 0
			*MESH_FACE   14:    A:  393 B:    7 C:   26 AB:    1 BC:    1 CA:    0	 *MESH_SMOOTHING 1 	*MESH_MTLID 0
			*MESH_FACE   15:    A:   32 B:  393 C:   26 AB:    1 BC:    0 CA:    0	 *MESH_SMOOTHING 1 	*MESH_MTLID 0
			*MESH_FACE   16:    A:   32 B:   26 C:   29 AB:    0 BC:    1 CA:    1	 *MESH_SMOOTHING 1 	*MESH_MTLID 0
			*MESH_FACE   17:    A:    5 B:  365 C:  397 AB:    1 BC:    1 CA:    0	 *MESH_SMOOTHING 1 	*MESH_MTLID 0
			*MESH_FACE   18:    A:  397 B:  404 C:    5 AB:    1 BC:    1 CA:    0	 *MESH_SMOOTHING 1 	*MESH_MTLID 0
			*MESH_FACE   19:    A:    3 B:  361 C:  405 AB:    1 BC:    1 CA:    0	 *MESH_SMOOTHING 1 	*MESH_MTLID 0
			*MESH_FACE   20:    A:  405 B:  398 C:    3 AB:    1 BC:    1 CA:    0	 *MESH_SMOOTHING 1 	*MESH_MTLID 0
			*MESH_FACE   21:    A:    6 B:  373 C:  407 AB:    1 BC:    1 CA:    0	 *MESH_SMOOTHING 1 	*MESH_MTLID 0
			*MESH_FACE   22:    A:  407 B:  411 C:    6 AB:    1 BC:    1 CA:    0	 *MESH_SMOOTHING 1 	*MESH_MTLID 0
			*MESH_FACE   23:    A:    0 B:  363 C:  412 AB:    1 BC:    1 CA:    0	 *MESH_SMOOTHING 1 	*MESH_MTLID 0
			*MESH_FACE   24:    A:  412 B:  408 C:    0 AB:    1 BC:    1 CA:    0	 *MESH_SMOOTHING 1 	*MESH_MTLID 0
			*MESH_FACE   25:    A:  413 B:    2 C:  368 AB:    1 BC:    1 CA:    0	 *MESH_SMOOTHING 1 	*MESH_MTLID 0
I'm thinking that I'm either not taking in the area that tells me what indicie is connected to what indicie or again building it wrong with the buildModel function (above). Thanks. [Edited by - kubapl on June 7, 2008 7:51:44 PM]
Advertisement
when i was building my ase loader i had a few problems (i think i still might). one technique i tried was to build smaller, simpler models that utilized the same modeling techniques. try loading them and see what kinds of things turn up.
What do you mean by simpler .. like not applying smooth on them. . .building a model out of multiple objects and then combining at the en versus extruding?
Did you by any chance figure out texture coordinates out of the ase file?
You might want to have a look at Assimp - Open Import Library, which, among others, loads ASE files. Beware, though, it's still maturing. And I'm a bit biased on it, I'm one of the contributors.
----------
Gonna try that "Indie" stuff I keep hearing about. Let's start with Splatter.
Quote:Original post by Schrompf
You might want to have a look at Assimp - Open Import Library, which, among others, loads ASE files. Beware, though, it's still maturing. And I'm a bit biased on it, I'm one of the contributors.


Cool I had a brief look at the doxygen documentation. I'm just wondering if you have a library that I can download and use or is there source code somewhere in there?
Are you sure you should be using GL_TRIANGLE_STRIP instead of GL_TRIANGLES?
The kind of error you get really looks like you should be using a different glBegin() type.

Try compiling the display list with GL_POINTS instead and see if it looks correct.

/Robert
"Game Maker For Life, probably never professional thou." =)
Quote:Original post by kubapl
What do you mean by simpler .. like not applying smooth on them. . .building a model out of multiple objects and then combining at the en versus extruding?


A simpler model like, for example, a cube :)

No i'm not kidding, my first ASE loader I wrote at Uni' suffered from some of the same issues you're seeing. So go right back to the least complex 3d model that you can and get it displaying that.

The advantage of doing this is that you can view the ASE file very easily, and you can step through the entire loading process and write down each loop that the code goes through. Just stepping through that code in a debugger will probably help you spot any errors.

Once it's loaded you can then step through the drawing code as well to verify that it's behaving.

Andy

"Ars longa, vita brevis, occasio praeceps, experimentum periculosum, iudicium difficile"

"Life is short, [the] craft long, opportunity fleeting, experiment treacherous, judgement difficult."

Quote:Original post by kubapl
Quote:Original post by Schrompf
You might want to have a look at Assimp - Open Import Library, which, among others, loads ASE files. Beware, though, it's still maturing. And I'm a bit biased on it, I'm one of the contributors.


Cool I had a brief look at the doxygen documentation. I'm just wondering if you have a library that I can download and use or is there source code somewhere in there?


Seems Schrompf has forgotten to answer here, so I'll do that :-)

Firstly, I'm one of the contributors of ASSIMP, too. And I've written the ASE loader. It loads most models correctly. However, there are still some unfixed bugs in there. But they will be caught, I swear :D In our repos is a ASE test model with some cubes, at least this one works perfectly.

Here's the source code:
http://assimp.svn.sourceforge.net/viewvc/assimp

You can check-out it from the server via Subversion. Or you can send me a PN with your email address, then I'm going to send you a ZIP with the source. Remember, it's under active development although a stable release is not far away.

Best regards,
Alexander

This topic is closed to new replies.

Advertisement