예제 #1
0
        private IEnumerator GenerateBonePoseFile()
        {
            yield return(null);

            var context = (Context)data;
            var model   = ModelReader.LoadMmdModel(context.ModelPath, new ModelReadConfig {
                GlobalToonPath = ""
            });
            var motion = new VmdReader().Read(context.MotionPath);

            Debug.Log("motion load finished" + motion.Length + " frames");
            var generator =
                BonePoseFileGenerator.GenerateAsync(model, motion, context.SavePath, 1.0f / 60.0f, 5.0f, 1.0f / 120.0f);

            _generator = generator;
            while (true)
            {
                var generatorStatus = generator.Status;
                if (generatorStatus == BonePoseFileGenerator.GenerateStatus.Failed ||
                    generatorStatus == BonePoseFileGenerator.GenerateStatus.Finished ||
                    generatorStatus == BonePoseFileGenerator.GenerateStatus.Canceled)
                {
                    break;
                }
                if (generatorStatus == BonePoseFileGenerator.GenerateStatus.CalculatingFrames)
                {
                    _tipText.text = "已计算" + generator.CalculatedFrames + "帧, 共" + generator.TotalFrames + "帧。 已完成"
                                    + 100L * generator.CalculatedFrames / generator.TotalFrames + "%";
                }
                yield return(null);
            }
            if (generator.Status == BonePoseFileGenerator.GenerateStatus.Finished)
            {
                MainSceneController.Instance.ChangeCurrentBonePoseFile(context.SavePath);
            }
            ClosePage();
            switch (generator.Status)
            {
            case BonePoseFileGenerator.GenerateStatus.Finished:
                ShowPage <OkDialog>(new OkDialog.Context
                {
                    Title = "提示",
                    Tip   =
                        "计算完成。现在可以流畅地播放了。以后如果需要再次播放同模型配同动作,选择模型、动作后可以再载入已保存的动作结果文件。记得在选择结果文件时可能需要先点“扫描”才能看到计算结果文件。",
                    OnOk = () => { OnceTipPage.ShowOnceTip(TipNames.WhereIsBonePoseFile); }
                });
                break;

            case BonePoseFileGenerator.GenerateStatus.Failed:
                ShowPage <OkDialog>(new OkDialog.Context
                {
                    Title = "提示",
                    Tip   = "计算发生错误。"
                });
                break;
            }
        }
예제 #2
0
        protected void Start()
        {
            var model = new PmxReader().Read(ModelPath, new ModelReadConfig {
                GlobalToonPath = ""
            });

            Debug.Log("model load finished");
            var motion = new VmdReader().Read(MotionPath);

            Debug.Log("motion load finished" + motion.Length + " frames");
            var bonePoseFileGenerator =
                BonePoseFileGenerator.GenerateAsync(model, motion, BonePoseFileOutputPath);

            StartCoroutine(CheckGenerateStatus(bonePoseFileGenerator));
        }
예제 #3
0
        private static void BuildVmd([NotNull] string outputRoot, [NotNull] string subDirName, [NotNull] string vmdFilePath)
        {
            var vmd = VmdReader.ReadMotionFrom(vmdFilePath);

            var set = new HashSet <string>();

            foreach (var frame in vmd.BoneFrames)
            {
                set.Add(frame.Name);
            }

            foreach (var name in set)
            {
                UnityEngine.Debug.Log(name);
            }
        }
예제 #4
0
파일: Program.cs 프로젝트: Nankk/Beastrack
        static void Main(string[] args)
        {
#if DEBUG
            string path = @"C:\tmp\Sample_000000000213_keypoints.vmd";
#else
            string path = args[0];
#endif

            var vr  = new VmdReader(path);
            var vmd = vr.Read();

            var vw = new VmdWriter(path.Substring(0, path.LastIndexOf('.')) + "_rewrite.vmd");
            vw.Write(vmd);

            foreach (var frame in vmd.Frames)
            {
                Console.WriteLine($"Frame #{frame.Index}");
                Console.WriteLine($"-----------------------------------------");

                foreach (var bone in frame.Bones)
                {
                    Console.WriteLine($"Bone {bone.Key}:");

                    var p = bone.Value.Position;
                    Console.WriteLine($"  Position     (x,y,z)   = ({p.X}, {p.Y}, {p.Z})");
                    var q = bone.Value.Quaternion;
                    Console.WriteLine($"  Quartenion   (x,y,z,w) = ({q.X}, {q.Y}, {q.Z}, {q.W})");
                    var e = EulerAngle.FromQuaternion(q);
                    Console.WriteLine($"  Euler angles (h,p,b)   = ({e.HeadingDeg}, {e.PitchDeg}, {e.BankDeg})");
                }
                Console.WriteLine($"");
            }

#if DEBUG
            Console.WriteLine("Press any key to continue...");
            Console.ReadKey(true);
#else
#endif
        }
