Example #1
0
 public static void read(MmdVector4 i_dest, DataReader i_reader)
 {
     i_dest.x = i_reader.readFloat();
     i_dest.y = i_reader.readFloat();
     i_dest.z = i_reader.readFloat();
     i_dest.w = i_reader.readFloat();
     return;
 }
Example #2
0
 public static void write(MmdVector4 i_dest, DataWriter i_writer)
 {
     i_writer.writeFloat(i_dest.x);
     i_writer.writeFloat(i_dest.y);
     i_writer.writeFloat(i_dest.z);
     i_writer.writeFloat(i_dest.w);
     return;
 }
Example #3
0
        private void limitAngle(MmdVector4 pvec4Out, MmdVector4 pvec4Src)
        {
            MmdVector3 vec3Angle = this._work_vector3[0];

            // XYZ軸回転の取得
            vec3Angle.QuaternionToEuler(pvec4Src);

            // 角度制限
            if (vec3Angle.x < -Math.PI)
            {
                vec3Angle.x = (float)-Math.PI;
            }
            if (-0.002f < vec3Angle.x)
            {
                vec3Angle.x = -0.002f;
            }
            vec3Angle.y = 0.0f;
            vec3Angle.z = 0.0f;

            // XYZ軸回転からクォータニオンへ
            pvec4Out.QuaternionCreateEuler(vec3Angle);
            return;
        }
Example #4
0
        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;
        }
Example #5
0
        private PmdBone m_pNeckBone;            // 首のボーン


        private void getMotionPosRot(MotionData pMotionData, float fFrame, MmdVector3 pvec3Pos, MmdVector4 pvec4Rot)
        {
            int i;
            int ulNumKeyFrame = pMotionData.ulNumKeyFrames;

            // 最終フレームを過ぎていた場合
            if (fFrame > pMotionData.pKeyFrames[ulNumKeyFrame - 1].fFrameNo)
            {
                fFrame = pMotionData.pKeyFrames[ulNumKeyFrame - 1].fFrameNo;
            }

            // 現在の時間がどのキー近辺にあるか
            for (i = 0; i < ulNumKeyFrame; i++)
            {
                if (fFrame <= pMotionData.pKeyFrames[i].fFrameNo)
                {
                    break;
                }
            }

            // 前後のキーを設定
            int lKey0,
                lKey1;

            lKey0 = i - 1;
            lKey1 = i;

            if (lKey0 <= 0)
            {
                lKey0 = 0;
            }
            if (i == ulNumKeyFrame)
            {
                lKey1 = ulNumKeyFrame - 1;
            }

            // 前後のキーの時間
            float fTime0 = pMotionData.pKeyFrames[lKey0].fFrameNo;
            float fTime1 = pMotionData.pKeyFrames[lKey1].fFrameNo;

            // 前後のキーの間でどの位置にいるか
            float fLerpValue;

            if (lKey0 != lKey1)
            {
                fLerpValue = (fFrame - fTime0) / (fTime1 - fTime0);
                pvec3Pos.Vector3Lerp(pMotionData.pKeyFrames[lKey0].vec3Position, pMotionData.pKeyFrames[lKey1].vec3Position, fLerpValue);
                pvec4Rot.QuaternionSlerp(pMotionData.pKeyFrames[lKey0].vec4Rotate, pMotionData.pKeyFrames[lKey1].vec4Rotate, fLerpValue);
                pvec4Rot.QuaternionNormalize(pvec4Rot);//これほんとにいるの?
            }
            else
            {
                pvec3Pos.setValue(pMotionData.pKeyFrames[lKey0].vec3Position);
                pvec4Rot.setValue(pMotionData.pKeyFrames[lKey0].vec4Rotate);
            }
        }
Example #6
0
        private bool updateBoneFace(float fElapsedFrame)
        {
            //---------------------------------------------------------
            // 指定フレームのデータでボーンを動かす
            PmdBone[]  ppBone       = this.m_ppBoneList;
            MmdVector3 vec3Position = new MmdVector3();
            MmdVector4 vec4Rotate   = new MmdVector4();

            MotionData[] pMotionDataList = _ref_vmd_motion.refMotionDataArray();
            for (int i = 0; i < pMotionDataList.Length; i++)
            {
                if (ppBone[i] == null)
                {
                    continue;
                }
                getMotionPosRot(pMotionDataList[i], m_fFrame, vec3Position, vec4Rotate);

                // 補間なし
                ppBone[i].m_vec3Position.setValue(vec3Position);
                ppBone[i].m_vec4Rotate.setValue(vec4Rotate);

                //	 補間あり
                //				Vector3Lerp( &((*pBone)->m_vec3Position), &((*pBone)->m_vec3Position), &vec3Position, fLerpValue );
                //				QuaternionSlerp( &((*pBone)->m_vec4Rotate), &((*pBone)->m_vec4Rotate), &vec4Rotate, fLerpValue );
            }

            //---------------------------------------------------------
            // 指定フレームのデータで表情を変形する
            MmdVector3[] position_array = this._ref_pmd_model.getPositionArray();

            PmdFace[]  ppFace        = this.m_ppFaceList;
            FaceData[] pFaceDataList = _ref_vmd_motion.refFaceDataArray();
            for (int i = 0; i < pFaceDataList.Length; i++)
            {
                if (ppFace[i] == null)
                {
                    continue;
                }

                float fFaceRate = getFaceRate(pFaceDataList[i], m_fFrame);

                if (fFaceRate == 1.0f)
                {
                    ppFace[i].setFace(position_array);
                }
                else if (0.001f < fFaceRate)
                {
                    ppFace[i].blendFace(position_array, fFaceRate);
                }
            }

            //---------------------------------------------------------
            // フレームを進める
            bool bMotionFinshed = false;

            this.m_fOldFrame = this.m_fFrame;
            this.m_fFrame   += fElapsedFrame;

            if (this.m_bLoop)
            {
                if (m_fOldFrame >= this._ref_vmd_motion.getMaxFrame())
                {
                    this.m_fOldFrame = 0.0f;
                    this.m_fFrame    = this.m_fFrame - this._ref_vmd_motion.getMaxFrame();
                }
            }

            if (this.m_fFrame >= this._ref_vmd_motion.getMaxFrame())
            {
                this.m_fFrame  = this._ref_vmd_motion.getMaxFrame();
                bMotionFinshed = true;
            }

            return(bMotionFinshed);
        }