Пример #1
0
        // Copies the source mesh from the obj and removes blend shapes with little to no influence on the vertices.
        public static void PruneBlendShapes(Object obj)
        {
            if (!obj)
            {
                return;
            }

            GameObject sceneRoot = PrefabUtility.GetOutermostPrefabInstanceRoot(obj);
            GameObject asset     = PrefabUtility.GetCorrespondingObjectFromSource(sceneRoot);
            Object     srcObj    = PrefabUtility.GetCorrespondingObjectFromSource(obj);
            Mesh       srcMesh   = GetMeshFromSelected(srcObj);
            string     path      = AssetDatabase.GetAssetPath(asset);

            if (string.IsNullOrEmpty(path))
            {
                Debug.LogWarning("Object: " + obj.name + " has no source Prefab Asset.");
                path = Path.Combine("Assets", "dummy.prefab");
            }

            if (!srcMesh)
            {
                Debug.LogError("No mesh found in selected object.");
                return;
            }

            string folder     = Path.GetDirectoryName(path);
            string meshFolder = Path.Combine(folder, PRUNED_FOLDER_NAME);

            Mesh dstMesh = new Mesh();

            dstMesh.vertices     = srcMesh.vertices;
            dstMesh.uv           = srcMesh.uv;
            dstMesh.uv2          = srcMesh.uv2;
            dstMesh.normals      = srcMesh.normals;
            dstMesh.colors       = srcMesh.colors;
            dstMesh.boneWeights  = srcMesh.boneWeights;
            dstMesh.bindposes    = srcMesh.bindposes;
            dstMesh.bounds       = srcMesh.bounds;
            dstMesh.tangents     = srcMesh.tangents;
            dstMesh.triangles    = srcMesh.triangles;
            dstMesh.subMeshCount = srcMesh.subMeshCount;

            for (int s = 0; s < srcMesh.subMeshCount; s++)
            {
                SubMeshDescriptor submesh = srcMesh.GetSubMesh(s);
                dstMesh.SetSubMesh(s, submesh);
            }

            // copy any blendshapes across
            if (srcMesh.blendShapeCount > 0)
            {
                Vector3[] deltaVertices = new Vector3[srcMesh.vertexCount];
                Vector3[] deltaNormals  = new Vector3[srcMesh.vertexCount];
                Vector3[] deltaTangents = new Vector3[srcMesh.vertexCount];

                for (int i = 0; i < srcMesh.blendShapeCount; i++)
                {
                    string name = srcMesh.GetBlendShapeName(i);

                    int frameCount = srcMesh.GetBlendShapeFrameCount(i);
                    for (int f = 0; f < frameCount; f++)
                    {
                        float frameWeight = srcMesh.GetBlendShapeFrameWeight(i, f);
                        srcMesh.GetBlendShapeFrameVertices(i, f, deltaVertices, deltaNormals, deltaTangents);

                        Vector3 deltaSum = Vector3.zero;
                        for (int d = 0; d < srcMesh.vertexCount; d++)
                        {
                            deltaSum += deltaVertices[d];
                        }
                        Debug.Log(name + ": deltaSum = " + deltaSum.ToString());

                        if (deltaSum.magnitude > 0.01f)
                        {
                            dstMesh.AddBlendShapeFrame(name, frameWeight, deltaVertices, deltaNormals, deltaTangents);
                        }
                    }
                }
            }

            // Save the mesh asset.
            if (!AssetDatabase.IsValidFolder(meshFolder))
            {
                AssetDatabase.CreateFolder(folder, PRUNED_FOLDER_NAME);
            }
            string meshPath = Path.Combine(meshFolder, srcObj.name + ".mesh");

            AssetDatabase.CreateAsset(dstMesh, meshPath);

            if (obj.GetType() == typeof(GameObject))
            {
                GameObject go = (GameObject)obj;
                if (go)
                {
                    Mesh createdMesh = AssetDatabase.LoadAssetAtPath <Mesh>(meshPath);

                    if (!ReplaceMesh(obj, createdMesh))
                    {
                        Debug.LogError("Unable to set mesh in selected object!");
                    }
                }
            }
        }
 public static void AddBlendShapeFrame(Mesh m, string nm, float wt, Vector3[] vs, Vector3[] ns, Vector3[] ts)
 {
     m.AddBlendShapeFrame(nm, wt, vs, ns, ts);
 }
Пример #3
0
        private static void BuildNewMesh(SkinnedMeshRenderer skinnedMeshRenderer, Dictionary <int, int> newIndexLookUpDict,
                                         Dictionary <int, int[]> subMeshes, BlendShapeLogic blendShapeLabel)
        {
            // get original mesh data
            var materialList = new List <Material>();

            skinnedMeshRenderer.GetSharedMaterials(materialList);
            var mesh            = skinnedMeshRenderer.sharedMesh;
            var meshVertices    = mesh.vertices;
            var meshNormals     = mesh.normals;
            var meshTangents    = mesh.tangents;
            var meshColors      = mesh.colors;
            var meshBoneWeights = mesh.boneWeights;
            var meshUVs         = mesh.uv;

            // build new mesh
            var materialListNew = new List <Material>();
            var newMesh         = new Mesh();

            if (mesh.vertexCount > ushort.MaxValue)
            {
#if UNITY_2017_3_OR_NEWER
                Debug.LogFormat("exceed 65535 vertices: {0}", mesh.vertexCount);
                newMesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32;
#else
                throw new NotImplementedException(String.Format("exceed 65535 vertices: {0}", integrator.Positions.Count.ToString()));
#endif
            }

            var newDataLength  = newIndexLookUpDict.Count;
            var newIndexLookUp = newIndexLookUpDict.Keys.ToArray();

            newMesh.vertices = newIndexLookUp.Select(x => meshVertices[x]).ToArray();
            if (meshNormals.Length > 0)
            {
                newMesh.normals = newIndexLookUp.Select(x => meshNormals[x]).ToArray();
            }
            if (meshTangents.Length > 0)
            {
                newMesh.tangents = newIndexLookUp.Select(x => meshTangents[x]).ToArray();
            }
            if (meshColors.Length > 0)
            {
                newMesh.colors = newIndexLookUp.Select(x => meshColors[x]).ToArray();
            }
            if (meshBoneWeights.Length > 0)
            {
                newMesh.boneWeights = newIndexLookUp.Select(x => meshBoneWeights[x]).ToArray();
            }
            if (meshUVs.Length > 0)
            {
                newMesh.uv = newIndexLookUp.Select(x => meshUVs[x]).ToArray();
            }
            newMesh.bindposes = mesh.bindposes;

            // add BlendShape data
            if (blendShapeLabel == BlendShapeLogic.WithBlendShape)
            {
                for (int i = 0; i < mesh.blendShapeCount; i++)
                {
                    // get original BlendShape data
                    var srcVertices = new Vector3[mesh.vertexCount];
                    var srcNormals  = new Vector3[mesh.vertexCount];
                    var srcTangents = new Vector3[mesh.vertexCount];
                    mesh.GetBlendShapeFrameVertices(i, 0, srcVertices, srcNormals, srcTangents);

                    // declare the size for the destination array
                    var dstVertices = new Vector3[newDataLength];
                    var dstNormals  = new Vector3[newDataLength];
                    var dstTangents = new Vector3[newDataLength];

                    dstVertices = newIndexLookUp.Select(x => srcVertices[x]).ToArray();
                    dstNormals  = newIndexLookUp.Select(x => srcNormals[x]).ToArray();
                    dstTangents = newIndexLookUp.Select(x => srcTangents[x]).ToArray();
                    newMesh.AddBlendShapeFrame(mesh.GetBlendShapeName(i), mesh.GetBlendShapeFrameWeight(i, 0),
                                               dstVertices, dstNormals, dstTangents);
                }
            }

            newMesh.subMeshCount = subMeshes.Count;
            var cosMaterialIndex = subMeshes.Keys.ToArray();

            // build material list
            for (int i = 0; i < subMeshes.Count; i++)
            {
                newMesh.SetTriangles(subMeshes[cosMaterialIndex[i]], i);
                materialListNew.Add(materialList[cosMaterialIndex[i]]);
            }
            skinnedMeshRenderer.sharedMaterials = materialListNew.ToArray();
            skinnedMeshRenderer.sharedMesh      = newMesh;

            // save mesh as asset
            var assetPath = string.Format("{0}{1}", Path.GetFileNameWithoutExtension(mesh.name), ASSET_SUFFIX);
            Debug.Log(assetPath);
            if (!string.IsNullOrEmpty((AssetDatabase.GetAssetPath(mesh))))
            {
                var directory = Path.GetDirectoryName(AssetDatabase.GetAssetPath(mesh)).Replace("\\", "/");
                assetPath = string.Format("{0}/{1}{2}", directory, Path.GetFileNameWithoutExtension(mesh.name) + "_" + blendShapeLabel.ToString(), ASSET_SUFFIX);
            }
            else
            {
                assetPath = string.Format("Assets/{0}{1}", Path.GetFileNameWithoutExtension(mesh.name) + "_" + blendShapeLabel.ToString(), ASSET_SUFFIX);
            }
            Debug.LogFormat("CreateAsset: {0}", assetPath);
            AssetDatabase.CreateAsset(newMesh, assetPath);
        }
        public void Generate()
        {
            if (source != null)
            {
                if (mesh == null)
                {
                    mesh = new Mesh();
                }

                mesh.Clear(false);
                mesh.name = source.name + " (Copied Coords)";

                mesh.bindposes    = source.bindposes;
                mesh.bounds       = source.bounds;
                mesh.subMeshCount = source.subMeshCount;

                source.GetBoneWeights(boneWeights);
                source.GetColors(colors);
                source.GetNormals(normals);
                source.GetTangents(tangents);
                source.GetUVs(0, coords0);
                source.GetUVs(1, coords1);
                source.GetUVs(2, coords2);
                source.GetUVs(3, coords3);
                source.GetVertices(positions);

                mesh.SetVertices(positions);

                for (var i = 0; i < source.subMeshCount; i++)
                {
                    source.GetTriangles(indices, i);

                    mesh.SetTriangles(indices, i);
                }

                mesh.boneWeights = boneWeights.ToArray();
                mesh.SetColors(colors);
                mesh.SetNormals(normals);
                mesh.SetTangents(tangents);
                //mesh.SetUVs(0, coords0);
                mesh.SetUVs(0, coords1);
                mesh.SetUVs(1, coords1);
                mesh.SetUVs(2, coords2);
                mesh.SetUVs(3, coords3);

                if (source.blendShapeCount > 0)
                {
                    var deltaVertices = new Vector3[source.vertexCount];
                    var deltaNormals  = new Vector3[source.vertexCount];
                    var deltaTangents = new Vector3[source.vertexCount];

                    for (var i = 0; i < source.blendShapeCount; i++)
                    {
                        var shapeName  = source.GetBlendShapeName(i);
                        var frameCount = source.GetBlendShapeFrameCount(i);

                        for (var j = 0; j < frameCount; j++)
                        {
                            source.GetBlendShapeFrameVertices(i, j, deltaVertices, deltaNormals, deltaTangents);

                            mesh.AddBlendShapeFrame(shapeName, source.GetBlendShapeFrameWeight(i, j), deltaVertices, deltaNormals, deltaTangents);
                        }
                    }
                }

#if UNITY_EDITOR
                if (P3dHelper.IsAsset(this) == true)
                {
                    var assets = AssetDatabase.LoadAllAssetsAtPath(AssetDatabase.GetAssetPath(this));

                    for (var i = 0; i < assets.Length; i++)
                    {
                        var assetMesh = assets[i] as Mesh;

                        if (assetMesh != null && assetMesh != mesh)
                        {
                            DestroyImmediate(assetMesh, true);
                        }
                    }

                    if (P3dHelper.IsAsset(mesh) == false)
                    {
                        AssetDatabase.AddObjectToAsset(mesh, this);
                    }
                }
#endif
            }

#if UNITY_EDITOR
            if (P3dHelper.IsAsset(this) == true)
            {
                P3dHelper.ReimportAsset(this);
            }
#endif
        }
Пример #5
0
        public static IEnumerator BuildMeshCoroutine(ImporterContext ctx, MeshImporter.MeshContext meshContext)
        {
            if (!meshContext.materialIndices.Any())
            {
                meshContext.materialIndices.Add(0);
            }

            var mesh = new Mesh();

            mesh.name = meshContext.name;

            if (meshContext.positions.Length > UInt16.MaxValue)
            {
#if UNITY_2017_3_OR_NEWER
                mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32;
#else
                Debug.LogWarningFormat("vertices {0} exceed 65535. not implemented. Unity2017.3 supports large mesh",
                                       meshContext.positions.Length);
#endif
            }


            mesh.vertices = meshContext.positions;
            bool recalculateNormals = false;
            if (meshContext.normals != null && meshContext.normals.Length > 0)
            {
                mesh.normals = meshContext.normals;
            }
            else
            {
                recalculateNormals = true;
            }

            if (meshContext.uv != null && meshContext.uv.Length > 0)
            {
                mesh.uv = meshContext.uv;
            }

            bool recalculateTangents = true;
#if UNIGLTF_IMPORT_TANGENTS
            if (meshContext.tangents != null && meshContext.tangents.Length > 0)
            {
                mesh.tangents       = meshContext.tangents;
                recalculateTangents = false;
            }
#endif

            if (meshContext.colors != null && meshContext.colors.Length > 0)
            {
                mesh.colors = meshContext.colors;
            }
            if (meshContext.boneWeights != null && meshContext.boneWeights.Count > 0)
            {
                mesh.boneWeights = meshContext.boneWeights.ToArray();
            }
            mesh.subMeshCount = meshContext.subMeshes.Count;
            for (int i = 0; i < meshContext.subMeshes.Count; ++i)
            {
                mesh.SetTriangles(meshContext.subMeshes[i], i);
            }

            if (recalculateNormals)
            {
                mesh.RecalculateNormals();
            }
            if (recalculateTangents)
            {
#if UNITY_5_6_OR_NEWER
                yield return(null);

                mesh.RecalculateTangents();
                yield return(null);
#else
                CalcTangents(mesh);
#endif
            }

            var result = new MeshWithMaterials
            {
                Mesh      = mesh,
                Materials = meshContext.materialIndices.Select(x => ctx.GetMaterial(x)).ToArray()
            };

            yield return(null);

            if (meshContext.blendShapes != null)
            {
                Vector3[] emptyVertices = null;

                foreach (var blendShape in meshContext.blendShapes)
                {
                    if (blendShape.Positions.Count > 0)
                    {
                        if (blendShape.Positions.Count == mesh.vertexCount)
                        {
                            mesh.AddBlendShapeFrame(blendShape.Name, FRAME_WEIGHT,
                                                    blendShape.Positions.ToArray(),
                                                    (meshContext.normals != null && meshContext.normals.Length == mesh.vertexCount && blendShape.Normals.Count() == blendShape.Positions.Count()) ? blendShape.Normals.ToArray() : null,
                                                    null
                                                    );
                            yield return(null);
                        }
                        else
                        {
                            Debug.LogWarningFormat("May be partial primitive has blendShape. Require separate mesh or extend blend shape, but not implemented: {0}", blendShape.Name);
                        }
                    }
                    else
                    {
                        if (emptyVertices == null)
                        {
                            emptyVertices = new Vector3[mesh.vertexCount];
                        }
                        // Debug.LogFormat("empty blendshape: {0}.{1}", mesh.name, blendShape.Name);
                        // add empty blend shape for keep blend shape index
                        mesh.AddBlendShapeFrame(blendShape.Name, FRAME_WEIGHT,
                                                emptyVertices,
                                                null,
                                                null
                                                );
                        yield return(null);
                    }
                }
            }

            yield return(result);
        }
