Dark Bit Factory & Gravity
PROGRAMMING => Other languages => Blitz => Topic started 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.
-
possible this may help you... i found the source but i am not sure who is the org author... :(
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
-
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?
-
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.
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
-
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. :)
-
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.
-
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.
-
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
-
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
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
-
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:
-
@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!
-
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.
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
-
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.
-
Thanks for posting your loader Zawran, that is a Karmic moment.
Good luck in getting it finished.
-
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
-
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.
-
Take your time mate. 3ds files are pretty tough not least because there are mistakes and bugs in the format itself.
Jim
-
I might give up on the 3ds
Now that you've got so far you shouldn't trash it.
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.
-
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
-
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.
-
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.
-
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.