Tag365

smooth terrain init.lua

Feb 22nd, 2016
144
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 6.18 KB | None | 0 0
  1. local moduleName = ({...})[1]
  2. do
  3.     local bit32 = bit32
  4.     if not bit32 then
  5.         if not pcall(function() bit32 = require("bit32") end) then
  6.             bit32 = require(moduleName..".bit32")
  7.         end
  8.     end
  9.     package.loaded["bit32"] = bit32
  10. end
  11. local voxelPolygonizer = require(moduleName..".voxelPolygonizer")
  12. local Polygonise = voxelPolygonizer.Polygonise
  13.  
  14. local TextureTriangle = love.graphics.newImage("Lua3D/Textures/TextureTriangle.png")
  15.  
  16. ---------------------------
  17. -- Smooth Terrain object --
  18. ---------------------------
  19. local Terrain = {}
  20. Terrain.__index = Terrain
  21.  
  22. local chunkSize = 8
  23.  
  24. -- Creates a new terrain object.
  25. function Terrain.new()
  26.     local self = setmetatable({}, Terrain)
  27.    
  28.     self.Materials = {}
  29.     self.MaterialData = {}
  30.     self.OccupancyData = setmetatable({}, {__index = function()
  31.         return setmetatable({}, {__index = function()
  32.             return setmetatable({}, {__index = function() return 0 end})
  33.         end})
  34.     end})
  35.    
  36.     self.DrawingMeshes = {}
  37.     self.MeshesToReset = {}
  38.    
  39.     return self
  40. end
  41.  
  42. -- Regenerates the drawing mesh.
  43. function Terrain:RegenerateChunkMesh(xChunk, yChunk, zChunk, detail)
  44.     local terrainTriangles = {}
  45.  
  46.     -- Generate the terrainTriangles table
  47.     local triangles, grid = {}, {val = {}}
  48.     if detail <= 1 then
  49.         for y = yChunk*chunkSize, (yChunk + 1)*chunkSize do
  50.             for x = xChunk*chunkSize, (xChunk + 1)*chunkSize do
  51.                 for z = zChunk*chunkSize, (zChunk + 1)*chunkSize do
  52.                     grid.p = {
  53.                         {x = 0 + x, y = 0 + y, z = 0 + z},
  54.                         {x = 1 + x, y = 0 + y, z = 0 + z},
  55.                         {x = 1 + x, y = 0 + y, z = 1 + z},
  56.                         {x = 0 + x, y = 0 + y, z = 1 + z},
  57.                         {x = 0 + x, y = 1 + y, z = 0 + z},
  58.                         {x = 1 + x, y = 1 + y, z = 0 + z},
  59.                         {x = 1 + x, y = 1 + y, z = 1 + z},
  60.                         {x = 0 + x, y = 1 + y, z = 1 + z},
  61.                     }
  62.                     for vertex = 0, 7 do
  63.                         grid.p[vertex] = grid.p[vertex + 1]
  64.                         grid.val[vertex] = self.OccupancyData[grid.p[vertex].y][grid.p[vertex].x][grid.p[vertex].z]
  65.                     end
  66.                     for triangleId = 0, Polygonise(grid, detail, triangles) do
  67.                         terrainTriangles[#terrainTriangles + 1] = triangles[triangleId]
  68.                     end
  69.                 end
  70.             end
  71.         end
  72.     else
  73.         detail = math.ceil(detail)
  74.         for y = yChunk*chunkSize/detail, (yChunk + 1)*chunkSize/detail do
  75.             for x = xChunk*chunkSize/detail, (xChunk + 1)*chunkSize/detail do
  76.                 for z = zChunk*chunkSize/detail, (zChunk + 1)*chunkSize/detail do
  77.                     grid.p = {
  78.                         {x = 0 + x, y = 0 + y, z = 0 + z},
  79.                         {x = 1 + x, y = 0 + y, z = 0 + z},
  80.                         {x = 1 + x, y = 0 + y, z = 1 + z},
  81.                         {x = 0 + x, y = 0 + y, z = 1 + z},
  82.                         {x = 0 + x, y = 1 + y, z = 0 + z},
  83.                         {x = 1 + x, y = 1 + y, z = 0 + z},
  84.                         {x = 1 + x, y = 1 + y, z = 1 + z},
  85.                         {x = 0 + x, y = 1 + y, z = 1 + z},
  86.                     }
  87.                     for a = 1, 8 do
  88.                         grid.p[a].x = grid.p[a].x*detail
  89.                         grid.p[a].y = grid.p[a].y*detail
  90.                         grid.p[a].z = grid.p[a].z*detail
  91.                     end
  92.                     for vertex = 0, 7 do
  93.                         grid.p[vertex] = grid.p[vertex + 1]
  94.                         grid.val[vertex] = self.OccupancyData[grid.p[vertex].y][grid.p[vertex].x][grid.p[vertex].z]
  95.                     end
  96.                     for triangleId = 0, Polygonise(grid, 1, triangles) do
  97.                         terrainTriangles[#terrainTriangles + 1] = triangles[triangleId]
  98.                     end
  99.                 end
  100.             end
  101.         end
  102.     end
  103.  
  104.     local white = Color.new(255, 255, 255)
  105.     local finalTriangles = {}
  106.     for key, value in pairs(terrainTriangles) do
  107.         local vrt1 = value.p[0]
  108.         local vrt2 = value.p[1]
  109.         local vrt3 = value.p[2]
  110.         if vrt1 and vrt2 and vrt3 then
  111.             finalTriangles[#finalTriangles + 1] = {
  112.                 Vector3.new(vrt3.x, vrt3.y, vrt3.z),
  113.                 Vector3.new(vrt2.x, vrt2.y, vrt2.z),
  114.                 Vector3.new(vrt1.x, vrt1.y, vrt1.z),
  115.                 white,
  116.                 TextureTriangle
  117.             }
  118.         end
  119.     end
  120.    
  121.     -- Find duplicates
  122.     local duplicateTriangles = {}
  123.     local nonDuplicateTriangles = {}
  124.     for key, value in pairs(finalTriangles) do
  125.         local duplicateTriangle = false
  126.         for key2, value2 in pairs(nonDuplicateTriangles) do
  127.             if value2[1] == value[1] and value2[2] == value[2] and value2[3] == value[3] and (key ~= key2) then
  128.                 duplicateTriangles[#duplicateTriangles + 1] = key
  129.                 duplicateTriangle = true
  130.                 break
  131.             end
  132.         end
  133.         if not duplicateTriangle then
  134.             nonDuplicateTriangles[#nonDuplicateTriangles + 1] = value
  135.         end
  136.     end
  137.    
  138.     for key, value in pairs(duplicateTriangles) do
  139.         table.remove(finalTriangles, value - (key - 1))
  140.     end
  141.    
  142.     -- Add required parent tables
  143.     if not self.DrawingMeshes[xChunk] then
  144.         self.DrawingMeshes[xChunk] = {}
  145.     end
  146.     if not self.DrawingMeshes[xChunk][yChunk] then
  147.         self.DrawingMeshes[xChunk][yChunk] = {}
  148.     end
  149.     if not self.DrawingMeshes[xChunk][yChunk][zChunk] then
  150.         self.DrawingMeshes[xChunk][yChunk][zChunk] = {}
  151.     end
  152.     self.DrawingMeshes[xChunk][yChunk][zChunk][detail] = finalTriangles
  153. end
  154.  
  155. -- Draws the mesh
  156. function Terrain:DrawChunk(renderer, xChunk, yChunk, zChunk, detail)
  157.     if detail > 1 then
  158.         detail = math.ceil(detail)
  159.     end
  160.     if not self.DrawingMeshes[xChunk] then
  161.         self:RegenerateChunkMesh(xChunk, yChunk, zChunk, detail)
  162.     end
  163.     if not self.DrawingMeshes[xChunk][yChunk] then
  164.         self:RegenerateChunkMesh(xChunk, yChunk, zChunk, detail)
  165.     end
  166.     if not self.DrawingMeshes[xChunk][yChunk][zChunk] then
  167.         self:RegenerateChunkMesh(xChunk, yChunk, zChunk, detail)
  168.     end
  169.     if not self.DrawingMeshes[xChunk][yChunk][zChunk][detail] then
  170.         self:RegenerateChunkMesh(xChunk, yChunk, zChunk, detail)
  171.     end
  172.     for key, value in pairs(self.DrawingMeshes[xChunk][yChunk][zChunk][detail]) do
  173.         renderer:DrawTriangle(
  174.             value[1],
  175.             value[2],
  176.             value[3],
  177.             value[4],
  178.             value[5]
  179.         )
  180.     end
  181. end
  182.  
  183. -- Draws the terrain.
  184. function Terrain:Draw(renderer)
  185.     local range = 2
  186.     local posX = math.floor(renderer.CameraPositionX/chunkSize)
  187.     local posY = math.floor(renderer.CameraPositionY/chunkSize)
  188.     local posZ = math.floor(renderer.CameraPositionZ/chunkSize)
  189.     if #self.MeshesToReset > 0 then
  190.         for key, value in pairs(self.MeshesToReset) do
  191.             self.DrawingMeshes[value.x][value.y][value.z] = nil
  192.         end
  193.         self.MeshesToReset = {}
  194.         collectgarbage()
  195.     end
  196.     for x = posX - range, posX + range do
  197.         for y = posY - range, posY + range do
  198.             for z = posZ - range, posZ + range do
  199.                 self:DrawChunk(renderer, x, y, z, 2^(math.max(math.abs(x - posX), math.abs(y - posY), math.abs(z - posZ))*.5 - .5))
  200.             end
  201.         end
  202.     end
  203. end
  204.  
  205. return Terrain
Add Comment
Please, Sign In to add comment