Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- SuperStrict
- Framework sidesign.minib3d 'https://github.com/si-design/minib3d
- Graphics3D(DesktopWidth() * 0.7, DesktopHeight() * 0.7, 2)
- Local camera:TCamera = CreateCamera()
- MoveEntity(camera, 0, 0, -10)
- AmbientLight(255, 255, 255)
- Local testCube:TMesh = CreateCube()
- Local myBSP:TQBSP = TQBSP.LoadFile("DM1.BSP")
- 'Debug make a mesh
- Local mesh:TMesh = CreateMesh()
- Local surf:TSurface = CreateSurface(mesh, Null)
- For Local m:TQModel = EachIn myBSP.Models
- Local face:TQFace
- For Local fNr:Int = m.Face_ID Until m.Face_ID + m.Face_Num
- face = TQFace(myBSP.Faces.ValueAtIndex(fNr))
- Print face.Ledge_ID
- Next
- Next
- While Not AppTerminate() And Not KeyDown(KEY_ESCAPE)
- Cls()
- If KeyDown(KEY_LEFT) Then TurnEntity(camera, 0, 2, 0)
- If KeyDown(KEY_RIGHT) Then TurnEntity(camera, 0, -2, 0)
- If KeyDown(KEY_UP) Then TurnEntity(camera, -2, 0, 0)
- If KeyDown(KEY_DOWN) Then TurnEntity(camera, 2, 0, 0)
- If KeyDown(KEY_W) Then MoveEntity(camera, 0, 0, 1.5)
- If KeyDown(KEY_S) Then MoveEntity(camera, 0, 0, -1.5)
- If KeyDown(KEY_A) Then MoveEntity(camera, -1.5, 0, 0)
- If KeyDown(KEY_D) Then MoveEntity(camera, 1.5, 0, 0)
- If KeyDown(KEY_SPACE) Then MoveEntity(camera, 0, 1, 0)
- If KeyDown(KEY_LCONTROL) Then MoveEntity(camera, 0, -1, 0)
- RenderWorld()
- Flip(1)
- Wend
- End
- Type TQBSP
- Field File:String
- Field Stream:TStream
- Field Header:TQHeader
- Field PLANES:TList = CreateList()
- Field Vertices:TList = CreateList()
- Field Nodes:TList = CreateList()
- Field TexInfo:TList = CreateList()
- Field Faces:TList = CreateList()
- Field ClipNodes:TList = CreateList()
- Field Leaves:TList = CreateList()
- Field Edges:TList = CreateList()
- Field Models:TList = CreateList()
- Function LoadFile:TQBSP(url:String)
- Local nB:TQBSP = New TQBSP
- nB.File = url
- If nB.Process() Then
- Return nB
- Else
- nB.StreamError("Map ~q" + nB.file + "~q NOT loaded")
- Return Null
- EndIf
- EndFunction
- Method StreamError(MSG:String)
- If Stream Then CloseStream(Stream)
- Print "Read error: " + MSG
- EndMethod
- Method Process:Int()
- Stream = OpenStream(File)
- If Not Stream Then
- StreamError("Unable to read file ~q" + file + "~q")
- Return False
- EndIf
- Local num:Int 'For counting stuff
- Local i:Int 'For loops
- 'Read header
- Self.Header = TQHeader.Read(Stream)
- 'Read planes
- 'num = Self.Header.PLANES.Count(TQPlane.Size())
- 'DebugLog "Planes: " + num
- 'Self.Header.PLANES.JumpTo(Stream)
- 'For i = 0 Until num
- ' ListAddLast(Self.PLANES, TQPlane.Read(Stream))
- 'Next
- 'Read vertices
- num = Self.Header.Vertices.Count(TQVertex.Size())
- DebugLog "Vertices: " + num
- Self.Header.Vertices.JumpTo(Stream)
- For i = 0 Until num
- ListAddLast(Self.Vertices, TQVertex.Read(Stream))
- Next
- 'Read nodes
- 'num = Self.Header.Nodes.Count(TQNode.Size())
- 'DebugLog "Nodes: " + num
- 'Self.Header.Nodes.JumpTo(Stream)
- 'For i = 0 Until num
- ' ListAddLast(Self.Nodes, TQNode.Read(Stream))
- 'Next
- 'Read texture info
- num = Self.Header.TexInfo.Count(TQSurface.Size())
- DebugLog "TexInfos: " + num
- Self.Header.TexInfo.JumpTo(Stream)
- For i = 0 Until num
- ListAddLast(Self.TexInfo, TQSurface.Read(Stream))
- Next
- 'Read faces
- num = Self.Header.Faces.Count(TQFace.Size())
- DebugLog "Faces: " + num
- Self.Header.Faces.JumpTo(Stream)
- For i = 0 Until num
- ListAddLast(Self.Faces, TQFace.Read(Stream))
- Next
- 'Read clipnodes
- 'num = Self.Header.ClipNodes.Count(TQClipNode.Size())
- 'DebugLog "ClipNodes: " + num
- 'Self.Header.ClipNodes.JumpTo(Stream)
- 'For i = 0 Until num
- ' ListAddLast(Self.ClipNodes, TQClipNode.Read(Stream))
- 'Next
- 'Read leaves
- 'num = Self.Header.Leaves.Count(TQDLeaf.Size())
- 'DebugLog "Leaves: " + num
- 'Self.Header.Leaves.JumpTo(Stream)
- 'For i = 0 Until num
- ' ListAddLast(Self.Leaves, TQDLeaf.Read(Stream))
- 'Next
- 'Read edges
- num = Self.Header.Edges.Count(TQEdge.Size())
- DebugLog "Edges: " + num
- Self.Header.Edges.JumpTo(Stream)
- For i = 0 Until num
- ListAddLast(Self.Edges, TQEdge.Read(Stream))
- Next
- 'Read models
- num = Self.Header.Models.Count(TQModel.Size())
- DebugLog "Models: " + num
- Self.Header.Models.JumpTo(Stream)
- For i = 0 Until num
- ListAddLast(Self.Models, TQModel.Read(Stream))
- Next
- CloseStream(Stream)
- Return True
- EndMethod
- EndType
- 'http://www.gamers.org/dEngine/quake/spec/quake-spec34/qkspec_4.htm
- 'char 8bit = negative byte
- 'u_char 8bit = byte
- 'short 16bit = negative short
- 'u_short 16bit = short
- 'long 32bit = int
- 'u_long 32bit = longer int
- 'float 32bit = float
- 'scalar_t 32bit = float
- Type TQHeader
- Field Version:Int
- Field Entities:TQEntry
- Field PLANES:TQEntry
- Field MipTex:TQEntry
- Field Vertices:TQEntry
- Field VisiList:TQEntry
- Field Nodes:TQEntry
- Field TexInfo:TQEntry
- Field Faces:TQEntry
- Field LightMaps:TQEntry
- Field ClipNodes:TQEntry
- Field Leaves:TQEntry
- Field LFace:TQEntry
- Field Edges:TQEntry
- Field Ledges:TQEntry
- Field Models:TQEntry
- Function Read:TQHeader(Stream:TStream)
- Local nH:TQHeader = New TQHeader
- nH.Version = ReadCInt(Stream)
- If nH.Version = "29" Then
- Print "Correct BSP version (" + nH.Version + ")"
- Else
- Print "Warning: Wrong BSP version (" + nH.Version + ")"
- EndIf
- nH.Entities = TQEntry.Read(Stream)
- nH.PLANES = TQEntry.Read(Stream)
- nH.MipTex = TQEntry.Read(Stream)
- nH.Vertices = TQEntry.Read(Stream)
- nH.VisiList = TQEntry.Read(Stream)
- nH.Nodes = TQEntry.Read(Stream)
- nH.TexInfo = TQEntry.Read(Stream)
- nH.Faces = TQEntry.Read(Stream)
- nH.LightMaps = TQEntry.Read(Stream)
- nH.ClipNodes = TQEntry.Read(Stream)
- nH.Leaves = TQEntry.Read(Stream)
- nH.LFace = TQEntry.Read(Stream)
- nH.Edges = TQEntry.Read(Stream)
- nH.Ledges = TQEntry.Read(Stream)
- nH.Models = TQEntry.Read(Stream)
- Return nH
- EndFunction
- EndType
- Type TQModel
- Field Bound:TQBoundBox
- Field Origin:TQVec3
- Field Node_ID0:Int
- Field Node_ID1:Int
- Field Node_ID2:Int
- Field Node_ID3:Int
- Field NumLeafs:Int
- Field Face_ID:Int
- Field Face_Num:Int
- Function Read:TQModel(Stream:TStream)
- Local nM:TQModel = New TQModel
- nM.Bound = TQBoundBox.Read(Stream)
- nM.Origin = TQVec3.Read(Stream)
- nM.Node_ID0 = ReadCInt(Stream)
- nM.Node_ID1 = ReadCInt(Stream)
- nM.Node_ID2 = ReadCInt(Stream)
- nM.Node_ID3 = ReadCInt(Stream)
- nM.NumLeafs = ReadCInt(Stream)
- nM.Face_ID = ReadCInt(Stream)
- nM.Face_Num = ReadCInt(Stream)
- Return nM
- EndFunction
- Function Size:Int(C:Int = True)
- If C Then
- Return CSize([B_INT ,B_INT,B_INT,B_INT,B_INT,B_INT,B_INT, TQBoundBox.Size(), TQVec3.Size()])
- Else
- Return (B_INT * 7) + TQBoundBox.Size() + TQVec3.Size()
- EndIf
- EndFunction
- EndType
- Type TQVertex
- Field X:Float
- Field Y:Float
- Field Z:Float
- Function Read:TQVertex(Stream:TStream)
- Local nV:TQVertex = New TQVertex
- nV.Z = ReadCFloat(Stream)
- nV.X = ReadCFloat(Stream)
- nV.Y = ReadCFloat(Stream)
- Return nV
- EndFunction
- Function Size:Int(C:Int = True)
- If C Then
- Return CSize([B_FLOAT, B_FLOAT, B_FLOAT])
- Else
- Return B_FLOAT * 3
- EndIf
- EndFunction
- EndType
- Type TQSurface
- Field VectorS:TQVec3
- Field DistS:Float
- Field VectorT:TQVec3
- Field DistT:Float
- Field Texture_ID:Int
- Field Animated:Int
- Function Read:TQSurface(Stream:TStream)
- Local nS:TQSurface = New TQSurface
- nS.VectorS = TQVec3.Read(Stream)
- nS.DistS = ReadCFloat(Stream)
- nS.VectorT = TQVec3.Read(Stream)
- nS.DistT = ReadCFloat(Stream)
- nS.Texture_ID = ReadCInt(Stream)
- nS.Animated = ReadCInt(Stream)
- Return nS
- EndFunction
- Function Size:Int(C:Int = True)
- If C Then
- Return CSize([B_FLOAT, B_FLOAT, B_INT, B_INT, TQVec3.Size(), TQVec3.Size()])
- Else
- Return (B_FLOAT * 2) + (B_INT * 2) + (TQVec3.Size() * 2)
- EndIf
- EndFunction
- EndType
- Type TQEdge
- Field Vertex0:Short
- Field Vertex1:Short
- Function Read:TQEdge(Stream:TStream)
- Local nE:TQEdge = New TQEdge
- nE.Vertex0 = ReadCShort(Stream)
- nE.Vertex1 = ReadCShort(Stream)
- Return nE
- EndFunction
- Function Size:Int(C:Int = True)
- If C Then
- Return CSize([B_SHORT, B_SHORT])
- Else
- Return B_SHORT*2
- EndIf
- EndFunction
- EndType
- Type TQFace
- Field Plane_ID:Short
- Field Side:Short
- Field Ledge_ID:Int
- Field Ledge_Num:Short
- Field TexInfo_ID:Short
- Field TypeLight:Byte
- Field BaseLight:Byte
- Field Light:Byte[2]
- Field LightMap:Int
- Function Read:TQFace(Stream:TStream)
- Local nF:TQFace = New TQFace
- nF.Plane_ID = ReadCShort(Stream)
- nF.Side = ReadCShort(Stream)
- nF.Ledge_ID = ReadCInt(Stream)
- nF.Ledge_Num = ReadCShort(Stream)
- nF.TexInfo_ID = ReadCShort(Stream)
- nF.TypeLight = ReadCByte(Stream)
- nF.BaseLight = ReadCByte(Stream)
- nF.Light = ReadCByteArray(Stream, 2)
- nF.LightMap = ReadCInt(Stream)
- Return nF
- EndFunction
- Function Size:Int(C:Int = True)
- If C Then
- Return CSize([B_SHORT, B_SHORT, B_SHORT, B_SHORT, B_INT, B_INT, B_BYTE, B_BYTE, B_BYTE, B_BYTE])
- Else
- Return (B_SHORT * 4) + (B_INT * 2) + (B_BYTE * 4)
- EndIf
- EndFunction
- EndType
- Type TQMipHeader
- Field NumTex:Int
- Field Offset:Int[]
- Function Read:TQMipHeader(Stream:TStream)
- Local nM:TQMipHeader = New TQMipHeader
- nM.NumTex = ReadCInt(Stream)
- nM.Offset = ReadCIntArray(Stream, nM.NumTex) 'Should I even read this?
- Return nM
- EndFunction
- EndType
- Type TQMipTex
- 'Field Name:Byte[16]
- Field Name:String
- Field width:Int
- Field Height:Int
- Field Offset1:Int
- Field Offset2:Int
- Field Offset4:Int
- Field Offset8:Int
- Function Read:TQMipTex(Stream:TStream)
- Local nM:TQMipTex = New TQMipTex
- nM.Name = ReadCString(Stream, 16)
- nM.width = ReadCInt(Stream)
- nM.Height = ReadCInt(Stream)
- nM.Offset1 = ReadCInt(Stream)
- nM.Offset2 = ReadCInt(Stream)
- nM.Offset4 = ReadCInt(Stream)
- nM.Offset8 = ReadCInt(Stream)
- Return nM
- EndFunction
- Function Size:Int()
- Print "Not correct!"
- Return (4 * 6) + (16)
- EndFunction
- EndType
- Type TQEntry
- Field Offset:Int
- Field Size:Int
- Function Read:TQEntry(Stream:TStream)
- Local nE:TQEntry = New TQEntry
- nE.Offset = ReadCInt(Stream)
- nE.Size = ReadCInt(Stream)
- Return nE
- EndFunction
- Method Count:Int(typeSize:Int)
- Return Size / typeSize
- EndMethod
- Method JumpTo(Stream:TStream)
- Stream.Seek(Self.Offset)
- EndMethod
- EndType
- Type TQNode
- Field Plane_ID:Int
- Field Front:Short
- Field Back:Short
- Field Box:TQBBoxShort
- Field Face_ID:Short
- Field Face_Num:Short
- Function Read:TQNode(Stream:TStream)
- Local nN:TQNode = New TQNode
- nN.Plane_ID = ReadCInt(Stream)
- nN.Front = ReadCShort(Stream)
- nN.Back = ReadCShort(Stream)
- nN.Box = TQBBoxShort.Read(Stream)
- nN.Face_ID = ReadCShort(Stream)
- nN.Face_Num = ReadCShort(Stream)
- Return nN
- EndFunction
- Function Size:Int()
- Print "Not correct!"
- Return (4) + (2 * 4) + TQBBoxShort.Size()
- EndFunction
- EndType
- Type TQDLeaf
- Field Typ:Int
- Field VisList:Int
- Field Bound:TQBBoxShort
- Field LFace_ID:Short
- Field LFace_Num:Short
- Field SndWater:Byte
- Field SndSky:Byte
- Field SndSlime:Byte
- Field SndLava:Byte
- Function Read:TQDLeaf(Stream:TStream)
- Local nD:TQDLeaf = New TQDLeaf
- nD.Typ = ReadCInt(Stream)
- nD.VisList = ReadCInt(Stream)
- nD.Bound = TQBBoxShort.Read(Stream)
- nD.LFace_ID = ReadCShort(Stream)
- nD.LFace_Num = ReadCShort(Stream)
- nD.SndWater = ReadCByte(Stream)
- nD.SndSky = ReadCByte(Stream)
- nD.SndSlime = ReadCByte(Stream)
- nD.SndLava = ReadCByte(Stream)
- Return nD
- EndFunction
- Function Size:Int()
- Print "Not correct!"
- Return (4 * 2) + (2 * 2) + (4) + TQBBoxShort.Size()
- EndFunction
- EndType
- Type TQPlane
- Field Normal:TQVec3
- Field Dist:Float
- Field Typ:Int
- Function Read:TQPlane(Stream:TStream)
- Local nP:TQPlane = New TQPlane
- nP.Normal = TQVec3.Read(Stream)
- nP.Dist = ReadCFloat(Stream)
- nP.Typ = ReadCInt(Stream)
- Return nP
- EndFunction
- Function Size:Int()
- Print "Not correct!"
- Return SizeOf(4 * 2) + TQVec3.Size()
- EndFunction
- EndType
- Type TQClipNode
- Field PlaneNum:Int
- Field Front:Short
- Field Back:Short
- Function Read:TQClipNode(Stream:TStream)
- Local nC:TQClipNode = New TQClipNode
- nC.PlaneNum = ReadCInt(Stream)
- nC.Front = ReadCShort(Stream)
- nC.Back = ReadCShort(Stream)
- Return nC
- EndFunction
- Function Size:Int()
- Print "Not correct!"
- Return SizeOf(TQClipNode)
- EndFunction
- EndType
- 'Basic types
- Type TQVec3
- Field X:Float
- Field Y:Float
- Field Z:Float
- Function Read:TQVec3(Stream:TStream)
- Local nV:TQVec3 = New TQVec3
- nV.X = ReadCFloat(Stream)
- nV.Y = ReadCFloat(Stream)
- nV.Z = ReadCFloat(Stream)
- Return nV
- EndFunction
- Function Size:Int(C:Int = True)
- If C Then
- Return CSize([B_FLOAT, B_FLOAT, B_FLOAT])
- Else
- Return B_FLOAT * 3
- EndIf
- EndFunction
- EndType
- Type TQBoundBox
- Field Minimum:TQVec3
- Field Maximum:TQVec3
- Function Read:TQBoundBox(Stream:TStream)
- Local nB:TQBoundBox = New TQBoundBox
- nB.Minimum = TQVec3.Read(Stream)
- nB.Maximum = TQVec3.Read(Stream)
- Return nB
- EndFunction
- Function Size:Int(C:Int = True)
- If C Then
- Return CSize([TQVec3.Size(), TQVec3.Size()])
- Else
- Return TQVec3.Size() * 2
- EndIf
- EndFunction
- EndType
- Type TQBBoxShort
- Field Minimum:Short
- Field Maximum:Short
- Function Read:TQBBoxShort(Stream:TStream)
- Local nB:TQBBoxShort = New TQBBoxShort
- nB.Minimum = ReadCShort(Stream)
- nB.Maximum = ReadCShort(Stream)
- Return nB
- EndFunction
- Function Size:Int(C:Int = True)
- If C Then
- Return CSize([B_SHORT, B_SHORT])
- Else
- Return B_SHORT * 2
- EndIf
- EndFunction
- EndType
- 'Reading padded C values
- Const B_BYTE:Int = 1
- Const B_SHORT:Int = 2
- Const B_INT:Int = 4
- Const B_FLOAT:Int = 4
- Function ReadCByte:Byte(Stream:TStream)
- Local result:Byte = ReadByte(Stream)
- Stream.Seek(((StreamPos(Stream) + 3) / 4) * 4)
- Return result
- EndFunction
- Function ReadCShort:Short(Stream:TStream)
- Local result:Short = ReadShort(Stream)
- Stream.Seek(((StreamPos(Stream) + 3) / 4) * 4)
- Return result
- EndFunction
- Function ReadCInt:Int(Stream:TStream)
- Return ReadInt(Stream)
- EndFunction
- Function ReadCFloat:Int(Stream:TStream)
- Return ReadFloat(Stream)
- EndFunction
- Function ReadCByteArray:Byte[] (Stream:TStream, Length:Int)
- Local result:Byte[Length]
- For Local i:Int = 0 Until result.Length
- result[i] = ReadByte(Stream)
- Next
- Stream.Seek(((StreamPos(Stream) + 3) / 4) * 4)
- Return result
- EndFunction
- Function ReadCIntArray:Int[] (Stream:TStream, Length:Int)
- Local result:Int[Length]
- For Local i:Int = 0 Until result.Length
- result[i] = ReadInt(Stream)
- Next
- Stream.Seek(((StreamPos(Stream) + 3) / 4) * 4)
- Return result
- EndFunction
- Function ReadCString:String(Stream:TStream, Length:Int)
- Local result:String
- For Local i:Int = 0 Until Length
- result:+ReadByte(Stream)
- Next
- Stream.Seek(((StreamPos(Stream) + 3) / 4) * 4)
- Return result
- EndFunction
- Function CSize:Int(val:Int[])
- Local result:Int
- For Local i:Int = 0 Until val.Length
- result:+((val[i] + 3) / 4) * 4
- Next
- Return result
- EndFunction
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement