Dark Bit Factory & Gravity

PROGRAMMING => Other languages => Blitz => Topic started by: Pixel_Outlaw on September 01, 2007

Title: Help loading .3ds files with OpenGL (Bmax)
Post by: Pixel_Outlaw on September 01, 2007

Hello,

I have gotten to the point in OpenGL where I would like to add models into my game. I currently have a program that exports them as .3ds files. What I want to do is save all the data from the file into a custom type.

I've been looking through some tutorials in loading such a file and the whole "chunk" reading is difficult for me to grasp. I havn't done any work with byte value reading either.

I was wondering if anyone has written any types/functions to read and store models for rendering in BMAX. I have quite a few things up in the air with my game right now and it would just be best for me to have something precoded if anyone has created such a thing. It's kind of a shame that Bmax supports OpenGL but nobody has done much in the way of functions for OpenGL libraries written in Bmax.
Title: Re: Help loading .3ds files with OpenGL (Bmax)
Post by: va!n on September 01, 2007
possible this may help you... i found the source but i am not sure who is the org author... :(

Code: [Select]

Strict
Global ScreenW=800,screenH=600
Global wireframe

init()

'    ------------------------------------------------------------------------------
'    Type Vertex, contient les positions des vertices.
'    ------------------------------------------------------------------------------
Type Vertex
    Field x:Float,y:Float,z:Float
   
    Method constructor(vx:Float,vy:Float,vz:Float)'assigne des coordonnees a un vertex cree
        x=vx; y=vy; z=vz
    End Method
End Type

'    ------------------------------------------------------------------------------
'    Type Polygone, contient les informations sur le vertices des ploygones(classe par ID)
'    ------------------------------------------------------------------------------
Type Polygone
    Field v1,v2,v3
    Field flag
    Field id_mat
   
    Method constructor(a,b,c)'assigne les vertices au polygone
        v1=a; v2=b; v3=c
    End Method
End Type

'    ------------------------------------------------------------------------------
'    Type MapCoord Contient les coordonnees des textures sur les polygones
'    ------------------------------------------------------------------------------
Type MapCoord
    Field u:Float,v:Float
   
    Method constructor(mu:Float,mv:Float)
        u=mu; v=mv
    End Method
End Type

'    ------------------------------------------------------------------------------
'    Type Objet Contient les polygones des sous objets d une scene
'    ------------------------------------------------------------------------------
Type Objet
    Field nom:String
    Field nombre_vertices,nombre_polygones,nombre_coordonnees
    Field n_vertex,n_polygone,n_mapCoord
    Field v:vertex[]
    Field p:polygone[]
    Field m:mapCoord[]
    Global texture:Int[],texture_name:String[],texture_path:String[],n_texture
   
    Method resizeV()
        v=v[..nombre_vertices]
    End Method
    Method resizeP()
        p=p[..nombre_polygones]
    End Method
    Method resizeM()
        m=m[..nombre_coordonnees]
    End Method
    Method assignTexture(tex,pathfile:String,texname:String)
        texture=texture[..n_texture+1] '????Comprend pas array out of bound
        texture_name=texture_name[..n_texture+1]
        texture_path=texture_path[..n_texture+1]
        DebugLog n_texture
        texture_path[n_texture]=pathfile
        texture[n_texture]=tex
        texture_name[n_texture]=texname
        n_texture :+1
        Return n_texture-1
    End Method
    Method initTextureArray()
        texture=texture[..n_texture] '????Comprend pas array out of bound
        texture_name=texture_name[..n_texture]
        texture_path=texture_path[..n_texture]
    End Method
   
    Method NewVertex(vx:Float,vy:Float,vz:Float)
        'DebugLog n_vertex+"-"+vx+" "+vy+" "+vz
        v[n_vertex]=New vertex
        v[n_vertex].x=vx;v[n_vertex].y=vy;v[n_vertex].z=vz
        n_vertex:+1
    End Method
   
    Method newPolygon(a,b,c,flag:Short=0)
        'DebugLog n_polygone+"-"+a+" "+b+" "+c
        p[n_polygone]=New polygone
        p[n_polygone].v1=a;p[n_polygone].v2=b;p[n_polygone].v3=c
        p[n_polygone].flag=flag
        n_polygone:+1
    End Method
   
    Method newMapCoord(u:Float,v:Float)
        'DebugLog n_mapCoord+"-"+u+" "+v
        m[n_mapCoord]=New mapCoord
        m[n_mapCoord].u=u;m[n_mapCoord].v=v
        n_mapCoord:+1
    End Method
   
    Method draw()
        Local l
        'DebugLog texture
       
       
        For l=0 To nombre_polygones-1
            'glColor3f Rnd(1),Rnd(1),Rnd(1)
            glBindTexture (GL_TEXTURE_2D,texture[p[l].id_mat])
            'DebugLog p[l].id_mat
            glBegin GL_TRIANGLES
            glTexCoord2f m[p[l].v1].u,m[p[l].v1].v
            glVertex3f v[p[l].v1].x, v[p[l].v1].y, v[p[l].v1].z
            glTexCoord2f m[p[l].v2].u,m[p[l].v2].v
            glVertex3f v[p[l].v2].x, v[p[l].v2].y, v[p[l].v2].z
            glTexCoord2f m[p[l].v3].u,m[p[l].v3].v
            glVertex3f v[p[l].v3].x, v[p[l].v3].y, v[p[l].v3].z
            glEnd
        Next
       
    End Method
   
    Method LoadTexture(filePath:String,texname:String,filter=2)
        Local img:TPixmap
        Local texture
        filepath=Lower$(filepath)
        If Right$(filepath,3)="png"
            img=LoadPixmapPNG(filePath)
            texture=bglTexFromPixmap(img,True)
        ElseIf Right$(filepath,3)="jpg"
            img=LoadPixmap(filePath)
            texture=bglTexFromPixmap(img,True)
        EndIf   
        If img=Null Or texture=Null Return 0
        glBindTexture (GL_TEXTURE_2D,texture)
        If filter=0
            glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR)
            glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR)
        ElseIf filter=1
            glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST)
            glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST)
        ElseIf filter=2   
            glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR)
            glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST)
        EndIf
        Return assignTexture(texture,filepath,texname)
       
    End Method
   
End Type

'    ------------------------------------------------------------------------------
'    Type Scene Contient les textures et les sous objets de .. ..
'    ------------------------------------------------------------------------------
Type Scene
    Field path:String
    Field directory:String
    Field o:Objet[],nombre_objets=-1
    Field listObjet:TList,obj:objet
    Field size
   
    Method New()
        If listObjet=Null Then listObjet=New TList
    End Method
   
    Method resizeO()
        nombre_objets:+1
        o=o[..nombre_objets]
    End Method
   
    Method load3ds(file:String)
       
        Local stream,id_noeud:String,taille_noeud,b:Byte,l,newobj:Objet,texture_name:String
        stream=ReadStream(file)
        If stream=0 Then Return 0
        size=FileSize(file)
        DebugLog "Open "+file+" | Size:"+size
       
        Local char:String
        Repeat
            l:+1
            char=Mid$(file,Len(file)-l,1)
        Until char="/"
        directory=Left$(file,Len(file)-l)
        Print "Directory="+directory
       
        While Not Eof(stream)
            id_noeud=Right$(Upper$(Hex$(ReadShort(stream))),4)
            taille_noeud=Readint(stream)
           
            DebugLog "Id="+id_noeud+"  taille="+taille_noeud
           
            Select id_noeud
                Case "4D4D" 'Noeud Principal
                'Case "0002" 'Version
                    'version=readint(stream)
                Case "3D3D" 'Editeur
                Case "4000" 'nom de l objet
                    resizeO()
                    newobj=New objet
                    listObjet.AddLast newobj
                    DebugLog "Nouvel objet "+nombre_objets
                    Repeat '???????????????????? peut etre limite a 20 char?
                        b=ReadByte(stream)   
                        If b=0 Exit
                        newobj.nom:+Chr(b)                       
                    Until b = 0
                    DebugLog "Nom ="+newobj.nom
                Case "4100" 'regroupe les donnees/positions des points, faces
                Case "4110" 'liste des vertices   
                    newobj.nombre_vertices=ReadShort(stream)
                    newobj.resizeV()
                    DebugLog "    Vertices:"+newobj.nombre_vertices
                    For l = 0 To newobj.nombre_vertices-1
                        newobj.newVertex(ReadFloat(stream),ReadFloat(stream),ReadFloat(stream))
                    Next
                Case "4120"
                    Local a,b,c
                    newobj.nombre_polygones=ReadShort(stream)
                    newobj.resizeP()
                    DebugLog "    Polygones:"+newobj.nombre_polygones
                    For l=0 To newobj.nombre_polygones-1
                        newobj.newPolygon(ReadShort(stream),ReadShort(stream),ReadShort(stream))
                        ReadShort(stream)
                    Next
                Case "4130"
                    newobj.initTextureArray()
                    Local mat_name:String="",id_mat,face_n,id_poly
                    Repeat
                        b=ReadByte(stream)
                        If b=0 Exit
                        mat_name:+Chr(b)
                    Until b=0
                   
                    DebugLog "Assign "+mat_name +" as material. "+newobj.n_texture
                    For l= 0 To newobj.n_texture 'donne l id du materiel en echange de son nom
                                            '(pour l utiliser dans les arrays)
                        If mat_name=newobj.texture_name[l]
                            id_mat=l
                            Exit
                        EndIf
                    Next
                    face_n=ReadShort(stream)
                    DebugLog "N FACE TO TEX TO "+mat_name+":"+face_n
                    For l=0 To face_n-1
                        id_poly=ReadShort(stream)
                        newobj.p[id_poly].id_mat=id_mat
                        'DebugLog "="newobj.p[id_poly].id_mat
                    Next
                Case "4140"
                    newobj.nombre_Coordonnees=ReadShort(stream)
                    newobj.resizeM()
                    DebugLog "    MapCoord"+newobj.nombre_Coordonnees
                    For l=0 To newobj.nombre_Coordonnees-1
                        newobj.newMapCoord(ReadFloat(stream),ReadFloat(stream))
                    Next                   
               
                Case "AFFF" 'textures
                   
                    Case "A000"
                        texture_name=""
                        Repeat
                            b=ReadByte(stream)
                            If b=0 Exit
                            texture_name:+Chr(b)
                        Until b=0
                        DebugLog "Nom Texture:"+texture_name
                    Case "A200"'le fichier contient une texture
                        newobj=New objet
                    Case "A300"
                        Local texture_path:String
                        Repeat
                            b=ReadByte(stream)
                            If b=0 Exit
                            texture_path:+Chr(b)
                        Until b=0
                        DebugLog "Path to  Texture:"+texture_path
                        newobj.loadtexture(directory+texture_path,texture_name)
                   
                   
                Default
                    SeekStream(stream,StreamPos(stream)-6+taille_noeud)
            End Select
        Wend
        CloseStream stream
        DebugLog "*** Fichier Ferme ***"
    End Method
   
    Method draw()
        For obj=EachIn ListObjet
            obj.draw()
        Next
    End Method
End Type

Function init()
    bglCreateContext ScreenW,ScreenH
    glEnable GL_TEXTURE_2D
    glShadeModel(GL_SMOOTH)
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)
    glEnable GL_DEPTH_TEST
    glMatrixMode GL_PROJECTION
    glLoadIdentity()
    glFrustum -0.1, 0.1,-0.1, 0.1, 0.1, 10000.0
    glMatrixMode GL_MODELVIEW
    glLoadIdentity()
End Function

