Model Joints

Can anyone point me to a good tutorial of how “Joints” on models work?

Ummm well since no one seems to be able to help find me good examples. Here is some none working code that I have


import direct.directbase.DirectStart
import sys,os
from pandac.PandaModules import Filename
from direct.task import Task
from direct.gui.OnscreenText import OnscreenText 
from direct.actor import Actor
from direct.gui.DirectGui import *

pathname = os.path.abspath(sys.path[0])
pathname = Filename.fromOsSpecific(pathname).getFullpath()

base.disableMouse()

neko = Actor.Actor(pathname + "/BrotherLittle/littlebrother")

nekoElbow = neko.controlJoint(None, pathname + "/BrotherLittle/littlebrother", "LeftElbow")

Could anyone help me turn it into working code?

The second parameter to controlJoint() should be the literal string “modelRoot”, not the path to your actor model.

This parameter refers to the particular subpart of the actor whose joint you wish to control; the only time it is ever something other than “modelRoot” is when you have a multi-part Actor, which is a more advanced feature.

David

Ahhh… I see cool thanks.

Next question… what functions do I use to manipulate a joint once I have control over it?

You can use the normal NodePath interface on the NodePath returned from controlJoint. For instance, setPos(), setHpr(), lookAt(), etc.

One of the tutorials that ships with Panda illustrates doing exactly this.

David

Hmmmm… I will look into the tutorials.

Hurray for new code that does not work at all. Help please.


import direct.directbase.DirectStart
import sys,os
from pandac.PandaModules import *
from direct.task import Task
from direct.gui.OnscreenText import OnscreenText 
from direct.actor import Actor
from direct.gui.DirectGui import *
from direct.showbase import DirectObject

pathname = os.path.abspath(sys.path[0])
pathname = Filename.fromOsSpecific(pathname).getFullpath()

def restrain(i, mn = -1, mx = 1): return min(max(i, mn), mx)

base.disableMouse()

base.camera.setPos(0, -25, 0)

class HandMove(DirectObject.DirectObject):
	def __init__(self):
		self.neko = Actor.Actor(pathname + "/LittleBrother/littlebrother")
		self.neko.reparentTo(render)
		self.neko.setPos(0,0, -5)
		self.neko.setScale(3)
		
		self.nekoElbow = self.neko.controlJoint(None, "modelRoot", "LeftShoulder")
		
		self.accept('v', self.moveHUp)
		self.accept('b', self.moveHDown)
		self.accept('y', self.movePUp)
		self.accept('u', self.movePDown)
		self.accept('z', self.moveRUp)
		self.accept('x', self.moveRDown)
		
	def moveHUp(self):
		self.nekoElbow.setH(self.nekoElbow.getH() + 1)
		print "Position H:" + str(self.nekoElbow.getH()) + " P:" + str(self.nekoElbow.getP()) + " R:" + str(self.nekoElbow.getR())
	
	def moveHDown(self):
		self.nekoElbow.setH(self.nekoElbow.getH() - 1)
		print "Position H:" + str(self.nekoElbow.getH()) + " P:" + str(self.nekoElbow.getP()) + " R:" + str(self.nekoElbow.getR())
		
	def movePUp(self):
		self.nekoElbow.setP(self.nekoElbow.getP() + 1)
		print "Position H:" + str(self.nekoElbow.getH()) + " P:" + str(self.nekoElbow.getP()) + " R:" + str(self.nekoElbow.getR())
		
	def movePDown(self):
		self.nekoElbow.setP(self.nekoElbow.getP() - 1)
		print "Position H:" + str(self.nekoElbow.getH()) + " P:" + str(self.nekoElbow.getP()) + " R:" + str(self.nekoElbow.getR())
		
	def moveRUp(self):
		self.nekoElbow.setR(self.nekoElbow.getR() + 1)
		print "Position H:" + str(self.nekoElbow.getH()) + " P:" + str(self.nekoElbow.getP()) + " R:" + str(self.nekoElbow.getR())
		
	def moveRDown(self):
		self.nekoElbow.setR(self.nekoElbow.getR() - 1)
		print "Position H:" + str(self.nekoElbow.getH()) + " P:" + str(self.nekoElbow.getP()) + " R:" + str(self.nekoElbow.getR())
		
		
