Skip to main content
GameDev.net gamedev.net
🔒 Locked

lib3ds - model displaying problem

Started by Ginyal Mar 7, 2005 at 11:34 AM 20 replies 6.8k views
Original Post
Ginyal
Ginyal
Hi, I have a problem with the displaying of a 3d model in OpenGL which I loaded with the lib3ds library. The problem is that it doesn't seem to draw all faces of the model, here's what I mean: [Program's output.] And here is the code:
#include <allegro.h>
#include <alleggl.h>

#include <gl/glu.h>

#include <lib3ds/camera.h>
#include <lib3ds/file.h>
#include <lib3ds/material.h>
#include <lib3ds/mesh.h>

static Lib3dsFile* katana = NULL; //model file

int init(void) {
	allegro_init();
	install_allegro_gl();
	install_keyboard();
	install_timer();
	
	set_color_depth(24);
	if(set_gfx_mode(GFX_OPENGL_FULLSCREEN, 640, 480, 0, 0) < 0) {
		set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
		allegro_message("Errors:\nAllegro: %s\nAllegroGL: %s", allegro_error, allegro_gl_error);
		return 0;
	}	
	
	//open and check if file is opened
	katana = lib3ds_file_load("..\\models\\katana\\katana.3ds");
	if(!katana) {
		set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
		allegro_message("no katana");
		return 0;
	}
	
	//check for meshes
	if(!katana->meshes) {
		set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
		allegro_message("no meshes");
		return 0;
	}
	
	//check for cameras
	if(!katana->cameras) {
		set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
		allegro_message("no cameras");
		return 0;
	}
	
	//set some opengl parameters
	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);	
	glEnable(GL_LIGHTING);
	glEnable(GL_LIGHT0);	
	glEnable(GL_DEPTH_TEST);
	glDepthFunc(GL_LESS);
	
	return 1;
}

void setcamera(void) {
	Lib3dsCamera* camera = katana->cameras; //camera in model file
	
	//set up viewport and perspective with camera properties
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glViewport(0, 0, SCREEN_W, SCREEN_H);
	gluPerspective(camera->fov, SCREEN_W / SCREEN_H, camera->near_range, camera->far_range);
	
	//set up cameraview
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	gluLookAt(camera->position[0], camera->position[1], camera->position[2],
		camera->target[0], camera->target[1], camera->target[2],
		0.0, 1.0, 0.0);
	
	glFlush();
	allegro_gl_flip();
}

void draw(void) {
	Lib3dsMesh* mesh = katana->meshes; //current mesh in model file
	
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glBegin(GL_TRIANGLES);
	while(mesh) {
		for(unsigned long i = 0; i < mesh->faces; i++) {
			//set material to the current face material
			Lib3dsMaterial* material = lib3ds_file_material_by_name(katana, mesh->faceL.material);
			glMaterialf(GL_FRONT, GL_SHININESS, material->shininess);
			glMaterialfv(GL_FRONT, GL_AMBIENT, material->ambient);
			glMaterialfv(GL_FRONT, GL_DIFFUSE, material->diffuse);
			glMaterialfv(GL_FRONT, GL_SPECULAR, material->specular);
			
			//draw face
			glVertex3fv(mesh->pointL[mesh->faceL.points[0]].pos);
			glVertex3fv(mesh->pointL[mesh->faceL.points[1]].pos);
			glVertex3fv(mesh->pointL[mesh->faceL.points[2]].pos);
		}
		
		//go to next mesh if any
		if(mesh->next) mesh = mesh->next;
		else mesh = NULL;
	}
	glEnd();
	
	glFlush();
	allegro_gl_flip();
}

