コード例 #1
0
        internal void DropFileToHandle(IntPtr handle, dynamic script, string directory)
        {
            if (PmxModel.ShouldDrop(script))
            {
                Drop(handle, new StringCollection()
                {
                    Path.Combine(directory, ExportFileName + ".pmx")
                });

                if (VmdSequence.ShouldDrop(script))
                {
                    Drop(handle, new StringCollection()
                    {
                        Path.Combine(directory, ExportFileName + ".vmd")
                    });
                }
            }

            void Drop(IntPtr hWnd, StringCollection filePaths)
            {
                Clipboard.Clear();
                Clipboard.SetFileDropList(filePaths);
                var data = Clipboard.GetDataObject();

                IDropTarget     target   = Control.FromHandle(hWnd);
                DragDropEffects dwEffect = DragDropEffects.Copy | DragDropEffects.Link;

                target.OnDragDrop(new DragEventArgs(data, 0, 0, 0, dwEffect, dwEffect));

                Clipboard.Clear();
            }
        }
コード例 #2
0
ファイル: PmxWriter.cs プロジェクト: superowner/MLTDTools
        private void BuildTextureNameMap([NotNull] PmxModel model)
        {
            var materials = model.Materials;

            if (materials == null)
            {
                return;
            }

            var nameList = new List <string>();

            foreach (var material in materials)
            {
                if (!string.IsNullOrEmpty(material.TextureFileName))
                {
                    nameList.Add(material.TextureFileName);
                }

                if (!string.IsNullOrEmpty(material.SphereTextureFileName))
                {
                    nameList.Add(material.SphereTextureFileName);
                }

                if (!string.IsNullOrEmpty(material.ToonTextureFileName) && !ToonNameRegex.IsMatch(material.ToonTextureFileName))
                {
                    nameList.Add(material.ToonTextureFileName);
                }
            }

            _textureNameList.AddRange(nameList.Distinct());
        }
