• 3D
  • Getting an odd behavior using the SurfaceTool

I'm getting some strange behavior, not sure if it's from the SurfaceTool or the MeshDataTool.

To create a cube, I define 8 vertices, and I feed them into the SurfaceTool in a certain order, and everything seems fine, except when I use SurfaceTool.index(), instead of the resulting mesh having 24 vertices, it has 26 vertices, according to the MeshDataTool.

I commented the lines that were feeding the vertices from the faces and found out one of the faces is going wrong, but I have no idea why. I'm feeding its vertices in the exact same order for every face. I tried changing the order of those vertices, and most configurations go wrong, except at least one (see the comment on line 25 below).

I'm not sure this is gonna be a problem, but I'd like to understand what's happening here just in case. I'm I missing something, or is the SurfaceTool not indexing properly, or is the MeshDataTool not reading the mesh properly?

# --------------------------------------------------------------------------
# 		Reference
# 
#               010           110                         Z
#   Vertices     A0 ---------- B1            Faces      Top    -Y
#           011 /  |      111 /  |                        |   North
#             E4 ---------- F5   |                        | /
#             |    |        |    |          -X West ----- 0 ----- East X
#             |   D3 -------|-- C2                      / |
#             |  /  000     |  / 100               South  |
#             H7 ---------- G6                      Y    Bottom
#              001           101                          -Z
# --------------------------------------------------------------------------
var a = Vector3(0, 1, 0)
var b = Vector3(1, 1, 0)
var c = Vector3(1, 0, 0)    
var d = Vector3(0, 0, 0)
var e = Vector3(0, 1, 1)
var f = Vector3(1, 1, 1)
var g = Vector3(1, 0, 1)
var h = Vector3(0, 0, 1)

var faces = [
	# b,a,d,  b,d,c,     # N
	e,f,g,  e,g,h,     # S     <-- these triangles go wrong (but 'e,f,g,  h,e,g' works)
	# a,e,h,  a,h,d,     # W
	# f,b,c,  f,c,g,     # E
	# a,b,f,  a,f,e,     # T
	# h,g,c,  h,c,d      # B
]

surface_tool.begin(Mesh.PRIMITIVE_TRIANGLES)
for v in faces: surface_tool.add_vertex(v)
surface_tool.index()                   
surface_tool.generate_normals()

var mesh = sft.commit()
mesh_instance.mesh = mesh
mesh_data_tool.create_from_surface(mesh, 0)

# the results are just like if I didn't use SurfaceTool.index():
print("Faces: ", mesh_data_tool.get_face_count())      # 2
print("Edges: ", mesh_data_tool.get_edge_count())      # 6    - should be 5
print("Verts: ", mesh_data_tool.get_vertex_count())    # 6    - should be 4

I'm not sure right off what would be causing the issue, glancing at the code I don't see what would be causing additional edges or vertices. My guess is that it could be the automatic generation of indices using the index() function is causing the issue, but its just a guess.

I think the extra edge comes from the middle edge of the triangle, as the face (composed of two tranges) are not connected to each other. For example, instead of adding 6 vertices (e,f,g,e,g,h) you can add 4 and set the indices to connect them all together. At least, this is what I did on my tutorial on using the SurfaceTool and I think it should give the right face, edge, and vertex count.

Yes, the extra edge and 2 extra vertices are exactly because it isn't reusing the vertices, so there's two whole triangles there: 3 edges 2, 3 vertices 2, as if index() didn't have any effect.

I tried with indices as well, I forgot to mention. Though I didn't do it quite like you said (I will try it, though). I did it like this:

var verts = [a,b,c,d,e,f,g,h]
var indices = [
	1,0,3, 1,3,2,  # N
	4,5,6, 4,6,7,  # S    <-- this face still hates me
	0,4,7, 0,7,3,  # W
	5,1,2, 5,2,6,  # E
	0,1,5, 0,5,4,  # T
	7,6,2, 7,2,3,  # B
]
for v in verts:    surface_tool.add_vertex(v)
for i in indices:  surface_tool.add_index(i)
# didn't call index() for this, of course

The result was the same. There's still two whole triangles on the front (south) face. I didn't test this with different orders, though, but I presume 4,5,6, 7,4,6 would work.

Also, shouldn't that result in the mesh having only 8 vertices in total, since I'm reusing all of them? I was expecting that to happen, but it doesn't. It still has 24 (or 26 with the order above).

Well the vertices still need to exist somewhere, even when using indices. Maybe there is nothing wrong.

I think each face that is not connected makes duplicate vertices, though I could be wrong as its been awhile since I've looked into it. With each face 4 vertices each (vertices on each corner), a cube with 6 faces would lead to 24 vertices (4 X 6 = 24), which would explain the number. I'm not sure where the 2 extra come from for 26 though.

I've been looking at the source code for the SurfaceTool, and it seems quite straightforward and to be much like I was expecting it to be.

But then I did more tests, and I noticed a discrepancy between the indices that I feed it with and the indices it gives me back with SurfaceTool.commit_to_arrays()

This is what I feed it with (with the fixed ordering of that face, so there's a total of 24 verts in the mesh):

vertices: [a,b,c,d,e,f,g,h]
indices: [1, 0, 3, 1, 3, 2, 4, 5, 6, 7, 4, 6, 0, 4, 7, 0, 7, 3, 5, 1, 2, 5, 2, 6, 0, 1, 5, 0, 5, 4, 7, 6, 2, 7, 2, 3]

And this is what it gives me back (I converted the Vector3s to letters):

vertices: [b, a, d, c, e, f, g, h, a, e, h, d, f, b, c, g, a, b, f, e, h, g, c, d]   
indices[0, 1, 2, 0, 2, 3, 4, 5, 6, 7, 4, 6, 8, 9, 10, 8, 10, 11, 12, 13, 14, 12, 14, 15, 16, 17, 18, 16, 18, 19, 20, 21, 22, 20, 22, 23]

Note that 0=a in my indices, but in the SurfaceTool 0=b. Looking at the source code I cannot tell where it does these rearrangements that make it not reuse all the vertices and come up with new indices.

Now I'm even more confused...

I spoke with Calinou on IRC, and he brought to my attention that smoothing makes a difference as far as joinging vertices that converge at the corners. Using SurfaceTool.add_smooth_group(true) before adding the 8 vertices, makes the resulting mesh have only those 8 vertices and use the indices I fed it with. I think it can also be used for individual vertices, but I'm not 100% sure how it works.

So at least that I understand now.

Still couldn't figure out my initial problem though.