How can I modify a pose made in Blender?

I want to create a VR game using Panda3DVr (Thanks el-dee!) and ran into a problem. I have a pose and want to move it. However, there doesn’t seem to be a way to do this. Can you help? Thanks in advance.

You can use control joints.

Okay, I rigged a hand model, but don’t know how to rotate my bone. Can you help? Thanks!

Once you’ve acquired a NodePath that controls the bone (as shown in Moguri’s link, above), just rotate that NodePath like any other, and the bone should follow.

Alright, is Yaw the same as H in HPR or are they different things?

Going by the dictionary definition of “yaw”–“rotation around the vertical axis”, in short–I think so, yes. Just note that the “vertical axis” is, by default, relative to the parent of the node in question, not absolute, so rotations of the parent will change which way that axis points.

I tried controlJoint but it appears to be just NoneType on my OBJ that I exported from Blender.
Can you help? Thanks.
EDIT:
Here’s the error:

Traceback (most recent call last):
  File "C:\Users\zurgE\AppData\Local\Programs\Python\Python37-32\lib\site-packages\p3dopenvr\p3dopenvr.py", line 233, in update_poses_task
    self.update_tracked_devices()
  File "C:\Users\zurgE\AppData\Local\Programs\Python\Python37-32\lib\site-packages\p3dopenvr\p3dopenvr.py", line 200, in update_tracked_devices
    self.update_tracked_device(i, pose)
  File "C:\Users\zurgE\AppData\Local\Programs\Python\Python37-32\lib\site-packages\p3dopenvr\p3dopenvr.py", line 188, in update_tracked_device
    self.new_tracked_device(device_index, device_anchor)
  File "C:/Users/zurgE/OneDrive/Documents/3D Python programs/use_your_hands.py", line 81, in new_tracked_device
    self.thumb.setHpr(quaternion_to_euler(90,0,0,0))
AttributeError: 'NoneType' object has no attribute 'setHpr'
Traceback (most recent call last):
  File "C:/Users/zurgE/OneDrive/Documents/3D Python programs/use_your_hands.py", line 102, in <module>
    app.run()
  File "C:\Users\zurgE\AppData\Local\Programs\Python\Python37-32\lib\site-packages\direct\showbase\ShowBase.py", line 3152, in run
    self.taskMgr.run()
  File "C:\Users\zurgE\AppData\Local\Programs\Python\Python37-32\lib\site-packages\direct\task\Task.py", line 537, in run
    self.step()
  File "C:\Users\zurgE\AppData\Local\Programs\Python\Python37-32\lib\site-packages\direct\task\Task.py", line 491, in step
    self.mgr.poll()
  File "C:\Users\zurgE\AppData\Local\Programs\Python\Python37-32\lib\site-packages\p3dopenvr\p3dopenvr.py", line 233, in update_poses_task
    self.update_tracked_devices()
  File "C:\Users\zurgE\AppData\Local\Programs\Python\Python37-32\lib\site-packages\p3dopenvr\p3dopenvr.py", line 200, in update_tracked_devices
    self.update_tracked_device(i, pose)
  File "C:\Users\zurgE\AppData\Local\Programs\Python\Python37-32\lib\site-packages\p3dopenvr\p3dopenvr.py", line 188, in update_tracked_device
    self.new_tracked_device(device_index, device_anchor)
  File "C:/Users/zurgE/OneDrive/Documents/3D Python programs/use_your_hands.py", line 81, in new_tracked_device
    self.thumb.setHpr(quaternion_to_euler(90,0,0,0))
AttributeError: 'NoneType' object has no attribute 'setHpr'

Could you show us the code in which you call “controlJoint”, please, and–if it’s different–the code in which you assign the variable “self.thumb”?

Yep! Here it is:

from direct.showbase.ShowBase import ShowBase
from panda3d.core import PointLight, AmbientLight
from panda3d.core import LightRampAttrib, AuxBitplaneAttrib
from panda3d.core import LightRampAttrib, AuxBitplaneAttrib
from panda3d.core import DirectionalLight
from panda3d.core import Spotlight
from panda3d.core import PerspectiveLens
from panda3d.core import NodePath
from panda3d.core import PandaNode, LightNode, TextNode
from direct.actor.Actor import Actor
from math import pi, sin, cos
from p3dopenvr.p3dopenvr import P3DOpenVR
import openvr
from direct.actor.Actor import Actor
def quaternion_to_euler(x, y, z, w):

    t0 = +2.0 * (w * x + y * z)
    t1 = +1.0 - 2.0 * (x * x + y * y)
    roll = math.atan2(t0, t1)
    t2 = +2.0 * (w * y - z * x)
    t2 = +1.0 if t2 > +1.0 else t2
    t2 = -1.0 if t2 < -1.0 else t2
    pitch = math.asin(t2)
    t3 = +2.0 * (w * z + x * y)
    t4 = +1.0 - 2.0 * (y * y + z * z)
    yaw = math.atan2(t3, t4)
    return [yaw, pitch, roll]