Function key()
    If KeyHit(KEY_F1)
        If wireframe=0
            wireframe=1
            glPolygonMode (GL_FRONT_AND_BACK,GL_POINT ) 'dessinne les poly comme des points
            'le 1er parametre peut etre GL_FRONT ou GL_BACK aussi
        ElseIf wireframe=1
            wireframe=2
            glPolygonMode (GL_FRONT_AND_BACK,GL_LINE ) 'comme des ligne (wireframe)
        ElseIf wireframe=2
            wireframe=0
            glPolygonMode (GL_FRONT_AND_BACK, GL_FILL ) 'dessinne les poly remplits
        EndIf
       
    EndIf
End Function


Local s:scene=New scene
s.load3ds("obj/essai2tex.3ds")
Local r:Float

While Not KeyHit(KEY_ESCAPE)
    key()
    glClear GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT 'nettoye les buffer(tampon) de couleur et de profondeur
    glLoadIdentity
    'gluLookAt(0,0,-500,    0,0,5,     0, 1, 0);
    glTranslatef 0,0,-200
    r:+.1
    If r>360 r:-360
    glRotatef r,1,.5,0
   
    s.draw()

   
   
    bglSwapBuffers
Wend
Title: Re: Help loading .3ds files with OpenGL (Bmax)
Post by: Pixel_Outlaw on September 01, 2007
Thanks for your help but the code won't compile. It seems to tip over commands regarding the buffer and image loading. Perhaps it is blitzbasic?
Title: Re: Help loading .3ds files with OpenGL (Bmax)
Post by: JumpMan on September 03, 2007
I am trying also to learn OGL through bmax and I am finding it hard to learn it due to the lack of users interest I guess. I posted a few questions
but never got an answer. any way on the code above some of the ogl commands there were modified to a more standardized format. Mostly all that start with Bgl...   are now just Gl some commands were ommitted and some were merged with the standard blitzmax commands. I don't know if I fixed it correctly sence I don't have any 3ds files but it runs with out any errors in my pc. I hope it works fine.
Code: [Select]
Strict
Global ScreenW=800,screenH=600
Global wireframe

init()

'    ------------------------------------------------------------------------------
'    Type Vertex, contient les positions des vertices.
'    ------------------------------------------------------------------------------
Type Vertex
    Field x:Float,y:Float,z:Float
   
    Method constructor(vx:Float,vy:Float,vz:Float)'assigne des coordonnees a un vertex cree
        x=vx; y=vy; z=vz
    End Method
End Type

'    ------------------------------------------------------------------------------
'    Type Polygone, contient les informations sur le vertices des ploygones(classe par ID)
'    ------------------------------------------------------------------------------
Type Polygone
    Field v1,v2,v3
    Field flag
    Field id_mat
   
    Method constructor(a,b,c)'assigne les vertices au polygone
        v1=a; v2=b; v3=c
    End Method
End Type

'    ------------------------------------------------------------------------------
'    Type MapCoord Contient les coordonnees des textures sur les polygones
'    ------------------------------------------------------------------------------
Type MapCoord
    Field u:Float,v:Float
   
    Method constructor(mu:Float,mv:Float)
        u=mu; v=mv
    End Method
End Type

'    ------------------------------------------------------------------------------
'    Type Objet Contient les polygones des sous objets d une scene
'    ------------------------------------------------------------------------------
Type Objet
    Field nom:String
    Field nombre_vertices,nombre_polygones,nombre_coordonnees
    Field n_vertex,n_polygone,n_mapCoord
    Field v:vertex[]
    Field p:polygone[]
    Field m:mapCoord[]
    Global texture:Int[],texture_name:String[],texture_path:String[],n_texture
   
    Method resizeV()
        v=v[..nombre_vertices]
    End Method
    Method resizeP()
        p=p[..nombre_polygones]
    End Method
    Method resizeM()
        m=m[..nombre_coordonnees]
    End Method
    Method assignTexture(tex,pathfile:String,texname:String)
        texture=texture[..n_texture+1] '????Comprend pas array out of bound
        texture_name=texture_name[..n_texture+1]
        texture_path=texture_path[..n_texture+1]
        DebugLog n_texture
        texture_path[n_texture]=pathfile
        texture[n_texture]=tex
        texture_name[n_texture]=texname
        n_texture :+1
        Return n_texture-1
    End Method
    Method initTextureArray()
        texture=texture[..n_texture] '????Comprend pas array out of bound
        texture_name=texture_name[..n_texture]
        texture_path=texture_path[..n_texture]
    End Method
   
    Method NewVertex(vx:Float,vy:Float,vz:Float)
        'DebugLog n_vertex+"-"+vx+" "+vy+" "+vz
        v[n_vertex]=New vertex
        v[n_vertex].x=vx;v[n_vertex].y=vy;v[n_vertex].z=vz
        n_vertex:+1
    End Method
   
    Method newPolygon(a,b,c,flag:Short=0)
        'DebugLog n_polygone+"-"+a+" "+b+" "+c
        p[n_polygone]=New polygone
        p[n_polygone].v1=a;p[n_polygone].v2=b;p[n_polygone].v3=c
        p[n_polygone].flag=flag
        n_polygone:+1
    End Method
   
    Method newMapCoord(u:Float,v:Float)
        'DebugLog n_mapCoord+"-"+u+" "+v
        m[n_mapCoord]=New mapCoord
        m[n_mapCoord].u=u;m[n_mapCoord].v=v
        n_mapCoord:+1
    End Method
   
    Method draw()
        Local l
        'DebugLog texture
       
       
        For l=0 To nombre_polygones-1
            'glColor3f Rnd(1),Rnd(1),Rnd(1)
            glBindTexture (GL_TEXTURE_2D,texture[p[l].id_mat])
            'DebugLog p[l].id_mat
            glBegin GL_TRIANGLES
            glTexCoord2f m[p[l].v1].u,m[p[l].v1].v
            glVertex3f v[p[l].v1].x, v[p[l].v1].y, v[p[l].v1].z
            glTexCoord2f m[p[l].v2].u,m[p[l].v2].v
            glVertex3f v[p[l].v2].x, v[p[l].v2].y, v[p[l].v2].z
            glTexCoord2f m[p[l].v3].u,m[p[l].v3].v
            glVertex3f v[p[l].v3].x, v[p[l].v3].y, v[p[l].v3].z
            glEnd
        Next
       
    End Method
   
    Method LoadTexture(filePath:String,texname:String,filter=2)
        Local img:TPixmap
        Local texture
        filepath=Lower$(filepath)
        If Right$(filepath,3)="png"
            img=LoadPixmapPNG(filePath)
            texture=GLTexFromPixmap(img,True)
        ElseIf Right$(filepath,3)="jpg"
            img=LoadPixmap(filePath)
            texture=GLTexFromPixmap(img,True)
        EndIf   
        If img=Null Or texture=Null Return 0
        glBindTexture (GL_TEXTURE_2D,texture)
        If filter=0
            glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR)
            glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR)
        ElseIf filter=1
            glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST)
            glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST)
        ElseIf filter=2   
            glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR)
            glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST)
        EndIf
        Return assignTexture(texture,filepath,texname)
       
    End Method
   
