Pose.kl

Types

Pose (object)

An object storing the pose of a Character

The Pose object stores the pose of a character, based on a given skeleton.

Custom Pose objects can be created that provide other methods for computing the pose of a character. For example, a pose object could pull the pose data directly from a cache file, or compute it using a simulation algorithm.

/*
** Example: pose.kl
*/

require Characters;

operator entry(){



  //////////////////////////////////
  // Generate a chain of bones with a random shape.
  Bone bones[];
  bones.resize(5);
  Xfo parentXfo();
  for(Integer i=0; i<bones.size(); i++) {

    Bone bone;
    bone.name = "Bone"+i;
    bone.parentIndex = i-1;

    // compute the angles
    Scalar random = 0.5 - mathRandomScalar(12, i);
    Scalar xAngle = sin(random * 0.4 + Scalar(i) * 0.03) * 0.5;
    Scalar zAngle = cos(0.11 + Scalar(i) * 0.01) * 0.1;

    Scalar boneLength = 5.0;
    Xfo xfo;
    xfo.tr = Vec3(boneLength, 0.0, 0.0);
    xfo.ori.setFromEulerAngles(Vec3(xAngle, 0.0f, zAngle));
    bone.referencePose = parentXfo * xfo;
    bone.length = boneLength;
    bone.radius = 1.0;
    bone.setFlag(BONEFLAG_DEFORMER);
    bones[i] = bone;
    parentXfo = bone.referencePose;
  }

  Skeleton skeleton = Skeleton("", bones);
  Character character('Clip');
  character.setSkeleton(skeleton);

  Pose pose(skeleton);
  character.setPose(pose);
  for(Integer i=0; i<bones.size(); i++) {
    report("Pose:" + skeleton.getBone(i).name + " :" + pose.getBoneXfo(i));
  }
}

/*
** Output:

Pose:Bone0 :{ori:{v:{x:-2.880228e-2,y:+1.432589e-3,z:+0.049656},w:+0.998349},tr:{x:+5.0,y:+0.0,z:+0.0},sc:{x:+1.0,y:+1.0,z:+1.0}}
Pose:Bone1 :{ori:{v:{x:-0.040728,y:+2.859098e-3,z:+0.099126},w:+0.994236},tr:{x:+9.975321,y:+0.495335,z:-2.860452e-2},sc:{x:+1.0,y:+1.0,z:+1.0}}
Pose:Bone2 :{ori:{v:{x:-1.088853e-2,y:+0.634854e-2,z:+0.148186},w:+0.988879},tr:{x:+14.87698,y:+1.479723,z:-0.097403},sc:{x:+1.0,y:+1.0,z:+1.0}}
Pose:Bone3 :{ori:{v:{x:+1.734111e-2,y:+0.965453e-2,z:+0.196705},w:+0.980261},tr:{x:+19.65698,y:+2.944419,z:-0.176318},sc:{x:+1.0,y:+1.0,z:+1.0}}
Pose:Bone4 :{ori:{v:{x:+0.055097,y:+1.436532e-2,z:+0.244337},w:+0.968017},tr:{x:+24.26912,y:+4.874321,z:-0.236847},sc:{x:+1.0,y:+1.0,z:+1.0}}

*/

/*
** Example: customPoseObject.kl
*/

require Characters;

// Custom poses enable character systems to be built that compute thier poses
// is thier own way. A ragdoll simulation might pull the pose transforms directly 
// from Bullet, or a cache reader might load a pose from disk. The IPose interface
// enables this integration of custom systems into the Fabric Engine scene.
object CustomPose : Pose {
};

function CustomPose(Skeleton skeleton){
  this.skeleton = skeleton;
  this.version = mathRandomInteger(67842, UInt32(this.skeleton.getVersion()));
  this.reset();
}


/// Updates the internal cache for a given bone. 
/// \internal
function CustomPose.updateXfo!(Index index){
  
  Scalar random = 0.5 - mathRandomScalar(12, index);
  Scalar xAngle = sin(random * 0.4 + Scalar(index) * 0.03) * 0.5;
  Scalar zAngle = cos(0.11 + Scalar(index) * 0.01) * 0.1;

  Xfo xfo;
  xfo.tr = Vec3(mathRandomScalar(13, index) * 5.0, mathRandomScalar(14, index) * 5.0, 0.0);
  xfo.ori.setFromEulerAngles(Vec3(xAngle, 0.0f, zAngle));

  this.xfos[index] = xfo;
  this.valid[index] = true;
}