class MinimalOpenVR(P3DOpenVR):
    classes_map = { openvr.TrackedDeviceClass_Invalid: 'Invalid',
                    openvr.TrackedDeviceClass_HMD: 'HMD',
                    openvr.TrackedDeviceClass_Controller: 'Controller',
                    openvr.TrackedDeviceClass_GenericTracker: 'Generic tracker',
                    openvr.TrackedDeviceClass_TrackingReference: 'Tracking reference',
                    openvr.TrackedDeviceClass_DisplayRedirect: 'Display redirect',
                  }

    roles_map = { openvr.TrackedControllerRole_Invalid: 'Invalid',
                  openvr.TrackedControllerRole_LeftHand: 'Left',
                  openvr.TrackedControllerRole_RightHand: 'Right',
                  openvr.TrackedControllerRole_OptOut: 'Opt out',
                  openvr.TrackedControllerRole_Treadmill: 'Treadmill',
                  openvr.TrackedControllerRole_Stylus: 'Stylus',
                }

    buttons_map = { openvr.k_EButton_System: 'System',
                    openvr.k_EButton_ApplicationMenu: 'Application Menu',
                    openvr.k_EButton_Grip: 'Grip',
                    openvr.k_EButton_DPad_Left: 'Pad left',
                    openvr.k_EButton_DPad_Up: 'Pad up',
                    openvr.k_EButton_DPad_Right: 'Pad right',
                    openvr.k_EButton_DPad_Down: 'Pad down',
                    openvr.k_EButton_A: 'A',
                    openvr.k_EButton_ProximitySensor: 'Proximity sensor',
                    openvr.k_EButton_Axis0: 'Axis 0',
                    openvr.k_EButton_Axis1: 'Axis 1',
                    openvr.k_EButton_Axis2: 'Axis 2',
                    openvr.k_EButton_Axis3: 'Axis 3',
                    openvr.k_EButton_Axis4: 'Axis 4',
                    #openvr.k_EButton_SteamVR_Touchpad: 'Touchpad',
                    #openvr.k_EButton_SteamVR_Trigger: 'Trigger',
                    #openvr.k_EButton_Dashboard_Back: 'Dashboard back',
                    #openvr.k_EButton_IndexController_A: 'Controller A',
                    #openvr.k_EButton_IndexController_B: 'Controller B',
                    #openvr.k_EButton_IndexController_JoyStick: 'Controller joystick',
                  }

    button_events_map = { openvr.VREvent_ButtonPress: 'Press',
                          openvr.VREvent_ButtonUnpress: 'Unpress',
                          openvr.VREvent_ButtonTouch: 'Touch',
                          openvr.VREvent_ButtonUntouch: 'Untouch'
                        }

    def new_tracked_device(self, device_index, device_anchor):
        print("Adding new device", device_anchor.name)
        device_class = self.vr_system.getTrackedDeviceClass(device_index)
        if device_class == openvr.TrackedDeviceClass_Controller:
            self.model = Actor("hand3.fbx")
            self.model.reparent_to(device_anchor)
            self.model.set_scale(3)
            print(self.model.getJoints())
            self.thumb = self.model.controlJoint(None,"modelRoot","finger_thumb_l_aux")
            self.thumb.setHpr(quaternion_to_euler(90,0,0,0))
        else:
            print(device_class)
            model = loader.loadModel("camera")
            model.reparent_to(device_anchor)
            model.set_scale(0.1)


class App(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)
        self.disableMouse()
        #self.hand = Actor('hand3.obj')
        #self.hand.setScale(0.25,0.25,0.25)
        self.vr = MinimalOpenVR()
        self.vr.init()
        #self.hand.setPos(0,-10,0)
        
        #self.hand.reparentTo(self.render)
        
app = App()
app.run()

EDIT: Here is where I load the model and expose the joint

            self.model = Actor("hand3.fbx")
            self.model.reparent_to(device_anchor)
            self.model.set_scale(3)
            print(self.model.getJoints())
            self.thumb = self.model.controlJoint(None,"modelRoot","finger_thumb_l_aux")
            self.thumb.setHpr(quaternion_to_euler(90,0,0,0))

Would you mind posting the output from the line " print(self.model.getJoints())" in your code, please?

@Thaumaturge The output is []

Ah! Well, there’s the problem then, presumably: your model as loaded doesn’t have any joints, and thus the call to “controlJoint” fails and returns “None”.

I’m not familiar with “fbx” files, myself; do they hold armature-data?

@Thaumaturge Yes they do hold bone data. Could it be how blender is exporting it?
Loading the model in blender results in the bones showing up.

It could well be something to do with exportation. Again, I don’t really use the “fbx” format myself, so I don’t know much about its use or exporting, and thus I’m afraid that I’m not in much of a position to offer specific help there! :/

Perhaps search the forum–someone else might have had a similar problem, or have posted some piece of information that may help!

1 Like