Open timshannon opened 2 years ago
cc @JFonS, who implemented occluder simplification on bake in https://github.com/godotengine/godot/pull/57627.
Is meshoptimizer compiled in release export templates? If not, mesh simplification at run-time will not work in an exported project. This might be worth checking with SurfaceTool as well. If this isn't done already, I think meshoptimiser should be available in exported projects – it probably doesn't impact binary size too much.
FWIW, It looks like SurfaceTool exposes a generate_lod
method that I think possibly uses the same meshoptimizer library.
FWIW, It looks like SurfaceTool exposes a
generate_lod
method that I think possibly uses the same meshoptimizer library.
Indeed, it uses meshoptimizer behind the scenes.
If anyone is trying to do something similar, this is the solution I came up with that appears to be working fine for me:
private void AddLevelOccluderInstance()
{
var instance = new OccluderInstance3D();
instance.Name = "OccluderInstance3D";
_root.AddChild(instance);
instance.Owner = _root;
var occluder = new ArrayOccluder3D();
var occSt = new SurfaceTool();
RecurseTreeOfType<MeshInstance3D>(_root, (mesh) =>
{
if (!IsPartialStructureMesh(mesh))
return;
var st = new SurfaceTool();
var m = mesh.Mesh;
var blnFound = false;
for (var i = 0; i < m.GetSurfaceCount(); i++)
{
var mat = m.SurfaceGetMaterial(i) as StandardMaterial3D;
if (mat == null)
continue;
if (mat.Transparency != StandardMaterial3D.TransparencyEnum.Disabled)
continue;
st.AppendFrom(m, i, Transform3D.Identity);
blnFound = true;
}
if (!blnFound)
return;
var arr = st.CommitToArrays();
var simplified = st.GenerateLod(0.1f);
arr[(int)ArrayMesh.ArrayType.Index] = simplified;
var smesh = new ArrayMesh();
smesh.AddSurfaceFromArrays(Mesh.PrimitiveType.Triangles, arr);
for (var i = 0; i < smesh.GetSurfaceCount(); i++)
occSt.AppendFrom(smesh, i, GetLocalRootTransform(mesh));
});
var arr = occSt.CommitToArrays();
var vertices = (Vector3[])arr[(int)ArrayMesh.ArrayType.Vertex];
var indices = (int[])arr[(int)ArrayMesh.ArrayType.Index];
occluder.SetArrays(vertices, indices);
instance.Occluder = occluder;
}
Would be great to have this implemented in one built-in function like BakeOccluders()
Because it currently asks where to save it, a path parameter would suffice:
occluderInstance3D.BakeOccluders("res://Assets/LevelMaps/Level1.occ")
Tools that auto-generate geometry (like Qodot) would benefit from this: I would press the "Full Build" button so that it generates lots of custom-defined groups of geometry from a .map file (a level designing format) and automatically bake their occluders while at it.
The current state would have me add each OccluderInstance child and hit the Bake Occluders button on every single wrapping Node3D in every re-generation. In advanced map prototyping, I'd have to repeat this about 100 times if I wanted the occluders working after every change.
Would be great to at least be able to bake via a @tool
script so that I don't have to open the large world scene anytime I change geometry.
Describe the project you are working on
A 3D FPS with procedurally generated levels.
Describe the problem or limitation you are having in your project
With procedurally generated geometry you have to manually add the occluder geometry to the ArrayOccluder3D by setting the Arrays value.
This works fine, but you miss out on the mesh simplification done during the Editor Bake. Also the simplification used isn't exposed anywhere you can access it in a script (that I can find, please correct me if I'm wrong here).
Describe the feature / enhancement and how it helps to overcome the problem or limitation
Expose the
bake_scene(Node *p_from_node, String p_occluder_path = "")
method to scripts.From there you could call it on the fly, or via a scene import script.
Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams
Expose the
bake_scene(Node *p_from_node, String p_occluder_path = "")
method to scripts.If this enhancement will not be used often, can it be worked around with a few lines of script?
A 1 to 1 behavior can't be replicated from scripts because we don't have access to the simplification features in the SurfaceTool.
Is there a reason why this should be core and not an add-on in the asset library?
It could probably be done in an addon, but it'd be an addon that simply exposes an existing method to scripts.