Пример #6
0
        public static void CopyMesh(Mesh _src, Mesh _tar)
        {
            _tar.Clear();
            Vector3[] verticies = _src.vertices;
            _tar.vertices    = verticies;
            _tar.normals     = _src.normals;
            _tar.tangents    = _src.tangents;
            _tar.name        = _src.name;
            _tar.bounds      = _src.bounds;
            _tar.bindposes   = _src.bindposes;
            _tar.colors      = _src.colors;
            _tar.boneWeights = _src.boneWeights;
            _tar.triangles   = _src.triangles;
            List <Vector4> uvs = new List <Vector4>();

            for (int i = 0; i < 8; i++)
            {
                _src.GetUVs(i, uvs);
                _tar.SetUVsResize(i, uvs);
            }

            _tar.subMeshCount = _src.subMeshCount;
            for (int i = 0; i < _src.subMeshCount; i++)
            {
                _tar.SetSubMesh(i, _src.GetSubMesh(i));
            }

            _tar.ClearBlendShapes();
            _src.TraversalBlendShapes(verticies.Length, (name, index, frame, weight, deltaVerticies, deltaNormals, deltaTangents) => _tar.AddBlendShapeFrame(name, weight, deltaVerticies, deltaNormals, deltaTangents));
        }
Пример #7
0
        public void AddBlendShapeFrame(Mesh m, string nm, float wt, Vector3[] vs, Vector3[] ns, Vector3[] ts)
        {
#if UNITY_5_3_OR_NEWER
            m.AddBlendShapeFrame(nm, wt, vs, ns, ts);
#endif
        }
Пример #8
0
    static void Execute()
    {
        // base vertices are all zero
        Vector3[] baseVertices = new Vector3[]
        {
            new Vector3(0f, 0f, 0f),
            new Vector3(0f, 0f, 0f),
            new Vector3(0f, 0f, 0f),
            new Vector3(0f, 0f, 0f),
        };
        // we will animate from vertices0 to vertices1
        Vector3[] vertices0 = new Vector3[]
        {
            new Vector3(0f, 0f, 0f),
            new Vector3(1f, 0f, 0f),
            new Vector3(1f, 1f, 0f),
            new Vector3(0f, 1f, 0f),
        };
        Vector3[] vertices1 = new Vector3[]
        {
            new Vector3(0f, 0f, 0f),
            new Vector3(10f, 0f, 0f),
            new Vector3(10f, 10f, 0f),
            new Vector3(0f, 10f, 0f),
        };

        Mesh mesh = new Mesh();

        mesh.vertices = vertices0; //  baseVertices;
        mesh.AddBlendShapeFrame("0", 100f, vertices0, null, null);
        mesh.AddBlendShapeFrame("1", 100f, vertices1, null, null);
        // set bounds to middle and size of vertices1 (largest blend shape)
        mesh.bounds = new Bounds(new Vector3(5f, 5f, 0f), new Vector3(10f, 10f, 1f));
        mesh.SetIndices(new int[]
        {
            0, 1,
            2, 3,
        },
                        // From Unity docs ( https://docs.unity3d.com/ScriptReference/MeshTopology.LineStrip.html etc.) :
                        // - Lines: Each two indices in the mesh index buffer form a line.
                        // - LineStrip:  First two indices form a line, and then each new index connects a new vertex to the existing line strip.
                        // - Points: In most of use cases, mesh index buffer should be "identity": 0, 1, 2, 3, 4, 5, ...
                        MeshTopology.Lines,
                        // submesh
                        0);

        // save Mesh to file
        AssetDatabase.DeleteAsset("Assets/test_lines.mesh");
        AssetDatabase.CreateAsset(mesh, "Assets/test_lines.mesh");

        GameObject go         = new GameObject("Test Mesh SetTopology");
        MeshFilter meshFilter = go.AddComponent <MeshFilter>();

        meshFilter.mesh = mesh;
        SkinnedMeshRenderer meshRenderer = go.AddComponent <SkinnedMeshRenderer>();

        meshRenderer.sharedMesh = mesh; // SkinnedMeshRenderer also needs to know the mesh
        //meshRenderer.sharedMaterial = ... we could assign here material
        go.AddComponent <BlendShapeAnimation>();

        // save GameObject to file
        AssetDatabase.DeleteAsset("Assets/test_lines_game_object.prefab");
        PrefabUtility.SaveAsPrefabAsset(go, "Assets/test_lines_game_object.prefab");
    }
        public void Setup()
        {
            #region Mesh Generation
            mesh.Clear();

            #region Vertices
            List <Vector3>    vertices    = new List <Vector3>();
            List <BoneWeight> boneWeights = new List <BoneWeight>();

            // Top Hemisphere.
            vertices.Add(new Vector3(0, 0, 0));
            boneWeights.Add(new BoneWeight()
            {
                boneIndex0 = 0, weight0 = 1
            });
            for (int ringIndex = 1; ringIndex < settings.Segments / 2; ringIndex++)
            {
                float percent      = (float)ringIndex / (settings.Segments / 2);
                float ringRadius   = settings.Radius * Mathf.Sin(90f * percent * Mathf.Deg2Rad);
                float ringDistance = settings.Radius * (-Mathf.Cos(90f * percent * Mathf.Deg2Rad) + 1f);

                for (int i = 0; i < settings.Segments; i++)
                {
                    float angle = i * 360f / settings.Segments;

                    float x = ringRadius * Mathf.Cos(angle * Mathf.Deg2Rad);
                    float y = ringRadius * Mathf.Sin(angle * Mathf.Deg2Rad);
                    float z = ringDistance;

                    vertices.Add(new Vector3(x, y, z));
                    boneWeights.Add(new BoneWeight()
                    {
                        boneIndex0 = 0, weight0 = 1f
                    });
                }
            }

            // Middle Cylinder.
            for (int ringIndex = 0; ringIndex < settings.Rings * data.bones.Count; ringIndex++)
            {
                float boneIndexFloat = (float)ringIndex / settings.Rings;
                int   boneIndex      = Mathf.FloorToInt(boneIndexFloat);

                float bonePercent = boneIndexFloat - boneIndex;

                int boneIndex0 = (boneIndex > 0) ? boneIndex - 1 : 0;
                int boneIndex2 = (boneIndex < data.bones.Count - 1) ? boneIndex + 1 : data.bones.Count - 1;
                int boneIndex1 = boneIndex;

                float weight0 = (boneIndex > 0) ? (1f - bonePercent) * 0.5f : 0f;
                float weight2 = (boneIndex < data.bones.Count - 1) ? bonePercent * 0.5f : 0f;
                float weight1 = 1f - (weight0 + weight2);

                for (int i = 0; i < settings.Segments; i++)
                {
                    float angle = i * 360f / settings.Segments;

                    float x = settings.Radius * Mathf.Cos(angle * Mathf.Deg2Rad);
                    float y = settings.Radius * Mathf.Sin(angle * Mathf.Deg2Rad);
                    float z = ringIndex * settings.Length / settings.Rings;

                    vertices.Add(new Vector3(x, y, settings.Radius + z));
                    boneWeights.Add(new BoneWeight()
                    {
                        boneIndex0 = boneIndex0,
                        boneIndex1 = boneIndex1,
                        boneIndex2 = boneIndex2,
                        weight0    = weight0,
                        weight1    = weight1,
                        weight2    = weight2
                    });
                }
            }

            // Bottom Hemisphere.
            for (int ringIndex = 0; ringIndex < settings.Segments / 2; ringIndex++)
            {
                float percent      = (float)ringIndex / (settings.Segments / 2);
                float ringRadius   = settings.Radius * Mathf.Cos(90f * percent * Mathf.Deg2Rad);
                float ringDistance = settings.Radius * Mathf.Sin(90f * percent * Mathf.Deg2Rad);

                for (int i = 0; i < settings.Segments; i++)
                {
                    float angle = i * 360f / settings.Segments;

                    float x = ringRadius * Mathf.Cos(angle * Mathf.Deg2Rad);
                    float y = ringRadius * Mathf.Sin(angle * Mathf.Deg2Rad);
                    float z = ringDistance;

                    vertices.Add(new Vector3(x, y, settings.Radius + (settings.Length * data.bones.Count) + z));
                    boneWeights.Add(new BoneWeight()
                    {
                        boneIndex0 = data.bones.Count - 1, weight0 = 1
                    });
                }
            }
            vertices.Add(new Vector3(0, 0, 2f * settings.Radius + (settings.Length * data.bones.Count)));
            boneWeights.Add(new BoneWeight()
            {
                boneIndex0 = data.bones.Count - 1, weight0 = 1
            });

            mesh.vertices    = vertices.ToArray();
            mesh.boneWeights = boneWeights.ToArray();
            #endregion

            #region Triangles
            List <int> triangles = new List <int>();

            // Top Cap.
            for (int i = 0; i < settings.Segments; i++)
            {
                int seamOffset = i != settings.Segments - 1 ? 0 : settings.Segments;

                triangles.Add(0);
                triangles.Add(i + 2 - seamOffset);
                triangles.Add(i + 1);
            }

            // Main.
            int rings = (settings.Rings * data.bones.Count) + (2 * (settings.Segments / 2 - 1));
            for (int ringIndex = 0; ringIndex < rings; ringIndex++)
            {
                int ringOffset = 1 + ringIndex * settings.Segments;

                for (int i = 0; i < settings.Segments; i++)
                {
                    int seamOffset = i != settings.Segments - 1 ? 0 : settings.Segments;

                    triangles.Add(ringOffset + i);
                    triangles.Add(ringOffset + i + 1 - seamOffset);
                    triangles.Add(ringOffset + i + 1 - seamOffset + settings.Segments);

                    triangles.Add(ringOffset + i + 1 - seamOffset + settings.Segments);
                    triangles.Add(ringOffset + i + settings.Segments);
                    triangles.Add(ringOffset + i);
                }
            }

            // Bottom Cap.
            int topIndex = 1 + (rings + 1) * settings.Segments;
            for (int i = 0; i < settings.Segments; i++)
            {
                int seamOffset = i != settings.Segments - 1 ? 0 : settings.Segments;

                triangles.Add(topIndex);
                triangles.Add(topIndex - i - 2 + seamOffset);
                triangles.Add(topIndex - i - 1);
            }

            mesh.triangles = triangles.ToArray();
            #endregion

            #region UV
            List <Vector2> uv = new List <Vector2>();

            uv.Add(Vector2.zero);
            for (int ringIndex = 0; ringIndex < rings + 1; ringIndex++)
            {
                float v = ringIndex / (float)rings;
                for (int i = 0; i < settings.Segments; i++)
                {
                    float u = i / (float)(settings.Segments - 1);
                    uv.Add(new Vector2(u, v * (data.bones.Count + 1)));
                }
            }
            uv.Add(Vector2.one);

            mesh.uv8 = uv.ToArray(); // Store copy of UVs in mesh.
            #endregion

            #region Bones
            Transform[] boneTransforms = new Transform[data.bones.Count];
            Matrix4x4[] bindPoses      = new Matrix4x4[data.bones.Count];
            Vector3[]   deltaZeroArray = new Vector3[vertices.Count];
            for (int vertIndex = 0; vertIndex < vertices.Count; vertIndex++)
            {
                deltaZeroArray[vertIndex] = Vector3.zero;
            }

            for (int boneIndex = 0; boneIndex < data.bones.Count; boneIndex++)
            {
                boneTransforms[boneIndex] = root.GetChild(boneIndex);

                #region Bind Pose
                boneTransforms[boneIndex].localPosition = Vector3.forward * (settings.Radius + settings.Length * (0.5f + boneIndex));
                boneTransforms[boneIndex].localRotation = Quaternion.identity;
                bindPoses[boneIndex] = boneTransforms[boneIndex].worldToLocalMatrix * transform.localToWorldMatrix;
                #endregion

                #region Hinge Joint
                if (boneIndex > 0)
                {
                    HingeJoint hingeJoint = boneTransforms[boneIndex].GetComponent <HingeJoint>();
                    hingeJoint.anchor        = new Vector3(0, 0, -settings.Length / 2f);
                    hingeJoint.connectedBody = boneTransforms[boneIndex - 1].GetComponent <Rigidbody>();
                }
                #endregion

                #region Blend Shapes
                Vector3[] deltaVertices = new Vector3[vertices.Count];
                for (int vertIndex = 0; vertIndex < vertices.Count; vertIndex++)
                {
                    // Round
                    //float distanceToBone = Mathf.Clamp(Vector3.Distance(vertices[vertIndex], boneTransforms[boneIndex].localPosition), 0, 2f * settings.Length);
                    //Vector3 directionToBone = (vertices[vertIndex] - boneTransforms[boneIndex].localPosition).normalized;

                    //deltaVertices[vertIndex] = directionToBone * (2f * settings.Length - distanceToBone);


                    // Smooth - https://www.desmos.com/calculator/wmpvvtmor8
                    float maxDistanceAlongBone = settings.Length * 2f;
                    float maxHeightAboveBone   = settings.Radius * 2f;

                    float displacementAlongBone = vertices[vertIndex].z - boneTransforms[boneIndex].localPosition.z;

                    float x = Mathf.Clamp(displacementAlongBone / maxDistanceAlongBone, -1, 1);
                    float a = maxHeightAboveBone;
                    float b = 1f / a;

                    float heightAboveBone = (Mathf.Cos(x * Mathf.PI) / b + a) / 2f;

                    deltaVertices[vertIndex] = new Vector2(vertices[vertIndex].x, vertices[vertIndex].y).normalized *heightAboveBone;
                }
                mesh.AddBlendShapeFrame("Bone." + boneIndex, 0, deltaZeroArray, deltaZeroArray, deltaZeroArray);
                mesh.AddBlendShapeFrame("Bone." + boneIndex, 100, deltaVertices, deltaZeroArray, deltaZeroArray);

                Scroll scroll = boneTransforms[boneIndex].GetComponent <Scroll>();
                int    index  = boneIndex;
                scroll.OnScrollUp.RemoveAllListeners();
                scroll.OnScrollDown.RemoveAllListeners();
                scroll.OnScrollUp.AddListener(delegate
                {
                    audioSource.PlayOneShot(sizeAudioClip);

                    AddWeight(index, 5f);
                });
                scroll.OnScrollDown.AddListener(delegate
                {
                    audioSource.PlayOneShot(sizeAudioClip);

                    RemoveWeight(index, 5f);
                });
                #endregion
            }

            mesh.bindposes            = bindPoses;
            skinnedMeshRenderer.bones = boneTransforms;
            #endregion

            mesh.RecalculateNormals();
            #endregion

            #region Mesh Deformation
            for (int boneIndex = 0; boneIndex < data.bones.Count; boneIndex++)
            {
                boneTransforms[boneIndex].position = data.bones[boneIndex].Position;
                boneTransforms[boneIndex].rotation = data.bones[boneIndex].Rotation;
                SetWeight(boneIndex, data.bones[boneIndex].Size);
            }

            UpdateMeshCollider();
            #endregion
        }
        /// <summary>
        /// <see cref="BlendShapePreset.Neutral"/>、および<see cref="BlendShapePreset.Blink"/>を変換します。
        /// </summary>
        /// <remarks>
        /// 参照:
        /// 最新版(10/02時点)自動まばたきの実装【VRChat技術情報】 — VRChatパブリックログ
        /// <https://jellyfish-qrage.hatenablog.com/entry/2018/10/02/152316>
        /// VRchatでMMDモデルをアバターとして使う方法——上級者編 — 東屋書店
        /// <http://www.hushimero.xyz/entry/vrchat-EyeTracking#%E5%A4%A7%E5%8F%A3%E9%96%8B%E3%81%91%E3%82%8B%E5%95%8F%E9%A1%8C%E3%81%AE%E8%A7%A3%E6%B1%BA>
        /// 技術勢の元怒さんのツイート: “自動まばたきはまばたきシェイプキーを、まばたき防止のほうは自動まばたきのエナブルONOFFを操作してますね。 欲しければサンプル渡せますよ。… ”
        /// <https://twitter.com/gend_VRchat/status/1100155987216879621>
        /// momoma/ナル@VRChatter/VTuberさんのツイート: “3F目にBehavior 1のキーを追加したら重複しなくなったわ、なるほどな… ”
        /// <https://twitter.com/momoma_creative/status/1137917887262339073>
        /// </remarks>
        /// <param name="avatar"></param>
        /// <param name="clips"></param>
        /// <paramref name="useShapeKeyNormalsAndTangents"/>
        private static void SetNeutralAndBlink(
            GameObject avatar,
            IEnumerable <VRMBlendShapeClip> clips,
            bool useShapeKeyNormalsAndTangents
            )
        {
            AnimatorController neutralAndBlinkController
                = BlendShapeReplacer.CreateSingleAnimatorController(avatar: avatar, name: "blink");
            AnimationClip animationClip = neutralAndBlinkController.animationClips[0];

            VRMBlendShapeClip blinkClip = null;

            foreach (var preset in new[] { BlendShapePreset.Blink, BlendShapePreset.Neutral })
            {
                VRMBlendShapeClip clip = clips.FirstOrDefault(c => c.Preset == preset);
                if (!clip)
                {
                    continue;
                }

                if (preset == BlendShapePreset.Blink)
                {
                    blinkClip = clip;
                }

                foreach (var(shapeKeyName, shapeKeyWeight) in clip.ShapeKeyValues)
                {
                    var keys = BlendShapeReplacer.BlinkWeights;
                    if (preset == BlendShapePreset.Neutral)
                    {
                        if (blinkClip && blinkClip.ShapeKeyValues.ContainsKey(shapeKeyName))
                        {
                            // NEUTRALとBlinkが同一のシェイプキーを参照していた場合
                            float blinkShapeKeyWeight = blinkClip.ShapeKeyValues[shapeKeyName];
                            var   animationCurve      = new AnimationCurve();
                            foreach (var(seconds, blendShapePreset) in BlendShapeReplacer.NeutralAndBlinkWeights)
                            {
                                float weight;
                                switch (blendShapePreset)
                                {
                                case BlendShapePreset.Neutral:
                                    weight = shapeKeyWeight;
                                    break;

                                case BlendShapePreset.Blink:
                                    weight = blinkShapeKeyWeight;
                                    break;

                                default:
                                    weight = 0;
                                    break;
                                }
                                animationCurve.AddKey(new Keyframe(seconds, weight));
                            }

                            animationClip.SetCurve(
                                "",
                                typeof(SkinnedMeshRenderer),
                                "blendShape." + shapeKeyName,
                                animationCurve
                                );
                            continue;
                        }

                        keys = BlendShapeReplacer.NeutralWeights;
                    }

                    SetBlendShapeCurve(animationClip, shapeKeyName, shapeKeyWeight, keys, setRelativePath: false);
                }

                foreach (MaterialValueBinding binding in clip.MaterialValues)
                {
                    // TODO
                }
            }

            Transform transform = avatar.transform.Find(VRChatUtility.AutoBlinkMeshPath);

            transform.gameObject.AddComponent <Animator>().runtimeAnimatorController = neutralAndBlinkController;

            // VRChat側の自動まばたきを回避
            Mesh mesh = transform.GetSharedMesh();
            IEnumerable <BlendShape> shapeKeys = BlendShapeReplacer.GetAllShapeKeys(mesh, useShapeKeyNormalsAndTangents);

            mesh.ClearBlendShapes();
            foreach (string name in BlendShapeReplacer.OrderedBlinkGeneratedByCatsBlenderPlugin)
            {
                BlendShapeReplacer.AddDummyShapeKey(mesh: mesh, name: name);
            }
            foreach (BlendShape shapeKey in shapeKeys)
            {
                if (BlendShapeReplacer.OrderedBlinkGeneratedByCatsBlenderPlugin.Contains(shapeKey.Name))
                {
                    continue;
                }

                mesh.AddBlendShapeFrame(
                    shapeKey.Name,
                    BlendShapeReplacer.MaxBlendShapeFrameWeight,
                    shapeKey.Positions.ToArray(),
                    shapeKey.Normals.ToArray(),
                    shapeKey.Tangents.ToArray()
                    );
            }
            EditorUtility.SetDirty(mesh);
        }
        /// <summary>
        /// Animatorコンポーネントを使用せずに、<see cref="BlendShapePreset.Neutral"/>、および<see cref="BlendShapePreset.Blink"/>を変換します。
        /// </summary>
        /// <remarks>
        /// <see cref="BlendShapePreset.Blink"/>が関連付けられたメッシュが見つからない、またはそのメッシュに
        /// <see cref="BlendShapeReplacer.OrderedBlinkGeneratedByCatsBlenderPlugin"/>がそろっていれば何もしません。
        /// それらのキーが存在せず、<see cref="BlendShapePreset.Blink_L"/>、<see cref="BlendShapePreset.Blink_R"/>がいずれも設定されていればそれを優先します。
        /// </remarks>
        /// <param name="avatar"></param>
        /// <param name="clips"></param>
        /// <param name="useShapeKeyNormalsAndTangents"></param>
        private static void SetBlinkWithoutAnimator(
            GameObject avatar,
            IEnumerable <VRMBlendShapeClip> clips,
            bool useShapeKeyNormalsAndTangents
            )
        {
            var  renderer = avatar.transform.Find(VRChatUtility.AutoBlinkMeshPath).GetComponent <SkinnedMeshRenderer>();
            Mesh mesh     = renderer.sharedMesh;

            if (BlendShapeReplacer.GetBlendShapeNames(mesh: mesh)
                .Take(BlendShapeReplacer.OrderedBlinkGeneratedByCatsBlenderPlugin.Count())
                .SequenceEqual(BlendShapeReplacer.OrderedBlinkGeneratedByCatsBlenderPlugin))
            {
                return;
            }

            IEnumerable <BlendShape> shapeKeys = BlendShapeReplacer.GetAllShapeKeys(mesh, useShapeKeyNormalsAndTangents);

            mesh.ClearBlendShapes();

            var dummyShapeKeyNames = new List <string>();

            if (clips.FirstOrDefault(c => c.Preset == BlendShapePreset.Blink_L) &&
                clips.FirstOrDefault(c => c.Preset == BlendShapePreset.Blink_R))
            {
                mesh.AddBlendShapeFrame(
                    BlendShapeReplacer.OrderedBlinkGeneratedByCatsBlenderPlugin.ElementAt(0),
                    BlendShapeReplacer.MaxBlendShapeFrameWeight,
                    BlendShapeReplacer.GenerateShapeKey(
                        namesAndWeights: clips.First(c => c.Preset == BlendShapePreset.Blink_L).ShapeKeyValues,
                        shapeKeys: shapeKeys
                        ),
                    null,
                    null
                    );
                mesh.AddBlendShapeFrame(
                    BlendShapeReplacer.OrderedBlinkGeneratedByCatsBlenderPlugin.ElementAt(1),
                    BlendShapeReplacer.MaxBlendShapeFrameWeight,
                    BlendShapeReplacer.GenerateShapeKey(
                        namesAndWeights: clips.First(c => c.Preset == BlendShapePreset.Blink_R).ShapeKeyValues,
                        shapeKeys: shapeKeys
                        ),
                    null,
                    null
                    );
            }
            else
            {
                mesh.AddBlendShapeFrame(
                    BlendShapeReplacer.OrderedBlinkGeneratedByCatsBlenderPlugin.ElementAt(0),
                    BlendShapeReplacer.MaxBlendShapeFrameWeight,
                    BlendShapeReplacer.GenerateShapeKey(
                        namesAndWeights: clips.First(c => c.Preset == BlendShapePreset.Blink).ShapeKeyValues,
                        shapeKeys: shapeKeys
                        ),
                    null,
                    null
                    );
                dummyShapeKeyNames.Add(BlendShapeReplacer.OrderedBlinkGeneratedByCatsBlenderPlugin.ElementAt(1));
            }
            dummyShapeKeyNames.AddRange(BlendShapeReplacer.OrderedBlinkGeneratedByCatsBlenderPlugin.Skip(2));
            foreach (string name in dummyShapeKeyNames)
            {
                BlendShapeReplacer.AddDummyShapeKey(mesh: mesh, name: name);
            }

            foreach (BlendShape shapeKey in shapeKeys)
            {
                if (BlendShapeReplacer.OrderedBlinkGeneratedByCatsBlenderPlugin.Contains(shapeKey.Name))
                {
                    continue;
                }

                mesh.AddBlendShapeFrame(
                    shapeKey.Name,
                    BlendShapeReplacer.MaxBlendShapeFrameWeight,
                    shapeKey.Positions.ToArray(),
                    shapeKey.Normals.ToArray(),
                    shapeKey.Tangents.ToArray()
                    );
            }

            EditorUtility.SetDirty(mesh);
        }
        /// <summary>
        /// リップシンクの設定を行います。
        /// </summary>
        /// <remarks>
        /// <see cref="BlendShapePreset.A"/>、<see cref="BlendShapePreset.I"/>、<see cref="BlendShapePreset.O"/>が
        /// 単一のフレームを持つシェイプキーが存在しない場合、設定を行いません。
        /// 生成するシェイプキー名と同じシェイプキーが存在する場合、それを利用します。
        /// </remarks>
        /// <param name="avatar"></param>
        /// <param name="clips"></param>
        /// <param name="useShapeKeyNormalsAndTangents"></param>
        private static void SetLipSync(
            GameObject avatar,
            IEnumerable <VRMBlendShapeClip> clips,
            bool useShapeKeyNormalsAndTangents
            )
        {
            Transform transform = avatar.transform.Find(VRChatUtility.AutoBlinkMeshPath);
            var       renderer  = transform.GetComponent <SkinnedMeshRenderer>();
            Mesh      mesh      = renderer.sharedMesh;

            foreach (var preset in new[] { BlendShapePreset.A, BlendShapePreset.I, BlendShapePreset.O })
            {
                if (!clips.FirstOrDefault(c => c.Preset == preset))
                {
                    return;
                }
            }

            IEnumerable <BlendShape> shapeKeys = BlendShapeReplacer.GetAllShapeKeys(mesh, useShapeKeyNormalsAndTangents);

            foreach (var(newName, values) in BlendShapeReplacer.VisemeShapeKeyNamesAndValues)
            {
                if (mesh.GetBlendShapeIndex(newName) != -1)
                {
                    continue;
                }

                Vector3[] deltaVertices = null;
                foreach (Vector3[] vertices in values.SelectMany(presetAndWeight =>
                                                                 clips.First(clip => clip.Preset == presetAndWeight.Key).ShapeKeyValues.Select(
                                                                     shapeKeyNameAndWeight => shapeKeys
                                                                     .First(shapeKey => shapeKey.Name == shapeKeyNameAndWeight.Key)
                                                                     .Positions
                                                                     .Select(vertix => vertix * (shapeKeyNameAndWeight.Value / VRMUtility.MaxBlendShapeBindingWeight * presetAndWeight.Value))
                                                                     .ToArray()
                                                                     )
                                                                 ))
                {
                    if (deltaVertices == null)
                    {
                        deltaVertices = vertices;
                        continue;
                    }

                    for (var i = 0; i < deltaVertices.Length; i++)
                    {
                        deltaVertices[i] += vertices[i];
                    }
                }

                mesh.AddBlendShapeFrame(
                    newName,
                    BlendShapeReplacer.MaxBlendShapeFrameWeight,
                    deltaVertices,
                    null,
                    null
                    );
            }
            EditorUtility.SetDirty(mesh);

#if VRC_SDK_VRCSDK2 || VRC_SDK_VRCSDK3
            var avatarDescriptor = avatar.GetComponent <VRC_AvatarDescriptor>();
            avatarDescriptor.lipSync           = VRC_AvatarDescriptor.LipSyncStyle.VisemeBlendShape;
            avatarDescriptor.VisemeSkinnedMesh = renderer;
            avatarDescriptor.VisemeBlendShapes
                = BlendShapeReplacer.VisemeShapeKeyNamesAndValues.Select(nameAndValues => nameAndValues.Key).ToArray();
#endif
        }
Пример #13
0
        /// <summary>
        /// Read blendshapes from the avatar directory and add them to 3D head mesh.
        /// </summary>
        private static IEnumerator AddBlendshapes(string avatarId, Mesh mesh, int[] indexMap, AsyncRequest <Mesh> request)
        {
            var blendshapesDirs = AvatarSdkMgr.Storage().GetAvatarBlendshapesDirs(avatarId);

            var loadBlendshapesRequest = new AsyncRequestThreaded <Dictionary <string, Vector3[]> > ((r) => {
                var timer       = new MeasureTime("Read all blendshapes");
                var blendshapes = new Dictionary <string, Vector3[]> ();
                List <string> blendshapeFiles = new List <string>();
                foreach (string dir in blendshapesDirs)
                {
                    blendshapeFiles.AddRange(Directory.GetFiles(dir));
                }
                var blendshapeReader = new BlendshapeReader(indexMap);

                for (int i = 0; i < blendshapeFiles.Count; ++i)
                {
                    var blendshapePath = blendshapeFiles [i];
                    var filename       = Path.GetFileName(blendshapePath);

                    // crude parsing of filenames
                    if (!filename.EndsWith(".bin"))
                    {
                        continue;
                    }
                    var tokens = filename.Split(new [] { ".bin" }, StringSplitOptions.None);
                    if (tokens.Length != 2)
                    {
                        continue;
                    }

                    var blendshapeName           = tokens [0];
                    blendshapes [blendshapeName] = blendshapeReader.ReadVerticesDeltas(blendshapePath);
                    r.Progress = (float)i / blendshapeFiles.Count;
                }

                timer.Stop();
                return(blendshapes);
            }, AvatarSdkMgr.Str(Strings.ParsingBlendshapes));

            yield return(request.AwaitSubrequest(loadBlendshapesRequest, finalProgress: 0.9f));

            if (request.IsError)
            {
                yield break;
            }

            var   addBlendshapesTimer = DateTime.Now;
            float targetFps           = 30.0f;

            int numBlendshapes = 0, loadedSinceLastPause = 0;
            var blendshapesDict = loadBlendshapesRequest.Result;

            foreach (var blendshape in blendshapesDict)
            {
                mesh.AddBlendShapeFrame(blendshape.Key, 100.0f, blendshape.Value, null, null);
                ++numBlendshapes;
                ++loadedSinceLastPause;

                if ((DateTime.Now - addBlendshapesTimer).TotalMilliseconds > 1000.0f / targetFps && loadedSinceLastPause >= 5)
                {
                    // Debug.LogFormat ("Pause after {0} blendshapes to avoid blocking the main thread", numBlendshapes);
                    yield return(null);

                    addBlendshapesTimer  = DateTime.Now;
                    loadedSinceLastPause = 0;
                }
            }

            request.Result = mesh;
            request.IsDone = true;
        }
