X File Parser

BlitzMax Forums/BlitzMax Programming/X File Parser

This code loads a text .x file and returns a node hierarchy. Each node has an id, name (if applicable), and string data contained within that node.

This code does not interpret mesh data, it just loads the .x file hierarchy. The next step would be to go through the nodes and create a model from the data.

The code might have problems if it encounters a name that is the same as an x node name, like if you have an object called "mesh" or "frame".

Type TXNode
	Field id$
	Field name$
	Field data$
	Field kids:TList=New TList
EndType

Function LoadX:TXNode(url:Object)
	Local stream:TStream
	Local root:TXNode
	Local tag$
	
	stream=ReadStream(url)
	If Not stream Return
	
	If stream.ReadLine()<>"xof 0303txt 0032"
		stream.close()
		Return
	EndIf
	
	root=New TXNode
	root.id="Root"
	ReadNode(root,stream)
	
	PrintNode root
	
	stream.close()
	
	Return root
	
	Function PrintNode(node:TXNode,tab$="")
		Local ch:TXNode
		Print tab+node.id+" "+node.name
		Print tab+"	{"
		If node.data<>"" Print node.data
		For ch=EachIn node.kids
			PrintNode ch,tab+"	"
		Next
		Print tab+"	}"
	EndFunction
	
	Function ReadToOpenParenthesis$(stream:TStream)
		Local s$,c$
		While Not stream.Eof()
			c=Chr(stream.ReadByte())
			If c="{" Return s
			s:+c
		Wend
	EndFunction
	
	Function TagValid:Int(tag$)
		Select tag
			Case "texturefilename","skinweights","skinmeshheader","frame","meshnormals","mesh","meshmateriallist","animation","animationkey","material","meshtexturecoords","frametransformmatrix","animationset","template" Return 1
			Default Return 0
		EndSelect
	EndFunction
	
	Function ReadWord$(stream:TStream)
		Local s$,c$
		While Not stream.Eof()
			c=Chr(stream.ReadByte())
			If IsWhiteSpace(c)
				If s<>"" Return s
			Else
				s:+c
			EndIf
		Wend
		Return s
	EndFunction
	
	Function IsWhiteSpace:Int(s$)
		If Trim(s)="" Return 1 Else Return 0
	EndFunction
	
	Function ReadNode(node:TXNode,stream:TStream)
		Local tag$
		Local ch:TXNode
		Local strarr$[]
		While Not stream.Eof()
			tag=Lower(readword(stream))
			If TagValid(tag)
				ch=New TXNode
				ch.id=tag
				node.kids.addlast ch
				ch.name=Trim(ReadToOpenParenthesis(stream))
				ReadNode(ch,stream)
			ElseIf tag="}"
				node.data=Replace(node.data,"{","")
				node.data=Replace(node.data,"}","")
				Return
			Else
				node.data:+tag+" "
			EndIf
		Wend
	EndFunction
	
EndFunction


