Advertisement
CheezusCrust

Untitled

Apr 3rd, 2017
125
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.00 KB | None | 0 0
  1. --@name Scanner
  2. --@author Cheezus
  3. --@shared
  4.  
  5. -------------------------------------------------------------------------------------------------------------
  6. if SERVER then -----------------------------------SERVER STUFF-----------------------------------------------
  7. -------------------------------------------------------------------------------------------------------------
  8.  
  9. if not chip():isWeldedTo() then return end --If the screen entity doesn't exist, shut 'er down, the chip shouldn't run
  10.  
  11. chip():isWeldedTo():linkComponent(chip()) --Automatically link the entity the chip is welded to - the screen
  12. local screen = chip():isWeldedTo() --Store it in a variable named 'screen'
  13.  
  14.  
  15. --Dunno why I have to send the screen entity to the client a bunch of times but just sending it once
  16. --means the client doesn't receive it fast enough(?) so I'm sending it 66 times with a 0-second timer
  17.  
  18. --Because fuck efficiency.
  19. timer.create("interval",0,66,function()
  20. net.start("screenEnt")
  21. net.writeEntity(screen)
  22. net.send()
  23. end)
  24.  
  25. -------------------------------------------------------------------------------------------------------------
  26. else ---------------------------------------------CLIENT STUFF-----------------------------------------------
  27. -------------------------------------------------------------------------------------------------------------
  28.  
  29. render.createRenderTarget("scanner") --Render targets are like a 'custom material' that you can draw to.
  30. --Here we're creating one named 'scanner'
  31. --Render targets are useful if you want previously drawn objects/pixels to 'persist' aka not
  32. --delete themselves when you stop calling the draw function for that specific object/pixel
  33.  
  34. -------------------------------------------------------------------------------------------------------------
  35. --------------------------------------------------SETUP------------------------------------------------------
  36. -------------------------------------------------------------------------------------------------------------
  37.  
  38. local fov = 75 --Field of view
  39. local maxDist = 10000 --After this distance (in source units) the fog is 100%
  40. local quotaLimit = 0.9 --Percentage of the client's CPU to use. 0.9-0.95 is usually fine
  41. local skyColor = Vector(165, 206, 235) --Color of the sky/fog
  42. local res = 512 --Resolution - keep this 1024 or under
  43. local useTextelColors = true --Use the world's textel colors for world color information. Slightly buggy, can look odd in some situations
  44. local shadows = true --Setting this to true enables shadowing, which increases render time but can look nice
  45. local shadowReduction = 0.5 --Percentage of light shadowed objects should receive, where 0 is flat black and 1 is no shadow
  46. local sunDirection = Vector(-0.85,0.5,0.5) --Direction the sun is in
  47.  
  48. -------------------------------------------------------------------------------------------------------------
  49. ----------------------------END OF SETUP - DON'T MESS WITH STUFF PAST HERE-----------------------------------
  50. -------------------------------------------------------------------------------------------------------------
  51.  
  52. local x = 0 --Starting pixel, X coordinate. Don't change this.
  53. local y = 0 --Starting pixel, Y coordinate. Don't change this.
  54. local startTime = timer.realtime() --Time the scan was started
  55.  
  56. --Create a function we'll use to make drawing pixels to the screen easier
  57. --It takes an X coordinate, a Y coordinate, and a color as inputs
  58. --local function draw(x, y, col, mat)
  59. local function draw(x, y, col)
  60. render.setRGBA(col.x, col.y, col.z, 255) --Sets the color of the next drawn object, based on the color input to this function
  61. render.drawRect(x * (1024/res), y * (1024/res), 1 + (1024/res), 1 + (1024/res))
  62. --Draws a rectangle at the specified x and y coordinates (basically a pixel), the size of the pixel being determined by the resolution
  63. end
  64.  
  65. --This function returns 1 if the SF is under the CPU quota, if not, returns 0
  66. local function canRun(quota)
  67. if quotaAverage() > quotaMax() * quota or quotaUsed() > quotaMax() * quota then --Checks whether the CPU quota is less than
  68. --what the user set in the settings
  69. return 0
  70. else
  71. return 1
  72. end
  73. end
  74.  
  75. --Function which mixes two input vectors together, the bias towards the first or second vector being decided by the ratio
  76. --Mixing essentially lets you 'slide' between the first and second input smoothly.
  77. --If your input 1 is Vector(0,0,0), and your input 2 is Vector(5,10,50), mixing with a ratio of 0.5 (half)
  78. --would return Vector(2.5,5,25), because Vector(2.5,5,25) is exactly half way between the two inputs.
  79. local function mix(vec1, vec2, ratio)
  80. return Vector(vec1.x * ratio + vec2.x * (1-ratio), vec1.y * ratio + vec2.y * (1-ratio), vec1.z * ratio + vec2.z * (1-ratio))
  81. --Mix equation: input1 * ratio + input2 * (1 - ratio)
  82. end
  83.  
  84. --Receive the screen entity which was previously sent from the server
  85. hook.add("net", "Net", function(name)
  86. screen = net.readEntity()
  87. end)
  88.  
  89. -------------------------------------------------------------------------------------------------------------
  90. --------------------------------------------------RENDERING--------------------------------------------------
  91. -------------------------------------------------------------------------------------------------------------
  92.  
  93. hook.add("render", "Render", function()
  94. render.selectRenderTarget("scanner") --Select the render target we created earlier
  95.  
  96. --While loop to speed things up. Runs on the following conditions:
  97. --The CPU quota is below the limit
  98. --The current Y coordinate is less than the resolution
  99. --The screen entity is actually a valid entity (is linked to the chip)
  100. while canRun(quotaLimit) == 1 and y < res+1 and screen:isValid() do
  101.  
  102. --When the scan is first started (both coordinates at 0), clear the screen
  103. if y == 0 and x == 0 then
  104. render.clear(Color(0,0,0,0))
  105. end
  106.  
  107. --Run a trace, based on the screen's position and some math to get the direction it should be facing using the X and Y coordinates
  108. local trace1 = trace.trace(screen:getPos() - screen:getUp()*10, screen:localToWorld( Vector((-res*fov/2 + y*fov) * (1024/res), (-res*fov/2 + x*fov) * (1024/res), -50000)), find.allPlayers())
  109.  
  110. local hitPos = trace1.HitPos --The trace's hit position
  111. local dist = (hitPos - screen:getPos()):getLength() --The distance of the trace's hit position from the screen
  112. local sky = Vector(skyColor.x/255 - (y/res)/2, skyColor.y/255 - (y/res)/2, skyColor.z/255 - (y/res)/2)*255 --Sky gradient effect
  113.  
  114. if shadows == true then
  115. trace2 = trace.trace(hitPos, hitPos + sunDirection * 100000)
  116. if trace2.HitSky then
  117. shadowReductionVal = 1
  118. else
  119. shadowReductionVal = shadowReduction
  120. end
  121. else
  122. shadowReductionVal = 1
  123. end
  124.  
  125. if trace1.Entity:isValid() then --If the trace hit an entity, get its color
  126. --local mat = trace1.Entity:getMaterials()[1]
  127. color = Vector(trace1.Entity:getColor().r, trace1.Entity:getColor().g, trace1.Entity:getColor().b) * shadowReductionVal
  128. elseif trace1.HitSky then --If the trace hits the sky, just set the color as the sky color
  129. color = sky
  130. else --If the trace hits anything else (probably the world)
  131. if useTextelColors then
  132. color = render.traceSurfaceColor(screen:getPos() - screen:getUp()*10, screen:localToWorld( Vector((-res*fov/2 + y*fov) * (1024/res), (-res*fov/2 + x*fov) * (1024/res), -50000))) * 255 * shadowReductionVal
  133. else
  134. --This is temporary, color getting shit goes here soon(tm)
  135. color = Vector(200, 200, 200) * shadowReductionVal
  136. end
  137. end
  138.  
  139. draw(x, y, mix(color, sky, math.clamp(1-(dist/maxDist), 0, 1))) --Draw the pixel based on current X/Y pos and current color
  140.  
  141. --Position advancement
  142. if x <= res then
  143. x = x + 1
  144. else
  145. x = 0
  146. y = y + 1
  147. end
  148. end --End of the while loop
  149.  
  150. render.selectRenderTarget() --Select a blank render target, which returns the chip to drawing to the actual screen instead of the RT texture
  151. if y < res then --If the scan hasn't finished yet, draw this stuff to the screen
  152. render.setColor(Color(255,255,255,255)) --Set the draw color to solid white
  153. render.drawSimpleText(0, 0, "Rendering " .. res .. "x" .. res .. " image", 0, 0) --Display image size
  154. render.drawSimpleText(0, 12, math.floor((y/res) * 100) .. "%", 0, 0) --Display progress
  155. render.drawSimpleText(0, 24, math.floor(timer.realtime()-startTime) .. " seconds elasped", 0, 0) --Display time elapsed
  156. render.drawSimpleText(0, 36, "CPU Usage: " .. math.round( ( quotaAverage() / quotaMax() ) * 100 ) .. "%", 0, 0)
  157. else --If the scan is finished
  158. render.setRenderTargetTexture("scanner") --Sets the draw texture to the name of the render target we were drawing to during the scan
  159. render.drawTexturedRect(0,0,512,512) --Finally, draw a screen-size textured rectangle, using the RT texture we just set
  160. end
  161. end)
  162. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement