123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190 |
- /*
- Copyright (c) 2020 Omar Duarte
- Unauthorized copying of this file, via any medium is strictly prohibited.
- Writen by Omar Duarte, 2020.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- THE SOFTWARE.
- */
- using System.Linq;
- using UnityEngine;
- namespace PluginMaster
- {
- public static class MeshUtils
- {
- public static bool IsPrimitive(Mesh mesh)
- {
- var assetPath = UnityEditor.AssetDatabase.GetAssetPath(mesh);
- return assetPath.Length < 6 ? false : assetPath.Substring(0, 6) != "Assets";
- }
- public static Collider AddCollider(Mesh mesh, GameObject target)
- {
- Collider collider = null;
- void AddMeshCollider()
- {
- var meshCollider = target.AddComponent<MeshCollider>();
- meshCollider.sharedMesh = mesh;
- collider = meshCollider;
- }
- if (IsPrimitive(mesh))
- {
- if (mesh.name == "Sphere") collider = target.AddComponent<SphereCollider>();
- else if (mesh.name == "Capsule") collider = target.AddComponent<CapsuleCollider>();
- else if (mesh.name == "Cube") collider = target.AddComponent<BoxCollider>();
- else if (mesh.name == "Plane") AddMeshCollider();
- }
- else AddMeshCollider();
- return collider;
- }
- public static GameObject[] FindFilters(LayerMask mask, GameObject[] exclude = null, bool excludeColliders = true)
- {
- var objects = new System.Collections.Generic.HashSet<GameObject>();
- #if UNITY_2022_2_OR_NEWER
- var meshFilters = GameObject.FindObjectsByType<MeshFilter>(FindObjectsSortMode.None);
- var skinnedMeshes = GameObject.FindObjectsByType<SkinnedMeshRenderer>(FindObjectsSortMode.None);
- #else
- var meshFilters = GameObject.FindObjectsOfType<MeshFilter>();
- var skinnedMeshes = GameObject.FindObjectsOfType<SkinnedMeshRenderer>();
- #endif
- objects.UnionWith(meshFilters.Select(comp => comp.gameObject));
- objects.UnionWith(skinnedMeshes.Select(comp => comp.gameObject));
- var filterList = new System.Collections.Generic.List<GameObject>(objects);
- if (exclude != null)
- {
- filterList = new System.Collections.Generic.List<GameObject>(objects.Except(exclude));
- objects = new System.Collections.Generic.HashSet<GameObject>(filterList);
- }
- if (excludeColliders)
- {
- #if UNITY_2022_2_OR_NEWER
- var colliders = GameObject.FindObjectsByType<Collider>(FindObjectsSortMode.None);
- #else
- var colliders = GameObject.FindObjectsOfType<Collider>();
- #endif
- var collidersSet
- = new System.Collections.Generic.HashSet<GameObject>(colliders.Select(comp => comp.gameObject));
- filterList = new System.Collections.Generic.List<GameObject>(objects.Except(collidersSet));
- }
- filterList = filterList.Where(obj => (mask.value & (1 << obj.layer)) != 0).ToList();
- return filterList.ToArray();
- }
- private static System.Reflection.MethodInfo intersectRayMesh = null;
- public static bool Raycast(Ray ray, out RaycastHit hitInfo,
- out GameObject collider, GameObject[] filters, float maxDistance,
- bool sameOriginAsRay = true, Vector3 origin = new Vector3())
- {
- collider = null;
- hitInfo = new RaycastHit();
- if (intersectRayMesh == null)
- {
- var editorTypes = typeof(UnityEditor.Editor).Assembly.GetTypes();
- var type_HandleUtility = editorTypes.FirstOrDefault(t => t.Name == "HandleUtility");
- intersectRayMesh = type_HandleUtility.GetMethod("IntersectRayMesh",
- System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
- }
- var minDistance = float.MaxValue;
- var result = false;
- foreach (var filter in filters)
- {
- if (filter == null) continue;
- var meshFilter = filter.GetComponent<MeshFilter>();
- Mesh mesh;
- if (meshFilter == null)
- {
- var skinnedMeshRenderer = filter.GetComponent<SkinnedMeshRenderer>();
- if (skinnedMeshRenderer == null) continue;
- mesh = skinnedMeshRenderer.sharedMesh;
- }
- else if (meshFilter.sharedMesh == null) continue;
- else mesh = meshFilter.sharedMesh;
- var parameters = new object[] { ray, mesh, filter.transform.localToWorldMatrix, null };
- if ((bool)intersectRayMesh.Invoke(null, parameters))
- {
- if (sameOriginAsRay)
- {
- if (hitInfo.distance > maxDistance) continue;
- }
- else
- {
- var hitInfoDistance = (hitInfo.point - origin).magnitude;
- if (hitInfoDistance > maxDistance) continue;
- }
- result = true;
- var hit = (RaycastHit)parameters[3];
- var hitDistance = hit.distance;
- if (!sameOriginAsRay) hitDistance = (hit.point - origin).magnitude;
- if (hitDistance < minDistance)
- {
- collider = filter;
- minDistance = hitDistance;
- hitInfo = hit;
- }
- }
- }
- if (result)
- {
- hitInfo.normal = hitInfo.normal.normalized;
- }
- return result;
- }
- public static bool Raycast(Vector3 origin, Vector3 direction,
- out RaycastHit hitInfo, out GameObject collider, GameObject[] filters, float maxDistance)
- {
- var ray = new Ray(origin, direction);
- return Raycast(ray, out hitInfo, out collider, filters, maxDistance);
- }
- public static bool RaycastAll(Ray ray, out RaycastHit[] hitInfo,
- out GameObject[] colliders, GameObject[] filters, float maxDistance)
- {
- System.Collections.Generic.List<RaycastHit> hitInfoList = new System.Collections.Generic.List<RaycastHit>();
- System.Collections.Generic.List<GameObject> colliderList = new System.Collections.Generic.List<GameObject>();
- if (intersectRayMesh == null)
- {
- var editorTypes = typeof(UnityEditor.Editor).Assembly.GetTypes();
- var type_HandleUtility = editorTypes.FirstOrDefault(t => t.Name == "HandleUtility");
- intersectRayMesh = type_HandleUtility.GetMethod("IntersectRayMesh",
- System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
- }
- foreach (var filter in filters)
- {
- if (filter == null) continue;
- var meshFilter = filter.GetComponent<MeshFilter>();
- Mesh mesh;
- if (meshFilter == null)
- {
- var skinnedMeshRenderer = filter.GetComponent<SkinnedMeshRenderer>();
- if (skinnedMeshRenderer == null) continue;
- mesh = skinnedMeshRenderer.sharedMesh;
- }
- else if (meshFilter.sharedMesh == null) continue;
- else mesh = meshFilter.sharedMesh;
- var parameters = new object[] { ray, mesh, filter.transform.localToWorldMatrix, null };
- if ((bool)intersectRayMesh.Invoke(null, parameters))
- {
- var hit = (RaycastHit)parameters[3];
- if (hit.distance > maxDistance) continue;
- hitInfoList.Add(hit);
- colliderList.Add(filter);
- }
- }
- hitInfo = hitInfoList.ToArray();
- colliders = colliderList.ToArray();
- return hitInfoList.Count > 0;
- }
- }
- }
|