Here is some example output:
Root 
	{
	template Frame
		{
<3d82ab46-62da-11cf-ab39-0020af71e433> [...] 
		}
	template Matrix4x4
		{
<f6f23f45-7686-11cf-8f52-0040333594a3> array float matrix[16]; 
		}
	template FrameTransformMatrix
		{
<f6f23f41-7686-11cf-8f52-0040333594a3> matrix4x4 framematrix; 
		}
	template Vector
		{
<3d82ab5e-62da-11cf-ab39-0020af71e433> float x; float y; float z; 
		}
	template MeshFace
		{
<3d82ab5f-62da-11cf-ab39-0020af71e433> dword nfacevertexindices; array dword facevertexindices[nfacevertexindices]; 
		}
	template Mesh
		{
<3d82ab44-62da-11cf-ab39-0020af71e433> dword nvertices; array vector vertices[nvertices]; dword nfaces; array meshface faces[nfaces]; [...] 
		}
	template MeshNormals
		{
<f6f23f43-7686-11cf-8f52-0040333594a3> dword nnormals; array vector normals[nnormals]; dword nfacenormals; array meshface facenormals[nfacenormals]; 
		}
	template ColorRGBA
		{
<35ff44e0-6c7c-11cf-8f52-0040333594a3> float red; float green; float blue; float alpha; 
		}
	template ColorRGB
		{
<d3e16e81-7835-11cf-8f52-0040333594a3> float red; float green; float blue; 
		}
	template Material
		{
<3d82ab4d-62da-11cf-ab39-0020af71e433> colorrgba facecolor; float power; colorrgb specularcolor; colorrgb emissivecolor; [...] 
		}
	template MeshMaterialList
		{
<f6f23f42-7686-11cf-8f52-0040333594a3> dword nmaterials; dword nfaceindexes; array dword faceindexes[nfaceindexes]; [material <3d82ab4d-62da-11cf-ab39-0020af71e433>] 
		}
	template Coords2d
		{
<f6f23f44-7686-11cf-8f52-0040333594a3> float u; float v; 
		}
	template MeshTextureCoords
		{
<f6f23f40-7686-11cf-8f52-0040333594a3> dword ntexturecoords; array coords2d texturecoords[ntexturecoords]; 
		}
	frame Box01
		{
		frametransformmatrix 
			{
1.000000,0.000000,0.000000,0.000000,0.000000,0.000000,-1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-6.513411,-7.662834,0.000000,1.000000;; 
			}
		mesh 
			{
20; -56.704979;0.000000;-41.379311;, 56.704979;0.000000;-41.379311;, -56.704979;0.000000;41.379311;, 56.704979;0.000000;41.379311;, -56.704979;89.655174;-41.379311;, 56.704979;89.655174;-41.379311;, -56.704979;89.655174;41.379311;, 56.704979;89.655174;41.379311;, -56.704979;0.000000;-41.379311;, 56.704979;89.655174;-41.379311;, 56.704979;0.000000;-41.379311;, -56.704979;89.655174;-41.379311;, 56.704979;0.000000;41.379311;, 56.704979;89.655174;-41.379311;, 56.704979;0.000000;41.379311;, -56.704979;89.655174;41.379311;, -56.704979;0.000000;41.379311;, 56.704979;89.655174;41.379311;, -56.704979;0.000000;41.379311;, -56.704979;89.655174;-41.379311;; 12; 3;0,3,2;, 3;3,0,1;, 3;4,7,5;, 3;7,4,6;, 3;8,9,10;, 3;9,8,11;, 3;1,7,12;, 3;7,1,13;, 3;14,15,16;, 3;15,14,17;, 3;18,19,0;, 3;19,18,6;; 
			meshnormals 
				{
6; 0.000000;-1.000000;0.000000;, 0.000000;1.000000;0.000000;, 0.000000;0.000000;-1.000000;, 1.000000;0.000000;0.000000;, 0.000000;0.000000;1.000000;, -1.000000;0.000000;0.000000;; 12; 3;0,0,0;, 3;0,0,0;, 3;1,1,1;, 3;1,1,1;, 3;2,2,2;, 3;2,2,2;, 3;3,3,3;, 3;3,3,3;, 3;4,4,4;, 3;4,4,4;, 3;5,5,5;, 3;5,5,5;; 
				}
			meshmateriallist 
				{
1; 12; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 
				material 
					{
0.721569;0.894118;0.600000;1.000000;; 0.000000; 0.721569;0.894118;0.600000;; 0.000000;0.000000;0.000000;; 
					}
				}
			meshtexturecoords 
				{
20; 1.000000;1.000000;, 0.000000;1.000000;, 1.000000;0.000000;, 0.000000;0.000000;, 0.000000;1.000000;, 1.000000;1.000000;, 0.000000;0.000000;, 1.000000;0.000000;, 0.000000;1.000000;, 1.000000;0.000000;, 1.000000;1.000000;, 0.000000;0.000000;, 1.000000;1.000000;, 0.000000;0.000000;, 0.000000;1.000000;, 1.000000;0.000000;, 1.000000;1.000000;, 0.000000;0.000000;, 0.000000;1.000000;, 1.000000;0.000000;; 
				}
			}
		}
	}