I want get Joints position into a List

The code like this:

def getAnimation(self,
		actor="models/c_a_b_body",
		animation="models/c_a_b_body-run",
		jointList=["Hip","Spine","Ribcage","Neck","Head",
			"Shoulder.L","Upperarm.L","Forearm.L","Hand.L","Finger_B.L","Pinger_A.L",
			"Shoulder.R","Upperarm.R","Forearm.R","Hand.L","Finger_B.R","Pinger_A.R",
			"Thigh.L","Shin.L","Foot.L","Toe.L",
			"Thigh.R","Shin.R","Foot.R","Toe.R"]):
	actor = Actor(actor,{'animation':animation})
	# 获得总帧数
	totel = actor.getNumFrames('animation')
	returnList = []
	for i in range(0,totel):
		# 停在某一帧
		actor.pose('animation',i)
		newTable = {}
		for j in jointList:
			NodePath = actor.controlJoint(None,"modelRoot",j)
			newTable[j] = (NodePath.getPos(),NodePath.getHpr(),NodePath.getScale())
		returnList.append(newTable)
	return returnList

But each newTable are exactly same, because pose() does not work.

You want exposeJoint(), not controlJoint().

controlJoint() is for write-only changes to the joint transform. The returned NodePath can be modified to move the joint.

exposeJoint() is for read-only access to the joint transform. The returned NodePath will automatically update with the joint’s position.

David

I use exposeJoint() and modified it:

def getAnimation(self,actor="models/c_a_b_body",animation="models/c_a_b_body-run"):
	actor = Actor(actor,{'animation':animation})
	# 获得总帧数
	totel = actor.getNumFrames('animation')
	returnList = []
	for i in range(0,totel):
		# 停在某一帧
		actor.pose('animation',i)
		newTable = {}
		for j in self.jointList:
			NodePath = actor.exposeJoint(None,"modelRoot",j)
			newTable[j] = (NodePath.getPos(),NodePath.getHpr(),NodePath.getScale())
			if j=="Hip":
				print NodePath.getPos()
				print i
		returnList.append(newTable)
	return returnList

I get the Hips position:

But in the c_a_b_body-run.egg:

