Here, my loader. It's basically like Terrabit's loader but rewritten. In my opinion it's a little more obvious, if you can figure out what you'd have to change to make it work (I'm using my own Vertex, Triangle and Mesh types). But I think that should be easier than writing it on your own. If you have questions don't hesitate to ask or look at
http://www.blitzbasic.com/sdkspecs/sdkspecs/userlibs_specs.txt .
Todo-List:
- Multiply all vertices with the local Node matrix (or the other way, you'll have to try)
- Brushes
- Bones / Animations
Global B3DL:B3DLoader Private
Public Type B3DLoader
'#Region Fields
Field File:Int
Field Mesh:eeMesh
Field Index:Int[]
Field Vertex:eeVertex[]
Field ChunkName:String
Field ChunkSize:Int
Field ChunkStart:Int
Field FileEnd:Int
Field LocalMatrix:Float[16]
'#End Region
Function LoadMesh:eeMesh ( Path:String ) Public
B3DL = New B3DLoader
B3DL.File:Int = OpenFile("littleendian::" + Path)
If Not B3DL.File Then Return Null
B3DL.Mesh = New eeMesh
B3DL.ReadChunk
B3DL.FileEnd = B3DL.ChunkStart + B3DL.ChunkSize
Readint(B3DL.File) 'version
Local start = MilliSecs()
B3DL.Parse
Local CompleteMesh:eeMesh = B3DL.Mesh
Local Vert:Int = 0
B3DL.Mesh.TriangleData = B3DL.Mesh.TriangleData[..B3DL.Mesh.TriangleCount]
For Local T:Int = 0 To B3DL.Index.Length/3 -1
Local Tri:eeTriangle = New eeTriangle
Tri.V[0] = B3DL.Vertex[B3DL.Index[Vert+0]]
Tri.V[1] = B3DL.Vertex[B3DL.Index[Vert+1]]
Tri.V[2] = B3DL.Vertex[B3DL.Index[Vert+2]]
Vert :+ 3
B3DL.Mesh.TriangleData[T] = Tri
Next
Release B3DL
Return CompleteMesh
End Function
Method ReadChunk ( ) Private
Self.ChunkName = ""
For Local i = 1 To 4
Self.ChunkName = Self.ChunkName + Chr( ReadByte(Self.File) )
Next
Self.ChunkSize = Readint(Self.File)
Self.ChunkStart = StreamPos(Self.File)
End Method
Method Parse ( ) Private
While StreamPos(Self.File) < Self.FileEnd
Self.ReadChunk
Select ChunkName
Case "NODE"
Local Name:String = ReadString(Self.File)
Local XPos:Float = ReadFloat(Self.File)
Local YPos:Float = ReadFloat(Self.File)
Local ZPos:Float = ReadFloat(Self.File)
Local XScl:Float = ReadFloat(Self.File)
Local YScl:Float = ReadFloat(Self.File)
Local ZScl:Float = ReadFloat(Self.File)
Local WRot:Float = ReadFloat(Self.File)
Local XRot:Float = ReadFloat(Self.File)
Local YRot:Float = ReadFloat(Self.File)
Local ZRot:Float = ReadFloat(Self.File)
Local CurrentMatrixMode:Int
glGetIntegerv(GL_MATRIX_MODE, Varptr CurrentMatrixMode)
glMatrixMode(GL_MODELVIEW)
glPushMatrix
glLoadIdentity
glTranslatef XPos, YPos, ZPos
glRotatef XRot, 1.0,0.0,0.0
glRotatef YRot, 0.0,1.0,0.0
glRotatef ZRot, 0.0,0.0,1.0
glScalef XScl, YScl, ZScl
glGetFloatv(GL_MODELVIEW_MATRIX, Self.LocalMatrix)
glPopMatrix
glMatrixMode(CurrentMatrixMode)
' (localmatrix) * (each vertex)
Self.Parse
Case "MESH"
Local BrushID:Int = Readint(Self.File)
Self.Parse
Case "TRIS"
Local BrushID:Int = Readint(Self.File)
Local V0:Int, V1:Int, V2:Int
Self.Index = New Int[65535]
Local IndexCount:Int = 0
While StreamPos(Self.File) < (Self.ChunkStart + Self.ChunkSize)
V0 = Readint(Self.File)
V1 = Readint(Self.File)
V2 = Readint(Self.File)
Self.Index[IndexCount+0] = V2
Self.Index[IndexCount+1] = V1
Self.Index[IndexCount+2] = V0
IndexCount :+ 3
Self.Mesh.TriangleCount :+ 1
Wend
Self.Index = Self.Index[..IndexCount]
Case "VRTS"
Local Flags:Int = Readint(Self.File)
Local TexCoordSets:Int = Readint(Self.File)
Local TexCoordCount:Int = Readint(Self.File)
Local VertCount:Int = 0
If (Self.Mesh.TriangleCount <> 0) Then
Self.Vertex = New eeVertex[3*Self.Mesh.TriangleCount]
Else
Self.Vertex = New eeVertex[65535]
EndIf
While StreamPos(Self.File) < (Self.ChunkStart + Self.ChunkSize)
Self.Vertex[VertCount] = New eeVertex
Local Vert:eeVertex = Self.Vertex[VertCount]
Vert.X = ReadFloat(Self.File)
Vert.Y = ReadFloat(Self.File)
Vert.Z = ReadFloat(Self.File)
If (Flags&1) Then
Vert.NX = ReadFloat(Self.File)
Vert.NY = ReadFloat(Self.File)
Vert.NZ = ReadFloat(Self.File)
EndIf
If (Flags&2) Then
Vert.Color[0] = ReadFloat(Self.File)
Vert.Color[1] = ReadFloat(Self.File)
Vert.Color[2] = ReadFloat(Self.File)
Vert.Alpha = ReadFloat(Self.File)
EndIf
For Local Set:Int = 1 To TexCoordSets
For Local Size:Int = 1 To TexCoordCount
Local Temp:Float = ReadFloat(Self.File)
If Set = 1 Then
If Size = 1 Then Vert.U = Temp
If Size = 2 Then Vert.V = Temp
EndIf
Next
Next
VertCount :+ 1
Wend
Self.Vertex = Self.Vertex[..VertCount]
End Select
SeekStream(Self.File, ChunkStart+ChunkSize)
Wend
End Method
End Type
Function ReadString:String ( In:TStream ) Private
Local Char:Byte, S:String
Repeat
Char = ReadByte(In)
If Char = 0 Return S$
S = S + Chr(Char)
Forever
End Function
By the way a nice site for file formats is
http://www.wotsit.org/search.asp?s=3d