示例#1
0
        public static MMDMotion2 bake(MMDMotion2 motion, MMDModel1 model)
        {
            //ボーン取得
            MMDBoneManager boneManager = ModelConverter.BuildBoneManager(model);
            //ベイク前のモーションとベイク後のモーションを準備
            MMDMotion beforeMotion = MotionConverter.Convert(motion);
            MMDMotion afterMotion  = CreateAfterMotionPrototype(beforeMotion, boneManager);
            //アニメーションプレイヤーを作成
            AnimationPlayer player = new AnimationPlayer(boneManager);

            player.SetMotion(beforeMotion);
            //ベイクしていく
            uint frameNo  = 0;
            bool ExitFlag = false;

            while (!ExitFlag)
            {
                ExitFlag = !player.Update();
                //ボーンのグローバル行列更新
                boneManager.CalcGlobalTransform();
                //IK更新
                boneManager.CalcIK();
                //ベイク
                boneManager.bake(frameNo, afterMotion);
                ++frameNo;
            }
            //元のMMDMotion2に直して返却
            return(MotionConverter.Convert(afterMotion, motion.ModelName));
        }
 public AnimationPlayer(MMDBoneManager boneManager)
 {
     this.boneManager = boneManager;
     BindPoses        = new Dictionary <string, SQTTransform>();
     for (int i = 0; i < boneManager.Count; ++i)
     {
         BindPoses.Add(boneManager[i].Name, boneManager[i].BindPose);
     }
 }
示例#3
0
 internal AnimationPlayer(MMDBoneManager bones, IMMDFaceManager faces)
 {
     boneManager = bones;
     faceManager = faces;
     BindPoses = new Dictionary<string, SQTTransform>();
     for (int i = 0; i < boneManager.Count; ++i)
     {
         BindPoses.Add(boneManager[i].Name, boneManager[i].BindPose);
     }
     Poses = new Dictionary<string, SQTTransform>(BindPoses.Count);
     Faces = new Dictionary<string, float>(faces.Count);
 }
示例#4
0
文件: MMDXModel.cs 项目: himapo/ccm
        /// <summary>
        /// コンストラクタ
        /// </summary>
        /// <param name="modelParts">モデルパーツ</param>
        /// <param name="boneManager">ボーンマネージャ</param>
        /// <param name="faceManager">表情マネージャ</param>
        /// <param name="attachedMotion">付属モーション</param>
        /// <param name="rigids">剛体</param>
        /// <param name="joints">ジョイント</param>
        public MMDXModel(List<IMMDModelPart> modelParts, MMDBoneManager boneManager, IMMDFaceManager faceManager, Dictionary<string, MMDMotion> attachedMotion, MMDRigid[] rigids, MMDJoint[] joints)
            : base(modelParts, boneManager, faceManager, attachedMotion, rigids, joints)
        {
#if XBOX
            //ボーンマネージャ・表情マネージャを変換しておく
            this.boneManager = (MMDXBoxBoneManager)boneManager;
            this.faceManager = (MMDXBoxFaceManager)faceManager;
            //グラフィックデバイスの抜き出し
            if (modelParts.Count > 0)
            {
                GraphicsDevice graphics = ((MMDModelPart)modelParts[0]).GraphicsDevice;
                //頂点バッファの作成
                skinVertexBuffer = new WritableVertexBuffer(graphics, this.boneManager.SKinTransformXBox.Length * 4, typeof(VertexSkinning));
                this.faceManager.SetUp(graphics);
            }
#endif
        }