<Table> Hip {
    <Xfm$Anim> xform {
        <Scalar> order { sprht }
        <Scalar> fps { 24 }
        <Scalar> contents { ijkprhxyz }
        <V> {
            1.000 1.000 1.000 109.497 -0.000 0.000 0.000 0.689 8.393
            1.000 1.000 1.000 109.497 -0.000 0.000 0.000 0.689 8.334
            1.000 1.000 1.000 109.497 -0.000 0.000 0.000 0.689 8.165
            1.000 1.000 1.000 109.497 -0.000 0.000 0.000 0.689 7.956
            1.000 1.000 1.000 109.497 -0.000 0.000 0.000 0.689 7.799
            ......

I should get
LPoint3f(0, 0.689, 8.393),
LPoint3f(0, 0.689, 8.334),
LPoint3f(0, 0.689, 8.165).
By the way, LPoint3f(0, 0.689, 8.305) is position when no animation.

Calling Actor.pose() doesn’t immediately apply the transform to the joints, only when the actor is next computed, which will happen by default when the frame is rendered, or when you query a relative transform from a joint node (instead of just a local transform).

Or you can call Actor.update() to force it to apply the transform immediately.

David

...
...
for i in range(0,totel):
	# 停在某一帧
	actor.pose('anim',i)
	actor.update()
	newTable = {}
	for j in self.jointList:
...
...

I add a actor.update(), I get LPoint3f(0, 0.689, 8.393). It means I get position for first frame, but I can’t get poition for second or third frame.

Maybe I should try to read .egg file directly.

By the way, I just update my graphics driver. Maybe the problem is caused by the graphics driver. I will reboot my computer.

This is not related to your graphics driver; the animation subsystem is computed entirely on the CPU.

I don’t understand why you don’t get the pose for second and later frames. There’s nothing different about those frames. Does it work if you start counting from the second frame instead of the first frame?

Note that you shouldn’t call exposeJoint() again for each frame. You should call it only once for a given joint, and then use that same node for all frames; the exposed joint nodes will accumulate otherwise.

David

I’m sorry. I save joint outside for(), but I still can’t second and later frames:

def getAnimation(self,
			actor="models/c_a_b_body",
			animation="models/c_a_b_body-run"):
	actor = Actor(actor,{'anim':animation})
	# 获得总帧数
	totel = actor.getNumFrames('anim')
	returnList = []
	# 获得骨骼
	NodePath = {}
	for j in self.jointList:
		NodePath[j] = actor.exposeJoint(None,"modelRoot",j)
	for i in range(0,totel):
		# 停在某一帧
		actor.pose('anim',i)
		actor.update()
		newTable = {}
		for j in self.jointList:
			newTable[j] = (NodePath[j].getPos(),(180-NodePath[j].getH(),180-NodePath[j].getP(),180-NodePath[j].getR()),NodePath[j].getScale())
			if j=="Hip" or j=="Spine" or j=="Ribcage":
				print j
				print newTable[j]
				print i
		returnList.append(newTable)
	return returnList

If I use range(3,totel) instead range(0,totel), I get LPoint3f(0, 0.689, 7.956), it’s fourth frame. I decided to read .egg file directly.

OK, strange. I wonder if actor.update(force = True) would have worked better?

David

Thank you, it’s work very well!
May be the reasons is I use panda3d1.8.0+cvs20120217~natty261_amd64.deb

for i in range(0,totel):
	# 停在某一帧
	actor.pose('anim',i)
	actor.update(force = True)
	newTable = {"Hip":(NodePath["Hip"].getPos(),NodePath["Hip"].getHpr(),NodePath["Hip"].getScale()),
			"Shoulder.L":(NodePath["Shoulder.L"].getPos(NodePath["Ribcage"]),
						NodePath["Shoulder.L"].getHpr(NodePath["Ribcage"]),
						NodePath["Shoulder.L"].getScale(NodePath["Ribcage"])),
			"Shoulder.R":(NodePath["Shoulder.R"].getPos(NodePath["Ribcage"]),
						NodePath["Shoulder.R"].getHpr(NodePath["Ribcage"]),
						NodePath["Shoulder.R"].getScale(NodePath["Ribcage"])),
			"Thigh.L":(NodePath["Thigh.L"].getPos(NodePath["Hip"]),
					NodePath["Thigh.L"].getHpr(NodePath["Hip"]),
					NodePath["Thigh.L"].getScale(NodePath["Hip"])),
			"Thigh.R":(NodePath["Thigh.R"].getPos(NodePath["Hip"]),
					NodePath["Thigh.R"].getHpr(NodePath["Hip"]),
					NodePath["Thigh.R"].getScale(NodePath["Hip"]))}
	for i in range(0,4):
		n = ["Spine","Ribcage","Neck","Head"][i]
		p = ["Hip","Spine","Ribcage","Neck"][i]
		newTable[n] = (NodePath[n].getPos(NodePath[p]),NodePath[n].getHpr(NodePath[p]),NodePath[n].getScale(NodePath[p]))
	for j in [".L",".R"]:
		for i in range(0,8):
			n = ["Upperarm","Forearm","Hand","Finger_B","Pinger_A","Shin","Foot","Toe"][i]
			p = ["Shoulder","Upperarm","Forearm","Hand","Hand","Thigh","Shin","Foot"][i]
			newTable[n+j] = (NodePath[n+j].getPos(NodePath[p+j]),NodePath[n+j].getHpr(NodePath[p+j]),NodePath[n+j].getScale(NodePath[p+j]))
	returnList.append(newTable)

If I was able to automatically get the tree structure of the joints, so much the better.

You can call getPartBundle() to get the root of the joint hierarchy, then recursively call getChildren() to walk through the entire hierarchy.

David

Thank you!

nodeList = actor.getPartBundle("modelRoot").getChildren()[0].getChildren()
name = nodeList[0].getName()
newTable = {name:(NodePath[name].getPos(),NodePath[name].getHpr(),NodePath[name].getScale())}
while nodeList:
	parent = NodePath[nodeList[0].getName()]
	for j in nodeList[0].getChildren():
		child = NodePath[j.getName()]
		newTable[j.getName()] = (child.getPos(parent),child.getHpr(parent),child.getScale(parent))
		nodeList.append(j)
	del nodeList[0]