123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750 |
- using System;
- using System.Diagnostics;
- namespace UnityEngine.Experimental.Rendering.Universal
- {
- using Real = System.Single;
- namespace LibTessDotNet
- {
- internal enum WindingRule
- {
- EvenOdd,
- NonZero,
- Positive,
- Negative,
- AbsGeqTwo
- }
- internal enum ElementType
- {
- Polygons,
- ConnectedPolygons,
- BoundaryContours
- }
- internal enum ContourOrientation
- {
- Original,
- Clockwise,
- CounterClockwise
- }
- internal struct ContourVertex
- {
- public Vec3 Position;
- public object Data;
- public override string ToString()
- {
- return string.Format("{0}, {1}", Position, Data);
- }
- }
- internal delegate object CombineCallback(Vec3 position, object[] data, Real[] weights);
- internal partial class Tess
- {
- private Mesh _mesh;
- private Vec3 _normal;
- private Vec3 _sUnit;
- private Vec3 _tUnit;
- private Real _bminX, _bminY, _bmaxX, _bmaxY;
- private WindingRule _windingRule;
- private Dict<ActiveRegion> _dict;
- private PriorityQueue<MeshUtils.Vertex> _pq;
- private MeshUtils.Vertex _event;
- private CombineCallback _combineCallback;
- private ContourVertex[] _vertices;
- private int _vertexCount;
- private int[] _elements;
- private int _elementCount;
- public Vec3 Normal { get { return _normal; } set { _normal = value; } }
- public Real SUnitX = 1;
- public Real SUnitY = 0;
- #if DOUBLE
- public Real SentinelCoord = 4e150;
- #else
- public Real SentinelCoord = 4e30f;
- #endif
-
-
-
- public bool NoEmptyPolygons = false;
-
-
-
- public bool UsePooling = false;
- public ContourVertex[] Vertices { get { return _vertices; } }
- public int VertexCount { get { return _vertexCount; } }
- public int[] Elements { get { return _elements; } }
- public int ElementCount { get { return _elementCount; } }
- public Tess()
- {
- _normal = Vec3.Zero;
- _bminX = _bminY = _bmaxX = _bmaxY = 0;
- _windingRule = WindingRule.EvenOdd;
- _mesh = null;
- _vertices = null;
- _vertexCount = 0;
- _elements = null;
- _elementCount = 0;
- }
- private void ComputeNormal(ref Vec3 norm)
- {
- var v = _mesh._vHead._next;
- var minVal = new Real[3] { v._coords.X, v._coords.Y, v._coords.Z };
- var minVert = new MeshUtils.Vertex[3] { v, v, v };
- var maxVal = new Real[3] { v._coords.X, v._coords.Y, v._coords.Z };
- var maxVert = new MeshUtils.Vertex[3] { v, v, v };
- for (; v != _mesh._vHead; v = v._next)
- {
- if (v._coords.X < minVal[0]) { minVal[0] = v._coords.X; minVert[0] = v; }
- if (v._coords.Y < minVal[1]) { minVal[1] = v._coords.Y; minVert[1] = v; }
- if (v._coords.Z < minVal[2]) { minVal[2] = v._coords.Z; minVert[2] = v; }
- if (v._coords.X > maxVal[0]) { maxVal[0] = v._coords.X; maxVert[0] = v; }
- if (v._coords.Y > maxVal[1]) { maxVal[1] = v._coords.Y; maxVert[1] = v; }
- if (v._coords.Z > maxVal[2]) { maxVal[2] = v._coords.Z; maxVert[2] = v; }
- }
-
-
- int i = 0;
- if (maxVal[1] - minVal[1] > maxVal[0] - minVal[0]) { i = 1; }
- if (maxVal[2] - minVal[2] > maxVal[i] - minVal[i]) { i = 2; }
- if (minVal[i] >= maxVal[i])
- {
-
- norm = new Vec3 { X = 0, Y = 0, Z = 1 };
- return;
- }
-
-
- Real maxLen2 = 0, tLen2;
- var v1 = minVert[i];
- var v2 = maxVert[i];
- Vec3 d1, d2, tNorm;
- Vec3.Sub(ref v1._coords, ref v2._coords, out d1);
- for (v = _mesh._vHead._next; v != _mesh._vHead; v = v._next)
- {
- Vec3.Sub(ref v._coords, ref v2._coords, out d2);
- tNorm.X = d1.Y * d2.Z - d1.Z * d2.Y;
- tNorm.Y = d1.Z * d2.X - d1.X * d2.Z;
- tNorm.Z = d1.X * d2.Y - d1.Y * d2.X;
- tLen2 = tNorm.X*tNorm.X + tNorm.Y*tNorm.Y + tNorm.Z*tNorm.Z;
- if (tLen2 > maxLen2)
- {
- maxLen2 = tLen2;
- norm = tNorm;
- }
- }
- if (maxLen2 <= 0.0f)
- {
-
- norm = Vec3.Zero;
- i = Vec3.LongAxis(ref d1);
- norm[i] = 1;
- }
- }
- private void CheckOrientation()
- {
-
-
- Real area = 0.0f;
- for (var f = _mesh._fHead._next; f != _mesh._fHead; f = f._next)
- {
- if (f._anEdge._winding <= 0)
- {
- continue;
- }
- area += MeshUtils.FaceArea(f);
- }
- if (area < 0.0f)
- {
-
- for (var v = _mesh._vHead._next; v != _mesh._vHead; v = v._next)
- {
- v._t = -v._t;
- }
- Vec3.Neg(ref _tUnit);
- }
- }
- private void ProjectPolygon()
- {
- var norm = _normal;
- bool computedNormal = false;
- if (norm.X == 0.0f && norm.Y == 0.0f && norm.Z == 0.0f)
- {
- ComputeNormal(ref norm);
- _normal = norm;
- computedNormal = true;
- }
- int i = Vec3.LongAxis(ref norm);
- _sUnit[i] = 0;
- _sUnit[(i + 1) % 3] = SUnitX;
- _sUnit[(i + 2) % 3] = SUnitY;
- _tUnit[i] = 0;
- _tUnit[(i + 1) % 3] = norm[i] > 0.0f ? -SUnitY : SUnitY;
- _tUnit[(i + 2) % 3] = norm[i] > 0.0f ? SUnitX : -SUnitX;
-
- for (var v = _mesh._vHead._next; v != _mesh._vHead; v = v._next)
- {
- Vec3.Dot(ref v._coords, ref _sUnit, out v._s);
- Vec3.Dot(ref v._coords, ref _tUnit, out v._t);
- }
- if (computedNormal)
- {
- CheckOrientation();
- }
-
- bool first = true;
- for (var v = _mesh._vHead._next; v != _mesh._vHead; v = v._next)
- {
- if (first)
- {
- _bminX = _bmaxX = v._s;
- _bminY = _bmaxY = v._t;
- first = false;
- }
- else
- {
- if (v._s < _bminX) _bminX = v._s;
- if (v._s > _bmaxX) _bmaxX = v._s;
- if (v._t < _bminY) _bminY = v._t;
- if (v._t > _bmaxY) _bmaxY = v._t;
- }
- }
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- private void TessellateMonoRegion(MeshUtils.Face face)
- {
-
-
-
-
- var up = face._anEdge;
- Debug.Assert(up._Lnext != up && up._Lnext._Lnext != up);
- while (Geom.VertLeq(up._Dst, up._Org)) up = up._Lprev;
- while (Geom.VertLeq(up._Org, up._Dst)) up = up._Lnext;
- var lo = up._Lprev;
- while (up._Lnext != lo)
- {
- if (Geom.VertLeq(up._Dst, lo._Org))
- {
-
-
-
- while (lo._Lnext != up && (Geom.EdgeGoesLeft(lo._Lnext)
- || Geom.EdgeSign(lo._Org, lo._Dst, lo._Lnext._Dst) <= 0.0f))
- {
- lo = _mesh.Connect(lo._Lnext, lo)._Sym;
- }
- lo = lo._Lprev;
- }
- else
- {
-
- while (lo._Lnext != up && (Geom.EdgeGoesRight(up._Lprev)
- || Geom.EdgeSign(up._Dst, up._Org, up._Lprev._Org) >= 0.0f))
- {
- up = _mesh.Connect(up, up._Lprev)._Sym;
- }
- up = up._Lnext;
- }
- }
-
-
- Debug.Assert(lo._Lnext != up);
- while (lo._Lnext._Lnext != up)
- {
- lo = _mesh.Connect(lo._Lnext, lo)._Sym;
- }
- }
-
-
-
-
-
- private void TessellateInterior()
- {
- MeshUtils.Face f, next;
- for (f = _mesh._fHead._next; f != _mesh._fHead; f = next)
- {
-
- next = f._next;
- if (f._inside)
- {
- TessellateMonoRegion(f);
- }
- }
- }
-
-
-
-
-
-
- private void DiscardExterior()
- {
- MeshUtils.Face f, next;
- for (f = _mesh._fHead._next; f != _mesh._fHead; f = next)
- {
-
- next = f._next;
- if( ! f._inside ) {
- _mesh.ZapFace(f);
- }
- }
- }
-
-
-
-
-
-
-
-
-
- private void SetWindingNumber(int value, bool keepOnlyBoundary)
- {
- MeshUtils.Edge e, eNext;
- for (e = _mesh._eHead._next; e != _mesh._eHead; e = eNext)
- {
- eNext = e._next;
- if (e._Rface._inside != e._Lface._inside)
- {
-
- e._winding = (e._Lface._inside) ? value : -value;
- }
- else
- {
-
- if (!keepOnlyBoundary)
- {
- e._winding = 0;
- }
- else
- {
- _mesh.Delete(e);
- }
- }
- }
- }
- private int GetNeighbourFace(MeshUtils.Edge edge)
- {
- if (edge._Rface == null)
- return MeshUtils.Undef;
- if (!edge._Rface._inside)
- return MeshUtils.Undef;
- return edge._Rface._n;
- }
- private void OutputPolymesh(ElementType elementType, int polySize)
- {
- MeshUtils.Vertex v;
- MeshUtils.Face f;
- MeshUtils.Edge edge;
- int maxFaceCount = 0;
- int maxVertexCount = 0;
- int faceVerts, i;
- if (polySize < 3)
- {
- polySize = 3;
- }
-
-
- if (polySize > 3)
- {
- _mesh.MergeConvexFaces(polySize);
- }
-
- for (v = _mesh._vHead._next; v != _mesh._vHead; v = v._next)
- v._n = MeshUtils.Undef;
-
- for (f = _mesh._fHead._next; f != _mesh._fHead; f = f._next)
- {
- f._n = MeshUtils.Undef;
- if (!f._inside) continue;
- if (NoEmptyPolygons)
- {
- var area = MeshUtils.FaceArea(f);
- if (Math.Abs(area) < Real.Epsilon)
- {
- continue;
- }
- }
- edge = f._anEdge;
- faceVerts = 0;
- do {
- v = edge._Org;
- if (v._n == MeshUtils.Undef)
- {
- v._n = maxVertexCount;
- maxVertexCount++;
- }
- faceVerts++;
- edge = edge._Lnext;
- }
- while (edge != f._anEdge);
- Debug.Assert(faceVerts <= polySize);
- f._n = maxFaceCount;
- ++maxFaceCount;
- }
- _elementCount = maxFaceCount;
- if (elementType == ElementType.ConnectedPolygons)
- maxFaceCount *= 2;
- _elements = new int[maxFaceCount * polySize];
- _vertexCount = maxVertexCount;
- _vertices = new ContourVertex[_vertexCount];
-
- for (v = _mesh._vHead._next; v != _mesh._vHead; v = v._next)
- {
- if (v._n != MeshUtils.Undef)
- {
-
- _vertices[v._n].Position = v._coords;
- _vertices[v._n].Data = v._data;
- }
- }
-
- int elementIndex = 0;
- for (f = _mesh._fHead._next; f != _mesh._fHead; f = f._next)
- {
- if (!f._inside) continue;
- if (NoEmptyPolygons)
- {
- var area = MeshUtils.FaceArea(f);
- if (Math.Abs(area) < Real.Epsilon)
- {
- continue;
- }
- }
-
- edge = f._anEdge;
- faceVerts = 0;
- do {
- v = edge._Org;
- _elements[elementIndex++] = v._n;
- faceVerts++;
- edge = edge._Lnext;
- } while (edge != f._anEdge);
-
- for (i = faceVerts; i < polySize; ++i)
- {
- _elements[elementIndex++] = MeshUtils.Undef;
- }
-
- if (elementType == ElementType.ConnectedPolygons)
- {
- edge = f._anEdge;
- do
- {
- _elements[elementIndex++] = GetNeighbourFace(edge);
- edge = edge._Lnext;
- } while (edge != f._anEdge);
-
- for (i = faceVerts; i < polySize; ++i)
- {
- _elements[elementIndex++] = MeshUtils.Undef;
- }
- }
- }
- }
- private void OutputContours()
- {
- MeshUtils.Face f;
- MeshUtils.Edge edge, start;
- int startVert = 0;
- int vertCount = 0;
- _vertexCount = 0;
- _elementCount = 0;
- for (f = _mesh._fHead._next; f != _mesh._fHead; f = f._next)
- {
- if (!f._inside) continue;
- start = edge = f._anEdge;
- do
- {
- ++_vertexCount;
- edge = edge._Lnext;
- }
- while (edge != start);
- ++_elementCount;
- }
- _elements = new int[_elementCount * 2];
- _vertices = new ContourVertex[_vertexCount];
- int vertIndex = 0;
- int elementIndex = 0;
- startVert = 0;
- for (f = _mesh._fHead._next; f != _mesh._fHead; f = f._next)
- {
- if (!f._inside) continue;
- vertCount = 0;
- start = edge = f._anEdge;
- do {
- _vertices[vertIndex].Position = edge._Org._coords;
- _vertices[vertIndex].Data = edge._Org._data;
- ++vertIndex;
- ++vertCount;
- edge = edge._Lnext;
- } while (edge != start);
- _elements[elementIndex++] = startVert;
- _elements[elementIndex++] = vertCount;
- startVert += vertCount;
- }
- }
- private Real SignedArea(ContourVertex[] vertices)
- {
- Real area = 0.0f;
- for (int i = 0; i < vertices.Length; i++)
- {
- var v0 = vertices[i];
- var v1 = vertices[(i + 1) % vertices.Length];
- area += v0.Position.X * v1.Position.Y;
- area -= v0.Position.Y * v1.Position.X;
- }
- return 0.5f * area;
- }
- public void AddContour(ContourVertex[] vertices)
- {
- AddContour(vertices, ContourOrientation.Original);
- }
- public void AddContour(ContourVertex[] vertices, ContourOrientation forceOrientation)
- {
- if (_mesh == null)
- {
- _mesh = new Mesh();
- }
- bool reverse = false;
- if (forceOrientation != ContourOrientation.Original)
- {
- var area = SignedArea(vertices);
- reverse = (forceOrientation == ContourOrientation.Clockwise && area < 0.0f) || (forceOrientation == ContourOrientation.CounterClockwise && area > 0.0f);
- }
- MeshUtils.Edge e = null;
- for (int i = 0; i < vertices.Length; ++i)
- {
- if (e == null)
- {
- e = _mesh.MakeEdge();
- _mesh.Splice(e, e._Sym);
- }
- else
- {
-
-
- _mesh.SplitEdge(e);
- e = e._Lnext;
- }
- int index = reverse ? vertices.Length - 1 - i : i;
-
- e._Org._coords = vertices[index].Position;
- e._Org._data = vertices[index].Data;
-
-
-
-
- e._winding = 1;
- e._Sym._winding = -1;
- }
- }
- public void Tessellate(WindingRule windingRule, ElementType elementType, int polySize)
- {
- Tessellate(windingRule, elementType, polySize, null);
- }
- public void Tessellate(WindingRule windingRule, ElementType elementType, int polySize, CombineCallback combineCallback)
- {
- _normal = Vec3.Zero;
- _vertices = null;
- _elements = null;
- _windingRule = windingRule;
- _combineCallback = combineCallback;
- if (_mesh == null)
- {
- return;
- }
-
-
- ProjectPolygon();
-
-
-
-
-
- ComputeInterior();
-
-
-
- if (elementType == ElementType.BoundaryContours)
- {
- SetWindingNumber(1, true);
- }
- else
- {
- TessellateInterior();
- }
- _mesh.Check();
- if (elementType == ElementType.BoundaryContours)
- {
- OutputContours();
- }
- else
- {
- OutputPolymesh(elementType, polySize);
- }
- if (UsePooling)
- {
- _mesh.Free();
- }
- _mesh = null;
- }
- }
- }
- }
|