我想对骨架进行标准化,以使其与人的大小不变 在kinect面前;与aveteering例子一样。 但我不想使用XNA为3D模型制作动画,我唯一需要的是规范化 骨架。
因此,为了完成这项任务,我将其分为两个部分:
(a)将绑定姿势应用于骨架,以便了解如何使用此矩阵。显然这不是我想要做的,但这是第一步 知道如何使用whit矩阵,等等。
(b)将任意姿势应用于标准化大小的骨架
首先,我想将绑定姿势应用于骨架(a)。
首先,我必须加载描述骨骼之间骨骼长度/偏移量的矩阵并将其存储 列出BindPose。
由于我不知道怎么做,我修改了Aveteering示例并在文件中写入定义的所有Matrix 花花公子的BindPose,InverseBindPose和SkeletonHierarchy。我只需要BindPose来完成这个任务,但我有 准备代码以执行第二项任务(b)
该文件如下所示:
1,331581E-06; -5,551115E-17; 1; 0; 1; -4,16881E-11; -1,331581E-06; 0; 4,16881E-11; 1; 8,153579E- 23; 0; 0,03756338; 37,46099; 2,230549; 1 1,110223E-16; -4,435054E-22; 1; 0; 1; 1,426127E-06; -2,220446E-16; 0; -1,426127E-06; 1; -7,654181E-22; 0; -0,9558675; -4,079016E-08; -6,266987E-12; 1 0,9954988; -0,09477358; 1,501821E-06; 0; 0,09477358; 0,9954988; -4,019565E-06; 0; -1,114112E-06; 4,143805E-06; 1; 0 ; 3,786007; -0,003599779; 5,107028E-06; 1 0,9948416; -0,101441; -3,23556E-07; 0; 0,101441; 0,9948416; -2,266755E-08; 0; 3,241862E-07; -1,027114E-08; 1; 0; 4,543321; -0,00359975; -1,33061E-07; 1 0,9950595; 0,09927933; 2,388133E-07; 0; -0,09927933; 0,9950595; -2,333792E-08; 0; -2,399506E-07; -4,86646E-10; 1; 0; 4,544049; -0,003599948; 6,324596E-08; 1 0,9992647; 0,02747673; 0,02674458; 0; -0,02928042; 0,9971476; 0,06956656; 0; -0,02475683; -0,07029849; 0,9972187; 0; 4,543965; - 0,004398902; 2,258555E-07; 1 0,9154034; 0,4025377; 1,107153E-06; 0; -0,4025377; 0,9154033; -2,437432E-07; 0; -1,109319E-06; -2,115673E-07; 1; 0; 5,536249; -0,00288291; 1,332601E-07; 1 0,9812952; -0,1925096; -4,732622E-07; 0; 0,1925095; 0,9812951; -3,00921E-08; 0; 4,697166E-07; -5,889972E-08; 1; 0; 3,953898; 1,702301E-07; 4,88653E-08; 1 .......
因此每一行都是一个定义BindPose的4X4矩阵。
要生成此文件,代码如下:
private void ViewSkinningData(SkinningData data)
{
string nameFile = "bind_pose_transformations";
bool append = false;
// The using statement automatically closes the stream and calls IDisposable.Dispose on the stream object.
using (System.IO.StreamWriter file = new System.IO.StreamWriter(@nameFile, append))
{
for (int i = 0; i < data.BindPose.Count; i++)
{
Matrix m = data.BindPose[i];
string matrixString = MatrixToString(m);
file.WriteLine(matrixString);
}
for (int i = 0; i < data.InverseBindPose.Count; i++)
{
Matrix m = data.InverseBindPose[i];
string matrixString = MatrixToString(m);
file.WriteLine(matrixString);
}
for (int i = 0; i < data.SkeletonHierarchy.Count; i++)
{
file.Write(data.SkeletonHierarchy[i] + ";");
}
}
}
string MatrixToString(Matrix m)
{
string result;
result = m.M11 + ";" + m.M12 + ";" + m.M13 + ";" + m.M14 + ";" + m.M21 + ";" + m.M22 + ";" + m.M23 + ";" + m.M24 + ";" + m.M31 + ";" + m.M32 + ";" + m.M33 + ";" + m.M34 + ";" + m.M41 + ";" + m.M42 + ";" + m.M43 + ";" + m.M44;
return result;
}
下一步是在我的程序中加载所有这些Skinning数据:
private void InitializeSkinningDataFromFile()
{
string filename = "bind_pose_transformations";
int number_avatar_joints = 58;
List<Matrix> binpose = new System.Collections.Generic.List<Matrix>();
List<Matrix> inversebindpose = new System.Collections.Generic.List<Matrix>();
List<int> skeletonhierarchy = new System.Collections.Generic.List<int>();
// The using statement automatically closes the stream and calls IDisposable.Dispose on the stream object.
using (System.IO.StreamReader file = new System.IO.StreamReader(filename))
{
string s;
int count = 0;
while (!String.IsNullOrEmpty(s = file.ReadLine()))
{
string[] values = s.Split(';');
Matrix m = BuildMatrix(values);
binpose.Add(m);
count++;
if (count == number_avatar_joints)
{
break;
}
}
count = 0;
while (!String.IsNullOrEmpty(s = file.ReadLine()))
{
string[] values = s.Split(';');
Matrix m = BuildMatrix(values);
inversebindpose.Add(m);
count++;
if (count == number_avatar_joints)
{
break;
}
}
string[] skeletonHierarchy = file.ReadLine().Split(';'); //lee un caracter de separacion al final...
//for (int i = 0; i < skeletonHierarchy.Count(); i++)
for (int i = 0; i < number_avatar_joints; i++)
{
skeletonhierarchy.Add(int.Parse(skeletonHierarchy[i]));
}
}
skinningDataValue = new SkinningData(binpose, inversebindpose, skeletonhierarchy);
}
之后,我必须构造boneTransforms结构:
// Bone matrices for the "dude" model
this.boneTransforms = new Matrix[skinningDataValue.BindPose.Count];
this.skinningDataValue.BindPose.CopyTo(this.boneTransforms, 0);
现在,boneTransforms对我的骨骼进行了转换。所以现在,我必须将这些trasnformation应用于骨架
Skeleton skeleton = new Skeleton();
foreach (Joint joint in skeleton.Joints)
{
int indexMatrix = AvatarBoneToNuiJointIndex(joint.JointType);
Matrix transform;
if (indexMatrix >= 0)
{
transform = this.boneTransforms[indexMatrix];
}
else
{
transform = Matrix.Identity;
}
Joint aux = ApplyMatrixTransformationToJoint(joint, transform);
normalizeSkel.Joints[joint.JointType] = aux;
}
这是一个帮助函数AvatarBoneToNuiJointIndex:
public int AvatarBoneToNuiJointIndex(JointType jointType)
{
switch (jointType)
{
case JointType.HipCenter:
return 1;
case JointType.Spine:
return 4;
case JointType.ShoulderCenter:
return 6;
case JointType.Head:
return 7;
case JointType.ShoulderLeft:
return 12;
case JointType.ElbowLeft:
return 13;
case JointType.WristLeft:
return 14;
case JointType.HandLeft:
return 15;
case JointType.ShoulderRight:
return 31;
case JointType.ElbowRight:
return 32;
case JointType.WristRight:
return 33;
case JointType.HandRight:
return 34;
case JointType.KneeLeft:
return 50;
case JointType.AnkleLeft:
return 51;
case JointType.FootLeft:
return 52;
case JointType.KneeRight:
return 54;
case JointType.AnkleRight:
return 55;
case JointType.FootRight:
return 56;
default: return -1;
}
}
这是一个辅助函数ApplyMatrixTransformationToJoint:
public Joint ApplyMatrixTransformationToJoint(Joint skeletonJoint, Matrix tranformations)
{
Vector3 pos = SkeletonPointToVector3(skeletonJoint.Position);
Vector3 result = ApplyMatrixTransformationToVector(pos, tranformations);
SkeletonPoint newPosition = new SkeletonPoint()
{
X = result.X,
Y = result.Y,
Z = result.Z
};
skeletonJoint.Position = newPosition;
return skeletonJoint;
}
这是ApplyMatrixTransformationToVector的代码:
static Vector3 ApplyMatrixTransformationToVector(Vector3 v, Matrix m)
{
return Vector3.Transform(v, m);
}
但问题是我看不到任何东西。 我不知道这种方法是否正确。 任何帮助都会很棒。 非常感谢!