Dark Bit Factory & Gravity

PROGRAMMING => C / C++ /C# => Topic started by: benny! on October 15, 2007

Title: [SEEKING] simple 3D model loading library
Post by: benny! on October 15, 2007
Hi Guys,

is there a simple 3D model loading library for loading and showing models (3ds, asc...)
in a OpenGL window? Preferred is a static lib for Visual C++.

Note: I do not want to include any DirectX stuff.
Title: Re: [SEEKING] simple 3D model loading library
Post by: slippy on October 15, 2007
Hey,

I dunno if it comes in handy for you ... but it was the first thing I thought about while reading your question ... and it's not DX :)

http://lib3ds.sourceforge.net/

Cheers,
SLiPPY
Title: Re: [SEEKING] simple 3D model loading library
Post by: Jim on October 15, 2007
Benny, the code I gave you the zip password for before includes a few model loading codes - if it doesn't let me know, I might have added them later.  The big deal is that the file formats are not that hard to work out - www.wotsit.org (http://www.wotsit.org) is a great link - but every program that wants to load 3d models wants them in a different format internally...so there aren't that many great libraries.  OpenGL has no standard formats, and Direct3D has only .x which is now deprecated.

Jim
Title: Re: [SEEKING] simple 3D model loading library
Post by: benny! on October 15, 2007
@Jim:
Thanks. To be honest - I hoped to find a class in your sources where I could do something
like this :

Code: [Select]
Model model = new Model();
model.load(mesh.3ds);
model.render();

Just had a quick browse through your sources. My problem at the moment is that my time is
really limited - and I try to use as many libraries as I can find which may help me with more
or less standard stuff. So, I try to avoid to do it by myself studying various formats.
Of course, this is rather lazy of me on the one hand - but on the other hand - atm the only
possibilty to do some democoding for me...

Anyway, I will try to have a closer look at your sources in the next days...

@sl!ppy:
Thanks for the link - I will check it out in the next days, too.
Title: Re: [SEEKING] simple 3D model loading library
Post by: benny! on October 17, 2007
Just found the following lib :

http://www.gamedev.net/community/forums/topic.asp?topic_id=385236 (http://www.gamedev.net/community/forums/topic.asp?topic_id=385236)

It works - but it is not exactly what I was looking for. hmm ...


@Jim:
What 3D format do you prefer for simple / static (no anim frames) purposes ?
Title: Re: [SEEKING] simple 3D model loading library
Post by: taj on October 17, 2007
Benny ,

dont know if this does what you want ... but I pieced this together from sources I forget now. My idea was to have a minimal 3ds model loader. Anyway you are welcome to code if it helps.

NOTE Beney (you see what I did there?) it was written using GCC so may barf under VC++ for a moment or two ;-)

Code: [Select]
///////////////////////////////////////////////////////////////////////////////
//  Self contained... 3DS CODE
//  Its baby code, slow and silly, but it works for now
///////////////////////////////////////////////////////////////////////////////

typedef struct vertex_struct{float x,y,z;} vertex;
typedef struct mapcoord_struct{float u,v;} mapcoord;
typedef struct tri_struct{int a,b,c;} tri;

typedef struct object_struct{
    char name[20];
    int numVerts,numPolys;
    vertex v[20000];
    tri p[20000];
    mapcoord m[20000];
} object;


static object swirl;  //our object

void load3dsObject (object *obj, char *filename)
{
FILE *file; //Our file pointer

char temp; //Temporary char for reading name of object
short chunkID; //Stores ID of current chunk.
int chunkLength;

short useless;

file=fopen (filename, "rb");

int i;

//While current position is lesser than the total length
while (ftell(file) < _filelength (fileno (file))) 
{
fread (&chunkID, 2, 1, file);
fread (&chunkLength, 4, 1,file);

switch (chunkID)
                {
case 0x4d4d: //Skip these chunks
break;   
case 0x3d3d:
break;
case 0x4000: //Chunk containing name
for(i=0;i<20;i++)
{
fread (&temp, 1, 1, file);
                                        obj->name[i]=temp;
if(temp == '\0')break;
                                }
break;

case 0x3f80: //Skip again
break;
case 0x4100:
break;
case 0x4110: //Chunk with num of vertices
//followed by their coordinates
fread (&obj->numVerts, sizeof (unsigned short), 1, file);
for (i=0; i<obj->numVerts; i++)
                                {
fread (&obj->v[i].x, sizeof(float), 1, file);
                                        fread (&obj->v[i].y, sizeof(float), 1, file);
fread (&obj->v[i].z, sizeof(float), 1, file);
}
break;
case 0x4120: //Chunk with numPolys and
         //the indices
fread (&obj->numPolys, sizeof (unsigned short), 1, file);
                                for (i=0; i<obj->numPolys; i++)
                                {
fread (&obj->p[i].a, sizeof (unsigned short), 1, file);
fread (&obj->p[i].b, sizeof (unsigned short), 1, file);
fread (&obj->p[i].c, sizeof (unsigned short), 1, file);
fread (&useless, sizeof (unsigned short), 1, file);
}
break;
case 0x4140: //Chunk with texture coords
fread (&useless, sizeof (unsigned short), 1, file);
for (i=0; i<obj->numVerts; i++)
{
fread (&obj->m[i].u, sizeof (float), 1, file);
                                        fread (&obj->m[i].v, sizeof (float), 1, file);
}
                                break;

default:
fseek(file,chunkLength-6, SEEK_CUR);
                  }//switch
}
fclose (file);
}


