3ds loader for minib3d

BlitzMax Forums/MiniB3D Module/3ds loader for minib3d

Silver_Knee(Posted 2015) [#1]
Hey, so i tried to convert the 3ds.cpp file from OpenB3d to minib3d. I din't change its contents - or at least I hope so - just the syntax. I did some changes like changing unsigned char to Byte and a list to an array but this shouldn't affect the loader.

Well i have a Mesh with 2 surfaces and it won't load correctly: There is only one surface loaded. Maybe someone who has openb3d and minib3d can try and load the same file with both loaders and can look into it, if they differ.

SuperStrict

Import sidesign.minib3d

Type T3dsLoader
	Const M3D_3DS_RGB3F:Int          = $0010
	Const M3D_3DS_RGB3B:Int          = $0011
	Const M3D_3DS_RGBGAMMA3B:Int     = $0012
	Const M3D_3DS_RGBGAMMA3F:Int     = $0013
	Const M3D_3DS_PERCENTI:Int       = $0030
	Const M3D_3DS_PERCENTF:Int       = $0031
	Const M3D_3DS_MAIN:Int           = $4D4D
	Const M3D_3DS_3DEDITOR:Int       = $3D3D
	Const M3D_3DS_OBJECTBLOCK:Int    = $4000
	Const M3D_3DS_TRIMESH:Int        = $4100
	Const M3D_3DS_VERTEXLIST:Int     = $4110
	Const M3D_3DS_FACELIST:Int       = $4120
	Const M3D_3DS_FACEMATLIST:Int    = $4130
	Const M3D_3DS_TEXCOORDS:Int      = $4140
	Const M3D_3DS_BrushBLOCK:Int     = $AFFF
	Const M3D_3DS_BrushNAME:Int      = $A000
	Const M3D_3DS_BrushAMBIENT:Int   = $A010
	Const M3D_3DS_BrushDIFFUSE:Int   = $A020
	Const M3D_3DS_BrushSPECULAR:Int  = $A030
	Const M3D_3DS_BrushSHININESS:Int = $A040
	Const M3D_3DS_TEXTUREMAP1:Int    = $A200
	Const M3D_3DS_TEXTUREMAP2:Int    = $A33A
	Const M3D_3DS_MAPFILENAME:Int    = $A300
	Const M3D_3DS_MAPVSCALE:Int      = $A354
	Const M3D_3DS_MAPUSCALE:Int      = $A356
	Const M3D_3DS_MAPUOFFSET:Int     = $A358
	Const M3D_3DS_MAPVOFFSET:Int     = $A35A
	Const M3D_3DS_MAPROTATION:Int    = $A35C
	
	Function Load3ds:TMesh(URL:String , parent_ent:TEntity)
		Return New T3dsLoader.Load(URL, parent_ent)
	End Function

	Field Stream:TStream
	Field ChunkID:Short
	Field ChunkSize:Int
	Field surface:TSurface
	Field VertexCount:Int
	Field TriangleCount:Int
	Field mesh:TMesh
	Field Brushs:TBrush[]
	Field brush:TBrush
	Field TextureLayer:Int
	Field texture:TTexture
	Field MovedTris:Int[]

	Method ReadChunk()
	  ChunkID   = Stream.ReadShort()
	  ChunkSize = Stream.ReadInt()
	End Method

	Method SkipChunk()
	  Stream.Seek(Stream.Pos()+ChunkSize-6)
	End Method

	Method ReadCString:String()
	  Local s:String
	  Local c:Byte=Stream.ReadByte()
	
	  'get String up To first New line character or End of file
	  While(c<>0 And Stream.Eof()=0)
	    s=s+Chr(c)
	    c=Stream.ReadByte()
	  Wend
	  Return s
	End Method

	Method ReadRGB(Format:Int, Red:Byte Var, Green:Byte Var, Blue:Byte Var)
	  Select (Format)
	    Case M3D_3DS_RGB3F
	      Red   = Byte(Stream.ReadFloat()*255)
	      Green = Byte(Stream.ReadFloat()*255)
	      Blue  = Byte(Stream.ReadFloat()*255)
	    Case M3D_3DS_RGB3B
	      Red   = Stream.ReadByte()
	      Green = Stream.ReadByte()
	      Blue  = Stream.ReadByte()
	    Case M3D_3DS_RGBGAMMA3F
	      Red   = Byte(Stream.ReadFloat()*255)
	      Green = Byte(Stream.ReadFloat()*255)
	      Blue  = Byte(Stream.ReadFloat()*255)
	    Case M3D_3DS_RGBGAMMA3B
	      Red   = Stream.ReadByte()
	      Green = Stream.ReadByte()
	      Blue  = Stream.ReadByte()
	    Default
	      SkipChunk()
	  End Select
	End Method

	Method ReadPercent:Byte(Format:Int )
	  Select (Format)
	    Case M3D_3DS_PERCENTI
	      Return Byte(Stream.ReadShort())
	    Case M3D_3DS_PERCENTF
	      Return Byte(Stream.ReadFloat())
	    Default
	      SkipChunk()
	      Return 0
	  End Select
	End Method

	Method ReadVertexList()
	  Local Index:Int
	  Local Position:Float[3]
	  VertexCount = Stream.ReadShort()
	  For Index = 0 Until VertexCount
	    Position[0] = Stream.ReadFloat()
	    Position[1] = Stream.ReadFloat()
	    Position[2] = Stream.ReadFloat()
	    surface.AddVertex(Position[0], Position[1], Position[2])
	  Next
	End Method

	Method ReadFaceList()
	  Local Index:Int
	  Local Indices:Int[3]
	  TriangleCount = Stream.ReadShort()
	  For Index = 0 Until TriangleCount
	    Indices[0] = Stream.ReadShort()
	    Indices[1] = Stream.ReadShort()
	    Indices[2] = Stream.ReadShort()
	    Stream.ReadShort() ' FaceFlags
	    surface.AddTriangle(Indices[0], Indices[1], Indices[2])
	  Next 
	End Method

	Method ReadFaceMatList()
	  Local Name:String
	  Local Found:Int
	  Local Count:Int
	  Local Index:Int
	  Local brush:TBrush
	  Local New_surface:TSurface
	  Local v:Short
	
	  Name = ReadCString()
	
	  'Search For the BrushName
	  Found = False
	
	  For brush = EachIn Brushs
	    If (brush.name = Name)
	      Found = True
	      Exit
	    EndIf
	  Next
	
	  If (Found=True) 
	    New_surface = mesh.CreateSurface()
	    Count = Stream.ReadShort()
	    'Stream.SeekFile(Stream.FilePos()+Count*2)
	    For Index = 0 Until Count
	      v = Stream.ReadShort()
	      Local v0:Int[3]
	      For Local i:Int=0 Until 3
	        v0[i]=surface.TriangleVertex(v,i)
	        Local x:Float,y:Float,z:Float,u:Float,v:Float,w:Float
	        x=surface.VertexX(v0[i])
	        y=surface.VertexY(v0[i])
	        z=surface.VertexZ(v0[i])
	        u=surface.VertexU(v0[i])
	        v=surface.VertexV(v0[i])
	        w=surface.VertexW(v0[i])
	        v0[i]=New_surface.AddVertex(x,y,z,u,v,w)
	      Next
	      New_surface.AddTriangle(v0[0],v0[1],v0[2])
	      'surface.RemoveTri(v)
	      Rem v=(v+1)*3
	      surface.tris[v-1]=0
	      surface.tris[v-2]=0
	      surface.tris[v-3]=0
		End Rem
	     	MovedTris = MovedTris[..MovedTris.length + 1]
		MovedTris[MovedTris.length-1]=v
	    Next 
	    New_surface.PaintSurface(brush)
	  EndIf
	End Method
	
	Method ReadTexCoords()
	  Local Count:Int
	  Local Index:Int
	  Local U:Float, V:Float
	
	  Count = Stream.ReadShort()
	  For Index = 0 Until Count
	    U = Stream.ReadFloat()
	    V = -Stream.ReadFloat()
	    surface.VertexTexCoords(Index, U, V,0, 0)
	    surface.VertexTexCoords(Index, U, V,0, 1)
	  Next
	End Method

	Method LoadMap()
	  Local Filename:String
	  'Int Pixmap
	  Filename = ReadCString()
	  'Pixmap = FileType(Filename)
	  'If Pixmap <> 0 Then
	  texture = TTexture.LoadTexture(Filename,4)
	  If (TextureLayer = M3D_3DS_TEXTUREMAP1)
	    ' Layer 0
	    brush.BrushTexture(texture, 0, 0)
	  Else
	    ' Layer 1
	    brush.BrushTexture(texture, 0, 1)
	  EndIf 
	  'EndIf
	End Method

	Method ReadMap(Layer:Int)
	  texture = TTexture.CreateTexture(1,1)
	  TextureLayer = Layer
	End Method 

	Method ReadTriMesh()
	  If (surface<>Null)
	    MovedTris.sort(False)
	    Local CheckSurface:Int=0
	    For Local tris:Int =EachIn MovedTris
	      TSurface.RemoveTri(surface,tris)
	      CheckSurface=1
	    Next
	    MovedTris=New Int[0]
	    If (surface.no_tris=0 And CheckSurface <>0)
	      surface.ClearSurface()
	      mesh.surf_list.remove(surface)
		surface=Null
	      mesh.no_surfs=mesh.no_surfs-1
	    EndIf
	  EndIf
	  surface = mesh.CreateSurface()
	End Method
		
	Method ReadBrushBlock()
	  brush = TBrush.CreateBrush()
	  Brushs=Brushs[..Brushs.length+1]
	  Brushs[Brushs.length-1]=brush
	End Method

	Method New()
	  Stream        = Null
	  ChunkID       = 0
	  ChunkSize     = 0
	  surface       = Null
	  VertexCount   = 0
	  TriangleCount = 0
	  mesh          = Null
	  brush         = Null
	  TextureLayer  = 0
	  texture       = Null
	End Method

	Method Load:TMesh(URL:String, parent_ent:TEntity)
	  Local Size:Int 
	  Local Red:Byte, Green:Byte, Blue:Byte
	  'unsigned char Percent
	  'Local Pixmap:TPixmap
	  Stream = ReadFile(URL)
	  If (Stream = Null) Return Null
	
	  Size = Stream.Size()
	Rem 
	  fseek(Stream.pFile, 0, SEEK_END) ' seek To End of file
	  Size = ftell(Stream.pFile) ' get Current file pointer
	  fseek(Stream.pFile, 0, SEEK_SET)
	End Rem
	
	  ' Read Main-Chunk
	  ReadChunk()
	  If (ChunkID <> M3D_3DS_MAIN Or ChunkSize <> Size)
	    Stream.Close()
	    'Print "No 3DS File"
	    Return Null
	  EndIf 
	
	  ' Find 3DEditor-Chunk
	  While (Stream.Eof()=0)
	    ReadChunk()
	    If (ChunkID = M3D_3DS_3DEDITOR)
	      Exit
	    Else
	      SkipChunk()
	    EndIf
	  Wend
	
	  Local OldDir:String = CurrentDir()
	  If String(URL) <> "" Then ChangeDir(ExtractDir(String(URL)))
	  mesh = TMesh.CreateMesh(parent_ent)
	  While (Stream.Eof()=0)
	    ReadChunk()
	    Select (ChunkID)
	    Case M3D_3DS_OBJECTBLOCK
	      ReadCString() ' ' ObjectName
	    Case M3D_3DS_BrushBLOCK
	      ReadBrushBlock()
	    Case M3D_3DS_TRIMESH
	      ReadTriMesh()
	    Case M3D_3DS_VERTEXLIST
	      ReadVertexList()
	    Case M3D_3DS_FACELIST
	      ReadFaceList()
	    Case M3D_3DS_FACEMATLIST
	      ReadFaceMatList()
	    Case M3D_3DS_TEXCOORDS
	      ReadTexCoords()
	    Case M3D_3DS_BrushNAME
	      'Loader.Brush = CreateBrush()
	      brush.name = ReadCString()
	    Case M3D_3DS_BrushAMBIENT
	      'ReadChunk()
	      'ReadRGB(ChunkID, Red, Green, Blue)
	      'brush.SetAmbientColor(Red, Green, Blue)
	    Case M3D_3DS_BrushDIFFUSE
	      ReadChunk()
	      ReadRGB(ChunkID, Red, Green, Blue)
	      brush.BrushColor(Red, Green, Blue)
	    Case M3D_3DS_BrushSPECULAR
	      ''Loader.ReadChunk()
	      ''Loader.ReadRGB(Loader.ChunkID, Red, Green, Blue)
	      ''Loader.Brush.SetSpecularColor(Red, Green, Blue)
	    Case M3D_3DS_BrushSHININESS
	      ''Loader.ReadChunk()
	      ''Percent = Loader.ReadPercent(Loader.ChunkID)
	      ''Loader.Brush.BrushShininess(Percent)
	    Case M3D_3DS_MAPFILENAME
	      LoadMap()
	    Case M3D_3DS_MAPVSCALE
	      texture.v_scale = Stream.ReadFloat()
	    Case M3D_3DS_MAPUSCALE
	      texture.u_scale = Stream.ReadFloat()
	    Case M3D_3DS_MAPUOFFSET
	      texture.u_pos = Stream.ReadFloat()
	    Case M3D_3DS_MAPVOFFSET
	      texture.v_pos = Stream.ReadFloat()
	    Case M3D_3DS_MAPROTATION
	      texture.angle = Stream.ReadFloat()
	    Default
	      If ((ChunkID = M3D_3DS_TEXTUREMAP1) or (ChunkID = M3D_3DS_TEXTUREMAP2))
	        ReadMap(ChunkID)
	      Else
	        SkipChunk()
	      EndIf 
	    End Select 
	  Wend
	
	  Stream.Close()
	
	  If (surface<>Null)
	    MovedTris.sort(False)
	    Local CheckSurface:Int =0
	    For Local tris:Int=EachIn MovedTris
	      TSurface.RemoveTri(surface,tris)
	      CheckSurface=1
	    Next 
	    MovedTris=New Int[0]
	
	    If (surface.no_tris=0 And CheckSurface <>0)
	      surface.ClearSurface()
	      mesh.surf_list.remove(surface)
		surface=Null
	      mesh.no_surfs=mesh.no_surfs-1
	    EndIf
	  EndIf
	
	
	  ChangeDir(OldDir)
	'    Loader.Surface.UpdateVertices()
	'    Loader.Surface.UpdateTriangles()
	  mesh.UpdateNormals()
	  '/*Loader.Mesh.UpdateBuffer()
	  'Print Loader.Surface.Tris.Length
	  'Print Loader.Surface.no_verts
	  'Loader.Mesh.FlipMesh()*/
	
	  Return mesh
	End Method
End Type