Game Development Community

Shape Animation Problem - HELP!!

by James Urquhart · in Torque Game Engine · 08/29/2003 (12:42 pm) · 3 replies

I've managed to get animation working *partially* in my blender exporter. But of course, theres an annoying problem that i can't seem to get my head around.

The shape is meant to look like (part way through the anim) :

www.kitsuneaye.co.uk/torque/blender_anim2.jpg
But it ends up something like this :
www.kitsuneaye.co.uk/torque/blender_anim1.jpg
I've got the quaternion's right, i've changed the axis to what torque uses, but whatever i do, the mesh isn't being deformed properly! The end bit of the cylinder just seems to think it can rotate slower than the middle, and the middle just goes TOO far and crashes into the rest of the cyliner =/
Its *supposed* to bend nicely like in blender.

And if anyone wants to see this thing in action, download :
Here

Any ideas?

Thanks =)

#1
08/29/2003 (1:03 pm)
Looks like you're not keeping track of your transformation matrices through the whole bone system. For instance, if you look at your verts that are deforming, they appear to be deforming around the root bone. I had to write a few animation plugins for Max before and lets just say that your screen shot is VERY familiar. :)

Anyway make sure you are applying all of the matrices all the way down the bone system.

Hope this helps a little...

John.
#2
08/29/2003 (1:47 pm)
@Bob:

1) The vertexes i have are all assigned to the correct bones. (There are 3, left, middle and center)
2) Im not sure about the node rotations and the node translations. My exporter is exporting every frame, as taken from blender.

In blender, i am executing this code:
# AddSequences Currently creates an "ambient" sequence out of all the frames
def AddSequences(shape):
  readingFrames = 1
  sqf = SeqFlag()
  scene = Blender.Scene.GetCurrent() # Only export current scene
  sq = ShapeSequence()
  sq.name = "ambient" # TODO: perhaps we can somehow extract some sequence names?
  sq.flags = sqf.ArbitraryScale | sqf.Cyclic # Add more flags.
  #sq.flags = 0
  sq.fps = 10.0
  sq.sFrame = scene.startFrame()-1
  sq.eFrame = scene.endFrame()-1
  for frameCount in range(scene.startFrame(),scene.endFrame()):
    # TODO: Loop through bones, note any changes.
    scene.currentFrame(frameCount)
    bcount = 0
    for bone in shape.Bones:
      bBone = findBlenderBone(bone.name)
      nt = NodeTranslation()
      nt.bId = bcount
      nt.frame = frameCount-1 # Frame...
      nt.size = bBone.getSize()
      # getLoc possibly returns offset from orig loc
      nt.pos = bBone.getLoc()
      nt.quat = Blend2TorQuat(bBone.getQuat())
      cquat = nt.quat
      sq.translations.append(nt)
      bcount += 1
    scene.update(1)
  # Add our sequence
  shape.Sequences.append(sq)

The sequence is later written via this code :
# Now print them
  for seq in shape.Sequences:
    print "s %s %d %f %d %d %d" % (seq.name, seq.flags, seq.fps, seq.sFrame, seq.eFrame, getNodeCount(seq.translations))
    for tra in seq.translations:
      print "b %d %d" % (tra.bId, tra.frame) # bone, frame
      print "t %f %f %f" % (tra.pos[0], tra.pos[1], tra.pos[2])
      print "r %f %f %f %f" % (tra.quat[0], tra.quat[1], tra.quat[2], tra.quat[3])
      print "s %f %f %f" % (tra.size[0], tra.size[1], tra.size[2])
      print "x"
    print "x"


And in the file reading code (that makes the final DTS), it goes like :

fscanf(fp, "%d %d", &bIndex, &frame);
     while (!feof(fp) && !bClosed)
     {
     ch = fgetc(fp);
     switch (ch) {
       case 't':
         fscanf(fp, "%f %f %f", &vertex[0], &vertex[1], &vertex[2]);
         s->matters.translation[bIndex] = true;
         translations = &nodeTranslations[s->baseTranslation + bIndex * s->numKeyFrames];
         translations[frame] = nodeDefTranslations[bIndex] + nodeDefRotations[bIndex].apply(Point(vertex[0],vertex[1],vertex[2]) * scaleFactor);
         fgets(buffer, 100, fp);
       break;
       case 'r':
         fscanf(fp, "%f %f %f %f", &qvertex[0], &qvertex[1], &qvertex[2], &qvertex[3]);
         s->matters.rotation[bIndex] = true;

         rotations = &nodeRotations[s->baseTranslation + bIndex * s->numKeyFrames];
	 vecs[0] = qvertex[0];
	 vecs[1] = qvertex[1];
	 vecs[2] = qvertex[2];
	 vecs[3] = qvertex[3];
         rotations[frame] = Quaternion(vecs) * nodeDefRotations[bIndex];
	 // QUAT is X, Y, Z, W
         fgets(buffer, 100, fp);
       break;
       case 's':
       fscanf(fp, "%f %f %f", &vertex[0], &vertex[1], &vertex[2]);
       fgets(buffer, 100, fp);
       break;
       case 'x':
         bClosed = true;
       break;
       default:
         //fgets(buffer, 100, fp);
       break;
     }

   }

As far as i understand it, im writing "BONE X is at position P and rotation R at frame F".... what am i doing wrong? =/
#3
08/29/2003 (4:43 pm)
Sorry I'm not following you...

Are you getting the aggregate transformation for each bone? For example:

Sillyboneroot.transform = blenderboneroot.transform;
Sillybone2.transform = Sillyboneroot.transform * blenderbone2.transform;
Sillybone3.transform = Sillybone2.transform * blenderbone3.transform;
Sillybone4.transform = Sillybone3.transform * blenderbone4.transform;

So bone 4 will have the combined transforms of bones root to 3 and including itself.

Does this make sense (not sure if I'm explaining this well)? Again this is from my experience with Max. Blender may be different, but generally bone systems store each bones transform relative to its parent.

John.