End Type

'    ------------------------------------------------------------------------------
'    Type Scene Contient les textures et les sous objets de .. ..
'    ------------------------------------------------------------------------------
Type Scene
    Field path:String
    Field directory:String
    Field o:Objet[],nombre_objets=-1
    Field listObjet:TList,obj:objet
    Field size
   
    Method New()
        If listObjet=Null Then listObjet=New TList
    End Method
   
    Method resizeO()
        nombre_objets:+1
        o=o[..nombre_objets]
    End Method
   
    Method load3ds(file:String)
       
        Local stream:TStream,id_noeud:String,taille_noeud,b:Byte,l,newobj:Objet,texture_name:String
        stream=ReadStream(file)
        If stream=Null Then Return 0
        size=FileSize(file)
        DebugLog "Open "+file+" | Size:"+size
       
        Local char:String
        Repeat
            l:+1
            char=Mid$(file,Len(file)-l,1)
        Until char="/"
        directory=Left$(file,Len(file)-l)
        Print "Directory="+directory
       
        While Not Eof(stream)
            id_noeud=Right$(Upper$(Hex$(ReadShort(stream))),4)
            taille_noeud=ReadInt(stream)
           
            DebugLog "Id="+id_noeud+"  taille="+taille_noeud
           
            Select id_noeud
                Case "4D4D" 'Noeud Principal
                'Case "0002" 'Version
                    'version=readint(stream)
                Case "3D3D" 'Editeur
                Case "4000" 'nom de l objet
                    resizeO()
                    newobj=New objet
                    listObjet.AddLast newobj
                    DebugLog "Nouvel objet "+nombre_objets
                    Repeat '???????????????????? peut etre limite a 20 char?
                        b=ReadByte(stream)   
                        If b=0 Exit
                        newobj.nom:+Chr(b)                       
                    Until b = 0
                    DebugLog "Nom ="+newobj.nom
                Case "4100" 'regroupe les donnees/positions des points, faces
                Case "4110" 'liste des vertices   
                    newobj.nombre_vertices=ReadShort(stream)
                    newobj.resizeV()
                    DebugLog "    Vertices:"+newobj.nombre_vertices
                    For l = 0 To newobj.nombre_vertices-1
                        newobj.newVertex(ReadFloat(stream),ReadFloat(stream),ReadFloat(stream))
                    Next
                Case "4120"
                    Local a,b,c
                    newobj.nombre_polygones=ReadShort(stream)
                    newobj.resizeP()
                    DebugLog "    Polygones:"+newobj.nombre_polygones
                    For l=0 To newobj.nombre_polygones-1
                        newobj.newPolygon(ReadShort(stream),ReadShort(stream),ReadShort(stream))
                        ReadShort(stream)
                    Next
                Case "4130"
                    newobj.initTextureArray()
                    Local mat_name:String="",id_mat,face_n,id_poly
                    Repeat
                        b=ReadByte(stream)
                        If b=0 Exit
                        mat_name:+Chr(b)
                    Until b=0
                   
                    DebugLog "Assign "+mat_name +" as material. "+newobj.n_texture
                    For l= 0 To newobj.n_texture 'donne l id du materiel en echange de son nom
                                            '(pour l utiliser dans les arrays)
                        If mat_name=newobj.texture_name[l]
                            id_mat=l
                            Exit
                        EndIf
                    Next
                    face_n=ReadShort(stream)
                    DebugLog "N FACE TO TEX TO "+mat_name+":"+face_n
                    For l=0 To face_n-1
                        id_poly=ReadShort(stream)
                        newobj.p[id_poly].id_mat=id_mat
                        'DebugLog "="newobj.p[id_poly].id_mat
                    Next
                Case "4140"
                    newobj.nombre_Coordonnees=ReadShort(stream)
                    newobj.resizeM()
                    DebugLog "    MapCoord"+newobj.nombre_Coordonnees
                    For l=0 To newobj.nombre_Coordonnees-1
                        newobj.newMapCoord(ReadFloat(stream),ReadFloat(stream))
                    Next                   
               
                Case "AFFF" 'textures
                   
                    Case "A000"
                        texture_name=""
                        Repeat
                            b=ReadByte(stream)
                            If b=0 Exit
                            texture_name:+Chr(b)
                        Until b=0
                        DebugLog "Nom Texture:"+texture_name
                    Case "A200"'le fichier contient une texture
                        newobj=New objet
                    Case "A300"
                        Local texture_path:String
                        Repeat
                            b=ReadByte(stream)
                            If b=0 Exit
                            texture_path:+Chr(b)
                        Until b=0
                        DebugLog "Path to  Texture:"+texture_path
                        newobj.loadtexture(directory+texture_path,texture_name)
                   
                   
                Default
                    SeekStream(stream,StreamPos(stream)-6+taille_noeud)
            End Select
        Wend
        CloseStream stream
        DebugLog "*** Fichier Ferme ***"
    End Method
   
    Method draw()
        For obj=EachIn ListObjet
            obj.draw()
        Next
    End Method
