Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local sin = math.sin
- local cos = math.cos
- local tan = math.tan
- local abs = math.abs
- local min = math.min
- local max = math.max
- local floor = math.floor
- local sqrt = math.sqrt
- local clock = os.clock
- local pi = math.pi
- -- Threshold values for RGB to RGBI conversion.
- R_THRESHOLD = 0.5
- G_THRESHOLD = 0.5
- B_THRESHOLD = 0.5
- I_THRESHOLD = 0.5
- -- Conversion of 4-bit RGBI to CC colors.
- local palette = {
- colors.black,
- colors.gray,
- colors.blue,
- colors.blue,
- colors.green,
- colors.lime,
- colors.cyan,
- colors.lightBlue,
- colors.red,
- colors.red,
- colors.purple,
- colors.magenta,
- colors.brown,
- colors.yellow,
- colors.lightGray,
- colors.white,
- }
- local function clamp(a, m, n)
- return (a > n) and n or (a < m and m or a)
- end
- -- Convert RGB to 4-bit RGBI index.
- local function rgbtorgbi(r, g, b)
- r = clamp(r, 0, 1)
- g = clamp(g, 0, 1)
- b = clamp(b, 0, 1)
- local R = r > R_THRESHOLD and 1 or 0
- local G = g > G_THRESHOLD and 1 or 0
- local B = b > B_THRESHOLD and 1 or 0
- local I = (r + g + b)/3 > I_THRESHOLD and 1 or 0
- return R * 8 + G * 4 + B * 2 + I
- end
- --[[ Vector functions ]]--
- local function length2(x, y)
- return sqrt(x*x + y*y)
- end
- local function length3(x, y, z)
- return sqrt(x*x + y*y + z*z)
- end
- local function normalize3(x, y, z)
- local len = length3(x, y, z)
- return x/len, y/len, z/len
- end
- local function vec3add(x, y, z, a, b, c)
- return x + a, y + b, z + c
- end
- local function vec3sub(x, y, z, a, b, c)
- return x - a, y - b, z - c
- end
- local function vec3mulscalar(x, y, z, a)
- return x * a, y * a, z * a
- end
- local function vec3abs(x, y, z)
- return abs(x), abs(y), abs(z)
- end
- --[[ Matrix functions ]]
- local function mat2mulvec2(m, x, y)
- return m[1] * x + m[2] * y,
- m[3] * x + m[4] * y
- end
- local function mat3mulvec3(m, x, y, z)
- return m[1] * x + m[2] * y + m[3] * z,
- m[4] * x + m[5] * y + m[6] * z,
- m[7] * x + m[8] * y + m[9] * z
- end
- local function getRotMat2(a)
- return { cos(a), -sin(a), sin(a), cos(a) }
- end
- local function getRotMat3x(a)
- return { 1, 0, 0,
- 0, cos(a), -sin(a),
- 0, sin(a), cos(a) }
- end
- local function getRotMat3y(a)
- return { cos(a), 0, sin(a),
- 0, 1, 0,
- -sin(a), 0, cos(a) }
- end
- local function getRotMat3z(a)
- return { cos(a), -sin(a), 0,
- sin(a), cos(a), 0,
- 0, 0, 1 }
- end
- local w, h = term.getSize()
- --[[ Distance functions ]]--
- local function sphere(x, y, z, r)
- return length3(x, y, z) - r
- end
- local function box(x, y, z, a, b, c)
- return max(max(abs(x) - a, abs(y) - b), abs(z) - c)
- end
- -- Place all the models.
- local function map(x, y, z)
- local d1, r1, g1, b1 = box(x, y + 1.5, z, 5, 1, 5), 1, 0, 0
- local d2, r2, g2, b2 = box(x, y, z, 1, 2, 1), 0, 0, 1
- local d, r, g, b = d1, r1, g1, b1
- if d2 < d then d, r, g, b = d2, r2, g2, b2 end
- return d, r, g, b
- end
- local EPSILON = 0.001
- local MAX_DIST = 20
- local lx, ly, lz = 0, 0, 0
- local function pixel(x, y)
- -- Fix stretching.
- local u, v = x/w, y/h
- u = u * w/h*2/3
- u = u - w/h*2/3/2
- v = (1 - v) - 0.5
- lx, ly, lz = sin(clock())*4, 4, cos(clock())*4
- -- Rotation
- local pitch, yaw, roll = 0.8, pi/4, 0
- local rox, roy, roz = 0, 0, -5
- rox, roy, roz = mat3mulvec3(getRotMat3x(pitch), rox, roy, roz)
- rox, roy, roz = mat3mulvec3(getRotMat3y(yaw ), rox, roy, roz)
- rox, roy, roz = mat3mulvec3(getRotMat3z(roll ), rox, roy, roz)
- local rdx, rdy, rdz = normalize3(u, v, 1)
- rdx, rdy, rdz = mat3mulvec3(getRotMat3x(pitch), rdx, rdy, rdz)
- rdx, rdy, rdz = mat3mulvec3(getRotMat3y(yaw ), rdx, rdy, rdz)
- rdx, rdy, rdz = mat3mulvec3(getRotMat3z(roll ), rdx, rdy, rdz)
- local r, g, b
- local hit = false
- -- Raymarching
- local l = 0
- for i = 1, 100 do
- local rx, ry, rz = vec3add(rox, roy, roz, vec3mulscalar(rdx, rdy, rdz, l))
- local d
- d, r, g, b = map(rx, ry, rz)
- if d <= EPSILON then
- rox, roy, roz = rx, ry, rz
- hit = true
- break
- end
- if l > MAX_DIST then
- return 0, 0, 0
- end
- l = l + d
- end
- if not hit then return 0, 0, 0 end
- l = 0.1
- rdx, rdy, rdz = normalize3(vec3sub(lx, ly, lz, rox, roy, roz))
- for i = 1, 40 do
- local rx, ry, rz = vec3add(rox, roy, roz, vec3mulscalar(rdx, rdy, rdz, l))
- local d, r, g, b = map(rx, ry, rz)
- local ldist = length3(vec3sub(lx, ly, lz, rx, ry, rz))
- if d <= EPSILON then
- return 0, 1, 0
- end
- if ldist <= d then
- break
- end
- l = l + min(d, ldist)
- end
- return r, g, b
- end
- term.clear()
- local scp = term.setCursorPos
- local sbc = term.setBackgroundColor
- local tw = term.write
- -- Draw the pixels.
- while true do
- for j = 1, h do
- for i = 1, w do
- scp(i, j)
- sbc(palette[rgbtorgbi(pixel(i - 1, j - 1)) + 1])
- tw(" ")
- end
- end
- sleep(0)
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement