blert2112 wrote:Can somebody shed some light on the MapGen object: heightmap?
Consider the following code:
Code: Select all
cid_diamond = core.get_content_id("default:diamondblock")
core.register_on_generated(function(minp, maxp, seed)
-- get mapgen objects
local hm = core.get_mapgen_object("heightmap")
local vm, emin, emax = core.get_mapgen_object("voxelmanip")
local vm_area = VoxelArea:new({MinEdge = emin, MaxEdge = emax})
local vm_data = vm:get_data()
-- get a random position
local index3d = 0
do
local p1 = {
x = math.random(minp.x,maxp.x),
y = 0,
z = math.random(minp.z,maxp.z)
}
-- returns the height based on height map
local chunksize = maxp.x - minp.x + 1
local index2d = (p1.z - minp.z) * chunksize + (p1.x - minp.x) + 1
--[[
local index2d = 0
for i = minp.x, maxp.x do
local br = false
for j = minp.z, maxp.z do
index2d = index2d + 1
if (i == p1.x) and (j == p1.z) then
br = true
break
end
end
if br == true then break end
end
]]
p1.y = hm[index2d]
index3d = vm_area:indexp(p1)
print(core.pos_to_string(p1))
end
vm_data[index3d] = cid_diamond
vm:set_data(vm_data)
vm:write_to_map()
end)
No matter if using the mathematical method of finding the index or the (commented) count method, more often than not the position is not on the ground. The mathematical method seems to work better, but still, more often than not if I teleport to the position I am many nodes above or below the ground. There has to be something I am missing or something is wrong with my code. Anybody have any ideas?
If you're using valleys, the reason has to do with this part of the generateTerrain method.
Code: Select all
// This happens if we're generating a block that doesn't
// contain the terrain surface, in which case, an
// approximation should be good enough.
if (heightmap[index_2d] == -MAX_MAP_GENERATION_LIMIT)
heightmap[index_2d] = myround(surface_y);
Surface height is determined by a 3D noise (inter-valley fill), which allows overhangs and tunnels to be generated. The way valleys (C and lua) gets the actual ground level is to run through a series of possible altitudes and compare their y value to each noise value at that position. When the numbers compare right, we have the ground level.
This causes problems for heightmap. The estimated terrain level is given by surface_y, but the actual terrain level is usually different. If it's not in the chunk being generated, no actual terrain level is available to generateTerrain. So, we fall back to the method used when the chunk is up in the air or underground -- we store surface_y as an approximation.
Unfortunately, lua code has no way to tell if the number it's getting is a real value or the estimate. I'm very unhappy about that, and I've been trying to think of a better way to go about it. I considered passing -31000 instead, but it's probably more useful to most mods to get something in the neighborhood of ground level than no information at all.
To get the index for heightmap, just loop x inside z and add one to the index each time x counts. (I hope you didn't copy your loops from valleys_c. It was wrong until very recently.) That gives you the correct entry from heightmap, which may still be wrong.
Code: Select all
for z = minp.z, maxp.z do
for x = minp.x, maxp.x do
index_2d = index_2d + 1
Edit: I removed some comments that weren't very helpful.
Believe in people and you don't need to believe anything else.