Manipulating bones
I think i know whats the problem. When the ball is clicked it rotates to look at camera, but when ball is moved the bone sets the ball global position and transform and so the ball rotates back facing away or whatever and so this messes up the position left-right, so in one frame it tries to go left in other right because it flips from looking at camera to the transform of the bone wich is different..
Ill try to fix this tomorrow.
kuligs2 So maybe my question is - is there a better way to create manipulators to pose the mesh in godot game?
If I understand correctly, you're trying to use bones for what is normally done with shapekeys. That's a very interesting approach. I'll keep an eye on the topic. My plan is to start experimenting on this topic in about a month
But i will never be able to replicate the initial face armature because it was hand made (bone placement).
It's a strange approach to learnflow. Usually first, as a base, do something simple that can always be easily repeated.
Tomcat It's a strange approach to learnflow. Usually first, as a base, do something simple that can always be easily repeated.
imo this is as simple as it can get using sort of production mock up models.. i mean why would i try to do this on a cube mesh with one bone where if you start adding more bones it gets very complex?
Also this way i learn how to and not to create bones in blender.
Tomcat If I understand correctly, you're trying to use bones for what is normally done with shapekeys.
whats a shape key?
xyz uhm, i think i did that because i needed the x/y/z axis to be in aligned position with the mouse positive negative x/y axis so that it could translate without the trying to convert them somehow i cant even imagine right now..
kuligs2 lol I was about to suggest that your origin axis or something to that effect was flipped in Blender
Yeah but you don't need that at all. The orientation/basis of the gizmo or of the bone is not important as you're just need to set the position to a point calculated by constraining the mouse projection to a plane.
xyz Continuing debugging, i noticed:
When i click on the ball (i removed look_at() ) i print out positions of the ball and intersection.
ball_node.gd
if cam != null:
#look_at(cam.global_transform.origin,Vector3.UP)
print("interset click0: ", global_position)
temp_plane = Plane(cam.global_transform.basis.z,global_position)
var RAY_LENGTH = (cam.global_position - global_position).length()*1.1
var mousepos = get_viewport().get_mouse_position()
var origin = cam.project_ray_origin(mousepos)
var end = origin + cam.project_ray_normal(mousepos) * RAY_LENGTH
var query = PhysicsRayQueryParameters3D.create(origin, end)
query.exclude = [self]
query.collide_with_areas = true
var intersect = temp_plane.intersects_ray(end, cam.global_transform.origin-global_position)
if intersect:
ball_position_changed.emit(bone_index, intersect)
print("interset click1: ", intersect)
ball_clicked.emit(position)
Clicking the ball that is not related to bones prints out position that is close to real position of the ball.
interset click0: (0, 0.959433, -1.63808)
interset click1: (0.03866, 0.905366, -1.619112)
But when i click the ball that is attached to bone, the ball jumps to some arbitrary location and prints out that wrong location.
While i was writing this, i figured it out i think.
Previously on garbanzo..
func _on_ball_position_changed(bone_index, bone_pos):
skeleton_3d.set_bone_pose_position(bone_index,bone_pos)
pass
Working code:
func _on_ball_position_changed(bone_index, bone_pos):
var pos = bone_pos * skeleton_3d.global_transform
skeleton_3d.set_bone_pose_position(bone_index,pos)
pass
So the problem was the transforms3d as per usual..
Another culprit is that skeleton_3d.get_bone_global_pose
and skeleton_3d.set_bone_pose_position
work in local coord space relative to skeleton.
But.. as per usual, some things are still not working.. .. In the video i try to move the child-bone
and this messes up everything.. mowing root-bone
works as expected.
Still need to work on the child node manipulations..
func get_bones():
var bone_count = skeleton_3d.get_bone_count()
if bone_count <1:
return
for b_index in range(0,bone_count-1):
var b_pos = skeleton_3d.get_bone_global_pose(b_index)
var pos = skeleton_3d.global_transform * b_pos * global_transform
var new_ball:Ball = ball.instantiate()
new_ball.ball_position_changed.connect(_on_ball_position_changed)
new_ball.bone_index = b_index
new_ball.cam = cam
kuligs2 whats a shape key?
Surprising question… well it's a mesh change (similar to what you're doing), just in a different, more traditional way.
xyz Blend shapes are per-vertex animation technique.
I mean, both are changes to the meshes. Yeah, in different ways. But they're similar enough in appearance. We don't know the end goal thoroughly. Somehow modifying by bones is supposed to be easier for the engine (so it's sometimes claimed). I want to try it, though I'm still vague about how it might be.
Tomcat so its a blender thing.. not really what im looking for unless the "end" goal i have in mind can be achieved with this.
I agree with xyz, its always transforms..
Tomcat well i didnt know any other way to do what i want - change for instance character shape.. i havent tested this with baked in animations, how it will all work, but the goal is to have character manipulation thingie, that players can set up their char face or any other bone/mesh the way they want.. with limits tho ..
I kinda hate when devs take a shortcut and just give few options to change the hair or have pre baked faces or body types..
I think something similar is in ARK survival game, tho i dont remember if you could adjust face.. i mean if you can adjust bone then face should be no problem.. ??
kuligs2 so its a blender thing.. not really what im looking for unless the "end" goal i have in mind can be achieved with this.
Well, those keys can be transferred to the engine.
well i didnt know any other way to do what i want - change for instance character shape..
Yep, that's exactly what the keys are for.
But character customization is a bit more complicated. Just to give you a very brief rundown on that: you have to be careful to match the rig and the mesh.
Tomcat Well, those keys can be transferred to the engine.
from what i seen keys are like linear manipulation, but idk.. yes i saw you can export to godot, but i dont like that you have to manually select vertices and move to a "maximum" distortion value rather than just modifying the root deformation bone somehow.. idk.. maybe the bone thing wont work out with animations etc.. need more testing..
Tomcat But character customization is a bit more complicated. Just to give you a very brief rundown on that: you have to be careful to match the rig and the mesh.
yeah this i learned, but you need to scale rig + mesh at the same time, and it should be ok, pretty easy to do in godot on node level.
kuligs2 need more testing..
Yeah, I want to try that too.
but you need to scale rig + mesh at the same time, and it should be ok, pretty easy to do in godot on node level.
No, it's not the size (not only the size) but the ratio of the different bones that changes, and this leads to severe distortions.
So i keep breaking things, not sure how and why..
Idea today was to create function that resets the bones to the initial positions. But somehow when i do that the mesh is mangled up.
As a bonus i figured out why the child bone didnt work properly. It was that function that get triggered when the skeleton is updated, so i disabled it and now i can move child bones and the bone/ball is not jumping away from my grip but the mesh is still deforming in not the bone direction but opposite (child bones)
Working code so far:
func get_bones():
var bone_count = skeleton_3d.get_bone_count()
if bone_count <1:
return
for b_index in range(0,bone_count-1):
# works
var b_pos = skeleton_3d.get_bone_global_pose(b_index)
var pos = skeleton_3d.global_transform * b_pos
var new_ball:Ball = ball.instantiate()
new_ball.ball_position_changed.connect(_on_ball_position_changed)
new_ball.bone_index = b_index
new_ball.cam = cam
new_ball.global_transform = pos
ball_nodes.add_child(new_ball)
get_bone_reset_postions()
pass
func _on_ball_position_changed(bone_index, bone_pos):
# works
var pos = bone_pos * skeleton_3d.global_transform
skeleton_3d.set_bone_pose_position(bone_index,pos)
pass
func get_bone_reset_postions():
var bone_count = skeleton_3d.get_bone_count()
if bone_count <1:
return
for b_index in range(0,bone_count-1):
# works
var b_pos = skeleton_3d.get_bone_global_pose(b_index)
var pos = skeleton_3d.global_transform * b_pos
reset_bones_positions[b_index] = pos
print("Reset position get")
func set_bone_reset_postions():
for child:Ball in ball_nodes.get_children():
child.global_transform = reset_bones_positions[child.bone_index]
var pos = reset_bones_positions[child.bone_index].origin * skeleton_3d.global_transform
skeleton_3d.set_bone_pose_position(child.bone_index,pos)
print("Reset position set")
Its all inside the garbanzo - the face scene where i have access to skeleton and ball_node which contains balls that gets spawned by get_bones()