• 3D
  • Offset to gridmap object in meshlibrary through code

I have had trouble getting 3d models from blender (.glb) to offset within a gridmap cell. As in roof tiles aligned to the top of a cell, floor tiles aligned to the bottom of a cell, or anything inbetween. Changing the origin in blender does not seem to affect this. I did uncheck the "Center Y" option in the Cell property of the Gridmap node. Also dragging models into a scene, selecting them all and clicking Scene -> Convert to... -> Meshlibrary... does not always seem to work that well.

I imported the models (made in Blender and exported with a .glb extension) and created a new inherited scene from it. This new inherited scene I then saved in a folder called Assets.

My solution was to make a simple script that would generate the meshlibrary for me, and change offset if needed. A new scene (MeshLibraryMaker.tscn) is made with only a spatial node, to which this script (MeshLibraryMaker.gd) is attached.

It succesfully adds the models to a meshlibrary. The offset also works, but makes the texture dissapear. (texture was added in Blender and came with the exported model) If you run this scene (MeshLibraryMaker.tscn) a few times in a row it bugs out and rearranges items in the meshlibrary randomly, and sometimes swaps models, or copies one model to use for all items, or makes items dissapear. If this happens restart Godot and it should work again.

With my limited knowledge of both Godot and programming this is where i am now, and cant get any further. Can you identify where the script goes wrong? Or have any tips on how to refactor this script?

extends Spatial var lib = MeshLibrary.new() func _ready(): #Manually add items for the meshLibrary here addToMeshLib("res://Assets/FloorTile03.tscn", 0.5) addToMeshLib("res://Assets/PedestalTile02.tscn") ResourceSaver.save("res://Tools/newMeshLib.meshlib", lib) func addToMeshLib(path, offsetY := 0.0): var ID = lib.get_last_unused_item_id() lib.create_item(ID) var mesh = extractMesh(path) if offsetY != 0: mesh = applyOffsetY(mesh, offsetY) lib.set_item_mesh(ID, mesh) var name = extractName(path) lib.set_item_name(ID, name) func extractMesh(path) -> Mesh: var mesh var source = load(path) var instance = source.instance() var arr = instance.get_children() for n in arr: if n.get_class() == "MeshInstance": mesh = n.mesh break return mesh func extractName(path: String) -> String: var name = path if name.ends_with(".tscn"): name.erase(name.length() - 5, 5) name.erase(0, name.find_last("/") + 1) return name func applyOffsetY(mesh, offset): var newArrayMesh = ArrayMesh.new() newArrayMesh.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLES, mesh.surface_get_arrays(0)) var mdt = MeshDataTool.new() mdt.create_from_surface(newArrayMesh, 0) for i in range(mdt.get_vertex_count()): var vertex = mdt.get_vertex(i) vertex = vertex + Vector3(0,offset,0) mdt.set_vertex(i, vertex) var vertex2 = mdt.get_vertex_normal(i) vertex2 = vertex2 + Vector3(0,offset,0) mdt.set_vertex_normal(i, vertex2) newArrayMesh.surface_remove(0) mdt.commit_to_surface(newArrayMesh) return newArrayMesh

It should work with moved origins from Blender. Definitely tried this myself and it was fine. You want to use the 3D cursor to place the point where you want and then use "Origin to 3D Cursor". I can't recall where the gridmap expects the origin to be, I think in a corner when you uncheck center y. That should definitely work.

I redid the models in Blender and changed the origin to several different positions and exported to a .glb. The correct origin is indeed used in the gridmap cell. So i guess the error was in the model, not Godot's gridmap.

Also I tinkered with the code some more and did something so obvious it shows I am new to this. I added two lines of code to the addToMesh function that store and add the material to the new mesh.

var mesh = extractMesh(path) if offsetY != 0: var mat = mesh.surface_get_material(0) mesh = applyOffsetY(mesh, offsetY) mesh.surface_set_material(0,mat) lib.set_item_mesh(ID, mesh)

So now both imported models automatically center, and the script works. Sorry for bothering with this question.

Oh yeah, I noticed that too. Sorry I didn't mention anything.