public static void InsertEdgeLoop(PrimitiveBrush brush, Plane localClipPlane) { // Clip the polygons against the plane List <Polygon> polygonsFront; List <Polygon> polygonsBack; if (PolygonFactory.SplitPolygonsByPlane(new List <Polygon>(brush.GetPolygons()), localClipPlane, true, out polygonsFront, out polygonsBack)) { List <Polygon> allPolygons = new List <Polygon>(); // Concat back into one list allPolygons.AddRange(polygonsFront); allPolygons.AddRange(polygonsBack); // Remove the inserted polygons for (int i = 0; i < allPolygons.Count; i++) { if (allPolygons[i].ExcludeFromFinal) { allPolygons.RemoveAt(i); i--; } } // Update the brush with the new polygons brush.SetPolygons(allPolygons.ToArray(), true); } }
/// <summary> /// Create a brush at the origin using a specified set of polygons /// </summary> /// <returns>The custom brush game object.</returns> /// <param name="polygons">Polygons.</param> public GameObject CreateCustomBrush(Polygon[] polygons) { GameObject brushObject = new GameObject("AppliedBrush"); brushObject.transform.parent = this.transform; PrimitiveBrush primitiveBrush = brushObject.AddComponent <PrimitiveBrush>(); primitiveBrush.SetPolygons(polygons, true); return(brushObject); }
/// <summary> /// Applies a clip or split operation to a brush by supplying a plane local to the brush. Clipping allows you to cut away and discard parts of the brush, while splitting allows you to split a brush in two. /// </summary> /// <returns>If keepBothSides is <c>true</c>, this returns the second brush if one was created.</returns> /// <param name="brush">Brush to clip/split</param> /// <param name="localPlane">Local plane to clip/split against</param> /// <param name="keepBothSides">If set to <c>true</c> split the brush and keep both sides.</param> /// <param name="resetPivots">If set to <c>true</c> make sure the pivot clipped brush and any new brush are at their center.</param> public static GameObject ApplyClipPlane(PrimitiveBrush brush, Plane localPlane, bool keepBothSides, bool resetPivots = true) { // Clip the polygons against the plane List <Polygon> polygonsFront; List <Polygon> polygonsBack; List <Polygon> polygonList = new List <Polygon>(brush.GetPolygons()); if (PolygonFactory.SplitPolygonsByPlane(polygonList, localPlane, false, out polygonsFront, out polygonsBack)) { // Update the brush with the new polygons brush.SetPolygons(polygonsFront.ToArray(), true); GameObject newObject = null; // If they have decided to split instead of clip, create a second brush with the other side if (keepBothSides) { newObject = brush.Duplicate(); // Finally give the new brush the other set of polygons newObject.GetComponent <PrimitiveBrush>().SetPolygons(polygonsBack.ToArray(), true); newObject.transform.SetSiblingIndex(brush.transform.GetSiblingIndex()); // Reset the new brush's pivot if (resetPivots) { newObject.GetComponent <PrimitiveBrush>().ResetPivot(); } } // Can't reset the first brush pivot until after the second brush is made, otherwise the second // brush is effectively translated twice, ending up in the wrong position if (resetPivots) { brush.ResetPivot(); } return(newObject); } else { return(null); } }
private void CreateBrush(List <Vector3> positions) { Polygon sourcePolygon = PolygonFactory.ConstructPolygon(positions, true); // Early out if it wasn't possible to create the polygon if (sourcePolygon == null) { return; } if (activePolygon != null) { for (int i = 0; i < sourcePolygon.Vertices.Length; i++) { Vector2 newUV = GeometryHelper.GetUVForPosition(activePolygon, sourcePolygon.Vertices[i].Position); sourcePolygon.Vertices[i].UV = newUV; } } Vector3 planeNormal = GetActivePlane().normal; // Debug.Log(Vector3.Dot(sourcePolygon.Plane.normal, planeNormal)); // Flip the polygon if the winding order is wrong if (Vector3.Dot(sourcePolygon.Plane.normal, planeNormal) < 0) { sourcePolygon.Flip(); // Need to flip the UVs across the U (X) direction for (int i = 0; i < sourcePolygon.Vertices.Length; i++) { Vector2 uv = sourcePolygon.Vertices[i].UV; uv.x = 1 - uv.x; sourcePolygon.Vertices[i].UV = uv; } } float extrusionDistance = 1; Vector3 positionOffset = Vector3.zero; if (selectingHeight) { extrusionDistance = prismHeight; } else { if (activePolygon != null && activeBrush != null) { extrusionDistance = activeBrush.CalculateExtentsInAxis(planeNormal); } else { Brush lastSelectedBrush = csgModel.LastSelectedBrush; if (lastSelectedBrush != null) { Bounds lastSelectedBrushBounds = lastSelectedBrush.GetBoundsTransformed(); for (int i = 0; i < 3; i++) { if (!planeNormal[i].EqualsWithEpsilon(0)) { if (lastSelectedBrushBounds.size[i] != 0) { extrusionDistance = lastSelectedBrushBounds.size[i]; if (planeNormal[i] > 0) { positionOffset[i] = lastSelectedBrushBounds.center[i] - lastSelectedBrushBounds.extents[i]; } else { positionOffset[i] = lastSelectedBrushBounds.center[i] + lastSelectedBrushBounds.extents[i]; } } } } } } // Subtractions should go through if (csgMode == CSGMode.Subtract) { sourcePolygon.Flip(); } } Quaternion rotation; Polygon[] polygons; SurfaceUtility.ExtrudePolygon(sourcePolygon, extrusionDistance, out polygons, out rotation); GameObject newObject = csgModel.CreateCustomBrush(polygons); PrimitiveBrush newBrush = newObject.GetComponent <PrimitiveBrush>(); newObject.transform.rotation = rotation; newObject.transform.position += positionOffset; if (activePolygon != null && activePolygon.Material != csgModel.GetDefaultMaterial()) { for (int i = 0; i < polygons.Length; i++) { polygons[i].Material = activePolygon.Material; } } // Finally give the new brush the other set of polygons newBrush.SetPolygons(polygons, true); newBrush.Mode = csgMode; newBrush.ResetPivot(); // Use this brush as the basis for drawing the next brush csgModel.SetLastSelectedBrush(newBrush); Undo.RegisterCreatedObjectUndo(newObject, "Draw Brush"); }