/// <summary>
        /// Updates the extrusion with the given <see cref="_discretization"/> and <see cref="Extrusion"/> values.
        /// Updates the <see cref="MeshFilter"/> component with the resulting Mesh.
        /// </summary>
        public void UpdateExtrusion()
        {
            if (_meshFilter == null)
            {
                _meshFilter = GetComponent <MeshFilter>();
            }

            if (_meshRenderer == null)
            {
                _meshRenderer = GetComponent <MeshRenderer>();
            }

            bool doExtrusion = Math.Abs(_extrusion) > ExtrusionNumericalPrecision.MinimumExtrusionDistanceExclusive;

            if (doExtrusion)
            {
                try
                {
                    _lineExtrusionConfiguration = GetLineExtrusionConfiguration(_extrusion);
                    _extrusionResults           = SegmentedLineExtrusionFromIntersection.ExtrudeSegmentedLineBothDirections(this, _lineExtrusionConfiguration);
                    var linePointsWithUVs        = LineSegmentation.GetLinePointsUV(this);
                    var segmentwiseLinePointList = new SegmentwiseLinePointListUV(linePointsWithUVs);
                    _extrudedMesh = ExtrusionTriangulator2D.TriangulatePolygon(_extrusionResults, segmentwiseLinePointList, _lineExtrusionConfiguration);
                    var verts = _extrudedMesh.vertices;
                    for (int i = 0; i < verts.Length; i++)
                    {
                        verts[i] = transform.InverseTransformPoint(verts[i]);
                    }
                    _extrudedMesh.vertices = verts;
                    _meshFilter.mesh       = _extrudedMesh;
                    bool singleContour = _extrusionResults.Contours.Count <= 1;
                    _meshRenderer.material = singleContour ? _singleContourMaterial : _multipleContourMaterial;
                    (singleContour ? OnSingleContourExtrusionUpdated : OnMultipleContourExtrusionUpdated).Invoke();
                }
                catch (Exception e)
                {
                    Debug.LogWarning(string.Format("Error in extrusion of amount {0}: {1}\n{2}.", _extrusion, e.Message, e.StackTrace));
                    _extrudedMesh    = new Mesh();
                    _meshFilter.mesh = _extrudedMesh;
                }
                finally
                {
                }
            }
            else
            {
                _extrudedMesh    = new Mesh();
                _meshFilter.mesh = _extrudedMesh;
            }
        }
        /// <summary>
        /// Triangulate a polygon based on an outer closed contour of extruded points, further inner hole contours of extruded points, and the original line points from which they were extruded.
        /// </summary>
        /// <param name="originalLinePointList">Original line points</param>
        /// <param name="lineExtrusionResults">Line extrusion results</param>
        /// <param name="extrusionConfiguration">The extrusion configuration parameters</param>
        public Mesh TriangulatePolygonWithHoleContours(LineExtrusionResults lineExtrusionResults, SegmentwiseLinePointListUV originalLinePointList, LineExtrusionConfiguration extrusionConfiguration)
        {
            var polygon = new Polygon();

            var outerThenAllInnerPointsList = lineExtrusionResults.Contours;
            var originalLinePoints          = originalLinePointList.Points;

            int marker = 0;

            AddContourToPolygon(polygon, outerThenAllInnerPointsList[0], ref marker, contourIsHole: false);

            if (IncludeOriginalLinePoints)
            {
                AddOriginalLinePointsVerticesAndSegmentsToPolygon(originalLinePoints, polygon, ref marker);
            }

            if (IncludeRemovedContours)
            {
                List <Vector2WithUV[]> removedContours = lineExtrusionResults.RemovedContours;
                for (int i = 0; i < removedContours.Count; i++)
                {
                    AddContourToPolygon(polygon, removedContours[i], ref marker, contourIsHole: false);
                }
            }

            for (int i = 1; i < outerThenAllInnerPointsList.Count; i++)
            {
                AddContourToPolygon(polygon, outerThenAllInnerPointsList[i], ref marker, contourIsHole: true);
            }

            var options = ConstraintOptions;
            var quality = QualityOptions;

            var iMesh     = polygon.Triangulate(options, quality);
            var unityMesh = new Mesh();

            Vector3[] vectorArray; Dictionary <int, int> vertexIdToArrayIndexDictionary;
            GetVector3ArrayAndIndexIdDictionaryFromVertices(iMesh.Vertices, out vectorArray, out vertexIdToArrayIndexDictionary);
            var trindicesArray = GetTrindicesArrayFromTriangles(iMesh.Triangles, vertexIdToArrayIndexDictionary);

            Vector2[] uvArray = GenerateTriangulatedPointUVs(vectorArray, lineExtrusionResults, originalLinePointList, extrusionConfiguration);

            unityMesh.vertices  = vectorArray;
            unityMesh.triangles = trindicesArray;
            unityMesh.uv        = uvArray;

            return(unityMesh);
        }
