How do write animation to a .egg file ?

I can read animation in a list:

	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(force = True)
			nodeList = actor.getPartBundle("modelRoot").getChildren()[0].getChildren()
			name = nodeList[0].getName()
			newTable = {name:[NodePath[name].getPos(),LVecBase3f(180,180,180)-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[0].getName()]
					nodeList.append(j)
				del nodeList[0]
			returnList.append(newTable)
		return returnList

	self.animationJoints = self.getAnimationTable(self.pandaActor)

I can show they list too:

	def animationGo(self,step):
		self.animationStep=(self.animationStep+len(self.animation)+step)%len(self.animation)
		for i in self.jointList:
			# 使用数组里的数据,为骨骼定位
			j = self.animation[self.animationStep][i]
			self.animationJoints[i].setPos(j[0])
			self.animationJoints[i].setHpr(j[1])
			self.animationJoints[i].setScale(j[2])
			# 还要给bulletJoint定位
			# render.attachNewNode(self.bulletJoint[i]).setPos(j[0])
			# 修改服装的节点
			for k in [self.animationJointsCoat,
					self.animationJointsSkirt,
					self.animationJointsShoes,
					self.animationJointsSocks]:
				k[i].setPos(j[0])
				k[i].setHpr(j[1])
				k[i].setScale(j[2])

but .egg file that I wirte animation difference to old .egg file:

	def save(self):
		myfile = file(sys.path[0] + "/models/" + self.directFileName.get(), 'w')
		print >> myfile, "<CoordinateSystem> { Z-up } "
		print >> myfile, "<Table> {"
		print >> myfile, "  <Bundle> Mesh.042 {"
		print >> myfile, "    <Table> \"<skeleton>\" {"
		# 再获取一遍骨骼的树状结构,这次使用递归,我本来不想用递归的。
		self.RecursionSave(self.pandaActor.getPartBundle("modelRoot").getChildren()[0].getChildren()[0],wirteFile=myfile,space="     ")
		# 保存变形动画部分
		print >> myfile, "    }"
		print >> myfile, "    <Table> morph {"
		for i in self.pandaActor.getPartBundle("modelRoot").getChildren()[1].getChildren():
			print >> myfile, "      <S$Anim>", i.getName(), "{"
			print >> myfile, "        <Scalar> fps { 24 }"
			print >> myfile, "        <V> {", "1.000 "*len(self.animation), "}"
			print >> myfile, "      }"
		print >> myfile, "    }"
		print >> myfile, "  }"
		print >> myfile, "}"
		myfile.close()

	def RecursionSave(self,node,wirteFile,space=""):
		nodeName = node.getName()
		print >> wirteFile, space, "<Table> "+nodeName+" {"
		print >> wirteFile, space, "  <Xfm$Anim> xform {"
		print >> wirteFile, space, "    <Scalar> order { sprht }"
		print >> wirteFile, space, "    <Scalar> fps { 24 }"
		print >> wirteFile, space, "    <Scalar> contents { ijkprhxyz }"
		print >> wirteFile, space, "    <V> {"

		for i in self.animation:
			j = i[nodeName]
			print >> wirteFile, space,"     ",st(j[2][0]),st(j[2][1]),st(j[2][2]),st(j[1][0]),st(j[1][1]),st(j[1][2]),	st(j[0][0]),st(j[0][1]),st(j[0][2])
		print >> wirteFile, space, "    }"
		print >> wirteFile, space, "  }"
		for i in node.getChildren():
			self.RecursionSave(i,space=space+"  ",wirteFile=wirteFile)
		print >> wirteFile, space, "}"

def st(num):
	if num>-0.001 and num<0.001:
		return "0.000"
	else:
		return str(num+0.0000001)[0:5]

The old .egg file:

<CoordinateSystem> { Z-up } 
<Table> {
  <Bundle> Mesh.042 {
    <Table> "<skeleton>" {
      <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
            1.000 1.000 1.000 109.497 -0.000 0.000 0.000 0.689 7.680
            1.000 1.000 1.000 109.497 -0.000 0.000 0.000 0.689 7.628
            1.000 1.000 1.000 109.497 -0.000 0.000 0.000 0.689 7.999
            1.000 1.000 1.000 109.497 -0.000 0.000 0.000 0.689 8.369
            1.000 1.000 1.000 109.497 -0.000 0.000 0.000 0.689 8.308
            1.000 1.000 1.000 109.497 -0.000 0.000 0.000 0.689 8.183
            1.000 1.000 1.000 109.497 -0.000 0.000 0.000 0.689 8.029
            1.000 1.000 1.000 109.497 -0.000 0.000 0.000 0.689 7.938
            1.000 1.000 1.000 109.497 -0.000 0.000 0.000 0.689 8.076
            1.000 1.000 1.000 109.497 -0.000 0.000 0.000 0.689 8.282
          }
        }
        <Table> Spine {
          <Xfm$Anim> xform {
            <Scalar> order { sprht }
            <Scalar> fps { 24 }
            <Scalar> contents { ijkprhxyz }
            <V> {
              1.000 1.000 1.000 -31.236 -0.000 -0.000 0.000 0.200 0.000
              1.000 1.000 1.000 -31.236 -0.000 -0.000 0.000 0.200 -0.000
              1.000 1.000 1.000 -31.236 -0.000 -0.000 0.000 0.200 -0.000
              1.000 1.000 1.000 -31.236 -0.000 -0.000 0.000 0.200 0.000
              1.000 1.000 1.000 -31.236 -0.000 -0.000 0.000 0.200 -0.000
              1.000 1.000 1.000 -31.236 -0.000 -0.000 0.000 0.200 -0.000
              1.000 1.000 1.000 -31.236 -0.000 -0.000 0.000 0.200 -0.000
              1.000 1.000 1.000 -31.236 -0.000 -0.000 0.000 0.200 -0.000
              1.000 1.000 1.000 -31.236 -0.000 -0.000 0.000 0.200 0.000
              1.000 1.000 1.000 -31.236 -0.000 -0.000 0.000 0.200 -0.000
              1.000 1.000 1.000 -31.236 -0.000 -0.000 0.000 0.200 -0.000
              1.000 1.000 1.000 -31.236 -0.000 -0.000 0.000 0.200 -0.000
              1.000 1.000 1.000 -31.236 -0.000 -0.000 0.000 0.200 0.000
              1.000 1.000 1.000 -31.236 -0.000 -0.000 0.000 0.200 -0.000
              1.000 1.000 1.000 -31.236 -0.000 -0.000 0.000 0.200 -0.000
            }
          }
.
.
.
            <Table> Shoulder.L {
              <Xfm$Anim> xform {
                <Scalar> order { sprht }
                <Scalar> fps { 24 }
                <Scalar> contents { ijkprhxyz }
                <V> {
                  1.000 1.000 1.000 -23.275 -15.729 -100.959 0.023 0.153 0.089
                  1.000 1.000 1.000 -23.275 -15.729 -100.959 0.023 0.153 0.089
                  1.000 1.000 1.000 -23.275 -15.729 -100.959 0.023 0.153 0.089
                  1.000 1.000 1.000 -23.275 -15.729 -100.959 0.023 0.153 0.089
                  1.000 1.000 1.000 -23.275 -15.729 -100.959 0.023 0.153 0.089
                  1.000 1.000 1.000 -23.275 -15.729 -100.959 0.023 0.153 0.089
                  1.000 1.000 1.000 -23.275 -15.729 -100.959 0.023 0.153 0.089
                  1.000 1.000 1.000 -23.275 -15.729 -100.959 0.023 0.153 0.089
                  1.000 1.000 1.000 -23.275 -15.729 -100.959 0.023 0.153 0.089
                  1.000 1.000 1.000 -23.275 -15.729 -100.959 0.023 0.153 0.089
                  1.000 1.000 1.000 -23.275 -15.729 -100.959 0.023 0.153 0.089
                  1.000 1.000 1.000 -23.275 -15.729 -100.959 0.023 0.153 0.089
                  1.000 1.000 1.000 -23.275 -15.729 -100.959 0.023 0.153 0.089
                  1.000 1.000 1.000 -23.275 -15.729 -100.959 0.023 0.153 0.089
                  1.000 1.000 1.000 -23.275 -15.729 -100.959 0.023 0.153 0.089
                }
              }

The new .egg file:

<CoordinateSystem> { Z-up } 
<Table> {
  <Bundle> Mesh.042 {
    <Table> "<skeleton>" {
      <Table> Hip {
        <Xfm$Anim> xform {
          <Scalar> order { sprht }
          <Scalar> fps { 24 }
          <Scalar> contents { ijkhprxyz }
          <V> {
            1.000 1.000 1.000 0.000 109.4 0.000 0.000 0.689 8.392
            1.000 1.000 1.000 0.000 109.4 0.000 0.000 0.689 8.333
            1.000 1.000 1.000 0.000 109.4 0.000 0.000 0.689 8.165
            1.000 1.000 1.000 0.000 109.4 0.000 0.000 0.689 7.955
            1.000 1.000 1.000 0.000 109.4 0.000 0.000 0.689 7.798
            1.000 1.000 1.000 0.000 109.4 0.000 0.000 0.689 7.679
            1.000 1.000 1.000 0.000 109.4 0.000 0.000 0.689 7.627
            1.000 1.000 1.000 0.000 109.4 0.000 0.000 0.689 7.999
            1.000 1.000 1.000 0.000 109.4 0.000 0.000 0.689 8.369
            1.000 1.000 1.000 0.000 109.4 0.000 0.000 0.689 8.307
            1.000 1.000 1.000 0.000 109.4 0.000 0.000 0.689 8.182
            1.000 1.000 1.000 0.000 109.4 0.000 0.000 0.689 8.029
            1.000 1.000 1.000 0.000 109.4 0.000 0.000 0.689 7.938
            1.000 1.000 1.000 0.000 109.4 0.000 0.000 0.689 8.076
            1.000 1.000 1.000 0.000 109.4 0.000 0.000 0.689 8.281
          }
        }
        <Table> Spine {
          <Xfm$Anim> xform {
            <Scalar> order { sprht }
            <Scalar> fps { 24 }
            <Scalar> contents { ijkhprxyz }
            <V> {
              1.000 1.000 1.000 0.000 -31.2 0.000 0.000 0.199 0.000
              1.000 1.000 1.000 0.000 -31.2 0.000 0.000 0.199 0.000
              1.000 1.000 1.000 0.000 -31.2 0.000 0.000 0.199 0.000
              1.000 1.000 1.000 0.000 -31.2 0.000 0.000 0.199 0.000
              1.000 1.000 1.000 0.000 -31.2 0.000 0.000 0.199 0.000
              1.000 1.000 1.000 0.000 -31.2 0.000 0.000 0.199 0.000
              1.000 1.000 1.000 0.000 -31.2 0.000 0.000 0.199 0.000
              1.000 1.000 1.000 0.000 -31.2 0.000 0.000 0.199 0.000
              1.000 1.000 1.000 0.000 -31.2 0.000 0.000 0.199 0.000
              1.000 1.000 1.000 0.000 -31.2 0.000 0.000 0.199 0.000
              1.000 1.000 1.000 0.000 -31.2 0.000 0.000 0.199 0.000
              1.000 1.000 1.000 0.000 -31.2 0.000 0.000 0.199 0.000
              1.000 1.000 1.000 0.000 -31.2 0.000 0.000 0.199 0.000
              1.000 1.000 1.000 0.000 -31.2 0.000 0.000 0.199 0.000
              1.000 1.000 1.000 0.000 -31.2 0.000 0.000 0.199 0.000
            }
          }
.
.
.
            <Table> Shoulder.L {
              <Xfm$Anim> xform {
                <Scalar> order { sprht }
                <Scalar> fps { 24 }
                <Scalar> contents { ijkhprxyz }
                <V> {
                  1.000 1.000 1.000 -107. -22.3 -17.0 0.023 0.152 0.089
                  1.000 1.000 1.000 -107. -22.3 -17.0 0.023 0.152 0.089
                  1.000 1.000 1.000 -107. -22.3 -17.0 0.023 0.152 0.089
                  1.000 1.000 1.000 -107. -22.3 -17.0 0.023 0.152 0.089
                  1.000 1.000 1.000 -107. -22.3 -17.0 0.023 0.152 0.089
                  1.000 1.000 1.000 -107. -22.3 -17.0 0.023 0.152 0.089
                  1.000 1.000 1.000 -107. -22.3 -17.0 0.023 0.152 0.089
                  1.000 1.000 1.000 -107. -22.3 -17.0 0.023 0.152 0.089
                  1.000 1.000 1.000 -107. -22.3 -17.0 0.023 0.152 0.089
                  1.000 1.000 1.000 -107. -22.3 -17.0 0.023 0.152 0.089
                  1.000 1.000 1.000 -107. -22.3 -17.0 0.023 0.152 0.089
                  1.000 1.000 1.000 -107. -22.3 -17.0 0.023 0.152 0.089
                  1.000 1.000 1.000 -107. -22.3 -17.0 0.023 0.152 0.089
                  1.000 1.000 1.000 -107. -22.3 -17.0 0.023 0.152 0.089
                  1.000 1.000 1.000 -107. -22.3 -17.0 0.023 0.152 0.089
                }
              }

The h and p and r is wrong !

I think animation matrices in .egg are stored in absolute coordinates, not relative ones.

But the pos is right and the hpr is wrong .

The order matters in the “order” string. This specifies the order in which the rotations of your h, p, r columns are combined. If you just use NodePath.setHpr(), Panda composes them in a certain predefined order, which is (I believe) phr (but I could be wrong).

In the animation file you can specify any order, and if you specify the wrong order, the result will look wrong.

David