Added lighting code, didn't include it yet.

This commit is contained in:
Aryn
2014-02-23 01:40:51 -07:00
committed by ZomgPonies
parent 458ecedddd
commit d443734d60
6 changed files with 443 additions and 0 deletions
@@ -0,0 +1,115 @@
/*
Overview:
Unlike the previous lighting controller, this is mostly here to hold global lighting procs and vars.
It does not process every tick, because not even DAL did something so stupid.
Global Vars:
initial_lights - This holds all lights formed before the lighting controller started up. It becomes null on initialization.
Class Vars:
starlight - The light value of space.
icon_updates - The list of turfs which need an update to their overlays.
light_border - Space turfs which are adjacent to non-space turfs.
Class Procs:
Initialize()
Starts the lighting system, creating all light points and turf overlays.
StarLight(n)
Sets the light produced by space. If a solar eclipse suddenly happens, it'll probably lag.
MarkIconUpdate(turf/T)
Called when a turf needs an update to its light icon. Ensures that it only gets calculated once per turf.
FlushIconUpdates()
Called when a light is done marking icon updates. Updates every marked turf.
AddBorder(turf/T) & RemoveBorder(turf/T)
Called by turf/CheckForOpaqueObjects() to modify the light_border list.
*/
var/datum/controller/lighting/lighting_controller
var/list/initial_lights = list()
var/all_lightpoints_made = 0
/datum/controller/lighting
var/starlight = 4
var/list/icon_updates = list()
var/list/light_border = list()
//var/icon/border = icon('Icons/Test.dmi', "border")
/datum/controller/lighting/New()
lighting_controller = src
/datum/controller/lighting/proc/Initialize()
var/start_time = world.timeofday
world << "<b><font color=red>Processing lights...</font></b>"
var/turfs_updated = 0
for(var/z = 1, z <= world.maxz, z++)
for(var/y = 0, y <= world.maxy, y++)
for(var/x = 0, x <= world.maxx, x++)
if(x > 0 && y > 0)
var/turf/T = locate(x,y,z)
if(!T.light_overlay)
T.light_overlay = new(T)
T.CheckForOpaqueObjects()
turfs_updated++
if(!all_lightpoints_made) new/lightpoint(x+0.5,y+0.5,z)
all_lightpoints_made = 1
for(var/atom/movable/M in initial_lights)
if(!M.light)
M.SetLight(M.luminosity,M.luminosity)
else
M.light.Reset()
StarLight(starlight)
initial_lights = null
world << "<b><font color=red>Lighting initialization took [(world.timeofday-start_time)/world.fps] seconds.</font></b>"
world << "<font color=red>Updated [turfs_updated] turfs.</font>"
/datum/controller/lighting/proc/StarLight(n)
starlight = n
for(var/turf/T in light_border)
T.SetLight(5,n-1)
for(var/turf/T)
if(T.is_outside)
T.ResetValue()
FlushIconUpdates()
/datum/controller/lighting/proc/MarkIconUpdate(turf/T)
if(!T.needs_light_update)
icon_updates.Add(T)
T.needs_light_update = 1
/datum/controller/lighting/proc/FlushIconUpdates()
for(var/turf/T in icon_updates)
T.UpdateLight()
T.needs_light_update = 0
icon_updates = list()
/datum/controller/lighting/proc/AddBorder(turf/T)
if(!T.is_border)
light_border.Add(T)
T.is_border = 1
//T.overlays.Add(border)
/datum/controller/lighting/proc/RemoveBorder(turf/T)
if(T.is_border)
light_border.Remove(T)
T.is_border = 0
+176
View File
@@ -0,0 +1,176 @@
/*
Overview:
Procs given to atom and turf by the lighting engine, as well as the lighting overlay object.
Atom Vars:
light - Contains the light object this atom is currently shining with.
Turf Vars:
light_overlay - Contains an object showing the lighting icon over this turf.
lit_value - Stores how brightly lit the turf is.
has_opaque - A cached value updated by CheckForOpaqueObjects()
is_outside - Any turf with this set to true will be considered as bright as space.
needs_light_update - Turf is marked for icon updates when true.
lightNE, lightSE, lightNW, lightSW - Hold the lightpoints on the four corners of this turf. See Lightpoint.dm
lit_by - A list of lights that are lighting this turf.
Atom Procs:
SetLight(intensity, radius)
A more versatile SetLuminosity() that allows independent control of intensity and radius.
Called behind the scenes of SetLuminosity().
SetOpacity(opacity)
Does the same thing as DAL.
Turf Procs:
UpdateLight()
Called by the lighting controller. It is advisable not to call this manually due to the cost of lightpoint/max_value()
AddLight(light/light)
Called by light/Reset() to light this turf with a particular light.
RemoveLight(light/light)
Called by light/Off() to unlight turfs that were lit by it.
ResetValue()
Called when lights are reset or starlight is changed.
ResetCachedValues()
Resets cached values of all four light points. Called by ResetValue().
CheckForOpaqueObjects()
Called by lighting_controller.Initialize(), SetOpacity() or when a turf might change opacity.
Resets the opacity cache and looks for opaque objects. Also responsible for adding and removing borders to space.
*/
#define LIGHTCLAMP(x) ( max(0,min(3,round(x,1))) )
obj/effect/lighting_overlay
//anchored = 1
layer = 9
mouse_opacity = 0
icon = 'icons/effects/ArynLights.dmi'
icon_state = "0000"
atom/var/light/light
turf/var/obj/effect/lighting_overlay/light_overlay
turf/var/lit_value = 0
turf/var/has_opaque = 0
turf/var/is_outside = 0
turf/var/is_border = 0
turf/var/needs_light_update = 0
turf/var/lightpoint/lightNE
turf/var/lightpoint/lightNW
turf/var/lightpoint/lightSE
turf/var/lightpoint/lightSW
turf/var/list/lit_by
atom/New()
. = ..()
if(luminosity || light)
if(!lighting_controller)
initial_lights.Add(src)
else
if(!light)
SetLight(luminosity,luminosity)
else
light.Reset()
if(lighting_controller)
if(opacity)
opacity = 0
SetOpacity(1)
atom/movable/Move()
var/o = opacity
if(o) SetOpacity(0)
. = ..()
if(.)
if(o) SetOpacity(1)
if(light)
light.Reset()
lighting_controller.FlushIconUpdates()
atom/proc/SetLight(intensity, radius)
if(!light) light = new(src)
light.radius = min(radius,15)
light.intensity = intensity
light.Reset()
lighting_controller.FlushIconUpdates()
atom/proc/SetOpacity(o)
if(o == opacity) return
opacity = o
var/turf/T = loc
if(isturf(T))
for(var/light/A in T.lit_by)
A.Reset()
lighting_controller.FlushIconUpdates()
turf/proc/UpdateLight()
if(light_overlay)
light_overlay.icon_state = "[lightSE.max_value()][lightSW.max_value()][lightNW.max_value()][lightNE.max_value()]"
turf/proc/AddLight(light/light)
if(!lit_by) lit_by = list()
lit_by.Add(light)
if(!has_opaque)
var/brightness = light.CalculateBrightness(src)
if(brightness > lit_value)
lit_value = LIGHTCLAMP(brightness)
ResetCachedValues()
for(var/turf/T in range(1,src))
lighting_controller.MarkIconUpdate(T)
turf/proc/RemoveLight(light/light)
lit_by.Remove(light)
ResetValue()
if(!lit_by.len) lit_by = null
turf/proc/ResetValue()
CheckForOpaqueObjects()
if(has_opaque)
lit_value = 0
else
var/max_brightness = (is_outside?(lighting_controller.starlight):0)
for(var/light/light in lit_by)
var/brightness = light.CalculateBrightness(src)
if(brightness > max_brightness)
max_brightness = brightness
lit_value = LIGHTCLAMP(max_brightness)
ResetCachedValues()
for(var/turf/T in range(1,src))
lighting_controller.MarkIconUpdate(T)
turf/proc/ResetCachedValues()
lightNE.cached_value = -1
lightNW.cached_value = -1
lightSE.cached_value = -1
lightSW.cached_value = -1
turf/proc/CheckForOpaqueObjects()
has_opaque = opacity
if(!opacity)
for(var/atom/movable/M in contents)
if(M.opacity)
has_opaque = 1
break
if(is_outside)
for(var/d = 1, d < 16, d*=2)
var/turf/T = get_step(src,d)
if(T && !T.is_outside)
lighting_controller.AddBorder(src)
return
if(is_border) lighting_controller.RemoveBorder(src)
#undef LIGHTCLAMP
@@ -0,0 +1,70 @@
/*
Overview:
This object functions similarly to /tg/'s /light. It is responsible for calculating what turfs are lit by it.
Class Vars:
radius - Set by atom/SetLight(). This stores how far out turfs will be lit up.
intensity - Set by atom/SetLight(). Stores the amount of light generated at the center.
lit_turfs - A list of turfs being lit by this light.
atom - The atom this light is attached to.
Class Procs:
Reset()
This is called whenever the light changes, or the underlying atom changes position.
Off()
A quick way to turn off a light. Removes the light from all turfs in lit_turfs.
CalculateBrightness(turf/T)
Returns the brightness that should be displayed by this light on a specific turf.
*/
light/var/radius = 0
light/var/intensity = 0
light/var/list/lit_turfs
light/var/atom/atom
light/New(atom/atom)
src.atom = atom
light/proc/Reset()
Off()
lit_turfs = list()
if(intensity > 0)
for(var/turf/T in view(atom,radius+1))
T.AddLight(src)
lit_turfs.Add(T)
light/proc/Off()
for(var/turf/T in lit_turfs)
T.RemoveLight(src)
light/proc/CalculateBrightness(turf/T)
var/square = get_square_dist(atom.x,atom.y,atom.z,T.x,T.y,T.z)
if(square > (radius+2)*(radius+2)) return 0
//+2 offset gives an ambient light effect.
var/value = ((radius)/(2*fsqrt(square) + 1)) * intensity - 0.48
/*
lightRadius
---------------- * lightValue - 0.48
2 * distance + 1
The light decreases by twice the distance, starting from the radius.
The + 1 causes the graph to shift to the left one unit so that division by zero is prevented on the source tile.
This is then multiplied by the light value to give the final result.
The -0.48 offset causes the value to be near zero at the radius.
This gives a result which is likely close to the inverse-square law in two dimensions instead of three.
*/
return max(min( value , intensity), 0) //Ensure the value never goes above the maximum light value or below zero.
//return cos(90 * sqrt(square) / max(1,lightRadius)) * lightValue
@@ -0,0 +1,60 @@
/*
Overview:
Perhaps the most cryptic datum in the lighting engine, there are four of these at the corners of every turf.
Any two turfs that share a corner will also have the same lightpoint. Because of the nature of the icons used,
light is shown at the corner of the turf rather than in the middle, necessitating some way to keep track of what
icon state to use.
Class Vars:
x, y, z - The position of the lightpoint. x and y will usually be expressed in terms of 0.5 due to its location on the corner.
NE, NW, SE, SW - The turfs that are in these directions relative to the lightpoint.
cached_value - A cached value of max_value().
Class Procs:
max_value()
The maximum of the light amounts on the four turfs of this light point.
*/
lightpoint
var/x
var/y
var/z
var/turf/NE
var/turf/NW
var/turf/SW
var/turf/SE
var/cached_value = -1
New(x,y,z)
var/turf/T = locate(x+0.5,y+0.5,z)
if(T)
NE = T
T.lightSW = src
T = locate(x-0.5,y+0.5,z)
if(T)
NW = T
T.lightSE = src
T = locate(x-0.5,y-0.5,z)
if(T)
SW = T
T.lightNE = src
T = locate(x+0.5,y-0.5,z)
if(T)
SE = T
T.lightNW = src
proc/max_value()
if(cached_value < 0)
var
valueA = (NW?(NW.lit_value):0)
valueB = (NE?(NE.lit_value):0)
valueC = (SW?(SW.lit_value):0)
valueD = (SE?(SE.lit_value):0)
cached_value = max(valueA,valueB,valueC,valueD)
return cached_value
+22
View File
@@ -0,0 +1,22 @@
/*
Some math procs used by lighting, including ul's fastroot.
*/
var/list/fastroot = list(0, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7)
proc/get_square_dist(Ax,Ay,Az,Bx,By,Bz)
var/X = (Ax - Bx)
var/Y = (Ay - By)
var/Z = (Az - Bz)
return (X * X + Y * Y + Z * Z)
proc/fsqrt(n)
if (n > fastroot.len)
//world << "Adding [n-fastroot.len] entries to root table."
for(var/i = fastroot.len, i <= n, i++)
fastroot += round(sqrt(i))
return fastroot[n + 1]