I created a .b3d mesh loader. It doesn't handle materials yet, but this shows how you can add support for additional formats. Most of this is Mark's original .b3d parser code. Just put this in the engine directory and run it. Change the name of the .b3d file to load, since I didn't include the jeep b3d in the package.
Framework leadwerks.engine
AppTitle=StripAll(AppFile)
SetGraphicsDriver GLGraphicsDriver()
Graphics 1024,768,0,60,2
'A world must be created or loaded before you do anything:
CreateWorld()
'Create a mesh:
mesh:TMesh=LoadMesh("meshes\vehicles\jeep.b3d")
'Create a camera
camera:TCamera=CreateCamera()
CameraClsColor camera,0,0,255
MoveEntity camera,0,0,-400
'Create a light
light:TLight=CreateLight()
RotateEntity light,45,45,0
'Main loop
While Not KeyHit(KEY_ESCAPE)
TurnEntity mesh,0,AppSpeed(),0
UpdateWorld()
RenderWorld()
GLDrawText "UPS: "+UPS(),0,0
GLDrawText TrisRendered()+" triangles",0,20
Flip False
Wend
End
'==========================================================
'B3D Mesh loader class
'
'To create a new mesh loader, declare the type,
'indicate the supported file extensions, and write the Load() method.
'You can then use the standard LoadMesh() command to load the file format.
'
'==========================================================
Type B3DMeshLoader Extends TMeshLoader
Global loader:TMeshLoader=New B3DMeshLoader
Method New()
extensions.addlast "b3d"
EndMethod
Method Load:TMesh(stream:TStream)
b3dSetFile(stream)
If b3dReadChunk$()<>"BB3D"
DebugLog "Invalid b3d file."
Return Null
EndIf
If b3dReadInt()/100>0
DebugLog "Invalid b3d file version."
Return Null
EndIf
root:TMesh=ReadChunks()
b3dExitChunk()
Return root
EndMethod
Function ReadChunks:TMesh( tab$="" )
Global entity:TEntity
Global root:TMesh
Global vertexlist#[,]
Global normallist#[,]
Global texcoordList#[,,]
Global colorList#[,]
Global x_pos#
Global y_pos#
Global z_pos#
Global x_scl#
Global y_scl#
Global z_scl#
Global w_rot#
Global x_rot#
Global y_rot#
Global z_rot#
tt$=tab$
tab$=tab$+" "
While b3dChunkSize()
chunk$=b3dReadChunk$()
DebugLog tt$+"Chunk:"+chunk$+" (size="+b3dChunkSize()+")"
Select chunk$
Rem
Case "ANIM"
flags=b3dReadInt()
n_frames=b3dReadInt()
fps=b3dReadFloat()
DebugLog tab$+flags+" "+n_frames+" "+fps
EndRem
Rem
Case "KEYS"
flags=b3dReadInt()
sz=4
If flags And 1 sz=sz+12
If flags And 2 sz=sz+12
If flags And 4 sz=sz+16
n_keys=b3dChunkSize()/sz
If n_keys*sz=b3dChunkSize()
DebugLog tab$+n_keys+" keys"
'read all keys in chunk
While b3dChunkSize()
frame=b3dReadInt()
If flags And 1
key_px#=b3dReadFloat()
key_py#=b3dReadFloat()
key_pz#=b3dReadFloat()
EndIf
If flags And 2
key_sx#=b3dReadFloat()
key_sy#=b3dReadFloat()
key_sz#=b3dReadFloat()
EndIf
If flags And 4
key_rw#=b3dReadFloat()
key_rx#=b3dReadFloat()
key_ry#=b3dReadFloat()
key_rz#=b3dReadFloat()
EndIf
Wend
Else
DebugLog tab$+"***** Illegal number of keys *****"
EndIf
EndRem
Case "TEXS"
While b3dChunkSize()
name$=b3dReadString$()
flags=b3dReadInt()
blend=b3dReadInt()
x_pos#=b3dReadFloat()
y_pos#=b3dReadFloat()
x_scl#=b3dReadFloat()
y_scl#=b3dReadFloat()
rot#=b3dReadFloat()
DebugLog tab$+name$
Wend
'ReadChunks( tab$ ) 'dump any subchunks
Case "BRUS"
n_texs=b3dReadInt()
'read all brushes in chunk...
While b3dChunkSize()
name$=b3dReadString$()
r#=b3dReadFloat()
g#=b3dReadFloat()
b#=b3dReadFloat()
alp#=b3dReadFloat()
shi#=b3dReadFloat()
blend=b3dReadInt()
fx=b3dReadInt()
For k=0 To n_texs-1
tex_id=b3dReadInt()
Next
DebugLog tab$+name$
Wend
'ReadChunks( tab$ ) 'dump any subchunks
Case "VRTS"
flags=b3dReadInt()
tc_sets=b3dReadInt()
tc_size=b3dReadInt()
sz=12+tc_sets*tc_size*4
If (1 & flags) sz=sz+12
If (2 & flags) sz=sz+16
n_verts=b3dChunkSize()/sz
Local verts#[n_verts,3]
vertexlist=verts
Local norms#[n_verts,3]
normallist=norms
tsize=tc_size
If tsize<2 tsize=2
tsets=tc_sets
If tsets<2 tsets=2
Local texcoords#[n_verts,tsize,tsets]
texcoordList=texcoords
If n_verts*sz=b3dChunkSize()
DebugLog tab$+n_verts+" vertices"
'read all verts in chunk
n=0
While b3dChunkSize()>0
x#=b3dReadFloat()
y#=b3dReadFloat()
z#=b3dReadFloat()
vertexlist[n,0]=x
vertexlist[n,1]=y
vertexlist[n,2]=z
DebugLog x+", "+y+", "+z
If (1 & flags)
nx#=b3dReadFloat()
ny#=b3dReadFloat()
nz#=b3dReadFloat()
normallist[n,0]=nx
normallist[n,1]=ny
normallist[n,2]=nz
EndIf
If (2 & flags)
r#=b3dReadFloat()
g#=b3dReadFloat()
b#=b3dReadFloat()
lfa#=b3dReadFloat()
EndIf
'read tex coords...
For set=0 To tc_sets-1
For coord=0 To tc_size-1
texcoordList[n,coord,set]=b3dReadFloat()
Next
Next
n:+1
Wend
Else
DebugLog tab$+"***** Illegal number of vertices *****"
EndIf
'ReadChunks( tab$ ) 'dump any subchunks
Case "TRIS"
brush_id=b3dReadInt()
sz=12
n_tris=b3dChunkSize()/sz
If n_tris*sz=b3dChunkSize()
'DebugLog tab$+n_tris+" triangles"
'read all tris in chunk
n=0
surf:TSurface=CreateSurface(TMesh(entity))
While b3dChunkSize()
v0=b3dReadInt()
v1=b3dReadInt()
v2=b3dReadInt()
DebugLog v0+", "+v1+", "+v2
x0#=vertexlist[v0,0]
y0#=vertexlist[v0,1]
z0#=vertexlist[v0,2]
x1#=vertexlist[v1,0]
y1#=vertexlist[v1,1]
z1#=vertexlist[v1,2]
x2#=vertexlist[v2,0]
y2#=vertexlist[v2,1]
z2#=vertexlist[v2,2]
nx0#=normallist[v0,0]
ny0#=normallist[v0,1]
nz0#=normallist[v0,2]
nx1#=normallist[v1,0]
ny1#=normallist[v1,1]
nz1#=normallist[v1,2]
nx2#=normallist[v2,0]
ny2#=normallist[v2,1]
nz2#=normallist[v2,2]
u00#=texcoordlist[v0,0,0]
v00#=texcoordlist[v0,1,0]
u01#=texcoordlist[v0,0,1]
v01#=texcoordlist[v0,1,1]
u10#=texcoordlist[v1,0,0]
v10#=texcoordlist[v1,1,0]
u11#=texcoordlist[v1,0,1]
v11#=texcoordlist[v1,1,1]
u20#=texcoordlist[v2,0,0]
v20#=texcoordlist[v2,1,0]
u21#=texcoordlist[v2,0,1]
v21#=texcoordlist[v2,1,1]
v0=surf.findvertex(x0,y0,z0,nx0,ny0,nz0,u00,v00,u01,v01)
v1=surf.findvertex(x1,y1,z1,nx1,ny1,nz1,u10,v10,u11,v11)
v2=surf.findvertex(x2,y2,z2,nx2,ny2,nz2,u20,v20,u21,v21)
surf.addtriangle(v0,v1,v2,True)
'indicelist[n,0]=v0
'indicelist[n,1]=v1
'indicelist[n,2]=v2
n:+1
Wend
Else
DebugLog tab$+"***** Illegal number of triangles *****"
EndIf
'ReadChunks( tab$ ) 'dump any subchunks
Case "MESH"
brush_id=b3dReadInt()
entity=CreateMesh(entity)
SetEntityProperty entity,"name",name$
PositionEntity entity,x_pos,y_pos,z_pos
ScaleEntity entity,x_scl,y_scl,z_scl
EntityQuaternion entity,x_rot,y_rot,z_rot,w_rot
reverttoparent=True
'DebugLog tab$+"brush="+brush_id
Rem
Case "BONE"
sz=8
n_weights=b3dChunkSize()/sz
If n_weights*sz=b3dChunkSize()
DebugLog tab$+n_weights+" weights"
'read all weights
While b3dChunkSize()
vertex_id=b3dReadInt()
weight#=b3dReadFloat()
Wend
Else
DebugLog tab$+"***** Illegal number of bone weights *****"
EndIf
EndRem
ReadChunks( tab$ ) 'dump any subchunks
Case "NODE"
name$=b3dReadString$()
x_pos#=b3dReadFloat()
y_pos#=b3dReadFloat()
z_pos#=b3dReadFloat()
x_scl#=b3dReadFloat()
y_scl#=b3dReadFloat()
z_scl#=b3dReadFloat()
w_rot#=b3dReadFloat()
x_rot#=b3dReadFloat()
y_rot#=b3dReadFloat()
z_rot#=b3dReadFloat()
'DebugLog tab$+"name="+name$
ReadChunks( tab$ ) 'dump any subchunks
EndSelect
b3dExitChunk() 'Exit this chunk
If root:TMesh=Null root=TMesh(entity)
If reverttoparent
If entity entity=entity.parent
EndIf
Wend
Return root
EndFunction
'
'b3d file utils To be included
'
Global b3d_stack[100]
Global b3d_file:TStream,b3d_tos
Function b3dSetFile( file:TStream )
b3d_tos=0
b3d_file=file
End Function
'***** functions For reading from B3D files *****
Function b3dReadByte()
Return ReadByte( b3d_file )
End Function
Function b3dReadInt()
Return ReadInt( b3d_file )
End Function
Function b3dReadFloat#()
Return ReadFloat( b3d_file )
End Function
Function b3dReadString$()
Repeat
ch=b3dReadByte()
If ch=0 Return t$
t$=t$+Chr$(ch)
Forever
End Function
Function b3dReadChunk$()
For k=1 To 4
tag$=tag$+Chr$(b3dReadByte())
Next
sz=ReadInt( b3d_file )
b3d_tos=b3d_tos+1
b3d_stack[b3d_tos]=StreamPos( b3d_file )+sz
Return tag$
End Function
Function b3dExitChunk()
SeekStream b3d_file,b3d_stack[b3d_tos]
b3d_tos=b3d_tos-1
End Function
Function b3dChunkSize()
Return b3d_stack[b3d_tos]-StreamPos( b3d_file )
End Function
'***** Functions For writing To B3D files *****
Function b3dWriteByte( n )
WriteByte( b3d_file,n )
End Function
Function b3dWriteInt( n )
WriteInt( b3d_file,n )
End Function
Function b3dWriteFloat( n# )
WriteFloat( b3d_file,n )
End Function
Function b3dWriteString( t$ )
For k=1 To Len( t$ )
ch=Asc(Mid$(t$,k,1))
b3dWriteByte(ch)
If ch=0 Return
Next
b3dWriteByte( 0 )
End Function
Function b3dBeginChunk( tag$ )
b3d_tos=b3d_tos+1
For k=1 To 4
b3dWriteByte(Asc(Mid$( tag$,k,1 )))
Next
b3dWriteInt( 0 )
b3d_stack[b3d_tos]=StreamPos( b3d_file )
End Function
Function b3dEndChunk()
n=StreamPos( b3d_file )
SeekStream b3d_file,b3d_stack[b3d_tos]-4
b3dWriteInt( n-b3d_stack[b3d_tos] )
SeekStream b3d_file,n
b3d_tos=b3d_tos-1
End Function
EndType