新增动态水物理插件
This commit is contained in:
@@ -0,0 +1,900 @@
|
||||
// ╔════════════════════════════════════════════════════════════════╗
|
||||
// ║ Copyright © 2025 NWH Coding d.o.o. All rights reserved. ║
|
||||
// ║ Licensed under Unity Asset Store Terms of Service: ║
|
||||
// ║ https://unity.com/legal/as-terms ║
|
||||
// ║ Use permitted only in compliance with the License. ║
|
||||
// ║ Distributed "AS IS", without warranty of any kind. ║
|
||||
// ╚════════════════════════════════════════════════════════════════╝
|
||||
|
||||
#region
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
#endregion
|
||||
|
||||
// Based on:
|
||||
// Progressive Mesh type Polygon Reduction Algorithm
|
||||
// by Stan Melax (c) 1998
|
||||
// http://www.melax.com/polychop/
|
||||
|
||||
namespace NWH.DWP2.MeshDecimation
|
||||
{
|
||||
/// <summary>
|
||||
/// Progressive mesh decimation implementation using edge collapse algorithm.
|
||||
/// Reduces mesh complexity while preserving overall shape and texture coordinates.
|
||||
/// </summary>
|
||||
public class MeshDecimate
|
||||
{
|
||||
/// <summary>
|
||||
/// Whether to recalculate smooth normals after decimation.
|
||||
/// </summary>
|
||||
public bool bRecalculateNormals;
|
||||
|
||||
/// <summary>
|
||||
/// Final vertex normals after decimation.
|
||||
/// </summary>
|
||||
public Vector3[] finalNormals;
|
||||
|
||||
/// <summary>
|
||||
/// Final triangle indices after decimation.
|
||||
/// </summary>
|
||||
public int[] finalTriangles;
|
||||
|
||||
/// <summary>
|
||||
/// Final texture coordinates after decimation.
|
||||
/// </summary>
|
||||
public Vector2[] finalUVs;
|
||||
|
||||
/// <summary>
|
||||
/// Final vertex positions after decimation.
|
||||
/// </summary>
|
||||
public Vector3[] finalVertices;
|
||||
|
||||
/// <summary>
|
||||
/// Last target vertex count from progressive mesh operation.
|
||||
/// </summary>
|
||||
public int lastTarget;
|
||||
|
||||
/// <summary>
|
||||
/// Whether to lock selected vertices from being collapsed.
|
||||
/// </summary>
|
||||
public bool lockSelPoint = true;
|
||||
|
||||
/// <summary>
|
||||
/// Size in bytes of LOD history data for progressive mesh.
|
||||
/// </summary>
|
||||
public float lodDataSize;
|
||||
|
||||
/// <summary>
|
||||
/// Whether pre-calculation of decimation data has been completed.
|
||||
/// </summary>
|
||||
public bool preCalculateDone;
|
||||
|
||||
/// <summary>
|
||||
/// Target ratio of vertices to keep (0.0 to 1.0).
|
||||
/// </summary>
|
||||
public float ratio = 0.5f;
|
||||
|
||||
/// <summary>
|
||||
/// List of vertices marked as selected (protected from collapse if locked).
|
||||
/// </summary>
|
||||
public List<Vector3> selectedVertices = new();
|
||||
|
||||
/// <summary>
|
||||
/// Smoothing angle threshold in degrees for normal calculation.
|
||||
/// </summary>
|
||||
public float smoothAngle = 45.0f;
|
||||
private List<Vert> cache = new();
|
||||
private int cacheSize;
|
||||
private History[] collapseHistory;
|
||||
|
||||
private int currentcnt;
|
||||
private Vert[] myLODVertices;
|
||||
|
||||
private Tri[] myTriangles;
|
||||
private Vector3[] originalNormals;
|
||||
|
||||
private int[] originalTriangles;
|
||||
private Vector2[] originalUVs;
|
||||
private Vector3[] originalVertices;
|
||||
private int searchIndex;
|
||||
|
||||
private int[] sharedTriangles;
|
||||
private Vector3[] sharedVertices;
|
||||
private float smoothAngleDot;
|
||||
private int[] triOrder;
|
||||
|
||||
|
||||
private float ComputeEdgeCollapseCosts(Vert u, Vert v)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
Tri faceU;
|
||||
Tri faceV;
|
||||
|
||||
float edgelength = (v.position - u.position).sqrMagnitude;
|
||||
float cost = 0;
|
||||
|
||||
// find the "vFaces" triangles that are on the edge uv
|
||||
List<Tri> vFaces = new();
|
||||
int uFaceCount = u.face.Count;
|
||||
for (i = 0; i < uFaceCount; ++i)
|
||||
{
|
||||
faceU = u.face[i];
|
||||
|
||||
if (faceU.HasVertex(v))
|
||||
{
|
||||
vFaces.Add(faceU);
|
||||
}
|
||||
}
|
||||
|
||||
// use the triangle facing most away from the sides
|
||||
// to determine our curvature term
|
||||
int vFaceCount = vFaces.Count;
|
||||
for (i = 0; i < uFaceCount; ++i)
|
||||
{
|
||||
float mindot = 1; // curve for face i and closer side to it
|
||||
faceU = u.face[i];
|
||||
Vector3 faceN = faceU.normal;
|
||||
for (j = 0; j < vFaceCount; ++j)
|
||||
{
|
||||
// use dot product of face normals. '^' defined in vector
|
||||
faceV = vFaces[j];
|
||||
Vector3 ns = faceV.normal;
|
||||
float dot = (1 - (faceN.x * ns.x + faceN.y * ns.y + faceN.z * ns.z)) * 0.5f;
|
||||
if (dot < mindot)
|
||||
{
|
||||
mindot = dot;
|
||||
}
|
||||
}
|
||||
|
||||
if (mindot > cost)
|
||||
{
|
||||
cost = mindot;
|
||||
}
|
||||
}
|
||||
|
||||
if (u.IsBorder() && vFaceCount > 1)
|
||||
{
|
||||
cost = 1.0f;
|
||||
}
|
||||
|
||||
// texture UV check
|
||||
// if neighbor face has different uv
|
||||
// means that shouldn't be collapsed.
|
||||
// set its priority as higher cost.
|
||||
int found = 0;
|
||||
for (i = 0; i < uFaceCount; ++i)
|
||||
{
|
||||
faceU = u.face[i];
|
||||
Vector2 uv = faceU.uvAt(u);
|
||||
for (j = 0; j < vFaceCount; ++j)
|
||||
{
|
||||
faceV = vFaces[j];
|
||||
if (uv == faceV.uvAt(u))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (j == vFaceCount)
|
||||
{
|
||||
++found;
|
||||
}
|
||||
}
|
||||
|
||||
// all neighbor faces share same uv
|
||||
// so set u as higher cost.
|
||||
if (found > 0)
|
||||
{
|
||||
cost = 1.0f;
|
||||
}
|
||||
|
||||
if (u.selected && lockSelPoint)
|
||||
{
|
||||
cost = 6553.5f;
|
||||
}
|
||||
|
||||
// the more coplanar the lower the curvature term
|
||||
// cost 0 means u and v are on the same plane.
|
||||
return edgelength * cost;
|
||||
}
|
||||
|
||||
|
||||
private void ComputeEdgeCostAtVertex(Vert v)
|
||||
{
|
||||
// compute the edge collapse cost for all edges that start
|
||||
// from vertex v. Since we are only interested in reducing
|
||||
// the object by selecting the min cost edge at each step, we
|
||||
// only cache the cost of the least cost edge at this vertex
|
||||
// (in member variable collapse) as well as the value of the
|
||||
// cost (in member variable cost).
|
||||
if (v.neighbor.Count == 0)
|
||||
{
|
||||
// v doesn't have neighbors so it costs nothing to collapse
|
||||
v.collapse = null;
|
||||
v.cost = 0; //-0.01f;
|
||||
return;
|
||||
}
|
||||
|
||||
v.cost = 65535;
|
||||
v.collapse = null;
|
||||
// search all neighboring edges for "least cost" edge
|
||||
int neighborCount = v.neighbor.Count;
|
||||
float cost;
|
||||
for (int i = 0; i < neighborCount; ++i)
|
||||
{
|
||||
cost = ComputeEdgeCollapseCosts(v, v.neighbor[i]);
|
||||
if (cost < v.cost)
|
||||
{
|
||||
v.collapse = v.neighbor[i]; // candidate for edge collapse
|
||||
v.cost = cost; // cost of the collapse
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void ComputeAllEdgeCollapseCosts()
|
||||
{
|
||||
// For all the edges, compute the difference it would make
|
||||
// to the model if it was collapsed. The least of these
|
||||
// per vertex is cached in each vertex object.
|
||||
int count = myLODVertices.Length;
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
Vert v = myLODVertices[i];
|
||||
ComputeEdgeCostAtVertex(v);
|
||||
cache.Insert(i, v);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void UnCollapse(History his)
|
||||
{
|
||||
int i;
|
||||
int n;
|
||||
Tri t;
|
||||
|
||||
List<int> l = his.removedTriangles;
|
||||
n = l.Count;
|
||||
for (i = 0; i < n; ++i)
|
||||
{
|
||||
myTriangles[l[i]].deleted = false;
|
||||
}
|
||||
|
||||
List<ArrayList> list = his.replacedVertex;
|
||||
n = list.Count;
|
||||
for (i = 0; i < n; ++i)
|
||||
{
|
||||
ArrayList tmp = list[i];
|
||||
t = myTriangles[(int)tmp[0]];
|
||||
int changedIndex = (int)tmp[1];
|
||||
|
||||
if (changedIndex == 0)
|
||||
{
|
||||
t.v0 = myLODVertices[(int)tmp[2]];
|
||||
t.vn0 = (Vector3)tmp[3];
|
||||
t.uv0 = (Vector2)tmp[4];
|
||||
}
|
||||
else if (changedIndex == 1)
|
||||
{
|
||||
t.v1 = myLODVertices[(int)tmp[2]];
|
||||
t.vn1 = (Vector3)tmp[3];
|
||||
t.uv1 = (Vector2)tmp[4];
|
||||
}
|
||||
else
|
||||
{
|
||||
t.v2 = myLODVertices[(int)tmp[2]];
|
||||
t.vn2 = (Vector3)tmp[3];
|
||||
t.uv2 = (Vector2)tmp[4];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void Collapse(History his)
|
||||
{
|
||||
int i;
|
||||
int n;
|
||||
Tri t;
|
||||
|
||||
List<int> l = his.removedTriangles;
|
||||
n = l.Count;
|
||||
for (i = 0; i < n; ++i)
|
||||
{
|
||||
myTriangles[l[i]].deleted = true;
|
||||
}
|
||||
|
||||
List<ArrayList> list = his.replacedVertex;
|
||||
n = list.Count;
|
||||
for (i = 0; i < n; ++i)
|
||||
{
|
||||
ArrayList tmp = list[i];
|
||||
t = myTriangles[(int)tmp[0]];
|
||||
int changedIndex = (int)tmp[1];
|
||||
|
||||
if (changedIndex == 0)
|
||||
{
|
||||
t.v0 = myLODVertices[(int)tmp[5]];
|
||||
t.vn0 = (Vector3)tmp[6];
|
||||
t.uv0 = (Vector2)tmp[7];
|
||||
}
|
||||
else if (changedIndex == 1)
|
||||
{
|
||||
t.v1 = myLODVertices[(int)tmp[5]];
|
||||
t.vn1 = (Vector3)tmp[6];
|
||||
t.uv1 = (Vector2)tmp[7];
|
||||
}
|
||||
else
|
||||
{
|
||||
t.v2 = myLODVertices[(int)tmp[5]];
|
||||
t.vn2 = (Vector3)tmp[6];
|
||||
t.uv2 = (Vector2)tmp[7];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void CollapseTest()
|
||||
{
|
||||
Vert u = cache[searchIndex++];
|
||||
Vert v = u.collapse;
|
||||
|
||||
// which Vert will be collapsed.
|
||||
History his = new();
|
||||
collapseHistory[currentcnt - 1] = his;
|
||||
|
||||
// u is a vertex all by itself so just delete it
|
||||
if (v != null && v.deleted)
|
||||
{
|
||||
u.RemoveVert();
|
||||
return;
|
||||
}
|
||||
|
||||
if (v == null)
|
||||
{
|
||||
u.RemoveVert();
|
||||
return;
|
||||
}
|
||||
|
||||
int i;
|
||||
int j;
|
||||
Tri uFace;
|
||||
Tri vFace;
|
||||
int vFaceCount;
|
||||
int neighborCount = u.neighbor.Count;
|
||||
Vert[] neighbors = new Vert[neighborCount];
|
||||
int count = u.face.Count;
|
||||
|
||||
// make tmp a list of all the neighbors of u
|
||||
for (i = 0; i < neighborCount; ++i)
|
||||
{
|
||||
neighbors[i] = u.neighbor[i];
|
||||
}
|
||||
|
||||
// make a list and add face to the list if it has v.
|
||||
List<Tri> vFaces = new();
|
||||
for (i = 0; i < count; ++i)
|
||||
{
|
||||
uFace = u.face[i];
|
||||
if (uFace.HasVertex(v))
|
||||
{
|
||||
vFaces.Add(uFace);
|
||||
}
|
||||
}
|
||||
|
||||
vFaceCount = vFaces.Count;
|
||||
|
||||
// delete triangles on edge uv:
|
||||
for (i = u.face.Count - 1; i >= 0; --i)
|
||||
{
|
||||
try
|
||||
{
|
||||
uFace = u.face[i];
|
||||
if (uFace.HasVertex(v))
|
||||
{
|
||||
uFace.RemoveTriangle(his);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
// update remaining triangles to have v instead of u
|
||||
Vector2 u_uv;
|
||||
Vector2 foundUV = new();
|
||||
Vector3 foundVN = new();
|
||||
|
||||
for (i = u.face.Count - 1; i >= 0; --i)
|
||||
{
|
||||
uFace = u.face[i];
|
||||
if (!uFace.deleted)
|
||||
{
|
||||
u_uv = uFace.uvAt(u);
|
||||
|
||||
for (j = 0; j < vFaceCount; ++j)
|
||||
{
|
||||
vFace = vFaces[j];
|
||||
if (u_uv == vFace.uvAt(u))
|
||||
{
|
||||
foundUV = vFace.uvAt(v);
|
||||
foundVN = vFace.normalAt(v);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uFace.ReplaceVertex(u, v, foundUV, foundVN, his);
|
||||
}
|
||||
}
|
||||
|
||||
u.RemoveVert();
|
||||
|
||||
// recompute the edge collapse costs in neighborhood
|
||||
Vert neighbor;
|
||||
float oldCost;
|
||||
for (i = 0; i < neighborCount; ++i)
|
||||
{
|
||||
neighbor = neighbors[i];
|
||||
oldCost = neighbor.cost;
|
||||
ComputeEdgeCostAtVertex(neighbor);
|
||||
|
||||
if (oldCost > neighbor.cost)
|
||||
{
|
||||
SortLeft(neighbor);
|
||||
}
|
||||
else
|
||||
{
|
||||
SortRight(neighbor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void SortRight(Vert v)
|
||||
{
|
||||
int cacheIndex = cache.IndexOf(v);
|
||||
if (cacheIndex == cacheSize - 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
float cost = v.cost;
|
||||
Vert c2 = cache[cacheIndex + 1];
|
||||
if (cost == c2.cost)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int maxIndex = cacheSize - 2;
|
||||
while (cost > c2.cost && cacheIndex < maxIndex)
|
||||
{
|
||||
cache[cacheIndex++] = c2;
|
||||
c2 = cache[cacheIndex + 1];
|
||||
}
|
||||
|
||||
if (cost > c2.cost)
|
||||
{
|
||||
cache[cacheIndex++] = c2;
|
||||
}
|
||||
|
||||
cache[cacheIndex] = v;
|
||||
}
|
||||
|
||||
|
||||
private void SortLeft(Vert v)
|
||||
{
|
||||
int cacheIndex = cache.IndexOf(v);
|
||||
if (cacheIndex == searchIndex)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
float cost = v.cost;
|
||||
Vert c2 = cache[cacheIndex - 1];
|
||||
if (cost == c2.cost)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
while (cost < c2.cost && cacheIndex > searchIndex + 2)
|
||||
{
|
||||
cache[cacheIndex--] = c2;
|
||||
c2 = cache[cacheIndex - 1];
|
||||
}
|
||||
|
||||
if (cost < c2.cost)
|
||||
{
|
||||
cache[cacheIndex--] = c2;
|
||||
}
|
||||
|
||||
cache[cacheIndex] = v;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Pre-calculates all edge collapse operations and builds the progressive mesh history.
|
||||
/// Must be called once before Calculate can be used.
|
||||
/// </summary>
|
||||
/// <param name="tmpMesh">Input mesh to decimate.</param>
|
||||
public void PreCalculate(Mesh tmpMesh)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
|
||||
smoothAngleDot = 1 - smoothAngle / 90.0f;
|
||||
|
||||
int[] tris = tmpMesh.triangles;
|
||||
|
||||
originalTriangles = tmpMesh.triangles;
|
||||
originalVertices = tmpMesh.vertices;
|
||||
if (tmpMesh.uv.Length > 0)
|
||||
{
|
||||
originalUVs = tmpMesh.uv;
|
||||
}
|
||||
else
|
||||
{
|
||||
List<Vector2> uvs = new();
|
||||
foreach (Vector2 nr in tmpMesh.normals)
|
||||
{
|
||||
uvs.Add(nr);
|
||||
}
|
||||
|
||||
originalUVs = uvs.ToArray();
|
||||
}
|
||||
|
||||
originalNormals = tmpMesh.normals;
|
||||
|
||||
int triNum = tris.Length;
|
||||
int vertNum = originalVertices.Length;
|
||||
List<Vector3> newVertices = new();
|
||||
|
||||
int n;
|
||||
int foundAt = -1;
|
||||
int indice;
|
||||
Vector3 v;
|
||||
|
||||
for (i = 0; i < triNum; ++i)
|
||||
{
|
||||
indice = tris[i];
|
||||
v = originalVertices[indice];
|
||||
|
||||
n = newVertices.Count;
|
||||
foundAt = -1;
|
||||
for (j = 0; j < n; ++j)
|
||||
{
|
||||
if (newVertices[j] == v)
|
||||
{
|
||||
foundAt = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (foundAt != -1)
|
||||
{
|
||||
tris[i] = foundAt;
|
||||
}
|
||||
else
|
||||
{
|
||||
tris[i] = n;
|
||||
newVertices.Insert(n, v);
|
||||
}
|
||||
}
|
||||
|
||||
sharedTriangles = tris;
|
||||
sharedVertices = newVertices.ToArray();
|
||||
|
||||
myTriangles = new Tri[sharedTriangles.Length / 3];
|
||||
myLODVertices = new Vert[sharedVertices.Length];
|
||||
|
||||
ComputeProgressiveMesh();
|
||||
preCalculateDone = true;
|
||||
|
||||
// calculate triangle remove order
|
||||
triOrder = new int[myTriangles.Length];
|
||||
n = collapseHistory.Length;
|
||||
int cnt = 0;
|
||||
for (i = 0; i < n; ++i)
|
||||
{
|
||||
History his = collapseHistory[i];
|
||||
List<int> list = his.removedTriangles;
|
||||
int m = list.Count;
|
||||
for (j = 0; j < m; ++j)
|
||||
{
|
||||
triOrder[cnt++] = list[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the decimated mesh at the current ratio.
|
||||
/// Applies progressive mesh simplification and outputs final geometry arrays.
|
||||
/// PreCalculate must be called first.
|
||||
/// </summary>
|
||||
/// <param name="tmpMesh">Mesh reference (used for validation).</param>
|
||||
public void Calculate(Mesh tmpMesh)
|
||||
{
|
||||
ProgressiveMesh(ratio);
|
||||
|
||||
int i;
|
||||
int j;
|
||||
int foundAt = -1;
|
||||
Vector3 v = new();
|
||||
Vector3 vn = new();
|
||||
Vector3 dvn = new();
|
||||
Vector2 vuv = new();
|
||||
//History his = new History();
|
||||
|
||||
int cnt = 0;
|
||||
int vertsCount = myLODVertices.Length;
|
||||
int trisCount = myTriangles.Length;
|
||||
|
||||
int reducedTriCount = 0;
|
||||
foreach (Tri t in myTriangles)
|
||||
{
|
||||
if (t.deleted)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
++reducedTriCount;
|
||||
}
|
||||
|
||||
int minTriCount = reducedTriCount * 3;
|
||||
int[] tris = new int[minTriCount];
|
||||
Vector3[] verts = new Vector3[minTriCount];
|
||||
Vector2[] uvs = new Vector2[minTriCount];
|
||||
Vector3[] norms = new Vector3[minTriCount];
|
||||
int[] indices = new int[minTriCount];
|
||||
|
||||
for (i = 0; i < reducedTriCount; ++i)
|
||||
{
|
||||
Tri tri = myTriangles[triOrder[i]];
|
||||
|
||||
int cnt1 = cnt + 1;
|
||||
int cnt2 = cnt + 2;
|
||||
Vert v0 = tri.v0;
|
||||
Vert v1 = tri.v1;
|
||||
Vert v2 = tri.v2;
|
||||
|
||||
verts[cnt] = v0.position;
|
||||
verts[cnt1] = v1.position;
|
||||
verts[cnt2] = v2.position;
|
||||
tris[cnt] = cnt;
|
||||
tris[cnt1] = cnt1;
|
||||
tris[cnt2] = cnt2;
|
||||
uvs[cnt] = tri.uv0;
|
||||
uvs[cnt1] = tri.uv1;
|
||||
uvs[cnt2] = tri.uv2;
|
||||
norms[cnt] = tri.vn0;
|
||||
norms[cnt1] = tri.vn1;
|
||||
norms[cnt2] = tri.vn2;
|
||||
|
||||
indices[cnt] = tri.defaultIndex0;
|
||||
indices[cnt1] = tri.defaultIndex1;
|
||||
indices[cnt2] = tri.defaultIndex2;
|
||||
|
||||
cnt += 3;
|
||||
}
|
||||
|
||||
int triNum = tris.Length;
|
||||
List<Vector3> newVertices = new();
|
||||
List<Vector2> newUVs = new();
|
||||
List<Vector3> newNormals = new();
|
||||
List<Vector3> newDNormals = new();
|
||||
|
||||
if (bRecalculateNormals)
|
||||
{
|
||||
for (i = 0; i < triNum; ++i)
|
||||
{
|
||||
v = verts[i];
|
||||
vuv = uvs[i];
|
||||
vn = norms[i];
|
||||
int n = newVertices.Count;
|
||||
foundAt = -1;
|
||||
for (j = 0; j < n; ++j)
|
||||
{
|
||||
if (newVertices[j] == v && newUVs[j] == vuv &&
|
||||
Vector3.Dot(newNormals[j], vn) > smoothAngleDot)
|
||||
{
|
||||
foundAt = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (foundAt != -1)
|
||||
{
|
||||
tris[i] = foundAt;
|
||||
}
|
||||
else
|
||||
{
|
||||
tris[i] = n;
|
||||
newVertices[n] = v;
|
||||
newUVs[n] = vuv;
|
||||
newNormals[n] = vn;
|
||||
newDNormals[n] = dvn;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < triNum; ++i)
|
||||
{
|
||||
v = verts[i];
|
||||
vuv = uvs[i];
|
||||
vn = norms[i];
|
||||
dvn = originalNormals[indices[i]];
|
||||
int n = newVertices.Count;
|
||||
foundAt = -1;
|
||||
for (j = 0; j < n; ++j)
|
||||
{
|
||||
if (newVertices[j] == v && newUVs[j] == vuv && newDNormals[j] == dvn)
|
||||
{
|
||||
foundAt = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (foundAt != -1)
|
||||
{
|
||||
tris[i] = foundAt;
|
||||
}
|
||||
else
|
||||
{
|
||||
tris[i] = n;
|
||||
newVertices.Insert(n, v);
|
||||
newUVs.Insert(n, vuv);
|
||||
newNormals.Insert(n, vn);
|
||||
newDNormals.Insert(n, dvn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
finalVertices = newVertices.ToArray();
|
||||
finalNormals = newNormals.ToArray();
|
||||
finalUVs = newUVs.ToArray();
|
||||
finalTriangles = tris;
|
||||
}
|
||||
|
||||
|
||||
private void ComputeProgressiveMesh()
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
int n;
|
||||
Tri t;
|
||||
|
||||
int vertexCount = sharedVertices.Length;
|
||||
int triangleCount = sharedTriangles.Length;
|
||||
|
||||
Array.Clear(myLODVertices, 0, myLODVertices.Length);
|
||||
for (i = 0; i < vertexCount; ++i)
|
||||
{
|
||||
Vector3 dv = sharedVertices[i];
|
||||
bool sel = false;
|
||||
|
||||
n = selectedVertices.Count;
|
||||
for (j = 0; j < n; ++j)
|
||||
{
|
||||
if (selectedVertices[j] == dv)
|
||||
{
|
||||
sel = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
myLODVertices[i] = new Vert(dv, i, sel);
|
||||
}
|
||||
|
||||
// new myTris
|
||||
Array.Clear(myTriangles, 0, myTriangles.Length);
|
||||
int cnt = 0;
|
||||
for (i = 0; i < triangleCount; i += 3)
|
||||
{
|
||||
t = new Tri(cnt,
|
||||
myLODVertices[sharedTriangles[i]],
|
||||
myLODVertices[sharedTriangles[i + 1]],
|
||||
myLODVertices[sharedTriangles[i + 2]],
|
||||
originalUVs[originalTriangles[i]],
|
||||
originalUVs[originalTriangles[i + 1]],
|
||||
originalUVs[originalTriangles[i + 2]]);
|
||||
|
||||
t.SetDefaultIndices(originalTriangles[i], originalTriangles[i + 1], originalTriangles[i + 2]);
|
||||
if (bRecalculateNormals)
|
||||
{
|
||||
t.vn0 = t.vn1 = t.vn2 = t.normal;
|
||||
}
|
||||
else
|
||||
{
|
||||
t.vn0 = originalNormals[originalTriangles[i]];
|
||||
t.vn1 = originalNormals[originalTriangles[i + 1]];
|
||||
t.vn2 = originalNormals[originalTriangles[i + 2]];
|
||||
}
|
||||
|
||||
myTriangles[cnt] = t;
|
||||
++cnt;
|
||||
}
|
||||
|
||||
cache = new List<Vert>();
|
||||
cacheSize = vertexCount;
|
||||
|
||||
if (bRecalculateNormals)
|
||||
{
|
||||
RecalculateNormal(); // set normals for vertex.
|
||||
}
|
||||
|
||||
ComputeAllEdgeCollapseCosts(); // cache all edge collapse costs
|
||||
//System.Array.Sort(cache, myComparer); // lower cost to the left.
|
||||
cache = cache.OrderBy(p => p.cost).ToList();
|
||||
|
||||
collapseHistory = new History[vertexCount];
|
||||
|
||||
currentcnt = myLODVertices.Length + 1;
|
||||
searchIndex = 0;
|
||||
while (--currentcnt > 0)
|
||||
{
|
||||
CollapseTest();
|
||||
}
|
||||
|
||||
// LOD Data size calculation
|
||||
n = collapseHistory.Length;
|
||||
int tmpBytes = 0;
|
||||
History tmpHis;
|
||||
for (i = 0; i < n; ++i)
|
||||
{
|
||||
tmpHis = collapseHistory[i];
|
||||
tmpBytes += (
|
||||
tmpHis.removedTriangles.Count * 2 +
|
||||
tmpHis.replacedVertex.Count * 14
|
||||
) * 4;
|
||||
}
|
||||
|
||||
lodDataSize = tmpBytes;
|
||||
}
|
||||
|
||||
|
||||
private void ProgressiveMesh(float ratio)
|
||||
{
|
||||
int i;
|
||||
int target = Mathf.FloorToInt(ratio * sharedVertices.Length);
|
||||
|
||||
if (lastTarget < target)
|
||||
{
|
||||
for (i = lastTarget; i < target; ++i)
|
||||
{
|
||||
UnCollapse(collapseHistory[i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = lastTarget - 1; i >= target; --i)
|
||||
{
|
||||
Collapse(collapseHistory[i]);
|
||||
}
|
||||
}
|
||||
|
||||
lastTarget = target;
|
||||
}
|
||||
|
||||
|
||||
private void RecalculateNormal()
|
||||
{
|
||||
int n = myTriangles.Length;
|
||||
for (int i = 0; i < n; ++i)
|
||||
{
|
||||
Tri f = myTriangles[i];
|
||||
if (f.deleted)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
f.RecalculateAvgNormals(smoothAngleDot);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user