Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local moduleName = ({...})[1]
- do
- local bit32 = bit32
- if not bit32 then
- if not pcall(function() bit32 = require("bit32") end) then
- bit32 = require(moduleName..".bit32")
- end
- end
- package.loaded["bit32"] = bit32
- end
- local voxelPolygonizer = require(moduleName..".voxelPolygonizer")
- local Polygonise = voxelPolygonizer.Polygonise
- local TextureTriangle = love.graphics.newImage("Lua3D/Textures/TextureTriangle.png")
- ---------------------------
- -- Smooth Terrain object --
- ---------------------------
- local Terrain = {}
- Terrain.__index = Terrain
- local chunkSize = 8
- -- Creates a new terrain object.
- function Terrain.new()
- local self = setmetatable({}, Terrain)
- self.Materials = {}
- self.MaterialData = {}
- self.OccupancyData = setmetatable({}, {__index = function()
- return setmetatable({}, {__index = function()
- return setmetatable({}, {__index = function() return 0 end})
- end})
- end})
- self.DrawingMeshes = {}
- self.MeshesToReset = {}
- return self
- end
- -- Regenerates the drawing mesh.
- function Terrain:RegenerateChunkMesh(xChunk, yChunk, zChunk, detail)
- local terrainTriangles = {}
- -- Generate the terrainTriangles table
- local triangles, grid = {}, {val = {}}
- if detail <= 1 then
- for y = yChunk*chunkSize, (yChunk + 1)*chunkSize do
- for x = xChunk*chunkSize, (xChunk + 1)*chunkSize do
- for z = zChunk*chunkSize, (zChunk + 1)*chunkSize do
- grid.p = {
- {x = 0 + x, y = 0 + y, z = 0 + z},
- {x = 1 + x, y = 0 + y, z = 0 + z},
- {x = 1 + x, y = 0 + y, z = 1 + z},
- {x = 0 + x, y = 0 + y, z = 1 + z},
- {x = 0 + x, y = 1 + y, z = 0 + z},
- {x = 1 + x, y = 1 + y, z = 0 + z},
- {x = 1 + x, y = 1 + y, z = 1 + z},
- {x = 0 + x, y = 1 + y, z = 1 + z},
- }
- for vertex = 0, 7 do
- grid.p[vertex] = grid.p[vertex + 1]
- grid.val[vertex] = self.OccupancyData[grid.p[vertex].y][grid.p[vertex].x][grid.p[vertex].z]
- end
- for triangleId = 0, Polygonise(grid, detail, triangles) do
- terrainTriangles[#terrainTriangles + 1] = triangles[triangleId]
- end
- end
- end
- end
- else
- detail = math.ceil(detail)
- for y = yChunk*chunkSize/detail, (yChunk + 1)*chunkSize/detail do
- for x = xChunk*chunkSize/detail, (xChunk + 1)*chunkSize/detail do
- for z = zChunk*chunkSize/detail, (zChunk + 1)*chunkSize/detail do
- grid.p = {
- {x = 0 + x, y = 0 + y, z = 0 + z},
- {x = 1 + x, y = 0 + y, z = 0 + z},
- {x = 1 + x, y = 0 + y, z = 1 + z},
- {x = 0 + x, y = 0 + y, z = 1 + z},
- {x = 0 + x, y = 1 + y, z = 0 + z},
- {x = 1 + x, y = 1 + y, z = 0 + z},
- {x = 1 + x, y = 1 + y, z = 1 + z},
- {x = 0 + x, y = 1 + y, z = 1 + z},
- }
- for a = 1, 8 do
- grid.p[a].x = grid.p[a].x*detail
- grid.p[a].y = grid.p[a].y*detail
- grid.p[a].z = grid.p[a].z*detail
- end
- for vertex = 0, 7 do
- grid.p[vertex] = grid.p[vertex + 1]
- grid.val[vertex] = self.OccupancyData[grid.p[vertex].y][grid.p[vertex].x][grid.p[vertex].z]
- end
- for triangleId = 0, Polygonise(grid, 1, triangles) do
- terrainTriangles[#terrainTriangles + 1] = triangles[triangleId]
- end
- end
- end
- end
- end
- local white = Color.new(255, 255, 255)
- local finalTriangles = {}
- for key, value in pairs(terrainTriangles) do
- local vrt1 = value.p[0]
- local vrt2 = value.p[1]
- local vrt3 = value.p[2]
- if vrt1 and vrt2 and vrt3 then
- finalTriangles[#finalTriangles + 1] = {
- Vector3.new(vrt3.x, vrt3.y, vrt3.z),
- Vector3.new(vrt2.x, vrt2.y, vrt2.z),
- Vector3.new(vrt1.x, vrt1.y, vrt1.z),
- white,
- TextureTriangle
- }
- end
- end
- -- Find duplicates
- local duplicateTriangles = {}
- local nonDuplicateTriangles = {}
- for key, value in pairs(finalTriangles) do
- local duplicateTriangle = false
- for key2, value2 in pairs(nonDuplicateTriangles) do
- if value2[1] == value[1] and value2[2] == value[2] and value2[3] == value[3] and (key ~= key2) then
- duplicateTriangles[#duplicateTriangles + 1] = key
- duplicateTriangle = true
- break
- end
- end
- if not duplicateTriangle then
- nonDuplicateTriangles[#nonDuplicateTriangles + 1] = value
- end
- end
- for key, value in pairs(duplicateTriangles) do
- table.remove(finalTriangles, value - (key - 1))
- end
- -- Add required parent tables
- if not self.DrawingMeshes[xChunk] then
- self.DrawingMeshes[xChunk] = {}
- end
- if not self.DrawingMeshes[xChunk][yChunk] then
- self.DrawingMeshes[xChunk][yChunk] = {}
- end
- if not self.DrawingMeshes[xChunk][yChunk][zChunk] then
- self.DrawingMeshes[xChunk][yChunk][zChunk] = {}
- end
- self.DrawingMeshes[xChunk][yChunk][zChunk][detail] = finalTriangles
- end
- -- Draws the mesh
- function Terrain:DrawChunk(renderer, xChunk, yChunk, zChunk, detail)
- if detail > 1 then
- detail = math.ceil(detail)
- end
- if not self.DrawingMeshes[xChunk] then
- self:RegenerateChunkMesh(xChunk, yChunk, zChunk, detail)
- end
- if not self.DrawingMeshes[xChunk][yChunk] then
- self:RegenerateChunkMesh(xChunk, yChunk, zChunk, detail)
- end
- if not self.DrawingMeshes[xChunk][yChunk][zChunk] then
- self:RegenerateChunkMesh(xChunk, yChunk, zChunk, detail)
- end
- if not self.DrawingMeshes[xChunk][yChunk][zChunk][detail] then
- self:RegenerateChunkMesh(xChunk, yChunk, zChunk, detail)
- end
- for key, value in pairs(self.DrawingMeshes[xChunk][yChunk][zChunk][detail]) do
- renderer:DrawTriangle(
- value[1],
- value[2],
- value[3],
- value[4],
- value[5]
- )
- end
- end
- -- Draws the terrain.
- function Terrain:Draw(renderer)
- local range = 2
- local posX = math.floor(renderer.CameraPositionX/chunkSize)
- local posY = math.floor(renderer.CameraPositionY/chunkSize)
- local posZ = math.floor(renderer.CameraPositionZ/chunkSize)
- if #self.MeshesToReset > 0 then
- for key, value in pairs(self.MeshesToReset) do
- self.DrawingMeshes[value.x][value.y][value.z] = nil
- end
- self.MeshesToReset = {}
- collectgarbage()
- end
- for x = posX - range, posX + range do
- for y = posY - range, posY + range do
- for z = posZ - range, posZ + range do
- self:DrawChunk(renderer, x, y, z, 2^(math.max(math.abs(x - posX), math.abs(y - posY), math.abs(z - posZ))*.5 - .5))
- end
- end
- end
- end
- return Terrain
Add Comment
Please, Sign In to add comment