예제 #5
0
        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            _spriteBatch = new SpriteBatch(GraphicsDevice);

            // TODO: use this.Content to load your game content here

            var modelBaseDir = Content.RootDirectory;

            PmxModel pmxModel;

            using (var fileStream = File.Open(Path.Combine(modelBaseDir, "mayu.pmx"), FileMode.Open, FileAccess.Read, FileShare.Read)) {
                pmxModel = PmxReader.ReadModel(fileStream);
            }

            Debug.Assert(pmxModel != null, nameof(pmxModel) + " != null");

            foreach (var mat in pmxModel.Materials)
            {
                if (string.IsNullOrEmpty(mat.TextureFileName))
                {
                    continue;
                }

                TryLoadTexture(mat.TextureFileName);
            }

            if (!_modelTextures.ContainsKey(string.Empty))
            {
                var tex = new Texture2D(GraphicsDevice, 1, 1, false, SurfaceFormat.Color);

                tex.SetData(new[] {
                    0xffffffff
                });

                _modelTextures[string.Empty] = tex;
            }

            _pmxModel     = pmxModel;
            _modelBaseDir = modelBaseDir;

            var camera = this.SimpleFindComponentOf <Camera>();

            Debug.Assert(camera != null, nameof(camera) + " != null");

            _pmxRenderer.InitializeContents(pmxModel, camera, _modelTextures);

            VmdMotion vmdMotion;

            using (var fileStream = File.Open(Path.Combine(modelBaseDir, "LD.vmd"), FileMode.Open, FileAccess.Read, FileShare.Read)) {
                vmdMotion = VmdReader.ReadMotion(fileStream);
            }

            const bool rescaleVmd = true;

            if (rescaleVmd)
            {
                var vmdMotionScaleFactor = TryDetectVmdScaleFactor();
                vmdMotion.Scale(vmdMotionScaleFactor);
            }

            _pmxVmdAnimator.InitializeContents(pmxModel, vmdMotion);

            _pmxVmdAnimator.Enabled = false;

            _vmdMotion = vmdMotion;

            _boneDebugVisualizer.InitializeContents(pmxModel, camera, _spriteBatch);

            void TryLoadTexture(string relativeFilePath)
            {
                if (_modelTextures.ContainsKey(relativeFilePath))
                {
                    return;
                }

                var texture = ContentHelper.LoadTexture(GraphicsDevice, Path.Combine(modelBaseDir, relativeFilePath));

                if (texture != null)
                {
                    _modelTextures[relativeFilePath] = texture;
                }
            }

            float TryDetectVmdScaleFactor()
            {
                const float defaultScaleFactor = 1.0f;

                PmxBone pmxBone1, pmxBone2;

                try {
                    pmxBone1 = pmxModel.Bones.SingleOrDefault(b => string.Equals(b.Name, "全ての親", StringComparison.Ordinal));
                    pmxBone2 = pmxModel.Bones.SingleOrDefault(b => string.Equals(b.Name, "センター", StringComparison.Ordinal));
                } catch (InvalidOperationException ex) {
                    // Multiple bones in PMX model having the same name.
                    Debug.Print(ex.ToString());

                    return(defaultScaleFactor);
                }

                var vmdBone1 = vmdMotion.BoneFrames.FirstOrDefault(b => string.Equals(b.Name, "全ての親", StringComparison.Ordinal));
                var vmdBone2 = vmdMotion.BoneFrames.FirstOrDefault(b => string.Equals(b.Name, "センター", StringComparison.Ordinal));

                if (pmxBone1 == null || pmxBone2 == null || vmdBone1 == null || vmdBone2 == null)
                {
                    Debug.Print("At least one of the standard bones is not found. Returning default scale.");

                    return(defaultScaleFactor);
                }

                if (vmdBone1.FrameIndex != 0 || vmdBone2.FrameIndex != 0)
                {
                    Debug.Print("The two VMD standard bones should have appeared at the first frame (index=0). Returning default scale.");

                    return(defaultScaleFactor);
                }

                if (pmxBone2.ParentBone != pmxBone1)
                {
                    Debug.Print("The parent of PMX bone #2 (\"センター\") should be PMX bone #1 (\"全ての親\").");

                    return(defaultScaleFactor);
                }

                var pmxRelativePosition = pmxBone2.InitialPosition - pmxBone1.InitialPosition;
                var vmdRelativePosition = vmdBone2.Position - vmdBone1.Position;

                var pmxLength = pmxRelativePosition.Length();
                var vmdLength = vmdRelativePosition.Length();

                if (vmdLength.Equals(0))
                {
                    return(defaultScaleFactor);
                }
                else
                {
                    return(pmxLength / vmdLength);
                }
            }
        }