コード例 #3
0
        public void InitializeContents([NotNull] PmxModel pmxModel, [NotNull] Camera camera, [NotNull] SpriteBatch spriteBatch)
        {
            _pmxModel = pmxModel;
            _camera   = camera;

            var boneSegmentCount       = pmxModel.Bones.Count - pmxModel.RootBoneIndices.Count;
            var boneSegmentPairs       = new(int ParentIndex, int ChildIndex)[boneSegmentCount];
コード例 #4
0
        public static void ExportMaterial(PmxModel pmx, Stream outputStream)
        {
            var oldCulture = Thread.CurrentThread.CurrentCulture;

            Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
            try
            {
                using (var writer = new StreamWriter(outputStream, Encoding.Default, 2048, true))
                {
                    foreach (var mat in pmx.Materials)
                    {
                        writer.WriteLine($"newmtl mat{pmx.Materials.IndexOf(mat)}");
                        writer.WriteLine($"Ka {mat.AmbientColor.X} {mat.AmbientColor.Y} {mat.AmbientColor.Z}");
                        writer.WriteLine($"Kd {mat.DiffuseColor.X} {mat.DiffuseColor.Y} {mat.DiffuseColor.Z}");
                        //writer.WriteLine($"Ks {mat.SpecularColor.X} {mat.SpecularColor.Y} {mat.SpecularColor.Z}");
                        //writer.WriteLine($"Ns {mat.SpecularStrength}");
                        //writer.WriteLine($"d {mat.DiffuseColor.W}");
                        //writer.WriteLine($"Tr {1 - mat.DiffuseColor.W}");
                        //writer.WriteLine($"illum 2");
                        if (mat.TextureIndex > 0)
                        {
                            writer.WriteLine($"map_Ka {pmx.Textures[mat.TextureIndex].Replace("\\", "/")}");
                            writer.WriteLine($"map_Kd {pmx.Textures[mat.TextureIndex].Replace("\\", "/")}");
                        }
                        writer.WriteLine();
                        //writer.WriteLine($"map_Ks {pmx.Textures[mat.TextureIndex]}");
                    }
                }
            }
            finally
            {
                Thread.CurrentThread.CurrentCulture = oldCulture;
            }
        }
コード例 #5
0
        private string[] BuildTextureNameMap([NotNull] PmxModel model)
        {
            var materials = model.Materials;

            var nameList = new List <string>();

            foreach (var material in materials)
            {
                if (!string.IsNullOrEmpty(material.TextureFileName))
                {
                    nameList.Add(material.TextureFileName);
                }

                if (!string.IsNullOrEmpty(material.SphereTextureFileName))
                {
                    nameList.Add(material.SphereTextureFileName);
                }

                if (!string.IsNullOrEmpty(material.ToonTextureFileName) && !ToonNameRegex.IsMatch(material.ToonTextureFileName))
                {
                    nameList.Add(material.ToonTextureFileName);
                }
            }

            return(nameList.Distinct().ToArray());
        }
コード例 #6
0
        public void Write([NotNull] PmxModel model)
        {
            EnsureNotDisposed();

            WriteHeader();
            WriteElementFormats(model);

            WritePmxModel(model);
        }
コード例 #7
0
        private void WriteJointInfo([NotNull] PmxModel model)
        {
            _writer.Write(model.Joints.Length);

            foreach (var joint in model.Joints)
            {
                WritePmxJoint(joint);
            }
        }
コード例 #8
0
        private void WriteRigidBodyInfo([NotNull] PmxModel model)
        {
            _writer.Write(model.RigidBodies.Length);

            foreach (var body in model.RigidBodies)
            {
                WritePmxRigidBody(body);
            }
        }
コード例 #9
0
        private void WriteNodeInfo([NotNull] PmxModel model)
        {
            _writer.Write(model.Nodes.Length);

            foreach (var node in model.Nodes)
            {
                WritePmxNode(node);
            }
        }
コード例 #10
0
        private void WriteMorphInfo([NotNull] PmxModel model)
        {
            _writer.Write(model.Morphs.Length);

            foreach (var morph in model.Morphs)
            {
                WritePmxMorph(morph);
            }
        }
コード例 #11
0
        private void WriteBoneInfo([NotNull] PmxModel model)
        {
            _writer.Write(model.Bones.Length);

            foreach (var bone in model.Bones)
            {
                WritePmxBone(bone);
            }
        }
コード例 #12
0
        private void WriteMaterialInfo([NotNull] PmxModel model, [NotNull, ItemNotNull] string[] textureNames)
        {
            _writer.Write(model.Materials.Length);

            foreach (var material in model.Materials)
            {
                WritePmxMaterial(material, textureNames);
            }
        }
コード例 #13
0
        private void WriteFaceInfo([NotNull] PmxModel model)
        {
            _writer.Write(model.FaceTriangles.Length);

            foreach (var v in model.FaceTriangles)
            {
                _writer.WriteInt32AsVarLenInt(v, VertexElementSize, true);
            }
        }
コード例 #14
0
        private void WriteVertexInfo([NotNull] PmxModel model)
        {
            _writer.Write(model.Vertices.Length);

            foreach (var vertex in model.Vertices)
            {
                WritePmxVertex(model, vertex);
            }
        }
コード例 #15
0
        internal void Export(dynamic script, string directory)
        {
            PmxModel.FinalizeModel(VmdSequence.MorphFrameDict.Values.Select(t => t.frame));
            VmdSequence.FinalizeKeyFrame(PmxModel.ModelData.MorphArray);

            ExportEvent?.Invoke(this, new ExportEventArgs(Path.Combine(directory, ExportFileName + ".pmx"), Path.Combine(directory, ExportFileName + ".vmd"))
            {
                Script = script
            });
        }
コード例 #16
0
        private void WritePmxVertex([NotNull] PmxModel model, [NotNull] PmxVertex vertex)
        {
            _writer.Write(vertex.Position);
            _writer.Write(vertex.Normal);
            _writer.Write(vertex.UV);

            for (var i = 0; i < model.UvaCount && i < PmxVertex.MaxUvaCount; ++i)
            {
                _writer.Write(vertex.Uva[i]);
            }

            _writer.Write((byte)vertex.Deformation);

            switch (vertex.Deformation)
            {
            case Deformation.Bdef1:
                _writer.WriteInt32AsVarLenInt(vertex.BoneWeights[0].BoneIndex, BoneElementSize);
                break;

            case Deformation.Bdef2:
                _writer.WriteInt32AsVarLenInt(vertex.BoneWeights[0].BoneIndex, BoneElementSize);
                _writer.WriteInt32AsVarLenInt(vertex.BoneWeights[1].BoneIndex, BoneElementSize);
                _writer.Write(vertex.BoneWeights[0].Weight);
                break;

            case Deformation.Bdef4:
            case Deformation.Qdef:
                _writer.WriteInt32AsVarLenInt(vertex.BoneWeights[0].BoneIndex, BoneElementSize);
                _writer.WriteInt32AsVarLenInt(vertex.BoneWeights[1].BoneIndex, BoneElementSize);
                _writer.WriteInt32AsVarLenInt(vertex.BoneWeights[2].BoneIndex, BoneElementSize);
                _writer.WriteInt32AsVarLenInt(vertex.BoneWeights[3].BoneIndex, BoneElementSize);
                _writer.Write(vertex.BoneWeights[0].Weight);
                _writer.Write(vertex.BoneWeights[1].Weight);
                _writer.Write(vertex.BoneWeights[2].Weight);
                _writer.Write(vertex.BoneWeights[3].Weight);
                break;

            case Deformation.Sdef: {
                _writer.WriteInt32AsVarLenInt(vertex.BoneWeights[0].BoneIndex, BoneElementSize);
                _writer.WriteInt32AsVarLenInt(vertex.BoneWeights[1].BoneIndex, BoneElementSize);
                _writer.Write(vertex.BoneWeights[0].Weight);

                _writer.Write(vertex.C0);
                _writer.Write(vertex.R0);
                _writer.Write(vertex.R1);

                break;
            }

            default:
                throw new ArgumentOutOfRangeException();
            }

            _writer.Write(vertex.EdgeScale);
        }
コード例 #17
0
ファイル: BoneLookup.cs プロジェクト: gagho0/yeahhhhhhh
        public BoneNode[] BuildBoneHierarchy([NotNull] PmxModel pmx)
        {
            var boneList     = new List <BoneNode>();
            var pmxBones     = pmx.Bones;
            var pmxBoneCount = pmxBones.Length;

            var boneNameMapInversion = _boneNameMapInversion;

            for (var i = 0; i < pmxBoneCount; i++)
            {
                var pmxBone = pmxBones[i];
                var parent  = pmxBone.ParentIndex >= 0 ? boneList[pmxBone.ParentIndex] : null;

                boneNameMapInversion.TryGetValue(pmx.Name, out var mltdBoneName);

                var path = mltdBoneName ?? pmxBone.Name;

                Vector3 t;

                if (parent != null)
                {
                    t = pmxBone.InitialPosition - parent.InitialPosition;
                }
                else
                {
                    t = pmxBone.InitialPosition;
                }

                var bone = new BoneNode(parent, i, path, t, Quaternion.Identity);

                boneList.Add(bone);
            }

            foreach (var bone in boneList)
            {
                var level  = 0;
                var parent = bone.Parent;

                while (parent != null)
                {
                    ++level;
                    parent = parent.Parent;
                }

                bone.Level = level;
            }

            foreach (var bone in boneList)
            {
                bone.Initialize();
            }

            return(boneList.ToArray());
        }
コード例 #18
0
        internal ShotModelData AddShot(EntityShotBase entity)
        {
            ShotModelProvider.AddEntity(entity, out ShotModelData data);

            if (!data.IsInitialized)
            {
                PmxModel.InitShotModelData(data);
            }

            return(data);
        }
コード例 #19
0
        internal void Export()
        {
            EntityList.ForEach(e => e.OnDeath());

            PmxModel.FinalizeModel();
            KeyFrames.Finish();

            KeyFrames.Export();
            PmxModel.Export();

            OnExport(EventArgs.Empty);
        }
コード例 #20
0
ファイル: VmdCreator.Dance.cs プロジェクト: gagho0/yeahhhhhhh
        // Set the bones that appear in the animation file as "key bone"
        private static void MarkNamedBoneAsKeyBone([NotNull] PmxModel pmx, [NotNull] string name)
        {
            var bone = pmx.Bones.Find(b => b.Name == name);

            if (bone != null)
            {
                bone.IsMltdKeyBone = true;
            }
            else
            {
                Debug.WriteLine($"Warning: trying to mark bone {name} as MLTD key bone but the bone is missing from the model.");
            }
        }
コード例 #21
0
        public IReadOnlyList <BoneNode> BuildBoneHierarchy([NotNull] PmxModel pmx)
        {
            var boneList = new List <BoneNode>();

            for (var i = 0; i < pmx.Bones.Count; i++)
            {
                var pmxBone = pmx.Bones[i];
                var parent  = pmxBone.ParentIndex >= 0 ? boneList[pmxBone.ParentIndex] : null;

                var mltdBoneName = _boneNameMap.SingleOrDefault(kv => kv.Value == pmx.Name).Key;
                var path         = mltdBoneName ?? pmxBone.Name;

                Vector3 t;

                if (parent != null)
                {
                    t = pmxBone.InitialPosition - parent.InitialPosition;
                }
                else
                {
                    t = pmxBone.InitialPosition;
                }

                var bone = new BoneNode(parent, i, path, t, Quaternion.Identity);

                boneList.Add(bone);
            }

            foreach (var bone in boneList)
            {
                var level  = 0;
                var parent = bone.Parent;

                while (parent != null)
                {
                    ++level;
                    parent = parent.Parent;
                }

                bone.Level = level;
            }

            foreach (var bone in boneList)
            {
                bone.Initialize();
            }

            return(boneList);
        }
コード例 #22
0
ファイル: PmxFileTests.cs プロジェクト: superowner/PmxParse
        public void TestPmxHeader()
        {
            using (var stream = File.OpenRead(Path.Combine(TestContext.CurrentContext.TestDirectory, "Mockups", "Model.pmx")))
            {
                var model = new PmxModel(stream);
                Assert.AreEqual(2, model.Header.Version);

                Assert.IsNotNull(model.ModelInfo.CharacterName);
                Assert.IsNotNull(model.ModelInfo.UniversalCharacterName);
                Assert.IsNotNull(model.ModelInfo.Comment);
                Assert.IsNotNull(model.ModelInfo.UniversalComment);

                Assert.IsTrue(model.VertexData.Vertices.Length > 0);
                Assert.IsTrue(model.FaceData.Indices.All(i => i < model.VertexData.Vertices.Length));
            }
        }
コード例 #23
0
        private void WritePmxModel([NotNull] PmxModel model)
        {
            var textureNames = BuildTextureNameMap(model);

            WriteString(model.Name);
            WriteString(model.NameEnglish);
            WriteString(model.Comment);
            WriteString(model.CommentEnglish);

            WriteVertexInfo(model);
            WriteFaceInfo(model);
            WriteTextureInfo(textureNames);
            WriteMaterialInfo(model, textureNames);
            WriteBoneInfo(model);
            WriteMorphInfo(model);
            WriteNodeInfo(model);
            WriteRigidBodyInfo(model);
            WriteJointInfo(model);
            WriteSoftBodyInfo(model);
        }
コード例 #24
0
        private void WriteSoftBodyInfo([NotNull] PmxModel model)
        {
            if (DetailedVersion < 2.1f)
            {
                return;
            }

            if (model.SoftBodies != null)
            {
                _writer.Write(model.SoftBodies.Length);

                foreach (var body in model.SoftBodies)
                {
                    WritePmxSoftBody(body);
                }
            }
            else
            {
                _writer.Write(0);
            }
        }
コード例 #25
0
        public void InitializeContents([NotNull] PmxModel pmxModel, [NotNull] VmdMotion vmdMotion)
        {
            _pmxModel  = pmxModel;
            _vmdMotion = vmdMotion;

            foreach (var boneFrame in vmdMotion.BoneFrames)
            {
                if (!_lastBoneFrames.ContainsKey(boneFrame.Name))
                {
                    _lastBoneFrames[boneFrame.Name] = boneFrame;
                }

                List <VmdBoneFrame> cachedBoneFrames;

                if (!_boneFrameCache.ContainsKey(boneFrame.Name))
                {
                    cachedBoneFrames = new List <VmdBoneFrame>();
                    _boneFrameCache[boneFrame.Name] = cachedBoneFrames;
                }
                else
                {
                    cachedBoneFrames = _boneFrameCache[boneFrame.Name];
                }

                cachedBoneFrames.Add(boneFrame);
            }

            _boneFrameNames = _lastBoneFrames.Keys.ToArray();

#if DEBUG
            Debug.Print("VMD bone list:");

            foreach (var boneFrameName in _boneFrameNames)
            {
                Debug.Print(boneFrameName);
            }
#endif
        }
コード例 #26
0
        private void WriteElementFormats([NotNull] PmxModel model)
        {
            byte[] elementSizes;
            byte   elementSizeEntryCount;

            switch (MajorVersion)
            {
            case PmxFormatVersion.Version1:
                elementSizeEntryCount = 5;
                elementSizes          = new byte[elementSizeEntryCount];
                elementSizes[0]       = (byte)VertexElementSize;
                elementSizes[1]       = (byte)BoneElementSize;
                elementSizes[2]       = (byte)MorphElementSize;
                elementSizes[3]       = (byte)MaterialElementSize;
                elementSizes[4]       = (byte)RigidBodyElementSize;
                break;

            case PmxFormatVersion.Version2:
                elementSizeEntryCount = 8;
                elementSizes          = new byte[elementSizeEntryCount];
                elementSizes[0]       = (byte)StringEncoding;
                elementSizes[1]       = (byte)model.UvaCount;
                elementSizes[2]       = (byte)VertexElementSize;
                elementSizes[3]       = (byte)TexElementSize;
                elementSizes[4]       = (byte)MaterialElementSize;
                elementSizes[5]       = (byte)BoneElementSize;
                elementSizes[6]       = (byte)MorphElementSize;
                elementSizes[7]       = (byte)RigidBodyElementSize;
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }

            _writer.Write(elementSizeEntryCount);
            _writer.Write(elementSizes);
        }
コード例 #27
0
        public static void RecalculateAllBoneInfo([NotNull] this PmxModel pmxModel)
        {
            for (var i = 0; i < pmxModel.Bones.Count; i++)
            {
                var bone = pmxModel.Bones[i];
                bone.IsTransformCalculated = false;
            }

            for (var i = 0; i < pmxModel.Bones.Count; i++)
            {
                var bone = pmxModel.Bones[i];

                // VMD controlled pose
                bone.SetToVmdPose();
                // Binding pose
                //bone.SetToBindingPose();
            }

            for (var i = 0; i < pmxModel.Bones.Count; i++)
            {
                var bone = pmxModel.Bones[i];
                bone.UpdateSkinMatrix();
            }
        }
コード例 #28
0
        public void InitializeContents([NotNull] PmxModel pmxModel, [NotNull] Camera camera, [NotNull] IReadOnlyDictionary <string, Texture2D> textureMap)
        {
            _pmxModel   = pmxModel;
            _camera     = camera;
            _textureMap = textureMap;

            var graphicsDevice = GraphicsDevice;

            var pmxMaterials  = pmxModel.Materials;
            var faceTriangles = pmxModel.FaceTriangles;
            var pmxVertices   = pmxModel.Vertices;

            #region Vertex buffer
            var vertexBuffer = new VertexBuffer(graphicsDevice, VertexPositionNormalTexture.VertexDeclaration, pmxVertices.Count, BufferUsage.WriteOnly);
            var vertices     = new VertexPositionNormalTexture[pmxVertices.Count];

            for (var i = 0; i < pmxVertices.Count; ++i)
            {
                var v = pmxVertices[i];
                vertices[i] = new VertexPositionNormalTexture(v.Position, v.Normal, v.UV);
            }

            vertexBuffer.SetData(vertices);
            _vertices     = vertices;
            _vertexBuffer = vertexBuffer;
            #endregion

            #region Index buffer
            var indexBuffer = new IndexBuffer(graphicsDevice, IndexElementSize.ThirtyTwoBits, faceTriangles.Count, BufferUsage.WriteOnly);
            var indices     = new int[faceTriangles.Count];

            for (var i = 0; i < faceTriangles.Count; ++i)
            {
                indices[i] = faceTriangles[i];
            }

            indexBuffer.SetData(indices);
            _indices     = indices;
            _indexBuffer = indexBuffer;
            #endregion

            var currentFaceStartIndex = 0;

            for (var index = 0; index < pmxMaterials.Count; index++)
            {
                var pmxMaterial = pmxMaterials[index];
                var effect      = new BasicEffect(graphicsDevice);
                // A white pixel texture is set with key = string.Empty.
                var textureKey = textureMap.ContainsKey(pmxMaterial.TextureFileName) ? pmxMaterial.TextureFileName : string.Empty;

                effect.AmbientLightColor = pmxMaterial.Ambient;
                effect.DiffuseColor      = pmxMaterial.Diffuse.XYZ();
                effect.Alpha             = pmxMaterial.Diffuse.W;
                effect.SpecularColor     = pmxMaterial.Specular;
                effect.SpecularPower     = pmxMaterial.SpecularPower;
                effect.TextureEnabled    = true;
                effect.Texture           = textureMap[textureKey];

                var meshPart = new MeshPart();

                meshPart.Effect        = effect;
                meshPart.VertexBuffer  = vertexBuffer;
                meshPart.VertexStart   = 0;
                meshPart.IndexBuffer   = indexBuffer;
                meshPart.IndexStart    = currentFaceStartIndex;
                meshPart.TriangleCount = pmxMaterial.AppliedFaceVertexCount / 3;

                _meshParts.Add(meshPart);

                currentFaceStartIndex += pmxMaterial.AppliedFaceVertexCount;
            }

            Debug.Assert(currentFaceStartIndex == pmxModel.FaceTriangles.Count, "currentFaceStartIndex == pmxModel.FaceTriangles.Count");

#if DEBUG
            Debug.Print("PMX bone list:");

            foreach (var pmxBone in pmxModel.Bones)
            {
                Debug.Print(pmxBone.ToString());
            }
#endif
        }
コード例 #29
0
        private IReadOnlyList <VmdBoneFrame> CreateBoneFrames([NotNull] IBodyAnimationSource bodyMotionSource, [NotNull] PrettyAvatar avatar, [NotNull] PmxModel pmx)
        {
            var boneLookup = new BoneLookup(_conversionConfig);

            var mltdHierarchy = boneLookup.BuildBoneHierarchy(avatar);
            var pmxHierarchy  = boneLookup.BuildBoneHierarchy(pmx);

            if (_conversionConfig.AppendIKBones || _conversionConfig.AppendEyeBones)
            {
                throw new NotSupportedException("Character motion frames generation (from MLTD) is not supported when appending bones (eyes and/or IK) is enabled.");
            }
            else
            {
                Debug.Assert(mltdHierarchy.Count == pmxHierarchy.Count, "Hierarchy number should be equal between MLTD and MMD.");
            }

            foreach (var mltdBone in mltdHierarchy)
            {
                mltdBone.Initialize();
            }

            foreach (var pmxBone in pmxHierarchy)
            {
                pmxBone.Initialize();
            }

            var animation         = bodyMotionSource.Convert();
            var boneCount         = mltdHierarchy.Count;
            var animatedBoneCount = animation.BoneCount;
            var keyFrameCount     = animation.KeyFrames.Count;

            {
                void MarkNamedBone(string name)
                {
                    var bone = pmx.Bones.FirstOrDefault(b => b.Name == name);

                    if (bone != null)
                    {
                        bone.IsMltdKeyBone = true;
                    }
                    else
                    {
                        Debug.Print("Warning: trying to mark bone {0} as MLTD key bone but the bone is missing from the model.", name);
                    }
                }

                var names1 = animation.KeyFrames.Take(animatedBoneCount)
                             .Select(kf => kf.Path).ToArray();
                var names = names1.Select(boneLookup.GetVmdBoneNameFromBonePath).ToArray();
                // Mark MLTD key bones.
                foreach (var name in names)
                {
                    MarkNamedBone(name);
                }

                // Special cases
                MarkNamedBone("KUBI");
                MarkNamedBone("頭");
            }

            Debug.Assert(keyFrameCount % animatedBoneCount == 0, "keyFrameCount % animatedBoneCount == 0");

            var iterationTimes = keyFrameCount / animatedBoneCount;
            var boneFrameList  = new List <VmdBoneFrame>();

            // Reduce memory pressure of allocating new delegates (see mltdHierarchy.FirstOrDefault(...))
            var boneMatchPredicateCache = new Func <PmxBone, bool> [boneCount];

            for (var j = 0; j < boneCount; j += 1)
            {
                var refBone = pmx.Bones[j];
                boneMatchPredicateCache[j] = bone => bone.Name == refBone.Name;
            }

            // Cache `mltdBoneName`s so we don't have to compute them all in every iteration
            var boneNameCache = new Dictionary <string, string>();

            // OK, now perform iterations
            for (var i = 0; i < iterationTimes; ++i)
            {
                if (_conversionConfig.Transform60FpsTo30Fps)
                {
                    if (i % 2 == 1)
                    {
                        continue;
                    }
                }

                var keyFrameIndexStart = i * animatedBoneCount;

                for (var j = 0; j < animatedBoneCount; ++j)
                {
                    var    keyFrame = animation.KeyFrames[keyFrameIndexStart + j];
                    string mltdBoneName;

                    if (boneNameCache.ContainsKey(keyFrame.Path))
                    {
                        mltdBoneName = boneNameCache[keyFrame.Path];
                    }
                    else
                    {
                        if (keyFrame.Path.Contains("BODY_SCALE/"))
                        {
                            mltdBoneName = keyFrame.Path.Replace("BODY_SCALE/", string.Empty);
                        }
                        else
                        {
                            mltdBoneName = keyFrame.Path;
                        }

                        boneNameCache.Add(keyFrame.Path, mltdBoneName);
                    }

                    var targetBone = mltdHierarchy.SingleOrDefault(bone => bone.Name == mltdBoneName);

                    if (targetBone == null)
                    {
                        //throw new ArgumentException("Bone not found.");
                        continue; // Shika doesn't have the "POSITION" bone.
                    }

                    BoneNode transferredBone = null;

                    foreach (var kv in BoneAttachmentMap)
                    {
                        if (kv.Key == mltdBoneName)
                        {
                            transferredBone = mltdHierarchy.SingleOrDefault(bone => bone.Name == kv.Value);

                            if (transferredBone == null)
                            {
                                throw new ArgumentException();
                            }

                            break;
                        }
                    }

                    if (keyFrame.HasPositions)
                    {
                        // ReSharper disable once PossibleInvalidOperationException
                        var x = keyFrame.PositionX.Value;
                        // ReSharper disable once PossibleInvalidOperationException
                        var y = keyFrame.PositionY.Value;
                        // ReSharper disable once PossibleInvalidOperationException
                        var z = keyFrame.PositionZ.Value;

                        var t = new Vector3(x, y, z);

                        t = t.FixUnityToOpenTK();

                        if (_conversionConfig.ScaleToVmdSize)
                        {
                            t = t * _scalingConfig.ScaleUnityToPmx;
                        }

                        targetBone.LocalPosition = t;

                        //if (transferredBone != null) {
                        //    transferredBone.LocalPosition = t;
                        //}
                    }

                    if (keyFrame.HasRotations)
                    {
                        // ReSharper disable once PossibleInvalidOperationException
                        var x = keyFrame.AngleX.Value;
                        // ReSharper disable once PossibleInvalidOperationException
                        var y = keyFrame.AngleY.Value;
                        // ReSharper disable once PossibleInvalidOperationException
                        var z = keyFrame.AngleZ.Value;

                        var q = UnityRotation.EulerDeg(x, y, z);

                        q = q.FixUnityToOpenTK();

                        targetBone.LocalRotation = q;

                        if (transferredBone != null)
                        {
                            transferredBone.LocalRotation = q;
                        }
                    }
                }

                foreach (var mltdBone in mltdHierarchy)
                {
                    mltdBone.UpdateTransform();
                }

                for (var j = 0; j < boneCount; ++j)
                {
                    var pmxBone  = pmxHierarchy[j];
                    var mltdBone = mltdHierarchy[j];

                    {
                        var predicate = boneMatchPredicateCache[j];
                        var pb        = pmx.Bones.FirstOrDefault(predicate);

#if DEBUG
                        if (pb == null)
                        {
                            // Lazy evaluation of the assertion message
                            Debug.Assert(pb != null, $"PMX bone with the name \"{pmxBone.Name}\" should exist.");
                        }
#endif

                        if (!pb.IsMltdKeyBone)
                        {
                            continue;
                        }
                    }

                    var skinMatrix      = mltdBone.SkinMatrix;
                    var mPmxBindingPose = pmxBone.BindingPose;
                    var mWorld          = pmxBone.Parent?.WorldMatrix ?? Matrix4.Identity;

                    // skinMatrix == inv(mPmxBindingPose) x mLocal x mWorld
                    var mLocal = mPmxBindingPose * skinMatrix * mWorld.Inverted();

                    // Here, translation is in... world coords? WTF?
                    var t = mLocal.ExtractTranslation();
                    var q = mLocal.ExtractRotation();

                    if (pmxBone.Parent != null)
                    {
                        t = t - (pmxBone.InitialPosition - pmxBone.Parent.InitialPosition);
                    }

                    int frameIndex;

                    if (_conversionConfig.Transform60FpsTo30Fps)
                    {
                        frameIndex = i / 2;
                    }
                    else
                    {
                        frameIndex = i;
                    }

                    var vmdBoneName = boneLookup.GetVmdBoneNameFromBoneName(mltdBone.Path);
                    var boneFrame   = new VmdBoneFrame(frameIndex, vmdBoneName);

                    boneFrame.Position = t;
                    boneFrame.Rotation = q;

                    boneFrameList.Add(boneFrame);

                    pmxBone.LocalPosition = t;
                    pmxBone.LocalRotation = q;
                    pmxBone.UpdateTransform();
                }
            }

            return(boneFrameList);
        }
コード例 #30
0
ファイル: Scene.cs プロジェクト: ousttrue/csmeshio
 /// <summary>
 /// pmxモデルを追加
 /// </summary>
 public void Load(meshio.Pmx.Model pmx)
 {
     var model=new PmxModel(pmx);
     _drawables.Add(model);
     _resourceManager.Add(model);
 }
コード例 #31
0
ファイル: PmxReader.cs プロジェクト: logchan/MLTDTools
        private PmxModel ReadPmxModel()
        {
            var model = new PmxModel();

            model.Name           = ReadString() ?? string.Empty;
            model.NameEnglish    = ReadString() ?? string.Empty;
            model.Comment        = ReadString() ?? string.Empty;
            model.CommentEnglish = ReadString() ?? string.Empty;

            ReadVertexInfo();
            ReadFaceInfo();
            ReadTextureInfo();
            ReadMaterialInfo();
            ReadBoneInfo();
            ReadMorphInfo();
            ReadNodeInfo();
            ReadRigidBodyInfo();
            ReadJointInfo();
            ReadSoftBodyInfo();

            return(model);

            void ReadVertexInfo()
            {
                var vertexCount = _reader.ReadInt32();
                var vertices    = new PmxVertex[vertexCount];

                for (var i = 0; i < vertexCount; ++i)
                {
                    vertices[i] = ReadPmxVertex();
                }

                model.Vertices = vertices;
            }

            void ReadFaceInfo()
            {
                var faceCount   = _reader.ReadInt32();
                var faceIndices = new int[faceCount];

                for (var i = 0; i < faceCount; ++i)
                {
                    faceIndices[i] = _reader.ReadVarLenIntAsInt32(VertexElementSize, true);
                }

                model.FaceTriangles = faceIndices;
            }

            void ReadTextureInfo()
            {
                var textureCount       = _reader.ReadInt32();
                var textureNameMap     = new Dictionary <int, string>();
                var textureIndexLookup = new Dictionary <string, int>();

                for (var i = 0; i < textureCount; ++i)
                {
                    var textureName = ReadString() ?? string.Empty;
                    textureNameMap[i] = textureName;
                    textureIndexLookup[textureName] = i;
                }

                textureNameMap[-1] = string.Empty;

                TextureNameMap     = textureNameMap;
                TextureIndexLookup = textureIndexLookup;
            }

            void ReadMaterialInfo()
            {
                var materialCount = _reader.ReadInt32();
                var materials     = new PmxMaterial[materialCount];

                for (var i = 0; i < materialCount; ++i)
                {
                    materials[i] = ReadPmxMaterial();
                }

                model.Materials = materials;
            }

            void ReadBoneInfo()
            {
                var boneCount = _reader.ReadInt32();
                var bones     = new PmxBone[boneCount];

                for (var i = 0; i < boneCount; ++i)
                {
                    bones[i]           = ReadPmxBone();
                    bones[i].BoneIndex = i;
                }

                model.Bones           = bones;
                model.BonesDictionary = bones.ToDictionary(bone => bone.Name);

                var rootBoneIndexList = new List <int>();

                for (var i = 0; i < bones.Length; ++i)
                {
                    var bone = bones[i];

                    if (bone.ParentIndex < 0)
                    {
                        rootBoneIndexList.Add(i);
                    }
                    else
                    {
                        bone.Parent = bones[bone.ParentIndex];
                    }

                    if (bone.AppendParentIndex >= 0)
                    {
                        bone.AppendParent = bones[bone.AppendParentIndex];
                    }

                    if (bone.ExternalParentIndex >= 0)
                    {
                        bone.ExternalParent = bones[bone.ExternalParentIndex];
                    }

                    if (bone.HasFlag(BoneFlags.IK))
                    {
                        var ik = bone.IK;

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

                        ik.TargetBone = bones[ik.TargetBoneIndex];

                        foreach (var link in ik.Links)
                        {
                            if (link.BoneIndex >= 0)
                            {
                                link.Bone = bones[link.BoneIndex];
                            }
                        }
                    }
                }

                model.RootBoneIndices = rootBoneIndexList.ToArray();

                foreach (var bone in bones)
                {
                    bone.SetToBindingPose();
                }
            }

            void ReadMorphInfo()
            {
                var morphCount = _reader.ReadInt32();
                var morphs     = new PmxMorph[morphCount];

                for (var i = 0; i < morphCount; ++i)
                {
                    morphs[i] = ReadPmxMorph();
                }

                model.Morphs = morphs;
            }

            void ReadNodeInfo()
            {
                var nodeCount = _reader.ReadInt32();
                var nodes     = new PmxNode[nodeCount];

                for (var i = 0; i < nodeCount; ++i)
                {
                    var node = ReadPmxNode();

                    nodes[i] = node;

                    if (node.IsSystemNode)
                    {
                        if (node.Name == "Root")
                        {
                            model.RootNodeIndex = i;
                        }
                        else if (node.Name == "表情")
                        {
                            model.FacialExpressionNodeIndex = i;
                        }
                    }
                }

                model.Nodes = nodes;
            }

            void ReadRigidBodyInfo()
            {
                var bodyCount = _reader.ReadInt32();
                var bodies    = new PmxRigidBody[bodyCount];

                for (var i = 0; i < bodyCount; ++i)
                {
                    bodies[i] = ReadPmxRigidBody();
                }

                model.RigidBodies = bodies;
            }

            void ReadJointInfo()
            {
                var jointCount = _reader.ReadInt32();
                var joints     = new PmxJoint[jointCount];

                for (var i = 0; i < jointCount; ++i)
                {
                    joints[i] = ReadPmxJoint();
                }

                model.Joints = joints;
            }

            void ReadSoftBodyInfo()
            {
                if (DetailedVersion < 2.1f)
                {
                    return;
                }

                var bodyCount = _reader.ReadInt32();
                var bodies    = new PmxSoftBody[bodyCount];

                for (var i = 0; i < bodyCount; ++i)
                {
                    bodies[i] = ReadPmxSoftBody();
                }

                model.SoftBodies = bodies;
            }
        }