Disclaimer : I don't claim to know what I'm doing ; I'm discovering things as I go.
The purpose is to get a simple 3d animation working in Godot (no skeleton animation).
In MagicaVoxel, I created a model of Bethee for every frame of the walk cycle, with the 'idle' model as a starting point.
Next, I exported all models as separate .obj files, and imported them by one into Blender.
With each model, I removed the duplicate vertices and set the origin to the bottom of the mesh (center).
Cleaning up a MagicaVoxel
model in Blender gives you at least 2 advantages : you can reduce the number of vertices (for this simple mesh, I went from
about 1350 verts to about 420 verts), and you can set a convenient origin.
The 7 meshes were then copied into a second layer and positioned at (0,0,0) for exporting as .obj files (= 7 .obj files).
In the next step, the 7 Blender .obj files as well as the MagicaVoxel .mtl and .png files were copied into the resource
folder of a Godot project. I want to use these models to create a
simple idle / walk animation in Godot.
In 2d, you can create an animation using the AnimatedSprite node to swap out sprites at runtime. I don't think there's a way to do something similar in 3d (swap out models at runtime), so I'll have to create the animation in code.
Edit : I was wrong ! You can use the AnimationPlayer node in 3d to swap out meshes (see my post 'Animations in 3d.') !
This is the scene setup : a Spatial root node, a light and a camera, and another Spatial node (Bethee_Root) with a MeshInstance. I've also added a temporary MeshInstance Primitive (Camera_Mark) at (0,0,0) so I know where to point the camera at.
The MeshInstance 'mesh' and 'material_override' properties will be used to select a material and a mesh from code.
The mesh property of the MeshInstance will receive an .obj file so it can create the model mesh. The material_override needs a material, so we'll need to create one.
Click the 'Create a new resource in memory' btn (top left in inspector) and choose 'SpatialMaterial'. Drag the MagicaVoxel .png file (palette colors) into the texture slot of the albedo property. Save the material as a .tres (text format) or .res (binary format).
As for the code (script on Bethee_Root node) ... The idea is to load the meshes (.obj) into an array and cycle through the array in the _process(delta) function.
A simplified script is used to test my setup : pressing the right arrow key should make Bethee walk in place. Releasing the arrow key should show the default 'idle' mesh.
And the result :
Now for the hard part : rotating the mesh CCW or CW when the left or right arrow key is pressed ...
The Godot documentation tells us we should avoid using the Spatial node's rotation property (Euler angles).
Instead, we should the transform (rotation relative to parent node) and
global_transform (rotation relative to world) properties.
Let's see if we can understand how this works ...
The Model node has 3 'arms' that point in the direction of the positive X, Y, and Z world axes. It is positioned at (0,0,0).
The Euler rotation is (0,0,0) degrees (= no rotation).
If we take a look at the transform panel, we find the following properties : transform, translation, rotation (degrees), and scale. All of these properties are 'local', meaning : relative to the parent node (Spatial).
'Transform' looks quite complicated, with a lot of numbers. It is in fact a matrix, and it contains all the information from the other 3 properties. Rotation and scale together are called the 'transform basis', translation is called the 'transform origin'.
If we rotate the Model node 90 degrees around the Y-axis, we see the local X and Z axis now pointing in new directions. As expected, this is reflected in the transform property.
Two things should be kept in mind, when using transforms :
The Godot documentation shows us how to rotate a mesh using the transform.basis property. For our convenience, there's also a shorter way to write the code, using rotate_xyz().
The result, when I press the left / right / up keys :
Mission accomplished ! =)
In the next blog post, I'll try to set up a camera-follow.
Personal note : I have decided to be more transparent about what it is like for me, to be a creative person with an aging autistic brain.
It took me 3 weeks to write these 3 posts. I think that's a ridiculously long time. But there you have it.
Some days, my mind and body just don't work, and I feel exhausted. It's terribly discouraging, but I do my best not to give in to my frustration. =)