Procedural Generation of Skeleton3d

Hi

Godot Version

Godot 4.3-stable-mono

Question

I am using the SurfaceTool to generate a 3D Mesh at runtime. I am also trying to generate a Skeleton that follows the edges of each face.

As first step, I created a square out of two triangles and added a skeleton & bones to it in order to get a feel for this feature. Unfortunately, I don’t see any bones in the editor at runtime and the mesh no longer appears as soon as I set the Skeleton to a Skeleton3D Node. I’m guessing I don’t understand Skeleton’s fully, so any help would be appreciated.
Here’s my scene layout:

Here’s my code attached to “Mesh”:

extends MeshInstance3D

func createBaseMesh(origin: Vector3, end: Vector3, st: SurfaceTool):
    var x = origin.x
    var y = origin.y
    var z = origin.z

    var lowerLeft = origin
    var upperLeft = Vector3(end.x, y, z)
    var lowerRight = Vector3(x, y, end.z)
    var upperRight = Vector3(end.x, y, end.z)

    st.begin(Mesh.PRIMITIVE_TRIANGLES)

    ## Playing with bones
    var skel = get_node(skeleton)
    var bone_middle = skel.add_bone("middle")
    var bone_left = skel.add_bone("left")
    var bone_right = skel.add_bone("right")
    var bone_up = skel.add_bone("up")
    var bone_down = skel.add_bone("down")

    skel.set_bone_parent(bone_left, bone_middle)
    skel.set_bone_parent(bone_down, bone_middle)
    skel.set_bone_parent(bone_up, bone_middle)
    skel.set_bone_parent(bone_right, bone_middle)

    skel.set_bone_pose_position(bone_left, origin)
    skel.set_bone_pose_position(bone_middle, origin)
    skel.set_bone_pose_position(bone_down, origin)
    skel.set_bone_pose_position(bone_up, end)
    skel.set_bone_pose_position(bone_right, end)


    skel.set_bone_pose_rotation(bone_left, Quaternion(Vector3.RIGHT, 0))
    # rotate middle, so it's along the shared axis of both faces
    skel.set_bone_pose_rotation(bone_middle, Quaternion(Vector3.UP, TAU / 8))
    skel.set_bone_pose_rotation(bone_down, Quaternion(Vector3.FORWARD, 0))
    skel.set_bone_pose_rotation(bone_up, Quaternion(Vector3.FORWARD, 0))
    skel.set_bone_pose_rotation(bone_right, Quaternion(Vector3.RIGHT, 0))

    skel.set_bone_rest(bone_left, Transform3D.IDENTITY)
    skel.set_bone_rest(bone_middle, Transform3D.IDENTITY)
    skel.set_bone_rest(bone_down, Transform3D.IDENTITY)
    skel.set_bone_rest(bone_up, Transform3D.IDENTITY)
    skel.set_bone_rest(bone_right, Transform3D.IDENTITY)

    skel.set_bone_global_pose(bone_left, Transform3D.IDENTITY)
    skel.set_bone_global_pose(bone_middle, Transform3D.IDENTITY)
    skel.set_bone_global_pose(bone_down, Transform3D.IDENTITY)
    skel.set_bone_global_pose(bone_up, Transform3D.IDENTITY)
    skel.set_bone_global_pose(bone_right, Transform3D.IDENTITY)


    # Define nodes and skeletons
    st.set_weights([0.3, 0.3, 0.3, 0])
    st.set_bones([bone_left, bone_middle, bone_down, bone_right])
    st.add_vertex(lowerLeft)
    st.set_weights([0.5, 0.5, 0, 0])
    st.set_bones([bone_left, bone_up, bone_down, bone_right])
    st.add_vertex(upperLeft)
    st.set_weights([0.5, 0.5, 0, 0])
    st.set_bones([bone_down, bone_right, bone_left, bone_up])
    st.add_vertex(lowerRight)
    st.set_weights([0.3, 0.3, 0.3, 0])
    st.set_bones([bone_right, bone_middle, bone_up, bone_left])
    st.add_vertex(upperRight)


    # lower left
    st.add_index(1)
    st.add_index(0)
    st.add_index(2)

    # upper right
    st.add_index(1)
    st.add_index(2)
    st.add_index(3)

func finishGeometry(st: SurfaceTool):
    mesh.clear_surfaces()
    st.generate_normals()
    mesh = st.commit()
    ResourceSaver.save(mesh, "res://mesh.tres", ResourceSaver.FLAG_COMPRESS)
    var material: StandardMaterial3D = StandardMaterial3D.new()
    material.cull_mode = StandardMaterial3D.CULL_DISABLED
    material.albedo_color = Color.ORANGE
    set_surface_override_material(0, material)


func createMesh(origin: Vector3, end: Vector3):
    var st = SurfaceTool.new()

    createBaseMesh(origin, end, st)
    finishGeometry(st)

func _ready():
    var origin = Vector3(0, 0, 0)
    var end = Vector3(1, 0, 1)
    createMesh(origin, end)

The final goal of the skeleton is to have players drag one of the edges of the square and have the skeleton determine how the rest of the mesh should rotate/look like in 3D.

1 Like