Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local component = require("component")
- local gpu = component.gpu
- local event = require("event")
- local keyboard = require("keyboard")
- local math = require("math")
- -- Set to Tier 3 resolution
- local width, height = 160, 50
- gpu.setResolution(width, height)
- -- Set to 32-bit color mode
- gpu.setDepth(gpu.maxDepth())
- -- Create double buffers
- local buffers = {gpu.allocateBuffer(width, height), gpu.allocateBuffer(width, height)}
- local currentBuffer = 1
- -- Scene objects
- local mirroredSphere = {center = {x = 0, y = 0, z = 0}, radius = 15, color = 0xCCCCCC}
- local purpleSphere = {center = {x = 0, y = -10, z = 25}, radius = 7, color = 0x800080}
- local background = {color = 0x87CEFA} -- Light blue background
- -- Camera properties
- local camera = {
- x = 0,
- y = 0,
- z = -50,
- angleX = 0,
- angleY = 0
- }
- -- 3D vector operations
- local function vec3(x, y, z) return {x = x, y = y, z = z} end
- local function add(v1, v2) return vec3(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z) end
- local function sub(v1, v2) return vec3(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z) end
- local function mul(v, s) return vec3(v.x * s, v.y * s, v.z * s) end
- local function dot(v1, v2) return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z end
- local function length(v) return math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z) end
- local function normalize(v)
- local len = length(v)
- return vec3(v.x / len, v.y / len, v.z / len)
- end
- -- Ray-sphere intersection
- local function intersectSphere(origin, dir, sphere)
- local oc = sub(origin, sphere.center)
- local a = dot(dir, dir)
- local b = 2 * dot(oc, dir)
- local c = dot(oc, oc) - sphere.radius * sphere.radius
- local discriminant = b * b - 4 * a * c
- if discriminant < 0 then return nil end
- local t = (-b - math.sqrt(discriminant)) / (2 * a)
- if t < 0 then return nil end
- return t
- end
- -- 3D to 2D projection
- local function project(point)
- local rotX = {
- {1, 0, 0},
- {0, math.cos(camera.angleX), -math.sin(camera.angleX)},
- {0, math.sin(camera.angleX), math.cos(camera.angleX)}
- }
- local rotY = {
- {math.cos(camera.angleY), 0, math.sin(camera.angleY)},
- {0, 1, 0},
- {-math.sin(camera.angleY), 0, math.cos(camera.angleY)}
- }
- local function matMul(m, v)
- return vec3(
- m[1][1]*v.x + m[1][2]*v.y + m[1][3]*v.z,
- m[2][1]*v.x + m[2][2]*v.y + m[2][3]*v.z,
- m[3][1]*v.x + m[3][2]*v.y + m[3][3]*v.z
- )
- end
- local rotated = matMul(rotY, matMul(rotX, sub(point, camera)))
- local scale = 200 / (rotated.z + 200)
- return width / 2 + rotated.x * scale, height / 2 - rotated.y * scale
- end
- -- Render frame
- local function renderFrame(time)
- -- Rotate purple sphere around the mirrored sphere horizontally
- local angle = time * math.pi / 2.5 -- Complete rotation every 5 seconds
- purpleSphere.center.x = math.cos(angle) * 25
- purpleSphere.center.z = math.sin(angle) * 25
- gpu.setActiveBuffer(buffers[currentBuffer])
- -- Draw background
- gpu.setBackground(background.color)
- gpu.fill(1, 1, width, height, " ")
- -- Render scene
- for y = 1, height do
- for x = 1, width do
- local dir = normalize(vec3(x - width/2, height/2 - y, 100))
- local color = background.color
- local t1 = intersectSphere(camera, dir, mirroredSphere)
- if t1 then
- local hitPoint = add(camera, mul(dir, t1))
- local normal = normalize(sub(hitPoint, mirroredSphere.center))
- local reflectDir = sub(dir, mul(normal, 2 * dot(dir, normal)))
- local t2 = intersectSphere(hitPoint, reflectDir, purpleSphere)
- if t2 then
- color = purpleSphere.color
- else
- color = mirroredSphere.color
- end
- else
- local t2 = intersectSphere(camera, dir, purpleSphere)
- if t2 then
- color = purpleSphere.color
- end
- end
- gpu.setBackground(color)
- gpu.set(x, y, " ")
- end
- end
- end
- -- Draw buffer to screen
- local function drawBuffer()
- gpu.bitblt(0, 1, 1, width, height, buffers[currentBuffer], 1, 1)
- end
- -- Handle camera rotation
- local function handleInput()
- if keyboard.isKeyDown(keyboard.keys.up) then
- camera.angleX = camera.angleX - 0.05
- elseif keyboard.isKeyDown(keyboard.keys.down) then
- camera.angleX = camera.angleX + 0.05
- elseif keyboard.isKeyDown(keyboard.keys.left) then
- camera.angleY = camera.angleY - 0.05
- elseif keyboard.isKeyDown(keyboard.keys.right) then
- camera.angleY = camera.angleY + 0.05
- end
- end
- -- Animation loop
- local startTime = os.clock()
- while true do
- local currentTime = os.clock() - startTime
- handleInput()
- renderFrame(currentTime)
- drawBuffer()
- currentBuffer = 3 - currentBuffer -- Switch buffers
- if keyboard.isKeyDown(keyboard.keys.q) then break end
- os.sleep(0.01) -- Small delay to prevent excessive CPU usage
- end
- -- Clean up
- gpu.freeBuffer(buffers[1])
- gpu.freeBuffer(buffers[2])
- gpu.setActiveBuffer(0)
- gpu.setBackground(0x000000)
- gpu.setForeground(0xFFFFFF)
- print("Animation complete.")
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement