on
Intro to my Voxel Engine
I don’t really have a name for this project, so I have just been calling it “Voxel Engine” …
What is it? An application that renders cubic voxel, creates terrain through procedural generation and is controlled through Lua scripting. Well that’s the goal :P
Project repo is located here
Voxel Engine is made using my opengl library SGL
Here’s what it can do so far:
With a little shading:
So not super impressive visually, though I think it’s pretty neat!
I’m still working on the under the hood stuff (mainly chunk managment).
And the script that generates the world:
-- main.lua
-- Voxel Engine Script
-- @author Natesh Narain
package.path = '?.lua;' .. package.path
require("player")
-- -------------------------------------------------------------------------
-- Main
-- -------------------------------------------------------------------------
function main()
--
engine = Engine.getEngine()
-- get the camera
camera = engine:getCamera()
-- create the opengl window and initial context
engine:createWindow("Voxel Engine Test", 1080, 720)
-- register the window for UI callbacks
window = engine:getWindow()
registerUICallbacks(window)
-- load assets
engine:loadAtlas("assets/atlas.png")
-- create a chunk manager for the terrain
local terrain = ChunkManager(32, 32, 32, 16, 1, "atlas")
generateTerrain(terrain, 7)
-- add the chunk managers to the engine
engine:addManager(terrain)
-- create a timer to get the delta frame time
timer = Timer()
-- create the player
player = Player(camera)
-- Window Event Loop: loop while window hasn't been signaled to close
while not window:shouldClose() do
-- poll user events
window:pollEvents()
-- get the delta time
delta = timer:getElapsed()
-- update game logic
update(delta)
-- render
engine:render()
--
window:swapBuffers()
end
end
function update(delta)
engine:updateCameraView(delta)
updatePlayer(delta)
end
-- update the cameras movement on the xz plane
function updatePlayer(delta)
-- update forward \ backward movement
if window:isKeyPressed(Window.Key.W) then
player:advanceForward(delta)
elseif window:isKeyPressed(Window.Key.S) then
player:advanceForward(-delta)
end
-- update right \ left movement
if window:isKeyPressed(Window.Key.A) then
player:advanceRight(-delta)
elseif window:isKeyPressed(Window.Key.D) then
player:advanceRight(delta)
end
end
-- use a height map generating using a Noise class the create the terrain
function generateTerrain(terrain, octaves)
local x = terrain:getBlockX()
local z = terrain:getBlockZ()
local heightMap = Noise(x, z)
heightMap:generate(octaves)
for i = 0,x-1 do
for k = 0,z-1 do
local h = math.floor(heightMap:at(i, k) * 20)
for j = 0,h do
if j == h then
terrain:setBlock(i, j, k, 2)
elseif j == h-1 then
terrain:setBlock(i, j, k, 4)
else
terrain:setBlock(i, j, k, 3)
end
end
end
end
end
function onKeyEvent(keycode)
end
function onMouseMove(x, y)
end
-- run main
main()
-- Player.lua
Player = {}
Player.__index = Player
setmetatable(Player, {
__call = function(cls, ...)
local self = setmetatable({}, Player)
self:_init(...)
return self
end
})
function Player:_init(camera)
self.camera = camera
self.speed = 20
end
function Player:advanceForward(delta)
self.camera.position = self.camera.position + (self.camera.direction * self.speed * delta)
end
function Player:advanceRight(delta)
self.camera.position = self.camera.position + (self.camera.right * self.speed * delta)
end
The idea here is that a chunk manager is a grid of blocks that the user has control over, to make a height map terrain for example. Eventually there will be multiple chunk managers interacting together. So one manager can be terrain and another can be a building or a character.
TODO
- explore an octree implementation that can speed up chunk culling
- implement voxel lighting
- get blocks selected by the user