Пример #14
0
        // Copies the source mesh from the object and reverses the order of triangles.
        // (this is for hair meshes that look too 'inside out')
        public static void ReverseTriangleOrder(Object obj)
        {
            if (!obj)
            {
                return;
            }

            GameObject sceneRoot = PrefabUtility.GetOutermostPrefabInstanceRoot(obj);
            GameObject asset     = PrefabUtility.GetCorrespondingObjectFromSource(sceneRoot);
            Object     srcObj    = PrefabUtility.GetCorrespondingObjectFromSource(obj);
            Mesh       srcMesh   = GetMeshFromSelected(srcObj);
            string     path      = AssetDatabase.GetAssetPath(asset);

            if (string.IsNullOrEmpty(path))
            {
                Debug.LogWarning("Object: " + obj.name + " has no source Prefab Asset.");
                path = Path.Combine("Assets", "dummy.prefab");
            }

            if (!srcMesh)
            {
                Debug.LogError("No mesh found in selected object.");
                return;
            }

            string folder     = Path.GetDirectoryName(path);
            string meshFolder = Path.Combine(folder, INVERTED_FOLDER_NAME);

            Mesh dstMesh = new Mesh();

            dstMesh.vertices    = srcMesh.vertices;
            dstMesh.uv          = srcMesh.uv;
            dstMesh.uv2         = srcMesh.uv2;
            dstMesh.normals     = srcMesh.normals;
            dstMesh.colors      = srcMesh.colors;
            dstMesh.boneWeights = srcMesh.boneWeights;
            dstMesh.bindposes   = srcMesh.bindposes;
            dstMesh.bounds      = srcMesh.bounds;
            dstMesh.tangents    = srcMesh.tangents;

            int[] reversed = new int[srcMesh.triangles.Length];
            int[] forward  = srcMesh.triangles;

            // first pass: reverse the triangle order for each submesh
            for (int s = 0; s < srcMesh.subMeshCount; s++)
            {
                SubMeshDescriptor submesh = srcMesh.GetSubMesh(s);
                int start = submesh.indexStart;
                int end   = start + submesh.indexCount;
                int j     = end - 3;
                for (int i = start; i < end; i += 3)
                {
                    reversed[j]     = forward[i];
                    reversed[j + 1] = forward[i + 1];
                    reversed[j + 2] = forward[i + 2];
                    j -= 3;
                }
            }

            dstMesh.triangles    = reversed;
            dstMesh.subMeshCount = srcMesh.subMeshCount;

            // second pass: copy sub-mesh data (vertex and triangle data must be present for this)
            for (int s = 0; s < srcMesh.subMeshCount; s++)
            {
                SubMeshDescriptor submesh = srcMesh.GetSubMesh(s);
                dstMesh.SetSubMesh(s, submesh);
            }

            // copy any blendshapes across
            if (srcMesh.blendShapeCount > 0)
            {
                Vector3[] deltaVertices = new Vector3[srcMesh.vertexCount];
                Vector3[] deltaNormals  = new Vector3[srcMesh.vertexCount];
                Vector3[] deltaTangents = new Vector3[srcMesh.vertexCount];

                for (int i = 0; i < srcMesh.blendShapeCount; i++)
                {
                    string name = srcMesh.GetBlendShapeName(i);

                    int frameCount = srcMesh.GetBlendShapeFrameCount(i);
                    for (int f = 0; f < frameCount; f++)
                    {
                        float frameWeight = srcMesh.GetBlendShapeFrameWeight(i, f);
                        srcMesh.GetBlendShapeFrameVertices(i, f, deltaVertices, deltaNormals, deltaTangents);
                        dstMesh.AddBlendShapeFrame(name, frameWeight, deltaVertices, deltaNormals, deltaTangents);
                    }
                }
            }

            // Save the mesh asset.
            if (!AssetDatabase.IsValidFolder(meshFolder))
            {
                AssetDatabase.CreateFolder(folder, INVERTED_FOLDER_NAME);
            }
            string meshPath = Path.Combine(meshFolder, srcObj.name + ".mesh");

            AssetDatabase.CreateAsset(dstMesh, meshPath);

            if (obj.GetType() == typeof(GameObject))
            {
                GameObject go = (GameObject)obj;
                if (go)
                {
                    Mesh createdMesh = AssetDatabase.LoadAssetAtPath <Mesh>(meshPath);

                    if (!ReplaceMesh(obj, createdMesh))
                    {
                        Debug.LogError("Unable to set mesh in selected object!");
                    }
                }
            }
        }
Пример #15
0
        public static void LoadMesh(this Mesh mesh, VrmLib.Mesh src, VrmLib.Skin skin = null)
        {
            mesh.vertices = src.VertexBuffer.Positions.GetSpan <Vector3>().ToArray();
            mesh.normals  = src.VertexBuffer.Normals?.GetSpan <Vector3>().ToArray();
            mesh.uv       = src.VertexBuffer.TexCoords?.GetSpan <Vector2>().ToArray();
            mesh.colors   = src.VertexBuffer.Colors?.GetSpan <Color>().ToArray();
            if (src.VertexBuffer.Weights != null && src.VertexBuffer.Joints != null)
            {
                var boneWeights = new BoneWeight[mesh.vertexCount];
                if (src.VertexBuffer.Weights.Count != mesh.vertexCount || src.VertexBuffer.Joints.Count != mesh.vertexCount)
                {
                    throw new ArgumentException();
                }
                var weights = src.VertexBuffer.Weights.GetSpan <Vector4>();
                var joints  = src.VertexBuffer.Joints.GetSpan <VrmLib.SkinJoints>();
                if (skin != null)
                {
                    mesh.bindposes = skin.InverseMatrices.GetSpan <Matrix4x4>().ToArray();
                }

                for (int i = 0; i < weights.Length; ++i)
                {
                    var w = weights[i];
                    boneWeights[i].weight0 = w.x;
                    boneWeights[i].weight1 = w.y;
                    boneWeights[i].weight2 = w.z;
                    boneWeights[i].weight3 = w.w;
                }
                for (int i = 0; i < joints.Length; ++i)
                {
                    var j = joints[i];
                    boneWeights[i].boneIndex0 = j.Joint0;
                    boneWeights[i].boneIndex1 = j.Joint1;
                    boneWeights[i].boneIndex2 = j.Joint2;
                    boneWeights[i].boneIndex3 = j.Joint3;
                }
                mesh.boneWeights = boneWeights;
            }

            mesh.subMeshCount = src.Submeshes.Count;
            var triangles = src.IndexBuffer.GetAsIntList();

            for (int i = 0; i < src.Submeshes.Count; ++i)
            {
                var submesh = src.Submeshes[i];
                mesh.SetTriangles(triangles.GetRange(submesh.Offset, submesh.DrawCount), i);
            }

            foreach (var morphTarget in src.MorphTargets)
            {
                var positions =
                    morphTarget.VertexBuffer.Positions != null
                    ? morphTarget.VertexBuffer.Positions.GetSpan <Vector3>().ToArray()
                    : new Vector3[mesh.vertexCount] // dummy
                ;

                mesh.AddBlendShapeFrame(morphTarget.Name, 100.0f, positions, null, null);
            }

            mesh.RecalculateBounds();
            mesh.RecalculateTangents();
        }
Пример #16
0
        public static MeshWithMaterials BuildMesh(ImporterContext ctx, MeshContext meshContext)
        {
            if (!meshContext.materialIndices.Any())
            {
                meshContext.materialIndices.Add(0);
            }

            //Debug.Log(prims.ToJson());
            var mesh = new Mesh();

            mesh.name = meshContext.name;

            if (meshContext.positions.Length > UInt16.MaxValue)
            {
#if UNITY_2017_3_OR_NEWER
                mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32;
#else
                Debug.LogWarningFormat("vertices {0} exceed 65535. not implemented. Unity2017.3 supports large mesh",
                                       meshContext.positions.Length);
#endif
            }

            mesh.vertices = meshContext.positions;
            if (meshContext.normals != null && meshContext.normals.Length > 0)
            {
                mesh.normals = meshContext.normals;
            }
            else
            {
                mesh.RecalculateNormals();
            }
            if (meshContext.tangents != null && meshContext.tangents.Length > 0)
            {
                mesh.tangents = meshContext.tangents;
            }
            else
            {
#if UNITY_5_6_OR_NEWER
                mesh.RecalculateTangents();
#endif
            }
            if (meshContext.uv != null && meshContext.uv.Length > 0)
            {
                mesh.uv = meshContext.uv;
            }
            if (meshContext.colors != null && meshContext.colors.Length > 0)
            {
                mesh.colors = meshContext.colors;
            }
            if (meshContext.boneWeights != null && meshContext.boneWeights.Count > 0)
            {
                mesh.boneWeights = meshContext.boneWeights.ToArray();
            }
            mesh.subMeshCount = meshContext.subMeshes.Count;
            for (int i = 0; i < meshContext.subMeshes.Count; ++i)
            {
                mesh.SetTriangles(meshContext.subMeshes[i], i);
            }
            var result = new MeshWithMaterials
            {
                Mesh      = mesh,
                Materials = meshContext.materialIndices.Select(x => ctx.Materials[x]).ToArray()
            };

            if (meshContext.blendShapes != null)
            {
                foreach (var blendShape in meshContext.blendShapes)
                {
                    if (blendShape.Positions.Count > 0)
                    {
                        if (blendShape.Positions.Count == mesh.vertexCount)
                        {
                            mesh.AddBlendShapeFrame(blendShape.Name, FRAME_WEIGHT,
                                                    blendShape.Positions.ToArray(),
                                                    (meshContext.normals != null && meshContext.normals.Length == mesh.vertexCount) ? blendShape.Normals.ToArray() : null,
                                                    null
                                                    );
                        }
                        else
                        {
                            Debug.LogWarningFormat("May be partial primitive has blendShape. Rquire separete mesh or extend blend shape, but not implemented: {0}", blendShape.Name);
                        }
                    }
                }
            }

            return(result);
        }