class TheCamera(DirectObject.DirectObject):
	def __init__(self):
		self.x = 0
		self.y = 0
		self.z = 0
		
		self.h = 0
		self.p = 0
		self.r = 0
		base.camera.setPos(self.x, self.y, self.z)
		base.camera.setHpr(self.h, self.p, self.r)
		
		self.camPos = OnscreenText(text = "Camera Position " + str(self.x) + ", " + str(self.y) + ", " + str(self.z), style=1, fg=(1,0,0,1), pos=(0.8,-0.95), scale = .07, mayChange=1)
		self.camHPR = OnscreenText(text = "HPR " + str(self.h) + ", " + str(self.p) + ", " + str(self.r), style = 1, fg=(0,1,0,1), pos=(0.8, -0.85), scale = .07, mayChange=1)
		self.cam = 1
		
		self.accept('c', self.changeCam)
		self.accept('1', self.moveOnePlus)
		self.accept('4', self.moveOneMinus)
		self.accept('2', self.moveTwoPlus)
		self.accept('5', self.moveTwoMinus)
		self.accept('3', self.moveThreePlus)
		self.accept('6', self.moveThreeMinus)
		
	def moveOneMinus(self):
		if self.cam == 1:
			self.x = self.x - 1
			base.camera.setPos(self.x, self.y, self.z)
			text = "Camera Position " + str(self.x) + ", " + str(self.y) + ", " + str(self.z)
			self.camPos.setText(text)
		else:
			self.h = self.h - 1
			base.camera.setHpr(self.h, self.p, self.r)
			text = "HPR " + str(self.h) + ", " + str(self.p) + ", " + str(self.r)
			self.camHPR.setText(text)
	
	def moveOnePlus(self):
		if self.cam == 1:
			self.x = self.x + 1
			base.camera.setPos(self.x, self.y, self.z)
			text = "Camera Position " + str(self.x) + ", " + str(self.y) + ", " + str(self.z)
			self.camPos.setText(text)
		else:
			self.h = self.h + 1
			base.camera.setHpr(self.h, self.p, self.r)
			text = "HPR " + str(self.h) + ", " + str(self.p) + ", " + str(self.r)
			self.camHPR.setText(text)
	
	def moveTwoMinus(self):
		if self.cam == 1:
			self.y = self.y - 1
			base.camera.setPos(self.x, self.y, self.z)
			text = "Camera Position " + str(self.x) + ", " + str(self.y) + ", " + str(self.z)
			self.camPos.setText(text)
		else:
			self.p = self.p - 1
			base.camera.setHpr(self.h, self.p, self.r)
			text = "HPR " + str(self.h) + ", " + str(self.p) + ", " + str(self.r)
			self.camHPR.setText(text)
	
	def moveTwoPlus(self):
		if self.cam == 1:
			self.y = self.y + 1
			base.camera.setPos(self.x, self.y, self.z)
			text = "Camera Position " + str(self.x) + ", " + str(self.y) + ", " + str(self.z)
			self.camPos.setText(text)
		else:
			self.p = self.p + 1
			base.camera.setHpr(self.h, self.p, self.r)
			text = "HPR " + str(self.h) + ", " + str(self.p) + ", " + str(self.r)
			self.camHPR.setText(text)

	def moveThreePlus(self):
		if self.cam == 1:
			self.z = self.z + 1
			base.camera.setPos(self.x, self.y, self.z)
			text = "Camera Position " + str(self.x) + ", " + str(self.y) + ", " + str(self.z)
			self.camPos.setText(text)
		else:
			self.r = self.r + 1
			base.camera.setHpr(self.h, self.p, self.r)
			text = "HPR " + str(self.h) + ", " + str(self.p) + ", " + str(self.r)
			self.camHPR.setText(text)
			
	def moveThreeMinus(self):
		if self.cam == 1:
			self.z = self.z - 1
			base.camera.setPos(self.x, self.y, self.z)
			text = "Camera Position " + str(self.x) + ", " + str(self.y) + ", " + str(self.z)
			self.camPos.setText(text)
		else:	
			self.r = self.r - 1
			base.camera.setHpr(self.h, self.p, self.r)
			text = "HPR " + str(self.h) + ", " + str(self.p) + ", " + str(self.r)
			self.camHPR.setText(text)
			
	def changeCam(self):
		if self.cam == 0:
			self.cam = 1
			print "Camera " + str(self.cam)
		else:
			self.cam = 0
			print "HPR " + str(self.cam)
		
c = TheCamera()		
h = HandMove()
run()

The actor needs to load an animation and loop through it. The animation could be a single frame animation that doesn’t actually move any joints, but some kind of animation needs to be playing.

Thanks for reminding me

But now this code does not do what I want it too. More Help please


import direct.directbase.DirectStart
import sys,os
from pandac.PandaModules import *
from direct.task import Task
from direct.gui.OnscreenText import OnscreenText 
from direct.actor import Actor
from direct.gui.DirectGui import *
from direct.showbase import DirectObject

