Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- SuperStrict
- Framework sidesign.minib3d 'https://github.com/si-design/minib3d
- Import brl.Stream
- Import brl.linkedlist
- Import brl.standardio
- Import brl.bmploader
- Import brl.pngloader
- 'Data sizes
- Const B_BYTE:Int = 1
- Const B_SHORT:Int = 2
- Const B_INT:Int = 4
- Const B_FLOAT:Int = 4
- SetGraphicsDriver GLGraphicsDriver(),GRAPHICS_BACKBUFFER|GRAPHICS_DEPTHBUFFER
- Graphics3D(DesktopWidth() * 0.7, DesktopHeight() * 0.7, 0, 2)
- ClearTextureFilters()
- Global camera:TCamera = CreateCamera()
- MoveEntity(camera, 0, 0, -10)
- 'AmbientLight(255, 255, 255)
- 'Local light:TLight = CreateLight(1)
- 'RotateEntity(light, 45, 45, 0)
- TQPalette.LoadPalette("palette.lmp")
- Global myBSP:TQBSP
- Global levelMesh:TMesh
- Global levelMeshAlpha:TMesh
- 'Debug make a mesh
- Function GenerateBSPMesh(mesh:TMesh var, alphaMesh:TMesh var, myBSP:TQBSP)
- If mesh Then FreeEntity(mesh)
- If alphaMesh Then FreeEntity(alphaMesh)
- 'Local mesh:TMesh = CreateMesh()
- 'Local surf:TSurface[1024 * 10]
- GCCollect()
- mesh = CreateMesh()
- alphaMesh = CreateMesh()
- Local face:TQFace
- Local ledge:TQLedge
- Local edge:TQEdge
- Local plane:TQPlane
- Local texInfo:TQSurface
- Local vert:TQVertex
- Local fNr:Int
- Local eNr:Int
- Local surf:TSurface
- Local vertCount:Int
- Local newVertCount:Int
- Local s:Float
- Local t:Float
- For Local model:TQModel = EachIn myBSP.Models 'Go through models
- For fNr = model.Face_ID Until model.Face_ID + model.Face_Num 'Go through faces
- 'Debug progress
- 'If fNr Mod 100 <= 0 Then Print "Generating: " + fNr + "/" + model.Face_Num
- face = myBSP.Faces[fNr] 'Get current face
- texInfo = myBSP.texInfo[face.TexInfo_ID]
- plane = myBSP.PLANES[face.Plane_ID]
- If myBSP.MipTexs[texInfo.Texture_ID].Name.StartsWith("trigger") Then Continue
- 'ERROR if we're using too many vertices
- If face.Surface And face.Surface.CountVertices() > (10000 * 3) - 1 Then Print "TOO MANY VERTICES!!";End
- 'If we don't have a surface to work with, create one
- If Not face.Surface Then
- If myBSP.MipTexs[texInfo.Texture_ID].Name.StartsWith("*") Then
- face.Surface = CreateSurface(alphaMesh, Null)
- Else
- face.Surface = CreateSurface(mesh, Null)
- EndIf
- EndIf
- surf = face.Surface
- 'Get verts
- newVertCount = 0
- vertCount = surf.CountVertices()
- For eNr = face.Ledge_ID Until face.Ledge_ID + face.Ledge_Num 'Go through edges
- ledge = myBSP.Ledges[eNr] 'Get ledge
- edge = myBSP.Edges[Abs(ledge.edge)] 'Get edge via ledge
- If ledge.edge < 0 Then
- vert = myBSP.Vertices[edge.Vertex0]
- Else
- vert = myBSP.Vertices[edge.Vertex1]
- EndIf
- AddVertex(surf, -vert.Y * 0.2, vert.Z * 0.2, vert.X * 0.2)
- 'Calculate UV
- s = DotProduct(vert.X, vert.Y, vert.Z, texInfo.VectorS.X, texInfo.VectorS.Y, texInfo.VectorS.Z) + texInfo.DistS
- t = DotProduct(vert.X, vert.Y, vert.Z, texInfo.VectorT.X, texInfo.VectorT.Y, texInfo.VectorT.Z) + texInfo.DistT
- 'Test UV for lightmap
- If face.LightBrush Then VertexTexCoords(surf, vertCount, (s - face.LightMinUV.x) / face.LightDist.x, (t - face.LightMinUV.y) / face.LightDist.y)
- 'Based on texture size
- s:/myBSP.MipTexs[texInfo.Texture_ID].width
- t:/myBSP.MipTexs[texInfo.Texture_ID].Height
- 'VertexTexCoords(surf, vertCount, s, t) 'Real texture UV
- VertexNormal(surf, vertCount, plane.Normal.Z, plane.Normal.Y, plane.Normal.X)
- vertCount:+1
- newVertCount:+1
- Next
- 'Make Tris
- For Local i:Int = vertCount - newVertCount Until vertCount - 2
- AddTriangle(surf, vertCount - newVertCount, i + 1, i + 2)
- Next
- 'PaintSurface(surf, myBSP.MipTexs[texInfo.Texture_ID].Brush)
- If face.LightBrush Then PaintSurface(surf, face.LightBrush)
- Next
- Next
- EntityFX(mesh, 1 + 2)
- EntityFX(alphaMesh, 1 + 2)
- 'Return mesh
- GCCollect()
- EndFunction
- 'Print mesh.CountSurfaces()
- Function RequestBSP()
- Local filter:String = "BSP Files:bsp;All Files:*"
- Local file:String = RequestFile("Select BSP file to load", filter:String)
- If file Then
- PositionEntity(camera, -2, 2.5, -10)
- RotateEntity(camera, 0, 0, 0)
- myBSP = TQBSP.LoadFile(file)
- GenerateBSPMesh(levelMesh, levelMeshAlpha, myBSP)
- EndIf
- FlushKeys()
- FlushMouse()
- EndFunction
- If FileSize(AppDir + "/dm1.bsp") > 0 Then
- myBSP = TQBSP.LoadFile(AppDir + "/dm1.bsp")
- GenerateBSPMesh(levelMesh, levelMeshAlpha, myBSP)
- PositionEntity(camera, -250, 30, 70)
- RotateEntity(camera, 15, 180 + 25, 0)
- Else
- RequestBSP()
- EndIf
- 'Main loop
- While Not AppTerminate() And Not KeyDown(KEY_ESCAPE)
- 'Cls()
- 'If KeyHit(KEY_O) Then Wireframe(False)
- If KeyDown(KEY_P) Then Wireframe(True)
- 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)
- If KeyHit(KEY_TAB) Then RequestBSP()
- If myBSP Then myBSP.Update()
- RenderWorld()
- BeginMax2D()
- DrawText("TAB: Open BSP", 0, 0)
- EndMax2D()
- Flip(1)
- Wend
- End
- Type TQBSP
- Field File:String
- Field Stream:TStream
- Field Header:TQHeader
- Field PLANES:TQPlane[]
- Field Vertices:TQVertex[]
- Field Nodes:TList = CreateList()
- Field TexInfo:TQSurface[]
- Field MipTexHeader:TQMipHeader
- Field MipTexs:TQMipTex[]
- Field AnimatedMipTexs:TQMipTex[]
- Field Faces:TQFace[]
- Field ClipNodes:TList = CreateList()
- Field Leaves:TList = CreateList()
- Field Edges:TQEdge[]
- Field Ledges:TQLedge[]
- Field Models:TQModel[]
- 'Field LightMap:Byte[]
- Field StartMS:Int
- 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 Update()
- For Local m:TQMipTex = EachIn Self.AnimatedMipTexs
- PositionTexture(GetBrushTexture(m.Brush), (MilliSecs() - StartMS) * 0.00005, -(MilliSecs() - StartMS) * 0.0001)
- RotateTexture(GetBrushTexture(m.Brush), (MilliSecs() - StartMS) * 0.0005)
- Next
- EndMethod
- Method StreamError(MSG:String)
- If Stream Then CloseStream(Stream)
- DebugLog "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.PLANES = New TQPlane[num]
- Self.Header.PLANES.JumpTo(Stream)
- For i = 0 Until num
- 'ListAddLast(Self.PLANES, TQPlane.Read(Stream))
- Self.PLANES[i] = TQPlane.Read(Stream)
- Next
- 'Read vertices
- num = Self.Header.Vertices.Count(TQVertex.Size())
- DebugLog "Vertices: " + num
- Self.Vertices = New TQVertex[num]
- Self.Header.Vertices.JumpTo(Stream)
- For i = 0 Until num
- 'ListAddLast(Self.Vertices, TQVertex.Read(Stream))
- Self.Vertices[i] = 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 "TexInfo: " + num
- Self.TexInfo = New TQSurface[num]
- Self.Header.TexInfo.JumpTo(Stream)
- For i = 0 Until num
- Self.TexInfo[i] = TQSurface.Read(Stream)
- Next
- 'Read mipmap header
- Self.Header.MipTex.JumpTo(Stream)
- Self.MipTexHeader = TQMipHeader.Read(Stream)
- num = Self.MipTexHeader._count
- DebugLog "MipMap Texs: " + num
- 'Read miptexs from mipmap header
- 'CreateDir(AppDir + "/tex/", True) 'Debug for exporting
- MipTexs = New TQMipTex[num]
- For i = 0 Until num
- Stream.Seek(Self.Header.MipTex.Offset + Self.MipTexHeader.Offset[i])
- Self.MipTexs[i] = TQMipTex.Read(Stream)
- If Self.MipTexs[i].width > 1 And Self.MipTexs[i].Height > 1 Then
- Local pix:TPixmap = CreatePixmap(Self.MipTexs[i].width, Self.MipTexs[i].Height, PF_RGB888)
- Local x:Int
- Local y:Int
- Local colorID:Byte
- Local palColor:TQColor32
- Stream.Seek(Self.Header.MipTex.Offset + Self.MipTexHeader.Offset[i] + Self.MipTexs[i].Offset1)
- For Local bI:Int = 0 Until pix.width * pix.Height
- colorID = ReadByte(Stream)
- palColor = TQPalette.colors[colorID]
- pix.WritePixel(x, y, GenRGB(palColor.r, palColor.g, palColor.b))
- x:+1
- If x >= pix.width Then
- x = 0
- y:+1
- EndIf
- Next
- If pix Then
- Self.MipTexs[i].Brush = LoadBrushPixmap(pix, 0)
- If Self.MipTexs[i].Name.StartsWith("*") Then
- BrushAlpha(Self.MipTexs[i].Brush, 0.65)
- BrushBlend(Self.MipTexs[i].Brush, 1)
- AnimatedMipTexs = AnimatedMipTexs[..AnimatedMipTexs.Length + 1]
- AnimatedMipTexs[AnimatedMipTexs.Length - 1] = Self.MipTexs[i]
- EndIf
- EndIf
- EndIf
- Next
- 'Read faces
- num = Self.Header.Faces.Count(TQFace.Size())
- DebugLog "Faces: " + num
- Self.Faces = New TQFace[num]
- Self.Header.Faces.JumpTo(Stream)
- For i = 0 Until num
- Self.Faces[i] = TQFace.Read(Stream)
- Next
- 'Read lightmaps
- 'Self.Header.LightMaps.JumpTo(Stream)
- 'LightMap = New Byte[Self.Header.LightMaps.Size]
- 'For i:Int = 0 Until LightMap.Length
- ' LightMap[i] = ReadByte(Stream)
- 'Next
- 'Stream.ReadBytes(LightMap, LightMap.Length)
- '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.Edges = New TQEdge[num]
- Self.Header.Edges.JumpTo(Stream)
- For i = 0 Until num
- 'ListAddLast(Self.Edges, TQEdge.Read(Stream))
- Self.Edges[i] = TQEdge.Read(Stream)
- Next
- 'Read ledges
- num = Self.Header.Ledges.Count(TQLedge.Size())
- DebugLog "Ledges: " + num
- Self.Ledges = New TQLedge[num]
- Self.Header.Ledges.JumpTo(Stream)
- For i = 0 Until num
- 'ListAddLast(Self.Ledges, TQLedge.Read(Stream))
- Self.Ledges[i] = TQLedge.Read(Stream)
- Next
- 'Read models
- num = Self.Header.Models.Count(TQModel.Size())
- DebugLog "Models: " + num
- Self.Models = New TQModel[num]
- Self.Header.Models.JumpTo(Stream)
- For i = 0 Until num
- 'ListAddLast(Self.Models, TQModel.Read(Stream))
- Self.Models[i] = TQModel.Read(Stream)
- Next
- 'Read lightmaps from faces
- For i = 0 Until Self.Faces.Length
- Self.Faces[i].GetLightmap(Self)
- Next
- StartMS = MilliSecs()
- 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 = ReadInt(Stream)
- If nH.Version = "29" Then
- DebugLog "BSP version: " + nH.Version + " (correct)"
- Else
- DebugLog "BSP version: " + nH.Version + " (incorrect)"
- 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 = ReadInt(Stream)
- nM.Node_ID1 = ReadInt(Stream)
- nM.Node_ID2 = ReadInt(Stream)
- nM.Node_ID3 = ReadInt(Stream)
- nM.NumLeafs = ReadInt(Stream)
- nM.Face_ID = ReadInt(Stream)
- nM.Face_Num = ReadInt(Stream)
- Return nM
- EndFunction
- Function Size:Int()
- Return (B_INT * 7) + TQBoundBox.Size() + TQVec3.Size()
- EndFunction
- EndType
- Type TQVertex
- Field X:Float
- Field Y:Float
- Field Z:Float
- Function Read:TQVertex(Stream:TStream)
- Local nV:TQVertex = New TQVertex
- nV.X = ReadFloat(Stream)
- nV.Y = ReadFloat(Stream)
- nV.Z = ReadFloat(Stream)
- Return nV
- EndFunction
- Function Size:Int()
- Return B_FLOAT * 3
- 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 = ReadFloat(Stream)
- nS.VectorT = TQVec3.Read(Stream)
- nS.DistT = ReadFloat(Stream)
- nS.Texture_ID = ReadInt(Stream)
- nS.Animated = ReadInt(Stream)
- Return nS
- EndFunction
- Function Size:Int()
- Return (B_FLOAT * 2) + (B_INT * 2) + (TQVec3.Size() * 2)
- EndFunction
- EndType
- Type TQEdge
- Field Vertex0:Short
- Field Vertex1:Short
- Function Read:TQEdge(Stream:TStream)
- Local nE:TQEdge = New TQEdge
- nE.Vertex0 = ReadShort(Stream)
- nE.Vertex1 = ReadShort(Stream)
- Return nE
- EndFunction
- Function Size:Int()
- Return B_SHORT * 2
- EndFunction
- EndType
- Type TQLedge
- Field Edge:Int
- Function Read:TQLedge(Stream:TStream)
- Local nL:TQLedge = New TQLedge
- nL.Edge = ReadInt(Stream)
- Return nL
- EndFunction
- Function Size:Int()
- Return B_INT
- 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
- Field Surface:TSurface
- Field LightBrush:TBrush
- Field LightDist:TQIntVec2
- Field LightMinUV:TQVec2
- Field LightMaxUV:TQVec2
- Field LightS:Float
- Field LightT:Float
- Function Read:TQFace(Stream:TStream)
- Local nF:TQFace = New TQFace
- nF.Plane_ID = ReadShort(Stream)
- nF.Side = ReadShort(Stream)
- nF.Ledge_ID = ReadInt(Stream)
- nF.Ledge_Num = ReadShort(Stream)
- nF.TexInfo_ID = ReadShort(Stream)
- nF.TypeLight = ReadByte(Stream)
- nF.BaseLight = ReadByte(Stream)
- nF.Light[0] = ReadByte(Stream)
- nF.Light[1] = ReadByte(Stream)
- nF.LightMap = ReadInt(Stream)
- Return nF
- EndFunction
- Method GetLightmap(bsp:TQBSP)
- If Self.LightMap < 0 Then Return
- bsp.Stream.Seek(bsp.Header.LightMaps.Offset + Self.LightMap)
- Local plane:TQPlane = bsp.PLANES[Self.Plane_ID]
- 'Get the vertex data from all edges
- LightDist = New TQIntVec2
- LightMinUV = New TQVec2
- LightMaxUV = New TQVec2
- Local ledge:TQLedge
- Local edge:TQEdge
- Local vert:TQVertex
- Local texInfo:TQSurface = bsp.texInfo[Self.TexInfo_ID]
- For Local eNr:Int = Self.Ledge_ID Until Self.Ledge_ID + Self.Ledge_Num 'Go through edges
- ledge = bsp.Ledges[eNr] 'Get ledge
- edge = bsp.Edges[Abs(ledge.edge)] 'Get edge via ledge
- If ledge.edge < 0 Then
- vert = bsp.Vertices[edge.Vertex0]
- Else
- vert = bsp.Vertices[edge.Vertex1]
- EndIf
- LightS = DotProduct(vert.x, vert.y, vert.z, texInfo.VectorS.x, texInfo.VectorS.y, texInfo.VectorS.z) + texInfo.DistS
- LightT = DotProduct(vert.x, vert.y, vert.z, texInfo.VectorT.x, texInfo.VectorT.y, texInfo.VectorT.z) + texInfo.DistT
- If (eNr = Self.Ledge_ID) Then
- 'Starting point
- LightMinUV.x = LightS
- LightMinUV.y = LightT
- LightMaxUV.x = LightS
- LightMaxUV.y = LightT
- Else
- 'Is this a new minimum?
- If LightS < LightMinUV.x Then LightMinUV.x = LightS
- If LightT < LightMinUV.y Then LightMinUV.y = LightT
- 'Is this a new maximum
- If LightS > LightMaxUV.x Then LightMaxUV.x = LightS
- If LightT > LightMaxUV.y Then LightMaxUV.y = LightT
- End If
- Next
- 'Get distances
- LightDist.x = LightMaxUV.x - LightMinUV.x
- LightDist.y = LightMaxUV.y - LightMinUV.y
- Local pix:TPixmap = CreatePixmap(Ceil(LightDist.x / 16.0) + 1, Ceil(LightDist.y / 16.0) + 1, PF_RGB888)
- If pix.width <= 0 Or pix.Height <= 0 Then
- pix = Null
- Return
- EndIf
- 'Print pix.width + "/" + pix.Height
- Local x:Int
- Local y:Int
- Local color:Byte
- For y = 0 Until pix.Height
- For x = 0 Until pix.width
- color = bsp.Stream.ReadByte()' - Self.BaseLight
- pix.WritePixel(x, y, GenRGB(color,color,color))
- Next
- Next
- If FileType(AppDir + "/lightmaps") = FILETYPE_DIR Then SavePixmapPNG(pix, AppDir + "/lightmaps/" + Plane_ID + ".png", 0)
- Self.LightBrush = LoadBrushPixmap(pix, 16 + 32)
- EndMethod
- Function Size:Int()
- Return (B_SHORT * 4) + (B_INT * 2) + (B_BYTE * 4)
- EndFunction
- EndType
- Type TQMipHeader
- Field NumTex:Int
- Field Offset:Int[]
- Field _count:Int
- Function Read:TQMipHeader(Stream:TStream)
- Local nM:TQMipHeader = New TQMipHeader
- nM.NumTex = ReadInt(Stream)
- 'Should I even read this?
- nM.Offset = New Int[nM.NumTex]
- For Local i:Int = 0 Until nM.NumTex
- nM.Offset[i] = ReadInt(Stream)
- nM._count:+1
- Next
- Return nM
- EndFunction
- EndType
- Type TQMipTex
- Field Name:String
- Field width:Int
- Field Height:Int
- Field Offset1:Int
- Field Offset2:Int
- Field Offset4:Int
- Field Offset8:Int
- Field Texture:TTexture
- Field Brush:TBrush
- Function Read:TQMipTex(Stream:TStream)
- Local nM:TQMipTex = New TQMipTex
- For Local i:Int = 0 Until 16
- nM.Name:+Chr(ReadByte(Stream))
- Next
- nM.width = ReadInt(Stream)
- nM.Height = ReadInt(Stream)
- nM.Offset1 = ReadInt(Stream)
- nM.Offset2 = ReadInt(Stream)
- nM.Offset4 = ReadInt(Stream)
- nM.Offset8 = ReadInt(Stream)
- Return nM
- EndFunction
- Function Size:Int()
- Return (B_BYTE * 16) + (B_INT * 6)
- EndFunction
- EndType
- Type TQEntry
- Field Offset:Int
- Field Size:Int
- Function Read:TQEntry(Stream:TStream)
- Local nE:TQEntry = New TQEntry
- nE.Offset = ReadInt(Stream)
- nE.Size = ReadInt(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 = ReadInt(Stream)
- nN.Front = ReadShort(Stream)
- nN.Back = ReadShort(Stream)
- nN.Box = TQBBoxShort.Read(Stream)
- nN.Face_ID = ReadShort(Stream)
- nN.Face_Num = ReadShort(Stream)
- Return nN
- 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 = ReadInt(Stream)
- nD.VisList = ReadInt(Stream)
- nD.Bound = TQBBoxShort.Read(Stream)
- nD.LFace_ID = ReadShort(Stream)
- nD.LFace_Num = ReadShort(Stream)
- nD.SndWater = ReadByte(Stream)
- nD.SndSky = ReadByte(Stream)
- nD.SndSlime = ReadByte(Stream)
- nD.SndLava = ReadByte(Stream)
- Return nD
- 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 = ReadFloat(Stream)
- nP.Typ = ReadInt(Stream)
- Return nP
- EndFunction
- Function Size:Int()
- Return B_FLOAT + B_INT + 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 = ReadInt(Stream)
- nC.Front = ReadShort(Stream)
- nC.Back = ReadShort(Stream)
- Return nC
- EndFunction
- EndType
- Type TQPalette
- Global colors:TQColor32[]
- Function LoadPalette(url:String)
- Local Stream:TStream = OpenStream(url, True, False)
- If Not Stream Then Print("Unable to load palette ~q" + url + "~q")
- colors = New TQColor32[Stream.Size() / 3]
- For Local i:Int = 0 Until colors.Length
- colors[i] = New TQColor32
- colors[i].r = Stream.ReadByte()
- colors[i].g = Stream.ReadByte()
- colors[i].b = Stream.ReadByte()
- Next
- 'debug save palette
- Rem
- Local pix:TPixmap = CreatePixmap(colors.Length, 8, PF_RGB888)
- For Local i:Int = 0 Until colors.Length
- For Local y:Int = 0 Until pix.Height
- pix.WritePixel(i, y, GenRGB(colors[i].r, colors[i].g, colors[i].b))
- Next
- Next
- SavePixmapPNG(pix, AppDir + "/palette.png", 9)
- endrem
- CloseStream(Stream)
- DebugLog "Palette: " + url + " @ " + colors.Length + " colors"
- EndFunction
- EndType
- Type TQColor32
- Field r:Byte
- Field g:Byte
- Field b:Byte
- 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 = ReadFloat(Stream)
- nV.Y = ReadFloat(Stream)
- nV.Z = ReadFloat(Stream)
- Return nV
- EndFunction
- Function Size:Int()
- Return B_FLOAT * 3
- EndFunction
- EndType
- Type TQVec2
- Field X:Float
- Field Y:Float
- Function Read:TQVec2(Stream:TStream)
- Local nV:TQVec2 = New TQVec2
- nV.X = ReadFloat(Stream)
- nV.Y = ReadFloat(Stream)
- Return nV
- EndFunction
- Function Size:Int()
- Return B_FLOAT * 2
- EndFunction
- EndType
- Type TQIntVec2
- Field X:Float
- Field Y:Float
- Function Read:TQVec2(Stream:TStream)
- Local nV:TQVec2 = New TQVec2
- nV.X = ReadFloat(Stream)
- nV.Y = ReadFloat(Stream)
- Return nV
- EndFunction
- Function Size:Int()
- Return B_FLOAT * 2
- 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()
- Return TQVec3.Size() * 2
- EndFunction
- EndType
- Type TQBBoxShort
- Field Minimum:Short
- Field Maximum:Short
- Function Read:TQBBoxShort(Stream:TStream)
- Local nB:TQBBoxShort = New TQBBoxShort
- nB.Minimum = ReadShort(Stream)
- nB.Maximum = ReadShort(Stream)
- Return nB
- EndFunction
- Function Size:Int()
- Return B_SHORT * 2
- EndFunction
- EndType
- 'Common
- Function CrossProduct:TQVec3(x1:Float, y1:Float, z1:Float, x2:Float, y2:Float, z2:Float)
- Local CProd:TQVec3 = New TQVec3
- CProd.x = (y1 * z2) - (z1 * y2)
- CProd.y = (z1 * x2) - (x1 * z2)
- CProd.z = (x1 * y2) - (y1 * x2)
- Return CProd
- End Function
- Function DotProduct:Float(x1:Float, y1:Float, z1:Float, x2:Float, y2:Float, z2:Float)
- Return ((x1 * x2) + (y1 * y2) + (z1 * z2))
- EndFunction
- Function GenRGB:Int(r:Byte, g:Byte, b:Byte, a:Byte = 255)
- Return (a Shl 24) | (r Shl 16) | (g Shl 8) | b
- EndFunction
- Function GetRGB:Int(argb:Int, a:byte Var, r:byte Var, g:byte Var, b:byte Var)
- a=(argb Shr 24) & $ff
- r=(argb Shr 16) & $ff
- g=(argb Shr 8) & $ff
- b=argb & $ff
- EndFunction
- 'Custom brushes
- Function LoadBrushPixmap:TBrush(pixmapin:TPixmap, Flags:Int = 1, u_scale:Float = 1.0, v_scale:Float = 1.0)
- Return PixTBrush.LoadBrushPixmap(pixmapin, Flags, u_scale, v_scale)
- EndFunction
- Function LoadTexturePixmap:TTexture(pixmapin:TPixmap,flags:Int=1)
- Return PixTTexture.LoadTexturePixmap(pixmapin, Flags)
- EndFunction
- Type PixTBrush Extends TBrush
- Function LoadBrushPixmap:TBrush(pixmapin:TPixmap,flags:Int=1,u_scale:Float=1.0,v_scale:Float=1.0)
- Local brush:TBrush=New TBrush
- brush.tex[0]=PixTTexture.LoadTexturePixmap:TTexture(pixmapin,flags)
- brush.no_texs=1
- 'brush.tex[0].u_scale#=u_scale#
- 'brush.tex[0].v_scale#=v_scale#
- pixmapin = Null
- Return brush
- EndFunction
- EndType
- Type PixTTexture Extends TTexture
- Function LoadTexturePixMap:TTexture(pixmapin:TPixmap,flags:Int=1,tex:TTexture=Null)
- Return LoadAnimTexturePixMap:TTexture(pixmapin,flags,0,0,0,1,tex)
- End Function
- Function LoadAnimTexturePixMap:TTexture(pixmapin:TPixmap,flags:Int,frame_width:Int,frame_height:Int,first_frame:Int,frame_count:Int,tex:TTexture=Null)
- Local pixmapFileName:String="pixmap"+MilliSecs()+Rnd()
- If flags&128 Then Return LoadCubeMapTexture(pixmapFileName$,flags,tex)
- If tex=Null Then tex:TTexture=New TTexture
- tex.file:String=pixmapFileName
- tex.file_abs:String=pixmapFileName
- ' set tex.flags before TexInList
- tex.flags=flags
- tex.FilterFlags()
- ' check to see if texture with same properties exists already, if so return existing texture
- Local old_tex:TTexture
- old_tex=tex.TexInList()
- If old_tex<>Null And old_tex<>tex
- Return old_tex
- Else
- If old_tex<>tex
- ListAddLast(tex_list,tex)
- EndIf
- EndIf
- ' load pixmap
- tex.pixmap = CopyPixmap(pixmapin)
- ' check to see if pixmap contain alpha layer, set alpha_present to true if so (do this before converting)
- Local alpha_present:Int=False
- If tex.pixmap.format=PF_RGBA8888 Or tex.pixmap.format=PF_BGRA8888 Or tex.pixmap.format=PF_A8 Then alpha_present=True
- ' convert pixmap to appropriate format
- If tex.pixmap.format<>PF_RGBA8888
- tex.pixmap=tex.pixmap.Convert(PF_RGBA8888)
- EndIf
- ' if alpha flag is true and pixmap doesn't contain alpha info, apply alpha based on color values
- If tex.flags&2 And alpha_present=False
- tex.pixmap=ApplyAlpha(tex.pixmap)
- EndIf
- ' if mask flag is true, mask pixmap
- If tex.flags&4
- tex.pixmap=MaskPixmap(tex.pixmap,0,0,0)
- EndIf
- ' ---
- ' if tex not anim tex, get frame width and height
- If frame_width=0 And frame_height=0
- frame_width=tex.pixmap.width
- frame_height=tex.pixmap.height
- EndIf
- ' ---
- tex.no_frames=frame_count
- tex.gltex=tex.gltex[..tex.no_frames]
- ' ---
- ' pixmap -> tex
- Local xframes:Int=tex.pixmap.width/frame_width
- Local yframes:Int=tex.pixmap.height/frame_height
- Local startx:Int=first_frame Mod xframes
- Local starty:Int=(first_frame/yframes) Mod yframes
- Local x:Int=startx
- Local y:Int=starty
- Local pixmap:TPixmap
- For Local i:Int=0 To tex.no_frames-1
- ' get static pixmap window. when resize pixmap is called new pixmap will be returned.
- pixmap=tex.pixmap.Window(x*frame_width,y*frame_height,frame_width,frame_height)
- x=x+1
- If x>=xframes
- x=0
- y=y+1
- EndIf
- ' ---
- pixmap=AdjustPixmap(pixmap)
- tex.width=pixmap.width
- tex.height=pixmap.height
- Local width:Int=pixmap.width
- Local height:Int=pixmap.height
- Local name:Int
- glGenTextures 1,Varptr name
- glBindtexture GL_TEXTURE_2D,name
- Local mipmap:Int
- If tex.flags&8 Then mipmap=True
- Local mip_level:Int=0
- Repeat
- glPixelStorei GL_UNPACK_ROW_LENGTH,pixmap.pitch/BytesPerPixel[pixmap.format]
- glTexImage2D GL_TEXTURE_2D,mip_level,GL_RGBA8,width,height,0,GL_RGBA,GL_UNSIGNED_BYTE,pixmap.pixels
- If Not mipmap Then Exit
- If width=1 And height=1 Exit
- If width>1 width:/2
- If height>1 height:/2
- pixmap=ResizePixmap(pixmap,width,height)
- mip_level:+1
- Forever
- tex.no_mipmaps=mip_level
- tex.gltex[i]=name
- Next
- tex.pixmap = Null
- Return tex
- End Function
- EndType
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement