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 ) |