• 3D
  • MeshInstance doesn't render if looking from the top

Hi, my problem is that the 3D mesh only renders when I'm looking at it from the bottom. If the camera is pointing down and is above the mesh, nothing renders.

Note that it only happens with GDScript generated mesh.

Example of square planes slowly disappearing as I'm flying upwards: https://i.imgur.com/zkWmsc0.png

Code:

extends Spatial

var tmpMesh = Mesh.new()
var vertices = PoolVector3Array()
var normals = PoolVector3Array()
var UVs = PoolVector2Array()
var mat = SpatialMaterial.new()

func _ready():
	var noise = OpenSimplexNoise.new()
	
	noise.seed = randi()
	noise.octaves = 4
	noise.period = 20.0
	noise.persistence = 0.8
	
	var height = 0.10
	var size = 0.01
	for i in 1:
		for j in 1:
			vertices.push_back(Vector3((j+1)*size,height * noise.get_noise_2d(j, i),(i+0)*size))
			vertices.push_back(Vector3((j+0)*size,height * noise.get_noise_2d(j, i),(i+0)*size))
			vertices.push_back(Vector3((j+0)*size,height * noise.get_noise_2d(j, i),(i+1)*size))
			vertices.push_back(Vector3((j+0)*size,height * noise.get_noise_2d(j, i),(i+1)*size))
			vertices.push_back(Vector3((j+1)*size,height * noise.get_noise_2d(j, i),(i+1)*size))
			vertices.push_back(Vector3((j+1)*size,height * noise.get_noise_2d(j, i),(i+0)*size))

	mat.albedo_color = Color(0.9, 0.2, 0.5)

	var st = SurfaceTool.new()
	st.begin(Mesh.PRIMITIVE_TRIANGLES)
	st.set_material(mat)

	for v in vertices.size(): 
		var rand = rand_range(0.00, 1.00)
		var color = Color(rand, rand, rand)
		st.add_color(color)
		st.add_vertex(vertices[v])

	st.commit(tmpMesh)

	$MeshInstance.mesh = tmpMesh

It sounds like the problem is that the mesh's normals are not setup correctly. Looking at the code, it appears you are not setting the normals, which could be part of the problem.

You have to use add_normal and pass in the normal vector for the vertex before each add_vertex call so the vertex has it's normals set correctly. You can also try using the generate_normals function and see if that works, though personally I've found it to only work with meshes that are closed and 3D (like a cube).

Another potential fix you could try is disabling the cull mode in the Spatial material so it renders all of the faces in the MeshInstance regardless of the normals of the faces in the mesh.

Hopefully this helps :smile:

(Just as an FYI, I edited your post so the code was formatted correctly. All I did was indent your code by a single tab so it renders the code properly)

Hmm yeah thanks for help, disabling cull mode works.

However I'm not sure why adding normals to the mesh doesn't work. for v in vertices.size(): st.add_normal(Vector3(0.0, 1.0, 0.0)) st.add_vertex(vertices[v]) st.commit(tmpMesh) $top.mesh = tmpMesh

Now after I draw it with normal color it should be all green but it isn't: shader_type spatial; void fragment() { ALBEDO = NORMAL; }

Any idea how to check if normals were properly added to the mesh?

I tried printing with print("Faces: " + str(tmpMesh.get_faces())) but it returns only vertices and not normals. Is there a similar method to print normals?

@Saran said: Hmm yeah thanks for help, disabling cull mode works.

However I'm not sure why adding normals to the mesh doesn't work. for v in vertices.size(): st.add_normal(Vector3(0.0, 1.0, 0.0)) st.add_vertex(vertices[v]) st.commit(tmpMesh) $top.mesh = tmpMesh

Now after I draw it with normal color it should be all green but it isn't: shader_type spatial; void fragment() { ALBEDO = NORMAL; }

Any idea how to check if normals were properly added to the mesh?

I tried printing with print("Faces: " + str(tmpMesh.get_faces())) but it returns only vertices and not normals. Is there a similar method to print normals?

That is strange that adding the normals are not working. I used the same normals in a test project, and that I got the same results where the mesh is not visible from above. I changed the cull mode from back to font, and then it rendered from the top with no issues, despite the normals pointing the opposite way.

I am not really sure why it is not behaving as expected, or maybe we are missing something? I am confused now, as I thought the cull mode would cull faces based on whether the normals in each face is pointing towards the camera or not, but it appears this is not the case, at least not with flat meshes.

Unfortunately I do not know of functions similar to get_faces for figuring out a mesh's normals and searching through the documentation did not yield anything.

I really do not know why it is not working. I suppose you could set the cull mode to front and see if that works? Outside of that, I'm not really sure.

You do realize in case of surface normal's it's not "y-up" but "z-up", right? Z is the protruding axis I mean. I mean I haven't really tested to confirm that is the case for godot, but typical standard tends to be Z as the protruding one.