pathname = os.path.abspath(sys.path[0])
pathname = Filename.fromOsSpecific(pathname).getFullpath()

def restrain(i, mn = -1, mx = 1): return min(max(i, mn), mx)

base.disableMouse()

base.camera.setPos(0, -25, 0)

class HandMove(DirectObject.DirectObject):
	def __init__(self):
		self.neko = Actor.Actor(pathname + "/BroMan/bromanactormodel", {"anime":pathname + "/BroMan/bromanactoranim"})
		self.neko.reparentTo(render)
		self.neko.setPos(0,0, -5)
		self.neko.setScale(3)
		
		self.neko.loop("anime")
		
		self.nekoElbow = self.neko.controlJoint(None, "modelRoot", "bromanLeftShoulder")
		
		self.accept('v', self.moveHUp)
		self.accept('b', self.moveHDown)
		self.accept('y', self.movePUp)
		self.accept('u', self.movePDown)
		self.accept('z', self.moveRUp)
		self.accept('x', self.moveRDown)
		
	def moveHUp(self):
		self.nekoElbow.setX(self.nekoElbow.getH() + 1)
		print "Position X:" + str(self.nekoElbow.getX()) + " Y:" + str(self.nekoElbow.getY()) + " Z:" + str(self.nekoElbow.getZ())
	
	def moveHDown(self):
		self.nekoElbow.setX(self.nekoElbow.getX() - 1)
		print "Position X:" + str(self.nekoElbow.getX()) + " Y:" + str(self.nekoElbow.getY()) + " Z:" + str(self.nekoElbow.getZ())
		
	def movePUp(self):
		self.nekoElbow.setY(self.nekoElbow.getY() + 1)
		print "Position X:" + str(self.nekoElbow.getX()) + " Y:" + str(self.nekoElbow.getY()) + " Z:" + str(self.nekoElbow.getZ())
		
	def movePDown(self):
		self.nekoElbow.setY(self.nekoElbow.getY() - 1)
		print "Position X:" + str(self.nekoElbow.getX()) + " Y:" + str(self.nekoElbow.getY()) + " Z:" + str(self.nekoElbow.getZ())
		
	def moveRUp(self):
		self.nekoElbow.setZ(self.nekoElbow.getZ() + 1)
		print "Position X:" + str(self.nekoElbow.getX()) + " Y:" + str(self.nekoElbow.getY()) + " Z:" + str(self.nekoElbow.getZ())
		
	def moveRDown(self):
		self.nekoElbow.setZ(self.nekoElbow.getZ() - 1)
		print "Position X:" + str(self.nekoElbow.getX()) + " Y:" + str(self.nekoElbow.getY()) + " Z:" + str(self.nekoElbow.getZ())
		
		
