Godot: CSGShape's _update_shape() doesn't produce indices

Created on 29 May 2019  路  7Comments  路  Source: godotengine/godot

Godot version:
3.1.1

OS/device including version:
Ubuntu 18.04
GeForce GTX 1070, NVIDIA 418.56

Issue description:
While CSG generally works, when using the following code to create and export an actual mesh from it...

csgMesh._update_shape()
var actualMesh = csgMesh.get_meshes()[1]

... the resulting Mesh will not have its indices set. It still displays fine when duplicated, exported, loaded, etc., but it shows the following error whenever used anywhere:

E 0:00:01:0818 Condition ' surface->index_array_len == 0 ' is true. returned: PoolVector()
drivers/gles3/rasterizer_storage_gles3.cpp:3774 @ mesh_surface_get_index_array()

For example, this code will show the error, and the lack of indices also prevents it from working:

var navMesh :NavigationMesh = NavigationMesh.new()
# create_from_mesh fails due to actualMesh not having indices
navMesh.create_from_mesh(actualMesh)

Looking at the code of _update_shape() in csg_shape.cpp, indeed no indices are created.
They may not be necessary to display the result of the CSGShape, but this lack of indices seems to cause aforementioned error as well as other problems down the line (I'm certain not only navmesh's create_from_mesh is affected here).

So far, the only workaround is to produce the indices manually afterwards - which isn't too hard as the order simply seems to be [0, 1, 2][3, 4, 5][6, 7, 8] etc - but this shouldn't be necessary at all. _update_shape() creates normals, UVs and tangents, so why not add indices?

Steps to reproduce:
See above.

Minimal reproduction project:
Any project using CSGMesh (or possibly other CSG nodes) would probably do, but here is my project from another issue, also showing the problem:
procmeshtest.zip

bug core rendering

Most helpful comment

This is the code I used to create the indices from an ArrayMesh and add it to a navMesh.
However, note that the result did not really work for me as I simply added the entire 3D mesh (including walls, etc.), not just the parts that should be used for navigation.
In that context, know that create_from_mesh() does NOT analyze a mesh and create a fitting navMesh for it - that would be the baking functionality which is not exposed to scripts, one of the many things severely lacking about Navigation in Godot -, but really uses the entire passed mesh as a navigation mesh.

create_from_mesh() is really only useful if you pass it what is basically already a navigation mesh.

Anyway, here's the code:

var csgFloor :CSGCombiner = get_node("CSGFloor")
csgFloor._update_shape()
var floorMesh :ArrayMesh = csgFloor.get_meshes()[1]

var array :Array = floorMesh.surface_get_arrays(0)
var vertices :PoolVector3Array = array[Mesh.ARRAY_VERTEX]
navMesh.set_vertices(vertices)
for i in range(0, vertices.size(), 3):
    var polygon :PoolIntArray = []
    polygon.resize(3)
    polygon[0] = i
    polygon[1] = i + 1
    polygon[2] = i + 2
    navMesh.add_polygon(polygon)

All 7 comments

Hi,

I was about to open a bug report due to "navMesh.create_from_mesh()" not working. I didn't found out the lack of indices on the ArrayMesh. Right now CSGMesh is the easier way to create navigation meshes on the flight so it's sad that it's not working :(

Meanwhile, @TheSHEEEP may I ask you how do you create the index for the ArrayMesh? SurfaceTool maybe? Im kinda puzzled on how to do it.

This is the code I used to create the indices from an ArrayMesh and add it to a navMesh.
However, note that the result did not really work for me as I simply added the entire 3D mesh (including walls, etc.), not just the parts that should be used for navigation.
In that context, know that create_from_mesh() does NOT analyze a mesh and create a fitting navMesh for it - that would be the baking functionality which is not exposed to scripts, one of the many things severely lacking about Navigation in Godot -, but really uses the entire passed mesh as a navigation mesh.

create_from_mesh() is really only useful if you pass it what is basically already a navigation mesh.

Anyway, here's the code:

var csgFloor :CSGCombiner = get_node("CSGFloor")
csgFloor._update_shape()
var floorMesh :ArrayMesh = csgFloor.get_meshes()[1]

var array :Array = floorMesh.surface_get_arrays(0)
var vertices :PoolVector3Array = array[Mesh.ARRAY_VERTEX]
navMesh.set_vertices(vertices)
for i in range(0, vertices.size(), 3):
    var polygon :PoolIntArray = []
    polygon.resize(3)
    polygon[0] = i
    polygon[1] = i + 1
    polygon[2] = i + 2
    navMesh.add_polygon(polygon)

The mesh I use is made only for the purpose of using it in the NavMesh, so in my case it's fine.I tweaked your code and it's working nicely for me.

I hope that Navigation gains more attention, it's a part of the engine that looks kinda under-developed to me.

Anyway, thank you so much for sharing your code, it helped me a lot.

Feel free to add your voice or thumbs to the "main" navmesh improvement issue here.

Also, how do you use CSGMesh to create a mesh to put into NavMesh? Do you add a plane and then use the walls to "cut out" holes in it? How do you deal with stuff like stairs in that scenario?

My use case is a bit weird. I use the NavMesh to create a plane where enemies can go, basically to avoid static objects (the levels will be procedural). I don't know if I can link youtube videos... so... if you search for "Gravity Wars Godot" you can find a video called "Prototype 0" to check what I mean.

I'll write on the issue; life would be way easier if we had "agents" with an avoidance system.

Not reproducible on 3.2.3.rc3.

Closing as resolved in 3.2 per @hoontee's comment.

Was this page helpful?
0 / 5 - 0 ratings