-
Notifications
You must be signed in to change notification settings - Fork 131
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Terrain3DStorage: Add get_normal() utility function #246
Conversation
9b7d4da
to
a7dc731
Compare
src/terrain_3d_storage.cpp
Outdated
real_t left = get_height(p_global_position + Vector3(-_region_size, 0.0f, 0.0f)); | ||
real_t right = get_height(p_global_position + Vector3(_region_size, 0.0f, 0.0f)); | ||
real_t back = get_height(p_global_position + Vector3(0.0f, 0.0f, -_region_size)); | ||
real_t front = get_height(p_global_position + Vector3(0.0f, 0.0f, _region_size)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The original formula from the shader added _region_pixel_size to UV. The value of that is 1/1024. Here, replace _region_size with 1.0f/_region_size
.
Also you can remove the tangent and binormal options, and consolidate get_normal_simple into this function. Thanks for the idea for two options, but it's not necessary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I updated the note above. We need make sure the offset for get_height is big enough so that it moves to the next pixel in the map image. 1/region_size should do it as it's the same size as in the shader, and region_size will change in the future.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This way it still didnt work as expected. I experimented a bit and came with something else, but I am not sure at all if its correct.
I looked closer at the shader and this is how it's calculated: get_height(uv + vec2(_region_texel_size, 0));
get_height((vertex.xz + 0.5)/1024 + vec2(1/1024, 0)); That get_height is using 0-1 UV coordinates. Our C++ get_height uses full range values, so if we multiply the above by 1024 we get real_t left = get_height(p_global_position + Vector3(-1.0f, 0.0f, 0.0f));
real_t right = get_height(p_global_position + Vector3(1.0f, 0.0f, 0.0f));
real_t back = get_height(p_global_position + Vector3(0.f, 0.f, -1.0f));
real_t front = get_height(p_global_position + Vector3(0.f, 0.f, 1.0f)); I then tested this by adding an MMI to DemoScene._ready() var count: int = 1024
var mmi := MultiMeshInstance3D.new()
mmi.multimesh = MultiMesh.new()
mmi.multimesh.transform_format = MultiMesh.TRANSFORM_3D
mmi.multimesh.instance_count = count*count
mmi.multimesh.mesh = PrismMesh.new()
mmi.multimesh.mesh.size = Vector3(.25, 1, .25)
add_child(mmi)
for x in count:
for z in count:
var xform := Transform3D()
#xform.origin = Vector3(x, 0, z) * $Terrain3D.get_mesh_vertex_spacing()
xform.origin = Vector3(x, 0, z)
var normal: Vector3 = $Terrain3D.storage.get_normal(xform.origin)
if is_nan(normal.x):
normal = Vector3.UP
normal = normal.normalized()
xform.basis.y = normal
xform.basis.x = -xform.basis.z.cross(normal)
xform.basis = xform.basis.orthonormalized()
var height: float = $Terrain3D.storage.get_height(xform.origin)
if is_nan(height):
xform.origin.y = -100
else:
xform.origin.y = height
xform.origin += normal * .5
mmi.multimesh.set_instance_transform(z*count + x, xform)
It looks pretty good. |
Fixes #142