public void SnapSelectedVertices(bool isAbsoluteGrid) { // So we know which polygons need to have their normals recalculated List <Polygon> affectedPolygons = new List <Polygon>(); foreach (PrimitiveBrush brush in targetBrushes) { Polygon[] polygons = brush.GetPolygons(); for (int i = 0; i < polygons.Length; i++) { Polygon polygon = polygons[i]; 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; } bool polygonAffected = false; for (int j = 0; j < vertexCount; j++) { Vertex vertex = polygon.Vertices[j]; if (selectedVertices.ContainsKey(vertex)) { Vector3 newPosition = vertex.Position; float snapDistance = CurrentSettings.PositionSnapDistance; if (isAbsoluteGrid) { newPosition = brush.transform.TransformPoint(newPosition); } newPosition = MathHelper.RoundVector3(newPosition, snapDistance); if (isAbsoluteGrid) { newPosition = brush.transform.InverseTransformPoint(newPosition); } newPositions[j] = newPosition; newUV[j] = GeometryHelper.GetUVForPosition(polygon, newPosition); polygonAffected = true; } } if (polygonAffected) { affectedPolygons.Add(polygon); } // 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.CalculatePlane(); } } if (affectedPolygons.Count > 0) { for (int i = 0; i < affectedPolygons.Count; i++) { affectedPolygons[i].ResetVertexNormals(); } foreach (PrimitiveBrush brush in targetBrushes) { brush.Invalidate(true); brush.BreakTypeRelation(); } } }
/// <summary> /// Translates the specified vertices by a position delta (local to the brush) and updates the UVs /// </summary> /// <param name="brush">Brush from which the vertices belong.</param> /// <param name="specifiedVertices">Specified vertices to be translated.</param> /// <param name="localDelta">Local positional delta.</param> public static void TranslateSpecifiedVertices(Brush brush, List <Vertex> specifiedVertices, Vector3 localDelta) { Polygon.Vector3ComparerEpsilon positionComparer = new Polygon.Vector3ComparerEpsilon(); // Cache the positions as the position of vertices will change while in the for loop List <Vector3> specifiedPositions = specifiedVertices.Select(item => item.Position).ToList(); // So we know which polygons need to have their normals recalculated List <Polygon> affectedPolygons = new List <Polygon>(); Polygon[] polygons = brush.GetPolygons(); for (int i = 0; i < polygons.Length; i++) { Polygon polygon = polygons[i]; 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; } bool polygonAffected = false; for (int j = 0; j < vertexCount; j++) { Vertex vertex = polygon.Vertices[j]; if (specifiedPositions.Contains(vertex.Position, positionComparer)) { Vector3 newPosition = vertex.Position + localDelta; newPositions[j] = newPosition; newUV[j] = GeometryHelper.GetUVForPosition(polygon, newPosition); polygonAffected = true; } } if (polygonAffected) { affectedPolygons.Add(polygon); } // 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.CalculatePlane(); } if (affectedPolygons.Count > 0) { for (int i = 0; i < affectedPolygons.Count; i++) { affectedPolygons[i].ResetVertexNormals(); } } }
public void TranslateSelectedVertices(Vector3 worldDelta) { // So we know which polygons need to have their normals recalculated List <Polygon> affectedPolygons = new List <Polygon>(); foreach (PrimitiveBrush brush in targetBrushes) { Polygon[] polygons = brush.GetPolygons(); Vector3 localDelta = brush.transform.InverseTransformDirection(worldDelta); for (int i = 0; i < polygons.Length; i++) { Polygon polygon = polygons[i]; 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; } bool polygonAffected = false; for (int j = 0; j < vertexCount; j++) { Vertex vertex = polygon.Vertices[j]; if (selectedVertices.ContainsKey(vertex)) { Vector3 startPosition = startPositions[vertex]; Vector3 newPosition = vertex.Position + localDelta; Vector3 accumulatedDelta = newPosition - startPosition; if (CurrentSettings.PositionSnappingEnabled) { float snapDistance = CurrentSettings.PositionSnapDistance; // newPosition = targetBrush.transform.TransformPoint(newPosition); accumulatedDelta = MathHelper.RoundVector3(accumulatedDelta, snapDistance); // newPosition = targetBrush.transform.InverseTransformPoint(newPosition); } if (accumulatedDelta != Vector3.zero) { newPosition = startPosition + accumulatedDelta; newPositions[j] = newPosition; newUV[j] = GeometryHelper.GetUVForPosition(polygon, newPosition); polygonAffected = true; } } } if (polygonAffected) { affectedPolygons.Add(polygon); } // 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.CalculatePlane(); } } if (affectedPolygons.Count > 0) { for (int i = 0; i < affectedPolygons.Count; i++) { affectedPolygons[i].ResetVertexNormals(); } foreach (PrimitiveBrush brush in targetBrushes) { brush.Invalidate(true); brush.BreakTypeRelation(); } } }
public void TranslateSelectedVertices(Vector3 worldDelta) { foreach (PrimitiveBrush brush in targetBrushes) { bool anyAffected = false; Polygon[] polygons = brush.GetPolygons(); Vector3 localDelta = brush.transform.InverseTransformDirection(worldDelta); for (int i = 0; i < polygons.Length; i++) { Polygon polygon = polygons[i]; polygon.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; } bool polygonAffected = false; for (int j = 0; j < vertexCount; j++) { Vertex vertex = polygon.Vertices[j]; if (selectedVertices.ContainsKey(vertex)) { Vector3 startPosition = startPositions[vertex]; Vector3 newPosition = vertex.Position + localDelta; Vector3 accumulatedDelta = newPosition - startPosition; if (CurrentSettings.PositionSnappingEnabled) { float snapDistance = CurrentSettings.PositionSnapDistance; // newPosition = targetBrush.transform.TransformPoint(newPosition); accumulatedDelta = MathHelper.RoundVector3(accumulatedDelta, snapDistance); // newPosition = targetBrush.transform.InverseTransformPoint(newPosition); } if (accumulatedDelta != Vector3.zero) { newPosition = startPosition + accumulatedDelta; newPositions[j] = newPosition; newUV[j] = GeometryHelper.GetUVForPosition(polygon, newPosition); polygonAffected = true; anyAffected = true; } } } // 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]; } if (polygonAffected) { // 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); // Update the affected normals so they are rotated by the rotational difference of the polygon from translation for (int j = 0; j < vertexCount; j++) { Vertex vertex = polygon.Vertices[j]; vertex.Normal = normalRotation * vertex.Normal; } } } if (anyAffected) // If any polygons have changed { // Mark the polygons and brush as having changed brush.Invalidate(true); // Assume that the brush no longer resembles it's base shape, this has false positives but that's not a big issue brush.BreakTypeRelation(); } } }