Jelajahi Sumber

Added mojo3d .glb (gltf binary) support.

Mark Sibly 7 tahun lalu
induk
melakukan
77ae9841b1
2 mengubah file dengan 78 tambahan dan 23 penghapusan
  1. 11 2
      modules/mojo3d/loader/gltf2.monkey2
  2. 67 21
      modules/mojo3d/loader/gltf2loader.monkey2

+ 11 - 2
modules/mojo3d/loader/gltf2.monkey2

@@ -121,7 +121,6 @@ End
 #rem monkeydoc @hidden
 #end
 Class Gltf2AnimationChannel
-	
 	Field sampler:Gltf2AnimationSampler	'for shared samplers (nice).
 	Field targetNode:Gltf2Node
 	Field targetPath:String
@@ -130,7 +129,6 @@ End
 #rem monkeydoc @hidden
 #end
 Class Gltf2AnimationSampler
-	
 	Field input:Gltf2Accessor	'time
 	Field output:Gltf2Accessor	'post/rot etc
 	Field interpolation:String
@@ -180,6 +178,17 @@ Class Gltf2Asset
 		Return asset
 	End
 	
+	Function Parse:Gltf2Asset( json:String )
+		
+		Local root:=JsonObject.Parse( json )
+		If Not root Return Null
+		
+		Local asset:=New Gltf2Asset( root )
+		If Not asset.LoadAsset() Return Null
+		
+		Return asset
+	End
+	
 	Private
 	
 	Field root:JsonObject

+ 67 - 21
modules/mojo3d/loader/gltf2loader.monkey2

@@ -5,9 +5,10 @@ Private
 
 Class Gltf2Loader
 	
-	Method New( asset:Gltf2Asset,dir:String )
+	Method New( asset:Gltf2Asset,bindata:DataBuffer,dir:String )
 		
 		_asset=asset
+		_bindata=bindata
 		_dir=dir
 	End
 	
@@ -72,8 +73,8 @@ Class Gltf2Loader
 	Field _dir:String
 	
 	Field _data:=New Map<Gltf2Buffer,DataBuffer>
-	
-'	Field _uridata:=New StringMap<DataBuffer>
+	Field _uridata:=New StringMap<DataBuffer>
+	Field _bindata:DataBuffer
 	
 	Field _textureCache:=New Map<Gltf2Texture,Texture>
 	Field _materialCache:=New Map<Gltf2Material,Material>
@@ -84,37 +85,38 @@ Class Gltf2Loader
 	
 	Field _bones:Model.Bone[]
 
-#rem
-	Method GetData:UByte Ptr( uri:String )
-		Local data:=_data[uri]
-		If Not data
-			data=DataBuffer.Load( _dir+uri )
-			_data[uri]=data
-		Endif
-		Return data.Data
-	End
-#end
-
 	Method GetData:UByte Ptr( buffer:Gltf2Buffer )
 		
 		If _data.Contains( buffer ) Return _data[buffer]?.Data
 		
-		Local data:DataBuffer
+		Local data:DataBuffer,uri:=buffer.uri
+		
+		If Not uri
+			
+			data=_bindata
 		
-		Local uri:=buffer.uri
-		If uri.StartsWith( "data:" )
+		Else If uri.StartsWith( "data:" )
+			
 			Local i:=uri.Find( ";base64," )
+			
 			If i<>-1
 				Local base64:=uri.Slice( i+8 )
 				data=DecodeBase64( base64 )
 			Else
 				Print "Can't decode data:"
 			Endif
+			
+		Else If _uridata.Contains( uri )
+			
+			data=_uridata[uri]
 		Else
+			
 			data=DataBuffer.Load( _dir+uri )
+			_uridata[uri]=data
 		Endif
 		
 		_data[buffer]=data
+		
 		Return data?.Data
 	End
 	
@@ -660,14 +662,58 @@ Class Gltf2Mojo3dLoader Extends Mojo3dLoader
 	
 	Private
 	
-	Method Open:Gltf2Loader( path:String )
+	Method Open:Gltf2Loader( path:String  )
+		
+		path=RealPath( path )
 		
-		If ExtractExt( path ).ToLower()<>".gltf" Return Null
+		Local asset:Gltf2Asset,bindata:DataBuffer
+		
+		Select ExtractExt( path ).ToLower()
+		Case ".glb"
+			
+			Local stream:=Stream.Open( path,"r" )
 			
-		Local asset:=Gltf2Asset.Load( path )
+			Local json:=""
+				
+			If stream.ReadUInt()=$46546C67	'"GLTF"
+				
+				Local version:=stream.ReadUInt()
+				Local length:=stream.ReadUInt()-12
+				
+				While length>0
+					
+					Local clength:=stream.ReadUInt()
+					Local ctype:=stream.ReadUInt()
+					
+					Select ctype
+					Case $4E4F534A		'"JSON"
+						Local buf:=stream.ReadAll( clength )
+						json=buf.PeekString( 0 )
+						buf.Discard()
+					Case $004E4942		'"BIN"
+						bindata=stream.ReadAll( clength )
+					End
+					
+					length-=clength+8
+				Wend
+			
+			Endif
+			
+			stream.Close()
+			
+			If Not json Return Null
+			
+			asset=Gltf2Asset.Parse( json )
+		
+		Case ".gltf"
+		
+			asset=Gltf2Asset.Load( path )
+			
+		End
+		
 		If Not asset Return Null
 		
-		Local loader:=New Gltf2Loader( asset,ExtractDir( path ) )
+		Local loader:=New Gltf2Loader( asset,bindata,ExtractDir( path ) )
 		
 		Return loader
 	End