示例#3
0
        /// <summary>
        /// Triangulate a polygon based on line extrusion results and original line points from which extrusion occured.
        /// </summary>
        /// <param name="lineExtrusionResults">Results of line extrusion.</param>
        /// <param name="originalLinePointList">Original line points</param>
        /// <param name="extrusionConfiguration">The extrusion configuration parameters</param>
        public static Mesh TriangulatePolygon(LineExtrusionResults lineExtrusionResults, SegmentwiseLinePointListUV originalLinePointList, LineExtrusionConfiguration extrusionConfiguration)
        {
            PolygonHelper.OrderContourByAreaDescending(lineExtrusionResults.Contours);
            PolygonHelper.OrderContourByAreaDescending(lineExtrusionResults.ContoursWithAlteredUParameters);
            var outerThenAllInnerPointsListWithAlteredUVs = lineExtrusionResults.ContoursWithAlteredUParameters;

            Mesh mesh;

            if (outerThenAllInnerPointsListWithAlteredUVs.Count == 1)
            {
                mesh = extrusionConfiguration.GetSingleContourTriangulation().TriangulateClosedContour(lineExtrusionResults, originalLinePointList, extrusionConfiguration);
            }
            else if (outerThenAllInnerPointsListWithAlteredUVs.Count >= 1)
            {
                mesh = extrusionConfiguration.GetMultipleContourTriangulation().TriangulatePolygonWithHoleContours(lineExtrusionResults, originalLinePointList, extrusionConfiguration);
            }
            else
            {
                mesh = new Mesh();
            }
            return(mesh);
        }
 /// <summary>
 /// Updates the MeshRenderer's sharedMaterial based on extrusion results.
 /// </summary>
 /// <param name="lineExtrusionConfiguration">The line extrusion configuration</param>
 /// <param name="lineExtrusionResults">The line extrusion results</param>
 protected abstract void DoUpdateMaterialBasedOnExtrusionResults(LineExtrusionConfiguration lineExtrusionConfiguration, LineExtrusionResults lineExtrusionResults);
 public ExtrusionConfigurationAndResults(LineExtrusionConfiguration lineExtrusionConfiguration, LineExtrusionResults lineExtrusionResults)
 {
     LineExtrusionConfiguration = lineExtrusionConfiguration;
     LineExtrusionResults       = lineExtrusionResults;
 }
        /// <summary>
        /// Triangulate a line based on a single closed contour of extruded points, by creating quads connecting points of the the same u-parameter on opposite sides of the original line.
        /// </summary>
        /// <param name="lineExtrusionResults">Line extrusion results</param>
        /// <param name="extrusionConfiguration">The extrusion configuration parameters</param>
        private static Mesh TriangulateLine_ConnectExtrudedPointsOfSameUParameter(LineExtrusionResults lineExtrusionResults, LineExtrusionConfiguration extrusionConfiguration)
        {
            var mesh = new Mesh();

            var originalLinePointsList = lineExtrusionResults.OriginalLinePointList;
            //NB Setting closest original segment index is not even needed in this implementation, but it's a reasonable choice to sent as the second half of the addition uv we're sending.
            var extrusionAmountAbs              = Mathf.Abs(extrusionConfiguration.ExtrusionAmount);
            var connectedSegmentsResults        = lineExtrusionResults.ConnectedSegmentsExtrusionResults;
            var contourConnectedSegmentsResults = connectedSegmentsResults.SegmentwiseCoverageOfSingleContour;

            if (contourConnectedSegmentsResults != null)
            {
                var firstPoint = contourConnectedSegmentsResults.FirstPoint;
                var lastPoint  = contourConnectedSegmentsResults.LastPoint;
                var increasingSegmentPoints = contourConnectedSegmentsResults.IncreasingPortionSegmentPoints;
                var decreasingSegmentPoints = contourConnectedSegmentsResults.DecreasingPortionSegmentPoints;

                if (increasingSegmentPoints.Count == decreasingSegmentPoints.Count && increasingSegmentPoints.Count >= 1)
                {
                    int       numInBetweenUParameters = decreasingSegmentPoints.Count;
                    Vector3[] vertices  = new Vector3[numInBetweenUParameters * 2 + 2];
                    Vector2[] uvs       = new Vector2[numInBetweenUParameters * 2 + 2];
                    Vector2[] indexUvs  = new Vector2[numInBetweenUParameters * 2 + 2];
                    int[]     trindices = new int[(numInBetweenUParameters - 1) * 6 + 6];

                    vertices[0] = firstPoint.Vector;
                    uvs[0]      = firstPoint.UV;
                    int closestOriginalSegmentIndex = SegmentedLineUtil.ClosestIndexAlongSegmentwiseLine(firstPoint.Vector, originalLinePointsList, extrusionAmountAbs);
                    indexUvs[0] = new Vector2(-1, closestOriginalSegmentIndex);
                    vertices[numInBetweenUParameters * 2 + 1] = lastPoint.Vector;
                    uvs[numInBetweenUParameters * 2 + 1]      = lastPoint.UV;
                    closestOriginalSegmentIndex = SegmentedLineUtil.ClosestIndexAlongSegmentwiseLine(lastPoint.Vector, originalLinePointsList, extrusionAmountAbs);
                    indexUvs[numInBetweenUParameters * 2 + 1] = new Vector2(numInBetweenUParameters, closestOriginalSegmentIndex);

                    for (int i = 0; i < numInBetweenUParameters; i++)
                    {
                        var increasingPoint = increasingSegmentPoints[i];
                        var decreasingPoint = decreasingSegmentPoints[i];

                        vertices[i * 2 + 1]         = increasingPoint.Vector;
                        uvs[i * 2 + 1]              = increasingPoint.UV;
                        closestOriginalSegmentIndex = SegmentedLineUtil.ClosestIndexAlongSegmentwiseLine(increasingPoint.Vector, originalLinePointsList, extrusionAmountAbs);
                        indexUvs[i * 2 + 1]         = new Vector2(i, closestOriginalSegmentIndex);

                        vertices[i * 2 + 2]         = decreasingPoint.Vector;
                        uvs[i * 2 + 2]              = decreasingPoint.UV;
                        closestOriginalSegmentIndex = SegmentedLineUtil.ClosestIndexAlongSegmentwiseLine(decreasingPoint.Vector, originalLinePointsList, extrusionAmountAbs);
                        indexUvs[i * 2 + 2]         = new Vector2(i, closestOriginalSegmentIndex);
                    }

                    //NB This order of triangle indices is consistent with our direction of extrusion points winding around the original line
                    trindices[0] = 0;
                    trindices[1] = 1;
                    trindices[2] = 2;
                    trindices[numInBetweenUParameters * 6 - 3] = numInBetweenUParameters * 2 + 0;
                    trindices[numInBetweenUParameters * 6 - 2] = numInBetweenUParameters * 2 - 1;
                    trindices[numInBetweenUParameters * 6 - 1] = numInBetweenUParameters * 2 + 1;

                    for (int j = 0; j < numInBetweenUParameters - 1; j++)
                    {
                        trindices[3 + j * 6 + 0] = 1 + j * 2 + 1;
                        trindices[3 + j * 6 + 1] = 1 + j * 2 + 0;
                        trindices[3 + j * 6 + 2] = 1 + j * 2 + 2;
                        trindices[3 + j * 6 + 3] = 1 + j * 2 + 2;
                        trindices[3 + j * 6 + 4] = 1 + j * 2 + 3;
                        trindices[3 + j * 6 + 5] = 1 + j * 2 + 1;
                    }

                    mesh.vertices  = vertices;
                    mesh.uv        = uvs;
                    mesh.triangles = trindices;
                    mesh.uv4       = indexUvs;
                }
                else
                {
                    Debug.LogError("Not enough connected extruded points to create mesh.");
                }
            }
            else
            {
                Debug.LogError("Single contour connected segments results are not calculated.");
            }

            return(mesh);
        }
 /// <summary>
 /// Triangulate a line based on a single closed contour of extruded points by connecting points of equal u-parameter.
 /// </summary>
 /// <param name="originalLinePointList">Original line points</param>
 /// <param name="lineExtrusionResults">Line extrusion results</param>
 /// <param name="extrusionConfiguration">The extrusion configuration parameters</param>
 public Mesh TriangulateClosedContour(LineExtrusionResults lineExtrusionResults, SegmentwiseLinePointListUV originalLinePointList, LineExtrusionConfiguration extrusionConfiguration)
 {
     return(TriangulateLine_ConnectExtrudedPointsOfSameUParameter(lineExtrusionResults, extrusionConfiguration));
 }
 /// <summary>
 /// Generates UV values for triangulated points on the interior of an extruded surface.
 /// </summary>
 /// <param name="triangulatedPoints">The triangulated points</param>
 /// <param name="lineExtrusionResults">Line extrusion resulting contours.</param>
 /// <param name="originalLinePointsList">Original line points</param>
 /// <param name="extrusionConfiguration">The extrusion configuration parameters</param>
 protected abstract Vector2[] GenerateTriangulatedPointUVs(Vector3[] triangulatedPoints, LineExtrusionResults lineExtrusionResults, SegmentwiseLinePointListUV originalLinePointsList, LineExtrusionConfiguration extrusionConfiguration);
示例#9
0
        /// <summary>
        /// Updates the MeshRenderer's sharedMaterial based on extrusion results.
        /// </summary>
        /// <param name="lineExtrusionConfiguration">The line extrusion configuration</param>
        /// <param name="lineExtrusionResults">The line extrusion results</param>
        protected override void DoUpdateMaterialBasedOnExtrusionResults(LineExtrusionConfiguration lineExtrusionConfiguration, LineExtrusionResults lineExtrusionResults)
        {
            var connectedSegmentsResults       = lineExtrusionResults.ConnectedSegmentsExtrusionResults;
            var singleContourConnectedSegments = connectedSegmentsResults.SegmentwiseCoverageOfSingleContour;

            if (singleContourConnectedSegments != null)
            {
                var firstVector4 = Vector2WithUVToLocalVector4(singleContourConnectedSegments.FirstPoint);
                var lastVector4  = Vector2WithUVToLocalVector4(singleContourConnectedSegments.LastPoint);
                var increasingChunkPackedArrays = ConvertMonotonicChunkPointsToLocalVector4Array(singleContourConnectedSegments.IncreasingPortionSegmentPoints);
                var decreasingChunkPackedArrays = ConvertMonotonicChunkPointsToLocalVector4Array(singleContourConnectedSegments.DecreasingPortionSegmentPoints);

                var renderer = MeshRenderer;
                var mpb      = MaterialPropertyBlock;

                mpb.SetFloat("_ExtrusionLength", Mathf.Abs(lineExtrusionConfiguration.ExtrusionAmount));

                //TODO Set connected segments floats using textures, not uniforms, to help alleviate uniform limits. The best choice may be platform dependent.
                mpb.SetVector("_connectedSegmentFirstPoint", firstVector4);
                mpb.SetVector("_connectedSegmentLastPoint", lastVector4);
                mpb.SetVectorArray("_increasingChunkConnectedSegmentPoints", increasingChunkPackedArrays.PackedPoints);
                mpb.SetVectorArray("_increasingChunkConnectedSegmentUvs", increasingChunkPackedArrays.PackedUvs);
                mpb.SetVectorArray("_decreasingChunkConnectedSegmentPoints", decreasingChunkPackedArrays.PackedPoints);
                mpb.SetVectorArray("_decreasingChunkConnectedSegmentUvs", decreasingChunkPackedArrays.PackedUvs);
                mpb.SetFloat("_numberOfConnectedSegments", Mathf.Min(increasingChunkPackedArrays.NumberOfPoints, decreasingChunkPackedArrays.NumberOfPoints));

                renderer.SetPropertyBlock(mpb);
            }
        }
 /// <summary>
 /// Generates empty UV values for triangulated points on the interior of an extruded surface.
 /// </summary>
 /// <param name="triangulatedPoints">The triangulated points</param>
 /// <param name="lineExtrusionResults">Line extrusion resulting contours.</param>
 /// <param name="originalLinePointsList">Original line points</param>
 /// <param name="extrusionConfiguration">The extrusion configuration parameters</param>
 protected override Vector2[] GenerateTriangulatedPointUVs(Vector3[] triangulatedPoints, LineExtrusionResults lineExtrusionResults, SegmentwiseLinePointListUV originalLinePointsList, LineExtrusionConfiguration extrusionConfiguration)
 {
     return(new Vector2[triangulatedPoints.Length]);
 }