/// <summary> /// Scales the brush by a local Vector3 scale from its pivot /// </summary> /// <param name="brush">The brush to be rescaled</param> /// <param name="rescaleValue">Local scale to apply</param> public static void Scale(PrimitiveBrush brush, Vector3 scaleValue) { Polygon[] polygons = brush.GetPolygons(); for (int i = 0; i < polygons.Length; i++) { Polygon polygon = polygons[i]; polygons[i].CalculatePlane(); Vector3 previousPlaneNormal = polygons[i].Plane.normal; int vertexCount = polygon.Vertices.Length; Vector3[] newPositions = new Vector3[vertexCount]; Vector2[] newUV = new Vector2[vertexCount]; for (int j = 0; j < vertexCount; j++) { newPositions[j] = polygon.Vertices[j].Position; newUV[j] = polygon.Vertices[j].UV; } for (int j = 0; j < vertexCount; j++) { Vertex vertex = polygon.Vertices[j]; Vector3 newPosition = vertex.Position.Multiply(scaleValue); newPositions[j] = newPosition; newUV[j] = GeometryHelper.GetUVForPosition(polygon, newPosition); } // Apply all the changes to the polygon for (int j = 0; j < vertexCount; j++) { Vertex vertex = polygon.Vertices[j]; vertex.Position = newPositions[j]; vertex.UV = newUV[j]; } // Polygon geometry has changed, inform the polygon that it needs to recalculate its cached plane polygons[i].CalculatePlane(); Vector3 newPlaneNormal = polygons[i].Plane.normal; // Find the rotation from the original polygon plane to the new polygon plane Quaternion normalRotation = Quaternion.FromToRotation(previousPlaneNormal, newPlaneNormal); // Rotate all the vertex normals by the new rotation for (int j = 0; j < vertexCount; j++) { Vertex vertex = polygon.Vertices[j]; vertex.Normal = normalRotation * vertex.Normal; } } #if UNITY_EDITOR EditorHelper.SetDirty(brush); #endif brush.Invalidate(true); }
/// <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); }