3D renderer

cool thingy

by kasicakim

Author Avatar

1st we need a layout of pixles, all pixles that are on, pixle names, campositionm screenposition and FOV

local X = 70
local Y = 70

local pixles = {}
local pixlenames = {}
local whitepixls = {}

local CamPosition = Vector3.zero
local ScreenPosition = 5
--screen position is 5 bc thats its z position, it doesnt need x or y bc it goes infinitevly far into those directions
local FOV = 80


for x=1, X do
	for y=1, Y do
		local pixle = Instance.new("Part")
		pixle.Size = Vector3.new(1/10, 1/10)
		pixle.Color = Color3.new()
		pixle.Position = Vector3.new(x/10, y/10, 100)
		pixle.Name = "X"..tostring(x-X/2).."Y"..tostring(y-Y/2)
		pixle.Anchored = true
		pixle.Parent = workspace
		table.insert(pixles, pixle)
		table.insert(pixlenames, pixle.Name)
	end
	wait()
end

Other functions we will need are: FindPixle, AddVertex, AddEdge, AddObject.

Vertexes are just positions used for 3d space

Edges are tables that have 2 values that contain the place in the tbl where a vertex is

Object has its vertexes, edges and its color, the vertex table of the object are just positions in the table Vertexes where a vertex is, same of edges.

local Vertexes = {}
local Edges = {}
local Objects = {}

local function AddVertex(v, ad)
	table.insert(Vertexes, {v, ad})
end

local function AddEdge(ad1, ad2)
	table.insert(Edges, {ad1, ad2})
end

local function AddObject(verts, edgs, color)
	table.insert(Objects, {verts, edgs, color})
end

We now have our layout done, next thing we need to do is calculate the position of the pixle that needs to be lighten up. For this we will use a formula (idk how to explain it :p).

local function GetProjected(pos, Z)
	return math.round((pos*FOV)/(FOV+Z))
end

local function CalculatePosition(v)
	local x = GetProjected(v.X, v.Z)
	local y = GetProjected(v.Y, v.Z)
	
	return Vector2.new(x, y)
end

Now for the edges we will use a simple DrawLine function that takes 2 Vector2s on the screen and a color:

local function LightPixle(pos, color)
	pcall(function()
		FindPixle(pos).Color = color
		table.insert(whitepixls, pos)
	end)
end

local function LightPixleWithProjected(pos, color)
	local v = CalculatePosition(pos)
	LightPixle(v, color)
end

local function DrawLine(pos1, pos2, color)
	local poss = {}

	local dy = math.abs(pos1.Y - pos2.Y)
	local dx = math.abs(pos1.X - pos2.X)

	if dy >= dx then
		local currentY = pos1.Y
		local ddy = 0
		if pos1.Y > pos2.Y then
			ddy = -1
		else
			ddy = 1
		end
		while currentY ~= pos2.Y do
			local currentX = math.round(pos2.X + ((pos1.X - pos2.X) / (pos1.Y - pos2.Y)) * (currentY - pos2.Y))
			table.insert(poss, Vector2.new(currentX, currentY))
			currentY = currentY + ddy
		end
	else
		local currentX = pos1.X
		local ddx = 0
		if pos1.X > pos2.X then
			ddx = -1
		else
			ddx = 1
		end
		while currentX ~= pos2.X do
			local currentY = math.round(pos2.Y + ((pos1.Y - pos2.Y) / (pos1.X - pos2.X)) * (currentX - pos2.X))
			table.insert(poss, Vector2.new(currentX, currentY))
			currentX = currentX + ddx
		end
	end
	for i=1, #poss do
		LightPixle(poss[i], color)
	end
end

Now we just need to project the object using these functions:

local function ProjectObject(object)
	local verts = object[1]
	local edges = object[2]
	local color = object[3]
	
	for x=1, #verts do
		local vertex = Vertexes[verts[x]]
		LightPixleWithProjected(vertex[1], color)
	end
	for x=1, #edges do
		local edge = Edges[edges[x]]
		local e1 = edge[1]
		local e2 = edge[2]
		local pos1 = CalculatePosition(Vertexes[e1][1])
		local pos2 = CalculatePosition(Vertexes[e2][1])
		DrawLine(pos1, pos2, color)
	end
end

You can have some fun and add rotation (rly hard to explain go onto a wiki about matrix rotation to find out more).

local function ClearPixles()
	for x=1, #whitepixls do
		LightPixle(whitepixls[x], Color3.new())
	end
	table.clear(whitepixls)
end


local function RotateObjX(obj, r, poss)
	for x=1, #obj[1] do
		local pos = Vertexes[obj[1][x]][1]-poss
		local newpos = Vector3.new(pos.X, pos.Y*math.cos(math.rad(r))+pos.Z*math.sin(math.rad(r)),pos.Y*-math.sin(math.rad(r))+pos.Z*math.cos(math.rad(r)))+poss
		Vertexes[obj[1][x]][1] = newpos
	end
end

local function RotateObjY(obj, r, poss)
	local s = poss
	for x=1, #obj[1] do
		local pos = Vertexes[obj[1][x]][1]-poss
		local newpos = Vector3.new(pos.X*math.cos(math.rad(r))+pos.Z*math.sin(math.rad(r)),pos.y,pos.X*-math.sin(math.rad(r))+pos.Z*math.cos(math.rad(r)))+poss
		Vertexes[obj[1][x]][1] = newpos
	end
end

local function RotateObjZ(obj, r, poss)
	for x=1, #obj[1] do
		local pos = Vertexes[obj[1][x]][1]-poss
		local newpos = Vector3.new(pos.X*math.cos(math.rad(r))+pos.Y*math.sin(math.rad(r)),pos.X*-math.sin(math.rad(r))+pos.Y*math.cos(math.rad(r)), pos.Z)+poss
		Vertexes[obj[1][x]][1] = newpos
	end
end

Lets make a plane and project it:

AddVertex(Vector3.new(10, 10, 40), 1)
AddVertex(Vector3.new(-10, 10, 40), 2)
AddVertex(Vector3.new(10, -10, 40), 3)
AddVertex(Vector3.new(-10, -10, 40), 4)

AddEdge(1, 2)
AddEdge(1, 3)
AddEdge(4, 2)
AddEdge(4, 3)
AddEdge(4, 1)

AddObject({1, 2, 3, 4}, {1, 2, 3, 4, 5}, Color3.new(1, 0, 0))

ProjectObject(Objects[1])

You can also add rotation with rotate functions:

while wait() do
	ProjectObject(Objects[1])
	wait(.05)
	ClearPixles()
	RotateObjY(Objects[1], 5, Vector3.new(0, 0, 40))
	wait()
	RotateObjX(Objects[1], 5, Vector3.new(0, 0, 40))
end

Go and have fun or smth, this script isnt rly good for a lot of objects bc roblox is slow :p. It could be faster if you dont use pixles and add parts into the workspace. go make smth with this.

View in-game to comment, award, and more!