.x Microsoft Direct X XoF loader
Posted: Wed Feb 11, 2026 11:54 am
For exporting to ogre mesh:
More description in the header.
More description in the header.
Code: Select all
;=====================================
;.x (microsoft direct x XOF) loader.
;Created by miso
;Usage policy 777, do what you please
;No warranties whatsoever.
;
;This is not a parser, but a quick and dirty hack
;to get the mesh data from a xof file.
;I post this, as it surprisingly performed well with 95% of my .x meshes.
;
;Works with :
;-text format .x
;-single mesh
;
;-if submeshes are presented, only the last one will be loaded
;-animations might be presented, but will be skipped
;This tool is mainly for loading meshes and export it with savemesh() to native ogre
;if you lack an exporter, or have to deal with different exporters winding issues programmatically first.
;NOTE: If you improve this in any way, please consider reposting. Thanks.
;NOTE: After this I started to make a tokenizer that could even extract bone and animation data,
;I finished the tokenizer part, idents, lbrace, rbrace, int, float, string, etc
;but got distracted so I don't know when will I deal with the mesh assembly part.
;It's not advised, but if you need that and got strength to fiddle with it, pm me. Will send you the tokenizer part.
;I also could not managed to use zlib inflate, it will be required for the binary parse.
;(I'm not good with linking/debugging external libraries.)
UseJPEGImageDecoder()
UsePNGImageEncoder()
Structure vertex
x.f : y.f : z.f : nx.f : ny.f : nz.f : u.f : v.f
EndStructure
Structure face
v.i : a.i : b.i : c.i : d.i
EndStructure
;===========================================
;Windowed fullscreen quickstart for 3d
;===========================================
Procedure ministart3d(wTitle.s)
InitEngine3D():InitSprite():InitKeyboard():InitMouse():UsePNGImageDecoder():UsePNGImageEncoder():UseJPEGImageDecoder():UseJPEGImageEncoder()
ExamineDesktops()
OpenWindow(0, 0, 0, DesktopUnscaledX(DesktopWidth(0)), DesktopUnscaledY(DesktopHeight(0)), wTitle, #PB_Window_ScreenCentered|#PB_Window_BorderLess|#PB_Window_Invisible)
OpenWindowedScreen(WindowID(0), 0, 0, WindowWidth(0) * DesktopResolutionX() , WindowHeight(0) * DesktopResolutionY(), 0, 0, 0, #PB_Screen_WaitSynchronization)
CreateCamera(0,0,0,100,100)
CameraBackColor(0,RGB(0,0,0))
CreateLight(0,RGB(255,255,255),-50,50,0,#PB_Light_Point)
RenderWorld()
HideWindow(0,#False)
EndProcedure
;===========================================
;Quickly handles flipbuffers, window events,
;keyboard and mouse, esc And mouse middle
;quits For short programs/tests
;===========================================
Procedure minicheckevents()
FlipBuffers()
While WindowEvent() : Wend
ClearScreen(RGBA(0,0,0,255)) ;Linux Fix at the moment
ExamineKeyboard()
ExamineMouse()
MouseDeltaX() ;Linux Fix at the moment
If KeyboardPushed(#PB_Key_Escape) Or MouseButton(#PB_MouseButton_Middle) : End : EndIf
EndProcedure
Procedure.s fixstring(s.s)
Protected temp.s
temp.s = UCase(s.s)
temp.s = ReplaceString(temp.s,"MESH ","MESH$")
temp.s = ReplaceString(temp.s," ","")
temp.s = ReplaceString(temp.s,Chr(9),"")
ProcedureReturn temp.s
EndProcedure
Procedure loadx(filename.s)
Protected fID.i
Protected sread.s
Protected vcount.i
Protected fcount.i
Protected Dim vertices.vertex(0)
Protected Dim faces.face(0)
Protected fval.i
fID =OpenFile(#PB_Any,filename)
Repeat
sread = fixstring ( ReadString(fID) )
If Left(sread,5)="MESH$"
sread = fixstring( ReadString(fid) )
If sread ="{" : sread = fixstring( ReadString(fid) ) : EndIf
vcount = Val(StringField(sread,1,";"))
Debug vcount
Dim vertices.vertex(vcount-1)
For i = 0 To vcount-1
sread = fixstring( ReadString(fid) )
vertices(i)\x = ValF(StringField(sread,1,";"))
vertices(i)\y = ValF(StringField(sread,2,";"))
vertices(i)\z = ValF(StringField(sread,3,";"))
;Debug vertices(i)\x
Next i
sread = fixstring( ReadString(fid) )
fcount = Val(StringField(sread,1,";"))
Dim faces.face(fcount)
Debug fcount
For i = 0 To fcount-1
sread = fixstring( ReadString(fid) )
fval = Val(StringField(sread,1,";"))
faces(i)\v = fval
sread = StringField(sread,2,";")
If fval = 3
faces(i)\a = Val(StringField(sread,1,","))
faces(i)\b = Val(StringField(sread,2,","))
faces(i)\c = Val(StringField(sread,3,","))
Else
faces(i)\a = Val(StringField(sread,1,","))
faces(i)\b = Val(StringField(sread,2,","))
faces(i)\c = Val(StringField(sread,3,","))
faces(i)\d = Val(StringField(sread,4,","))
EndIf
Next i
EndIf
If Left(sread,11)="MESHNORMALS"
;often buggy, so it will be generated instead
Repeat
sread = fixstring( ReadString(fid) )
Until Left(sread,1)="}"
EndIf
If Left(sread,8)="MESHTEXT"
sread = fixstring( ReadString(fid) )
If sread ="{" : sread = fixstring( ReadString(fid) ) : EndIf
Debug Val(StringField(sread,1,";"))
If vcount = Val(StringField(sread,1,";"))
Debug "OK==========================="
For i = 0 To vcount-1
sread = fixstring( ReadString(fid) )
vertices(i)\u = ValF(StringField(sread,1,";"))
vertices(i)\v = ValF(StringField(sread,2,";"))
Debug "----"
Next i
Else
Debug "NOT OK==========================="
vcount = Val(StringField(sread,1,";"))
For i = 0 To vcount-1
sread = fixstring( ReadString(fid) )
vertices(i)\u = ValF(StringField(sread,1,";"))
vertices(i)\v = ValF(StringField(sread,2,";"))
Debug "----"
Next i
EndIf
EndIf
Until Eof(fid)
CloseFile(fid)
m_id = CreateMesh(#PB_Any,#PB_Mesh_TriangleList)
For i = 0 To vcount-1
index = i
MeshVertex(vertices(index)\x,vertices(index)\y,vertices(index)\z,vertices(index)\u,vertices(index)\v,vertices(index)\nx,vertices(index)\ny,vertices(index)\nz,RGB(255,255,255))
Debug vertices(index)\u
Debug vertices(index)\v
Next i
For i = 0 To fcount-1
If faces(i)\v = 3
MeshFace(faces(i)\a,faces(i)\b,faces(i)\c)
ElseIf faces(i)\v = 4
MeshFace(faces(i)\c,faces(i)\b,faces(i)\a)
MeshFace(faces(i)\a,faces(i)\d,faces(i)\c)
EndIf
Next i
FinishMesh(#True)
NormalizeMesh(m_id)
BuildMeshTangents(m_id)
Debug fcount
Debug vcount
ProcedureReturn m_id
EndProcedure
ministart3d("Xof Loader")
MoveCamera(0,0,0,-50)
CameraLookAt(0,0,0,0)
Add3DArchive("shaders",#PB_3DArchive_FileSystem)
Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Main", #PB_3DArchive_FileSystem)
Parse3DScripts()
;-model name
knotmesh = loadx("model.x")
LoadTexture(1,"texture.png")
CreateMaterial(2,TextureID(1))
;Some mesh exported with a bad exporter. Uncheck culling to see faulty mesh.
;MaterialCullingMode(2,#PB_Material_NoCulling)
CreateEntity(1,MeshID(knotmesh),MaterialID(2))
speed = 2
Repeat
minicheckevents()
If KeyboardPushed(#PB_Key_W)
MoveCamera(0,0,0,-speed,#PB_Relative)
ElseIf KeyboardPushed(#PB_Key_S)
MoveCamera(0,0,0,speed,#PB_Relative)
EndIf
If KeyboardPushed(#PB_Key_A)
RotateCamera(0,0,0.5,0,#PB_Relative)
ElseIf KeyboardPushed(#PB_Key_D)
RotateCamera(0,0,-0.5,0,#PB_Relative)
EndIf
RotateEntity(1,0,0.1,0,#PB_Relative)
RenderWorld()
ForEver