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