예제 #1
0
        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);
        }
예제 #2
0
        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);
                }
            }
        }
예제 #3
0
        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));
                }
            }
        }
예제 #4
0
        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 */
        }
예제 #5
0
        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);
            }
        }