End Type

Function init()
    GLGraphics ScreenW,ScreenH
    glEnable GL_TEXTURE_2D
    glShadeModel(GL_SMOOTH)
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)
    glEnable GL_DEPTH_TEST
    glMatrixMode GL_PROJECTION
    glLoadIdentity()
    glFrustum -0.1, 0.1,-0.1, 0.1, 0.1, 10000.0
    glMatrixMode GL_MODELVIEW
    glLoadIdentity()
End Function

Function key()
    If KeyHit(KEY_F1)
        If wireframe=0
            wireframe=1
            glPolygonMode (GL_FRONT_AND_BACK,GL_POINT ) 'dessinne les poly comme des points
            'le 1er parametre peut etre GL_FRONT ou GL_BACK aussi
        ElseIf wireframe=1
            wireframe=2
            glPolygonMode (GL_FRONT_AND_BACK,GL_LINE ) 'comme des ligne (wireframe)
        ElseIf wireframe=2
            wireframe=0
            glPolygonMode (GL_FRONT_AND_BACK, GL_FILL ) 'dessinne les poly remplits
        EndIf
       
    EndIf
End Function


Local s:scene=New scene
s.load3ds("obj/essai2tex.3ds")

Local r:Float

While Not KeyHit(KEY_ESCAPE)
    key()
    glClear GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT 'nettoye les buffer(tampon) de couleur et de profondeur
    glLoadIdentity
    'gluLookAt(0,0,-500,    0,0,5,     0, 1, 0);
    glTranslatef 0,0,-200
    r:+.1
    If r>360 r:-360
    glRotatef r,1,.5,0
   
    s.draw()
Flip()
Wend
Title: Re: Help loading .3ds files with OpenGL (Bmax)
Post by: Pixel_Outlaw on September 03, 2007
Well I try to load a simple model and it appears to freeze.  The new code appears to have a leak somewhere.

I'll attach a model for example. :)
Title: Re: Help loading .3ds files with OpenGL (Bmax)
Post by: JumpMan on September 03, 2007
I think there is something wrong with the code itself I. I started testing it and found out that you have to put the 3ds file in a subfolder then access it with a "foldername\file name". then I get an error while reading the file. and sence I don't know how 3ds files are stored, I am stuck.   
Title: Re: Help loading .3ds files with OpenGL (Bmax)
Post by: Pixel_Outlaw on September 03, 2007
Well from what I understand the .3ds file format is split into Boolean chunks. I guess these chunks hold all the data for faces and points ect...
MY main problem is simply reading the data from the file. I'm more of a hobbyist programmer and haven't had the need to fiddle around with boolean file reading with exception cases in the data. It would seem that the whole blitz community has just accepted the 100 $ blitz3d as the only alternative. I've looked through a few loaders and they seem very complex to convert to blitzmax. I made some of my models dynamically in game and they were very difficult and time consuming to design.

I'm looking forward to preconstructed models mainly for their complexity and data regarding texture mapping and material mapping and normals data. I just hope sombody can crack this code. The original spanish programmer seemd  to know what he was doing. It's just a bit difficult for my current understanding of programming. I DO however understand how OpenGL works.
Title: Re: Help loading .3ds files with OpenGL (Bmax)
Post by: Jim on September 03, 2007
Problem is the 3ds format is complicated and you're probably going to have to put some effort into finding out why it doesn't work by yourself.  The code that's been posted looks pretty reasonable (the core of it where it's parsing the 3ds file) and I suspect what you really want to do is rip that bit out and make it fill in your own data structures rather than trying to use the rendering code that's there too.

The Method load3ds is where the good stuff is.  Each block in the file is a 2byte header id followed by the data for that type, including the length of the block.  What is doing is scanning for blocks that it knows and processing them, and then skipping over the ones it wants to ignore.

Jim
Title: Re: Help loading .3ds files with OpenGL (Bmax)
Post by: JumpMan on September 03, 2007
I been trying to figure this thing out. I think is that it expect the model to have a texture included. and it doesn't compensate for not having one thus giving an error. I remarked all of the lines that have anything to do with texture output and modified a couple of lines that have to do with texture to bypass if no texture is present and it seems to work. I really don't know if that is how it supposed to work sence this is the first time I do anything threed with ogl and 3ds. here is the code
Code: [Select]

Strict
Global ScreenW=800,screenH=600
Global wireframe

init()

'    ------------------------------------------------------------------------------
'    Type Vertex, contient les positions des vertices.
'    ------------------------------------------------------------------------------
Type Vertex
    Field x:Float,y:Float,z:Float
   
    Method constructor(vx:Float,vy:Float,vz:Float)'assigne des coordonnees a un vertex cree
        x=vx; y=vy; z=vz
    End Method
End Type

'    ------------------------------------------------------------------------------
'    Type Polygone, contient les informations sur le vertices des ploygones(classe par ID)
'    ------------------------------------------------------------------------------
Type Polygone
    Field v1,v2,v3
    Field flag
    Field id_mat
   
    Method constructor(a,b,c)'assigne les vertices au polygone
        v1=a; v2=b; v3=c
    End Method
End Type

'    ------------------------------------------------------------------------------
'    Type MapCoord Contient les coordonnees des textures sur les polygones
'    ------------------------------------------------------------------------------
Type MapCoord
    Field u:Float,v:Float
   
    Method constructor(mu:Float,mv:Float)
        u=mu; v=mv
    End Method
End Type

'    ------------------------------------------------------------------------------
'    Type Objet Contient les polygones des sous objets d une scene
'    ------------------------------------------------------------------------------
Type Objet
    Field nom:String
    Field nombre_vertices,nombre_polygones,nombre_coordonnees
    Field n_vertex,n_polygone,n_mapCoord
    Field v:vertex[]
    Field p:polygone[]
    Field m:mapCoord[]
    Global texture:Int[],texture_name:String[],texture_path:String[],n_texture
   
    Method resizeV()
        v=v[..nombre_vertices]
    End Method
    Method resizeP()
        p=p[..nombre_polygones]
    End Method
    Method resizeM()
        m=m[..nombre_coordonnees]
    End Method
    Method assignTexture(tex,pathfile:String,texname:String)
        texture=texture[..n_texture+1] '????Comprend pas array out of bound
        texture_name=texture_name[..n_texture+1]
        texture_path=texture_path[..n_texture+1]
        DebugLog "n_texture "+n_texture
       
texture_path[n_texture]=pathfile
        texture[n_texture]=tex
        texture_name[n_texture]=texname
        n_texture :+1
        Return n_texture-1
    End Method
    Method initTextureArray()
        texture=texture[..n_texture] '????Comprend pas array out of bound
        texture_name=texture_name[..n_texture]
        texture_path=texture_path[..n_texture]
    End Method
   
    Method NewVertex(vx:Float,vy:Float,vz:Float)
        'DebugLog n_vertex+"-"+vx+" "+vy+" "+vz
        v[n_vertex]=New vertex
        v[n_vertex].x=vx;v[n_vertex].y=vy;v[n_vertex].z=vz
        n_vertex:+1
    End Method
   
    Method newPolygon(a,b,c,flag:Short=0)
        'DebugLog n_polygone+"-"+a+" "+b+" "+c
        p[n_polygone]=New polygone
        p[n_polygone].v1=a;p[n_polygone].v2=b;p[n_polygone].v3=c
        p[n_polygone].flag=flag
        n_polygone:+1
    End Method
   
    Method newMapCoord(u:Float,v:Float)
        'DebugLog n_mapCoord+"-"+u+" "+v
        m[n_mapCoord]=New mapCoord
        m[n_mapCoord].u=u;m[n_mapCoord].v=v
        n_mapCoord:+1
    End Method
   
    Method draw()
        Local l
        'DebugLog texture
       
        Print nombre_polygones-1
        For l=0 To nombre_polygones-1

            'glColor3f Rnd(1),Rnd(1),Rnd(1)
            If n_texture glBindTexture (GL_TEXTURE_2D,texture[p[l].id_mat])
            'DebugLog p[l].id_mat
            glBegin GL_TRIANGLES
            'glTexCoord2f m[p[l].v1].u,m[p[l].v1].v
            glVertex3f v[p[l].v1].x, v[p[l].v1].y, v[p[l].v1].z
            'glTexCoord2f m[p[l].v2].u,m[p[l].v2].v
            glVertex3f v[p[l].v2].x, v[p[l].v2].y, v[p[l].v2].z
            'glTexCoord2f m[p[l].v3].u,m[p[l].v3].v
            glVertex3f v[p[l].v3].x, v[p[l].v3].y, v[p[l].v3].z
            glEnd
        Next
       
    End Method
   
    Method LoadTexture(filePath:String,texname:String,filter=2)
        Local img:TPixmap
        Local texture
        filepath=Lower$(filepath)
        If Right$(filepath,3)="png"
            img=LoadPixmapPNG(filePath)
            texture=GLTexFromPixmap(img,True)
        ElseIf Right$(filepath,3)="jpg"
            img=LoadPixmap(filePath)
            texture=GLTexFromPixmap(img,True)
        EndIf   
        If img=Null Or texture=Null Return 0
        glBindTexture (GL_TEXTURE_2D,texture)
        If filter=0
            glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR)
            glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR)
        ElseIf filter=1
            glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST)
            glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST)
        ElseIf filter=2   
            glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR)
            glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST)
        EndIf
        Return assignTexture(texture,filepath,texname)
       
    End Method
   
End Type

'    ------------------------------------------------------------------------------
'    Type Scene Contient les textures et les sous objets de .. ..
'    ------------------------------------------------------------------------------
Type Scene
    Field path:String
    Field directory:String
    Field o:Objet[],nombre_objets=-1
    Field listObjet:TList,obj:objet
    Field size
   
    Method New()
        If listObjet=Null Then listObjet=New TList
    End Method
   
    Method resizeO()
        nombre_objets:+1
        o=o[..nombre_objets]
    End Method
   
    Method load3ds(file:String)
       
        Local stream:TStream,id_noeud:String,taille_noeud,b:Byte,l,newobj:Objet,texture_name:String
        stream=ReadStream(file)
        If stream=Null Then Return 0
        size=FileSize(file)
        DebugLog "Open "+file+" | Size:"+size
       
        Local char:String
        Repeat
            l:+1
            char=Mid$(file,Len(file)-l,1)
        Until char="/"
        directory=Left$(file,Len(file)-l)
        Print "Directory="+directory
       
        While Not Eof(stream)
            id_noeud=Right$(Upper$(Hex$(ReadShort(stream))),4)
            taille_noeud=ReadInt(stream)
           
            DebugLog "Id="+id_noeud+"  taille="+taille_noeud
           
            Select id_noeud
                Case "4D4D" 'Noeud Principal
                'Case "0002" 'Version
                    'version=readint(stream)
                Case "3D3D" 'Editeur
                Case "4000" 'nom de l objet
                    resizeO()
                    newobj=New objet
                    listObjet.AddLast newobj
                    DebugLog "Nouvel objet "+nombre_objets
                    Repeat '???????????????????? peut etre limite a 20 char?
                        b=ReadByte(stream)   
                        If b=0 Exit
                        newobj.nom:+Chr(b)                       
                    Until b = 0
                    DebugLog "Nom ="+newobj.nom
                Case "4100" 'regroupe les donnees/positions des points, faces
                Case "4110" 'liste des vertices   
                    newobj.nombre_vertices=ReadShort(stream)
                    newobj.resizeV()
                    DebugLog "    Vertices:"+newobj.nombre_vertices
                    For l = 0 To newobj.nombre_vertices-1
                        newobj.newVertex(ReadFloat(stream),ReadFloat(stream),ReadFloat(stream))
                    Next
                Case "4120"
                    Local a,b,c
                    newobj.nombre_polygones=ReadShort(stream)
                    newobj.resizeP()
                    DebugLog "    Polygones:"+newobj.nombre_polygones
                    For l=0 To newobj.nombre_polygones-1
                        newobj.newPolygon(ReadShort(stream),ReadShort(stream),ReadShort(stream))
                        ReadShort(stream)
                    Next
                Case "4130"
                    newobj.initTextureArray()
                    Local mat_name:String="",id_mat,face_n,id_poly
                    Repeat
                        b=ReadByte(stream)
                        If b=0 Exit
                        mat_name:+Chr(b)
                    Until b=0
                    DebugLog "Assign "+mat_name +" as material. "+newobj.n_texture
                    If newobj.n_texture
For l= 0 To newobj.n_texture 'donne l id du materiel en echange de son nom '(pour l utiliser dans les arrays)
                        If mat_name=newobj.texture_name[l]
                            id_mat=l
                            Exit
                        EndIf
                    Next
EndIf
                    face_n=ReadShort(stream)
                    DebugLog "N FACE TO TEX TO "+mat_name+":"+face_n
                    For l=0 To face_n-1
                        id_poly=ReadShort(stream)
                        newobj.p[id_poly].id_mat=id_mat
                        'DebugLog "="newobj.p[id_poly].id_mat
                    Next
                Case "4140"
                    newobj.nombre_Coordonnees=ReadShort(stream)
                    newobj.resizeM()
                    DebugLog "    MapCoord"+newobj.nombre_Coordonnees
                    For l=0 To newobj.nombre_Coordonnees-1
                        newobj.newMapCoord(ReadFloat(stream),ReadFloat(stream))
                    Next                   
               
                Case "AFFF" 'textures
                   
                    Case "A000"
                        texture_name=""
                        Repeat
                            b=ReadByte(stream)
                            If b=0 Exit
                            texture_name:+Chr(b)
                        Until b=0
                        DebugLog "Nom Texture:"+texture_name
                    Case "A200"'le fichier contient une texture
                        newobj=New objet
                    Case "A300"
                        Local texture_path:String
                        Repeat
                            b=ReadByte(stream)
                            If b=0 Exit
                            texture_path:+Chr(b)
                        Until b=0
                        DebugLog "Path to  Texture:"+texture_path
                        newobj.loadtexture(directory+texture_path,texture_name)
                   
                   
                Default
                    SeekStream(stream,StreamPos(stream)-6+taille_noeud)
            End Select
        Wend
        CloseStream stream
        DebugLog "*** Fichier Ferme ***"
    End Method
   
    Method draw()
        For obj=EachIn ListObjet
            obj.draw()
        Next
    End Method
End Type

Function init()
    GLGraphics ScreenW,ScreenH
    glEnable GL_TEXTURE_2D
    glShadeModel(GL_SMOOTH)
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)
    glEnable GL_DEPTH_TEST
    glMatrixMode GL_PROJECTION
    glLoadIdentity()
    glFrustum -0.1, 0.1,-0.1, 0.1, 0.5, 10000.0
    glMatrixMode GL_MODELVIEW
    glLoadIdentity()
End Function

Function key()
    If KeyHit(KEY_F1)
        If wireframe=0
            wireframe=1
            glPolygonMode (GL_FRONT_AND_BACK,GL_POINT ) 'dessinne les poly comme des points
            'le 1er parametre peut etre GL_FRONT ou GL_BACK aussi
        ElseIf wireframe=1
            wireframe=2
            glPolygonMode (GL_FRONT_AND_BACK,GL_LINE ) 'comme des ligne (wireframe)
        ElseIf wireframe=2
            wireframe=0
            glPolygonMode (GL_FRONT_AND_BACK, GL_FILL ) 'dessinne les poly remplits
        EndIf
       
    EndIf
End Function


Local s:scene=New scene
s.load3ds("news/teapot.3ds")
Local r:Float

While Not KeyHit(KEY_ESCAPE)
    key()
    glClear GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT 'nettoye les buffer(tampon) de couleur et de profondeur
    glLoadIdentity
    'gluLookAt(0,0,-500,    0,0,5,     0, 1, 0);
    glTranslatef 0,0,-200
    r:+.1
    If r>360 r:-360
    glRotatef r,1,.5,0
   
    s.draw()
   
Flip()
Wend

Title: Re: Help loading .3ds files with OpenGL (Bmax)
Post by: Pixel_Outlaw on September 04, 2007
Well, it looks like the lighting vectors are being dealt with correctly.

It seems to still miss the color of the faces in the image however.

I'm going to try and look into reading the color data.

I used some colored lights to check the light vectors, they look good:
Title: Re: Help loading .3ds files with OpenGL (Bmax)
Post by: va!n on September 04, 2007
@Pixel_Outlaw:
Sorry that my first post doenst helped you really... btw, hope following link may help you to load 3ds file correctly.
http://www.spacesimulator.net/tut4_3dsloader.html (http://www.spacesimulator.net/tut4_3dsloader.html)
Good luck!
Title: Re: Help loading .3ds files with OpenGL (Bmax)
Post by: zawran on February 16, 2009
Sorry for digging up an older thread, but I am working on getting 3ds models loaded, and I so far I have the following code loading the teapot 3ds file without crashing on me. Its basically code redone from that other posting but with only the actual loading, not all the object and display stuff. I still haven't tried getting texture to work, and I cannot seem to locate vertex color information in the file. Also missing is normal values, but I guess those can be calculated from the vertices since the polygon point order is known.

If also needs to look into either displaylists or vbo depending on which might be most useful and I am able to figure out :)

I will continue in the quest to get a fully working loader done, unless fustration gets the best of me.

The following code is Bmax code, and there are a few references to methods and variable names that are part of the complete code I am working on, but it should be possible to get the idea about how it works form it anyways.

