Files
PrinceOfGlory/Assets/Third Party/SimpleLOD/Extensions/MeshExtensions.cs
kridoo 6e91a0c7f0 111
2025-09-15 17:32:08 +08:00

598 lines
20 KiB
C#

/* SimpleLOD 1.5a */
/* By Orbcreation BV */
/* Richard Knol */
/* March 18, 2015 */
/* Note: if you also use other packages by Orbcreation, */
/* you may end up with multiple copies of this file. */
/* In that case, better delete/merge those files into 1. */
using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
#if UNITY_WP8
#elif UNITY_WP_8_1
#elif UNITY_WSA
#elif UNITY_WSA_8_0
#elif UNITY_WSA_8_1
#elif UNITY_WINRT
#elif UNITY_WINRT_8_0
#elif UNITY_WINRT_8_1
#elif NETFX_CORE
#else
using System.Threading;
#endif
namespace OrbCreationExtensions
{
public static class MeshExtensions {
public static void RecalculateTangents(this Mesh mesh) {
int vertexCount = mesh.vertexCount;
Vector3[] vertices = mesh.vertices;
Vector3[] normals = mesh.normals;
Vector2[] texcoords = mesh.uv;
int[] triangles = mesh.triangles;
int triangleCount = triangles.Length/3;
Vector4[] tangents = new Vector4[vertexCount];
Vector3[] tan1 = new Vector3[vertexCount];
Vector3[] tan2 = new Vector3[vertexCount];
int tri = 0;
if(texcoords.Length<=0) return;
for (int i = 0; i < (triangleCount); i++) {
int i1 = triangles[tri];
int i2 = triangles[tri+1];
int i3 = triangles[tri+2];
Vector3 v1 = vertices[i1];
Vector3 v2 = vertices[i2];
Vector3 v3 = vertices[i3];
Vector2 w1 = texcoords[i1];
Vector2 w2 = texcoords[i2];
Vector2 w3 = texcoords[i3];
float x1 = v2.x - v1.x;
float x2 = v3.x - v1.x;
float y1 = v2.y - v1.y;
float y2 = v3.y - v1.y;
float z1 = v2.z - v1.z;
float z2 = v3.z - v1.z;
float s1 = w2.x - w1.x;
float s2 = w3.x - w1.x;
float t1 = w2.y - w1.y;
float t2 = w3.y - w1.y;
float div = s1 * t2 - s2 * t1;
float r = div == 0.0f ? 0.0f : 1.0f / div;
Vector3 sdir = new Vector3((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r);
Vector3 tdir = new Vector3((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r);
tan1[i1] += sdir;
tan1[i2] += sdir;
tan1[i3] += sdir;
tan2[i1] += tdir;
tan2[i2] += tdir;
tan2[i3] += tdir;
tri += 3;
}
for (int i = 0; i < (vertexCount); i++) {
Vector3 n = normals[i];
Vector3 t = tan1[i];
// Gram-Schmidt orthogonalize
Vector3.OrthoNormalize(ref n, ref t );
tangents[i].x = t.x;
tangents[i].y = t.y;
tangents[i].z = t.z;
// Calculate handedness
tangents[i].w = ( Vector3.Dot(Vector3.Cross(n, t), tan2[i]) < 0.0f ) ? -1.0f : 1.0f;
}
mesh.tangents = tangents;
}
public static Mesh ScaledRotatedTranslatedMesh(this Mesh mesh, Vector3 scale, Quaternion rotate, Vector3 translate) {
Mesh newMesh = (Mesh)Mesh.Instantiate(mesh);
Vector3[] vertices = newMesh.vertices;
Vector3[] normals = newMesh.normals;
bool rotateNormals = true;
if(normals == null || normals.Length < vertices.Length || rotate == Quaternion.identity) rotateNormals = false;
for(int i=0;i<vertices.Length;i++) {
vertices[i].x *= scale.x;
vertices[i].y *= scale.y;
vertices[i].z *= scale.z;
vertices[i] = rotate * vertices[i];
if(rotateNormals) normals[i] = rotate * normals[i];
vertices[i] += translate;
}
newMesh.vertices = vertices;
if(rotateNormals) newMesh.normals = normals;
newMesh.RecalculateBounds();
return newMesh;
}
public static bool IsSkinnedMesh(this Mesh mesh) {
return mesh.blendShapeCount > 0 || (mesh.bindposes != null && mesh.bindposes.Length > 0);
}
public static int GetTriangleCount(this Mesh orig) {
return orig.triangles.Length / 3;
}
public static Mesh MakeLODMesh(this Mesh orig, float aMaxWeight, bool recalcNormals, float removeSmallParts = 1f, float protectNormals = 1f, float protectUvs = 1f, float protectSubMeshesAndSharpEdges = 1f, float smallTrianglesFirst = 1f) {
return LODMaker.MakeLODMesh(orig, aMaxWeight, removeSmallParts, protectNormals, protectUvs, protectSubMeshesAndSharpEdges, smallTrianglesFirst, recalcNormals);
}
#if UNITY_WP8
#elif UNITY_WP_8_1
#elif UNITY_WSA
#elif UNITY_WSA_8_0
#elif UNITY_WSA_8_1
#elif UNITY_WINRT
#elif UNITY_WINRT_8_0
#elif UNITY_WINRT_8_1
#elif NETFX_CORE
#else
public static IEnumerator MakeLODMeshInBackground(this Mesh mesh, float maxWeight, bool recalcNormals, float removeSmallParts, System.Action<Mesh> result) {
Hashtable lodInfo = new Hashtable();
lodInfo["maxWeight"] = maxWeight;
lodInfo["removeSmallParts"] = removeSmallParts;
Vector3[] vs = mesh.vertices;
if(vs.Length <= 0) throw new ApplicationException("Mesh was empty");
Vector3[] ns = mesh.normals;
if(ns.Length == 0) { // mesh has no normals
mesh.RecalculateNormals();
ns = mesh.normals;
}
Vector2[] uv1s = mesh.uv;
Vector2[] uv2s = mesh.uv2;
#if UNITY_4_3
Vector2[] uv3s = new Vector2[0];
Vector2[] uv4s = new Vector2[0];
#elif UNITY_4_4
Vector2[] uv3s = new Vector2[0];
Vector2[] uv4s = new Vector2[0];
#elif UNITY_4_5
Vector2[] uv3s = new Vector2[0];
Vector2[] uv4s = new Vector2[0];
#elif UNITY_4_6
Vector2[] uv3s = new Vector2[0];
Vector2[] uv4s = new Vector2[0];
#else
Vector2[] uv3s = mesh.uv3;
Vector2[] uv4s = mesh.uv4;
#endif
Color32[] colors32 = mesh.colors32;
int[] ts = mesh.triangles;
Matrix4x4[] bindposes = mesh.bindposes;
BoneWeight[] bws = mesh.boneWeights;
int[] subMeshOffsets = new int[mesh.subMeshCount];
if(mesh.subMeshCount > 1) { // read triangles of submeshes 1 by 1 because I dont know the internal order of the mesh
for(int s=0;s<mesh.subMeshCount;s++) {
int[] subTs = mesh.GetTriangles(s);
int t=0;
for(;t<subTs.Length;t++) ts[subMeshOffsets[s] + t] = subTs[t];
if(s+1 < mesh.subMeshCount) subMeshOffsets[s+1] = subMeshOffsets[s] + t;
}
}
Bounds meshBounds = mesh.bounds;
lodInfo["vertices"] = vs;
lodInfo["normals"] = ns;
lodInfo["uv1s"] = uv1s;
lodInfo["uv2s"] = uv2s;
lodInfo["uv3s"] = uv3s;
lodInfo["uv4s"] = uv4s;
lodInfo["colors32"] = colors32;
lodInfo["triangles"] = ts;
lodInfo["bindposes"] = bindposes;
lodInfo["boneWeights"] = bws;
lodInfo["subMeshOffsets"] = subMeshOffsets;
lodInfo["meshBounds"] = meshBounds;
Thread thread = new Thread(LODMaker.MakeLODMeshInBackground);
thread.Start(lodInfo);
while(!lodInfo.ContainsKey("ready")) {
yield return new WaitForSeconds(0.2f);
}
result(LODMaker.CreateNewMesh((Vector3[])lodInfo["vertices"], (Vector3[])lodInfo["normals"], (Vector2[])lodInfo["uv1s"], (Vector2[])lodInfo["uv2s"], (Vector2[])lodInfo["uv3s"], (Vector2[])lodInfo["uv4s"], (Color32[])lodInfo["colors32"], (int[])lodInfo["triangles"], (BoneWeight[])lodInfo["boneWeights"], (Matrix4x4[])lodInfo["bindposes"], (int[])lodInfo["subMeshOffsets"], recalcNormals));
}
#endif
public static Mesh[] MakeLODMeshes(this Mesh mesh, float[] maxWeights, bool recalcNormals, float removeSmallParts = 1f, float protectNormals = 1f, float protectUvs = 1f, float protectSubMeshesAndSharpEdges = 1f, float smallTrianglesFirst = 1f, int nrOfSteps = 1) {
if(maxWeights.Length < 1) {
Debug.LogError("Mesh.GetLODLevelMeshes: maxWeights arrays is empty");
return null;
}
// Create LODs
Mesh[] lodMeshes = new Mesh[maxWeights.Length];
float prevWeight = 0f;
for(int i=0;i<maxWeights.Length;i++) {
if(nrOfSteps < 1) nrOfSteps = 1;
for(int s=0;s<nrOfSteps;s++) {
float weight = (maxWeights[i] - prevWeight);
mesh = mesh.MakeLODMesh(((float)(s+1) * (weight / nrOfSteps)) + prevWeight, recalcNormals, removeSmallParts, protectNormals, protectUvs, protectSubMeshesAndSharpEdges, smallTrianglesFirst);
}
prevWeight = maxWeights[i];
lodMeshes[i] = mesh;
}
return lodMeshes;
}
public static Vector4 GetUvRange(this Mesh mesh) {
Vector4 range = new Vector4(0,0,1,1);
Vector2[] uvs = mesh.uv;
for(int i=0;i<uvs.Length;i++) {
Vector2 uv = uvs[i];
if(uv.x < range.x) range.x = uv.x;
if(uv.y < range.y) range.y = uv.y;
if(uv.x > range.z) range.z = uv.x;
if(uv.y > range.w) range.w = uv.y;
}
return range;
}
public static bool CheckUvsWithin01Range(this Mesh mesh) {
Vector2[] uvs = mesh.uv;
for(int i=0;i<uvs.Length;i++) {
Vector2 uv = uvs[i];
if(uv.x<0f || uv.x > 1f || uv.y < 0f || uv.y > 1f) return false;
}
return true;
}
public static void ClampUvs(this Mesh mesh) {
Vector2[] uvs = mesh.uv;
for(int i=0;i<uvs.Length;i++) {
Vector2 uv = uvs[i];
uv.x = Mathf.Clamp01(uv.x);
uv.y = Mathf.Clamp01(uv.y);
uvs[i] = uv;
}
mesh.uv = uvs;
}
public static void WrapUvs(this Mesh mesh) {
Vector2[] uvs = mesh.uv;
for(int i=0;i<uvs.Length;i++) {
Vector2 uv = uvs[i];
while(uv.x>1f) uv.x-=1f;
while(uv.x<0f) uv.x+=1f;
while(uv.y>1f) uv.y-=1f;
while(uv.y<0f) uv.y+=1f;
uvs[i] = uv;
}
mesh.uv = uvs;
}
public static void SetAtlasRectForSubmesh(this Mesh mesh, Rect atlasRect, int submeshIndex) {
if(submeshIndex >= mesh.subMeshCount) return;
int[] tris = mesh.GetTriangles(submeshIndex);
List<int> uvsToMove = new List<int>();
for(int i=0;i<tris.Length;i++) {
int j = 0;
for(;j<uvsToMove.Count;j++) {
if(uvsToMove[j] == tris[i]) break;
}
if(j>=uvsToMove.Count) {
uvsToMove.Add(tris[i]);
}
}
Vector2[] uvs = mesh.uv;
for(int i=0;i<uvsToMove.Count;i++) {
Vector2 uv = uvs[uvsToMove[i]];
// when uv coordinates are outside of 0-1, the uv moves to a neighbouring texture
uv.x = (Mathf.Clamp01(uv.x) * atlasRect.width) + atlasRect.x;
uv.y = (Mathf.Clamp01(uv.y) * atlasRect.height) + atlasRect.y;
uvs[uvsToMove[i]] = uv;
}
mesh.uv = uvs;
}
public static void MergeSubmeshInto(this Mesh mesh, int from, int to) {
int[] fromTris = mesh.GetTriangles(from);
int[] toTris = mesh.GetTriangles(to);
List<int> newTris = new List<int>();
for(int i=0;i<toTris.Length;i++) newTris.Add(toTris[i]);
for(int i=0;i<fromTris.Length;i++) newTris.Add(fromTris[i]);
mesh.SetTriangles(newTris.ToArray(), to);
// move all submeshes 1 up
for(int i=from+1;i<mesh.subMeshCount;i++) {
mesh.SetTriangles(mesh.GetTriangles(i), i-1);
}
mesh.SetTriangles((int[])null, mesh.subMeshCount-1);
mesh.subMeshCount = mesh.subMeshCount-1;
}
public static Mesh CopyAndRemoveSubmeshes(this Mesh orig, int[] submeshesToRemove) {
Mesh mesh = (Mesh)Mesh.Instantiate(orig);
List<List<int>> submeshes = new List<List<int>>(mesh.subMeshCount);
List<Vector3> vs = new List<Vector3>(orig.vertices);
List<Vector3> ns = new List<Vector3>(orig.vertexCount);
List<Vector2> uv1s = new List<Vector2>(orig.vertexCount);
List<Vector2> uv2s = new List<Vector2>();
List<Vector2> uv3s = new List<Vector2>();
List<Vector2> uv4s = new List<Vector2>();
List<Color32> colors32 = new List<Color32>();
List<BoneWeight> bws = new List<BoneWeight>();
ns.AddRange(orig.normals);
uv1s.AddRange(orig.uv);
uv2s.AddRange(orig.uv2);
#if UNITY_4_3
#elif UNITY_4_4
#elif UNITY_4_5
#elif UNITY_4_6
#else
uv3s.AddRange(orig.uv3);
uv4s.AddRange(orig.uv4);
#endif
colors32.AddRange(orig.colors32);
bws.AddRange(orig.boneWeights);
for(int s=0;s<mesh.subMeshCount;s++) {
bool remove = false;
for(int i=0;i<submeshesToRemove.Length;i++) {
if(submeshesToRemove[i] == s) remove = true;
}
if(!remove) {
List<int> submesh = new List<int>();
submesh.AddRange(mesh.GetTriangles(s));
submeshes.Add(submesh);
}
}
LODMaker.RemoveUnusedVertices(vs, ns, uv1s, uv2s, uv3s, uv4s, colors32, bws, submeshes);
#if UNITY_4_3
#elif UNITY_4_4
#elif UNITY_4_5
#elif UNITY_4_6
#else
mesh.uv4 = null;
mesh.uv3 = null;
#endif
mesh.uv2 = null;
mesh.uv2 = null;
mesh.boneWeights = null;
mesh.colors32 = null;
mesh.normals = null;
mesh.tangents = null;
mesh.triangles = null;
mesh.vertices = vs.ToArray();
if(ns.Count>0) mesh.normals = ns.ToArray();
if(uv1s.Count>0) mesh.uv = uv1s.ToArray();
if(uv2s.Count>0) mesh.uv2 = uv2s.ToArray();
#if UNITY_4_3
#elif UNITY_4_4
#elif UNITY_4_5
#elif UNITY_4_6
#else
if(uv3s.Count>0) mesh.uv3 = uv3s.ToArray();
if(uv4s.Count>0) mesh.uv4 = uv4s.ToArray();
#endif
if(colors32.Count>0) mesh.colors32 = colors32.ToArray();
if(bws.Count>0) mesh.boneWeights = bws.ToArray();
mesh.subMeshCount = submeshes.Count;
for(int s=0;s<submeshes.Count;s++) {
mesh.SetTriangles(submeshes[s].ToArray(), s);
}
if(ns == null || ns.Count <= 0) mesh.RecalculateNormals();
RecalculateTangents(mesh);
mesh.RecalculateBounds();
return mesh;
}
public static Mesh CopyAndRemoveHiddenTriangles(this Mesh orig, int subMeshIdx, Matrix4x4 localToWorldMatrix, Mesh[] hidingMeshes, int[] hidingSubMeshes, Matrix4x4[] hidingLocalToWorldMatrices, float maxRemoveDistance = 0.01f) {
if(subMeshIdx >= orig.subMeshCount) return null;
if(hidingMeshes.Length <= 0) return null;
if(hidingMeshes.Length != hidingSubMeshes.Length || hidingMeshes.Length != hidingLocalToWorldMatrices.Length) return null;
// copy orig mesh and get everything in Lists
Mesh mesh = (Mesh)Mesh.Instantiate(orig);
List<List<int>> submeshes = new List<List<int>>(mesh.subMeshCount);
List<Vector3> vs = new List<Vector3>(orig.vertices);
List<Vector3> ns = new List<Vector3>(orig.vertexCount);
List<Vector2> uv1s = new List<Vector2>(orig.vertexCount);
List<Vector2> uv2s = new List<Vector2>();
List<Vector2> uv3s = new List<Vector2>();
List<Vector2> uv4s = new List<Vector2>();
List<Color32> colors32 = new List<Color32>();
List<BoneWeight> bws = new List<BoneWeight>();
ns.AddRange(orig.normals);
if(ns == null || ns.Count <= 0) {
orig.RecalculateNormals();
ns.AddRange(orig.normals);
}
uv1s.AddRange(orig.uv);
uv2s.AddRange(orig.uv2);
#if UNITY_4_3
#elif UNITY_4_4
#elif UNITY_4_5
#elif UNITY_4_6
#else
uv3s.AddRange(orig.uv3);
uv4s.AddRange(orig.uv4);
#endif
colors32.AddRange(orig.colors32);
bws.AddRange(orig.boneWeights);
for(int s=0;s<orig.subMeshCount;s++) {
List<int> submesh = new List<int>();
submesh.AddRange(orig.GetTriangles(s));
submeshes.Add(submesh);
}
List<int> ts = submeshes[subMeshIdx];
// Make combined arrays for triangles/vertices/normals in hiding meshes
List<Vector3> hidingVs = new List<Vector3>();
List<int> hidingTs = new List<int>();
Mesh prevMesh = null;
int triOffset = 0;
int prevHvsCount = 0;
for(int h=0;h<hidingMeshes.Length;h++) {
Mesh hidingMesh = hidingMeshes[h];
int[] hts = hidingMesh.GetTriangles(hidingSubMeshes[h]);
if(prevMesh != hidingMesh) triOffset += prevHvsCount;
for(int i=0;i<hts.Length;i++) {
hidingTs.Add(hts[i]+triOffset);
}
if(prevMesh != hidingMesh) {
Matrix4x4 hidingMatrix = hidingLocalToWorldMatrices[h];
Vector3[] hvs = hidingMesh.vertices;
for(int i=0;i<hvs.Length;i++) {
hidingVs.Add(hidingMatrix.MultiplyPoint3x4(hvs[i])); // vertex in world coordinates
}
prevHvsCount = hvs.Length;
prevMesh = hidingMesh;
}
}
// get bounding box per triangle
List<Vector3> triMinCorners = new List<Vector3>();
List<Vector3> triMaxCorners = new List<Vector3>();
for(int t=0;t<hidingTs.Count;t+=3) {
Vector3 v0 = hidingVs[hidingTs[t]];
Vector3 v1 = hidingVs[hidingTs[t+1]];
Vector3 v2 = hidingVs[hidingTs[t+2]];
triMinCorners.Add(new Vector3(Mathf.Min(Mathf.Min(v0.x, v1.x), v2.x), Mathf.Min(Mathf.Min(v0.y, v1.y), v2.y), Mathf.Min(Mathf.Min(v0.z, v1.z), v2.z)));
triMaxCorners.Add(new Vector3(Mathf.Max(Mathf.Max(v0.x, v1.x), v2.x), Mathf.Max(Mathf.Max(v0.y, v1.y), v2.y), Mathf.Max(Mathf.Max(v0.z, v1.z), v2.z)));
}
List<int> newTs = new List<int>();
for(int t=0;t<ts.Count;t+=3) {
// we use vertices in world coordinates
Vector3 v0 = localToWorldMatrix.MultiplyPoint3x4(vs[ts[t]]);
Vector3 v1 = localToWorldMatrix.MultiplyPoint3x4(vs[ts[t+1]]);
Vector3 v2 = localToWorldMatrix.MultiplyPoint3x4(vs[ts[t+2]]);
if(!IsTriangleHidden(v0, v1, v2, maxRemoveDistance, triMinCorners, triMaxCorners, hidingVs, hidingTs)) {
newTs.Add(ts[t]);
newTs.Add(ts[t+1]);
newTs.Add(ts[t+2]);
}
}
// remove unused if anything deleted
submeshes[subMeshIdx] = newTs;
LODMaker.RemoveUnusedVertices(vs, ns, uv1s, uv2s, uv3s, uv4s, colors32, bws, submeshes);
// Fill new mesh
#if UNITY_4_3
#elif UNITY_4_4
#elif UNITY_4_5
#elif UNITY_4_6
#else
mesh.uv4 = null;
mesh.uv3 = null;
#endif
mesh.uv2 = null;
mesh.uv2 = null;
mesh.boneWeights = null;
mesh.colors32 = null;
mesh.normals = null;
mesh.tangents = null;
mesh.triangles = null;
mesh.vertices = vs.ToArray();
if(ns.Count>0) mesh.normals = ns.ToArray();
if(uv1s.Count>0) mesh.uv = uv1s.ToArray();
if(uv2s.Count>0) mesh.uv2 = uv2s.ToArray();
#if UNITY_4_5
#elif UNITY_4_6
#else
if(uv3s.Count>0) mesh.uv3 = uv3s.ToArray();
if(uv4s.Count>0) mesh.uv4 = uv4s.ToArray();
#endif
if(colors32.Count>0) mesh.colors32 = colors32.ToArray();
if(bws.Count>0) mesh.boneWeights = bws.ToArray();
mesh.subMeshCount = submeshes.Count;
for(int s=0;s<submeshes.Count;s++) {
if(s == subMeshIdx) mesh.SetTriangles(newTs.ToArray(), s);
else mesh.SetTriangles(submeshes[s].ToArray(), s);
}
if(ns == null || ns.Count <= 0) mesh.RecalculateNormals();
RecalculateTangents(mesh);
mesh.RecalculateBounds();
return mesh;
}
private static bool IsTriangleHidden(Vector3 v0, Vector3 v1, Vector3 v2, float maxDistance, List<Vector3> triMinCorners, List<Vector3> triMaxCorners, List<Vector3> hidingVs, List<int> hidingTs) {
Vector3 n = GetNormal(v0, v1, v2); // compute the normal rather than using the existing one. Because I want it square to the triangle plane
List<int> trianglesToCheck = GetTrianglesWithinRange(v0, v1, v2, maxDistance, triMinCorners, triMaxCorners);
if(!IsHidden((v0 + v1 + v2) / 3f, n, maxDistance, hidingVs, hidingTs, trianglesToCheck)) {
return false;
}
if(!IsHidden(v0, n, maxDistance, hidingVs, hidingTs, trianglesToCheck)) {
return false;
}
if(!IsHidden(v1, n, maxDistance, hidingVs, hidingTs, trianglesToCheck)) {
return false;
}
if(!IsHidden(v2, n, maxDistance, hidingVs, hidingTs, trianglesToCheck)) {
return false;
}
return true;
}
private static bool IsHidden(Vector3 v, Vector3 n, float maxDistance, List<Vector3> hidingVs, List<int> hidingTs, List<int> trianglesToCheck) {
for(int i=0;i<trianglesToCheck.Count;i++) {
int t = trianglesToCheck[i] * 3;
Vector3 hc0 = hidingVs[hidingTs[t]];
Vector3 hc1 = hidingVs[hidingTs[t+1]];
Vector3 hc2 = hidingVs[hidingTs[t+2]];
Vector3 hn = GetNormal(hc0, hc1, hc2);
float angle = Vector3.Angle(n, hn);
if(angle < 60f) {
float dist = DistanceToPlane(v, n, hc0, hn);
if(dist > 0f && dist <= maxDistance) {
Vector3 point = v + (n * dist);
Vector2 bar = point.Barycentric(hc0, hc1, hc2);
if(bar.IsBarycentricInTriangle()) {
return true;
}
}
}
}
return false;
}
private static List<int> GetTrianglesWithinRange(Vector3 v0, Vector3 v1, Vector3 v2, float maxDistance, List<Vector3> triMinCorners, List<Vector3> triMaxCorners) {
List<int> idxs = new List<int>();
Vector3 from = new Vector3(Mathf.Min(Mathf.Min(v0.x, v1.x), v2.x) - maxDistance, Mathf.Min(Mathf.Min(v0.y, v1.y), v2.y) - maxDistance, Mathf.Min(Mathf.Min(v0.z, v1.z), v2.z) - maxDistance);
Vector3 to = new Vector3(Mathf.Max(Mathf.Max(v0.x, v1.x), v2.x) + maxDistance, Mathf.Max(Mathf.Max(v0.y, v1.y), v2.y) + maxDistance, Mathf.Max(Mathf.Max(v0.z, v1.z), v2.z) + maxDistance);
for(int i=0;i<triMaxCorners.Count;i++) {
Vector3 maxCorner = triMaxCorners[i];
if(maxCorner.x > from.x && maxCorner.y > from.y && maxCorner.z > from.z) {
Vector3 minCorner = triMinCorners[i];
if(minCorner.x < to.x && minCorner.y < to.y && minCorner.z < to.z) {
idxs.Add(i);
}
}
}
return idxs;
}
public static float DistanceToPlane(Vector3 fromPos, Vector3 direction, Vector3 pointOnPlane, Vector3 normalPlane) {
float dist = Mathf.Infinity;
float divideBy = direction.InProduct(normalPlane);
if(divideBy != 0f) dist = (pointOnPlane - fromPos).InProduct(normalPlane) / direction.InProduct(normalPlane);
return dist;
}
public static Vector3 GetNormal(Vector3 v0, Vector3 v1, Vector3 v2) {
return Vector3.Cross(v1 - v0, v2 - v0).normalized;
}
}
}