class TheCamera(DirectObject.DirectObject):
	def __init__(self):
		self.x = 0
		self.y = 0
		self.z = 0
		
		self.h = 0
		self.p = 0
		self.r = 0
		base.camera.setPos(self.x, self.y, self.z)
		base.camera.setHpr(self.h, self.p, self.r)
		
		self.camPos = OnscreenText(text = "Camera Position " + str(self.x) + ", " + str(self.y) + ", " + str(self.z), style=1, fg=(1,0,0,1), pos=(0.8,-0.95), scale = .07, mayChange=1)
		self.camHPR = OnscreenText(text = "HPR " + str(self.h) + ", " + str(self.p) + ", " + str(self.r), style = 1, fg=(0,1,0,1), pos=(0.8, -0.85), scale = .07, mayChange=1)
		self.cam = 1
		
		self.accept('c', self.changeCam)
		self.accept('1', self.moveOnePlus)
		self.accept('4', self.moveOneMinus)
		self.accept('2', self.moveTwoPlus)
		self.accept('5', self.moveTwoMinus)
		self.accept('3', self.moveThreePlus)
		self.accept('6', self.moveThreeMinus)
		
	def moveOneMinus(self):
		if self.cam == 1:
			self.x = self.x - 1
			base.camera.setPos(self.x, self.y, self.z)
			text = "Camera Position " + str(self.x) + ", " + str(self.y) + ", " + str(self.z)
			self.camPos.setText(text)
		else:
			self.h = self.h - 1
			base.camera.setHpr(self.h, self.p, self.r)
			text = "HPR " + str(self.h) + ", " + str(self.p) + ", " + str(self.r)
			self.camHPR.setText(text)
	
	def moveOnePlus(self):
		if self.cam == 1:
			self.x = self.x + 1
			base.camera.setPos(self.x, self.y, self.z)
			text = "Camera Position " + str(self.x) + ", " + str(self.y) + ", " + str(self.z)
			self.camPos.setText(text)
		else:
			self.h = self.h + 1
			base.camera.setHpr(self.h, self.p, self.r)
			text = "HPR " + str(self.h) + ", " + str(self.p) + ", " + str(self.r)
			self.camHPR.setText(text)
	
	def moveTwoMinus(self):
		if self.cam == 1:
			self.y = self.y - 1
			base.camera.setPos(self.x, self.y, self.z)
			text = "Camera Position " + str(self.x) + ", " + str(self.y) + ", " + str(self.z)
			self.camPos.setText(text)
		else:
			self.p = self.p - 1
			base.camera.setHpr(self.h, self.p, self.r)
			text = "HPR " + str(self.h) + ", " + str(self.p) + ", " + str(self.r)
			self.camHPR.setText(text)
	
	def moveTwoPlus(self):
		if self.cam == 1:
			self.y = self.y + 1
			base.camera.setPos(self.x, self.y, self.z)
			text = "Camera Position " + str(self.x) + ", " + str(self.y) + ", " + str(self.z)
			self.camPos.setText(text)
		else:
			self.p = self.p + 1
			base.camera.setHpr(self.h, self.p, self.r)
			text = "HPR " + str(self.h) + ", " + str(self.p) + ", " + str(self.r)
			self.camHPR.setText(text)

	def moveThreePlus(self):
		if self.cam == 1:
			self.z = self.z + 1
			base.camera.setPos(self.x, self.y, self.z)
			text = "Camera Position " + str(self.x) + ", " + str(self.y) + ", " + str(self.z)
			self.camPos.setText(text)
		else:
			self.r = self.r + 1
			base.camera.setHpr(self.h, self.p, self.r)
			text = "HPR " + str(self.h) + ", " + str(self.p) + ", " + str(self.r)
			self.camHPR.setText(text)
			
	def moveThreeMinus(self):
		if self.cam == 1:
			self.z = self.z - 1
			base.camera.setPos(self.x, self.y, self.z)
			text = "Camera Position " + str(self.x) + ", " + str(self.y) + ", " + str(self.z)
			self.camPos.setText(text)
		else:	
			self.r = self.r - 1
			base.camera.setHpr(self.h, self.p, self.r)
			text = "HPR " + str(self.h) + ", " + str(self.p) + ", " + str(self.r)
			self.camHPR.setText(text)
			
	def changeCam(self):
		if self.cam == 0:
			self.cam = 1
			print "Camera " + str(self.cam)
		else:
			self.cam = 0
			print "HPR " + str(self.cam)
		
c = TheCamera()		
h = HandMove()
run()

Seriously I do not get it.

I am not sure if you want to rotate the joint or reposition it.

This is your code:

def moveHUp(self):
      self.nekoElbow.setX(self.nekoElbow.getH() + 1)
      print "Position X:" + str(self.nekoElbow.getX()) + " Y:" + str(self.nekoElbow.getY()) + " Z:" + str(self.nekoElbow.getZ()) 

To rotate the elbow properly, you will want it to look like this:

def moveHUp(self):
      self.nekoElbow.setH(self.nekoElbow.getH() + 1)
      print "Rotation H:" + str(self.nekoElbow.getH()) + " P:" + str(self.nekoElbow.getP()) + " R:" + str(self.nekoElbow.getR())

To reposition the elbow, you might want to re-name your function to moveXUp() so its less confusing:

def moveXUp(self):
      self.nekoElbow.setX(self.nekoElbow.getX() + 1)
      print "Position X:" + str(self.nekoElbow.getX()) + " Y:" + str(self.nekoElbow.getY()) + " Z:" + str(self.nekoElbow.getZ()) 

Yeah I am doing the stuff to rotate the arm but it is still not working

what is not working? what happens when you press the keys? Is this after you changed all of your code to the correct functions ( ex: change setY() to setP() )?

I did change the functions to setH(), setP(), setR() not doing what I want it too.

More questions…

Is the joint rotating in a way you don’t want it to visually, or is it not rotating at all? What does the debug output tell you? Do the values change by 1 degree when you press a key? What do you want it to do, and how is it behaving differently?

Nope there is no visible motion at all. I just want the joint to rotate around. That is all I want it too do.

ok. try to increase the change in angle…

def movePUp(self):
      self.nekoElbow.setP(self.nekoElbow.getP() + 15)
      print "Rotation H:" + str(self.nekoElbow.getH()) + " P:" + str(self.nekoElbow.getP()) + " R:" + str(self.nekoElbow.getR())

do your print statements show a change in angle at all?