Пример #17
0
        public static GameObject Execute(GameObject go, Dictionary <Transform, Transform> boneMap, bool forceTPose)
        {
            //
            // T-Poseにする
            //
            if (forceTPose)
            {
                var animator = go.GetComponent <Animator>();
                if (animator == null)
                {
                    throw new ArgumentException("Animator with avatar is required");
                }

                var avatar = animator.avatar;
                if (avatar == null)
                {
                    throw new ArgumentException("avatar is required");
                }

                if (!avatar.isValid)
                {
                    throw new ArgumentException("invalid avatar");
                }

                if (!avatar.isHuman)
                {
                    throw new ArgumentException("avatar is not human");
                }

                HumanPoseTransfer.SetTPose(avatar, go.transform);
            }

            //
            // 回転・スケールの無いヒエラルキーをコピーする
            //
            var normalized = new GameObject(go.name + "(normalized)");

            normalized.transform.position = go.transform.position;

            CopyAndBuild(go.transform, normalized.transform, boneMap);

            //
            // 新しいヒエラルキーからAvatarを作る
            //
            {
                var src = go.GetComponent <Animator>();

                var map = Enum.GetValues(typeof(HumanBodyBones))
                          .Cast <HumanBodyBones>()
                          .Where(x => x != HumanBodyBones.LastBone)
                          .Select(x => new { Key = x, Value = src.GetBoneTransform(x) })
                          .Where(x => x.Value != null)
                          .ToDictionary(x => x.Key, x => boneMap[x.Value])
                ;

                var animator          = normalized.AddComponent <Animator>();
                var vrmHuman          = go.GetComponent <VRMHumanoidDescription>();
                var avatarDescription = AvatarDescription.Create();
                if (vrmHuman != null && vrmHuman.Description != null)
                {
                    avatarDescription.armStretch        = vrmHuman.Description.armStretch;
                    avatarDescription.legStretch        = vrmHuman.Description.legStretch;
                    avatarDescription.upperArmTwist     = vrmHuman.Description.upperArmTwist;
                    avatarDescription.lowerArmTwist     = vrmHuman.Description.lowerArmTwist;
                    avatarDescription.upperLegTwist     = vrmHuman.Description.upperLegTwist;
                    avatarDescription.lowerLegTwist     = vrmHuman.Description.lowerLegTwist;
                    avatarDescription.feetSpacing       = vrmHuman.Description.feetSpacing;
                    avatarDescription.hasTranslationDoF = vrmHuman.Description.hasTranslationDoF;
                }
                avatarDescription.SetHumanBones(map);
                var avatar = avatarDescription.CreateAvatar(normalized.transform);

                avatar.name     = go.name + ".normalized";
                animator.avatar = avatar;

                var humanPoseTransfer = normalized.AddComponent <HumanPoseTransfer>();
                humanPoseTransfer.Avatar = avatar;
            }

            //
            // 各メッシュから回転・スケールを取り除いてBinding行列を再計算する
            //
            foreach (var src in go.transform.Traverse())
            {
                Transform dst;
                if (!boneMap.TryGetValue(src, out dst))
                {
                    continue;
                }

                {
                    //
                    // SkinnedMesh
                    //
                    var srcRenderer = src.GetComponent <SkinnedMeshRenderer>();
                    if (srcRenderer != null && srcRenderer.enabled &&
                        srcRenderer.sharedMesh != null &&
                        srcRenderer.sharedMesh.vertexCount > 0)
                    {
                        // clear blendShape
                        var srcMesh = srcRenderer.sharedMesh;
                        for (int i = 0; i < srcMesh.blendShapeCount; ++i)
                        {
                            srcRenderer.SetBlendShapeWeight(i, 0);
                        }

                        var mesh = new Mesh();
                        mesh.name = srcMesh.name + ".baked";
#if UNITY_2017_3_OR_NEWER
                        mesh.indexFormat = srcMesh.indexFormat;
#endif

                        srcRenderer.BakeMesh(mesh);

                        //var m = src.localToWorldMatrix;
                        var m = default(Matrix4x4);
                        m.SetTRS(Vector3.zero, src.rotation, Vector3.one);

                        mesh.vertices = mesh.vertices.Select(x => m.MultiplyPoint(x)).ToArray();
                        mesh.normals  = mesh.normals.Select(x => m.MultiplyVector(x).normalized).ToArray();

                        mesh.uv           = srcMesh.uv;
                        mesh.tangents     = srcMesh.tangents;
                        mesh.subMeshCount = srcMesh.subMeshCount;
                        for (int i = 0; i < srcMesh.subMeshCount; ++i)
                        {
                            mesh.SetIndices(srcMesh.GetIndices(i), srcMesh.GetTopology(i), i);
                        }
                        mesh.boneWeights = srcMesh.boneWeights;

                        var meshVertices = mesh.vertices;
                        var meshNormals  = mesh.normals;
                        var meshTangents = mesh.tangents.Select(x => (Vector3)x).ToArray();

                        var _meshVertices = new Vector3[meshVertices.Length];
                        var _meshNormals  = new Vector3[meshVertices.Length];
                        var _meshTangents = new Vector3[meshVertices.Length];

                        var blendShapeMesh = new Mesh();
                        for (int i = 0; i < srcMesh.blendShapeCount; ++i)
                        {
                            // check blendShape
                            srcRenderer.sharedMesh.GetBlendShapeFrameVertices(i, 0, _meshVertices, _meshNormals, _meshTangents);
                            var hasVertices = !_meshVertices.All(x => x == Vector3.zero);
                            var hasNormals  = !_meshNormals.All(x => x == Vector3.zero);
                            var hasTangents = !_meshTangents.All(x => x == Vector3.zero);

                            srcRenderer.SetBlendShapeWeight(i, 100.0f);
                            srcRenderer.BakeMesh(blendShapeMesh);
                            if (blendShapeMesh.vertices.Length != mesh.vertices.Length)
                            {
                                throw new Exception("diffrent vertex count");
                            }
                            srcRenderer.SetBlendShapeWeight(i, 0);

                            Vector3[] vertices = null;
                            if (hasVertices)
                            {
                                vertices = blendShapeMesh.vertices;
                                // to delta
                                for (int j = 0; j < vertices.Length; ++j)
                                {
                                    vertices[j] = m.MultiplyPoint(vertices[j]) - meshVertices[j];
                                }
                            }
                            else
                            {
                                vertices = new Vector3[mesh.vertexCount];
                            }

                            Vector3[] normals = null;
                            if (hasNormals)
                            {
                                normals = blendShapeMesh.normals;
                                // to delta
                                for (int j = 0; j < normals.Length; ++j)
                                {
                                    normals[j] = m.MultiplyVector(normals[j]) - meshNormals[j];
                                }
                            }
                            else
                            {
                                normals = new Vector3[mesh.vertexCount];
                            }

                            Vector3[] tangents = null;
                            if (hasTangents)
                            {
                                tangents = blendShapeMesh.tangents.Select(x => (Vector3)x).ToArray();
                                // to delta
                                for (int j = 0; j < tangents.Length; ++j)
                                {
                                    tangents[j] = m.MultiplyVector(tangents[j]) - meshTangents[j];
                                }
                            }
                            else
                            {
                                tangents = new Vector3[mesh.vertexCount];
                            }

                            var name = srcMesh.GetBlendShapeName(i);
                            if (string.IsNullOrEmpty(name))
                            {
                                name = String.Format("{0}", i);
                            }

                            var weight = srcMesh.GetBlendShapeFrameWeight(i, 0);

                            try
                            {
                                mesh.AddBlendShapeFrame(name,
                                                        weight,
                                                        vertices,
                                                        normals,
                                                        tangents
                                                        );
                            }
                            catch (Exception)
                            {
                                Debug.LogErrorFormat("fail to mesh.AddBlendShapeFrame {0}.{1}",
                                                     mesh.name,
                                                     srcMesh.GetBlendShapeName(i)
                                                     );
                                throw;
                            }
                        }

                        // recalc bindposes
                        var bones = srcRenderer.bones.Select(x => boneMap[x]).ToArray();
                        mesh.bindposes = bones.Select(x =>
                                                      x.worldToLocalMatrix * dst.transform.localToWorldMatrix).ToArray();

                        mesh.RecalculateBounds();

                        var dstRenderer = dst.gameObject.AddComponent <SkinnedMeshRenderer>();
                        dstRenderer.sharedMaterials = srcRenderer.sharedMaterials;
                        dstRenderer.sharedMesh      = mesh;
                        dstRenderer.bones           = bones;
                        if (srcRenderer.rootBone != null)
                        {
                            dstRenderer.rootBone = boneMap[srcRenderer.rootBone];
                        }
                    }
                }

                {
                    //
                    // not SkinnedMesh
                    //
                    var srcFilter = src.GetComponent <MeshFilter>();
                    if (srcFilter != null &&
                        srcFilter.sharedMesh != null &&
                        srcFilter.sharedMesh.vertexCount > 0)
                    {
                        var srcRenderer = src.GetComponent <MeshRenderer>();
                        if (srcRenderer != null && srcRenderer.enabled)
                        {
                            var dstFilter = dst.gameObject.AddComponent <MeshFilter>();
                            dstFilter.sharedMesh = TransformMesh(srcFilter.sharedMesh, src.localToWorldMatrix);

                            var dstRenderer = dst.gameObject.AddComponent <MeshRenderer>();
                            dstRenderer.sharedMaterials = srcRenderer.sharedMaterials;
                        }
                    }
                }
            }

            return(normalized);
        }
Пример #18
0
        /// <summary>

        /// Combines an array of meshes into a single mesh.

        /// </summary>

        /// <param name="meshes">The array of meshes to combine.</param>

        /// <param name="transforms">The array of transforms for the meshes.</param>

        /// <param name="materials">The array of materials for each mesh to combine.</param>

        /// <param name="bones">The array of bones for each mesh to combine.</param>

        /// <param name="resultMaterials">The resulting materials for the combined mesh.</param>

        /// <param name="resultBones">The resulting bones for the combined mesh.</param>

        /// <returns>The combined mesh.</returns>

        public static Mesh CombineMeshes(Mesh[] meshes, Matrix4x4[] transforms, Tuple <Matrix4x4, bool>[] normalsTransforms, Material[][] materials, Transform[][] bones, out Material[] resultMaterials, out Transform[] resultBones, Dictionary <string, BlendShapeFrame> blendShapes = null)
        {
            if (meshes == null)
            {
                throw new System.ArgumentNullException(nameof(meshes));
            }

            else if (transforms == null)
            {
                throw new System.ArgumentNullException(nameof(transforms));
            }

            else if (materials == null)
            {
                throw new System.ArgumentNullException(nameof(materials));
            }

            else if (transforms.Length != meshes.Length)
            {
                throw new System.ArgumentException("The array of transforms doesn't have the same length as the array of meshes.", nameof(transforms));
            }

            else if (materials.Length != meshes.Length)
            {
                throw new System.ArgumentException("The array of materials doesn't have the same length as the array of meshes.", nameof(materials));
            }

            else if (bones != null && bones.Length != meshes.Length)
            {
                throw new System.ArgumentException("The array of bones doesn't have the same length as the array of meshes.", nameof(bones));
            }



            int totalVertexCount = 0;

            int totalSubMeshCount = 0;

            for (int meshIndex = 0; meshIndex < meshes.Length; meshIndex++)
            {
                var mesh = meshes[meshIndex];

                if (mesh == null)
                {
                    throw new System.ArgumentException(string.Format("The mesh at index {0} is null.", meshIndex), nameof(meshes));
                }

                else if (!mesh.isReadable)
                {
                    throw new System.ArgumentException(string.Format("The mesh at index {0} is not readable.", meshIndex), nameof(meshes));
                }



                totalVertexCount += mesh.vertexCount;

                totalSubMeshCount += mesh.subMeshCount;



                // Validate the mesh materials

                var meshMaterials = materials[meshIndex];

                if (meshMaterials == null)
                {
                    throw new System.ArgumentException(string.Format("The materials for mesh at index {0} is null.", meshIndex), nameof(materials));
                }

                else if (meshMaterials.Length != mesh.subMeshCount)
                {
                    throw new System.ArgumentException(string.Format("The materials for mesh at index {0} doesn't match the submesh count ({1} != {2}).", meshIndex, meshMaterials.Length, mesh.subMeshCount), nameof(materials));
                }



                for (int materialIndex = 0; materialIndex < meshMaterials.Length; materialIndex++)
                {
                    if (meshMaterials[materialIndex] == null)
                    {
                        throw new System.ArgumentException(string.Format("The material at index {0} for mesh at index {1} is null.", materialIndex, meshIndex), nameof(materials));
                    }
                }



                // Validate the mesh bones

                if (bones != null)
                {
                    var meshBones = bones[meshIndex];

                    if (meshBones == null)
                    {
                        throw new System.ArgumentException(string.Format("The bones for mesh at index {0} is null.", meshIndex), nameof(meshBones));
                    }



                    for (int boneIndex = 0; boneIndex < meshBones.Length; boneIndex++)

                    {
                        if (meshBones[boneIndex] == null)
                        {
                            throw new System.ArgumentException(string.Format("The bone at index {0} for mesh at index {1} is null.", boneIndex, meshIndex), nameof(meshBones));
                        }
                    }
                }
            }



            var combinedVertices = new List <Vector3>(totalVertexCount);

            var combinedIndices = new List <int[]>(totalSubMeshCount);

            List <Vector3> combinedNormals = null;

            List <Vector4> combinedTangents = null;

            List <Color> combinedColors = null;

            List <BoneWeight> combinedBoneWeights = null;

            var combinedUVs = new List <Vector4> [MeshUtils.UVChannelCount];



            List <Matrix4x4> usedBindposes = null;

            List <Transform> usedBones = null;

            var usedMaterials = new List <Material>(totalSubMeshCount);

            var materialMap = new Dictionary <Material, int>(totalSubMeshCount);



            int currentVertexCount = 0;

            for (int meshIndex = 0; meshIndex < meshes.Length; meshIndex++)
            {
                var mesh = meshes[meshIndex];

                var meshTransform = transforms[meshIndex];

                var normalsTransform = normalsTransforms[meshIndex];

                var meshMaterials = materials[meshIndex];

                var meshBones = (bones != null ? bones[meshIndex] : null);



                int subMeshCount = mesh.subMeshCount;

                int meshVertexCount = mesh.vertexCount;

                var meshVertices = mesh.vertices;

                var meshNormals = mesh.normals;

                var meshTangents = mesh.tangents;

                var meshUVs = MeshUtils.GetMeshUVs(mesh);

                var meshColors = mesh.colors;

                var meshBoneWeights = mesh.boneWeights;

                var meshBindposes = mesh.bindposes;



                // Transform vertices with bones to keep only one bindpose

                if (meshBones != null && meshBoneWeights != null && meshBoneWeights.Length > 0 && meshBindposes != null && meshBindposes.Length > 0 && meshBones.Length == meshBindposes.Length)
                {
                    if (usedBindposes == null)
                    {
                        usedBindposes = new List <Matrix4x4>(meshBindposes);

                        usedBones = new List <Transform>(meshBones);
                    }



                    int[] boneIndices = new int[meshBones.Length];

                    for (int i = 0; i < meshBones.Length; i++)
                    {
                        int usedBoneIndex = usedBones.IndexOf(meshBones[i]);

                        if (usedBoneIndex == -1 || meshBindposes[i] != usedBindposes[usedBoneIndex])

                        {
                            usedBoneIndex = usedBones.Count;

                            usedBones.Add(meshBones[i]);

                            usedBindposes.Add(meshBindposes[i]);
                        }

                        boneIndices[i] = usedBoneIndex;
                    }



                    // Then we remap the bones

                    RemapBones(meshBoneWeights, boneIndices);
                }



                // Transforms the vertices, normals and tangents using the mesh transform

                TransformVertices(meshVertices, ref meshTransform);

                TransformNormals(meshNormals, ref normalsTransform);

                TransformTangents(meshTangents, ref normalsTransform);


                // Copy vertex positions & attributes

                CopyVertexPositions(combinedVertices, meshVertices);

                CopyVertexAttributes(ref combinedNormals, meshNormals, currentVertexCount, meshVertexCount, totalVertexCount, new Vector3(1f, 0f, 0f));

                CopyVertexAttributes(ref combinedTangents, meshTangents, currentVertexCount, meshVertexCount, totalVertexCount, new Vector4(0f, 0f, 1f, 1f));

                CopyVertexAttributes(ref combinedColors, meshColors, currentVertexCount, meshVertexCount, totalVertexCount, new Color(1f, 1f, 1f, 1f));

                CopyVertexAttributes(ref combinedBoneWeights, meshBoneWeights, currentVertexCount, meshVertexCount, totalVertexCount, new BoneWeight());



                for (int channel = 0; channel < meshUVs.Length; channel++)

                {
                    CopyVertexAttributes(ref combinedUVs[channel], meshUVs[channel], currentVertexCount, meshVertexCount, totalVertexCount, new Vector4(0f, 0f, 0f, 0f));
                }



                for (int subMeshIndex = 0; subMeshIndex < subMeshCount; subMeshIndex++)

                {
                    var subMeshMaterial = meshMaterials[subMeshIndex];

#if UNITY_MESH_INDEXFORMAT_SUPPORT
                    var subMeshIndices = mesh.GetTriangles(subMeshIndex, true);
#else
                    var subMeshIndices = mesh.GetTriangles(subMeshIndex);
#endif



                    if (currentVertexCount > 0)

                    {
                        for (int index = 0; index < subMeshIndices.Length; index++)

                        {
                            subMeshIndices[index] += currentVertexCount;
                        }
                    }



                    int existingSubMeshIndex;

                    if (materialMap.TryGetValue(subMeshMaterial, out existingSubMeshIndex))

                    {
                        combinedIndices[existingSubMeshIndex] = MergeArrays(combinedIndices[existingSubMeshIndex], subMeshIndices);
                    }

                    else

                    {
                        int materialIndex = combinedIndices.Count;

                        materialMap.Add(subMeshMaterial, materialIndex);

                        usedMaterials.Add(subMeshMaterial);

                        combinedIndices.Add(subMeshIndices);
                    }
                }



                currentVertexCount += meshVertexCount;
            }



            var resultVertices = combinedVertices.ToArray();

            var resultIndices = combinedIndices.ToArray();

            var resultNormals = (combinedNormals != null ? combinedNormals.ToArray() : null);

            var resultTangents = (combinedTangents != null ? combinedTangents.ToArray() : null);

            var resultColors = (combinedColors != null ? combinedColors.ToArray() : null);

            var resultBoneWeights = (combinedBoneWeights != null ? combinedBoneWeights.ToArray() : null);

            var resultUVs = combinedUVs.ToArray();

            var resultBindposes = (usedBindposes != null ? usedBindposes.ToArray() : null);

            resultMaterials = usedMaterials.ToArray();

            resultBones = (usedBones != null ? usedBones.ToArray() : null);

            Mesh combinedMesh = MeshUtils.CreateMesh(resultVertices, resultIndices, resultNormals, resultTangents, resultColors, resultBoneWeights, resultUVs, resultBindposes, null);

            if (blendShapes != null && blendShapes.Count > 0)
            {
                foreach (BlendShapeFrame blendShape in blendShapes.Values)
                {
                    Vector3[] deltaVertices = new Vector3[combinedMesh.vertexCount];
                    Vector3[] deltaNormals  = new Vector3[combinedMesh.vertexCount];
                    Vector3[] deltaTangents = new Vector3[combinedMesh.vertexCount];

                    for (int p = 0; p < blendShape.deltaVertices.Length; p++)
                    {
                        deltaVertices.SetValue(blendShape.deltaVertices[p], p + blendShape.vertexOffset);
                        deltaNormals.SetValue(blendShape.deltaNormals[p], p + blendShape.vertexOffset);
                        deltaTangents.SetValue(blendShape.deltaTangents[p], p + blendShape.vertexOffset);
                    }

                    combinedMesh.AddBlendShapeFrame(blendShape.shapeName, blendShape.frameWeight, deltaVertices, deltaNormals, deltaTangents);
                }
            }



            return(combinedMesh);
        }
