Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- screens = screens or {}
- screens.active_screens = screens.active_screens or {}
- screens.lock_player = false
- screens.mouse_delta = Vector(0, 0, 0)
- screens.focused_screen = screens.focused_screen or NULL
- do -- meta
- local SCREEN = {}
- SCREEN.__index = SCREEN
- function SCREEN:Remove()
- self:KillFocus()
- for _, ent in pairs(self.entities) do
- SafeRemoveEntity(ent)
- end
- function self:IsValid()
- return false
- end
- screens.active_screens[self.screen_id] = nil
- setmetatable(self, getmetatable(NULL))
- end
- function SCREEN:IsValid()
- return true
- end
- AccessorFunc(SCREEN, "terrain_mat", "TerrainMaterial")
- AccessorFunc(SCREEN, "rt_tex", "RTTexture")
- AccessorFunc(SCREEN, "fps", "FPS", FORCE_NUMBER)
- AccessorFunc(SCREEN, "width", "Width")
- AccessorFunc(SCREEN, "height", "Height")
- AccessorFunc(SCREEN, "water_level", "WaterLevel")
- AccessorFunc(SCREEN, "cam_pos", "CameraPos")
- AccessorFunc(SCREEN, "cam_ang", "CameraAngles")
- AccessorFunc(SCREEN, "cam_fov", "CameraFOV")
- function SCREEN:IsPaused()
- return self.paused
- end
- function SCREEN:Pause()
- self.paused = true
- end
- function SCREEN:Resume()
- self.paused = false
- end
- do -- input
- function SCREEN:RequestFocus()
- screens.EnableKeyMonitor(true)
- screens.focused_screen = self
- end
- function SCREEN:KillFocus()
- if screens.focused_screen == self then
- screens.EnableKeyMonitor(false)
- screens.focused_screen = NULL
- end
- end
- function SCREEN:IsFocused()
- return screens.focused_screen == self
- end
- function SCREEN:GetMouseDelta()
- return screens.mouse_delta
- end
- function SCREEN:OnInput(key, press)
- if key == IN_USE and press then
- self:KillFocus()
- end
- end
- end
- do -- entities
- function SCREEN:CreateEntity(mdl)
- local ent = ClientsideModel(mdl)
- ent:SetNoDraw(true)
- table.insert(self.entities, ent)
- return ent
- end
- function SCREEN:DrawEntities()
- render.SuppressEngineLighting(true)
- render.SetBlend(1)
- render.SetColorModulation(1,1,1)
- render.SetAmbientLight(0,0,0)
- render.ResetModelLighting(0.2,0.2,0.2)
- render.SetModelLighting(3, 1,1,1) -- global_light.r / 255, global_light.g / 255, global_light.b / 255)
- for _, ent in pairs(self.entities) do
- ent:DrawModel()
- end
- render.SuppressEngineLighting(false)
- end
- end
- if pac then
- function SCREEN:GetTextureFromURL(url, size, callback)
- pac.urltex.GetMaterialFromURL(url, function(mat, tex)
- callback(mat, tex)
- end, false, nil, size, false)
- end
- end
- do -- terrain
- local W, H = ScrW(), ScrH()
- local function start_height(tex)
- local mat = CreateMaterial("screens_heightmap_" .. os.clock(), "UnlitGeneric", {["$basetexture"] = "dev/hemisphere_height.vtf"})
- if tex then
- mat:SetTexture("$basetexture", tex)
- end
- cam.Start2D()
- surface.SetMaterial(mat)
- surface.SetDrawColor(255, 255, 255, 255)
- -- this kinda sucks but using a heightmap resolution higher than screen resolution will cause undesired results..
- surface.DrawTexturedRect(0, 0, W, H)
- render.CapturePixels()
- end
- local function get_height(x, y)
- local r,g,b = render.ReadPixel(math.ceil(x*W), math.ceil(y*H))
- return ((r+g+b) / 3) / 255
- end
- local function end_height()
- cam.End2D()
- end
- function SCREEN:CreateTerrainFromHeightmap(tex, size, res, height)
- local mesh = Mesh()
- start_height(tex)
- size = size or 32768
- res = res or 64
- height = height or 8192
- local data = {}
- local _size = size / res
- for y = 0, res do
- for x = 0, res do
- local z1 = get_height(x/res, (y+1)/res) * height -- bottom left
- local z2 = get_height(x/res, y/res) * height -- top left
- local z3 = get_height((x+1)/res, y/res) * height -- top right
- local z4 = get_height((x+1)/res, (y+1)/res) * height -- bottom right
- table.insert(data, {pos = Vector(x * _size + _size, y * _size, z3)})
- table.insert(data, {pos = Vector(x * _size, y * _size, z2)})
- table.insert(data, {pos = Vector(x * _size, y * _size + _size, z1)})
- table.insert(data, {pos = Vector(x * _size, y * _size + _size, z1)})
- table.insert(data, {pos = Vector(x * _size + _size, y * _size + _size, z4)})
- table.insert(data, {pos = Vector(x * _size + _size, y * _size, z3)})
- end
- end
- end_height()
- local height_cache = {}
- for _, vertex in pairs(data) do
- -- vertex.normal = VectorRand()
- vertex.u = (vertex.pos.x / size)
- vertex.v = (vertex.pos.y / size)
- end
- start_height(tex)
- for x = 0, W do
- for y = 0, H do
- local r,g,b = render.ReadPixel(x, y)
- local z = ((r+g+b) / 3) / 255
- height_cache[x] = height_cache[x] or {}
- height_cache[x][y] = height_cache[x][y] or z * height
- end
- end
- end_height()
- self.height_cache = height_cache
- mesh:BuildFromTriangles(data)
- SafeRemoveEntity(self.terrain_ent)
- local ent = self:CreateEntity("error.mdl")
- self.terrain_mat = Material("models/wireframe")
- self.terrain_size = size
- ent.RenderOverride = function(ent)
- render.MaterialOverride(self.terrain_mat)
- ent:SetModelScale(0, 0)
- ent:DrawModel()
- local mat = Matrix()
- mat:SetAngles(ent:GetAngles())
- mat:SetTranslation(ent:GetPos())
- cam.PushModelMatrix(mat)
- mesh:Draw()
- cam.PopModelMatrix()
- render.MaterialOverride()
- end
- end
- function SCREEN:GetTerrainHeight(pos)
- if self.height_cache then
- local x = math.floor((pos.x / self.terrain_size) * W)
- local y = math.floor((pos.y / self.terrain_size) * H)
- return self.height_cache[x] and self.height_cache[x][y] or 0
- end
- return 0
- end
- end
- function SCREEN:SetFog(start, _end, max_density, r,g,b)
- if start and _end and max_density and r and g and b then
- self.fog_params =
- {
- start = start,
- _end = _end,
- max_density = max_density,
- color = {r,g,b},
- }
- else
- self.fog_params = nil
- end
- end
- function SCREEN:CreateWorldScreen()
- SafeRemoveEntity(self.world_screen)
- local ent = ClientsideModel("models/hunter/plates/plate1x1.mdl")
- local mat = Matrix()
- mat:Scale(Vector(self.height / self.width, 1, 1))
- ent:EnableMatrix("RenderMultiply", mat)
- ent.RenderOverride = function(s)
- if not self:IsValid() then
- timer.Simple(0, function()
- s:Remove()
- end)
- end
- render.SetBlend(1)
- render.SetColorModulation(1, 1, 1)
- render.PushFilterMag(TEXFILTER.POINT)
- render.PushFilterMin(TEXFILTER.POINT)
- render.MaterialOverride(self.screen_mat)
- s:DrawModel()
- render.MaterialOverride()
- render.PopFilterMag()
- render.PopFilterMin()
- end
- self.world_screen = ent
- return ent
- end
- -- events
- function SCREEN:UpdateFreeroamCamera()
- local speed = 100
- local delta = screens.mouse_delta * 0.1
- local cam_pos = self.cam_pos
- local cam_ang = self.cam_ang
- cam_ang.p = cam_ang.p + delta.y
- cam_ang.y = cam_ang.y - delta.x
- cam_ang.p = math.clamp(cam_ang.p, -90, 90)
- if input.IsKeyDown(KEY_LSHIFT) then
- speed = speed * 4
- elseif input.IsKeyDown(KEY_LCONTROL) then
- speed = speed / 4
- end
- if input.IsKeyDown(KEY_SPACE) then
- cam_pos = cam_pos - Vector(0, 0, -speed)
- end
- local offset = cam_ang:Forward() * speed
- if input.IsKeyDown(KEY_W) then
- cam_pos = cam_pos + offset
- elseif input.IsKeyDown(KEY_S) then
- cam_pos = cam_pos - offset
- end
- offset = cam_ang:Right() * speed
- offset.z = -offset.z
- if input.IsKeyDown(KEY_D) then
- cam_pos = cam_pos + offset
- elseif input.IsKeyDown(KEY_A) then
- cam_pos = cam_pos - offset
- end
- self.cam_pos = cam_pos
- self.cam_ang = cam_ang
- end
- function SCREEN:UpdateWalkCamera()
- self.cam_vel = self.cam_vel or Vector(0,0,0)
- local speed = 10
- local delta = screens.mouse_delta * 0.1
- local cam_pos = self.cam_pos
- local cam_ang = self.cam_ang
- cam_ang.p = cam_ang.p + delta.y
- cam_ang.y = cam_ang.y - delta.x
- cam_ang.p = math.clamp(cam_ang.p, -90, 90)
- if input.IsKeyDown(KEY_LSHIFT) then
- speed = speed * 4
- elseif input.IsKeyDown(KEY_LCONTROL) then
- speed = speed / 4
- end
- if input.IsKeyDown(KEY_SPACE) then
- if not self.jumped then
- self.cam_vel.z = self.cam_vel.z + 500
- self.jumped = true
- end
- else
- self.jumped = false
- end
- local offset = cam_ang:Forward() * speed
- if input.IsKeyDown(KEY_W) then
- cam_pos = cam_pos + offset
- elseif input.IsKeyDown(KEY_S) then
- cam_pos = cam_pos - offset
- end
- offset = cam_ang:Right() * speed
- offset.z = -offset.z
- if input.IsKeyDown(KEY_D) then
- cam_pos = cam_pos + offset
- elseif input.IsKeyDown(KEY_A) then
- cam_pos = cam_pos - offset
- end
- cam_pos.z = math.max(cam_pos.z - 100, self:GetTerrainHeight(cam_pos) + 72)
- self.cam_vel = (self.cam_vel + (cam_pos - self.cam_pos)) * 0.35
- self.cam_pos = cam_pos + self.cam_vel
- self.cam_ang = cam_ang
- end
- function SCREEN:UpdateCamera()
- if not self:IsFocused() then return end
- self:UpdateFreeroamCamera()
- end
- function SCREEN:Think()
- self:UpdateCamera()
- end
- local skybox_ent = ClientsideModel("models/XQM/Rails/gumball_1.mdl")
- skybox_ent:SetMaterial("models/debug/debugwhite")
- function SCREEN:DrawSkyBox()
- render.SetColorModulation(0.4,0.7,1)
- render.SetBlend(1)
- render.SuppressEngineLighting(true)
- skybox_ent:SetPos(self.cam_pos)
- skybox_ent:SetModelScale(-1, 0)
- skybox_ent:DrawModel()
- render.SuppressEngineLighting(false)
- render.ClearDepth()
- end
- do -- water
- local water_mat = CreateMaterial("screens_water_"..RealTime(), "Refract",
- {
- ["$model"] = 1,
- ["$nocull"] = 1,
- ["$translucent"] = 1,
- ["$bluramount"] = 50,
- ["$refractamount"] = 0.1,
- ["$refracttint"] = "0.5 0.5 1",
- ["$dudvmap"] = "water/dx80_tfwater001_dudv",
- ["$normalmap"] = "water/tfwater001_normal",
- Proxies =
- {
- AnimatedTexture =
- {
- animatedtexturevar = "$normalmap",
- animatedtextureframenumvar = "$bumpframe",
- animatedtextureframerate = 30,
- },
- },
- })
- local water_mesh = Mesh()
- local data = {}
- local size = 32768 / 8
- for y = 0, 128 do
- for x = 0, 128 do
- table.insert(data, {pos = Vector(x * size + size, y * size)})
- table.insert(data, {pos = Vector(x * size, y * size)})
- table.insert(data, {pos = Vector(x * size, y * size + size)})
- table.insert(data, {pos = Vector(x * size, y * size + size)})
- table.insert(data, {pos = Vector(x * size + size, y * size + size)})
- table.insert(data, {pos = Vector(x * size + size, y * size)})
- end
- end
- local up = Vector(0,0,1)
- for k,v in pairs(data) do
- v.normal = up
- v.v = v.pos.x / size
- v.u = v.pos.y / size
- end
- water_mesh:BuildFromTriangles(data)
- function SCREEN:DrawWater()
- render.UpdateRefractTexture()
- render.SetBlend(1)
- render.SuppressEngineLighting(true)
- local mat = Matrix()
- mat:Translate(Vector(self.cam_pos.x - 32768*8, self.cam_pos.y - 32768*8,self.water_level))
- cam.PushModelMatrix(mat)
- render.SetMaterial(water_mat)
- water_mesh:Draw()
- cam.PopModelMatrix()
- render.SuppressEngineLighting(false)
- end
- end
- function SCREEN:Draw3D()
- self:DrawEntities()
- end
- function SCREEN:Draw2D()
- end
- function SCREEN:DrawPostProcess()
- if self.cam_pos.z < self.water_level then
- surface.SetDrawColor(20,50,100,100)
- surface.DrawRect(0,0,self.width,self.height)
- end
- end
- function SCREEN:Update()
- self:Think()
- local old_rt, old_w, old_h = render.GetRenderTarget(), ScrW(), ScrH()
- render.SetRenderTarget(self.rt_tex)
- render.SetViewPort(0, 0, self.width, self.height)
- render.Clear(0,0,0,0, true)
- local params = {}
- params.origin = self.cam_pos
- params.angles = self.cam_ang
- params.fob = self.cam_fov
- params.x = 0
- params.y = 0
- params.w = self.width
- params.h = self.height
- params.zfar = 32000*4
- params.aspect = self.width/self.height
- cam.Start(params)
- self:DrawSkyBox()
- local params = self.fog_params
- if params then
- render.FogMode(1)
- render.FogStart(params.start)
- render.FogEnd(params._end)
- render.FogMaxDensity(params.max_density)
- render.FogColor(unpack(params.color))
- end
- self:Draw3D()
- self:DrawWater()
- cam.End()
- cam.Start2D()
- self:Draw2D()
- self:DrawPostProcess()
- cam.End2D()
- render.SetRenderTarget(old_rt)
- render.SetViewPort(0, 0, old_w, old_h)
- end
- screens.ScreenMeta = SCREEN
- end
- function screens.GetAll()
- return screens.active_screens
- end
- function screens.Remove(id)
- local self = screens.active_screens[id] or NULL
- if self:IsValid() then
- self:Remove()
- end
- end
- function screens.Create(id, w, h, fps)
- w = w or 320
- h = h or 240
- fps = fps or 10
- screens.Remove(id)
- local self = setmetatable({}, screens.ScreenMeta)
- self.screen_id = id
- self.width = w
- self.height = h
- self.fps = fps
- self.cam_pos = Vector(0, 0, 0)
- self.cam_ang = Angle(0, 0, 0)
- self.cam_fov = 90
- self.rt_tex = GetRenderTarget(id, w, h, true)
- self.screen_mat = CreateMaterial(id, "UnlitGeneric")
- self.screen_mat:SetTexture("$basetexture", self.rt_tex)
- self.water_level = 1000
- self.world_screen = NULL
- self.entities = {}
- screens.active_screens[id] = self
- return self
- end
- function screens.EnableKeyMonitor(b)
- if b then
- screens.lock_player = LocalPlayer():EyeAngles()
- else
- screens.lock_player = false
- end
- end
- do -- hooks
- hook.Add("Think", "screens_update", function()
- local time = RealTime()
- for _, screen in pairs(screens.active_screens) do
- if not screen.paused and (not screen.last_update or screen.last_update < time) then
- screen:Update()
- screen.last_update = time + (1/screen.fps)
- end
- end
- end)
- hook.Add("CreateMove", "screens_camera", function(ucmd)
- if screens.lock_player then
- ucmd:SetForwardMove(0)
- ucmd:SetSideMove(0)
- ucmd:SetViewAngles(screens.lock_player)
- screens.mouse_delta.x = ucmd:GetMouseX()
- screens.mouse_delta.y = ucmd:GetMouseY()
- end
- end)
- local SIGH = {}
- hook.Add("KeyPress", "screens", function(ply, key)
- if key == IN_USE then
- for _, screen in pairs(screens.active_screens) do
- if screen.world_screen:IsValid() and screen.world_screen:GetPos():Distance(ply:EyePos()) < 100 then
- if not screens.last_focus or screens.last_focus < RealTime() then
- screen:RequestFocus()
- screens.last_focus = RealTime() + 0.5
- end
- end
- end
- end
- local screen = screens.focused_screen
- if screen:IsValid() then
- if not SIGH[key] then
- screen:OnInput(key, true)
- SIGH[key] = true
- end
- end
- end)
- hook.Add("KeyRelease", "screens", function(ply, key)
- local screen = screens.focused_screen
- if screen:IsValid() then
- if SIGH[key] then
- screen:OnInput(key, false)
- SIGH[key] = false
- end
- end
- end)
- end
- do -- test
- local size = 32768 * 4
- local screen = screens.Create("forest")
- screen:SetCameraPos(Vector(37032, 33568, 2500))
- screen:SetCameraAngles(Angle(0,45,0))
- local ent = screen:CreateWorldScreen()
- ent:SetPos(Vector(-15293.693359375, 863.96875, 14368.344726562))
- ent:SetAngles(Angle(90,90,0))
- screen:SetFog(0, size, 0.5, 80, 170, 255)
- screen:SetWaterLevel(1500)
- local trees = {
- "models/props_foliage/tree_pine01.mdl",
- "models/props_foliage/tree_pine01_8cluster.mdl",
- "models/props_foliage/tree_pine01_4cluster.mdl",
- "models/props_foliage/tree_pine_huge.mdl",
- "models/props_foliage/tree_pine_small.mdl",
- }
- -- screen:GetTextureFromURL("https://dl.dropbox.com/u/244444/ShareX/2013-07/2013-07-12_16-32-18.jpg", 2048, function(mat, tex)
- screen:CreateTerrainFromHeightmap(CreateMaterial("screens_terrain_height" .. os.clock(), "UnlitGeneric",{["$basetexture"] = "Models/shadertest/shieldnoise0_normal"}):GetTexture("$basetexture"), size, 5000)
- for i = 1, 1000 do
- local pos = Vector(math.random(), math.random(), 0) * size
- pos.z = screen:GetTerrainHeight(pos)
- if pos.z > screen:GetWaterLevel() + 500 and pos.z < 3000 then
- local ent = screen:CreateEntity(table.Random(trees))
- ent:SetModelScale(math.Rand(0.5, 2), 0)
- ent:SetPos(pos)
- end
- end
- --end)
- -- screen:GetTextureFromURL("https://dl.dropbox.com/u/244444/ShareX/2013-07/2013-07-12_16-32-18.jpg", 2048, function(mat)
- --- screen:SetTerrainMaterial(mat)
- --end)
- function screen:Draw2D()
- local t = RealTime()
- local w, h = screen:GetWidth(), screen:GetHeight()
- surface.SetFont("DermaDefault")
- surface.SetTextColor(255, 255, 255, 255)
- local pos = self:GetCameraPos()
- surface.SetTextPos(5, 5)
- surface.DrawText(tostring(pos))
- local height = self:GetTerrainHeight(pos)
- surface.SetTextPos(5, 20)
- surface.DrawText(height)
- end
- LOL_SCREEN = screen
- end
Advertisement
Add Comment
Please, Sign In to add comment