//OK so draw an object using triangles, dead slow but does allow for some neat
//effects such as explosions and shattering and stuff...
void draw3dsObject(object *obj)
{
int i;

    glBegin(GL_TRIANGLES);
    for (i=0;i<obj->numPolys;i++)
    {
  glTexCoord2f( obj->m[ obj->p[i].a ].u, obj->m[ obj->p[i].a ].v);
        glVertex3f( obj->v[ obj->p[i].a ].x, obj->v[ obj->p[i].a ].y, obj->v[ obj->p[i].a ].z);
glTexCoord2f( obj->m[ obj->p[i].b ].u, obj->m[ obj->p[i].b ].v);
        glVertex3f( obj->v[ obj->p[i].b ].x, obj->v[ obj->p[i].b ].y, obj->v[ obj->p[i].b ].z);
glTexCoord2f( obj->m[ obj->p[i].c ].u, obj->m[ obj->p[i].c ].v);
        glVertex3f( obj->v[ obj->p[i].c ].x, obj->v[ obj->p[i].c ].y, obj->v[ obj->p[i].c ].z);
}
    glEnd();

}

It works - tested, but no normals. This is a big drawback.

Chris
Title: Re: [SEEKING] simple 3D model loading library
Post by: Jim on October 17, 2007
In my prim.cpp, you can just
do
Code: [Select]
GLOBJECT *obj = new GLOBJECT();
obj->load_RWX(filename);
obj->render()
which is what you wanted.  You'd just need to add in OpenGL setup and viewport which is in escher.cpp.
ie.
Code: [Select]
 ogl_init()
  ogl_3d();
  for (;;)
  {
    ogl_cls()
    obj->render();
    ogl_flip()
  }
I use RWX (renderware), OBJ, 3DS ASC, and Milkshape files.  At least the first 3 of those are ascii files and easy to tinker with.

Jim
Title: Re: [SEEKING] simple 3D model loading library
Post by: benny! on October 18, 2007
@Jim / Chris:
Thanks to both of you - I really appreciate your help. I will have a deeper look into
your stuff in the evening !!!
Title: Re: [SEEKING] simple 3D model loading library
Post by: benny! on October 19, 2007
@Chris:
I tested your code - it works like a charme with really tiny modifications with Visual C++
compiler. However I tried to wrap your code in a little class - but now the loader seems
to be fucked and I have _no_ clue why ???

I couted the chunkIDs and realised that after the 13th ChunkID of the attached
3ds modell the CHUNKID varies from the functional loader vs. the loader method of the
class. Maybe I am blind - but I really dont see any differences.



Tiny3ds.h
Code: [Select]
/*
    Tiny3ds

Simple loader class for loading and displaying 3DS files.
Coded by chris!

Class version / VS2005 modifications by benny!weltenkonstrukteur.de
*/
#include <windows.h>
#include <GL/gl.h>
#include <io.h>
#include <iostream>
#include <fstream>

using namespace std;

class Tiny3ds
{
    private:
typedef struct vertex_struct{float x,y,z;} vertex;
typedef struct mapcoord_struct{float u,v;} mapcoord;
typedef struct tri_struct{int a,b,c;} tri;

typedef struct object_struct{
char name[20];
int numVerts,numPolys;
vertex v[20000];
tri p[20000];
mapcoord m[20000];
} object;
object swirl;

float angle;

    public:
Tiny3ds() {};
~Tiny3ds(){};
void load3dsObject (char *filename);
void draw3dsObject();
};


Tiny3ds.cpp
Code: [Select]
/*
    Tiny3ds

Simple loader class for loading and displaying 3DS files.
Coded by chris!

Class version / VS2005 modifications by benny!weltenkonstrukteur.de
*/

#include "Tiny3ds.h"

void Tiny3ds::draw3dsObject(){
int i;
/*
    glTranslatef(0,-1,400.0f);
glRotatef(angle,0.0,1, 0.0);
    angle += 0.2;
*/


    glBegin(GL_TRIANGLES);
for ( i=0; i < this->swirl.numPolys; i++)
    {
glTexCoord2f( this->swirl.m[ this->swirl.p[i].a ].u, this->swirl.m[ this->swirl.p[i].a ].v);
glVertex3f( this->swirl.v[ this->swirl.p[i].a ].x, this->swirl.v[ this->swirl.p[i].a ].y, this->swirl.v[ this->swirl.p[i].a ].z);
glTexCoord2f( this->swirl.m[ this->swirl.p[i].b ].u, this->swirl.m[ this->swirl.p[i].b ].v);
        glVertex3f( this->swirl.v[ this->swirl.p[i].b ].x, this->swirl.v[ this->swirl.p[i].b ].y, this->swirl.v[ this->swirl.p[i].b ].z);
glTexCoord2f( this->swirl.m[ this->swirl.p[i].c ].u, this->swirl.m[ this->swirl.p[i].c ].v);
        glVertex3f( this->swirl.v[ this->swirl.p[i].c ].x, this->swirl.v[ this->swirl.p[i].c ].y, this->swirl.v[ this->swirl.p[i].c ].z);
}
    glEnd();
}

void Tiny3ds::load3dsObject (char *filename) {

FILE *file; //Our file pointer

char temp; //Temporary char for reading name of object
short chunkID; //Stores ID of current chunk.
int chunkLength = 0;

short useless;

file=fopen (filename, "rb");

int i;

int t=0;

//While current position is lesser than the total length
while (ftell(file) < _filelength (fileno (file))) 
{

t++;
fread (&chunkID, 2, 1, file);
fread (&chunkLength, 4, 1,file);

//cout << t << ": " <<  chunkID << "\n";

switch (chunkID)
                {
case 0x4d4d: //Skip these chunks
break;   
case 0x3d3d:
break;
case 0x4000: //Chunk containing name
for(i=0;i<20;i++)
{
fread (&temp, 1, 1, file);
                                        swirl.name[i]=temp;
if(temp == '\0')break;
                                }
break;

case 0x3f80: //Skip again
break;
case 0x4100:
break;
case 0x4110: //Chunk with num of vertices
//followed by their coordinates
cout << swirl.numVerts;

fread (&swirl.numVerts, sizeof (unsigned short), 1, file);

cout << swirl.numVerts;

for (i=0; i<swirl.numVerts; i++) {
fread (&swirl.v[i].x, sizeof(float), 1, file);
                    fread (&swirl.v[i].y, sizeof(float), 1, file);
fread (&swirl.v[i].z, sizeof(float), 1, file);
}
break;

case 0x4120: //Chunk with numPolys and
         //the indices
fread (&swirl.numPolys, sizeof (unsigned short), 1, file);
                                for (i=0; i<swirl.numPolys; i++)
                                {
fread (&swirl.p[i].a, sizeof (unsigned short), 1, file);
fread (&swirl.p[i].b, sizeof (unsigned short), 1, file);
fread (&swirl.p[i].c, sizeof (unsigned short), 1, file);
fread (&useless, sizeof (unsigned short), 1, file);
}
break;
case 0x4140: //Chunk with texture coords
fread (&useless, sizeof (unsigned short), 1, file);
for (i=0; i<swirl.numVerts; i++)
{
fread (&swirl.m[i].u, sizeof (float), 1, file);
                    fread (&swirl.m[i].v, sizeof (float), 1, file);
}
                 break;

default:
fseek(file,chunkLength-6, SEEK_CUR);
                  }//switch
}
fclose (file);
}
Title: Re: [SEEKING] simple 3D model loading library
Post by: benny! on October 19, 2007
@Chris / Jim / all:

I just created a small testing app of this problem - so maybe you all can have a look
if your time permits it.

Just change the commenting of line 49 and 50 in main.cpp to see the different
results of the chunkID from the loader.

Thanks in advance!
Title: Re: [SEEKING] simple 3D model loading library
Post by: taj on October 19, 2007
Benny,

I had a quick look but I'm not a C++ programmer - sorry.

Chris
Title: Re: [SEEKING] simple 3D model loading library
Post by: ninogenio on October 19, 2007
benny shouldnt typedef struct tri_struct{int a,b,c;} tri; be unsigned shorts mate.

ive only got dev c installed atm so i cant tinkering.
Title: Re: [SEEKING] simple 3D model loading library
Post by: Jim on October 19, 2007
The bug is that numVerts and numPolys should be 'short' and not 'int' IN BOTH VERSIONS!  One is just fortunate to get away with it because the top part of the int is set to 0.  In the other it's set to crap...
It's gonna fuck up though, because you have multiple vert/poly chunks in that file.  You need to handle that.

Separate note:
Code: [Select]
mySwirl.~Tiny3ds();
er! wtf!

<edit>
nino's bang on about the tri structure as well, you're loading a short (16bit) over the top of an int (32bit).  In chris' version the object is statically allocated and therefore all set to 0s at startup, so no bug. In yours it's allocated off the heap, so it will contain random junk.

Jim
Title: Re: [SEEKING] simple 3D model loading library
Post by: benny! on October 19, 2007
@Jim:
Awesome. Thanks for the help and the good explenation, Jim !!!
K++

@nino/chris:
Thanks of course to you, too!
Title: Re: [SEEKING] simple 3D model loading library
Post by: taj on October 19, 2007
Karma to jim and nino - hey I can fix my version too now!