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)); }
/// <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); } } }