public static bool IntersectsWithShapePolygon(ShapePolygon shapePolygon, CSGPlane polygonPlane, Ray ray)
        {
            var intersection = polygonPlane.Intersection(ray);
            var vertices     = shapePolygon.Vertices;

            for (int v0 = vertices.Length - 1, v1 = 0; v1 < vertices.Length; v0 = v1, v1++)
            {
                var vertex0 = vertices[v0];
                var vertex1 = vertices[v1];
                var delta   = (vertex1 - vertex0);
                var length  = delta.sqrMagnitude;
                if (length <= MathConstants.EqualityEpsilonSqr)
                {
                    continue;
                }

                var tangent = delta / Mathf.Sqrt(length);
                var normal  = Vector3.Cross(polygonPlane.normal, tangent);
                var plane   = new CSGPlane(normal, vertex0);
                if (plane.Distance(intersection) < MathConstants.DistanceEpsilon)
                {
                    return(false);
                }
            }
            return(true);
        }
        public static void RemoveDuplicatePoints(ShapePolygon shapePolygon)
        {
            var vertices      = shapePolygon.Vertices;
            var edgeMaterials = shapePolygon.EdgeMaterials;
            var edgeTexgens   = shapePolygon.EdgeTexgens;

            // remove any points that are too close to one another
            for (int j = vertices.Length - 1, i = vertices.Length - 2; i >= 0; j = i, i--)
            {
                if ((vertices[j] - vertices[i]).sqrMagnitude < MathConstants.DistanceEpsilon)
                {
                    ArrayUtility.RemoveAt(ref vertices, j);
                    ArrayUtility.RemoveAt(ref edgeMaterials, j);
                    ArrayUtility.RemoveAt(ref edgeTexgens, j);
                }
            }
            while (vertices.Length > 3 && (vertices[0] - vertices[vertices.Length - 1]).sqrMagnitude < MathConstants.DistanceEpsilon)
            {
                var lastIndex = vertices.Length - 1;
                ArrayUtility.RemoveAt(ref vertices, lastIndex);
                ArrayUtility.RemoveAt(ref edgeMaterials, lastIndex);
                ArrayUtility.RemoveAt(ref edgeTexgens, lastIndex);
            }

            shapePolygon.Vertices      = vertices;
            shapePolygon.EdgeMaterials = edgeMaterials;
            shapePolygon.EdgeTexgens   = edgeTexgens;
        }