Code: [Select]
Method load3ds:Int(file:String)
Local stream:TStream, size:Int, id_node:String, size_node:Int, b:Byte, i:Int

stream = ReadStream(file)
If stream = Null Then Return 0 ' file could not be loaded, return false
size = FileSize(file)

While Not Eof(stream)
id_node = Right(Upper(Hex(ReadShort(stream))),4)
size_node = ReadInt(stream)

Select id_node
Case "4D4D" 'Main node
Case "3D3D" 'Config
Case "4000" ' OBJECT BLOCK
Repeat ' read the name of the object
b = ReadByte(stream)   
If b = 0 Exit
Self.name :+ Chr(b)
Until b = 0
Case "4100" ' MESH BLOCK
Case "4110" ' VERTICES LIST
Local t:Int = ReadShort(stream)
For i = 0 To t-1
Self.addVertex(ReadFloat(stream),ReadFloat(stream),ReadFloat(stream))
Next

Case "4120" ' FACES LIST
Local t:Int = ReadShort(stream)
For i = 0 To t-1
Self.addFace(ReadShort(stream),ReadShort(stream),ReadShort(stream))
ReadShort(stream)
Next
Case "4140" ' TEXTURE MAPPING COORDINATES LIST
Local t:Int = ReadShort(stream)
For i = 0 To t-1
Self.addTexCoord(ReadFloat(stream),ReadFloat(stream))
Next
Case "4150" ' SMOOTHING GROUPS
Local t:Int = ReadShort(stream)
For i = 0 To Self.faceCount-1
ReadInt(stream)
Next
Default
' no ID was found that we need, so fastforward past this chunk
SeekStream(stream,StreamPos(stream)-6+size_node)
End Select
Wend
CloseStream stream
End Method
Title: Re: Help loading .3ds files with OpenGL (Bmax)
Post by: Pixel_Outlaw on February 17, 2009
Kick ass work dude.

I've loved the speed of OpenGL but it comes at the price of having to understand everything that normally goes on behind the scenes in max2d. I really need to learn to invent the wheel or atleast understand it. I just keep to busy to dabble too long on any one thing.
Title: Re: Help loading .3ds files with OpenGL (Bmax)
Post by: Shockwave on February 17, 2009
Thanks for posting your loader Zawran, that is a Karmic moment.
Good luck in getting it finished.
Title: Re: Help loading .3ds files with OpenGL (Bmax)
Post by: Jim on February 17, 2009
It's really important to make sure you keep your loaders separate from your renderer.
Don't make your loader load into an OpenGL structure.  Come up with something which will work for all loaders and renderers, which works for you.

Jim
Title: Re: Help loading .3ds files with OpenGL (Bmax)
Post by: zawran on February 17, 2009
I am not really sure that I will ever get this 3ds loader working completely. It seems like most people on the web are having nothing but problems with loading 3ds files. So far I have the following things working: loading of vertices, faces, texture uv, smoothing groups. But I am not sure what to do with the smoothing groups, and I have not been able to make the vertex normal calculations complete.

I will probably continue working on the vertex normal thing, but I might give up on the 3ds and settle for making my own geometry in code where I know what is what. Not really decided on everything yet. I have updated the previous post with the latest version of the 3ds loading code. This time just the loader so it will confuse as little as possible.
Title: Re: Help loading .3ds files with OpenGL (Bmax)
Post by: Jim on February 17, 2009
Take your time mate.  3ds files are pretty tough not least because there are mistakes and bugs in the format itself.

Jim
Title: Re: Help loading .3ds files with OpenGL (Bmax)
Post by: hellfire on February 19, 2009
Quote
I might give up on the 3ds
Now that you've got so far you shouldn't trash it.

Quote
I am not sure what to do with the smoothing groups
I guess the easiest way to explain the concept is to show a picture:
(http://www.abload.de/img/smoothinggroupskbw4.jpg)
Different smoothing-group-ids are shown as different colours in the bottom right picture.
Only faces in the same group have averaged normals.
Title: Re: Help loading .3ds files with OpenGL (Bmax)
Post by: Pixel_Outlaw on February 23, 2009
Honestly I'm impressed how far you have gotten into loading that infernal file type.
I'd encourage you to keep going if you think it possible. I think many people would be indebted to you if you can pull it off. Many blitz coders are just hobbyists after all.

also

Hellfire seems to have a knack for drawing information out of the most murky data.
I'm fairly sure he could convert a Klingon file format to Romulan without knowing either.  :o
Title: Re: Help loading .3ds files with OpenGL (Bmax)
Post by: zawran on February 23, 2009
I am still working on the model loaders, but the .obj format seems a lot easier to work with, so that is where my focus is right now. I did not have too much time last week, but this week looks good as far as time goes, so I am hoping for further progress this week. I think I have a working .obj loader, but I want to be sure before I post the code for it. But when its done and working, I will put it on the forum. Then I might jump back to the .3ds loader and see if I can fix the remaining problems.
Title: Re: Help loading .3ds files with OpenGL (Bmax)
Post by: Clyde on February 26, 2009
I dont mean to interject or hijack the thread at all.

But Im pretty interested in this too; I have BMAX and followed the NeHe example stuff.
How would you obtain the information for the textures, like which one apply's to which face(s) - if using multiple ones. Not interested in where they are located on the Hard Drive / directory stuff of them, as I have the texture image file(s). Often called Materials.

I Doug up this link which you dudes probably know about: http://www.the-labs.com/Blender/3DS-details.html

Cheers,
Clyde.
Title: Re: Help loading .3ds files with OpenGL (Bmax)
Post by: zawran on February 26, 2009
Yes I had already checked the information at that link :)

Files that has more than one object can also point to more than one texture. Textures are not included in the .3ds file, so its basically the texture filename you get from the file. As far as I found out, each mesh within the file can have one texture/material attached to it, so as the mesh is read you would get the associated texture as well. At the moment I am working on finishing the .obj reader though because it seems like a better format to use, but I might revisit the .3ds format sometime down the road.