public static Pair <float?, float?> GetUVOffset(List <Polygon> polygons) { float?northOffset = 0; float?eastOffset = 0; for (int polygonIndex = 0; polygonIndex < polygons.Count; polygonIndex++) { Polygon polygon = polygons[polygonIndex]; Vector2 uvOffset = SurfaceUtility.GetUVOffset(polygon); if (polygonIndex == 0) { northOffset = uvOffset.y; eastOffset = uvOffset.x; } else { if (!northOffset.HasValue || !northOffset.Value.EqualsWithEpsilon(uvOffset.y)) { northOffset = null; } if (!eastOffset.HasValue || !eastOffset.Value.EqualsWithEpsilon(uvOffset.x)) { eastOffset = null; } } } return(new Pair <float?, float?> (eastOffset, northOffset)); }
/// <summary> /// Creates a brush under the CSG Model with the specified attributes. /// </summary> /// <returns>The created game object.</returns> /// <param name="brushType">Brush type.</param> /// <param name="localPosition">Local position of the brush's transform</param> /// <param name="localSize">Local bounds size of the brush (Optional, defaults to 2,2,2).</param> /// <param name="localRotation">Local rotation of the brush (Optional, defaults to identity quaternion).</param> /// <param name="material">Material to apply to all faces, (Optional, defaults to null for default material).</param> /// <param name="csgMode">Whether the brush is additive or subtractive (Optional, defaults to additive).</param> /// <param name="brushName">Name for the game object (Optional, defaults to "AppliedBrush").</param> public GameObject CreateBrush(PrimitiveBrushType brushType, Vector3 localPosition, Vector3 localSize = default(Vector3), Quaternion localRotation = default(Quaternion), Material material = null, CSGMode csgMode = CSGMode.Add, string brushName = null) { GameObject brushObject; if (!string.IsNullOrEmpty(brushName)) { brushObject = new GameObject(brushName); } else { brushObject = new GameObject(""); } brushObject.transform.localScale = this.transform.lossyScale; brushObject.transform.parent = this.transform; brushObject.transform.localPosition = localPosition; if (localRotation != default(Quaternion)) { brushObject.transform.localRotation = localRotation; } PrimitiveBrush primitiveBrush = brushObject.AddComponent <PrimitiveBrush>(); primitiveBrush.BrushType = brushType; primitiveBrush.Mode = csgMode; primitiveBrush.ResetPolygons(); if (localSize != default(Vector3) && localSize != new Vector3(2, 2, 2)) { BrushUtility.Resize(primitiveBrush, localSize); } else { // Resize automatically invalidates a brush with changed polygons set, if no resize took place we still need to make sure it happens primitiveBrush.Invalidate(true); } if (material != null) { SurfaceUtility.SetAllPolygonsMaterials(primitiveBrush, material); } return(brushObject); }
public static Vector2 GetUVOffset(Polygon polygon) { Vertex vertex1; Vertex vertex2; Vertex vertex3; // Get three vertices which will reliably give us good UV information (i.e. not collinear) SurfaceUtility.GetPrimaryPolygonDescribers(polygon, out vertex1, out vertex2, out vertex3); Vector2 newUV = GeometryHelper.GetUVForPosition(vertex1.Position, vertex2.Position, vertex3.Position, vertex1.UV, vertex2.UV, vertex3.UV, polygon.GetCenterPoint()); return(newUV); }
/// <summary> /// Creates a brush under the CSG Model with the specified attributes. /// </summary> /// <returns>The created game object.</returns> /// <param name="brushType">Brush type.</param> /// <param name="localPosition">Local position of the brush's transform</param> /// <param name="localSize">Local bounds size of the brush (Optional, defaults to 2,2,2).</param> /// <param name="localRotation">Local rotation of the brush (Optional, defaults to identity quaternion).</param> /// <param name="material">Material to apply to all faces, (Optional, defaults to null for default material).</param> /// <param name="csgMode">Whether the brush is additive or subtractive (Optional, defaults to additive).</param> /// <param name="brushName">Name for the game object (Optional, defaults to "AppliedBrush").</param> public GameObject CreateBrush(PrimitiveBrushType brushType, Vector3 localPosition, Vector3 localSize = default(Vector3), Quaternion localRotation = default(Quaternion), Material material = null, CSGMode csgMode = CSGMode.Add, string brushName = null) { GameObject brushObject; if (!string.IsNullOrEmpty(brushName)) { brushObject = new GameObject(brushName); } else { brushObject = new GameObject("AppliedBrush"); } brushObject.transform.parent = this.transform; brushObject.transform.localPosition = localPosition; if (localRotation != default(Quaternion)) { brushObject.transform.localRotation = localRotation; } PrimitiveBrush primitiveBrush = brushObject.AddComponent <PrimitiveBrush>(); primitiveBrush.BrushType = brushType; primitiveBrush.Mode = csgMode; primitiveBrush.ResetPolygons(); if (localSize != default(Vector3) && localSize != new Vector3(2, 2, 2)) { BrushUtility.Resize(primitiveBrush, localSize); // primitiveBrush.Invalidate(true); } if (material != null) { SurfaceUtility.SetAllPolygonsMaterials(primitiveBrush, material); } return(brushObject); }
public static void SplitIntersecting(PrimitiveBrush[] brushes) { List <Brush> intersections = new List <Brush>(); foreach (PrimitiveBrush brush in brushes) { intersections.AddRange(brush.BrushCache.IntersectingVisualBrushes); } foreach (PrimitiveBrush brush in brushes) { List <PrimitiveBrush> newBrushes = new List <PrimitiveBrush>(); foreach (Brush intersectingBrush in intersections) { PrimitiveBrush brushToClip = (PrimitiveBrush)intersectingBrush; Polygon[] polygons = brush.GetPolygons(); // A brush may have several polygons that share a plane, find all the distinct polygon planes List <Plane> distinctPlanes = new List <Plane>(); for (int polygonIndex = 0; polygonIndex < polygons.Length; polygonIndex++) { Polygon polygon = polygons[polygonIndex]; Vertex vertex1, vertex2, vertex3; SurfaceUtility.GetPrimaryPolygonDescribers(polygon, out vertex1, out vertex2, out vertex3); Vector3 position1 = vertex1.Position; Vector3 position2 = vertex2.Position; Vector3 position3 = vertex3.Position; // Transform from local to brush to local to intersectingBrush position1 = intersectingBrush.transform.InverseTransformPoint(brush.transform.TransformPoint(position1)); position2 = intersectingBrush.transform.InverseTransformPoint(brush.transform.TransformPoint(position2)); position3 = intersectingBrush.transform.InverseTransformPoint(brush.transform.TransformPoint(position3)); // Calculate plane in intersectingBrush's local space Plane polygonPlane = new Plane(position1, position2, position3); bool found = false; // See if it already exists for (int i = 0; i < distinctPlanes.Count; i++) { if (MathHelper.PlaneEqualsLooser(distinctPlanes[i], polygonPlane)) { found = true; break; } } // Not added to an existing group, so add new if (!found) { // Add a new group for the polygon distinctPlanes.Add(polygonPlane); } } foreach (Plane clipPlane in distinctPlanes) { #if UNITY_EDITOR UnityEditor.Undo.RecordObject(brushToClip, "Split Intersecting Brushes"); UnityEditor.Undo.RecordObject(brushToClip.transform, "Split Intersecting Brushes"); #endif GameObject newObject = ClipUtility.ApplyClipPlane(brushToClip, clipPlane, true, false); if (newObject != null) { #if UNITY_EDITOR UnityEditor.Undo.RegisterCreatedObjectUndo(newObject, "Split Intersecting Brushes"); #endif newBrushes.Add(newObject.GetComponent <PrimitiveBrush>()); } } brushToClip.ResetPivot(); } foreach (PrimitiveBrush newBrush in newBrushes) { newBrush.ResetPivot(); } intersections.AddRange(newBrushes.ConvertAll <Brush>(item => (Brush)item)); } }
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"); }