Example #3
0
		internal override bool CreateControlMeshForBrushIndex(CSGModel parentModel, CSGBrush brush, ShapePolygon polygon, Matrix4x4 localToWorld, float height, out ControlMesh newControlMesh, out Shape newShape)
		{
			var direction = haveForcedDirection ? forcedDirection : buildPlane.normal;
            if (!ShapePolygonUtility.GenerateControlMeshFromVertices(polygon,
																	 localToWorld,
																	 GeometryUtility.RotatePointIntoPlaneSpace(buildPlane, direction),
																	 height,
																	
																	 new TexGen(),
																			   
																	 false, 
																	 true,
																	 out newControlMesh,
																	 out newShape))
			{
				return false;
			}
						
			brush.Shape = newShape;
			brush.ControlMesh = newControlMesh;
			InternalCSGModelManager.ValidateBrush(brush, true);
			ControlMeshUtility.RebuildShape(brush);
			return true;
		}
 internal abstract bool CreateControlMeshForBrushIndex(CSGModel parentModel, CSGBrush brush, ShapePolygon polygon, Matrix4x4 localToWorld, float height, out ControlMesh newControlMesh, out Shape newShape);
        internal override bool CreateControlMeshForBrushIndex(CSGModel parentModel, CSGBrush brush, ShapePolygon polygon, Matrix4x4 localToWorld, float height, out ControlMesh newControlMesh, out Shape newShape)
        {
            bool smooth            = settings.circleSmoothShading;
            bool singleSurfaceEnds = settings.circleSingleSurfaceEnds;
            var  direction         = haveForcedDirection ? forcedDirection : buildPlane.normal;

            if (!ShapePolygonUtility.GenerateControlMeshFromVertices(polygon,
                                                                     localToWorld,
                                                                     GeometryUtility.RotatePointIntoPlaneSpace(buildPlane, direction),
                                                                     height,

                                                                     new TexGen(),

                                                                     smooth,
                                                                     singleSurfaceEnds,
                                                                     out newControlMesh,
                                                                     out newShape))
            {
                return(false);
            }

            brush.Shape       = newShape;
            brush.ControlMesh = newControlMesh;
            InternalCSGModelManager.ValidateBrush(brush, true);
            ControlMeshUtility.RebuildShape(brush);

            var   vertices      = polygon.Vertices;
            float circumference = 0.0f;

            for (int j = vertices.Length - 1, i = 0; i < vertices.Length; j = i, i++)
            {
                circumference += (vertices[j] - vertices[i]).magnitude;
            }

            var shape = brush.Shape;

            float desiredTextureLength = Mathf.Max(1.0f, Mathf.Round(circumference));
            float scalar = desiredTextureLength / circumference;

            shape.TexGens[0].Scale.x       = scalar;
            shape.TexGens[0].Scale.y       = shape.TexGens[0].Scale.y;
            shape.TexGens[0].Translation.x = 0;

            var count = vertices.Length;

            if (!singleSurfaceEnds)
            {
                GeometryUtility.ContinueTexGenFromSurfaceToSurface(brush, 0, count);
                GeometryUtility.ContinueTexGenFromSurfaceToSurface(brush, 0, count + count);
                for (int j = 0, i = 1; i < count; j = i, i++)
                {
                    GeometryUtility.ContinueTexGenFromSurfaceToSurface(brush, j, i);
                    GeometryUtility.ContinueTexGenFromSurfaceToSurface(brush, i, i + count);
                    GeometryUtility.ContinueTexGenFromSurfaceToSurface(brush, i, i + count + count);
                }
            }
            else
            {
                for (int j = 0, i = 1; i < count; j = i, i++)
                {
                    GeometryUtility.ContinueTexGenFromSurfaceToSurface(brush, j, i);
                }
            }

            return(true);
        }
        public static bool GenerateControlMeshFromVertices(ShapePolygon shape2DPolygon,
                                                           Matrix4x4 localToWorld,
                                                           Vector3 direction,
                                                           float height,
                                                           Material capMaterial,
                                                           TexGen capTexgen,
                                                           bool?smooth,
                                                           bool singleSurfaceEnds,                                                                                 //Plane buildPlane,
                                                           out ControlMesh controlMesh,
                                                           out Shape shape)
        {
            if (shape2DPolygon == null)
            {
                controlMesh = null;
                shape       = null;
                return(false);
            }

            var vertices = shape2DPolygon.Vertices;

            if (vertices.Length < 3)
            {
                controlMesh = null;
                shape       = null;
                return(false);
            }
            if (height == 0.0f)
            {
                controlMesh = null;
                shape       = null;
                return(false);
            }

            Vector3 from;
            Vector3 to;

            if (height > 0)
            {
                @from = direction * height;                // buildPlane.normal * height;
                to    = MathConstants.zeroVector3;
            }
            else
            {
                @from = MathConstants.zeroVector3;
                to    = direction * height;               //buildPlane.normal * height;
            }

            var count           = vertices.Length;
            var doubleCount     = (count * 2);
            var extraPoints     = 0;
            var extraEdges      = 0;
            var endsPolygons    = 2;
            var startEdgeOffset = doubleCount;

            if (!singleSurfaceEnds)
            {
                extraPoints      = 2;
                extraEdges       = (4 * count);
                endsPolygons     = doubleCount;
                startEdgeOffset += extraEdges;
            }


            var dstPoints   = new Vector3 [doubleCount + extraPoints];
            var dstEdges    = new HalfEdge[(count * 6) + extraEdges];
            var dstPolygons = new Polygon [count + endsPolygons];

            var center1 = MathConstants.zeroVector3;
            var center2 = MathConstants.zeroVector3;


            for (int i = 0; i < count; i++)
            {
                var point1 = vertices[i];
                var point2 = vertices[(count + i - 1) % count];

                point1 += @from;
                point2 += to;

                // swap y/z to solve texgen issues
                dstPoints[i].x = point1.x;
                dstPoints[i].y = point1.y;
                dstPoints[i].z = point1.z;

                center1 += dstPoints[i];

                dstEdges [i].VertexIndex = (short)i;
                dstEdges [i].HardEdge    = true;

                // swap y/z to solve texgen issues
                dstPoints[i + count].x = point2.x;
                dstPoints[i + count].y = point2.y;
                dstPoints[i + count].z = point2.z;
                center2 += dstPoints[i + count];

                dstEdges [i + count].VertexIndex = (short)(i + count);
                dstEdges [i + count].HardEdge    = true;
            }

            if (!singleSurfaceEnds)
            {
                dstPoints[doubleCount]     = center1 / count;
                dstPoints[doubleCount + 1] = center2 / count;

                int   edge_offset   = doubleCount;
                short polygon_index = (short)count;

                // 'top'
                for (int i = 0, j = count - 1; i < count; j = i, i++)
                {
                    var jm = (j) % count;
                    var im = (i) % count;

                    var edgeOut0 = edge_offset + (jm * 2) + 1;
                    var edgeIn0  = edge_offset + (im * 2) + 0;
                    var edgeOut1 = edge_offset + (im * 2) + 1;

                    dstEdges[edgeIn0].VertexIndex = (short)(doubleCount);
                    dstEdges[edgeIn0].HardEdge    = true;
                    dstEdges[edgeIn0].TwinIndex   = edgeOut1;

                    dstEdges[edgeOut1].VertexIndex = (short)im;
                    dstEdges[edgeOut1].HardEdge    = true;
                    dstEdges[edgeOut1].TwinIndex   = edgeIn0;

                    dstEdges[im].PolygonIndex       = polygon_index;
                    dstEdges[edgeIn0].PolygonIndex  = polygon_index;
                    dstEdges[edgeOut0].PolygonIndex = polygon_index;

                    dstPolygons[polygon_index] = new Polygon(new int[] { im, edgeIn0, edgeOut0 }, polygon_index);
                    polygon_index++;
                }

                edge_offset = doubleCount * 2;
                // 'bottom'
                for (int i = 0, j = count - 1; j >= 0; i = j, j--)
                {
                    var jm = (count + count - j) % count;
                    var im = (count + count - i) % count;

                    var edgeOut0 = edge_offset + (jm * 2) + 1;
                    var edgeIn0  = edge_offset + (im * 2) + 0;
                    var edgeOut1 = edge_offset + (im * 2) + 1;

                    dstEdges[edgeIn0].VertexIndex = (short)(doubleCount + 1);
                    dstEdges[edgeIn0].HardEdge    = true;
                    dstEdges[edgeIn0].TwinIndex   = edgeOut1;

                    dstEdges[edgeOut1].VertexIndex = (short)(im + count);
                    dstEdges[edgeOut1].HardEdge    = true;
                    dstEdges[edgeOut1].TwinIndex   = edgeIn0;

                    dstEdges[im + count].PolygonIndex = polygon_index;
                    dstEdges[edgeIn0].PolygonIndex    = polygon_index;
                    dstEdges[edgeOut0].PolygonIndex   = polygon_index;

                    dstPolygons[polygon_index] = new Polygon(new int[] { im + count, edgeIn0, edgeOut0 }, polygon_index);
                    polygon_index++;
                }
            }
            else
            {
                var polygon0Edges = new int[count];
                var polygon1Edges = new int[count];
                for (var i = 0; i < count; i++)
                {
                    dstEdges [i].PolygonIndex         = (short)(count + 0);
                    dstEdges [i + count].PolygonIndex = (short)(count + 1);
                    polygon0Edges[i] = i;
                    polygon1Edges[count - (i + 1)] = i + count;
                }
                dstPolygons[count + 0] = new Polygon(polygon0Edges, count + 0);
                dstPolygons[count + 1] = new Polygon(polygon1Edges, count + 1);
            }


            for (int v0 = count - 1, v1 = 0; v1 < count; v0 = v1, v1++)
            {
                var polygonIndex = (short)(v1);

                var nextOffset = startEdgeOffset + (((v1 + 1) % count) * 4);
                var currOffset = startEdgeOffset + (((v1)) * 4);
                var prevOffset = startEdgeOffset + (((v1 + count - 1) % count) * 4);

                var nextTwin = nextOffset + 1;
                var prevTwin = prevOffset + 3;

                dstEdges[v1].TwinIndex         = currOffset + 0;
                dstEdges[v1 + count].TwinIndex = currOffset + 2;

                dstEdges[currOffset + 0].PolygonIndex = polygonIndex;
                dstEdges[currOffset + 1].PolygonIndex = polygonIndex;
                dstEdges[currOffset + 2].PolygonIndex = polygonIndex;
                dstEdges[currOffset + 3].PolygonIndex = polygonIndex;

                dstEdges[currOffset + 0].TwinIndex = (v1);
                dstEdges[currOffset + 1].TwinIndex = prevTwin;
                dstEdges[currOffset + 2].TwinIndex = (v1 + count);
                dstEdges[currOffset + 3].TwinIndex = nextTwin;

                dstEdges[currOffset + 0].VertexIndex = (short)(v0);
                dstEdges[currOffset + 1].VertexIndex = (short)(v1 + count);
                dstEdges[currOffset + 2].VertexIndex = (short)(((v1 + 1) % count) + count);
                dstEdges[currOffset + 3].VertexIndex = (short)(v1);

                dstEdges[currOffset + 0].HardEdge = true;
                dstEdges[currOffset + 1].HardEdge = true;
                dstEdges[currOffset + 2].HardEdge = true;
                dstEdges[currOffset + 3].HardEdge = true;

                dstPolygons[polygonIndex] = new Polygon(new [] { currOffset + 0,
                                                                 currOffset + 1,
                                                                 currOffset + 2,
                                                                 currOffset + 3 }, polygonIndex);
            }

            for (int i = 0; i < dstPoints.Length; i++)
            {
                dstPoints[i] = localToWorld.MultiplyPoint(dstPoints[i]);
            }

            controlMesh = new ControlMesh
            {
                Vertices = dstPoints,
                Edges    = dstEdges,
                Polygons = dstPolygons
            };
            controlMesh.SetDirty();

            shape = new Shape
            {
                Materials   = new Material[dstPolygons.Length],
                Surfaces    = new Surface[dstPolygons.Length],
                TexGenFlags = new TexGenFlags[dstPolygons.Length],
                TexGens     = new TexGen[dstPolygons.Length]
            };


            var smoothinggroup = (smooth.HasValue && smooth.Value) ? SurfaceUtility.FindUnusedSmoothingGroupIndex() : 0;


            var containedMaterialCount = 0;

            if (shape2DPolygon.EdgeMaterials != null &&
                shape2DPolygon.EdgeTexgens != null /* &&
                                                    * shape2DPolygon.edgeTexgenFlags != null*/)
            {
                containedMaterialCount = Mathf.Min(shape2DPolygon.EdgeMaterials.Length,
                                                   shape2DPolygon.EdgeTexgens.Length /*,
                                                                                      *                        shape2DPolygon.edgeTexgenFlags.Length*/);
            }

            if (!capMaterial)
            {
                capMaterial = CSGSettings.DefaultMaterial;
                capTexgen   = new TexGen(-1);
            }

            for (var i = 0; i < dstPolygons.Length; i++)
            {
                if (i < containedMaterialCount)
                {
                    //shape.TexGenFlags[i] = shape2DPolygon.edgeTexgenFlags[i];
                    shape.Materials  [i]             = shape2DPolygon.EdgeMaterials[i];
                    shape.TexGens    [i]             = shape2DPolygon.EdgeTexgens[i];
                    shape.Surfaces   [i].TexGenIndex = i;
                    shape.TexGens[i].MaterialIndex   = -1;
                }
                else
                {
                    shape.Materials[i] = capMaterial;
                    shape.TexGens[i]   = capTexgen;
                    //shape.TexGenFlags[i]			= TexGenFlags.None;
                    shape.Surfaces[i].TexGenIndex  = i;
                    shape.TexGens[i].MaterialIndex = -1;
                }
                if (smooth.HasValue)
                {
                    if (i < count)
                    {
                        shape.TexGens[i].SmoothingGroup = smoothinggroup;
                    }
                    else
                    {
                        shape.TexGens[i].SmoothingGroup = 0;
                    }
                }
            }

            for (var s = 0; s < dstPolygons.Length; s++)
            {
                var normal = shape.Surfaces[s].Plane.normal;
                shape.Surfaces[s].Plane = GeometryUtility.CalcPolygonPlane(controlMesh, (short)s);
                Vector3 tangent, binormal;
                GeometryUtility.CalculateTangents(normal, out tangent, out binormal);
                //var tangent		= Vector3.Cross(GeometryUtility.CalculateTangent(normal), normal).normalized;
                //var binormal	= Vector3.Cross(normal, tangent);
                shape.Surfaces[s].Tangent     = tangent;
                shape.Surfaces[s].BiNormal    = binormal;
                shape.Surfaces[s].TexGenIndex = s;
            }

            controlMesh.IsValid = ControlMeshUtility.Validate(controlMesh, shape);
            if (controlMesh.IsValid)
            {
                return(true);
            }

            controlMesh = null;
            shape       = null;
            return(false);
        }