예제 #1
0
        public void Awake()
        {
                        #if UNITY_WEBGL
            if (workerThreadMode == WorkerThreadMode.Asynchronous)
            {
                Debug.LogWarning("Turbo Slicer will run synchronously because WebGL does not support threads.", this);
                workerThreadMode = WorkerThreadMode.Synchronous;
            }
                        #endif

            if (preloadMeshes != null)
            {
                for (int i = 0; i < preloadMeshes.Length; i++)
                {
                    var mesh    = preloadMeshes [i];
                    var indices = new int[mesh.subMeshCount][];
                    for (int j = 0; j < mesh.subMeshCount; j++)
                    {
                        indices [j] = mesh.GetIndices(j);
                    }
                    //Not that we don't pull the tangents at all.
                    var rom = new MeshSnapshot(null, mesh.vertices, mesh.normals, mesh.uv, mesh.uv2, mesh.tangents, indices, null, Matrix4x4.identity);
                    preloadedMeshes [mesh.GetInstanceID()] = rom;
                }
            }
        }
예제 #2
0
        private void Slice(GameObject subject, Vector4 planeInLocalSpace, int shatterStep, bool destroyOriginal)
        {
            if (subject == null)
            {
                throw new System.ArgumentNullException();
            }

            //Sanity check: are we already slicing this?
            foreach (var jobState in jobStates)
            {
                if (object.ReferenceEquals(jobState.Specification.Subject, subject))
                {
                    return;
//					Debug.Log ("Turbo Slicer was asked to slice '{0}' but this target is already enqueued.", subject.name);
                }
            }

            //If names in the hierarchy are replicated anywhere than we have a problem.

            transformBuffer.Clear();
            concatenateHierarchy(subject.transform, transformBuffer);
            nameBuffer.Clear();
            foreach (var t in transformBuffer)
            {
                nameBuffer.Add(t.gameObject.name);
            }
            if (nameBuffer.Count != transformBuffer.Count)
            {
                Debug.LogWarning("Turbo Slicer needs each object under its hierarchy to have a unique name.", subject);
                return;
            }

            var sliceable = subject.GetComponent <Sliceable> ();

            bool channelTangents, channelNormals, channelUV2;

            if (sliceable != null)
            {
                channelNormals  = sliceable.channelNormals;
                channelTangents = sliceable.channelTangents;
                channelUV2      = sliceable.channelUV2;
            }
            else
            {
                channelTangents = false;
                channelNormals  = true;
                channelUV2      = false;
            }

            var renderers = subject.GetComponentsInChildren <Renderer>();

            IEnumerable <MeshSnapshot> snapshots;

            var forwardPassAgent = subject.GetComponent <ForwardPassAgent> ();

            if (forwardPassAgent != null)
            {
                snapshots = forwardPassAgent.Snapshots;
            }
            else
            {
                var snapshotsBuilder = new List <MeshSnapshot>();

                foreach (var renderer in renderers)
                {
                    Mesh mesh;
                    bool meshIsABufferMesh;

                    if (renderer is MeshRenderer)
                    {
                        var filter = renderer.GetComponent <MeshFilter> ();
                        mesh = filter.sharedMesh;
                        meshIsABufferMesh = false;
                    }
                    else if (renderer is SkinnedMeshRenderer)
                    {
                        var smr = (SkinnedMeshRenderer)renderer;
                        meshIsABufferMesh = true;
                        mesh = new Mesh();
                        smr.BakeMesh(mesh);
                    }
                    else
                    {
                        throw new System.NotImplementedException("Turbo Slicer encountered a Renderer that is neither a MeshRenderer nor a SkinnedMeshRenderer");
                    }

                    var rootToLocalTransform = renderer.transform.worldToLocalMatrix * subject.transform.localToWorldMatrix;

                    var unitRect    = new Rect(0.0f, 0.0f, 1.0f, 1.0f);
                    var infillRects = new Rect[mesh.subMeshCount];

                    for (int i = 0; i < infillRects.Length; i++)
                    {
                        Rect?rect = null;
                        if (renderer.sharedMaterials.Length > i)
                        {
                            var mat = renderer.sharedMaterials [i];
                            if (sliceable != null)
                            {
                                for (int j = 0; j < sliceable.infillers.Length; j++)
                                {
                                    var ifc = sliceable.infillers [j];
                                    if (object.ReferenceEquals(ifc.material, mat))
                                    {
                                        rect = ifc.regionForInfill;
                                    }
                                }
                            }
                            infillRects [i] = rect.GetValueOrDefault(unitRect);
                        }
                    }

                    var isThisTheRoot = renderer.gameObject == subject;
                    var key           = isThisTheRoot ? MeshSnapshot.RootKey : renderer.gameObject.name;

                    MeshSnapshot snapshot;

                    if (preloadedMeshes.TryGetValue(mesh.GetInstanceID(), out snapshot) == false)
                    {
                        if (mesh.isReadable == false)
                        {
                            Debug.LogErrorFormat(subject, "Turbo Slicer needs to read mesh '{0}' on object '{1}', but cannot. If this object is " +
                                                 "an original, go to its mesh and enable readability. If this object is a slice result, go to the " +
                                                 "sliceable configuration on the original and turn on 'shreddable.", mesh.name, subject.name);
                            return;
                        }

                        var indices = new int[mesh.subMeshCount][];
                        for (int i = 0; i < mesh.subMeshCount; i++)
                        {
                            indices [i] = mesh.GetIndices(i);
                        }
                        var coords = mesh.uv;
                        if (coords == null || coords.Length < mesh.vertexCount)
                        {
                            //These might be null or empty but the core doesn't have a branch for UVs. So we'll put some junk in there if we need to.
                            coords = new Vector2[mesh.vertexCount];
                        }

                        snapshot = new MeshSnapshot(
                            key,
                            mesh.vertices,
                            channelNormals ? mesh.normals : new Vector3[0],
                            coords,
                            channelUV2 ? mesh.uv2 : new Vector2[0],
                            channelTangents ? mesh.tangents : new Vector4[0],
                            indices,
                            infillRects,
                            rootToLocalTransform);
                    }
                    else
                    {
                        snapshot = new MeshSnapshot(
                            key,
                            snapshot.vertices,
                            channelNormals ? snapshot.normals : new Vector3[0],
                            snapshot.coords,
                            channelUV2 ? snapshot.coords2 : new Vector2[0],
                            channelTangents ? snapshot.tangents : new Vector4[0],
                            snapshot.indices,
                            infillRects,
                            rootToLocalTransform);
                    }

                    if (meshIsABufferMesh)
                    {
                        GameObject.DestroyImmediate(mesh);
                    }

                    snapshotsBuilder.Add(snapshot);
                }

                snapshots = snapshotsBuilder;
            }

            var jobSpec = new JobSpecification(subject, snapshots, planeInLocalSpace, channelTangents, channelNormals, channelUV2, shatterStep, destroyOriginal);

            try {
                var jobState = new JobState(jobSpec);

                switch (workerThreadMode)
                {
                case WorkerThreadMode.Asynchronous:
                    jobStates.Add(jobState);
                                        #if NETFX_CORE && !UNITY_EDITOR
                    System.Threading.Tasks.Task.Factory.StartNew(ThreadSafeSlice.Slice, jobState);
                                        #else
                    System.Threading.ThreadPool.QueueUserWorkItem(ThreadSafeSlice.Slice, jobState);
                                        #endif
                    break;

                case WorkerThreadMode.Synchronous:
                    ThreadSafeSlice.Slice(jobState);
                    if (jobState.HasYield)
                    {
                        ConsumeJobYield(jobState.Specification, jobState.Yield);
                    }
                    else if (jobState.HasException)
                    {
                        throw jobState.Exception;
                    }
                    break;

                default:
                    throw new System.NotImplementedException();
                }
            } catch (System.Exception ex) {
                Debug.LogException(ex, subject);
            }
        }
예제 #3
0
        private void Slice(GameObject subject, Vector4 planeInLocalSpace, int shatterStep, bool destroyOriginal)
        {
            bool passSanityCheck = true;

            if (subject == null)
            {
                throw new System.ArgumentNullException();
            }

            //Sanity check: are we already slicing this?
            foreach (var jobState in jobStates)
            {
                if (object.ReferenceEquals(jobState.Specification.Subject, subject))
                {
                    passSanityCheck = false;
                    Debug.LogErrorFormat("Turbo Slicer was asked to slice '{0}' but this target is already enqueued.", subject.name);
                }
            }

            if (passSanityCheck)
            {
                var        sliceable = subject.GetComponent <Sliceable> ();
                GameObject meshHolder;

                bool channelTangents, channelNormals, channelUV2;

                if (sliceable != null)
                {
                    channelNormals  = sliceable.channelNormals;
                    channelTangents = sliceable.channelTangents;
                    channelUV2      = sliceable.channelUV2;
                }
                else
                {
                    channelTangents = false;
                    channelNormals  = true;
                    channelUV2      = false;
                }

                if (sliceable != null && sliceable.explicitlySelectedMeshHolder != null)
                {
                    meshHolder = sliceable.explicitlySelectedMeshHolder;
                }
                else
                {
                    meshHolder = subject;
                }

                var renderer = meshHolder.GetComponent <Renderer> ();

                MeshSnapshot snapshot;

                var forwardPassAgent = meshHolder.GetComponent <ForwardPassAgent> ();

                if (forwardPassAgent != null)
                {
                    snapshot = forwardPassAgent.Snapshot;
                }
                else
                {
                    Mesh mesh;
                    bool meshIsABufferMesh;

                    if (renderer is MeshRenderer)
                    {
                        var filter = meshHolder.GetComponent <MeshFilter> ();
                        mesh = filter.sharedMesh;
                        meshIsABufferMesh = false;
                    }
                    else if (renderer is SkinnedMeshRenderer)
                    {
                        var smr = (SkinnedMeshRenderer)renderer;
                        meshIsABufferMesh = true;
                        mesh = new Mesh();
                        smr.BakeMesh(mesh);
                    }
                    else
                    {
                        throw new System.NotImplementedException("Turbo Slicer encountered a Renderer that is neither a MeshRenderer nor a SkinnedMeshRenderer");
                    }

                    var unitRect    = new Rect(0.0f, 0.0f, 1.0f, 1.0f);
                    var infillRects = new Rect[mesh.subMeshCount];

                    for (int i = 0; i < infillRects.Length; i++)
                    {
                        Rect?rect = null;
                        if (renderer.sharedMaterials.Length > i)
                        {
                            var mat = renderer.sharedMaterials [i];
                            if (sliceable != null)
                            {
                                for (int j = 0; j < sliceable.infillers.Length; j++)
                                {
                                    var ifc = sliceable.infillers [j];
                                    if (object.ReferenceEquals(ifc.material, mat))
                                    {
                                        rect = ifc.regionForInfill;
                                    }
                                }
                            }
                            infillRects [i] = rect.GetValueOrDefault(unitRect);
                        }
                    }

                    if (preloadedMeshes.TryGetValue(mesh.GetInstanceID(), out snapshot) == false)
                    {
                        var indices = new int[mesh.subMeshCount][];
                        for (int i = 0; i < mesh.subMeshCount; i++)
                        {
                            indices [i] = mesh.GetIndices(i);
                        }
                        //Not that we don't pull the tangents at all.
                        snapshot = new MeshSnapshot(
                            mesh.vertices,
                            channelNormals ? mesh.normals : new Vector3[0],
                            mesh.uv,
                            channelUV2 ? mesh.uv2 : new Vector2[0],
                            channelTangents ? mesh.tangents : new Vector4[0],
                            indices,
                            infillRects);
                    }
                    else
                    {
                        snapshot = new MeshSnapshot(
                            snapshot.vertices,
                            channelNormals ? snapshot.normals : new Vector3[0],
                            snapshot.coords,
                            channelUV2 ? snapshot.coords2 : new Vector2[0],
                            channelTangents ? snapshot.tangents : new Vector4[0],
                            snapshot.indices,
                            infillRects);
                    }

                    if (meshIsABufferMesh)
                    {
                        GameObject.DestroyImmediate(mesh);
                    }
                }

                var jobSpec = new JobSpecification(subject, snapshot, planeInLocalSpace, channelTangents, channelNormals, channelUV2, shatterStep, destroyOriginal);

                try {
                    var jobState = new JobState(jobSpec);

                    switch (workerThreadMode)
                    {
                    case WorkerThreadMode.Asynchronous:
                        jobStates.Add(jobState);
                        System.Threading.ThreadPool.QueueUserWorkItem(ThreadSafeSlice.Slice, jobState);
                        break;

                    case WorkerThreadMode.Synchronous:
                        ThreadSafeSlice.Slice(jobState);
                        if (jobState.HasYield)
                        {
                            ConsumeJobYield(jobState.Specification, jobState.Yield);
                        }
                        else if (jobState.HasException)
                        {
                            throw jobState.Exception;
                        }
                        break;

                    default:
                        throw new System.NotImplementedException();
                    }
                } catch (System.Exception ex) {
                    Debug.LogException(ex, subject);
                }
            }
        }