/// <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); }
/// <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);
/// <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]); }