public static void StraightenHierarchie(PMXModel mdl, PMXBone source) { List <PMXBone> bones = new List <PMXBone>() { source }; bones.AddRange(GetAllChildBones(mdl, source)); foreach (PMXBone b in bones) { b.CreateLocalCoodinateAxis(); } }
private static void AddWeightInternal(PMXBone bne, float weight, Dictionary <PMXBone, float> weights, ref float weightSum) { if (weight == 0 || bne == null) { return; } if (!weights.ContainsKey(bne)) { weights[bne] = 0.0f; } weights[bne] += weight; weightSum += weight; }
public static List <PMXBone> GetAllChildBones(PMXModel mdl, PMXBone parent) { List <PMXBone> res = new List <PMXBone>(); foreach (PMXBone b in mdl.Bones) { if (b.Parent != parent) { continue; } res.Add(b); res.AddRange(GetAllChildBones(mdl, b)); } return(res); }
/// <summary> /// /// </summary> /// <param name="pos1">回転対象</param> /// <param name="pos2">目標ボーン</param> /// <param name="skeleton"></param> /// <param name="type1"></param> /// <param name="type2"></param> /// <returns></returns> private void getRotation(PMXBone b1, PMXBone b2, Skeleton skeleton, SkeletonJoint skel1, SkeletonJoint skel2) { SkeletonJoint targetBone = skel1; SkeletonJoint baseBone = skel2; if (targetBone.PositionConfidence < 0.5 || baseBone.PositionConfidence < 0.5) { return; } Vector3 t2b = Vector3.Normalize(ToVector3(targetBone.Position) - ToVector3(baseBone.Position)); Vector3 it2b = Vector3.Normalize(Vector3.TransformCoordinate(b2.Position, b2.GlobalPose) - Vector3.TransformCoordinate(b1.Position, b1.GlobalPose)); Vector3 axis = Vector3.Cross(t2b, it2b); float angle = (float)-Math.Acos(Vector3.Dot(t2b, it2b)); b1.Rotation *= Quaternion.RotationAxis(axis, angle); b1.UpdateGrobalPose(); }
public static void RotateZ(PMXModel mdl, PMXBone parent, double angle) { List <PMXBone> children = GetAllChildBones(mdl, parent); foreach (PMXBone child in children) { PMXVector3 originalLocation = child.Position; child.Position = Rotate(parent.Position, originalLocation, angle, 1.0f); if (!child.HasChildBone) { PMXVector3 targetLocation = Rotate(parent.Position, originalLocation + child.ChildVector, angle, 1.0f); child.ChildVector = targetLocation - child.Position; } } List <PMXBone> weightBones = new List <PMXBone>() { parent }; weightBones.AddRange(children); PMXVector3 baseVector = new PMXVector3(); foreach (PMXVertex v in mdl.Vertices) { float w = DetermineWeight(v, weightBones); if (w <= 0.0f) { continue; } PMXVector3 originalLocation = v.Position; v.Position = Rotate(parent.Position, originalLocation, angle, w); v.Normals = Rotate(baseVector, v.Normals, angle, w); } }
private void ImportBone(string boneName, int boneIndex, int boneParent, int boneId) { uint headerLength = sp.ReadU32(); int transformTotal = sp.ReadS32(); int i; uint[] transFormOffsets = new uint[transformTotal]; for (i = 0; i < transformTotal; i++) { transFormOffsets[i] = sp.ReadU32(); } float m11 = 1.0f, m12 = 0.0f, m13 = 0.0f, m14 = 0.0f; float m21 = 0.0f, m22 = 1.0f, m23 = 0.0f, m24 = 0.0f; float m31 = 0.0f, m32 = 0.0f, m33 = 1.0f, m34 = 0.0f; float m41 = 0.0f, m42 = 0.0f, m43 = 0.0f, m44 = 0.0f; float m15 = 1.0f, m16 = 0.0f, m17 = 0.0f, m18 = 0.0f; float m25 = 0.0f, m26 = 1.0f, m27 = 0.0f, m28 = 0.0f; float m35 = 0.0f, m36 = 0.0f, m37 = 1.0f, m38 = 0.0f; float rX = 0.0f, rY = 0.0f, rZ = 0.0f; float sX = 1.0f, sY = 1.0f, sZ = 1.0f; for (i = 0; i < transformTotal; i++) { sp.BaseStream.Seek(transFormOffsets[i], SeekOrigin.Begin); uint sectionType = sp.ReadU32(); if (sectionType == 20) { //Bone translation sp.BaseStream.Seek(4, SeekOrigin.Current); m41 = sp.ReadSingle() * _totalScale; m42 = sp.ReadSingle() * _totalScale; m43 = sp.ReadSingle() * _totalScale; } if (sectionType == 21) { //Bone scale sp.BaseStream.Seek(4, SeekOrigin.Current); sX = sp.ReadSingle(); sY = sp.ReadSingle(); sZ = sp.ReadSingle(); } if (sectionType == 93) { //Matrix X transform sp.BaseStream.Seek(4, SeekOrigin.Current); m15 = sp.ReadSingle(); m16 = sp.ReadSingle(); m17 = sp.ReadSingle(); m18 = sp.ReadSingle(); } if (sectionType == 94) { //Matrix Y transform sp.BaseStream.Seek(4, SeekOrigin.Current); m25 = sp.ReadSingle(); m26 = sp.ReadSingle(); m27 = sp.ReadSingle(); m28 = sp.ReadSingle(); } if (sectionType == 95) { //Matrix Z transform sp.BaseStream.Seek(4, SeekOrigin.Current); m35 = sp.ReadSingle(); m36 = sp.ReadSingle(); m37 = sp.ReadSingle(); m38 = sp.ReadSingle(); } if (sectionType == 103) { //Matrix J-X transform sp.BaseStream.Seek(4, SeekOrigin.Current); m11 = sp.ReadSingle(); m12 = sp.ReadSingle(); m13 = sp.ReadSingle(); m14 = sp.ReadSingle(); } if (sectionType == 104) { //Matrix J-Y transform sp.BaseStream.Seek(4, SeekOrigin.Current); m21 = sp.ReadSingle(); m22 = sp.ReadSingle(); m23 = sp.ReadSingle(); m24 = sp.ReadSingle(); } if (sectionType == 105) { //Matrix J-Z transform sp.BaseStream.Seek(4, SeekOrigin.Current); m31 = sp.ReadSingle(); m32 = sp.ReadSingle(); m33 = sp.ReadSingle(); m34 = sp.ReadSingle(); } //Todo: 113, 114, 115, 116, 117, 118, 119 } Matrix4x4 tfm = Matrix4x4.CreateScale(sX, sY, sZ); tfm = tfm * Matrix4x4.CreateRotationX(DegreeToRadian(m18)) * Matrix4x4.CreateRotationY(DegreeToRadian(m28)) * Matrix4x4.CreateRotationZ(DegreeToRadian(m38)); Matrix4x4 tfm2 = Matrix4x4.CreateScale(sX, sY, sZ); tfm2 = tfm2 * Matrix4x4.CreateRotationX(DegreeToRadian(m14)) * Matrix4x4.CreateRotationY(DegreeToRadian(m24)) * Matrix4x4.CreateRotationZ(DegreeToRadian(m34)); tfm = tfm * tfm2; tfm.M41 = m41; tfm.M42 = m42; tfm.M43 = m43; PMXBone parent = null; if (boneName != null && boneName.Trim().Length > 0) { if (boneParent >= 0 && boneTransforms.ContainsKey(boneParent)) { tfm *= boneTransforms[boneParent].Transformation; parent = boneTransforms[boneParent].Bone; } } /*Console.WriteLine(String.Format("matrix3 [{0:G6}, {1:G6}, {2:G6}] [{3:G6}, {4:G6}, {5:G6}] [{6:G6}, {7:G6}, {8:G6}] [{9:G6}, {10:G6}, {11:G6}]", new object[] { * tfm.M11, tfm.M12, tfm.M13, tfm.M21, tfm.M22, tfm.M23, tfm.M31, tfm.M32, tfm.M33, tfm.M41, tfm.M42, tfm.M43 * }));*/ PMXBone bn = new PMXBone(pmxModel); boneTransforms.Add(boneIndex, new BoneDataTransform() { Bone = bn, Transformation = tfm, Name = boneName }); bn.NameEN = boneName; bn.NameJP = boneName; Vector3 pos = tfm.Translation; bn.Position = new PMXVector3(pos.X, pos.Y, pos.Z); bn.Parent = parent; if (boneId > 0) { BoneArrRig.Add(boneId, bn); } pmxModel.Bones.Add(bn); }
private void CreateDeform(PMXVertex vtx, int boneCount, int boneIndexSize, int floatLength) { PMXBone[] bones = new PMXBone[boneCount]; float[] weights = new float[boneCount]; for (int i = 0; i < boneCount; i++) { switch (boneIndexSize) { case 1: bones[i] = GetBoneByBoneId((int)sp.ReadU8()); break; case 2: bones[i] = GetBoneByBoneId((int)sp.ReadU16()); break; default: throw new Exception(); } } for (int i = 0; i < boneCount; i++) { switch (floatLength) { case 2: weights[i] = sp.ReadHalfFloat(); break; case 4: weights[i] = sp.ReadSingle(); break; default: throw new Exception(); } } List <BonePlusWeight> usableBones = new List <BonePlusWeight>(); for (int i = 0; i < boneCount; i++) { if (bones[i] != null) { usableBones.Add(new BonePlusWeight() { Bone = bones[i], Weight = weights[i] }); } } usableBones.Sort(); if (usableBones.Count == 1) { PMXVertexDeformBDEF1 df = new PMXVertexDeformBDEF1(pmxModel, vtx); df.Bone1 = usableBones[0].Bone; vtx.Deform = df; } else if (usableBones.Count == 2) { PMXVertexDeformBDEF2 df = new PMXVertexDeformBDEF2(pmxModel, vtx); df.Bone1 = usableBones[0].Bone; df.Bone2 = usableBones[1].Bone; df.Bone1Weight = (usableBones[0].Weight) / (usableBones[0].Weight + usableBones[1].Weight); vtx.Deform = df; } else if (usableBones.Count == 3) { PMXVertexDeformBDEF4 df = new PMXVertexDeformBDEF4(pmxModel, vtx); float totalWeight = usableBones[0].Weight + usableBones[1].Weight + usableBones[2].Weight; df.Bone1 = usableBones[0].Bone; df.Bone2 = usableBones[1].Bone; df.Bone3 = usableBones[2].Bone; df.Bone4 = null; df.Bone1Weight = (usableBones[0].Weight) / totalWeight; df.Bone2Weight = (usableBones[1].Weight) / totalWeight; df.Bone3Weight = (usableBones[2].Weight) / totalWeight; df.Bone4Weight = 0.0f; vtx.Deform = df; } else { PMXVertexDeformBDEF4 df = new PMXVertexDeformBDEF4(pmxModel, vtx); float totalWeight = usableBones[0].Weight + usableBones[1].Weight + usableBones[2].Weight + usableBones[3].Weight; df.Bone1 = usableBones[0].Bone; df.Bone2 = usableBones[1].Bone; df.Bone3 = usableBones[2].Bone; df.Bone4 = usableBones[3].Bone; df.Bone1Weight = (usableBones[0].Weight) / totalWeight; df.Bone2Weight = (usableBones[1].Weight) / totalWeight; df.Bone3Weight = (usableBones[2].Weight) / totalWeight; df.Bone4Weight = (usableBones[3].Weight) / totalWeight; vtx.Deform = df; } }
/// <summary> /// Constructor /// </summary> /// <param name="bone">Bone</param> public BoneMotion(PMXBone bone) { this.bone = bone; }
private void loadMeshs() { int i, j, k, l, m; int vtxIndex = 0; for (i = 0; i < this.mdlInfo.Count7; i++) { long vtxBase = this.vertBase + this.meshInfoList[i].vtxBufferStart; long idxBase = this.faceBase + this.meshInfoList[i].idxBufferStart; uint vtxStride = this.meshInfoList[i].vtxStride; //Console.WriteLine(vtxStride); uint matBase = this.meshInfoList[i].meshId; FvfInfo[] fvfInfo = this.fvfList[i]; this.fs.Seek(this.boneMapStart + this.meshInfoList[i].bonePalletStart * 2, SeekOrigin.Begin); List <ushort> bonePallet = new List <ushort>(); for (j = 0; j < this.meshInfoList[i].bonePalletCount; j++) { bonePallet.Add(br.ReadUInt16()); } for (j = 0; j < this.meshInfoList[i].meshCount; j++) { PMXMaterial mat = new PMXMaterial(this.pmx); mat.Diffuse.R = 0.77f; mat.Diffuse.G = 0.77f; mat.Diffuse.B = 0.77f; mat.Specular.R = 0.0f; mat.Specular.G = 0.0f; mat.Specular.B = 0.0f; mat.Ambient.R = 0.5f; mat.Ambient.G = 0.5f; mat.Ambient.B = 0.5f; mat.EdgeEnabled = false; mat.EdgeSize = 0.0f; mat.StandardToonIndex = 3; string meshname = this.matInfoList[i].MeshName; if (this.matNames != null && matNames.Count > 0) { meshname = this.matNames[(int)this.meshInfoList[i].matID] + "_" + i.ToString() + "_" + j.ToString(); } mat.NameJP = meshname; mat.NameEN = meshname; MaterialInfo matInfo = this.matInfoList[(int)(matBase + j)]; if (matInfo.Lod != 1 && matInfo.Lod != -1) { continue; } this.fs.Seek(idxBase, SeekOrigin.Begin); List <int> idxTmp = new List <int>(); for (l = 0; l < matInfo.FaceCount; l++) { if (meshInfoList[i].idxType == 2) { idxTmp.Add((int)(this.br.ReadUInt32() - matInfo.FaceStart)); } else { idxTmp.Add((int)(this.br.ReadUInt16() - matInfo.FaceStart)); } } idxBase = this.fs.Position; this.fs.Seek(vtxBase + vtxStride * matInfo.FaceStart, SeekOrigin.Begin); long vtxPosition = this.fs.Position; List <PMXVertex> vertices = new List <PMXVertex>(); for (k = 0; k < matInfo.VertCount; k++) { PMXVertex vtx = new PMXVertex(this.pmx); byte[] idx = new byte[4] { 0, 0, 0, 0 }; byte[] wgt = new byte[4] { 0, 0, 0, 0 }; for (l = 0; l < fvfInfo.Length; l++) { this.fs.Seek(vtxPosition + k * vtxStride + fvfInfo[l].fvfPos, SeekOrigin.Begin); switch (fvfInfo[l].compType) { case 0: vtx.Position.X = this.br.ReadSingle() * SCALE; vtx.Position.Y = this.br.ReadSingle() * SCALE; vtx.Position.Z = this.br.ReadSingle() * SCALE * (-1); break; case 2: vtx.Normals.X = this.br.ReadSingle(); vtx.Normals.Y = this.br.ReadSingle(); vtx.Normals.Z = this.br.ReadSingle() * (-1); break; case 8: vtx.UV.U = this.br.ReadSingle(); vtx.UV.V = this.br.ReadSingle(); break; case 7: for (m = 0; m < 4; m++) { idx[m] = this.br.ReadByte(); } break; case 1: for (m = 0; m < 4; m++) { wgt[m] = this.br.ReadByte(); } break; } } int totalWeight = 0; Dictionary <ushort, int> weights = new Dictionary <ushort, int>(); for (m = 0; m < 4; m++) { byte bi = idx[m]; if (bi >= bonePallet.Count) { continue; } ushort bni = bonePallet[bi]; int weight = 0; if (weights.ContainsKey(bni)) { weight = weights[bni]; } byte cw = wgt[m]; totalWeight += cw; weight += cw; weights[bni] = weight; } if (weights.Count == 1) { PMXVertexDeformBDEF1 b1 = new PMXVertexDeformBDEF1(this.pmx, vtx); b1.Bone1 = this.pmx.Bones[weights.Keys.First()]; vtx.Deform = b1; } else { List <KeyValuePair <ushort, int> > weightList = weights.ToList(); weightList.Sort(delegate(KeyValuePair <ushort, int> pair1, KeyValuePair <ushort, int> pair2) { return(pair2.Value.CompareTo(pair1.Value)); }); for (m = 3; m >= 1; m--) { if (weightList.Count > m && weightList[m].Value == 0) { weightList.RemoveAt(m); } } if (weightList.Count == 1) { PMXVertexDeformBDEF1 b1 = new PMXVertexDeformBDEF1(this.pmx, vtx); b1.Bone1 = this.pmx.Bones[weightList[0].Key]; vtx.Deform = b1; } else if (weightList.Count == 2) { PMXVertexDeformBDEF2 b2 = new PMXVertexDeformBDEF2(this.pmx, vtx); b2.Bone1 = this.pmx.Bones[weightList[0].Key]; b2.Bone1Weight = (float)weightList[0].Value / (float)totalWeight; b2.Bone2 = this.pmx.Bones[weightList[1].Key]; vtx.Deform = b2; } else if (weightList.Count > 2) { PMXVertexDeformBDEF4 b4 = new PMXVertexDeformBDEF4(this.pmx, vtx); b4.Bone1 = this.pmx.Bones[weightList[0].Key]; b4.Bone1Weight = (float)weightList[0].Value / (float)totalWeight; b4.Bone2 = this.pmx.Bones[weightList[1].Key]; b4.Bone2Weight = (float)weightList[1].Value / (float)totalWeight; b4.Bone3 = this.pmx.Bones[weightList[2].Key]; b4.Bone3Weight = (float)weightList[2].Value / (float)totalWeight; if (weightList.Count < 4) { b4.Bone4 = null; } else { b4.Bone4 = this.pmx.Bones[weightList[3].Key]; b4.Bone4Weight = (float)weightList[3].Value / (float)totalWeight; } vtx.Deform = b4; } else { //Most likely a prop! //Console.WriteLine("Weight error on " + this.inFile); if (pmx.Bones.Count == 0) { PMXBone mb = new PMXBone(pmx); mb.NameEN = "prop"; mb.NameJP = "prop"; mb.Position = new PMXVector3(0, 0, 0); mb.Translatable = true; pmx.Bones.Add(mb); } PMXVertexDeformBDEF1 b1 = new PMXVertexDeformBDEF1(this.pmx, vtx); b1.Bone1 = this.pmx.Bones[0]; vtx.Deform = b1; } } vertices.Add(vtx); this.pmx.Vertices.Add(vtx); vtxIndex++; } for (k = 0; k < idxTmp.Count; k += 3) { PMXTriangle tri = new PMXTriangle(this.pmx); tri.Vertex1 = vertices[idxTmp[k + 2]]; tri.Vertex2 = vertices[idxTmp[k + 1]]; tri.Vertex3 = vertices[idxTmp[k + 0]]; mat.Triangles.Add(tri); } this.pmx.Materials.Add(mat); } } this.totalVertCount = (uint)vtxIndex; if (this.mdlInfo.hasExp == 0) { this.WritePMX(); } else { this.CheckForVertexMorphs(); } }
private void loadBones() { //this.fs.Seek(0x04, SeekOrigin.Current); long boneStart = this.fs.Position; List <string> boneNames = new List <string>(); List <Vec3> bonePosList = new List <Vec3>(); List <BoneInfoStruct> boneInfo = new List <BoneInfoStruct>(); List <BoneInfoStructB> boneInfoB = new List <BoneInfoStructB>(); List <Matrix4x4> boneMatrix3 = new List <Matrix4x4>(); int i; for (i = 0; i < this.mdlInfo.BoneCount; i++) { boneNames.Add(this.br.ReadASCIINullTerminatedString()); } this.fs.Seek(boneStart + this.mdlInfo.BoneNameSize, SeekOrigin.Begin); this.boneMapStart = this.fs.Position; this.fs.Seek(this.boneMapStart + this.mdlInfo.BoneMapSize, SeekOrigin.Begin); for (i = 0; i < this.mdlInfo.BoneCount; i++) { boneInfoB.Add(this.br.ReadStruct <BoneInfoStructB>()); bonePosList.Add(this.br.ReadStruct <Vec3>()); boneInfo.Add(this.br.ReadStruct <BoneInfoStruct>()); } for (i = 0; i < this.mdlInfo.BoneCount; i++) { this.fs.Seek(64, SeekOrigin.Current); } for (i = 0; i < this.mdlInfo.BoneCount; i++) { Matrix4x4 rmatrix = br.ReadMatrix().ToMat43(); Matrix4x4 matrix; Matrix4x4.Invert(rmatrix, out matrix); boneMatrix3.Add(matrix); if (boneInfo[i].S1 != -1) { if (matrix.M41 == 0 && matrix.M42 == 0 && matrix.M43 == 0 && i > 0) { matrix.M41 = boneMatrix3[i - 1].M41; matrix.M42 = boneMatrix3[i - 1].M42; matrix.M43 = boneMatrix3[i - 1].M43; } } PMXBone bone = new PMXBone(this.pmx); bone.NameEN = boneNames[i]; bone.NameJP = boneNames[i]; bone.Position.X = matrix.M41 * SCALE; bone.Position.Y = matrix.M42 * SCALE; bone.Position.Z = matrix.M43 * SCALE * (-1); this.pmx.Bones.Add(bone); } for (i = 0; i < boneInfoB.Count; i++) { PMXBone parent = null; short parentIndex = boneInfoB[i].P1; if (parentIndex >= 0 && parentIndex < this.pmx.Bones.Count) { parent = this.pmx.Bones[parentIndex]; } this.pmx.Bones[i].Parent = parent; } this.LoadMeshInfo(); }
/// <summary> /// ITransformUpdaterのメンバーの実装 /// </summary> public bool UpdateTransform() { UserTrackerFrameRef usrFrameRef = device.CurrentUserTrackerFrameRef; if (CurrentTrackUserId >= 0) { UserData[] usrs = (from sk in usrFrameRef.Users where sk.UserId == CurrentTrackUserId select sk).ToArray(); if (usrs.Length != 1) { return(true); } Skeleton skeleton = usrs[0].Skeleton; if (skeleton.State == Skeleton.SkeletonState.Tracked) { trackTarget = skeleton; if (TrackingUser != null) { TrackingUser(this, usrs[0]); } PMXBone head = getBone("頭"); PMXBone neck = getBone("首"); PMXBone torso = getBone("上半身"); PMXBone r_shoulder = getBone("右腕"); PMXBone r_elbow = getBone("右ひじ"); PMXBone r_hand = getBone("右手首"); PMXBone r_hip = getBone("右足"); PMXBone r_knee = getBone("右ひざ"); PMXBone r_foot = getBone("右足首"); PMXBone l_shoulder = getBone("左腕"); PMXBone l_elbow = getBone("左ひじ"); PMXBone l_hand = getBone("左手首"); PMXBone l_hip = getBone("左足"); PMXBone l_knee = getBone("左ひざ"); PMXBone l_foot = getBone("左足首"); SkeletonJoint sj_head = skeleton.GetJoint(SkeletonJoint.JointType.Head); SkeletonJoint sj_neck = skeleton.GetJoint(SkeletonJoint.JointType.Neck); SkeletonJoint sj_rShoulder = skeleton.GetJoint(SkeletonJoint.JointType.RightShoulder); SkeletonJoint sj_lShoulder = skeleton.GetJoint(SkeletonJoint.JointType.LeftShoulder); SkeletonJoint sj_rElbow = skeleton.GetJoint(SkeletonJoint.JointType.RightElbow); SkeletonJoint sj_lElbow = skeleton.GetJoint(SkeletonJoint.JointType.LeftElbow); SkeletonJoint sj_r_hand = skeleton.GetJoint(SkeletonJoint.JointType.RightHand); SkeletonJoint sj_l_hand = skeleton.GetJoint(SkeletonJoint.JointType.LeftHand); SkeletonJoint sj_torso = skeleton.GetJoint(SkeletonJoint.JointType.Torso); SkeletonJoint sj_rHip = skeleton.GetJoint(SkeletonJoint.JointType.RightHip); SkeletonJoint sj_lHip = skeleton.GetJoint(SkeletonJoint.JointType.LeftHip); SkeletonJoint sj_rKnee = skeleton.GetJoint(SkeletonJoint.JointType.RightKnee); SkeletonJoint sj_lKnee = skeleton.GetJoint(SkeletonJoint.JointType.LeftKnee); SkeletonJoint sj_rFoot = skeleton.GetJoint(SkeletonJoint.JointType.RightFoot); SkeletonJoint sj_lFoot = skeleton.GetJoint(SkeletonJoint.JointType.LeftFoot); //腰のひねり Vector3 shoulder_l2r = Vector3.Normalize( ToVector3(sj_rShoulder.Position) - ToVector3(sj_lShoulder.Position)); Vector3 hip_l2r = Vector3.Normalize( ToVector3(sj_rHip.Position) - ToVector3(sj_lHip.Position)); //shoulder_l2r.Normalize();hip_l2r.Normalize(); float angle = (float)Math.Acos(Math.Min(Vector3.Dot(shoulder_l2r, hip_l2r), 1f)); torso.Rotation *= Quaternion.RotationAxis(new Vector3(0, 1, 0), angle); torso.UpdateGrobalPose(); getRotation(neck, head, skeleton, sj_neck, sj_head); getRotation(r_shoulder, r_elbow, skeleton, sj_rShoulder, sj_rElbow); getRotation(r_elbow, r_hand, skeleton, sj_rElbow, sj_r_hand); getRotation(l_shoulder, l_elbow, skeleton, sj_lShoulder, sj_lElbow); getRotation(l_elbow, l_hand, skeleton, sj_lElbow, sj_l_hand); getRotation(torso, neck, skeleton, sj_torso, sj_neck); getRotation(r_hip, r_knee, skeleton, sj_rHip, sj_rKnee); getRotation(r_knee, r_foot, skeleton, sj_rKnee, sj_rFoot); getRotation(l_hip, l_knee, skeleton, sj_lHip, sj_lKnee); getRotation(l_knee, l_foot, skeleton, sj_lKnee, sj_lFoot); } } return(true); }