Advertisement
Guest User

Untitled

a guest
Oct 2nd, 2016
333
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
BlitzMax 38.19 KB | None | 0 0
  1. SuperStrict
  2. Framework sidesign.minib3d 'https://github.com/si-design/minib3d
  3. Import brl.Stream
  4. Import brl.linkedlist
  5. Import brl.standardio
  6. Import brl.bmploader
  7. Import brl.pngloader
  8.  
  9. 'Data sizes
  10. Const B_BYTE:Int = 1
  11. Const B_SHORT:Int = 2
  12. Const B_INT:Int = 4
  13. Const B_FLOAT:Int = 4
  14.  
  15. SetGraphicsDriver GLGraphicsDriver(),GRAPHICS_BACKBUFFER|GRAPHICS_DEPTHBUFFER
  16. Graphics3D(DesktopWidth() * 0.7, DesktopHeight() * 0.7, 0, 2)
  17. ClearTextureFilters()
  18.  
  19. Global camera:TCamera = CreateCamera()
  20. MoveEntity(camera, 0, 0, -10)
  21.  
  22. 'AmbientLight(255, 255, 255)
  23. 'Local light:TLight = CreateLight(1)
  24. 'RotateEntity(light, 45, 45, 0)
  25.  
  26. TQPalette.LoadPalette("palette.lmp")
  27. Global myBSP:TQBSP
  28. Global levelMesh:TMesh
  29. Global levelMeshAlpha:TMesh
  30.  
  31. 'Debug make a mesh
  32. Function GenerateBSPMesh(mesh:TMesh var, alphaMesh:TMesh var, myBSP:TQBSP)
  33.     If mesh Then FreeEntity(mesh)
  34.     If alphaMesh Then FreeEntity(alphaMesh)
  35.     'Local mesh:TMesh = CreateMesh()
  36.     'Local surf:TSurface[1024 * 10]
  37.    
  38.     GCCollect()
  39.    
  40.     mesh = CreateMesh()
  41.     alphaMesh = CreateMesh()
  42.    
  43.     Local face:TQFace
  44.     Local ledge:TQLedge
  45.     Local edge:TQEdge
  46.     Local plane:TQPlane
  47.     Local texInfo:TQSurface
  48.     Local mipTex:TQMipTex
  49.     Local vert:TQVertex
  50.     Local fNr:Int
  51.     Local eNr:Int
  52.     Local surf:TSurface
  53.     Local vertCount:Int
  54.     Local newVertCount:Int
  55.    
  56.     Local s:Float
  57.     Local t:Float
  58.     Local lightU:Float
  59.     Local lightV:Float
  60.    
  61.     For Local model:TQModel = EachIn myBSP.Models 'Go through models
  62.         For fNr = model.Face_ID Until model.Face_ID + model.Face_Num 'Go through faces
  63.             'Debug progress
  64.             'If fNr Mod 100 <= 0 Then Print "Generating: " + fNr + "/" + model.Face_Num
  65.             face = myBSP.Faces[fNr] 'Get current face
  66.             plane = myBSP.PLANES[face.Plane_ID]
  67.             texInfo = myBSP.texInfo[face.TexInfo_ID]
  68.             mipTex = myBSP.MipTexs[texInfo.Texture_ID]
  69.            
  70.             If mipTex.Name.StartsWith("trigger") Or mipTex.Name.StartsWith("sky") Then Continue
  71.            
  72.             If mipTex.Name.startswith("+") Then
  73.                 myBSP.AnimatedFaces = myBSP.AnimatedFaces[..myBSP.AnimatedFaces.Length + 1]
  74.                 myBSP.AnimatedFaces[myBSP.AnimatedFaces.Length - 1] = face
  75.             EndIf
  76.            
  77.            
  78.             'ERROR if we're using too many vertices
  79.             If mipTex.Surface And mipTex.Surface.CountVertices() > (10000 * 3) - 1 Then Print "TOO MANY VERTICES!!";End
  80.            
  81.             'If we don't have a surface to work with, create one
  82.             If Not mipTex.Surface Then
  83.                 If mipTex.Name.StartsWith("*") Then
  84.                     mipTex.Surface = CreateSurface(alphaMesh, Null)
  85.                 Else
  86.                     mipTex.Surface = CreateSurface(mesh, Null)
  87.                 EndIf
  88.             EndIf
  89.            
  90.             surf = mipTex.Surface
  91.            
  92.             'Get verts
  93.             newVertCount = 0
  94.             vertCount = surf.CountVertices()
  95.             For eNr = face.Ledge_ID Until face.Ledge_ID + face.Ledge_Num 'Go through edges
  96.                 ledge = myBSP.Ledges[eNr] 'Get ledge
  97.                 edge = myBSP.Edges[Abs(ledge.edge)] 'Get edge via ledge
  98.                
  99.                 If ledge.edge < 0 Then
  100.                     vert = myBSP.Vertices[edge.Vertex0]
  101.                 Else
  102.                     vert = myBSP.Vertices[edge.Vertex1]
  103.                 EndIf
  104.                
  105.                 AddVertex(surf, -vert.Y * 0.2, vert.Z * 0.2, vert.X * 0.2)
  106.                
  107.                 'Calculate UV
  108.                 s = DotProduct(vert.X, vert.Y, vert.Z, texInfo.VectorS.X, texInfo.VectorS.Y, texInfo.VectorS.Z) + texInfo.DistS
  109.                 t = DotProduct(vert.X, vert.Y, vert.Z, texInfo.VectorT.X, texInfo.VectorT.Y, texInfo.VectorT.Z) + texInfo.DistT
  110.                
  111.                 'Lightmap UV
  112.                 If face.LightMap >= 0 Then
  113.                     lightU = (s - face.LightMinUV.x) / Float(face.LightDist.x)
  114.                     lightV = (t - face.LightMinUV.y) / Float(face.LightDist.y)
  115.                    
  116.                     lightU = (face.LightMapPos.x + lightU * Float(face.LightMapSize.x)) / Float(myBSP.LightMapTexture.width)
  117.                     lightU = (face.LightMapPos.y + lightV * Float(face.LightMapSize.y)) / Float(myBSP.LightMapTexture.Height)
  118.                    
  119.                     VertexTexCoords(surf, vertCount, lightU, lightV, 0, 1)
  120.                 Else
  121.                     If Not mipTex.Name.StartsWith("*") Then VertexColor(surf, vertCount, 1, 1, 1)
  122.                 EndIf
  123.                
  124.                 'Texture UV
  125.                 s:/myBSP.MipTexs[texInfo.Texture_ID].width
  126.                 t:/myBSP.MipTexs[texInfo.Texture_ID].Height
  127.                
  128.                 VertexTexCoords(surf, vertCount, s, t, 0, 0) 'Real texture UV
  129.                 VertexNormal(surf, vertCount, plane.Normal.Z, plane.Normal.Y, plane.Normal.X)
  130.                
  131.                 vertCount:+1
  132.                 newVertCount:+1
  133.             Next
  134.            
  135.             'Make Tris
  136.             For Local i:Int = vertCount - newVertCount Until vertCount - 2
  137.                 AddTriangle(surf, vertCount - newVertCount, i + 1, i + 2)
  138.             Next
  139.            
  140.             If face.LightMap >= 0 Then
  141.                 Local tmpBrush:TBrush = CreateBrush()
  142.                 TextureCoords(myBSP.LightMapTexture, 1)
  143.                 TextureBlend(myBSP.LightMapTexture, 3)
  144.                
  145.                 BrushTexture(tmpBrush, myBSP.MipTexs[texInfo.Texture_ID].Texture, 0, 0)
  146.                 BrushTexture(tmpBrush, myBSP.LightMapTexture, 0, 1)
  147.                 PaintSurface(surf, tmpBrush)
  148.                 FreeBrush(tmpBrush)
  149.             Else
  150.                 PaintSurface(surf, myBSP.MipTexs[texInfo.Texture_ID].Brush)
  151.             EndIf
  152.         Next
  153.     Next
  154.    
  155.     EntityFX(mesh, 1)
  156.     EntityFX(alphaMesh, 1)
  157.    
  158.     EntityAlpha(alphaMesh, 0.9)
  159.     'EntityBlend(alphaMesh, 5)
  160.    
  161.     'Return mesh
  162.     GCCollect()
  163. EndFunction
  164.  
  165. 'Print mesh.CountSurfaces()
  166.  
  167. Function RequestBSP()
  168.     Local filter:String = "BSP Files:bsp;All Files:*"
  169.     Local file:String = RequestFile("Select BSP file to load", filter:String)
  170.    
  171.     If file Then
  172.         PositionEntity(camera, -2, 2.5, -10)
  173.         RotateEntity(camera, 0, 0, 0)
  174.        
  175.         If myBSP Then myBSP.Free()
  176.         myBSP = TQBSP.LoadFile(file)
  177.         GenerateBSPMesh(levelMesh, levelMeshAlpha, myBSP)
  178.     EndIf
  179.    
  180.     FlushKeys()
  181.     FlushMouse()
  182. EndFunction
  183.  
  184. If FileSize(AppDir + "/start.bsp") > 0 Then
  185.     myBSP = TQBSP.LoadFile(AppDir + "/start.bsp")
  186.     GenerateBSPMesh(levelMesh, levelMeshAlpha, myBSP)
  187.    
  188.     PositionEntity(camera, -50, 35, 80)
  189.     'RotateEntity(camera, 15, 180 + 25, 0)
  190.     RotateEntity(camera, 0, 90, 0)
  191. Else
  192.     RequestBSP()
  193. EndIf
  194.  
  195. 'Main loop
  196. While Not AppTerminate() And Not KeyDown(KEY_ESCAPE)
  197.     'Cls()
  198.     'If KeyHit(KEY_O) Then Wireframe(False)
  199.     If KeyDown(KEY_P) Then Wireframe(True)
  200.    
  201.     If KeyHit(KEY_O) Then GCCollect()
  202.    
  203.     If KeyDown(KEY_LEFT) Then TurnEntity(camera, 0, 2, 0)
  204.     If KeyDown(KEY_RIGHT) Then TurnEntity(camera, 0, -2, 0)
  205.     If KeyDown(KEY_UP) Then TurnEntity(camera, -2, 0, 0)
  206.     If KeyDown(KEY_DOWN) Then TurnEntity(camera, 2, 0, 0)
  207.    
  208.     If KeyDown(KEY_W) Then MoveEntity(camera, 0, 0, 1.5)
  209.     If KeyDown(KEY_S) Then MoveEntity(camera, 0, 0, -1.5)
  210.     If KeyDown(KEY_A) Then MoveEntity(camera, -1.5, 0, 0)
  211.     If KeyDown(KEY_D) Then MoveEntity(camera, 1.5, 0, 0)
  212.    
  213.     If KeyDown(KEY_SPACE) Then MoveEntity(camera, 0, 1, 0)
  214.     If KeyDown(KEY_LCONTROL) Then MoveEntity(camera, 0, -1, 0)
  215.    
  216.     If KeyHit(KEY_TAB) Then RequestBSP()
  217.    
  218.     If myBSP Then myBSP.Update()
  219.    
  220.     If Not KeyDown(KEY_I) Then myBSP.PositionSkyBox(EntityX(camera), EntityY(camera), EntityZ(camera), EntityPitch(camera), EntityYaw(camera))
  221.    
  222.     RenderWorld()
  223.    
  224.     BeginMax2D()
  225.     DrawText("TAB: Open BSP", 0, 0)
  226.     EndMax2D()
  227.    
  228.     Flip(1)
  229. Wend
  230. End
  231.  
  232. Type TQBSP
  233.     Field File:String
  234.     Field Stream:TStream
  235.    
  236.     Field Header:TQHeader
  237.    
  238.     Field PLANES:TQPlane[]
  239.     Field Vertices:TQVertex[]
  240.     Field Nodes:TList = CreateList()
  241.     Field TexInfo:TQSurface[]
  242.     Field MipTexHeader:TQMipHeader
  243.     Field MipTexs:TQMipTex[]
  244.     Field LiquidMipTexs:TQMipTex[]
  245.     Field AnimatedMipTexs:TQMipTex[]
  246.     Field AnimatedFaces:TQFace[]
  247.     Field Faces:TQFace[]
  248.     Field ClipNodes:TList = CreateList()
  249.     Field Leaves:TList = CreateList()
  250.     Field Edges:TQEdge[]
  251.     Field Ledges:TQLedge[]
  252.     Field Models:TQModel[]
  253.    
  254.     Field LightMapTexture:TTexture
  255.     Field LightMapPixmap:TPixmap
  256.     Field LightMapPreW:Int
  257.     Field LightMapPreH:Int
  258.     Field LightMapMaxH:Int
  259.    
  260.     Field SkyTexture:TTexture[2]
  261.     Field SkyBox:TMesh[2]
  262.    
  263.     Field AnimTime:Int
  264.     Field StartMS:Int
  265.    
  266.     Function LoadFile:TQBSP(url:String)
  267.         Local nB:TQBSP = New TQBSP
  268.         nB.File = url
  269.        
  270.         If nB.Process() Then
  271.             Return nB
  272.         Else
  273.             nB.StreamError("Map ~q" + nB.file + "~q NOT loaded")
  274.             Return Null
  275.         EndIf
  276.     EndFunction
  277.    
  278.     Method Free()
  279.         If SkyBox[0] Then FreeEntity(SkyBox[0])
  280.         If SkyBox[1] Then FreeEntity(SkyBox[1])
  281.     EndMethod
  282.    
  283.     Method PositionSkyBox(x:Float, y:Float, z:Float, Pitch:Float, Yaw:Float)
  284.         If Not SkyBox[0] Or Not SkyBox[1] Then Return
  285.        
  286.         PositionEntity(SkyBox[0], x, y, z)
  287.         PositionEntity(SkyBox[1], x, y, z)
  288.        
  289.         'RotateEntity(SkyBox[0], (Pitch - 90) / 2.0, 0, 0)
  290.         'RotateEntity(SkyBox[1], (Pitch - 90) / 2.0, 0, 0)
  291.        
  292.         'RotateTexture(Self.SkyTexture[0], Yaw)
  293.         'RotateTexture(Self.SkyTexture[1], Yaw)
  294.     EndMethod
  295.    
  296.     Method Update()
  297.         PositionTexture(Self.SkyTexture[0], -(MilliSecs() - StartMS) * 0.00005, -(MilliSecs() - StartMS) * 0.00005)
  298.         PositionTexture(Self.SkyTexture[1], -(MilliSecs() - StartMS) * 0.00005 * 2.5, -(MilliSecs() - StartMS) * 0.00005 * 2.5)
  299.        
  300.         For Local m:TQMipTex = EachIn Self.LiquidMipTexs
  301.             PositionTexture(GetBrushTexture(m.Brush), -(MilliSecs() - StartMS) * 0.000075, -(MilliSecs() - StartMS) * 0.0001)
  302.             'RotateTexture(GetBrushTexture(m.Brush), (MilliSecs() - StartMS) * 0.00075)
  303.         Next
  304.        
  305.         Local texInfo:TQSurface
  306.         Local mipTex:TQMipTex
  307.         Local newMipTex:TQMipTex
  308.         Local newMipTexName:String
  309.         While Self.AnimTime < (MilliSecs() - Self.StartMS) / 200
  310.             Self.AnimTime:+1
  311.            
  312.             For Local m:TQMipTex = EachIn Self.AnimatedMipTexs
  313.                 m.AnimStep:+1
  314.             Next
  315.            
  316.             For Local f:TQFace = EachIn Self.AnimatedFaces
  317.                 texInfo = myBSP.texInfo[f.TexInfo_ID]
  318.                 mipTex = myBSP.MipTexs[texInfo.Texture_ID]
  319.                 newMipTexName = "+" + (Int(Mid(mipTex.Name, 2, 1)) + mipTex.AnimStep)
  320.                 newMipTexName:+Right(mipTex.Name, Len(mipTex.Name) - 2)
  321.                
  322.                 'Find new image
  323.                 newMipTex = Null
  324.                 For Local nM:TQMipTex = EachIn Self.AnimatedMipTexs
  325.                     If nM.Name = newMipTexName Then
  326.                         newMipTex = nM
  327.                         'mipTex.AnimStep:+1
  328.                         Exit
  329.                     EndIf
  330.                 Next
  331.                 If Not newMipTex Then
  332.                     mipTex.AnimStep = 0
  333.                     newMipTex = mipTex
  334.                 EndIf
  335.                
  336.                 'Apply new image
  337.                 If f.LightMap >= 0 Then
  338.                     Local tmpBrush:TBrush = CreateBrush()
  339.                     TextureCoords(LightMapTexture, 1)
  340.                     TextureBlend(LightMapTexture, 3)
  341.                    
  342.                     BrushTexture(tmpBrush, newMipTex.Texture, 0, 0)
  343.                     BrushTexture(tmpBrush, LightMapTexture, 0, 1)
  344.                     PaintSurface(mipTex.Surface, tmpBrush)
  345.                     FreeBrush(tmpBrush)
  346.                 Else
  347.                     PaintSurface(mipTex.Surface, newMipTex.Brush)
  348.                 EndIf
  349.             Next
  350.         Wend
  351.     EndMethod
  352.    
  353.     Method StreamError(MSG:String)
  354.         If Stream Then CloseStream(Stream)
  355.         DebugLog "Read error: " + MSG
  356.     EndMethod
  357.    
  358.     Method Process:Int()
  359.         Stream = OpenStream(File)
  360.         If Not Stream Then
  361.             StreamError("Unable to read file ~q" + file + "~q")
  362.             Return False
  363.         EndIf
  364.        
  365.         Local num:Int 'For counting stuff
  366.         Local i:Int 'For loops
  367.        
  368.         'Make skybox
  369.         If Not SkyBox[0] Then
  370.             SkyBox[0] = CreateMesh()
  371.             Local surf:TSurface = CreateSurface(skybox[0])
  372.            
  373.             surf.AddVertex(-1.0, -1.0, 1.0)
  374.             surf.AddVertex(-1.0, 1.0, 1.0)
  375.             surf.AddVertex( 1.0, 1.0, 1.0)
  376.             surf.AddVertex( 1.0,-1.0, 1.0)
  377.            
  378.             surf.VertexTexCoords(0, 0.0, 1.0)
  379.             surf.VertexTexCoords(1, 0.0, 0.0)
  380.             surf.VertexTexCoords(2, 1.0, 0.0)
  381.             surf.VertexTexCoords(3, 1.0, 1.0)
  382.            
  383.             surf.AddTriangle(0, 1, 2)
  384.             surf.AddTriangle(0, 2, 3)
  385.            
  386.             SkyBox[1] = CopyMesh(SkyBox[0])
  387.            
  388.             For i = 0 Until SkyBox.Length
  389.                 'FlipMesh(SkyBox[i])
  390.                 ScaleMesh(SkyBox[i], 100, 100, 2)
  391.                 RotateMesh(SkyBox[i], -90, 180, 90)
  392.                 'PositionMesh(SkyBox[i], 0, 0, 2)
  393.                 EntityFX(SkyBox[i], 1)
  394.                 EntityOrder(SkyBox[i], 10000 - i)
  395.                 'ScaleEntity(SkyBox[i], 2, 2, 2)
  396.             Next
  397.         EndIf
  398.        
  399.         'Read header
  400.         Self.Header = TQHeader.Read(Stream)
  401.        
  402.         'Read planes
  403.         num = Self.Header.PLANES.Count(TQPlane.Size())
  404.         DebugLog "Planes: " + num
  405.         Self.PLANES = New TQPlane[num]
  406.         Self.Header.PLANES.JumpTo(Stream)
  407.         For i = 0 Until num
  408.             'ListAddLast(Self.PLANES, TQPlane.Read(Stream))
  409.             Self.PLANES[i] = TQPlane.Read(Stream)
  410.         Next
  411.        
  412.         'Read vertices
  413.         num = Self.Header.Vertices.Count(TQVertex.Size())
  414.         DebugLog "Vertices: " + num
  415.         Self.Vertices = New TQVertex[num]
  416.         Self.Header.Vertices.JumpTo(Stream)
  417.         For i = 0 Until num
  418.             'ListAddLast(Self.Vertices, TQVertex.Read(Stream))
  419.             Self.Vertices[i] = TQVertex.Read(Stream)
  420.         Next
  421.        
  422.         'Read nodes
  423.         'num = Self.Header.Nodes.Count(TQNode.Size())
  424.         'DebugLog "Nodes: " + num
  425.         'Self.Header.Nodes.JumpTo(Stream)
  426.         'For i = 0 Until num
  427.         '   ListAddLast(Self.Nodes, TQNode.Read(Stream))
  428.         'Next
  429.        
  430.         'Read texture info
  431.         num = Self.Header.TexInfo.Count(TQSurface.Size())
  432.         DebugLog "TexInfo: " + num
  433.         Self.TexInfo = New TQSurface[num]
  434.         Self.Header.TexInfo.JumpTo(Stream)
  435.         For i = 0 Until num
  436.             Self.TexInfo[i] = TQSurface.Read(Stream)
  437.         Next
  438.        
  439.         'Read mipmap header
  440.         Self.Header.MipTex.JumpTo(Stream)
  441.         Self.MipTexHeader = TQMipHeader.Read(Stream)
  442.         num = Self.MipTexHeader._count
  443.         DebugLog "MipMap Texs: " + num
  444.        
  445.         'Read miptexs from mipmap header
  446.         'CreateDir(AppDir + "/tex/", True) 'Debug for exporting
  447.        
  448.         MipTexs = New TQMipTex[num]
  449.         For i = 0 Until num
  450.             Stream.Seek(Self.Header.MipTex.Offset + Self.MipTexHeader.Offset[i])
  451.             Self.MipTexs[i] = TQMipTex.Read(Stream)
  452.            
  453.             If Self.MipTexs[i].width > 1 And Self.MipTexs[i].Height > 1 Then
  454.                 Local pix:TPixmap
  455.                 Local x:Int
  456.                 Local y:Int
  457.                 Local colorID:Byte
  458.                 Local palColor:TQColor32
  459.                
  460.                 Stream.Seek(Self.Header.MipTex.Offset + Self.MipTexHeader.Offset[i] + Self.MipTexs[i].Offset1)
  461.                 If Not Self.MipTexs[i].Name.StartsWith("sky") Then
  462.                     pix = CreatePixmap(Self.MipTexs[i].width, Self.MipTexs[i].Height, PF_RGB888)
  463.                    
  464.                     For Local bI:Int = 0 Until pix.width * pix.Height
  465.                         colorID = ReadByte(Stream)
  466.                         palColor = TQPalette.colors[colorID]
  467.                        
  468.                         pix.WritePixel(x, y, GenRGB(palColor.r, palColor.g, palColor.b))
  469.                        
  470.                         x:+1
  471.                         If x >= pix.width Then
  472.                             x = 0
  473.                             y:+1
  474.                         EndIf
  475.                     Next
  476.                    
  477.                     If pix Then
  478.                         'Print Self.MipTexs[i].Name
  479.                        
  480.                         Self.MipTexs[i].Brush = LoadBrushPixmap(pix, 0)
  481.                         Self.MipTexs[i].Texture = LoadTexturePixmap(pix, 0)
  482.                        
  483.                         'Liquids
  484.                         If Self.MipTexs[i].Name.StartsWith("*") Then
  485.                             LiquidMipTexs = LiquidMipTexs[..LiquidMipTexs.Length + 1]
  486.                             LiquidMipTexs[LiquidMipTexs.Length - 1] = Self.MipTexs[i]
  487.                         EndIf
  488.                        
  489.                         'Animated
  490.                         If Self.MipTexs[i].Name.StartsWith("+") Then
  491.                             AnimatedMipTexs = AnimatedMipTexs[..AnimatedMipTexs.Length + 1]
  492.                             AnimatedMipTexs[AnimatedMipTexs.Length - 1] = Self.MipTexs[i]
  493.                         EndIf
  494.                        
  495.                         pix = Null
  496.                     EndIf
  497.                 Else
  498.                     pix = CreatePixmap(Self.MipTexs[i].width / 2, Self.MipTexs[i].Height, PF_RGBA8888)
  499.                     Local pix2:TPixmap = CreatePixmap(Self.MipTexs[i].width / 2, Self.MipTexs[i].Height, PF_RGB888)
  500.                     Local blackness:Float
  501.                    
  502.                     For Local bI:Int = 0 Until Self.MipTexs[i].width * Self.MipTexs[i].Height
  503.                         colorID = ReadByte(Stream)
  504.                         palColor = TQPalette.colors[colorID]
  505.                        
  506.                         blackness = (palColor.r + palColor.g + palColor.b) / 2.0
  507.                         blackness:*2.5
  508.                         If blackness > 255 Then blackness = 255
  509.                        
  510.                         If x < pix.width Then
  511.                             pix.WritePixel(x, y, GenRGB(palColor.r, palColor.g, palColor.b, blackness))
  512.                         Else
  513.                             pix2.WritePixel(x - pix.width, y, GenRGB(palColor.r, palColor.g, palColor.b))
  514.                         EndIf
  515.                        
  516.                         x:+1
  517.                         If x >= Self.MipTexs[i].width Then
  518.                             x = 0
  519.                             y:+1
  520.                         EndIf
  521.                     Next
  522.                    
  523.                     Self.SkyTexture[0] = LoadTexturePixmap(pix2, 8)
  524.                     Self.SkyTexture[1] = LoadTexturePixmap(pix, 2 + 8)
  525.                    
  526.                     'TextureBlend(Self.SkyTexture[0], 5)
  527.                     'TextureBlend(Self.SkyTexture[1], 2)
  528.                    
  529.                     ScaleTexture(Self.SkyTexture[0], 0.0065, 0.0065)
  530.                     ScaleTexture(Self.SkyTexture[1], 0.0065, 0.0065)
  531.                    
  532.                     EntityTexture(Self.SkyBox[0], Self.SkyTexture[0], 0, 0)
  533.                     EntityTexture(Self.SkyBox[1], Self.SkyTexture[1], 0, 0)
  534.                    
  535.                     'SavePixmapPNG(pix, "sky1.png")
  536.                     'SavePixmapPNG(pix2, "sky2.png")
  537.                     pix = Null
  538.                     pix2 = Null
  539.                 EndIf
  540.             EndIf
  541.         Next
  542.        
  543.         'Read faces
  544.         num = Self.Header.Faces.Count(TQFace.Size())
  545.         DebugLog "Faces: " + num
  546.         Self.Faces = New TQFace[num]
  547.         Self.Header.Faces.JumpTo(Stream)
  548.         For i = 0 Until num
  549.             Self.Faces[i] = TQFace.Read(Stream)
  550.         Next
  551.        
  552.         'Read lightmaps
  553.         'Self.Header.LightMaps.JumpTo(Stream)
  554.         'LightMap = New Byte[Self.Header.LightMaps.Size]
  555.         'For i:Int = 0 Until LightMap.Length
  556.         '   LightMap[i] = ReadByte(Stream)
  557.         'Next
  558.         'Stream.ReadBytes(LightMap, LightMap.Length)
  559.        
  560.         'Read clipnodes
  561.         'num = Self.Header.ClipNodes.Count(TQClipNode.Size())
  562.         'DebugLog "ClipNodes: " + num
  563.         'Self.Header.ClipNodes.JumpTo(Stream)
  564.         'For i = 0 Until num
  565.         '   ListAddLast(Self.ClipNodes, TQClipNode.Read(Stream))
  566.         'Next
  567.        
  568.         'Read leaves
  569.         'num = Self.Header.Leaves.Count(TQDLeaf.Size())
  570.         'DebugLog "Leaves: " + num
  571.         'Self.Header.Leaves.JumpTo(Stream)
  572.         'For i = 0 Until num
  573.         '   ListAddLast(Self.Leaves, TQDLeaf.Read(Stream))
  574.         'Next
  575.        
  576.         'Read edges
  577.         num = Self.Header.Edges.Count(TQEdge.Size())
  578.         DebugLog "Edges: " + num
  579.         Self.Edges = New TQEdge[num]
  580.         Self.Header.Edges.JumpTo(Stream)
  581.         For i = 0 Until num
  582.             'ListAddLast(Self.Edges, TQEdge.Read(Stream))
  583.             Self.Edges[i] = TQEdge.Read(Stream)
  584.         Next
  585.        
  586.         'Read ledges
  587.         num = Self.Header.Ledges.Count(TQLedge.Size())
  588.         DebugLog "Ledges: " + num
  589.         Self.Ledges = New TQLedge[num]
  590.         Self.Header.Ledges.JumpTo(Stream)
  591.         For i = 0 Until num
  592.             'ListAddLast(Self.Ledges, TQLedge.Read(Stream))
  593.             Self.Ledges[i] = TQLedge.Read(Stream)
  594.         Next
  595.        
  596.         'Read models
  597.         num = Self.Header.Models.Count(TQModel.Size())
  598.         DebugLog "Models: " + num
  599.         Self.Models = New TQModel[num]
  600.         Self.Header.Models.JumpTo(Stream)
  601.         For i = 0 Until num
  602.             'ListAddLast(Self.Models, TQModel.Read(Stream))
  603.             Self.Models[i] = TQModel.Read(Stream)
  604.         Next
  605.        
  606.         'Read lightmaps from faces
  607.         For i = 0 Until Self.Faces.Length 'Calculate all lightmap part sizes and store them
  608.             Self.Faces[i].CalcLightmapSize(Self)
  609.         Next
  610.        
  611.         'Create a global lightmap image
  612.         Self.LightMapPreH = TQFace.LIGHT_PAD
  613.         Self.LightMapPreW = TQFace.LIGHT_PAD
  614.         Local pixSize:Int = Pow2Size(Sqr(Self.Header.LightMaps.Size) * 1.75)
  615.         LightMapPixmap = CreatePixmap(pixSize, pixSize, PF_RGB888)
  616.         For i = 0 Until Self.Faces.Length 'Store lightmap parts in big picture
  617.             Self.Faces[i].MakeLightmap(Self)
  618.         Next
  619.         LightMapTexture = LoadTexturePixmap(LightMapPixmap, 0)
  620.         'Debug save
  621.         'If LightMapPixmap Then SavePixmapPNG(LightMapPixmap, "lightmap.png", 0)
  622.         'End
  623.        
  624.         StartMS = MilliSecs()
  625.        
  626.         CloseStream(Stream)
  627.         Return True
  628.     EndMethod
  629. EndType
  630.  
  631. 'http://www.gamers.org/dEngine/quake/spec/quake-spec34/qkspec_4.htm
  632. 'char 8bit = negative byte
  633. 'u_char 8bit = byte
  634. 'short 16bit = negative short
  635. 'u_short 16bit = short
  636. 'long 32bit = int
  637. 'u_long 32bit = longer int
  638. 'float 32bit = float
  639. 'scalar_t 32bit = float
  640.  
  641. Type TQHeader
  642.     Field Version:Int
  643.     Field Entities:TQEntry
  644.     Field PLANES:TQEntry
  645.     Field MipTex:TQEntry
  646.     Field Vertices:TQEntry
  647.     Field VisiList:TQEntry
  648.     Field Nodes:TQEntry
  649.     Field TexInfo:TQEntry
  650.     Field Faces:TQEntry
  651.     Field LightMaps:TQEntry
  652.     Field ClipNodes:TQEntry
  653.     Field Leaves:TQEntry
  654.     Field LFace:TQEntry
  655.     Field Edges:TQEntry
  656.     Field Ledges:TQEntry
  657.     Field Models:TQEntry
  658.    
  659.     Function Read:TQHeader(Stream:TStream)
  660.         Local nH:TQHeader = New TQHeader
  661.        
  662.         nH.Version = ReadInt(Stream)
  663.         If nH.Version = "29" Then
  664.             DebugLog "BSP version: " + nH.Version + " (correct)"
  665.         Else
  666.             DebugLog "BSP version: " + nH.Version + " (incorrect)"
  667.         EndIf
  668.        
  669.         nH.Entities = TQEntry.Read(Stream)
  670.         nH.PLANES = TQEntry.Read(Stream)
  671.        
  672.         nH.MipTex = TQEntry.Read(Stream)
  673.         nH.Vertices = TQEntry.Read(Stream)
  674.        
  675.         nH.VisiList = TQEntry.Read(Stream)
  676.         nH.Nodes = TQEntry.Read(Stream)
  677.        
  678.         nH.TexInfo = TQEntry.Read(Stream)
  679.        
  680.         nH.Faces = TQEntry.Read(Stream)
  681.        
  682.         nH.LightMaps = TQEntry.Read(Stream)
  683.         DebugLog "Lightmap Size: " + nH.LightMaps.Size
  684.         nH.ClipNodes = TQEntry.Read(Stream)
  685.        
  686.         nH.Leaves = TQEntry.Read(Stream)
  687.        
  688.         nH.LFace = TQEntry.Read(Stream)
  689.         nH.Edges = TQEntry.Read(Stream)
  690.        
  691.         nH.Ledges = TQEntry.Read(Stream)
  692.         nH.Models = TQEntry.Read(Stream)
  693.        
  694.         Return nH
  695.     EndFunction
  696. EndType
  697.  
  698. Type TQModel
  699.     Field Bound:TQBoundBox
  700.     Field Origin:TQVec3
  701.     Field Node_ID0:Int
  702.     Field Node_ID1:Int
  703.     Field Node_ID2:Int
  704.     Field Node_ID3:Int
  705.     Field NumLeafs:Int
  706.     Field Face_ID:Int
  707.     Field Face_Num:Int
  708.    
  709.     Function Read:TQModel(Stream:TStream)
  710.         Local nM:TQModel = New TQModel
  711.         nM.Bound = TQBoundBox.Read(Stream)
  712.         nM.Origin = TQVec3.Read(Stream)
  713.         nM.Node_ID0 = ReadInt(Stream)
  714.         nM.Node_ID1 = ReadInt(Stream)
  715.         nM.Node_ID2 = ReadInt(Stream)
  716.         nM.Node_ID3 = ReadInt(Stream)
  717.         nM.NumLeafs = ReadInt(Stream)
  718.         nM.Face_ID = ReadInt(Stream)
  719.         nM.Face_Num = ReadInt(Stream)
  720.         Return nM
  721.     EndFunction
  722.    
  723.     Function Size:Int()
  724.         Return (B_INT * 7) + TQBoundBox.Size() + TQVec3.Size()
  725.     EndFunction
  726. EndType
  727.  
  728. Type TQVertex
  729.     Field X:Float
  730.     Field Y:Float
  731.     Field Z:Float
  732.    
  733.     Function Read:TQVertex(Stream:TStream)
  734.         Local nV:TQVertex = New TQVertex
  735.         nV.X = ReadFloat(Stream)
  736.         nV.Y = ReadFloat(Stream)
  737.         nV.Z = ReadFloat(Stream)
  738.        
  739.         Return nV
  740.     EndFunction
  741.    
  742.     Function Size:Int()
  743.         Return B_FLOAT * 3
  744.     EndFunction
  745. EndType
  746.  
  747. Type TQSurface
  748.     Field VectorS:TQVec3
  749.     Field DistS:Float
  750.     Field VectorT:TQVec3
  751.     Field DistT:Float
  752.     Field Texture_ID:Int
  753.    
  754.     Field Animated:Int
  755.    
  756.     Function Read:TQSurface(Stream:TStream)
  757.         Local nS:TQSurface = New TQSurface
  758.         nS.VectorS = TQVec3.Read(Stream)
  759.         nS.DistS = ReadFloat(Stream)
  760.         nS.VectorT = TQVec3.Read(Stream)
  761.         nS.DistT = ReadFloat(Stream)
  762.         nS.Texture_ID = ReadInt(Stream)
  763.         nS.Animated = ReadInt(Stream)
  764.         Return nS
  765.     EndFunction
  766.    
  767.     Function Size:Int()
  768.         Return (B_FLOAT * 2) + (B_INT * 2) + (TQVec3.Size() * 2)
  769.     EndFunction
  770. EndType
  771.  
  772. Type TQEdge
  773.     Field Vertex0:Short
  774.     Field Vertex1:Short
  775.    
  776.     Function Read:TQEdge(Stream:TStream)
  777.         Local nE:TQEdge = New TQEdge
  778.         nE.Vertex0 = ReadShort(Stream)
  779.         nE.Vertex1 = ReadShort(Stream)
  780.         Return nE
  781.     EndFunction
  782.    
  783.     Function Size:Int()
  784.         Return B_SHORT * 2
  785.     EndFunction
  786. EndType
  787.  
  788. Type TQLedge
  789.     Field Edge:Int
  790.    
  791.     Function Read:TQLedge(Stream:TStream)
  792.         Local nL:TQLedge = New TQLedge
  793.         nL.Edge = ReadInt(Stream)
  794.         Return nL
  795.     EndFunction
  796.    
  797.     Function Size:Int()
  798.         Return B_INT
  799.     EndFunction
  800. EndType
  801.  
  802. Type TQFace
  803.     Const LIGHT_PAD:Int = 1
  804.    
  805.     Field Plane_ID:Short
  806.    
  807.     Field Side:Short
  808.     Field Ledge_ID:Int
  809.    
  810.     Field Ledge_Num:Short
  811.     Field TexInfo_ID:Short
  812.    
  813.     Field TypeLight:Byte
  814.     Field BaseLight:Byte
  815.     Field Light:Byte[2]
  816.     Field LightMap:Int
  817.    
  818.     Field LightBrush:TBrush
  819.     Field LightDist:TQIntVec2
  820.     Field LightMinUV:TQVec2
  821.     Field LightMaxUV:TQVec2
  822.     Field LightS:Float
  823.     Field LightT:Float
  824.     Field LightMapSize:TQIntVec2
  825.     Field LightMapPos:TQVec2
  826.    
  827.     Function Read:TQFace(Stream:TStream)
  828.         Local nF:TQFace = New TQFace
  829.         nF.Plane_ID = ReadShort(Stream)
  830.         nF.Side = ReadShort(Stream)
  831.         nF.Ledge_ID = ReadInt(Stream)
  832.         nF.Ledge_Num = ReadShort(Stream)
  833.         nF.TexInfo_ID = ReadShort(Stream)
  834.         nF.TypeLight = ReadByte(Stream)
  835.         nF.BaseLight = ReadByte(Stream)
  836.         nF.Light[0] = ReadByte(Stream)
  837.         nF.Light[1] = ReadByte(Stream)
  838.         nF.LightMap = ReadInt(Stream)
  839.         Return nF
  840.     EndFunction
  841.    
  842.     Method GetLightmapSize:TQIntVec2(bsp:TQBSP)
  843.         If LightMapSize Then
  844.             Return LightMapSize
  845.         Else
  846.             Return CalcLightmapSize(bsp)
  847.         EndIf
  848.     EndMethod
  849.    
  850.     Method CalcLightmapSize:TQIntVec2(bsp:TQBSP)
  851.         If Self.LightMap < 0 Then Return New TQIntVec2
  852.        
  853.         If LightMapSize Then
  854.             Return LightMapSize
  855.         Else
  856.             LightMapSize = New TQIntVec2
  857.         EndIf
  858.        
  859.         'Get the vertex data from all edges
  860.         LightDist = New TQIntVec2
  861.         LightMinUV = New TQVec2
  862.         LightMaxUV = New TQVec2
  863.        
  864.         Local ledge:TQLedge
  865.         Local edge:TQEdge
  866.         Local vert:TQVertex
  867.         Local texInfo:TQSurface = bsp.texInfo[Self.TexInfo_ID]
  868.         For Local eNr:Int = Self.Ledge_ID Until Self.Ledge_ID + Self.Ledge_Num 'Go through edges
  869.             ledge = bsp.Ledges[eNr] 'Get ledge
  870.             edge = bsp.Edges[Abs(ledge.edge)] 'Get edge via ledge
  871.            
  872.             If ledge.edge < 0 Then
  873.                 vert = bsp.Vertices[edge.Vertex0]
  874.             Else
  875.                 vert = bsp.Vertices[edge.Vertex1]
  876.             EndIf
  877.            
  878.             LightS = DotProduct(vert.x, vert.y, vert.z, texInfo.VectorS.x, texInfo.VectorS.y, texInfo.VectorS.z) + texInfo.DistS
  879.             LightT = DotProduct(vert.x, vert.y, vert.z, texInfo.VectorT.x, texInfo.VectorT.y, texInfo.VectorT.z) + texInfo.DistT
  880.            
  881.             If (eNr = Self.Ledge_ID) Then
  882.                 'Starting point
  883.                 LightMinUV.x = LightS
  884.                 LightMinUV.y = LightT
  885.                 LightMaxUV.x = LightS
  886.                 LightMaxUV.y = LightT
  887.             Else
  888.                 'Is this a new minimum?
  889.                 If LightS < LightMinUV.x Then LightMinUV.x = LightS
  890.                 If LightT < LightMinUV.y Then LightMinUV.y = LightT
  891.                
  892.                 'Is this a new maximum
  893.                 If LightS > LightMaxUV.x Then LightMaxUV.x = LightS
  894.                 If LightT > LightMaxUV.y Then LightMaxUV.y = LightT
  895.             End If
  896.         Next
  897.        
  898.         'Get distances
  899.         LightDist.x = Ceil(LightMaxUV.x / 16) - Floor(LightMinUV.x / 16)
  900.         LightDist.y = Ceil(LightMaxUV.y / 16) - Floor(LightMinUV.y / 16)
  901.        
  902.         LightMapSize.x = LightDist.x + 1
  903.         LightMapSize.y = LightDist.y + 1
  904.        
  905.         LightDist.x:*16
  906.         LightDist.y:*16
  907.        
  908.         Return LightMapSize
  909.     EndMethod
  910.    
  911.     Method MakeLightmap(bsp:TQBSP)
  912.         If Self.LightMap < 0 Then Return
  913.        
  914.         bsp.Stream.Seek(bsp.Header.LightMaps.Offset + Self.LightMap)
  915.        
  916.         'Local pix:TPixmap = CreatePixmap(LightMapSize.x, LightMapSize.y, PF_RGB888)
  917.        
  918.         If LightMapSize.x <= 0 Or LightMapSize.y <= 0 Then
  919.         '   pix = Null
  920.             Return
  921.         EndIf
  922.        
  923.         If bsp.LightMapPreW + LightMapSize.x >= bsp.LightMapPixmap.width Then
  924.             bsp.LightMapPreW = LIGHT_PAD * 2
  925.             bsp.LightMapPreH:+bsp.LightMapMaxH
  926.             bsp.LightMapMaxH = 0
  927.         EndIf
  928.        
  929.         Self.LightMapPos = New TQVec2
  930.         Self.LightMapPos.x = Float (bsp.LightMapPreW) / Float(bsp.LightMapPixmap.width)
  931.         Self.LightMapPos.y = Float(bsp.LightMapPreH) / Float(bsp.LightMapPixmap.width)
  932.        
  933.         Local x:Int
  934.         Local y:Int
  935.         Local color:Byte
  936.         For y = 0 Until LightMapSize.y
  937.         For x = 0 Until LightMapSize.x
  938.             color = bsp.Stream.ReadByte()' - Self.BaseLight
  939.             'IF Not color Then Continue
  940.             'pix.WritePixel(x, y, GenRGB(color, color, color))
  941.            
  942.             'If x = 0 Or y = 0 Or x = LightMapSize.x - 1 Or y = LightMapSize.y - 1 Then
  943.             '   bsp.LightMapPixmap.WritePixel(bsp.LightMapPreW + x, bsp.LightMapPreH + y, GenRGB(255, 0, 0))
  944.             'Else
  945.                 bsp.LightMapPixmap.WritePixel(bsp.LightMapPreW + x, bsp.LightMapPreH + y, GenRGB(color, color, color))
  946.             'EndIf
  947.            
  948.             'Padding
  949.             If y = 0 And x = 0 Then bsp.LightMapPixmap.WritePixel(bsp.LightMapPreW + x - 1, bsp.LightMapPreH + y - 1, GenRGB(color, color, color))
  950.             If y = 0 And x = LightMapSize.x - 1 Then bsp.LightMapPixmap.WritePixel(bsp.LightMapPreW + x + 1, bsp.LightMapPreH + y - 1, GenRGB(color, color, color))
  951.            
  952.             If y = LightMapSize.y - 1 And x = 0 Then bsp.LightMapPixmap.WritePixel(bsp.LightMapPreW + x - 1, bsp.LightMapPreH + y + 1, GenRGB(color, color, color))
  953.             If y = LightMapSize.y - 1 And x = LightMapSize.x - 1 Then bsp.LightMapPixmap.WritePixel(bsp.LightMapPreW + x + 1, bsp.LightMapPreH + y + 1, GenRGB(color, color, color))
  954.            
  955.             If y = 0 Then bsp.LightMapPixmap.WritePixel(bsp.LightMapPreW + x, bsp.LightMapPreH + y - 1, GenRGB(color, color, color))
  956.             If x = 0 Then bsp.LightMapPixmap.WritePixel(bsp.LightMapPreW + x - 1, bsp.LightMapPreH + y, GenRGB(color, color, color))
  957.            
  958.             If y = LightMapSize.y - 1 Then bsp.LightMapPixmap.WritePixel(bsp.LightMapPreW + x, bsp.LightMapPreH + y + 1, GenRGB(color, color, color))
  959.             If x = LightMapSize.x - 1 Then bsp.LightMapPixmap.WritePixel(bsp.LightMapPreW + x + 1, bsp.LightMapPreH + y, GenRGB(color, color, color))
  960.         Next
  961.         Next
  962.        
  963.         bsp.LightMapPreW:+LightMapSize.x + LIGHT_PAD * 2
  964.         If bsp.LightMapMaxH < Self.LightMapSize.y + LIGHT_PAD Then bsp.LightMapMaxH = Self.LightMapSize.y + LIGHT_PAD
  965.        
  966.         'If FileType(AppDir + "/lightmaps") = FILETYPE_DIR Then SavePixmapPNG(pix, AppDir + "/lightmaps/" + Plane_ID + ".png", 0)
  967.        
  968.         'Self.LightBrush = LoadBrushPixmap(pix, 16 + 32)
  969.         'pix = Null
  970.     EndMethod
  971.    
  972.     Function Size:Int()
  973.         Return (B_SHORT * 4) + (B_INT * 2) + (B_BYTE * 4)
  974.     EndFunction
  975. EndType
  976.  
  977. Type TQMipHeader
  978.     Field NumTex:Int
  979.     Field Offset:Int[]
  980.    
  981.     Field _count:Int
  982.    
  983.     Function Read:TQMipHeader(Stream:TStream)
  984.         Local nM:TQMipHeader = New TQMipHeader
  985.         nM.NumTex = ReadInt(Stream)
  986.        
  987.         'Should I even read this?
  988.         nM.Offset = New Int[nM.NumTex]
  989.         For Local i:Int = 0 Until nM.NumTex
  990.             nM.Offset[i] = ReadInt(Stream)
  991.             nM._count:+1
  992.         Next
  993.         Return nM
  994.     EndFunction
  995. EndType
  996.  
  997. Type TQMipTex
  998.     Field Name:String
  999.     Field width:Int
  1000.     Field Height:Int
  1001.     Field Offset1:Int
  1002.     Field Offset2:Int
  1003.     Field Offset4:Int
  1004.     Field Offset8:Int
  1005.    
  1006.     Field Surface:TSurface
  1007.    
  1008.     Field Texture:TTexture
  1009.     Field Brush:TBrush
  1010.    
  1011.     Field AnimStep:Int
  1012.    
  1013.     Function Read:TQMipTex(Stream:TStream)
  1014.         Local nM:TQMipTex = New TQMipTex
  1015.         For Local i:Int = 0 Until 16
  1016.             nM.Name:+Chr(ReadByte(Stream))
  1017.         Next
  1018.         nM.width = ReadInt(Stream)
  1019.         nM.Height = ReadInt(Stream)
  1020.         nM.Offset1 = ReadInt(Stream)
  1021.         nM.Offset2 = ReadInt(Stream)
  1022.         nM.Offset4 = ReadInt(Stream)
  1023.         nM.Offset8 = ReadInt(Stream)
  1024.         Return nM
  1025.     EndFunction
  1026.    
  1027.     Function Size:Int()
  1028.         Return (B_BYTE * 16) + (B_INT * 6)
  1029.     EndFunction
  1030. EndType
  1031.  
  1032. Type TQEntry
  1033.     Field Offset:Int
  1034.     Field Size:Int
  1035.    
  1036.     Function Read:TQEntry(Stream:TStream)
  1037.         Local nE:TQEntry = New TQEntry
  1038.         nE.Offset = ReadInt(Stream)
  1039.         nE.Size = ReadInt(Stream)
  1040.         Return nE
  1041.     EndFunction
  1042.    
  1043.     Method Count:Int(typeSize:Int)
  1044.         Return Size / typeSize
  1045.     EndMethod
  1046.    
  1047.     Method JumpTo(Stream:TStream)
  1048.         Stream.Seek(Self.Offset)
  1049.     EndMethod
  1050. EndType
  1051.  
  1052. Type TQNode
  1053.     Field Plane_ID:Int
  1054.    
  1055.     Field Front:Short
  1056.    
  1057.     Field Back:Short
  1058.    
  1059.     Field Box:TQBBoxShort
  1060.     Field Face_ID:Short
  1061.     Field Face_Num:Short
  1062.    
  1063.     Function Read:TQNode(Stream:TStream)
  1064.         Local nN:TQNode = New TQNode
  1065.         nN.Plane_ID = ReadInt(Stream)
  1066.         nN.Front = ReadShort(Stream)
  1067.         nN.Back = ReadShort(Stream)
  1068.         nN.Box = TQBBoxShort.Read(Stream)
  1069.         nN.Face_ID = ReadShort(Stream)
  1070.         nN.Face_Num = ReadShort(Stream)
  1071.         Return nN
  1072.     EndFunction
  1073. EndType
  1074.  
  1075. Type TQDLeaf
  1076.     Field Typ:Int
  1077.     Field VisList:Int
  1078.    
  1079.     Field Bound:TQBBoxShort
  1080.     Field LFace_ID:Short
  1081.    
  1082.     Field LFace_Num:Short
  1083.     Field SndWater:Byte
  1084.     Field SndSky:Byte
  1085.     Field SndSlime:Byte
  1086.     Field SndLava:Byte
  1087.    
  1088.     Function Read:TQDLeaf(Stream:TStream)
  1089.         Local nD:TQDLeaf = New TQDLeaf
  1090.         nD.Typ = ReadInt(Stream)
  1091.         nD.VisList = ReadInt(Stream)
  1092.        
  1093.         nD.Bound = TQBBoxShort.Read(Stream)
  1094.         nD.LFace_ID = ReadShort(Stream)
  1095.        
  1096.         nD.LFace_Num = ReadShort(Stream)
  1097.         nD.SndWater = ReadByte(Stream)
  1098.         nD.SndSky = ReadByte(Stream)
  1099.         nD.SndSlime = ReadByte(Stream)
  1100.         nD.SndLava = ReadByte(Stream)
  1101.         Return nD
  1102.     EndFunction
  1103. EndType
  1104.  
  1105. Type TQPlane
  1106.     Field Normal:TQVec3
  1107.    
  1108.     Field Dist:Float
  1109.    
  1110.     Field Typ:Int
  1111.    
  1112.     Function Read:TQPlane(Stream:TStream)
  1113.         Local nP:TQPlane = New TQPlane
  1114.         nP.Normal = TQVec3.Read(Stream)
  1115.         nP.Dist = ReadFloat(Stream)
  1116.         nP.Typ = ReadInt(Stream)
  1117.         Return nP
  1118.     EndFunction
  1119.    
  1120.     Function Size:Int()
  1121.         Return B_FLOAT + B_INT + TQVec3.Size()
  1122.     EndFunction
  1123. EndType
  1124.  
  1125. Type TQClipNode
  1126.     Field PlaneNum:Int
  1127.     Field Front:Short
  1128.    
  1129.     Field Back:Short
  1130.    
  1131.     Function Read:TQClipNode(Stream:TStream)
  1132.         Local nC:TQClipNode = New TQClipNode
  1133.         nC.PlaneNum = ReadInt(Stream)
  1134.         nC.Front = ReadShort(Stream)
  1135.         nC.Back = ReadShort(Stream)
  1136.         Return nC
  1137.     EndFunction
  1138. EndType
  1139.  
  1140. Type TQPalette
  1141.     Global colors:TQColor32[]
  1142.    
  1143.     Function LoadPalette(url:String)
  1144.         Local Stream:TStream = OpenStream(url, True, False)
  1145.         If Not Stream Then Print("Unable to load palette ~q" + url + "~q")
  1146.         colors = New TQColor32[Stream.Size() / 3]
  1147.        
  1148.         For Local i:Int = 0 Until colors.Length
  1149.             colors[i] = New TQColor32
  1150.             colors[i].r = Stream.ReadByte()
  1151.             colors[i].g = Stream.ReadByte()
  1152.             colors[i].b = Stream.ReadByte()
  1153.         Next
  1154.        
  1155.         'debug save palette
  1156.         Rem
  1157.         Local pix:TPixmap = CreatePixmap(colors.Length, 8, PF_RGB888)
  1158.         For Local i:Int = 0 Until colors.Length
  1159.             For Local y:Int = 0 Until pix.Height
  1160.                 pix.WritePixel(i, y, GenRGB(colors[i].r, colors[i].g, colors[i].b))
  1161.             Next
  1162.         Next
  1163.         SavePixmapPNG(pix, AppDir + "/palette.png", 9)
  1164.         endrem
  1165.        
  1166.         CloseStream(Stream)
  1167.         DebugLog "Palette: " + url + " @ " + colors.Length + " colors"
  1168.     EndFunction
  1169.    
  1170. EndType
  1171.  
  1172. Type TQColor32
  1173.     Field r:Byte
  1174.     Field g:Byte
  1175.     Field b:Byte
  1176. EndType
  1177.  
  1178. 'Basic types
  1179. Type TQVec3
  1180.     Field X:Float
  1181.     Field Y:Float
  1182.     Field Z:Float
  1183.    
  1184.     Function Read:TQVec3(Stream:TStream)
  1185.         Local nV:TQVec3 = New TQVec3
  1186.         nV.X = ReadFloat(Stream)
  1187.         nV.Y = ReadFloat(Stream)
  1188.         nV.Z = ReadFloat(Stream)
  1189.         Return nV
  1190.     EndFunction
  1191.    
  1192.     Function Size:Int()
  1193.         Return B_FLOAT * 3
  1194.     EndFunction
  1195. EndType
  1196.  
  1197. Type TQVec2
  1198.     Field X:Float
  1199.     Field Y:Float
  1200.    
  1201.     Function Read:TQVec2(Stream:TStream)
  1202.         Local nV:TQVec2 = New TQVec2
  1203.         nV.X = ReadFloat(Stream)
  1204.         nV.Y = ReadFloat(Stream)
  1205.         Return nV
  1206.     EndFunction
  1207.    
  1208.     Function Size:Int()
  1209.         Return B_FLOAT * 2
  1210.     EndFunction
  1211. EndType
  1212.  
  1213. Type TQIntVec2
  1214.     Field X:Int
  1215.     Field Y:Int
  1216.    
  1217.     Function Read:TQIntVec2(Stream:TStream)
  1218.         Local nV:TQIntVec2 = New TQIntVec2
  1219.         nV.X = ReadInt(Stream)
  1220.         nV.Y = ReadInt(Stream)
  1221.         Return nV
  1222.     EndFunction
  1223.    
  1224.     Function Size:Int()
  1225.         Return B_INT * 2
  1226.     EndFunction
  1227. EndType
  1228.  
  1229. Type TQBoundBox
  1230.     Field Minimum:TQVec3
  1231.     Field Maximum:TQVec3
  1232.    
  1233.     Function Read:TQBoundBox(Stream:TStream)
  1234.         Local nB:TQBoundBox = New TQBoundBox
  1235.         nB.Minimum = TQVec3.Read(Stream)
  1236.         nB.Maximum = TQVec3.Read(Stream)
  1237.         Return nB
  1238.     EndFunction
  1239.    
  1240.     Function Size:Int()
  1241.             Return TQVec3.Size() * 2
  1242.     EndFunction
  1243. EndType
  1244.  
  1245. Type TQBBoxShort
  1246.     Field Minimum:Short
  1247.     Field Maximum:Short
  1248.    
  1249.     Function Read:TQBBoxShort(Stream:TStream)
  1250.         Local nB:TQBBoxShort = New TQBBoxShort
  1251.         nB.Minimum = ReadShort(Stream)
  1252.         nB.Maximum = ReadShort(Stream)
  1253.         Return nB
  1254.     EndFunction
  1255.    
  1256.     Function Size:Int()
  1257.         Return B_SHORT * 2
  1258.     EndFunction
  1259. EndType
  1260.  
  1261. 'Common
  1262. Function CrossProduct:TQVec3(x1:Float, y1:Float, z1:Float, x2:Float, y2:Float, z2:Float)
  1263.     Local CProd:TQVec3 = New TQVec3
  1264.     CProd.x = (y1 * z2) - (z1 * y2)
  1265.     CProd.y = (z1 * x2) - (x1 * z2)
  1266.     CProd.z = (x1 * y2) - (y1 * x2)
  1267.     Return CProd
  1268. End Function
  1269. Function DotProduct:Float(x1:Float, y1:Float, z1:Float, x2:Float, y2:Float, z2:Float)
  1270.     Return ((x1 * x2) + (y1 * y2) + (z1 * z2))
  1271. EndFunction
  1272.  
  1273. Function GenRGB:Int(r:Byte, g:Byte, b:Byte, a:Byte = 255)
  1274.     Return (a Shl 24) | (r Shl 16) | (g Shl 8) | b
  1275. EndFunction
  1276.    
  1277. Function GetRGB:Int(argb:Int, a:byte Var, r:byte Var, g:byte Var, b:byte Var)
  1278.     a=(argb Shr 24) & $ff
  1279.     r=(argb Shr 16) & $ff
  1280.     g=(argb Shr 8) & $ff
  1281.     b=argb & $ff
  1282. EndFunction
  1283.  
  1284. Function Pow2Size:Int(n:Int)
  1285.     Local t:Int = 1
  1286.     While t<n
  1287.         t:*2
  1288.     Wend
  1289.     Return t
  1290. EndFunction
  1291.  
  1292. 'Custom brushes
  1293. Function LoadBrushPixmap:TBrush(pixmapin:TPixmap, Flags:Int = 1, u_scale:Float = 1.0, v_scale:Float = 1.0)
  1294.     Return PixTBrush.LoadBrushPixmap(pixmapin, Flags, u_scale, v_scale)
  1295. EndFunction
  1296.  
  1297. Function LoadTexturePixmap:TTexture(pixmapin:TPixmap,flags:Int=1)
  1298.     Return PixTTexture.LoadTexturePixmap(pixmapin, Flags)
  1299. EndFunction
  1300.  
  1301. Type PixTBrush Extends TBrush
  1302.  
  1303.     Function LoadBrushPixmap:TBrush(pixmapin:TPixmap,flags:Int=1,u_scale:Float=1.0,v_scale:Float=1.0)
  1304.    
  1305.         Local brush:TBrush=New TBrush
  1306.        
  1307.         brush.tex[0]=PixTTexture.LoadTexturePixmap:TTexture(pixmapin,flags)
  1308.         brush.no_texs=1
  1309.        
  1310.         'brush.tex[0].u_scale#=u_scale#
  1311.         'brush.tex[0].v_scale#=v_scale#
  1312.        
  1313.         pixmapin = Null
  1314.                
  1315.         Return brush
  1316.        
  1317.     EndFunction
  1318. EndType
  1319.  
  1320. Type PixTTexture Extends TTexture
  1321.  
  1322.     Function LoadTexturePixMap:TTexture(pixmapin:TPixmap,flags:Int=1,tex:TTexture=Null)
  1323.    
  1324.         Return LoadAnimTexturePixMap:TTexture(pixmapin,flags,0,0,0,1,tex)
  1325.        
  1326.     End Function
  1327.  
  1328.     Function LoadAnimTexturePixMap:TTexture(pixmapin:TPixmap,flags:Int,frame_width:Int,frame_height:Int,first_frame:Int,frame_count:Int,tex:TTexture=Null)
  1329.    
  1330.         Local pixmapFileName:String="pixmap"+MilliSecs()+Rnd()
  1331.        
  1332.         If flags&128 Then Return LoadCubeMapTexture(pixmapFileName$,flags,tex)
  1333.    
  1334.         If tex=Null Then tex:TTexture=New TTexture
  1335.        
  1336.         tex.file:String=pixmapFileName
  1337.         tex.file_abs:String=pixmapFileName
  1338.        
  1339.         ' set tex.flags before TexInList
  1340.         tex.flags=flags
  1341.         tex.FilterFlags()
  1342.        
  1343.         ' check to see if texture with same properties exists already, if so return existing texture
  1344.         Local old_tex:TTexture
  1345.         old_tex=tex.TexInList()
  1346.         If old_tex<>Null And old_tex<>tex
  1347.             Return old_tex
  1348.         Else
  1349.             If old_tex<>tex
  1350.                 ListAddLast(tex_list,tex)
  1351.             EndIf
  1352.         EndIf
  1353.    
  1354.         ' load pixmap
  1355.         tex.pixmap = CopyPixmap(pixmapin)
  1356.        
  1357.         ' check to see if pixmap contain alpha layer, set alpha_present to true if so (do this before converting)
  1358.         Local alpha_present:Int=False
  1359.         If tex.pixmap.format=PF_RGBA8888 Or tex.pixmap.format=PF_BGRA8888 Or tex.pixmap.format=PF_A8 Then alpha_present=True
  1360.    
  1361.         ' convert pixmap to appropriate format
  1362.         If tex.pixmap.format<>PF_RGBA8888
  1363.             tex.pixmap=tex.pixmap.Convert(PF_RGBA8888)
  1364.         EndIf
  1365.        
  1366.         ' if alpha flag is true and pixmap doesn't contain alpha info, apply alpha based on color values
  1367.         If tex.flags&2 And alpha_present=False
  1368.             tex.pixmap=ApplyAlpha(tex.pixmap)
  1369.         EndIf      
  1370.    
  1371.         ' if mask flag is true, mask pixmap
  1372.         If tex.flags&4
  1373.             tex.pixmap=MaskPixmap(tex.pixmap,0,0,0)
  1374.         EndIf
  1375.        
  1376.         ' ---
  1377.        
  1378.         ' if tex not anim tex, get frame width and height
  1379.         If frame_width=0 And frame_height=0
  1380.             frame_width=tex.pixmap.width
  1381.             frame_height=tex.pixmap.height
  1382.         EndIf
  1383.    
  1384.         ' ---
  1385.        
  1386.         tex.no_frames=frame_count
  1387.         tex.gltex=tex.gltex[..tex.no_frames]
  1388.    
  1389.         ' ---
  1390.        
  1391.         ' pixmap -> tex
  1392.    
  1393.         Local xframes:Int=tex.pixmap.width/frame_width
  1394.         Local yframes:Int=tex.pixmap.height/frame_height
  1395.            
  1396.         Local startx:Int=first_frame Mod xframes
  1397.         Local starty:Int=(first_frame/yframes) Mod yframes
  1398.            
  1399.         Local x:Int=startx
  1400.         Local y:Int=starty
  1401.    
  1402.         Local pixmap:TPixmap
  1403.    
  1404.         For Local i:Int=0 To tex.no_frames-1
  1405.    
  1406.             ' get static pixmap window. when resize pixmap is called new pixmap will be returned.
  1407.             pixmap=tex.pixmap.Window(x*frame_width,y*frame_height,frame_width,frame_height)
  1408.             x=x+1
  1409.             If x>=xframes
  1410.                 x=0
  1411.                 y=y+1
  1412.             EndIf
  1413.        
  1414.             ' ---
  1415.        
  1416.             pixmap=AdjustPixmap(pixmap)
  1417.             tex.width=pixmap.width
  1418.             tex.height=pixmap.height
  1419.             Local width:Int=pixmap.width
  1420.             Local height:Int=pixmap.height
  1421.    
  1422.             Local name:Int
  1423.             glGenTextures 1,Varptr name
  1424.             glBindtexture GL_TEXTURE_2D,name
  1425.    
  1426.             Local mipmap:Int
  1427.             If tex.flags&8 Then mipmap=True
  1428.             Local mip_level:Int=0
  1429.             Repeat
  1430.                 glPixelStorei GL_UNPACK_ROW_LENGTH,pixmap.pitch/BytesPerPixel[pixmap.format]
  1431.                 glTexImage2D GL_TEXTURE_2D,mip_level,GL_RGBA8,width,height,0,GL_RGBA,GL_UNSIGNED_BYTE,pixmap.pixels
  1432.                 If Not mipmap Then Exit
  1433.                 If width=1 And height=1 Exit
  1434.                 If width>1 width:/2
  1435.                 If height>1 height:/2
  1436.    
  1437.                 pixmap=ResizePixmap(pixmap,width,height)
  1438.                 mip_level:+1
  1439.             Forever
  1440.             tex.no_mipmaps=mip_level
  1441.    
  1442.             tex.gltex[i]=name
  1443.    
  1444.         Next
  1445.                
  1446.         tex.pixmap = Null
  1447.                
  1448.         Return tex
  1449.        
  1450.     End Function
  1451. EndType
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement