public MmdMotionPlayer(MmdPmdModel i_pmd_model, MmdVmdMotion i_vmd_model) { this._ref_pmd_model = i_pmd_model; this._ref_vmd_motion = i_vmd_model; this.m_bLoop = false; PmdBone[] bone_array = i_pmd_model.getBoneArray(); //スキニング用のmatrix this._skinning_mat = MmdMatrix.createArray(bone_array.Length); //--------------------------------------------------------- // 操作対象ボーンのポインタを設定する MotionData[] pMotionDataList = i_vmd_model.refMotionDataArray(); this.m_ppBoneList = new PmdBone[pMotionDataList.Length]; for (int i = 0; i < pMotionDataList.Length; i++) { this.m_ppBoneList[i] = i_pmd_model.getBoneByName(pMotionDataList[i].szBoneName); } //--------------------------------------------------------- // 操作対象表情のポインタを設定する FaceData[] pFaceDataList = i_vmd_model.refFaceDataArray(); this.m_ppFaceList = new PmdFace[pFaceDataList.Length]; for (int i = 0; i < pFaceDataList.Length; i++) { this.m_ppFaceList[i] = i_pmd_model.getFaceByName(pFaceDataList[i].szFaceName); } //首^H頭のボーンを探しておく this.m_pNeckBone = null; for (int i = 0; i < bone_array.Length; i++) { if (bone_array[i].getName().Equals("頭")) { this.m_pNeckBone = bone_array[i]; break; } } // 変数初期値設定 this.m_fOldFrame = this.m_fFrame = 0.0f; return; }
//この関数でthis._vertex_arrayを更新する。 public void updateSkinning(MmdMatrix[] i_skinning_mat) { MmdPmdModel pmd = this._ref_pmd; int number_of_vertex = pmd.getNumberOfVertex(); MmdVector3[] org_pos_array = pmd.getPositionArray(); MmdVector3[] org_normal_array = pmd.getNormatArray(); PmdSkinInfo[] org_skin_info = pmd.getSkinInfoArray(); CustomVertex.PositionNormalTextured[] vertex_array = this._vertex_array; // 頂点スキニング MmdMatrix matTemp = new MmdMatrix(); MmdVector3 position = new MmdVector3(); MmdVector3 normal = new MmdVector3(); for (int i = 0; i < number_of_vertex; i++) { PmdSkinInfo si = org_skin_info[i]; if (si.fWeight == 0.0f) { MmdMatrix mat = i_skinning_mat[si.unBoneNo[1]]; position.Vector3Transform(org_pos_array[i], mat); normal.Vector3Rotate(org_normal_array[i], mat); } else if (si.fWeight >= 0.9999f) { MmdMatrix mat = i_skinning_mat[si.unBoneNo[0]]; position.Vector3Transform(org_pos_array[i], mat); normal.Vector3Rotate(org_normal_array[i], mat); } else { MmdMatrix mat0 = i_skinning_mat[si.unBoneNo[0]]; MmdMatrix mat1 = i_skinning_mat[si.unBoneNo[1]]; matTemp.MatrixLerp(mat0, mat1, si.fWeight); position.Vector3Transform(org_pos_array[i], matTemp); normal.Vector3Rotate(org_normal_array[i], matTemp); } //ここの転写は少し考える。 vertex_array[i].X = position.x; vertex_array[i].Y = position.y; vertex_array[i].Z = position.z; vertex_array[i].Nx = normal.x; vertex_array[i].Ny = normal.y; vertex_array[i].Nz = normal.z; } return; }
public void update() { MmdVector3 vec3OrgTargetPos = this.__update_vec3OrgTargetPos; MmdMatrix matInvBone = this.__update_matInvBone; vec3OrgTargetPos.x = (float)m_pTargetBone.m_matLocal.m[3, 0]; vec3OrgTargetPos.y = (float)m_pTargetBone.m_matLocal.m[3, 1]; vec3OrgTargetPos.z = (float)m_pTargetBone.m_matLocal.m[3, 2]; MmdVector3 vec3EffPos = this._work_vector3[0]; MmdVector3 vec3TargetPos = this._work_vector3[1]; MmdVector3 vec3Diff = this._work_vector3[2]; MmdVector3 vec3RotAxis = this._work_vector3[3]; MmdVector4 vec4RotQuat = this._work_vector4; for (int i = this.m_ppBoneList.Length - 1; i >= 0; i--) { this.m_ppBoneList[i].updateMatrix(); } m_pEffBone.updateMatrix(); for (int it = 0; it < m_unCount; it++) { for (int cbLinkIdx = 0; cbLinkIdx < this.m_ppBoneList.Length; cbLinkIdx++) { // エフェクタの位置の取得 vec3EffPos.x = (float)m_pEffBone.m_matLocal.m[3, 0]; vec3EffPos.y = (float)m_pEffBone.m_matLocal.m[3, 1]; vec3EffPos.z = (float)m_pEffBone.m_matLocal.m[3, 2]; // ワールド座標系から注目ノードの局所(ローカル)座標系への変換 matInvBone.MatrixInverse(m_ppBoneList[cbLinkIdx].m_matLocal); // エフェクタ,到達目標のローカル位置 vec3EffPos.Vector3Transform(vec3EffPos, matInvBone); vec3TargetPos.Vector3Transform(vec3OrgTargetPos, matInvBone); // 十分近ければ終了 vec3Diff.Vector3Sub(vec3EffPos, vec3TargetPos); if (vec3Diff.Vector3DotProduct(vec3Diff) < 0.0000001f) { return; } // (1) 基準関節→エフェクタ位置への方向ベクトル vec3EffPos.Vector3Normalize(vec3EffPos); // (2) 基準関節→目標位置への方向ベクトル vec3TargetPos.Vector3Normalize(vec3TargetPos); // ベクトル (1) を (2) に一致させるための最短回転量(Axis-Angle) // // 回転角 double fRotAngle = Math.Acos(vec3EffPos.Vector3DotProduct(vec3TargetPos)); if (0.00000001 < Math.Abs(fRotAngle)) { if (fRotAngle < -m_fFact) { fRotAngle = -m_fFact; } else if (m_fFact < fRotAngle) { fRotAngle = m_fFact; } // 回転軸 vec3RotAxis.Vector3CrossProduct(vec3EffPos, vec3TargetPos); if (vec3RotAxis.Vector3DotProduct(vec3RotAxis) < 0.0000001) { continue; } vec3RotAxis.Vector3Normalize(vec3RotAxis); // 関節回転量の補正 vec4RotQuat.QuaternionCreateAxis(vec3RotAxis, fRotAngle); if (m_ppBoneList[cbLinkIdx].m_bIKLimitAngle) { limitAngle(vec4RotQuat, vec4RotQuat); } vec4RotQuat.QuaternionNormalize(vec4RotQuat); m_ppBoneList[cbLinkIdx].m_vec4Rotate.QuaternionMultiply(m_ppBoneList[cbLinkIdx].m_vec4Rotate, vec4RotQuat); m_ppBoneList[cbLinkIdx].m_vec4Rotate.QuaternionNormalize(m_ppBoneList[cbLinkIdx].m_vec4Rotate); for (int i = cbLinkIdx; i >= 0; i--) { m_ppBoneList[i].updateMatrix(); } m_pEffBone.updateMatrix(); } } } return; }
public void lookAt(MmdVector3 pvecTargetPos) { // どうもおかしいので要調整 MmdMatrix matTemp = this._lookAt_matTemp; MmdMatrix matInvTemp = this._lookAt_matInvTemp; MmdVector3 vec3LocalTgtPosZY = this._lookAt_vec3LocalTgtPosZY; MmdVector3 vec3LocalTgtPosXZ = this._lookAt_vec3LocalTgtPosXZ; matTemp.MatrixIdentity(); matTemp.m[3, 0] = m_vec3Position.x + m_vec3Offset.x; matTemp.m[3, 1] = m_vec3Position.y + m_vec3Offset.y; matTemp.m[3, 2] = m_vec3Position.z + m_vec3Offset.z; if (this._parent_bone != null) { matInvTemp.MatrixInverse(_parent_bone.m_matLocal); matTemp.MatrixMultiply(matTemp, matInvTemp); } matTemp.MatrixInverse(matTemp); vec3LocalTgtPosZY.Vector3Transform(pvecTargetPos, matTemp); vec3LocalTgtPosXZ.setValue(vec3LocalTgtPosZY); vec3LocalTgtPosXZ.y = 0.0f; vec3LocalTgtPosXZ.Vector3Normalize(vec3LocalTgtPosXZ); vec3LocalTgtPosZY.x = 0.0f; vec3LocalTgtPosZY.Vector3Normalize(vec3LocalTgtPosZY); MmdVector3 vec3Angle = this._lookAt_vec3Angle; vec3Angle.x = vec3Angle.y = vec3Angle.z = 0; if (vec3LocalTgtPosZY.z > 0.0f) { vec3Angle.x = (float)(Math.Asin(vec3LocalTgtPosZY.y) - (20.0 * Math.PI / 180.0)); } if (vec3LocalTgtPosXZ.x < 0.0f) { vec3Angle.y = (float)Math.Acos(vec3LocalTgtPosXZ.z); } else { vec3Angle.y = (float)-Math.Acos(vec3LocalTgtPosXZ.z); } if (vec3Angle.x < (-25.0 * Math.PI / 180.0)) { vec3Angle.x = (float)(-25.0 * Math.PI / 180.0); } if ((45.0f * Math.PI / 180.0) < vec3Angle.x) { vec3Angle.x = (float)(45.0 * Math.PI / 180.0); } if (vec3Angle.y < (-80.0 * Math.PI / 180.0)) { vec3Angle.y = (float)(-80.0 * Math.PI / 180.0); } if ((80.0 * Math.PI / 180.0) < vec3Angle.y) { vec3Angle.y = (float)(80.0 * Math.PI / 180.0); } m_vec4Rotate.QuaternionCreateEuler(vec3Angle); }
public void updateSkinningMat(MmdMatrix o_matrix) { o_matrix.MatrixMultiply(this.m_matInvTransform, this.m_matLocal); return; }