Пример #19
0
        /// <summary>
        /// Applies the data to a Unity mesh.
        /// </summary>
        /// <param name="renderer">Target renderer.</param>
        /// <param name="skeleton">Skeleton.</param>
        public void ApplyDataToUnityMesh(SkinnedMeshRenderer renderer, UMASkeleton skeleton)
        {
            CreateTransforms(skeleton);

            Mesh mesh = renderer.sharedMesh;

#if UNITY_EDITOR
            if (UnityEditor.PrefabUtility.IsComponentAddedToPrefabInstance(renderer))
            {
                Debug.LogError("Cannot apply changes to prefab!");
            }
            if (UnityEditor.AssetDatabase.IsSubAsset(mesh))
            {
                Debug.LogError("Cannot apply changes to asset mesh!");
            }
#endif
            mesh.subMeshCount = 1;
            mesh.triangles    = new int[0];

            if (OwnSharedBuffers())
            {
                ApplySharedBuffers(mesh);
            }
            else
            {
                mesh.vertices    = vertices;
                mesh.boneWeights = unityBoneWeights != null ? unityBoneWeights : UMABoneWeight.Convert(boneWeights);
                mesh.normals     = normals;
                mesh.tangents    = tangents;
                mesh.uv          = uv;
                mesh.uv2         = uv2;
                mesh.uv3         = uv3;
                mesh.uv4         = uv4;
                mesh.colors32    = colors32;
            }
            mesh.bindposes = bindPoses;

            var subMeshCount = submeshes.Length;
            mesh.subMeshCount = subMeshCount;
            for (int i = 0; i < subMeshCount; i++)
            {
                mesh.SetTriangles(submeshes[i].triangles, i);
            }

            //Apply the blendshape data from the slot asset back to the combined UMA unity mesh.
            #region Blendshape
            mesh.ClearBlendShapes();
            if (blendShapes != null && blendShapes.Length > 0)
            {
                for (int shapeIndex = 0; shapeIndex < blendShapes.Length; shapeIndex++)
                {
                    if (blendShapes [shapeIndex] == null)
                    {
                        Debug.LogError("blendShapes [shapeIndex] == null!");
                        break;
                    }

                    for (int frameIndex = 0; frameIndex < blendShapes[shapeIndex].frames.Length; frameIndex++)
                    {
                        //There might be an extreme edge case where someone has the same named blendshapes on different meshes that end up on different renderers.
                        string name = blendShapes [shapeIndex].shapeName;
                        mesh.AddBlendShapeFrame(name,
                                                blendShapes [shapeIndex].frames [frameIndex].frameWeight,
                                                blendShapes [shapeIndex].frames [frameIndex].deltaVertices,
                                                blendShapes [shapeIndex].frames [frameIndex].deltaNormals,
                                                blendShapes [shapeIndex].frames [frameIndex].deltaTangents);
                    }
                }
            }
            #endregion

            mesh.RecalculateBounds();
            renderer.bones      = bones != null ? bones : skeleton.HashesToTransforms(boneNameHashes);
            renderer.sharedMesh = mesh;
            renderer.rootBone   = rootBone;
        }
Пример #20
0
        public void ShouldGetMeshBlendShapes()
        {
            var mesh = new Mesh();

            mesh.vertices = new Vector3[2];

            string shapeName    = "test";
            var    frameWeights = new float[]
            {
                0.2f,
                0.48f
            };
            var deltaVertices = new Vector3[][]
            {
                new Vector3[] {
                    new Vector3(15f, 13.7f, 8889.91f),
                    new Vector3(761.717f, -76.225f, 889.1f)
                },
                new Vector3[]
                {
                    new Vector3(-15f, 13.7f, -8889.91f),
                    new Vector3(761.717f, 76.225f, -889.1f)
                }
            };
            var deltaNormals = new Vector3[][]
            {
                new Vector3[]
                {
                    deltaVertices[0][0].normalized,
                    deltaVertices[0][1].normalized
                },
                new Vector3[]
                {
                    deltaVertices[1][0].normalized,
                    deltaVertices[1][1].normalized
                }
            };
            var deltaTangents = new Vector3[][]
            {
                new Vector3[]
                {
                    Vector3.Cross(deltaNormals[0][0], Vector3.forward).normalized,
                    Vector3.Cross(deltaNormals[0][1], Vector3.forward).normalized,
                },
                new Vector3[]
                {
                    Vector3.Cross(deltaNormals[1][0], Vector3.forward).normalized,
                    Vector3.Cross(deltaNormals[1][1], Vector3.forward).normalized
                }
            };

            mesh.AddBlendShapeFrame(shapeName, frameWeights[0], deltaVertices[0], deltaNormals[0], deltaTangents[0]);
            mesh.AddBlendShapeFrame(shapeName, frameWeights[1], deltaVertices[1], deltaNormals[1], deltaTangents[1]);

            var blendShapes = MeshUtils.GetMeshBlendShapes(mesh);

            Assert.IsNotNull(blendShapes);
            Assert.AreEqual(1, blendShapes.Length);

            var blendShape = blendShapes[0];

            Assert.IsNotNull(blendShape);
            Assert.AreEqual(shapeName, blendShape.ShapeName);
            Assert.IsNotNull(blendShape.Frames);
            Assert.AreEqual(2, blendShape.Frames.Length);

            for (int i = 0; i < blendShape.Frames.Length; i++)
            {
                var frame = blendShape.Frames[i];
                Assert.AreEqual(frameWeights[i], frame.FrameWeight);
                Assert.AreEqual(deltaVertices[i], frame.DeltaVertices);
                Assert.AreEqual(deltaNormals[i], frame.DeltaNormals);
                Assert.AreEqual(deltaTangents[i], frame.DeltaTangents);
            }
        }
Пример #21
0
        void UpdateCurrentMesh()
        {
            UpdateInitialMesh();

            if (m_InitialMesh)
            {
                if (!m_CurrentMesh)
                {
                    m_CurrentMesh           = new Mesh();
                    m_CurrentMesh.hideFlags = HideFlags.DontSave;
                    m_CurrentMesh.MarkDynamic();
                }

                m_CurrentMesh.Clear();
                m_CurrentMesh.name        = m_InitialMesh.name;
                m_CurrentMesh.vertices    = m_InitialMesh.vertices;
                m_CurrentMesh.uv          = m_InitialMesh.uv;
                m_CurrentMesh.normals     = m_InitialMesh.normals;
                m_CurrentMesh.tangents    = m_InitialMesh.tangents;
                m_CurrentMesh.boneWeights = m_InitialMesh.boneWeights;
                m_CurrentMesh.bindposes   = m_InitialMesh.bindposes;
                m_CurrentMesh.bounds      = m_InitialMesh.bounds;
                m_CurrentMesh.colors      = m_InitialMesh.colors;

                for (int i = 0; i < m_InitialMesh.subMeshCount; ++i)
                {
                    m_CurrentMesh.SetTriangles(m_InitialMesh.GetTriangles(i), i);
                }


#if !(UNITY_5_0 || UNITY_5_1 || UNITY_5_2)
                m_CurrentMesh.ClearBlendShapes();

                for (int i = 0; i < m_InitialMesh.blendShapeCount; ++i)
                {
                    string blendshapeName = m_InitialMesh.GetBlendShapeName(i);

                    for (int j = 0; j < m_InitialMesh.GetBlendShapeFrameCount(i); ++j)
                    {
                        float weight = m_InitialMesh.GetBlendShapeFrameWeight(i, j);

                        Vector3[] vertices = new Vector3[m_InitialMesh.vertexCount];

                        m_InitialMesh.GetBlendShapeFrameVertices(i, j, vertices, null, null);

                        m_CurrentMesh.AddBlendShapeFrame(blendshapeName, weight, vertices, null, null);
                    }
                }
#endif
                m_CurrentMesh.hideFlags = HideFlags.DontSave;
            }
            else
            {
                m_InitialMesh = null;

                if (m_CurrentMesh)
                {
                    m_CurrentMesh.Clear();
                }
            }

            if (m_CurrentMesh)
            {
                if (spriteMesh && spriteMesh.sprite && spriteMesh.sprite.packed)
                {
                    SetSpriteUVs(m_CurrentMesh, spriteMesh.sprite);
                }

                m_CurrentMesh.UploadMeshData(false);
            }

            UpdateRenderers();

#if UNITY_EDITOR
            UpdateTimestamp();
#endif
        }
Пример #22
0
        public Mesh Construct()
        {
            if (profile == null)
            {
                Debug.LogError("NoMesh Packaging profile to generate mesh");
                return(mesh);
            }

            GenerateTriangles();

            var valid = profile.Repack(this);

            if (!valid)
            {
                return(mesh);
            }

            mesh.bindposes = edMesh.bindPoses;

            if (edMesh.gotBoneWeights)
            {
                _boneWeights = new BoneWeight[vertexCount];

                // for (var i = 0; i < edMesh.meshPoints.Count; i++)
                //    _boneWeights[i] = edMesh.meshPoints[i].boneWeight;

                foreach (var vp in edMesh.meshPoints)
                {
                    foreach (var uvi in vp.vertices)
                    {
                        _boneWeights[uvi] = uvi.boneWeight;
                    }
                }

                mesh.boneWeights = _boneWeights;
            }

            var vCnt = mesh.vertices.Length;

            if (!edMesh.shapes.IsNullOrEmpty())
            {
                for (var s = 0; s < edMesh.shapes.Count; s++)
                {
                    var name   = edMesh.shapes[s];
                    var frames = edMesh.meshPoints[0].shapes[s].Count;

                    for (var f = 0; f < frames; f++)
                    {
                        var pos = new Vector3[vCnt];
                        var nrm = new Vector3[vCnt];
                        var tng = new Vector3[vCnt];

                        for (var v = 0; v < vCnt; v++)
                        {
                            var bf = edMesh.uvsByFinalIndex[v].meshPoint.shapes[s][f];

                            pos[v] = bf.deltaPosition;
                            nrm[v] = bf.deltaNormal;
                            tng[v] = bf.deltaTangent;
                        }
                        mesh.AddBlendShapeFrame(name, edMesh.blendWeights[s][f], pos, nrm, tng);
                    }
                }
            }

            edMesh.firstBuildRun = true;

            mesh.name = edMesh.meshName;

            return(mesh);
        }
Пример #23
0
    static GameObject CopyMesh(GameObject subject)
    {
        GameObject clone = (GameObject)GameObject.Instantiate(subject);

        MeshFilter[] mfs      = subject.GetComponentsInChildren <MeshFilter>();
        MeshFilter[] clonemfs = clone.GetComponentsInChildren <MeshFilter>();

        MeshCollider[] mcs      = clone.GetComponentsInChildren <MeshCollider>();
        MeshCollider[] clonemcs = clone.GetComponentsInChildren <MeshCollider>();

        int l = mfs.Length;

        for (int i = 0; i < l; i++)
        {
            MeshFilter mf        = mfs[i];
            MeshFilter clonemf   = clonemfs[i];
            Mesh       mesh      = mf.sharedMesh;
            Mesh       clonemesh = new Mesh();
            clonemesh.vertices = mesh.vertices;
#if UNITY_5_0 || UNITY_5_1 || UNITY_5 || UNITY_2017
            clonemesh.uv2 = mesh.uv2;
            clonemesh.uv3 = mesh.uv3;
            clonemesh.uv4 = mesh.uv4;
#else
            clonemesh.uv1 = mesh.uv1;
            clonemesh.uv2 = mesh.uv2;
#endif
            clonemesh.uv       = mesh.uv;
            clonemesh.normals  = mesh.normals;
            clonemesh.tangents = mesh.tangents;
            clonemesh.colors   = mesh.colors;

            clonemesh.subMeshCount = mesh.subMeshCount;

            for (int s = 0; s < mesh.subMeshCount; s++)
            {
                clonemesh.SetTriangles(mesh.GetTriangles(s), s);
            }

            //clonemesh.triangles = mesh.triangles;

#if UNITY_5_3 || UNITY_5_4 || UNITY_5_5 || UNITY_5_6 || UNITY_2017
            CopyBlendShapes(mesh, clonemesh);
#if false
            int bcount = mesh.blendShapeCount;                  //GetBlendShapeFrameCount();

            Vector3[] deltaverts = new Vector3[mesh.vertexCount];
            Vector3[] deltanorms = new Vector3[mesh.vertexCount];
            Vector3[] deltatans  = new Vector3[mesh.vertexCount];

            for (int j = 0; j < bcount; j++)
            {
                int    frames = mesh.GetBlendShapeFrameCount(j);
                string bname  = mesh.GetBlendShapeName(j);

                for (int f = 0; f < frames; f++)
                {
                    mesh.GetBlendShapeFrameVertices(j, f, deltaverts, deltanorms, deltatans);
                    float weight = mesh.GetBlendShapeFrameWeight(j, f);

                    clonemesh.AddBlendShapeFrame(bname, weight, deltaverts, deltanorms, deltatans);
                }
            }
#endif
#endif

            clonemesh.boneWeights = mesh.boneWeights;
            clonemesh.bindposes   = mesh.bindposes;
            clonemesh.name        = mesh.name + "_copy";
            clonemesh.RecalculateBounds();
            clonemf.sharedMesh = clonemesh;

            for (int j = 0; j < mcs.Length; j++)
            {
                MeshCollider mc = mcs[j];
                if (mc.sharedMesh == mesh)
                {
                    clonemcs[j].sharedMesh = clonemesh;
                }
            }
        }

        return(clone);
    }
