/// <summary>
 /// Check our cached previous simulations and see if we can skip the simulation process
 /// </summary>
 private bool CheckCached(ClippingProtectorSetup Check)
 {
     foreach (ClippingProtectorSetup cs in CachedResults.Keys)
     {
         if (cs.SetupEqual(Check))
         {
             OriginalMeshes = new Dictionary <SkinnedMeshRenderer, Mesh>();
             if (DebugLevel != CharClipDebugLevel.None)
             {
                 Debug.Log("Existing simulation found!");
             }
             List <Mesh> NewMeshes = CachedResults[cs].FinalMeshes;
             int         Ind       = 0;
             foreach (SkinnedMeshRenderer smr in Meshes)
             {
                 if (smr == null || smr.sharedMesh == null)
                 {
                     continue;
                 }
                 OriginalMeshes.Add(smr, smr.sharedMesh);
                 smr.sharedMesh = NewMeshes[Ind];
                 Ind++;
             }
             return(true);
         }
     }
     return(false);
 }
    public static CharacterClippingScriptableResult SaveOutToCache(ClippingProtectorSetup Setup, ClippingProtectorResult Result)
    {
        CharacterClippingScriptableResult Existing = TryGetExisting(Setup);

        if (Existing != null)
        {
            Debug.Log("Existing save found for Character Clipping Simulation");
            return(Existing);
        }
        CharacterClippingScriptableResult CCR = CharacterClippingScriptableResult.CreateInstance <CharacterClippingScriptableResult>();
        string ScriptableName = "CacheResult_" + System.DateTime.Now.ToString("dd_MM_yyyy_hh_mm_ss_ms");

        CheckDirExists(ScriptableName);
        //Make sure results are saved as proper meshes
        foreach (Mesh m in Result.FinalMeshes)
        {
            AssetDatabase.CreateAsset(m, "Assets/Resources/CharacterClippingCache/" + ScriptableName + "/" + m.name + "_" + ScriptableName + ".asset");
        }
        //Save out the asset
        UnityEditor.AssetDatabase.CreateAsset(CCR, "Assets/Resources/CharacterClippingCache/" + ScriptableName + "/" + ScriptableName + ".asset");
        CCR.Result = Result;
        CCR.Setup  = Setup;
        UnityEditor.EditorUtility.SetDirty(CCR);
        UnityEditor.AssetDatabase.SaveAssets();
        Debug.Log("Saved out Character Clipping Simulation");
        return(CCR);
    }
    public static ClippingProtectorResult TryLoadCachedResult(ClippingProtectorSetup Setup)
    {
        CharacterClippingScriptableResult Exist = TryGetExisting(Setup);

        if (Exist != null)
        {
            return(Exist.Result);
        }
        return(new ClippingProtectorResult());
    }
 public static CharacterClippingScriptableResult TryGetExisting(ClippingProtectorSetup Setup)
 {
     InitCachedResults();
     foreach (CharacterClippingScriptableResult Res in AllRes)
     {
         if (Setup.SetupEqual(Res.Setup))
         {
             return(Res);
         }
     }
     return(null);
 }
    public bool SetupEqual(object obj)
    {
        if (!(obj is ClippingProtectorSetup))
        {
            return(false);
        }
        ClippingProtectorSetup mys = (ClippingProtectorSetup)obj;

        // Compare setup variables
        if (OutCheckDistance != mys.OutCheckDistance)
        {
            return(false);
        }
        if (InCheckDistance != mys.InCheckDistance)
        {
            return(false);
        }
        if (MarginDistance != mys.MarginDistance)
        {
            return(false);
        }
        if (LowerChain != mys.LowerChain)
        {
            return(false);
        }
        //Compare mesh lists
        if (InputMeshes.Count != mys.InputMeshes.Count)
        {
            return(false);
        }
        var firstNotSecond = InputMeshes.Except(mys.InputMeshes).ToList();
        var secondNotFirst = mys.InputMeshes.Except(InputMeshes).ToList();

        if (firstNotSecond.Any() && secondNotFirst.Any())
        {
            return(false);
        }
        //Success
        return(true);
    }
Esempio n. 6
0
    /// <summary>
    /// Check our cached previous simulations and see if we can skip the simulation process
    /// </summary>
    private bool CheckCached(ClippingProtectorSetup Check)
    {
        //Check local cached
        foreach (ClippingProtectorSetup cs in CachedResults.Keys)
        {
            if (cs.SetupEqual(Check))
            {
                List <Mesh> NewMeshes = CachedResults[cs].FinalMeshes;
                SetFromCachedMeshes(NewMeshes);
                return(true);
            }
        }
        //Check Saved cache scriptbales
        ClippingProtectorResult Res = CharacterClippingScriptableResult.TryLoadCachedResult(Check);

        if (Res.FinalMeshes != null && Res.FinalMeshes.Count > 0)
        {
            SetFromCachedMeshes(Res.FinalMeshes);
            return(true);
        }
        return(false);
    }