示例#5
0
        /// <summary>
        /// コンストラクタ
        /// </summary>
        /// <param name="vertex">頂点データ</param>
        /// <param name="modelParts">モデルパーツ</param>
        /// <param name="boneManager">ボーンマネージャ</param>
        /// <param name="faceManager">表情マネージャ</param>
        /// <param name="attachedMotion">付随モーション</param>
        /// <param name="rigids">剛体情報</param>
        /// <param name="joints">関節情報</param>
        public SlimMMDModel(MMDVertexNmTx[] vertex, List<IMMDModelPart> modelParts, MMDBoneManager boneManager, MMDFaceManager faceManager, Dictionary<string, MMDMotion> attachedMotion, MMDRigid[] rigids, MMDJoint[] joints)
            : base(modelParts, boneManager, faceManager, attachedMotion, rigids, joints)
        {
            m_vertex = vertex;
            //データのコピー
            verticesSource = new VertexPNmTx[m_vertex.LongLength];
            for (long i = 0; i < m_vertex.LongLength; ++i)
            {
                verticesSource[i].Position = m_vertex[i].Position;
                verticesSource[i].Normal = m_vertex[i].Normal;
                verticesSource[i].Texture = m_vertex[i].TextureCoordinate;
            }

            InitGraphicsResource();

            SlimMMDXCore.Instance.LostDevice += OnLostDevice;
            SlimMMDXCore.Instance.ResetDevice += OnResetDevice;
        }
示例#6
0
文件: MMDModel.cs 项目: himapo/ccm
        /// <summary>
        /// コンストラクタ
        /// </summary>
        /// <param name="modelParts">モデルパーツ</param>
        /// <param name="boneManager">ボーンマネージャ</param>
        /// <param name="faceManager">表情マネージャ</param>
        /// <param name="attachedMotion">付随モーション</param>
        /// <param name="rigids">剛体情報</param>
        /// <param name="joints">関節情報</param>
        public MMDModel(List<IMMDModelPart> modelParts, MMDBoneManager boneManager, IMMDFaceManager faceManager, Dictionary<string, MMDMotion> attachedMotion, MMDRigid[] rigids, MMDJoint[] joints)
        {
            Transform = Matrix.Identity;
            this.modelParts = modelParts;
            this.boneManager = boneManager;
            this.faceManager = faceManager;
            this.attachedMotion = attachedMotion;
            Culling = true;
            boneManager.CalcGlobalTransform();
            this.physicsManager = new PhysicsManager(rigids, joints, this);

            foreach (var part in modelParts)
                part.SetModel(this);
            Parts = new ReadOnlyCollection<IMMDModelPart>(modelParts);
            animationPlayer = new AnimationPlayer(boneManager, faceManager);

            //イベントフック
            MMDCore.Instance.OnBoneUpdate += new Action<float>(BoneUpdate);
            MMDCore.Instance.OnSkinUpdate += new Action<float>(SkinUpdate);
        }
示例#7
0
        private static MMDMotion CreateAfterMotionPrototype(MMDMotion beforeMotion, MMDBoneManager boneManager)
        {
            //ベイク対象外の情報をコピー
            MMDMotion result = new MMDMotion();

            //表情は参照をコピーしておく
            result.FaceFrames = beforeMotion.FaceFrames;
            //ボーンは必要分だけ参照をコピー
            result.BoneFrames = new Dictionary <string, List <MMDBoneKeyFrame> >();
            foreach (KeyValuePair <string, List <MMDBoneKeyFrame> > boneSet in beforeMotion.BoneFrames)
            {
                if (!boneManager.IsUnderIK(boneSet.Key))
                {
                    result.BoneFrames.Add(boneSet.Key, boneSet.Value);
                }
                else
                {
                    result.BoneFrames.Add(boneSet.Key, new List <MMDBoneKeyFrame>());
                }
            }
            return(result);
        }
示例#8
0
        /// <summary>
        /// IKのソルブ
        /// </summary>
        /// <param name="ik">対象IK</param>
        /// <param name="BoneManager">ボーンマネージャ</param>
        /// <returns>呼び出し側でUpdateGlobalをもう一度呼ぶ場合はtrue</returns>
        public bool Solve(MMDIK ik, MMDBoneManager BoneManager)
        {
#if SlimDX
            Vector4 localTargetPos   = Vector4.Zero;
            Vector4 localEffectorPos = Vector4.Zero;
#else
            Vector3 localTargetPos   = Vector3.Zero;
            Vector3 localEffectorPos = Vector3.Zero;
#endif
            //エフェクタとなるボーンを取得
            MMDBone effector = ik.IKTargetBone;
            //IK対象のボーンのGlobalを更新(別のIK影響下のボーンからIKチェインが出ている場合があるので)
            Matrix local;
            for (int i = ik.IKChildBones.Count - 1; i >= 0; --i)
            {//順番に親子関係になっている。(Processorでチェックかけてある
                //GlobalTransformを仮更新
                int parentBone = ik.IKChildBones[i].SkeletonHierarchy;
                ik.IKChildBones[i].LocalTransform.CreateMatrix(out local);
                Matrix.Multiply(ref local, ref BoneManager[parentBone].GlobalTransform, out ik.IKChildBones[i].GlobalTransform);
            }
            effector.LocalTransform.CreateMatrix(out local);
            Matrix.Multiply(ref local, ref BoneManager[effector.SkeletonHierarchy].GlobalTransform, out effector.GlobalTransform);

            //ターゲット位置の取得
            Vector3 targetPos;
            Matrix.GetTranslation(ref ik.IKBone.GlobalTransform, out targetPos);

            //最大ループ回数分ループ
            for (int it = 0; it < ik.Iteration; ++it)
            {
                for (int nodeIndex = 0; nodeIndex < ik.IKChildBones.Count; ++nodeIndex)
                {//子ノードを子から順番に……
                    MMDBone node = ik.IKChildBones[nodeIndex];
                    //エフェクタの位置
                    Vector3 effectorPos;
                    Matrix.GetTranslation(ref effector.GlobalTransform, out effectorPos);
                    // 注目ノードの位置の取得
                    Vector3 jointPos;
                    Matrix.GetTranslation(ref node.GlobalTransform, out jointPos);

                    // ワールド座標系から注目ノードの局所座標系への変換
                    Matrix invCoord;
                    Matrix.Invert(ref node.GlobalTransform, out invCoord);
                    // 各ベクトルの座標変換を行い、検索中のボーンi基準の座標系にする
                    // (1) 注目ノード→エフェクタ位置へのベクトル(a)(注目ノード)
                    Vector3.Transform(ref effectorPos, ref invCoord, out localEffectorPos);
                    // (2) 基準関節i→目標位置へのベクトル(b)(ボーンi基準座標系)
                    Vector3.Transform(ref targetPos, ref invCoord, out localTargetPos);
#if SlimDX
                    //念のため……
                    // (1) 基準関節→エフェクタ位置への方向ベクトル
                    Vector3 basis2Effector = Vector3.Normalize(new Vector3(localEffectorPos.X, localEffectorPos.Y, localEffectorPos.Z));
                    // (2) 基準関節→目標位置への方向ベクトル
                    Vector3 basis2Target = Vector3.Normalize(new Vector3(localTargetPos.X, localTargetPos.Y, localTargetPos.Z));
#else
                    // (1) 基準関節→エフェクタ位置への方向ベクトル
                    Vector3 basis2Effector = Vector3.Normalize(localEffectorPos);
                    // (2) 基準関節→目標位置への方向ベクトル
                    Vector3 basis2Target = Vector3.Normalize(localTargetPos);
#endif

                    // 回転角
                    float rotationDotProduct = (float)Vector3.Dot(basis2Effector, basis2Target);
                    float rotationAngle      = (float)Math.Acos(rotationDotProduct);

                    //回転量制限をかける
                    if (rotationAngle > MathHelper.Pi * ik.ControlWeight * (nodeIndex + 1))
                    {
                        rotationAngle = MathHelper.Pi * ik.ControlWeight * (nodeIndex + 1);
                    }
                    if (rotationAngle < -MathHelper.Pi * ik.ControlWeight * (nodeIndex + 1))
                    {
                        rotationAngle = -MathHelper.Pi * ik.ControlWeight * (nodeIndex + 1);
                    }

                    // 回転軸
                    Vector3 rotationAxis = Vector3.Cross(basis2Effector, basis2Target);
                    BoneManager.IKLimitter.Adjust(node.Name, ref rotationAxis);
                    rotationAxis.Normalize();

                    if (!float.IsNaN(rotationAngle) && rotationAngle > 1.0e-3f && !rotationAxis.NaN)
                    {
                        // 関節回転量の補正
                        Quaternion subRot = Quaternion.CreateFromAxisAngle(rotationAxis, (decimal)rotationAngle);
                        Quaternion.Multiply(ref subRot, ref node.LocalTransform.Rotation, out node.LocalTransform.Rotation);
                        BoneManager.IKLimitter.Adjust(node);
                        //関係ノードのグローバル座標更新
                        for (int i = nodeIndex; i >= 0; --i)
                        {//順番に親子関係になっている。(Processorでチェックかけてある
                            //GlobalTransformを仮更新
                            int parentBone = ik.IKChildBones[i].SkeletonHierarchy;
                            ik.IKChildBones[i].LocalTransform.CreateMatrix(out local);
                            Matrix.Multiply(ref local, ref BoneManager[parentBone].GlobalTransform, out ik.IKChildBones[i].GlobalTransform);
                        }
                        effector.LocalTransform.CreateMatrix(out local);
                        Matrix.Multiply(ref local, ref BoneManager[effector.SkeletonHierarchy].GlobalTransform, out effector.GlobalTransform);
                    }
                }
            }
            return(true);//UpdateGlobalをもう一度呼ぶ
            //IKチェインにぶら下がってるIK影響外のボーンを更新するため。
        }