Пример #24
0
        public Mesh EncryptMesh(Mesh mesh, float distortRatio, bool[] keys)
        {
            if (mesh == null)
            {
                return(null);
            }

            int divideCount = keys.Length / DivideCount;

            Vector3[] newVertices = mesh.vertices;
            Vector3[] normals     = mesh.normals;
            Vector2[] uv7Offsets  = new Vector2[mesh.vertexCount];
            Vector2[] uv8Offsets  = new Vector2[mesh.vertexCount];

            float[] decodeKeys = new float[divideCount];

            for (int i = 0; i < divideCount; ++i)
            {
                decodeKeys[i] = (Convert.ToSingle(keys[i * DivideCount]) + _randomKeyMultiplier[i * DivideCount]) *
                                (Convert.ToSingle(keys[i * DivideCount + 1]) + _randomKeyMultiplier[i * DivideCount + 1]) *
                                (Convert.ToSingle(keys[i * DivideCount + 2]) + _randomKeyMultiplier[i * DivideCount + 2]) *
                                (Convert.ToSingle(keys[i * DivideCount + 3]) + _randomKeyMultiplier[i * DivideCount + 3]);
                Debug.Log("decodeKey: " + decodeKeys[i]);
            }

            StringBuilder sb0 = new StringBuilder();
            StringBuilder sb1 = new StringBuilder();

            float[] comKey = new float[divideCount];
            for (int i = 0; i < divideCount; ++i)
            {
                float firstAdd = _keySign0[i] > 0
                    ? decodeKeys[_randomKeyIndex[i * DivideCount]] - decodeKeys[_randomKeyIndex[i * DivideCount + 1]]
                    : decodeKeys[_randomKeyIndex[i * DivideCount]] + decodeKeys[_randomKeyIndex[i * DivideCount + 1]];
                float firstSign = _sign0[i] > 0 ? Mathf.Sin(firstAdd) : Mathf.Cos(firstAdd);

                float secondAdd = _keySign1[i] > 0
                    ? decodeKeys[_randomKeyIndex[i * DivideCount + 2]] - decodeKeys[_randomKeyIndex[i * DivideCount + 3]]
                    : decodeKeys[_randomKeyIndex[i * DivideCount + 2]] + decodeKeys[_randomKeyIndex[i * DivideCount + 3]];
                float secondSign = _sign1[i] > 0 ? Mathf.Sin(secondAdd) : Mathf.Cos(secondAdd);

                comKey[i] = firstSign * _randomDivideMultiplier[i] * secondSign;

                string firstAddStr   = _keySign0[i] > 0 ? "-" : "+";
                string firstSignStr  = _sign0[i] > 0 ? "sin" : "cos";
                string secondAddStr  = _keySign1[i] > 0 ? "-" : "+";
                string secondSignStr = _sign1[i] > 0 ? "sin" : "cos";

                sb0.AppendLine($"float decodeKey{i} = (_BitKey{i*DivideCount} + {_randomKeyMultiplier[i*DivideCount]}) * (_BitKey{i*DivideCount+1} + {_randomKeyMultiplier[i*DivideCount+1]}) * (_BitKey{i*DivideCount+2} + {_randomKeyMultiplier[i*DivideCount+2]}) * (_BitKey{i*DivideCount+3} + {_randomKeyMultiplier[i*DivideCount+3]});");
                sb1.AppendLine($"float comKey{i} = {firstSignStr}(decodeKey{_randomKeyIndex[i*DivideCount]} {firstAddStr} decodeKey{_randomKeyIndex[i*DivideCount+1]}) * {_randomDivideMultiplier[i]} * {secondSignStr}(decodeKey{_randomKeyIndex[i*DivideCount+2]} {secondAddStr} decodeKey{_randomKeyIndex[i*DivideCount+3]});");
            }

            var searchResult = AssetDatabase.FindAssets("CGI_GTModelDecode");

            if (searchResult.Length == 0)
            {
                Debug.LogError("CGI_GTModelDecode.cginc not found!");
            }
            else
            {
                foreach (string sr in searchResult)
                {
                    Debug.Log($"Writing GTModelDecode {sr}");
                    System.IO.File.WriteAllText(AssetDatabase.GUIDToAssetPath(sr), $"{ModelShaderDecodeFirst}{sb0.ToString()}{sb1.ToString()}{ModelShaderDecodeSecond}");
                }
            }

            float maxDistance = mesh.bounds.max.magnitude - mesh.bounds.min.magnitude;

            float       minRange = maxDistance * -distortRatio;
            const float maxRange = 0;

            for (var v = 0; v < newVertices.Length; v++)
            {
                uv7Offsets[v].x = Random.Range(minRange, maxRange);
                uv7Offsets[v].y = Random.Range(minRange, maxRange);

                uv8Offsets[v].x = Random.Range(minRange, maxRange);
                uv8Offsets[v].y = Random.Range(minRange, maxRange);

                newVertices[v] += normals[v] * (uv7Offsets[v].x * comKey[0]);
                newVertices[v] += normals[v] * (uv7Offsets[v].y * comKey[1]);
                newVertices[v] += normals[v] * (uv7Offsets[v].x * comKey[2]);
                newVertices[v] += normals[v] * (uv7Offsets[v].y * comKey[3]);

                newVertices[v] += normals[v] * (uv8Offsets[v].y * comKey[4]);
                newVertices[v] += normals[v] * (uv8Offsets[v].x * comKey[5]);
                newVertices[v] += normals[v] * (uv8Offsets[v].y * comKey[6]);
                newVertices[v] += normals[v] * (uv8Offsets[v].x * comKey[7]);
            }

            var existingMeshPath = AssetDatabase.GetAssetPath(mesh);

            if (string.IsNullOrEmpty(existingMeshPath) || existingMeshPath.Contains("unity default resources"))
            {
                Debug.LogError("Asset For Mesh Not Found, Invalid Or Is A Built In Unity Mesh!");
                return(null);
            }

            Debug.Log($"Existing Mesh Path For {mesh.name} Is {existingMeshPath}");

            //Do Not Care What File Type The Mesh Is, Attempt Anyway.
            //The Inline If Statement Is A Fallback Check, It Gets The Path Combined With The Filename Without Extension With Our Own Extension, If The Path Is Null, It Would Then Use Enviroment.CurrentDirectory Via Inheritance As The Path.
            var encryptedMeshPath = Path.GetDirectoryName(existingMeshPath) != null ? (Path.Combine(Path.GetDirectoryName(existingMeshPath), Path.GetFileNameWithoutExtension(existingMeshPath)) + $"_{mesh.name}_Encrypted.asset") : (Path.GetFileNameWithoutExtension(existingMeshPath) + $"_{mesh.name}_Encrypted.asset");

            Debug.Log($"Encrypted Mesh Path {encryptedMeshPath}");

            var newMesh = new Mesh
            {
                subMeshCount = mesh.subMeshCount,
                vertices     = newVertices,
                colors       = mesh.colors,
                normals      = mesh.normals,
                tangents     = mesh.tangents,
                bindposes    = mesh.bindposes,
                boneWeights  = mesh.boneWeights,
                uv           = mesh.uv,
                uv2          = mesh.uv2,
                uv3          = mesh.uv3,
                uv4          = mesh.uv4,
                uv5          = mesh.uv5,
                uv6          = mesh.uv6,
                uv7          = uv7Offsets,
                uv8          = uv8Offsets
            };

            // transfer sub meshes
            for (var meshIndex = 0; meshIndex < mesh.subMeshCount; meshIndex++)
            {
                var triangles = mesh.GetTriangles(meshIndex);

                newMesh.SetTriangles(triangles, meshIndex);
            }

            // transfer blend shapes
            for (int shapeIndex = 0; shapeIndex < mesh.blendShapeCount; shapeIndex++)
            {
                for (var frameIndex = 0; frameIndex < mesh.GetBlendShapeFrameCount(shapeIndex); frameIndex++)
                {
                    Vector3[] deltaVertices = new Vector3[newVertices.Length];
                    Vector3[] deltaNormals  = new Vector3[newVertices.Length];
                    Vector3[] deltaTangents = new Vector3[newVertices.Length];
                    mesh.GetBlendShapeFrameVertices(shapeIndex, frameIndex, deltaVertices, deltaNormals, deltaTangents);
                    float  weight    = mesh.GetBlendShapeFrameWeight(shapeIndex, frameIndex);
                    string shapeName = mesh.GetBlendShapeName(shapeIndex);
                    newMesh.AddBlendShapeFrame(shapeName, weight, deltaVertices, deltaNormals, deltaTangents);
                }
            }

            AssetDatabase.CreateAsset(newMesh, encryptedMeshPath);
            AssetDatabase.SaveAssets();

            return(newMesh);
        }
Пример #25
0
                public Mesh ToMesh()
                {
                    Mesh mesh = new Mesh();

                    if (verts.Count >= ushort.MaxValue)
                    {
                        mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32;
                    }
                    mesh.vertices     = verts.ToArray();
                    mesh.subMeshCount = submeshTris.Count;
                    var onlyTriangles = true;

                    for (int i = 0; i < submeshTris.Count; i++)
                    {
                        switch (submeshTrisMode[i])
                        {
                        case RenderingMode.POINTS:
                            mesh.SetIndices(submeshTris[i].ToArray(), MeshTopology.Points, i);
                            onlyTriangles = false;
                            break;

                        case RenderingMode.LINES:
                            mesh.SetIndices(submeshTris[i].ToArray(), MeshTopology.Lines, i);
                            onlyTriangles = false;
                            break;

                        case RenderingMode.LINE_STRIP:
                            mesh.SetIndices(submeshTris[i].ToArray(), MeshTopology.LineStrip, i);
                            onlyTriangles = false;
                            break;

                        case RenderingMode.TRIANGLES:
                            mesh.SetTriangles(submeshTris[i].ToArray(), i);
                            break;

                        default:
                            Debug.LogWarning("GLTF rendering mode " + submeshTrisMode[i] + " not supported.");
                            return(null);
                        }
                    }

                    mesh.colors = colors.ToArray();
                    if (uv1 != null)
                    {
                        mesh.uv = uv1.ToArray();
                    }
                    if (uv2 != null)
                    {
                        mesh.uv2 = uv2.ToArray();
                    }
                    if (uv3 != null)
                    {
                        mesh.uv3 = uv3.ToArray();
                    }
                    if (uv4 != null)
                    {
                        mesh.uv4 = uv4.ToArray();
                    }
                    if (uv5 != null)
                    {
                        mesh.uv5 = uv5.ToArray();
                    }
                    if (uv6 != null)
                    {
                        mesh.uv6 = uv6.ToArray();
                    }
                    if (uv7 != null)
                    {
                        mesh.uv7 = uv7.ToArray();
                    }
                    if (uv8 != null)
                    {
                        mesh.uv8 = uv8.ToArray();
                    }
                    if (weights != null)
                    {
                        mesh.boneWeights = weights.ToArray();
                    }

                    mesh.RecalculateBounds();

                    // Blend shapes
                    for (int i = 0; i < blendShapes.Count; i++)
                    {
                        mesh.AddBlendShapeFrame(blendShapes[i].name, 1f, blendShapes[i].pos, blendShapes[i].norm, blendShapes[i].tan);
                    }

                    if (normals.Count == 0 && onlyTriangles)
                    {
                        mesh.RecalculateNormals();
                    }
                    else
                    {
                        mesh.normals = normals.ToArray();
                    }

                    if (tangents.Count == 0 && onlyTriangles)
                    {
                        mesh.RecalculateTangents();
                    }
                    else
                    {
                        mesh.tangents = tangents.ToArray();
                    }

                    mesh.name = name;
                    return(mesh);
                }
Пример #26
0
        public static void RebuildBlendShapes(SpriteMesh spriteMesh, Mesh mesh)
        {
            if (!mesh)
            {
                return;
            }

            if (!spriteMesh)
            {
                return;
            }

            BlendShape[] blendShapes = null;

            SpriteMeshData spriteMeshData = LoadSpriteMeshData(spriteMesh);

            if (spriteMeshData)
            {
                blendShapes = spriteMeshData.blendshapes;
            }

            if (spriteMesh.sharedMesh.vertexCount != mesh.vertexCount)
            {
                return;
            }

            if (blendShapes != null)
            {
#if !(UNITY_5_0 || UNITY_5_1 || UNITY_5_2)
                List <string> blendShapeNames = new List <string>();

                mesh.ClearBlendShapes();

                Vector3[] from = mesh.vertices;

                for (int i = 0; i < blendShapes.Length; i++)
                {
                    BlendShape blendshape = blendShapes[i];

                    if (blendshape)
                    {
                        string blendShapeName = blendshape.name;

                        if (blendShapeNames.Contains(blendShapeName))
                        {
                            Debug.LogWarning("Found repeated BlendShape name '" + blendShapeName + "' in SpriteMesh: " + spriteMesh.name);
                        }
                        else
                        {
                            blendShapeNames.Add(blendShapeName);

                            for (int j = 0; j < blendshape.frames.Length; j++)
                            {
                                BlendShapeFrame l_blendshapeFrame = blendshape.frames[j];

                                if (l_blendshapeFrame && from.Length == l_blendshapeFrame.vertices.Length)
                                {
                                    Vector3[] deltaVertices = GetDeltaVertices(from, l_blendshapeFrame.vertices);

                                    mesh.AddBlendShapeFrame(blendShapeName, l_blendshapeFrame.weight, deltaVertices, null, null);
                                }
                            }
                        }
                    }
                }

                mesh.UploadMeshData(false);

                EditorUtility.SetDirty(mesh);

                HideMaterials(spriteMesh);
#endif
            }
        }