/// Get the pose of a bone in the skeleton using its index.
/// \note Lazily computes the pose if the cache is not valid.  
function Xfo CustomPose.getBoneXfo!(Index index){
  if(!this.valid[index])
    this.updateXfo(index);
  return this.xfos[index];
}


operator entry(){

  Character character('Procedural Pose');


  //////////////////////////////////
  // Generate a chain of bones with a random shape.
  Bone bones[];
  bones.resize(5);
  Xfo parentXfo();
  for(Integer i=0;i<5;i++) {

    Bone bone();
    bone.name = "Bone"+i;
    bone.parentIndex = i-1;

    Xfo xfo;
    xfo.tr = Vec3(5.0, 0.0, 0.0);
    bone.referencePose = parentXfo * xfo;
    bone.length = 5.0;
    bone.radius = 1.0;
    bone.setFlag(BONEFLAG_DEFORMER);
    bones[i] = bone;
    parentXfo = bone.referencePose;
  }

  Skeleton skeleton = Skeleton("", bones);
  character.setSkeleton(skeleton);
  character.setPose(CustomPose(skeleton));

  Mat44 skinningMatricies[] = character.getSkinningMatrices();
  report(skinningMatricies);
}

/*
** Output:

[{row0:{x:+0.995064,y:-0.099232,z:+0.0,t:-2.3679},row1:{x:+0.099066,y:+0.993409,z:+0.057651,t:+0.774196},row2:{x:-0.57209e-2,y:-0.057367,z:+0.998336,t:+2.860451e-2},row3:{x:+0.0,y:+0.0,z:+0.0,t:+1.0}},{row0:{x:+0.995075,y:-0.099117,z:-1.164153e-10,t:-7.850447},row1:{x:+0.099089,y:+0.994787,z:+2.407886e-2,t:-0.267534},row2:{x:-2.386645e-3,y:-2.396029e-2,z:+0.99971,t:+2.386645e-2},row3:{x:+0.0,y:+0.0,z:+0.0,t:+1.0}},{row0:{x:+0.995088,y:-0.098993,z:+0.0,t:-13.48693},row1:{x:+0.098819,y:+0.993333,z:-0.059358,t:-0.365168},row2:{x:+0.587611e-2,y:+0.059066,z:+0.998236,t:-0.088141},row3:{x:+0.0,y:+0.0,z:+0.0,t:+1.0}},{row0:{x:+0.995101,y:-0.098859,z:+0.0,t:-16.4809},row1:{x:+0.098704,y:+0.993536,z:-0.056054,t:+2.648208},row2:{x:+0.55415e-2,y:+0.055779,z:+0.998427,t:-0.11083},row3:{x:+0.0,y:+0.0,z:+0.0,t:+1.0}},{row0:{x:+0.995115,y:-0.098716,z:-2.328306e-10,t:-22.70404},row1:{x:+0.098434,y:+0.992281,z:-0.075418,t:-0.218665},row2:{x:+0.744506e-2,y:+0.07505,z:+0.997151,t:-0.186126},row3:{x:+0.0,y:+0.0,z:+0.0,t:+1.0}}]

*/

Members

Skeleton skeleton The skeleton that this pose is based on.
Xfo[] xfos The model space transforms for each bone in the skeleton
Boolean[] valid A flag for each item in the array above indicating that the Xfo has been computed.
UInt64 version The intenral version counter

Methods

  Pose ( in Pose other )
  Pose ( in Skeleton skeleton )
  Pose ()
Pose clone ? ()
Xfo getBoneXfo ! ( in Index index )
String getDesc ? ( in String indent, in Boolean includeXfos )
String getDesc ? ()
UInt64 getVersion ? ()
  incrementVersion ! ()
  reset ! ()
  setBoneXfo ! ( in Index index, in Xfo xfo )