示例#9
0
文件: CCDSolver.cs 项目: himapo/ccm
        /// <summary>
        /// IKのソルブ
        /// </summary>
        /// <param name="ik">対象IK</param>
        /// <param name="BoneManager">ボーンマネージャ</param>
        /// <returns>呼び出し側でUpdateGlobalをもう一度呼ぶ場合はtrue</returns>
        public bool Solve(MMDIK ik, MMDBoneManager BoneManager)
        {
#if SlimDX
            Vector4 localTargetPos = Vector4.Zero;
            Vector4 localEffectorPos = Vector4.Zero;
#else
            Vector3 localTargetPos = Vector3.Zero;
            Vector3 localEffectorPos = Vector3.Zero;
#endif
            //エフェクタとなるボーンを取得
            MMDBone effector = ik.IKTargetBone;
            //IK対象のボーンのGlobalを更新(別のIK影響下のボーンからIKチェインが出ている場合があるので)
            Matrix local;
            for (int i = ik.IKChildBones.Count - 1; i >= 0; --i)
            {//順番に親子関係になっている。(Processorでチェックかけてある
                //GlobalTransformを仮更新
                int parentBone = ik.IKChildBones[i].SkeletonHierarchy;
                ik.IKChildBones[i].LocalTransform.CreateMatrix(out local);
                Matrix.Multiply(ref local, ref BoneManager[parentBone].GlobalTransform, out ik.IKChildBones[i].GlobalTransform);
            }
            effector.LocalTransform.CreateMatrix(out local);
            Matrix.Multiply(ref local, ref BoneManager[effector.SkeletonHierarchy].GlobalTransform, out effector.GlobalTransform);

            //ターゲット位置の取得
            Vector3 targetPos; 
            MMDXMath.GetTranslation(ref ik.IKBone.GlobalTransform, out targetPos);

            //最大ループ回数分ループ
            for (int it = 0; it < ik.Iteration; ++it)
            {
                for (int nodeIndex = 0; nodeIndex < ik.IKChildBones.Count; ++nodeIndex)
                {//子ノードを子から順番に……
                    MMDBone node = ik.IKChildBones[nodeIndex];
                    //エフェクタの位置
                    Vector3 effectorPos;
                    MMDXMath.GetTranslation(ref effector.GlobalTransform, out effectorPos);
                    // 注目ノードの位置の取得
                    Vector3 jointPos;
                    MMDXMath.GetTranslation(ref node.GlobalTransform, out jointPos);

                    // ワールド座標系から注目ノードの局所座標系への変換
                    Matrix invCoord;
                    Matrix.Invert(ref node.GlobalTransform, out invCoord);
                    // 各ベクトルの座標変換を行い、検索中のボーンi基準の座標系にする
                    // (1) 注目ノード→エフェクタ位置へのベクトル(a)(注目ノード)
                    Vector3.Transform(ref effectorPos, ref invCoord, out localEffectorPos);
                    // (2) 基準関節i→目標位置へのベクトル(b)(ボーンi基準座標系)
                    Vector3.Transform(ref targetPos, ref invCoord, out localTargetPos);
#if SlimDX
                    //念のため……
                    // (1) 基準関節→エフェクタ位置への方向ベクトル
                    Vector3 basis2Effector = Vector3.Normalize(new Vector3(localEffectorPos.X, localEffectorPos.Y, localEffectorPos.Z));
                    // (2) 基準関節→目標位置への方向ベクトル
                    Vector3 basis2Target = Vector3.Normalize(new Vector3(localTargetPos.X, localTargetPos.Y, localTargetPos.Z));
#else
                    // (1) 基準関節→エフェクタ位置への方向ベクトル
                    Vector3 basis2Effector = Vector3.Normalize(localEffectorPos);
                    // (2) 基準関節→目標位置への方向ベクトル
                    Vector3 basis2Target = Vector3.Normalize(localTargetPos);
#endif

                    // 回転角
                    float rotationDotProduct = Vector3.Dot(basis2Effector, basis2Target);
                    float rotationAngle = (float)Math.Acos(rotationDotProduct);

                    //回転量制限をかける
                    if (rotationAngle > MathHelper.Pi * ik.ControlWeight * (nodeIndex + 1))
                        rotationAngle = MathHelper.Pi * ik.ControlWeight * (nodeIndex + 1);
                    if (rotationAngle < -MathHelper.Pi * ik.ControlWeight * (nodeIndex + 1))
                        rotationAngle = -MathHelper.Pi * ik.ControlWeight * (nodeIndex + 1);

                    // 回転軸
                    Vector3 rotationAxis = Vector3.Cross(basis2Effector, basis2Target);
                    MMDCore.Instance.IKLimitter.Adjust(node.Name, ref rotationAxis);
                    rotationAxis.Normalize();

                    if (!float.IsNaN(rotationAngle) && rotationAngle > 1.0e-3f && !MMDXMath.CheckNaN(rotationAxis))
                    {
                        // 関節回転量の補正
                        Quaternion subRot = MMDXMath.CreateQuaternionFromAxisAngle(rotationAxis, rotationAngle);
                        Quaternion.Multiply(ref subRot, ref node.LocalTransform.Rotation, out node.LocalTransform.Rotation);
                        MMDCore.Instance.IKLimitter.Adjust(node);
                        //関係ノードのグローバル座標更新
                        for (int i = nodeIndex; i >= 0; --i)
                        {//順番に親子関係になっている。(Processorでチェックかけてある
                            //GlobalTransformを仮更新
                            int parentBone = ik.IKChildBones[i].SkeletonHierarchy;
                            ik.IKChildBones[i].LocalTransform.CreateMatrix(out local);
                            Matrix.Multiply(ref local, ref BoneManager[parentBone].GlobalTransform, out ik.IKChildBones[i].GlobalTransform);
                        }
                        effector.LocalTransform.CreateMatrix(out local);
                        Matrix.Multiply(ref local, ref BoneManager[effector.SkeletonHierarchy].GlobalTransform, out effector.GlobalTransform);
                    }
                }
            }
            return true;//UpdateGlobalをもう一度呼ぶ
            //IKチェインにぶら下がってるIK影響外のボーンを更新するため。
        }