Esempio n. 7
0
    /// <summary>
    /// Main method. Runs a raycast simulation and hides parts of mesh that are obscured.
    /// NOTE has to be IEnumerator otherwise created collision meshes do not provide any raycast result on same frame.
    /// </summary>
    public IEnumerator RunClippingSimulation(Action OnSimulationComplete = null)
    {
        //TODO best to run in T or A pose!
        //TODO make sure that we are fully reset the meshes before re running!!

        //Make sure we are working with the propper meshes and not already partially hidden
        ResetMeshesToOriginal();

        //Check our cache to see if we have already run
        if (CacheResults)
        {
            List <Mesh> CheckValues = new List <Mesh>();
            foreach (SkinnedMeshRenderer smr in Meshes)
            {
                if (smr == null || smr.sharedMesh == null)
                {
                    continue;
                }
                CheckValues.Add(smr.sharedMesh);
            }
            ClippingProtectorSetup Check = new ClippingProtectorSetup
            {
                OutCheckDistance = OutwardCheckDistance,
                InputMeshes      = CheckValues,
                MarginDistance   = MarginDistance,
                InCheckDistance  = InwardCheckDistance,
                LowerChain       = PreventLowerChainItems
            };
            if (CheckCached(Check))
            {
                yield break;
            }
        }
        if (DebugLevel != CharClipDebugLevel.None)
        {
            Debug.Log("Could not find cached simulation. Running clipping check.");
        }

        //Create collider meshes that we can test against
        for (int i = 0; i < Colliders.Count; i++)
        {
            DestroyImmediate(Colliders[i]);
        }
        Colliders = new List <GameObject>();
        CreateColliders(Colliders);
        yield return(null); //REQUIRED!

        //Foreach mesh in meshes check occlude
        int         Index       = 0;
        List <Mesh> FinalMeshes = new List <Mesh>();

        foreach (SkinnedMeshRenderer smr in Meshes)
        {
            if (smr == null || smr.sharedMesh == null)
            {
                continue;
            }

            //Setup so we dont trigger ourselves or any mesh lower down the chain
            if (PreventLowerChainItems)
            {
                Colliders[Index].gameObject.SetActive(false);
                yield return(null);
            }
            //if(Index > 0) { Colliders[Index - 1].gameObject.SetActive(true); }
            OriginalMeshes.Add(smr, smr.sharedMesh);

            //Raycast for results
            bool[] Results = RaycastToFindOverlap(Colliders, Index);

            //If we have nothing to hide then no point to change the mesh etc!
            if (!Results.Contains(true))
            {
                FinalMeshes.Add(smr.sharedMesh); continue;
            }

            //Identify the triangles that we no longer want and remove them
            CalculateNewTrisJob newJob = new CalculateNewTrisJob {
                NewTris      = new NativeList <int>(Allocator.TempJob),
                OriginalTris = new NativeArray <int>(smr.sharedMesh.triangles, Allocator.TempJob),
                Results      = new NativeArray <bool>(Results, Allocator.TempJob)
            };
            newJob.Schedule().Complete();
            if (RunAsynch == AsyncHarshness.Harsh)
            {
                yield return(null);
            }

            //Setup instance mesh ready for hiding elements
            Mesh newm = Instantiate(smr.sharedMesh);
            newm.triangles = newJob.NewTris.ToArray();
            newm.name      = "Clone_" + smr.sharedMesh.name;
            smr.sharedMesh = newm;
            FinalMeshes.Add(newm);

            //Finalise
            newJob.Cleanup();
            Index++;

            if (RunAsynch == AsyncHarshness.Soft)
            {
                yield return(null);
            }
        }
        //Clear up old junk colliders
        for (int i = 0; i < Colliders.Count; i++)
        {
            DestroyImmediate(Colliders[i]);
        }

        //Add result to cache for quick rerun of any future meshes
        if (CacheResults)
        {
            LastSetup = new ClippingProtectorSetup
            {
                OutCheckDistance = OutwardCheckDistance,
                InputMeshes      = OriginalMeshes.Values.ToList(),
                MarginDistance   = MarginDistance,
                InCheckDistance  = InwardCheckDistance,
                LowerChain       = PreventLowerChainItems
            };

            CachedResults.Add(LastSetup,
                              new ClippingProtectorResult
            {
                FinalMeshes = FinalMeshes
            });
        }

        //Notify of completion
        if (OnSimulationComplete != null)
        {
            OnSimulationComplete.Invoke();
        }
    }