private void CreateMorphs(TBodySkin skin)
        {
            if (skin == null || skin.morph == null || skin.morph.BlendDatas.Count <= 0)
            {
                return;
            }
            if (!vertexIndexMap.ContainsKey(skin.obj.name))
            {
                Debug.Log($"Morph: {skin.obj.name} -> Missing vertex base!");
                return;
            }
            int vertexBase = vertexIndexMap[skin.obj.name];

            Debug.Log($"Morph: {skin.obj.name} -> {skin.morph.BlendDatas.Count} ({vertexBase})");
            for (int j = 0; j < skin.morph.BlendDatas.Count; j++)
            {
                BlendData blendData = skin.morph.BlendDatas[j];
                if (blendData != null)
                {
                    PmxMorph pmxMorph = GetOrCreateMorph(blendData.name);
                    for (int k = 0; k < blendData.v_index.Length; k++)
                    {
                        PmxVertexMorph pmxVertexMorph = new PmxVertexMorph(blendData.v_index[k] + vertexBase, new PmxLib.Vector3(-blendData.vert[k].x, blendData.vert[k].z, blendData.vert[k].y));
                        pmxVertexMorph.Offset *= scaleFactor;
                        pmxMorph.OffsetList.Add(pmxVertexMorph);
                    }
                }
            }
        }
示例#2
0
        private PmxVertexMorph ReadPmxVertexMorph()
        {
            var morph = new PmxVertexMorph();

            morph.Index  = _reader.ReadVarLenIntAsInt32(VertexElementSize, true);
            morph.Offset = _reader.ReadVector3();

            return(morph);
        }
示例#3
0
 private void WritePmxVertexMorph([NotNull] PmxVertexMorph morph)
 {
     _writer.WriteInt32AsVarLenInt(morph.Index, MorphElementSize);
     _writer.Write(morph.Offset);
 }
示例#4
0
        private static IReadOnlyList <PmxMorph> AddEmotionMorphs([NotNull] Mesh mesh)
        {
            var morphs = new List <PmxMorph>();

            var s = mesh.Shape;

            if (s != null)
            {
                Debug.Assert(s.Channels.Count == s.Shapes.Count, "s.Channels.Count == s.Shapes.Count");
                Debug.Assert(s.Channels.Count == s.FullWeights.Count, "s.Channels.Count == s.FullWeights.Count");

                var morphCount = s.Channels.Count;

                for (var i = 0; i < morphCount; i++)
                {
                    var channel  = s.Channels[i];
                    var shape    = s.Shapes[i];
                    var vertices = s.Vertices;
                    var morph    = new PmxMorph();

                    var morphName = channel.Name.Substring(12); // - "blendShape1."

                    if (ConversionConfig.Current.TranslateFacialExpressionNamesToMmd)
                    {
                        morph.Name = MorphUtils.LookupMorphName(morphName);
                    }
                    else
                    {
                        morph.Name = morphName;
                    }

                    morph.NameEnglish = morphName;

                    morph.OffsetKind = MorphOffsetKind.Vertex;

                    var offsets = new List <PmxBaseMorph>();

                    for (var j = shape.FirstVertex; j < shape.FirstVertex + shape.VertexCount; ++j)
                    {
                        var v = vertices[(int)j];
                        var m = new PmxVertexMorph();

                        var offset = v.Vertex.ToOpenTK().FixUnityToOpenTK();

                        if (ConversionConfig.Current.ScaleToPmxSize)
                        {
                            offset = offset * ScalingConfig.ScaleUnityToPmx;
                        }

                        m.Index  = (int)v.Index;
                        m.Offset = offset;

                        offsets.Add(m);
                    }

                    morph.Offsets = offsets.ToArray();

                    morphs.Add(morph);
                }

                // Now some custom morphs for our model to be compatible with TDA.
                do
                {
                    PmxMorph CreateCompositeMorph(string mltdTruncMorphName, params string[] truncNames)
                    {
                        int FindIndex <T>(IReadOnlyList <T> list, T item)
                        {
                            var comparer = EqualityComparer <T> .Default;

                            for (var i = 0; i < list.Count; ++i)
                            {
                                if (comparer.Equals(item, list[i]))
                                {
                                    return(i);
                                }
                            }

                            return(-1);
                        }

                        var morph = new PmxMorph();

                        if (ConversionConfig.Current.TranslateFacialExpressionNamesToMmd)
                        {
                            morph.Name = MorphUtils.LookupMorphName(mltdTruncMorphName);
                        }
                        else
                        {
                            morph.Name = mltdTruncMorphName;
                        }

                        morph.NameEnglish = mltdTruncMorphName;

                        var offsets  = new List <PmxBaseMorph>();
                        var vertices = s.Vertices;

                        foreach (var channel in truncNames.Select(name => {
                            // name: e.g. "E_metoji_l"
                            // ch_ex005_016tsu has "blendShape2.E_metoji_l" instead of the common one "blendShape1.E_metoji_l"
                            // so the old method (string equal to full name) breaks.
                            var chan = s.Channels.SingleOrDefault(ch => ch.Name.EndsWith(name));

                            if (chan == null)
                            {
                                Trace.WriteLine($"Warning: required blend channel not found: {name}");
                            }

                            return(chan);
                        }))
                        {
                            if (channel == null)
                            {
                                continue;
                            }

                            var channelIndex = FindIndex(s.Channels, channel);
                            var shape        = s.Shapes[channelIndex];

                            morph.OffsetKind = MorphOffsetKind.Vertex;

                            for (var j = shape.FirstVertex; j < shape.FirstVertex + shape.VertexCount; ++j)
                            {
                                var v = vertices[(int)j];
                                var m = new PmxVertexMorph();

                                var offset = v.Vertex.ToOpenTK().FixUnityToOpenTK();

                                if (ConversionConfig.Current.ScaleToPmxSize)
                                {
                                    offset = offset * ScalingConfig.ScaleUnityToPmx;
                                }

                                m.Index  = (int)v.Index;
                                m.Offset = offset;

                                offsets.Add(m);
                            }
                        }

                        morph.Offsets = offsets.ToArray();

                        return(morph);
                    }

                    morphs.Add(CreateCompositeMorph("E_metoji", "E_metoji_l", "E_metoji_r"));
                } while (false);
            }

            return(morphs.ToArray());
        }