int main(void) {
	if(!init()) return 0; //initialize
	
	setcamera(); //setup the camera
	
	do {
		draw(); //draw scene
		rest(1000 / 24); //rest
	}while(!keypressed());
	
	return 0;
}
END_OF_MAIN();
My guess is the problem is somehwere in the draw(void) function:
void draw(void) {
	Lib3dsMesh* mesh = katana->meshes; //current mesh in model file
	
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glBegin(GL_TRIANGLES);
	while(mesh) {
		for(unsigned long i = 0; i < mesh->faces; i++) {
			//set material to the current face material
			Lib3dsMaterial* material = lib3ds_file_material_by_name(katana, mesh->faceL.material);
			glMaterialf(GL_FRONT, GL_SHININESS, material->shininess);
			glMaterialfv(GL_FRONT, GL_AMBIENT, material->ambient);
			glMaterialfv(GL_FRONT, GL_DIFFUSE, material->diffuse);
			glMaterialfv(GL_FRONT, GL_SPECULAR, material->specular);
			
			//draw face
			glVertex3fv(mesh->pointL[mesh->faceL.points[0]].pos);
			glVertex3fv(mesh->pointL[mesh->faceL.points[1]].pos);
			glVertex3fv(mesh->pointL[mesh->faceL.points[2]].pos);
		}
		
		//go to next mesh if any
		if(mesh->next) mesh = mesh->next;
		else mesh = NULL;
	}
	glEnd();
	
	glFlush();
	allegro_gl_flip();
}
But I can't find out what I did wrong or what I didn't do at all. So therefore I've come here to ask you humbly for help ([grin]). Thanks in advance.
Jack Sotac
Jack Sotac
It looks like you are not setting the face or vertex normals. This may be causing OpenGl to cull your triangles.

Try glDisable(GL_CULL_FACE) in your init() function. If you can see all your faces , then it means normals are the problem.

Also, you will need to use glNormal*() when using lighting to have the faces lit correctly.
0xa0000000
Ginyal
Ginyal
Hi Jack Sotac, and thanks for your reply! I appreciate it alot, however, normals don't seem to be the problem. I tried disabling culling as you suggested and it left me with the same result.

