コード例 #1
0
        /// <summary>ボーンの姿勢を更新します。</summary>
        public void Update()
        {
            //子要素の更新
            foreach (var child in _childs)
            {
                child.Update();
            }

            //このボーン自体の姿勢更新
            var lmat = _bone.LocalMatrix;

            //ゼロ回転からではなくTポーズからの変化を知りたいので差分を求める
            var rotationMat = MatrixRotationDif.CreateDifFrom(lmat, _bone.InitialLocalMatrix);
            //クォータニオン表現に修正
            var rotation = CreateQuaternion(rotationMat);

            //回転軸を取得し、疑似座標系に投影して回転軸がXY(-Z)軸基準になるようにする
            Vector3 axis  = rotation.Axis;
            float   angle = rotation.Angle;

            Vector3 axisNormalized =
                axis.X * xAxis +
                axis.Y * yAxis +
                axis.Z * zAxis;

            Rotation = Quaternion.RotationAxis(axisNormalized, angle);
        }
コード例 #2
0
        private void ApplyIK(Model model)
        {
            //追加: 加速度センサONの場合に回転不変性取るよう改善
            var boneHip    = QumarionModel.Bones[StandardPSBones.Hips];
            var initPosHip = boneHip.InitialWorldMatrix.Translate;
            var posHip     = boneHip.WorldMatrix.Translate;
            //NOTE:
            var rotHipInverse = MatrixRotationDif.CreateDifFrom(
                boneHip.WorldMatrix.Rotate,
                boneHip.InitialWorldMatrix.Rotate
                ).Transpose();


            foreach (var t in _targetIKBones)
            {
                var src  = QumarionModel.Bones[QumaBone2MMDBone.GetQumaBone(t)];
                var dest = MMDStandardBones.GetBone(model, t);
                if (dest == null)
                {
                    continue;
                }

                //1: Tポーズでの Hip -> t のベクトル取得(これは直立)
                var initPosWorld = src.InitialWorldMatrix.Translate;
                var initPos      = new Vector3f(
                    initPosWorld.X - initPosHip.X,
                    initPosWorld.Y - initPosHip.Y,
                    initPosWorld.Z - initPosHip.Z
                    );
                //2: 現在の Hip -> t のベクトルを回転除去しつつ取得

                var posWorld = src.WorldMatrix.Translate;
                var pos      = new Vector3f(
                    posWorld.X - posHip.X,
                    posWorld.Y - posHip.Y,
                    posWorld.Z - posHip.Z
                    );
                //ここ大事: posのベクトルは体の回転込みの値なので逆回転して相殺
                pos = MatrixUtil.Multiply(rotHipInverse, pos);

                //NOTE: MMMではZ軸が後ろ向き正だがQumarionだと前向き正
                var dif = new Vector3(
                    pos.X - initPos.X,
                    pos.Y - initPos.Y,
                    -pos.Z + initPos.Z
                    );

                var motion = dest.CurrentLocalMotion;
                motion.Move             = dif * LegIKScaleFactor;
                dest.CurrentLocalMotion = motion;
            }
        }
コード例 #3
0
        //モデルを接地させる(接地の定義は実装を見よ。)
        private void BoundCenterToGround(Model model)
        {
            //追加: 加速度センサONの場合に回転不変性取るよう改善
            var boneHip    = QumarionModel.Bones[StandardPSBones.Hips];
            var initPosHip = boneHip.InitialWorldMatrix.Translate;
            var posHip     = boneHip.WorldMatrix.Translate;
            //NOTE:
            var rotHipInverse = MatrixRotationDif.CreateDifFrom(
                boneHip.WorldMatrix.Rotate,
                boneHip.InitialWorldMatrix.Rotate
                ).Transpose();


            var heights = new List <float>();

            foreach (var t in _groundingIKBones)
            {
                var src  = QumarionModel.Bones[QumaBone2MMDBone.GetQumaBone(t)];
                var dest = MMDStandardBones.GetBone(model, t);
                if (dest == null)
                {
                    continue;
                }

                //1: Tポーズでの Hip -> t のベクトル取得(これは直立)
                var initPosWorld = src.InitialWorldMatrix.Translate;
                var initPos      = new Vector3f(
                    initPosWorld.X - initPosHip.X,
                    initPosWorld.Y - initPosHip.Y,
                    initPosWorld.Z - initPosHip.Z
                    );
                //2: 現在の Hip -> t のベクトルを回転除去しつつ取得

                var posWorld = src.WorldMatrix.Translate;
                var pos      = new Vector3f(
                    posWorld.X - posHip.X,
                    posWorld.Y - posHip.Y,
                    posWorld.Z - posHip.Z
                    );
                //ここ大事: posのベクトルは体の回転込みの値なので逆回転して相殺
                pos = MatrixUtil.Multiply(rotHipInverse, pos);

                //NOTE: MMMではZ軸が後ろ向き正だがQumarionだと前向き正
                var dif = new Vector3(
                    pos.X - initPos.X,
                    pos.Y - initPos.Y,
                    -pos.Z + initPos.Z
                    );

                heights.Add(dif.Y * LegIKScaleFactor);
            }
            if (heights.Count == 0)
            {
                return;
            }

            //移動差分のうちもっとも低い値を取る
            float lowestPosDif = heights.Min();
            var   centerBone   = MMDStandardBones.GetBone(model, MMDStandardBone.Center);

            if (centerBone == null)
            {
                return;
            }

            var motion = centerBone.CurrentLocalMotion;

            //CAUTION: X, Zを勝手に書き換えないように!
            motion.Move = new Vector3(motion.Move.X, -lowestPosDif, motion.Move.Z);

            centerBone.CurrentLocalMotion = motion;
        }