i wanna be able to calculate the angle between two bones inside the game and store it in a database i know how to make and insert into the database the angles part that i don’t quite know how
Get the vector between the tail and the head of each bone then use the vector builtin method ‘angle’ to get the angle between those two vectors. ie. angle = vector1.angle(vector2)
what if i want to track the angle during the game ?
This can be done in a script at runtime.
i tried a script before and it keep on giving me the same angle even if the bones moves
ah bone tail and head positions might need to be converted into armature or world space.
cont = G.getCurrentController() own = cont.owner target=own["Targets"] path = logic.expandPath("//") while True: controller = bge.logic.getCurrentController() scene=bge.logic.getCurrentScene() own = controller.owner target=own.actuators["level"] v1=bge.data.objects["Armature"].pose.bones['Elbow_L'].vector v2=bge.data.objects["Armature"].pose.bones['Shoulder_L'].vector v3=bpy.data.objects["Armature"].pose.bones['Hand_L'].vector v4=bpy.data.objects["Armature"].pose.bones['Neck'].vector def dotproduct(v1, v2): return sum((a*b) for a, b in zip(v1, v2)) def length(v): return math.sqrt(dotproduct(v, v)) def angle(v1, v2): return math.acos(dotproduct(v1, v2) / (length(v1) * length(v2)))* 180/ math.pi elbow=int(180-angle(v1,v2)) shoulder=int(angle(v2,v4)) wrist= int(180-angle(v3,v1)) def save(): info1 = str(elbow)+" " file1= open(path+"angle_elbow"+".txt",'a') file1.write(info1) file1.close() info2 = str(wrist)+" " file2 = open(path+"angle_wrist"+".txt",'a') file2.write(info2) file2.close() info3 = str(shoulder)+" " file3 = open(path+"angle_shoulder"+".txt",'a') file3.write(info3) file3.close() print(elbow) if int(target.body)==0: break
this is my code and it dont get updated through the game
While loops can be incredibly volatile when used with the blender game engine. I would recommend against using them if possible.
Also, many of those functions that you have defined are already included in the mathutils module. (i.e the dot product) There are many useful vector functions which you can find here.
okay still the same problem the angles still the same through the game
import os import GameLogic as G import bge from bge import logic import Load import time import math import bpy import mathutils scene=bge.logic.getCurrentScene() cont = G.getCurrentController() own = cont.owner v1=bpy.data.objects["Armature"].pose.bones['Elbow_L'].vector v2=bpy.data.objects["Armature"].pose.bones['Shoulder_L'].vector v3=bpy.data.objects["Armature"].pose.bones['Hand_L'].vector v4=bpy.data.objects["Armature"].pose.bones['Neck'].vector def dotproduct(v1, v2): return sum((a*b) for a, b in zip(v1, v2)) def length(v): return math.sqrt(dotproduct(v, v)) def angle(v1, v2): return math.acos(dotproduct(v1, v2) / (length(v1) * length(v2))) elbow=int(180-angle(v1,v2)) shoulder=int(angle(v2,v4)) wrist= int(180-angle(v3,v1)) print(elbow +","+shoulder+","+wrist)
Although the code gets the correct bone angle at the beginning of the game … it Keeps printing the same angle although the armature moves during the game
note: the script is attached to “always sensor” running on "true edge triggered frequency "
dont use bpy its not meant for game engine and the data does not change within runtime as all objects are converted to game objects and only the game objects attributes change during runtime, to access bones use something like armature_object.channels.bone
can i get the bone vector form channels or only the positions ?
I gave it a try and this seems to work though I don’t think its a signed angle there are many different ways to go about getting the angle difference I suggest you just do some experimentation.
from bge import logicfrom math import degrees def get_bone_angle_diff(arm, bone1, bone2): scene = logic.getCurrentScene() bone1_ch = scene.objects[arm].channels[bone1] bone2_ch = scene.objects[arm].channels[bone2] bone1_vec = bone1_ch.pose_tail-bone1_ch.pose_head bone2_vec = bone2_ch.pose_tail-bone2_ch.pose_head print(degrees(bone1_vec.angle(bone2_vec))) def bone_info(): get_bone_angle_diff('Armature', 'Bone', 'Bone.001')
@Siegel, getting the vector between bone head and tail will override the Z rotation value, instead use bone.pose_matrix * armature.worldTransform.
Here’s something I’ve been doing recently that involves getting the full transforms of bones. I’m not on PC so sorry can’t just extract that only code part.
(that blend file simply adds rigid cubes with bone positions and orientations and adds joints between them, basically constructing a ragdoll out of armature)
bonetransforms.blend (528 KB)
I tried doing this, but ened up parenting empties to each bone(I needed them anyway) and then