After that I also changed my draw() function to use normals, it looks like this:
void draw(void) {	Lib3dsMesh* mesh = katana->meshes; //current mesh in model file		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);	glBegin(GL_TRIANGLES);	while(mesh) {		//create the list of required normals		Lib3dsVector* normals = new Lib3dsVector[3 * mesh->faces];		lib3ds_mesh_calculate_normals(mesh, normals);				for(unsigned long i = 0; i < mesh->faces; i++) {			//set material to the current face material			Lib3dsMaterial* material = lib3ds_file_material_by_name(katana, mesh->faceL.material);			glMaterialf(GL_FRONT, GL_SHININESS, material->shininess);			glMaterialfv(GL_FRONT, GL_AMBIENT, material->ambient);			glMaterialfv(GL_FRONT, GL_DIFFUSE, material->diffuse);			glMaterialfv(GL_FRONT, GL_SPECULAR, material->specular);						//draw face			glNormal3fv(normals[3 * i]);			glVertex3fv(mesh->pointL[mesh->faceL.points[0]].pos);			glNormal3fv(normals[3 * i + 1]);			glVertex3fv(mesh->pointL[mesh->faceL.points[1]].pos);			glNormal3fv(normals[3 * i + 2]);			glVertex3fv(mesh->pointL[mesh->faceL.points[2]].pos);		}				delete[] normals;				//go to next mesh if any		if(mesh->next) mesh = mesh->next;		else mesh = NULL;	}	glEnd();		glFlush();	allegro_gl_flip();}


Still no change in the results (except that the lighting of the faces which are visible is a bit different now, that's a good thing atleast). The faces were still missing... I found this hard to believe because when I tried the example program compiled from 'player.c' which is included in the lib3ds library it did load the model alright. So I switched off lighting to see if it would draw the entire model, but surprisingly faces were still missing... does this mean there are faces missing in the model file?
Drew_Benton
Drew_Benton
It could be your grpahics card as well. Try updating your drivers before you get too far into rewriting code. Also, try using another model and see if it works.
Ginyal
Ginyal
I'll try that Drew_Benton, thanks.
rick_appleton
rick_appleton
Which faces are backfacing and which are front facing is not dependent on the normal you pass into OpenGL, but rather the position of the three vertices and the order in which you specify them. Make sure all triangles are specified in counter clockwise order.

Edit: just read you'd already tried to disable culling without results. In that case it would seem that the model does indeed not have those faces.

If the model is a single mesh, could you host the .3ds file somewhere? I'll give a swing with my loader, and see what happens.
Ginyal
Ginyal
Hi rick_appleton. The model has 2 meshes if I'm not mistaking, one named "Blade" and the other named "Scabbard". Either way I've uploaded the file and you can get it from here: katana.3ds
rick_appleton
rick_appleton

So the file seems to be okay. The only thing that might be happening is that maybe the sword and the scabberd are overlapping, and the sword has a black color or so?

Do the meshes show up if you use only a solid color?
Ginyal
Ginyal
Well, I tried that. Drawing the model in a white color for example using glColor3f() and glVertex3fv(). But the result remains the same, only the triangles are now white. When I'm at home I'll try to draw the meshes seperately. Thanks rick_appleton.

[edit]still no change in the result... even when i draw the meshes seperately faces still seem to be missing[/edit]

[Edited by - Ginyal on March 10, 2005 10:52:25 AM]
rick_appleton
rick_appleton
If you want, I can send you my 3DS loading code, but I doubt it's better than 3dslib.

What I did when I was testing my 3ds loading code, is remove parts of the mesh in 3dsmax, re-export, reload into my program and display. Then see what happens. If the problem persists, you should be able to reduce the mesh to only a couple of triangles, at which point you can check what's going on by stepping through the code and confirming everything is alright.
Ginyal
Ginyal
I would do that, but I got this model from a website and I don't have 3ds Max.
Ginyal
Ginyal
Hi lonesock, thanks for your advice. I tried it, but the values are the same.
CRACK123
CRACK123
Have you got this working yet?
The more applications I write, more I find out how less I know
Ginyal
Ginyal
nope...
CRACK123
CRACK123
I will try your model. I am using lib3ds for my engine and 3ds files load fine.

The more applications I write, more I find out how less I know
CRACK123
CRACK123
I tried your model, it loads fine for me. No issues with loading it with lib3ds. However I can't find anything wrong with your code either.
The more applications I write, more I find out how less I know
Drew_Benton
Drew_Benton
Ginyal, if you can make a demo if this, I can run it on my compter and see if it works. It just may be your video card's properties. Since CRACK123 tried it and it worked, I am really thinking that is the problem.
CRACK123
CRACK123
Hi,

There is one thing in the code. You dont seem to use any of the transformation ? Possibly this could be the cause. You need to apply the node transformation as well as the mesh transformation. So it essentially will be something like this

while(mesh) {                            if(!nodes->user.d) {                    glMultMatrixf(node->matrix); //                     Lib3dsObjectData *d = &pNodes->data.object;                    glTranslatef(-d->pivot[0], -d->pivot[1], -d->pivot[2]);		                }                glMultMatrixf(mesh->matrix);		for(unsigned long i = 0; i < mesh->faces; i++) {			//set material to the current face material			Lib3dsMaterial* material = lib3ds_file_material_by_name(katana, mesh->faceL.material);			glMaterialf(GL_FRONT, GL_SHININESS, material->shininess);			glMaterialfv(GL_FRONT, GL_AMBIENT, material->ambient);			glMaterialfv(GL_FRONT, GL_DIFFUSE, material->diffuse);			glMaterialfv(GL_FRONT, GL_SPECULAR, material->specular);						//draw face			glVertex3fv(mesh->pointL[mesh->faceL.points[0]].pos);			glVertex3fv(mesh->pointL[mesh->faceL.points[1]].pos);			glVertex3fv(mesh->pointL[mesh->faceL.points[2]].pos);		}				//go to next mesh if any		if(mesh->next) mesh = mesh->next;		else mesh = NULL;                node = node->next;	}	glEnd();


Possibly this can easily explain the missing triangles. I doubt its your card or drivers as you yourself say that lib3ds example file loads it fine. But if you look carefully at the example source you will see that applying the transformations are extremely important.
The more applications I write, more I find out how less I know

Topic Locked

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

Sign in to reply to this topic.