Пример #27
0
        private static void FixSeams(Mesh source, Mesh output, List <List <int> > submeshes, List <Ring> rings, List <Insertion> insertions, P3dCoord coord)
        {
            output.bindposes    = source.bindposes;
            output.bounds       = source.bounds;
            output.subMeshCount = source.subMeshCount;
            output.indexFormat  = source.indexFormat;

            if (source.vertexCount + insertions.Count >= 65535)
            {
                output.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32;
            }

            var weights   = new List <BoneWeight>(); source.GetBoneWeights(weights);
            var colors    = new List <Color32>();    source.GetColors(colors);
            var normals   = new List <Vector3>();    source.GetNormals(normals);
            var tangents  = new List <Vector4>();    source.GetTangents(tangents);
            var coords0   = new List <Vector4>();    source.GetUVs(0, coords0);
            var coords1   = new List <Vector4>();    source.GetUVs(1, coords1);
            var coords2   = new List <Vector4>();    source.GetUVs(2, coords2);
            var coords3   = new List <Vector4>();    source.GetUVs(3, coords3);
            var positions = new List <Vector3>();    source.GetVertices(positions);

#if UNITY_2019_1_OR_NEWER
            var boneVertices = new List <byte>(source.GetBonesPerVertex());
            var boneWeights  = new List <BoneWeight1>(source.GetAllBoneWeights());
            var boneIndices  = new List <int>();

            if (boneVertices.Count > 0)
            {
                var total = 0;

                foreach (var count in boneVertices)
                {
                    boneIndices.Add(total);

                    total += count;
                }

                weights.Clear();
            }
#endif
            foreach (var insertion in insertions)
            {
#if UNITY_2019_1_OR_NEWER
                if (boneVertices.Count > 0)
                {
                    var index = boneIndices[insertion.Index];
                    var count = boneVertices[insertion.Index];

                    boneVertices.Add(count);

                    for (var i = 0; i < count; i++)
                    {
                        boneWeights.Add(boneWeights[index + i]);
                    }
                }
#endif
                if (weights.Count > 0)
                {
                    weights.Add(weights[insertion.Index]);
                }

                if (colors.Count > 0)
                {
                    colors.Add(colors[insertion.Index]);
                }

                if (normals.Count > 0)
                {
                    normals.Add(normals[insertion.Index]);
                }

                if (tangents.Count > 0)
                {
                    tangents.Add(tangents[insertion.Index]);
                }

                if (coords0.Count > 0)
                {
                    AddCoord(coords0, insertion, coord == P3dCoord.First);
                }

                if (coords1.Count > 0)
                {
                    AddCoord(coords1, insertion, coord == P3dCoord.Second);
                }

                if (coords2.Count > 0)
                {
                    AddCoord(coords2, insertion, coord == P3dCoord.Third);
                }

                if (coords3.Count > 0)
                {
                    AddCoord(coords3, insertion, coord == P3dCoord.Fourth);
                }

                positions.Add(positions[insertion.Index]);
            }

            output.SetVertices(positions);

            if (weights.Count > 0)
            {
                output.boneWeights = weights.ToArray();
            }
#if UNITY_2019_1_OR_NEWER
            if (boneVertices.Count > 0)
            {
                var na1 = new Unity.Collections.NativeArray <byte>(boneVertices.ToArray(), Unity.Collections.Allocator.Temp);
                var na2 = new Unity.Collections.NativeArray <BoneWeight1>(boneWeights.ToArray(), Unity.Collections.Allocator.Temp);
                output.SetBoneWeights(na1, na2);
                na2.Dispose();
                na1.Dispose();
            }
#endif
            output.SetColors(colors);
            output.SetNormals(normals);
            output.SetTangents(tangents);
            output.SetUVs(0, coords0);
            output.SetUVs(1, coords1);
            output.SetUVs(2, coords2);
            output.SetUVs(3, coords3);

            var deltaVertices = new List <Vector3>();
            var deltaNormals  = new List <Vector3>();
            var deltaTangents = new List <Vector3>();

            if (source.blendShapeCount > 0)
            {
                var tempDeltaVertices = new Vector3[source.vertexCount];
                var tempDeltaNormals  = new Vector3[source.vertexCount];
                var tempDeltaTangents = new Vector3[source.vertexCount];

                for (var i = 0; i < source.blendShapeCount; i++)
                {
                    var shapeName  = source.GetBlendShapeName(i);
                    var frameCount = source.GetBlendShapeFrameCount(i);

                    for (var j = 0; j < frameCount; j++)
                    {
                        source.GetBlendShapeFrameVertices(i, j, tempDeltaVertices, tempDeltaNormals, tempDeltaTangents);

                        deltaVertices.Clear();
                        deltaNormals.Clear();
                        deltaTangents.Clear();

                        deltaVertices.AddRange(tempDeltaVertices);
                        deltaNormals.AddRange(tempDeltaNormals);
                        deltaTangents.AddRange(tempDeltaTangents);

                        foreach (var insertion in insertions)
                        {
                            deltaVertices.Add(deltaVertices[insertion.Index]);
                            deltaNormals.Add(deltaNormals[insertion.Index]);
                            deltaTangents.Add(deltaTangents[insertion.Index]);
                        }

                        output.AddBlendShapeFrame(shapeName, source.GetBlendShapeFrameWeight(i, j), deltaVertices.ToArray(), deltaNormals.ToArray(), deltaTangents.ToArray());
                    }
                }
            }

            for (var i = 0; i < submeshes.Count; i++)
            {
                output.SetTriangles(submeshes[i], i);
            }
        }
Пример #28
0
        /// <summary>
        /// Applies the data to a Unity mesh.
        /// </summary>
        /// <param name="renderer">Target renderer.</param>
        /// <param name="skeleton">Skeleton.</param>
        public void ApplyDataToUnityMesh(SkinnedMeshRenderer renderer, UMASkeleton skeleton)
        {
            CreateTransforms(skeleton);

            Mesh mesh = renderer.sharedMesh;

#if UNITY_EDITOR
#if UNITY_2018_3_OR_NEWER
            if (UnityEditor.PrefabUtility.IsAddedComponentOverride(renderer))
            {
                if (Debug.isDebugBuild)
                {
                    Debug.LogError("Cannot apply changes to prefab!");
                }
            }
#else
            if (UnityEditor.PrefabUtility.IsComponentAddedToPrefabInstance(renderer))
            {
                if (Debug.isDebugBuild)
                {
                    Debug.LogError("Cannot apply changes to prefab!");
                }
            }
#endif
            if (UnityEditor.AssetDatabase.IsSubAsset(mesh))
            {
                if (Debug.isDebugBuild)
                {
                    Debug.LogError("Cannot apply changes to asset mesh!");
                }
            }
#endif
            mesh.subMeshCount = 1;
            mesh.triangles    = new int[0];

            if (OwnSharedBuffers())
            {
                ApplySharedBuffers(mesh);
            }
            else
            {
                mesh.vertices    = vertices;
                mesh.boneWeights = unityBoneWeights != null ? unityBoneWeights : UMABoneWeight.Convert(boneWeights);
                mesh.normals     = normals;
                mesh.tangents    = tangents;
                mesh.uv          = uv;
                mesh.uv2         = uv2;
                mesh.uv3         = uv3;
                mesh.uv4         = uv4;
                mesh.colors32    = colors32;
            }
            mesh.bindposes = bindPoses;

            var subMeshCount = submeshes.Length;
            mesh.subMeshCount = subMeshCount;
            for (int i = 0; i < subMeshCount; i++)
            {
                bool sharedBuffer = false;
                for (int j = 0; j < gSubmeshTris.Length; j++)
                {
                    if (gSubmeshTriIndices[j] == i)
                    {
                        sharedBuffer = true;
                        mesh.SetTriangles(gSubmeshTris[j], i);
                        gSubmeshTriIndices[j] = UNUSED_SUBMESH;
                        break;
                    }
                }

                if (!sharedBuffer)
                {
                    mesh.SetTriangles(submeshes[i].triangles, i);
                }
            }

            //Apply the blendshape data from the slot asset back to the combined UMA unity mesh.
            #region Blendshape
            mesh.ClearBlendShapes();
            if (blendShapes != null && blendShapes.Length > 0)
            {
                for (int shapeIndex = 0; shapeIndex < blendShapes.Length; shapeIndex++)
                {
                    if (blendShapes [shapeIndex] == null)
                    {
                        //Debug.LogError ("blendShapes [shapeIndex] == null!");
                        //No longer an error, this will be null if the blendshape got baked.
                        break;
                    }

                    for (int frameIndex = 0; frameIndex < blendShapes[shapeIndex].frames.Length; frameIndex++)
                    {
                        //There might be an extreme edge case where someone has the same named blendshapes on different meshes that end up on different renderers.
                        string name = blendShapes[shapeIndex].shapeName;

                        float     frameWeight   = blendShapes[shapeIndex].frames[frameIndex].frameWeight;
                        Vector3[] deltaVertices = blendShapes[shapeIndex].frames[frameIndex].deltaVertices;
                        Vector3[] deltaNormals  = blendShapes[shapeIndex].frames[frameIndex].deltaNormals;
                        Vector3[] deltaTangents = blendShapes[shapeIndex].frames[frameIndex].deltaTangents;

                        if (UMABlendFrame.isAllZero(deltaNormals))
                        {
                            deltaNormals = null;
                        }

                        if (UMABlendFrame.isAllZero(deltaTangents))
                        {
                            deltaTangents = null;
                        }

                        mesh.AddBlendShapeFrame(name, frameWeight, deltaVertices, deltaNormals, deltaTangents);
                    }
                }
            }
            #endregion

            mesh.RecalculateBounds();
            renderer.bones      = bones != null ? bones : skeleton.HashesToTransforms(boneNameHashes);
            renderer.sharedMesh = mesh;
            renderer.rootBone   = rootBone;

            if (clothSkinning != null && clothSkinning.Length > 0)
            {
                Cloth cloth = renderer.GetComponent <Cloth>();
                if (cloth != null)
                {
                    GameObject.DestroyImmediate(cloth);
                    cloth = null;
                }

                cloth = renderer.gameObject.AddComponent <Cloth>();

                /* DUSTIN REMOVAL
                 * UMAPhysicsAvatar physicsAvatar = renderer.gameObject.GetComponentInParent<UMAPhysicsAvatar>();
                 * if (physicsAvatar != null)
                 * {
                 *      cloth.sphereColliders = physicsAvatar.SphereColliders.ToArray();
                 *      cloth.capsuleColliders = physicsAvatar.CapsuleColliders.ToArray();
                 * }
                 */
                cloth.coefficients = clothSkinning;
            }
        }
Пример #29
0
    //Only available from Unity 5.3 onward
    private static void CopyBlendShapes(Mesh originalMesh, Mesh newMesh)
    {
        for(int i = 0; i < originalMesh.blendShapeCount; i++)
        {
            string shapeName = originalMesh.GetBlendShapeName(i);
            int frameCount = originalMesh.GetBlendShapeFrameCount(i);
            for(int j = 0; j < frameCount; j++)
            {
                Vector3[] dv = new Vector3[originalMesh.vertexCount];
                Vector3[] dn = new Vector3[originalMesh.vertexCount];
                Vector3[] dt = new Vector3[originalMesh.vertexCount];

                float frameWeight = originalMesh.GetBlendShapeFrameWeight(i, j);
                originalMesh.GetBlendShapeFrameVertices(i, j, dv, dn, dt);
                newMesh.AddBlendShapeFrame(shapeName, frameWeight, dv, dn, dt);
            }
        }
    }
Пример #30
0
        public static Mesh GetMesh(Mesh mesh, Transform obj, Transform projector, Mesh skinnedMesh, int submeshMask, float?interpolateNormals, float maxNormal = 0f)
        {
            Profiler.BeginSample("Building static decal mesh");

            var verts    = mesh.vertices;
            var normals  = maxNormal < 1f ? mesh.normals : null;
            var newVerts = new List <Vector3>(mesh.vertexCount);
            var vertMap  = new int[verts.Length];
            var newTris  = new List <int>(mesh.vertexCount);

            TransformVerts(verts, obj, projector);
            TransformNormals(normals, obj, projector);

            for (int i = 0; i < vertMap.Length; i++)
            {
                vertMap[i] = -1;
            }

            // Map valid vertices to a new list
            if (submeshMask == 0)
            {
                Profiler.BeginSample("Processing triangles");
                ProcessTriangles(mesh.triangles, verts, newTris, newVerts, vertMap, normals, maxNormal);
                Profiler.EndSample();
            }
            else
            {
                for (int i = 0; i < mesh.subMeshCount; i++)
                {
                    if ((submeshMask & 1 << i) != 0)
                    {
                        continue;
                    }
                    Profiler.BeginSample("Processing triangles for submesh " + i);
                    ProcessTriangles(mesh.GetTriangles(i), verts, newTris, newVerts, vertMap, normals, maxNormal);
                    Profiler.EndSample();
                }
            }

            if (newVerts.Count == 0 || newTris.Count == 0)
            {
                throw new Exception("New mesh is empty");
            }

            // Get the vertex IDs of the old mesh..
            var reverseMap = new int[newVerts.Count];

            for (int i = 0; i < vertMap.Length; i++)
            {
                if (vertMap[i] >= 0)
                {
                    reverseMap[vertMap[i]] = i;
                }
            }

            Profiler.BeginSample("Set geometry");
            var ret = new Mesh {
                subMeshCount = 1
            };
            var newUvs = newVerts.Select(v => (Vector2)v + new Vector2(0.5f, 0.5f)).ToArray();

            // Inverse transform verts
            for (int i = 0; i < newVerts.Count; i++)
            {
                newVerts[i] = obj.InverseTransformPoint(projector.TransformPoint(newVerts[i]));
            }

            // Set vertices before anything else
            ret.SetVertices(newVerts);
            ret.uv = newUvs;
            ret.SetTriangles(newTris, 0);
            var oldNormals  = mesh.normals;
            var oldTangents = mesh.tangents;

            if (interpolateNormals.HasValue)
            {
                var decalToObject = obj.worldToLocalMatrix * projector.localToWorldMatrix;
                var bitangent     = decalToObject.GetColumn(1);
                var normal        = -(Vector3)decalToObject.GetColumn(2);
                var t             = interpolateNormals.Value;
                var newNormals    = reverseMap
                                    .Select(id => Vector3.Lerp(oldNormals[id], normal, t))
                                    .ToArray();
                ret.normals  = newNormals;
                ret.tangents = newNormals
                               .Select(n => Vector3.Cross(n, bitangent))
                               .Select(v => new Vector4(v.x, v.y, v.z, -1))
                               .ToArray();
            }
            else
            {
                ret.normals  = reverseMap.Select(id => oldNormals[id]).ToArray();
                ret.tangents = reverseMap.Select(id => oldTangents[id]).ToArray();
            }
            ret.RecalculateBounds();
            Profiler.EndSample();

            // Find the start and end points of the new mesh within the old one
            int startVertex, endVertex;

            for (startVertex = 0; startVertex < vertMap.Length; startVertex++)
            {
                if (vertMap[startVertex] >= 0)
                {
                    break;
                }
            }
            for (endVertex = vertMap.Length - 1; endVertex >= 0; endVertex--)
            {
                if (vertMap[endVertex] >= 0)
                {
                    break;
                }
            }

            if (skinnedMesh != null)
            {
                Profiler.BeginSample("Setting skin data");
                var boneWeights = skinnedMesh.boneWeights;
                if (boneWeights.Length != mesh.vertexCount)
                {
                    Debug.LogError(skinnedMesh + " has no skin data");
                }
                else
                {
                    var newBoneWeights = new BoneWeight[newVerts.Count];
                    for (int k = startVertex; k <= endVertex; k++)
                    {
                        var vIndex = vertMap[k];
                        if (vIndex < 0)
                        {
                            continue;
                        }
                        newBoneWeights[vIndex] = boneWeights[k];
                    }
                    ret.boneWeights = newBoneWeights;
                    ret.bindposes   = skinnedMesh.bindposes;
                }
                Profiler.EndSample();
            }

            mesh = skinnedMesh;
            if (mesh != null && mesh.blendShapeCount > 0)
            {
                Profiler.BeginSample("Set blend shapes");
                var deltaVertices = verts;                 // We don't need the 'verts' array anymore so we can use it here
                var deltaNormals  = new Vector3[mesh.vertexCount];
                var deltaTangents = new Vector3[mesh.vertexCount];

                var newDeltaVertices = new Vector3[ret.vertexCount];
                var newDeltaNormals  = new Vector3[ret.vertexCount];
                var newDeltaTangents = new Vector3[ret.vertexCount];

                for (int i = 0; i < mesh.blendShapeCount; i++)
                {
                    var frameCount = mesh.GetBlendShapeFrameCount(i);
                    var shapeName  = mesh.GetBlendShapeName(i);
                    for (int j = 0; j < frameCount; j++)
                    {
                        var weight = mesh.GetBlendShapeFrameWeight(i, j);
                        mesh.GetBlendShapeFrameVertices(i, j,
                                                        deltaVertices, deltaNormals, deltaTangents);
                        for (int k = startVertex; k <= endVertex; k++)
                        {
                            var vIndex = vertMap[k];
                            if (vIndex < 0)
                            {
                                continue;
                            }
                            newDeltaVertices[vIndex] = deltaVertices[k];
                            newDeltaNormals[vIndex]  = deltaNormals[k];
                            newDeltaTangents[vIndex] = deltaTangents[k];
                        }
                        ret.AddBlendShapeFrame(shapeName, weight,
                                               newDeltaVertices, newDeltaNormals, newDeltaTangents);
                    }
                }
                Profiler.EndSample();
            }

            ret.UploadMeshData(true);

            Profiler.EndSample();
            return(ret);
        }