public static Selection FindClosest(Vector3 point, Model model, bool color_in_face = false) { Selection result = VertexSelection.FindClosestVertex(point, model); if (result == null) { result = EdgeSelection.FindClosestEdge(point, model); } if (result == null) { result = FaceSelection.FindClosestFace(point, model, color_in_face); } return(result); }
public MoveEdgeAction(Render render, Controller ctrl, EdgeSelection sel) : base(render, ctrl) { face = sel.face; num = sel.num; v1 = face.GetVertex(num); v2 = face.GetVertex(num + 1); origin = v1.position; org_direction = v2.position - origin; Vector3 pos = render.world.InverseTransformPoint(ctrl.position); grab_fraction = Vector3.Dot(pos - origin, org_direction) / org_direction.sqrMagnitude; face_rends = new List <FaceRenderer>(); faces = new List <TempFace>(); extra_edges = new List <Vector3>(); extra_edges_sel = new List <EdgeSelection>(); foreach (var face in render.model.faces) { int i1 = face.vertices.IndexOf(v1); int i2 = face.vertices.IndexOf(v2); if (i1 < 0 && i2 < 0) { continue; } face_rends.Add(render.GetFaceRenderer(face)); if (i1 >= 0 && i2 >= 0) { faces.Add(new TempFace { face = face, plane = face.plane }); } if (i1 >= 0) { AddExtraEdges(face, i1, i2); } if (i2 >= 0) { AddExtraEdges(face, i2, i1); } } }
public ExtrudeEdgeAction(Render render, Controller ctrl, EdgeSelection sel) : base(render, ctrl) { face = sel.face; num = sel.num; v1 = face.GetVertex(num); v2 = face.GetVertex(num + 1); origin = v1.position; org_direction = v2.position - origin; Vector3 pos = render.world.InverseTransformPoint(ctrl.position); grab_fraction = Vector3.Dot(pos - origin, org_direction) / org_direction.sqrMagnitude; face_rends = new List <FaceRenderer>(); foreach (var face in render.model.faces) { if (face.vertices.IndexOf(v1) >= 0 || face.vertices.IndexOf(v2) >= 0) { face_rends.Add(render.GetFaceRenderer(face)); } } }
Subspace SnapPosition(Vector3 pos, out EdgeSelection closest_edge) { closest_edge = null; Vector3 rpos = pos - origin; if (rpos.magnitude < Selection.DISTANCE_VERTEX_MIN) { /* snap to original position */ //foreach (var edge in edges) // AddSelection(new VertexSelection { vertex = edge.far_vertex }, Darker(Selection.SELECTION_COLOR)); return(new Subspace0()); } /* try to snap to a direction */ float closest = Selection.DISTANCE_EDGE_MIN; Vector3 closest_rpos = Vector3.zero; foreach (var edge in edges) { Vector3 shift = edge.direction - (origin - edge.far_vertex.position); Vector3 test_rpos = Vector3.Project(rpos - shift, edge.direction) + shift; float distance = Vector3.Distance(rpos, test_rpos); if (distance < closest) { closest = distance * 0.99f; closest_rpos = test_rpos; closest_edge = edge.sel; } } if (closest_edge != null) { AddSelection(closest_edge, COLOR); return(new Subspace1(closest_rpos)); } /* try to snap to a plane */ closest = Selection.DISTANCE_FACE_MIN; Vector3 closest_normal = Vector3.zero; Face closest_face = null; for (int i = 0; i < edges.Count; i += 2) { Vector3 plane_normal = Vector3.Cross(edges[i].direction, edges[i + 1].direction); plane_normal.Normalize(); float distance = Mathf.Abs(Vector3.Dot(rpos, plane_normal)); if (distance < closest) { closest = distance * 0.99f; closest_face = edges[i].sel.face; closest_normal = plane_normal; } } if (closest_face != null) { AddSelection(new FaceSelection { face = closest_face, color_in_face = true }, COLOR); return(new Subspace2(closest_normal)); } return(new Subspace3()); /* no snapping */ }
public override void Drag() { Vector3 pos = render.world.InverseTransformPoint(ctrl.position); EdgeSelection closest_edge; var subspace = SnapPosition(pos, out closest_edge); var ptsubspace = new PointedSubspace(subspace, origin); Vector3 otherpos = render.world.InverseTransformPoint(other_ctrl.position); Selection othersel = Selection.FindClosest(otherpos, render.model, color_in_face: true); Vector3? dummyedge_from = null; string other_ctrl_hint = null; if (othersel != null) { AddSelection(othersel, GUIDE_COLOR); if (!othersel.ContainsVertex(vertex)) { PointedSubspace otherptsubspace = othersel.GetPointedSubspace(); if (othersel is VertexSelection) { Vertex v = ((VertexSelection)othersel).vertex; var foot = v.position; otherptsubspace = new PointedSubspace(subspace.NormalSubspace(), foot); if (closest_edge != null && closest_edge.ContainsVertex(v)) { float distance = Vector3.Distance(v.position, pos); int cm_distance = Mathf.RoundToInt(distance * 100 / 5) * 5; other_ctrl_hint = "clamped at " + cm_distance + " cm"; var point0 = v.position + cm_distance * 0.01f * (origin - v.position).normalized; ptsubspace = new PointedSubspace(new Subspace0(), point0); otherptsubspace = PointedSubspace.Void(); } else if (subspace is Subspace0) { float distance = Vector3.Distance(v.position, origin); int mm_distance = Mathf.RoundToInt(distance * 1000); other_ctrl_hint = (mm_distance / 10.0).ToString() + " cm"; } } else if (othersel is EdgeSelection) { Vertex v1, v2; ((EdgeSelection)othersel).GetVertices(out v1, out v2); Vector3 foot1 = v1.position; Vector3 foot2 = v2.position; Subspace orthogonal_plane = new Subspace2(foot2 - foot1); var ptsub1 = new PointedSubspace(orthogonal_plane, foot1); var ptsub2 = new PointedSubspace(orthogonal_plane, foot2); var dist0 = otherptsubspace.Distance(pos); var dist1 = ptsub1.Distance(pos); var dist2 = ptsub2.Distance(pos); if (dist1 <= dist0 && dist1 <= dist2) { otherptsubspace = ptsub1; othersel = new VertexSelection { vertex = v1 }; } else if (dist2 <= dist0 && dist2 <= dist1) { otherptsubspace = ptsub2; othersel = new VertexSelection { vertex = v2 }; } } if (otherptsubspace.Distance(pos) < Selection.DISTANCE_VERTEX_MIN) { ptsubspace = ptsubspace.IntersectedWith(otherptsubspace); dummyedge_from = othersel.Center(); } } } pos = ptsubspace.Snap(pos); vertex.position = pos; foreach (var face_rend in face_rends) { face_rend.ComputeMesh(); } if (dummyedge_from.HasValue) { AddSelection(EdgeSelection.DummyEdgeSelection(dummyedge_from.Value, pos), GUIDE_COLOR); } AddSelection(new VertexSelection { vertex = vertex }, subspace is Subspace0 ? Darker(COLOR) : COLOR); SelectionFinished(); if (other_ctrl.CurrentHoverTracker() == null) { ControllerMode.Get(other_ctrl).UpdatePointer(render, EMode.Guide); other_ctrl.SetControllerHints(trigger: other_ctrl_hint); } }