From f391ac9fa94131ffa0397ce83c73bc06d4bfc971 Mon Sep 17 00:00:00 2001 From: Kilarin Date: Sun, 8 Mar 2015 14:54:15 -0500 Subject: [PATCH] world stone tower perlin noise problems --- mods/fracturerift/init.lua | 171 +++++++++++++++---------------- mods/worldstonetower/depends.txt | 3 + mods/worldstonetower/init.lua | 151 +++++++++++++++++++++++++++ 3 files changed, 238 insertions(+), 87 deletions(-) create mode 100644 mods/worldstonetower/depends.txt create mode 100644 mods/worldstonetower/init.lua diff --git a/mods/fracturerift/init.lua b/mods/fracturerift/init.lua index a330450..4391373 100644 --- a/mods/fracturerift/init.lua +++ b/mods/fracturerift/init.lua @@ -35,100 +35,97 @@ local np_walls = { --FRACTURE GENERATION minetest.register_on_generated(function(minp, maxp, seed) - if maxp.x < -fracrift_edge or minp.x > fracrift_edge or - maxp.y < fracrift_depth or minp.y > fracrift_top then - return --quit; otherwise, you'd have wasted resources - end + if maxp.x < -fracrift_edge or minp.x > fracrift_edge or + maxp.y < fracrift_depth or minp.y > fracrift_top then + return --quit; otherwise, you'd have wasted resources + end - --easy reference to commonly used values - local t1 = os.clock() - local x1 = maxp.x - local y1 = maxp.y - local z1 = maxp.z - local x0 = minp.x - local y0 = minp.y - local z0 = minp.z + --easy reference to commonly used values + local t1 = os.clock() + local x1 = maxp.x + local y1 = maxp.y + local z1 = maxp.z + local x0 = minp.x + local y0 = minp.y + local z0 = minp.z - --no need to scan outside the rift - --if x0 < -fracrift_edge then x0=-fracrift_edge end - --if x1 > fracrift_edge then x1=fracrift_edge end - --if y0 < fracrift_depth then y0=fracrift_depth end - --if y1 > fracrift_top then y1=fracrift_top end + --no need to scan outside the rift + --if x0 < -fracrift_edge then x0=-fracrift_edge end + --if x1 > fracrift_edge then x1=fracrift_edge end + --if y0 < fracrift_depth then y0=fracrift_depth end + --if y1 > fracrift_top then y1=fracrift_top end - print ("[fracrift_ure_gen] chunk minp ("..x0.." "..y0.." "..z0..")") --tell people you are generating a chunk + print ("[fracrift_ure_gen] chunk minp ("..x0.." "..y0.." "..z0..")") --tell people you are generating a chunk - --This actually initializes the LVM - local vm, emin, emax = minetest.get_mapgen_object("voxelmanip") - local area = VoxelArea:new{MinEdge=emin, MaxEdge=emax} - local data = vm:get_data() + --This actually initializes the LVM + local vm, emin, emax = minetest.get_mapgen_object("voxelmanip") + local area = VoxelArea:new{MinEdge=emin, MaxEdge=emax} + local data = vm:get_data() - local sidelen = x1 - x0 + 1 --length of a mapblock - local chulens = {x=sidelen, y=sidelen, z=sidelen} --table of chunk edges - local minposxyz = {x=x0, y=y0, z=z0} --bottom corner - - local nvals_walls = minetest.get_perlin_map(np_walls, chulens):get3dMap_flat(minposxyz) -- Get the noise map for the rift walls - - local changed=false - - local nixyz = 1 --3D node index - - for z = z0, z1 do -- for each xy plane progressing northwards - for y = y0, y1 do -- for each x row progressing upwards - vi = area:index(x0, y, z) --This accesses the node at a given position. vi is incremented inside the loop for greater performance. - for x = x0, x1 do -- for each node do - --local vi = area:index(x, y, z) -- This accesses the node at a given position - - local grad = math.abs(x / fracrift_edge) * (10^(math.abs(x / fracrift_edge)) / 10) -- Density gradient. This controls how much to offset the noise value as x approaches the walls of the chasm. - - if x > -fracrift_edge and x < fracrift_edge then -- If within chasm-generating limits - - if ((math.abs(nvals_walls[nixyz]) - grad) > 0) then -- Check the value of the perlin noise at this position with respect to distance from center - if data[vi] ~= c_air then - data[vi] = c_air -- Hollow out the chasm with smooth walls - end - else - if (x < -fracrift_edge/3 or x > fracrift_edge/3) then -- Put limits in to make sure the chasm always stays at least some ways open - if data[vi] == c_water then -- If there's water, make it wall material so as not to drain the oceans :P - data[vi] = fracrift_material - end - else - if (x > -fracrift_edge/3 or x < fracrift_edge/3) then -- In the limits, always hollow this - data[vi] = c_air - end - end - end - - changed = true - - end -- if x > -fracrift_edge and x < fracrift_edge - - if x == -fracrift_edge or x == fracrift_edge then -- x is on edge - if data[vi] == c_water and math.random() < fracrift_waterfallchance and (math.abs(nvals_walls[nixyz]) - grad) > -0.1 then - data[vi]=fracrift_material - changed=true - end -- change water to stone on edge - end -- if x == -fracrift_edge or x == fracrift_edge - - nixyz = nixyz + 1 - vi = vi + 1 - - end -- end 'x' loop - end -- end 'y' loop - end -- end 'z' loop + local sidelen = x1 - x0 + 1 --length of a mapblock + local chulens = {x=sidelen, y=sidelen, z=sidelen} --table of chunk edges + local minposxyz = {x=x0, y=y0, z=z0} --bottom corner - if changed==true then - -- Wrap things up and write back to map - --send data back to voxelmanip - vm:set_data(data) - --calc lighting - vm:set_lighting({day=0, night=0}) - vm:calc_lighting() - --write it to world - vm:write_to_map(data) - end --if changed write to map + local nvals_walls = minetest.get_perlin_map(np_walls, chulens):get3dMap_flat(minposxyz) -- Get the noise map for the rift walls - local chugent = math.ceil((os.clock() - t1) * 1000) --grab how long it took - print ("[fracrift_ure_gen] "..chugent.." ms") --tell people how long + local changed=false + + local nixyz = 1 --3D node index + + for z = z0, z1 do -- for each xy plane progressing northwards + for y = y0, y1 do -- for each x row progressing upwards + local vi = area:index(x0, y, z) --This accesses the node at a given position. vi is incremented inside the loop for greater performance. + for x = x0, x1 do -- for each node do + --local vi = area:index(x, y, z) -- This accesses the node at a given position + local grad = math.abs(x / fracrift_edge) * (10^(math.abs(x / fracrift_edge)) / 10) -- Density gradient. This controls how much to offset the noise value as x approaches the walls of the chasm. + + if x > -fracrift_edge and x < fracrift_edge then -- If within chasm-generating limits + + if ((math.abs(nvals_walls[nixyz]) - grad) > 0) then -- Check the value of the perlin noise at this position with respect to distance from center + if data[vi] ~= c_air then + data[vi] = c_air -- Hollow out the chasm with smooth walls + end + else + if (x < -fracrift_edge/3 or x > fracrift_edge/3) then -- Put limits in to make sure the chasm always stays at least some ways open + if data[vi] == c_water then -- If there's water, make it wall material so as not to drain the oceans :P + data[vi] = fracrift_material + end + else + if (x > -fracrift_edge/3 or x < fracrift_edge/3) then -- In the limits, always hollow this + data[vi] = c_air + end + end + end + changed = true + end -- if x > -fracrift_edge and x < fracrift_edge + + if x == -fracrift_edge or x == fracrift_edge then -- x is on edge + if data[vi] == c_water and math.random() < fracrift_waterfallchance and (math.abs(nvals_walls[nixyz]) - grad) > -0.1 then + data[vi]=fracrift_material + changed=true + end -- change water to stone on edge + end -- if x == -fracrift_edge or x == fracrift_edge + + nixyz = nixyz + 1 + vi = vi + 1 + + end -- end 'x' loop + end -- end 'y' loop + end -- end 'z' loop + + if changed==true then + -- Wrap things up and write back to map + --send data back to voxelmanip + vm:set_data(data) + --calc lighting + vm:set_lighting({day=0, night=0}) + vm:calc_lighting() + --write it to world + vm:write_to_map(data) + end --if changed write to map + + local chugent = math.ceil((os.clock() - t1) * 1000) --grab how long it took + print ("[fracrift_ure_gen] "..chugent.." ms") --tell people how long end) --register_on_generated fracture generation diff --git a/mods/worldstonetower/depends.txt b/mods/worldstonetower/depends.txt new file mode 100644 index 0000000..be73b52 --- /dev/null +++ b/mods/worldstonetower/depends.txt @@ -0,0 +1,3 @@ +default? +blastradius? +fracturerift? \ No newline at end of file diff --git a/mods/worldstonetower/init.lua b/mods/worldstonetower/init.lua new file mode 100644 index 0000000..38aae64 --- /dev/null +++ b/mods/worldstonetower/init.lua @@ -0,0 +1,151 @@ +-- + +--- +--- constants +--- +local wst_pos={x=0,y=0,z=0} +local wst_radius=15 +local wst_length=100 +local wst_floorheight=8 +local wst_shrinkheight=20 + +local wst_floorholeodds=0.1 +local wst_wallholeodds=0.01 + +local wst_material_wall = minetest.get_content_id("default:obsidianbrick") +local wst_material_floor = minetest.get_content_id("default:desert_stonebrick") +local wst_material_stair = minetest.get_content_id("stairs:stair_obsidianbrick") + +--local wst_start={x=0,y=0,z=0} --where to start trying to put the tower. +--local wst_lookdist=100 --distance to look for starting point. + + +--calculated constants +wst_radiussq=wst_radius^2 +--these have to be done later +local wst_min={x=wst_pos.x-math.floor(wst_length/2), + y=wst_pos.y-wst_radius, + z=wst_pos.z-wst_radius} +local wst_max={x=wst_pos.x+math.floor(wst_length/2), + y=wst_pos.y+wst_radius, + z=wst_pos.z+wst_radius} + + +--print("**ZZ** nspawn_pos="..dump(nspawn_pos).." min="..dump(nspawn_min).." max="..dump(nspawn_max).." nspawn_stepmin="..dump(nspawn_stepmin).." nspawn_stepmax="..dump(nspawn_stepmax)) + +--grab content IDs -- You need these to efficiently access and set node data. get_node() works, but is far slower +local c_air = minetest.get_content_id("air") + +-- 3D noise for tower damage +local np_dmg = { + offset = 0, + scale = 1, + spread = {x=192, y=512, z=512}, -- squashed 2:1 + --spread = {x=200, y=80, z=80}, + seed = 133742, --a LEET answer to life, the universe, and everything + octaves = 3, + persist = 0.67 +} + + + +minetest.register_on_generated(function(minp, maxp, seed) + --dont bother if we are not near new spawn + --print("[wst] minp="..dump(minp).." maxp="..dump(maxp).." wstmin="..dump(wst_min).." wstmax="..wst_max) + if minp.x > wst_max.x or maxp.x < wst_min.x and + minp.y > wst_max.y or maxp.y < wst_min.y and + minp.z > wst_max.z or maxp.z < wst_min.z then + --print("rejected: min=("..minp.x..","..minp.y..","..minp.z..") max=("..maxp.x..","..maxp.y..","..maxp.z..")") + return --quit; otherwise, you'd have wasted resources + end -- if minp.x + --print("accepted: min=("..minp.x..","..minp.y..","..minp.z..") max=("..maxp.x..","..maxp.y..","..maxp.z..")") + + --easy reference to commonly used values + local t1 = os.clock() + local x1 = maxp.x + local y1 = maxp.y + local ymax=maxp.y + local z1 = maxp.z + local x0 = minp.x + local y0 = minp.y + local ymin=minp.y + local z0 = minp.z + + print ("[wst_gen] chunk minp ("..x0.." "..y0.." "..z0..")") --tell people you are generating a chunk + --if x0wst_max.x then x1=wst_max.x end + --if y0wst_max.y then y1=wst_max.y end + --if z0wst_max.z then z1=wst_max.z end + + --This actually initializes the LVM + local vm, emin, emax = minetest.get_mapgen_object("voxelmanip") + local area = VoxelArea:new{MinEdge=emin, MaxEdge=emax} + local data = vm:get_data() + + local sidelen = x1 - x0 + 1 --length of a mapblock + local chulens = {x=sidelen, y=sidelen, z=sidelen} --table of chunk edges + local minposxyz = {x=x0, y=y0, z=z0} --bottom corner + local nvals_dmg = minetest.get_perlin_map(np_dmg, chulens):get3dMap_flat(minposxyz) -- Get the noise map for the rift walls + + local nixyz=1 + --print("***---*** "..dump(nvals_dmg)) + --print("***XXX*** "..nvals_dmg[1]) + local xbeg=wst_pos.x-wst_length/2 + local radius=wst_radius + for z = z0, z1 do -- + for y = y0, y1 do -- + local vi = area:index(x0, y, z) --This accesses the node at a given position. vi is incremented inside the loop for greater performance. + for x = x0, x1 do -- + --calculate distance y,z from center of circle + if x>=wst_min.x and x<=wst_max.x and + y>=wst_min.y and y<=wst_max.y and + z>=wst_min.z and z<=wst_max.z then + local yzdist= math.floor(math.sqrt((y-wst_pos.y)^2+(z-wst_pos.z)^2)) + --print("x="..x.." y="..y.." z="..z.." yzdist="..yzdist.." wst_radius="..wst_radius) + local xdist=math.abs((x-xbeg))+1 + radius=wst_radius-(math.floor(xdist/wst_shrinkheight)) + --local vi = area:index(x, y, z) -- This accesses the node at a given position + if yzdist==radius then + --if nvals_dmg[nixyz] and nvals_dmg[nixyz] > 0.8 then + if nvals_dmg[nixyz] > 0.6 then + data[vi] = c_air + print(" w> vi="..vi.." nvals_dmg["..nixyz.."]="..nvals_dmg[nixyz]) + else + print(" w< vi="..vi.." nvals_dmg["..nixyz.."]="..nvals_dmg[nixyz]) + data[vi]=wst_material_wall + end + elseif yzdist 0.6 then + print(" f> vi="..vi.." nvals_dmg["..nixyz.."]="..nvals_dmg[nixyz]) + data[vi] = c_air + else + print(" f< vi="..vi.." nvals_dmg["..nixyz.."]="..nvals_dmg[nixyz]) + data[vi]=wst_material_floor + end + end -- if (xdist/wst_floorheight) + end --if yzdist + end --if x>=wst_min.x + nixyz = nixyz + 1 + vi = vi + 1 + end -- end 'x' loop + end -- end 'y' loop + end -- end 'z' loop + + -- Wrap things up and write back to map + --send data back to voxelmanip + vm:set_data(data) + --calc lighting + vm:set_lighting({day=0, night=0}) + vm:calc_lighting() + --write it to world + vm:write_to_map(data) + --print(">>>saved") + + local chugent = math.ceil((os.clock() - t1) * 1000) --grab how long it took + print ("[wst_gen] "..chugent.." ms") --tell people how long +end) -- register_on_generated fucntion for wst + +