3DS questions.
BlitzMax Forums/BlitzMax Programming/3DS questions.
| ||
I'm doing a 3ds loader for v2, and have a question.. The loader is working fine, but I've got to the final stage where I need to make sure of face mapping data(I.e the list of faces present for each material) Do I apply linearly to the loaded faces(I.e regardless of which object they're a part of) or is it simply restricted to the parent object chunk? Also, real reason for this post really is this little 'wierdity', the code for the loader thus far is below, and if you look for the Case $A200 construct, where it is supposed to load the texture name, you see I had to severly kludge that paticulary part because it seems there is in all 3ds an alien chunk before it, int value of 48. Without the kludge it just fails to work...but I'm worried about this not being a common to all 3ds (And therefore making my loader incompatible with them)...Any ideas what the chunk's for? Type Loader3DS Extends Loader Field LastSurf:Surface Method New() SetAuthor( "Antony Wells" ) SetCopyright( "Antony Wells" ) SetVersion( "V1.0" ) SetExt( "3ds" ) End Method Method Delete() stream = Null End Method 'Internal Function GetNewLoader:Loader3DS() Return New Loader3DS End Function Method RequestNew:Object() Local Out:Object = GetNewLoader() Return Object( Out ) End Method Method ParseStream () Local Name:String Local MatList:TList = CreateList() Local LastMat:Material Local vBase:Int,iBase:Int Local U:Float,V:Float Local V0:Int,V1:Int,V2:Int Local Face:Int,X:Float,Y:Float,Z:Float While Not Eof (Stream) LastId = Int(ReadShort( Stream )) LastLen = Readint( Stream ) DebugLog "Chunk Hex>"+Hex( lastId )+" Len>"+LastLen Select LastId Case MainChunk ' Main_Error.Invoke "Reached Main Chunk Len:"+LastLen,0 Case EditorChunk ' Main_Error.Invoke "Reached Editor Chunk",0 Case ObjectBlock Name = Self.ReadStr() DebugLog name+" Obj name" ' Main_Error.Invoke "Name >"+Name,0 ' If Root = Null ' Root = New TMesh ' Root.RenderState= False ' Root.Name = Name ' vBase = 0 ' iBase = 0 ' End If Root.Name=Name Case TriangularMesh Case MaterialBlock ' Main_Error.Invoke "Reached Material Block>",0 LastMat = New Material Case MaterialName Local MatName:String = Self.ReadStr() DebugLog "Material Name>"+MatName Case $A010 Case $A020 Case $A200 Local TexFile:String 'Local texfile:String = self.readstr(lastLen) lastid = Int(ReadShort( stream )) 'While StreamPos( stream )<sstream+lastLen For Local j=1 To 4 lastId = Int(ReadShort( stream )) lastLen = Readint( stream ) If lastId = $a300 texFile= self.readStr() Exit EndIf ' DebugLog "Id>"+LastId+" Hex>"+Hex(lastId) self.skipchunk() Next DebugLog "Loaded Texture >"+texfile 'DebugStop Case $A300 Case VerticesList ' Main_Error.Invoke "Reached Vertices List",0 Local VertC = ReadShort( Stream ) ' Main_Error.Invoke "Vertices:"+VertC,0 'This prevents any other threads from accessing. LastSurf:Surface = Surface.create( vertC*3 ) For Local Vert:Int = 0 To VertC-1 X = ReadFloat( Stream ) Y = ReadFloat( Stream ) Z = ReadFloat( Stream ) LastSurf.AddVertex( Vertex.Create(X,Y,Z) ) FlushMem Next Root.AddSurface( LastSurf ) Case FacesList ' Main_Error.Invoke "Reached Faces List",0 Local TriC = ReadShort( Stream ) ' Main_Error.Invoke "Faces:"+TriC,0 If LastSurf = Null Throw "No surface to add triangles to" For Local Tri:Int = 0 To TriC-1 Local Va0:Int = ReadShort( Stream ) Local Va1:Int = ReadShort( Stream ) Local Va2:Int = ReadShort( Stream ) Local Faace:Int = ReadShort( Stream) 'If va1>lastsurf.vertcount Or v2>lastsurf.vertcount Or v0>lastsurf.vertcount ' Throw "Vertex ID>"+V0+" 1>"+V1+" 2>"+v2+" Max>"+lastsurf.vertcount ' EndIf LastSurf.AddTriangle( Triangle.Create( lastsurf.getVertex(Va0),lastsurf.getVertex(Va1),lastsurf.getvertex(Va2) )) FlushMem Next Case CoordList ' Main_Error.Invoke "Reached Coords List",0 Local CoordC:Int = ReadShort( Stream ) ' Main_Error.Invoke "Coords:"+CoordC,0 If LastSurf = Null Throw "No surface defined in 3ds prior to coord set" If coordC<>lastsurf.vertCount Throw "Coords>"+coordC+" Verts>"+lastsurf.vertcount For Local vert:vertex = EachIn lastsurf.verts U = ReadFloat( Stream ) V = ReadFloat( Stream ) vert.SetCoords( U,V,0 ) FlushMem Next Case $4130 Local matIs:String matIs = self.readStr() DebugLog "face map for :"+MatIs Local faceCount:Int = Int(ReadShort(stream)) DebugLog "faceCount >"+FaceCount For Local j=0 To faceCount-1 Local Face:Int = ReadShort(stream) Next Default SeekStream stream,StreamPos( Stream ) + (LastLen-6) FlushMem End Select Wend End Method Method SkipThis() SeekStream stream,StreamPos( Stream ) + (LastLen-6) End Method Method ReadStr:String(ReadBytes = 0) If LastID =0 Or LastLen = 0 Throw "No Data to read in 3DS" End If Local Out:String,Char:String Local By:Byte If ReadBytes =0 Repeat If Eof( Stream ) Throw "Unexpectly reached end of file while reading string in Loader3DS.ReadStr()" By=ReadByte( Stream ) If By = 0 Exit Out=out + Chr( By ) Forever Else Local fI:Short=0 Repeat If Eof(stream) Throw "Unable to read that many bytes" by=ReadByte( stream ) fi:+1 out=out+Chr( by) Until fi=readBytes EndIf Return Out End Method Function NewMesh:Mesh() Return New Mesh End Function Method StreamLoad:Mesh( File:String) Final ' RequestLock( L3D_Lock ) ' LoadThread:TThread = TThread.Create( Loader3DS_Parse ) ' Stream = ReadFile( file ) ' If Stream = Null Throw "Unable to read file File:"+file ' Root = Loader3DS.NewMesh() ' Root.Lock() ' Root.RenderState = False ' ActiveLoader =Loader3DS ( Self ) ' LoadThread.Run() 'Thread unlocks L3d_Lock, this prevents cross thread 'boogy' ' Return Root End Method Method Load:Mesh( File:String ) Final 'Main_Error.Invoke( FileSize( File ) , False ) Stream = OpenStream( File,True,False ) Root = New Mesh If Stream=Null Throw "Unable to read file File:"+File Self.ParseStream() If Root = Null Throw "Parse Finished without Mesh as result in Loader3DS.Load" Return Root End Method Method Reset() If Stream = Null Throw "No stream in Reset()" SeekStream Stream,0 End Method Method Save:Mesh( File:String ) Final End Method Method EndStream:Int() If Stream = Null Throw "No Stream in Loader3DS.EndStream" Return Eof( Stream ) End Method Method FindChunk:Int( ID:Int ,WrapStream:Int = False,ZeroStream:Int=False) Local WrapPoint:Int = StreamPos( Stream ) Local EndPoint:Int = StreamSize( Stream ) If ZeroStream SeekStream Stream,0 WrapPoint = 0 End If 'Throw "Chunks:"+Self.CountChunks() Repeat While StreamPos( Stream ) < EndPoint Self.ReadChunk() If LastID = ID Return True End If Self.SkipChunk() Wend If WrapStream SeekStream Stream,0 EndPoint = WrapPoint WrapStream = False ' Main_Error.Invoke "Wrapped Stream" Continue ' Main_Error.Invoke "Uh...shit!" End If ' Main_Error.Invoke "Fuck nuts!" Return False Forever End Method Method CountChunks:Int() Local Count:Int Self.SavePos() SeekStream Stream,0 While Not EndStream() Self.ReadChunk() Self.SkipChunk() Count:+1 Wend Self.LoadPos() Return Count End Method Method SavePos() If Stream = Null Throw "Stream not found in SavePos()" OldPos = StreamPos ( Stream) End Method Method LoadPos() If Stream = Null Throw "Stream not found In LoadPos()" SeekStream Stream,OldPos End Method Method ValidateChunk:Int() Return True 'legacy. remove. End Method Method ParseChunk() Self.SkipChunk() End Method Method ReadChunk:Int( Count:Int = 1 ) While Count > 0 If Stream = Null Throw "No Stream in Loader3DS.ReadChunk()" LastID = ReadShort( Stream ) LastLen = Readint( Stream ) ' Main_Error.invoke "Chunk ID>"+LastID+" Length>"+LastLen Self.ValidateChunk() Count:-1 Wend End Method Method SkipChunk() If lastId =0 Return If lastId =8 Return If LastLen=0 Throw "Cannot skip null chunk LastId:"+LastId If Stream = Null Throw "No Stream in Loader3DS.SkipChunk" SeekStream ( Stream, StreamPos( Stream )+LastLen ) End Method Field LastID:Int,LastLen:Int 'Field LoadThread:TThread Field Root:Mesh,OldPos:Int End Type Global Loader_3DS:Loader = New Loader3DS FileIO.RegisterLoader( Loader_3DS ) Global ActiveLoader:Loader3DS 'Global ActiveLock = CreateLock() Global L3D_Stack:Loader3DS[5000] Global L3D_SLock[5000] Global L3D_Index:Int =0 'Global L3d_lock = Createlock() Function Loader3DS_Parse:Int( bb_func:Byte Ptr) Rem If ActiveLoader = Null Throw "No active loader registered, unable to spawn thread" Local TLoad:Loader3DS = ActiveLoader ActiveLoader = Null ReleaseLock( L3D_Lock ) Local Ms=MilliSecs() TLoad.ParseStream() 'Print "Stream took >"+String(MilliSecs()-Ms)+" Millisecs" RequestLock( TLoad.Root.RenderMutex ) TLoad.Root.RenderState = True ReleaseLock( TLoad.Root.RenderMutex ) TLoad.Root.Unlock() TLoad = Null Repeat Delay 5000 Forever End Rem End Function Private Const MAINCHUNK=$4D4D Const EDITORCHUNK=$3D3D Const ObjectBLOCK=$4000 Const TRIANGULARMESH=$4100 Const VERTICESLIST=$4110 Const FacesList=$4120 Const FACESMATERIAL=$4130 Const CoordList =$4140 Const SMOOTHINGGROUPLIST=$4150 Const COORDINATESSYSTEM=$4160 Const LightChunk=$4600 Const SPOTLightChunk =$4610 Const CameraChunk =$4700 Const MATERIALBLOCK =$AFFF Const MATERIALNAME =$A000 Const AMBIENTCOLOR =$A010 Const DIFFUSECOLOR =$A020 Const SPECULARCOLOR =$A030 Const TEXTUREMAP =$A200 Const BUMPMAP =$A230 Const REFLECTIONMAP=$A220 Const TextureMap1 =$A300 Const MAPPINGPARAMETERS =$A351 Const KEYFRAMERCHUNK =$B000 Const MESHINFORMATIONBLOCK =$B002 Const SPOTLightChunkINFORMATIONBLOCK =$B007 Const FramePoint =$B008 Const ObjectNAME =$B010 Const ObjectPIVOTPOINT =$B013 Const POSITIONTRACK =$B020 Const ROTATIONTRACK =$B021 Const SCALETRACK =$B022 Const HIERARCHYPOSITION =$B030 |