示例#1
0
        public static bool VertexRaycast(Vector2 mousePosition, int rectSize, ElementCache selection, out int index)
        {
            qe_Mesh mesh = selection.mesh;

            float bestDistance = Mathf.Infinity;
            float distance     = 0f;

            index = -1;

            GameObject go = HandleUtility.PickGameObject(mousePosition, false);

            if (go == null || go != selection.transform.gameObject)
            {
                Camera cam    = SceneView.lastActiveSceneView.camera;
                int    width  = Screen.width;
                int    height = Screen.height;

                Rect       mouseRect = new Rect(mousePosition.x - (rectSize / 2f), mousePosition.y - (rectSize / 2f), rectSize, rectSize);
                List <int> user      = (List <int>)selection.mesh.GetUserIndices();

                for (int i = 0; i < user.Count; i++)
                {
                    if (mouseRect.Contains(HandleUtility.WorldToGUIPoint(selection.verticesInWorldSpace[user[i]])))
                    {
                        Vector3 v = cam.WorldToScreenPoint(selection.verticesInWorldSpace[user[i]]);

                        distance = Vector2.Distance(mousePosition, v);

                        if (distance < bestDistance)
                        {
                            if (v.z <= 0 || v.x < 0 || v.y < 0 || v.x > width || v.y > height)
                            {
                                continue;
                            }

                            if (PointIsOccluded(mesh, selection.verticesInWorldSpace[user[i]]))
                            {
                                continue;
                            }

                            index        = user[i];
                            bestDistance = Vector2.Distance(v, mousePosition);
                        }
                    }
                }
            }
            else
            {
                // Test culling
                List <qe_RaycastHit> hits;
                Ray ray = HandleUtility.GUIPointToWorldRay(mousePosition);

                if (MeshRaycast(ray, mesh, out hits, Mathf.Infinity, Culling.FrontBack))
                {
                    // Sort from nearest hit to farthest
                    hits.Sort((x, y) => x.Distance.CompareTo(y.Distance));

                    // Find the nearest edge in the hit faces
                    Vector3[] v = mesh.vertices;

                    for (int i = 0; i < hits.Count; i++)
                    {
                        if (PointIsOccluded(mesh, mesh.transform.TransformPoint(hits[i].Point)))
                        {
                            continue;
                        }

                        foreach (int tri in mesh.faces[hits[i].FaceIndex].indices)
                        {
                            float d = Vector3.Distance(hits[i].Point, v[tri]);

                            if (d < bestDistance)
                            {
                                bestDistance = d;
                                index        = tri;
                            }
                        }

                        if (Vector3.Dot(ray.direction, mesh.transform.TransformDirection(hits[i].Normal)) < 0f)
                        {
                            break;
                        }
                    }

                    if (index > -1 && Vector2.Distance(mousePosition, HandleUtility.WorldToGUIPoint(selection.verticesInWorldSpace[index])) > rectSize * 1.3f)
                    {
                        index = -1;
                    }
                }
            }

            if (index > -1)
            {
                index = mesh.ToUserIndex(index);
            }

            return(index > -1);
        }
示例#2
0
        /**
         * Checks if mouse is over an edge, and if so, returns true setting @edge.
         */
        public static bool EdgeRaycast(Vector2 mousePosition, ElementCache selection, out qe_Edge edge)
        {
            qe_Mesh mesh = selection.mesh;

            Vector3 v0, v1;
            float   bestDistance = Mathf.Infinity;
            float   distance     = 0f;

            edge = null;

            GameObject go = HandleUtility.PickGameObject(mousePosition, false);

            if (go == null || go != selection.transform.gameObject)
            {
                qe_Edge[] edges = mesh.userEdges;

                int width  = Screen.width;
                int height = Screen.height;

                for (int i = 0; i < edges.Length; i++)
                {
                    v0 = selection.verticesInWorldSpace[edges[i].x];
                    v1 = selection.verticesInWorldSpace[edges[i].y];

                    distance = HandleUtility.DistanceToLine(v0, v1);

                    if (distance < bestDistance && distance < MAX_EDGE_SELECT_DISTANCE)                      // && !PointIsOccluded(mesh, (v0+v1)*.5f) )
                    {
                        Vector3 vs0 = SceneView.lastActiveSceneView.camera.WorldToScreenPoint(v0);

                        // really simple frustum check (will fail on edges that have vertices outside the frustum but is visible)
                        if (vs0.z <= 0 || vs0.x < 0 || vs0.y < 0 || vs0.x > width || vs0.y > height)
                        {
                            continue;
                        }

                        Vector3 vs1 = SceneView.lastActiveSceneView.camera.WorldToScreenPoint(v1);

                        if (vs1.z <= 0 || vs1.x < 0 || vs1.y < 0 || vs1.x > width || vs1.y > height)
                        {
                            continue;
                        }


                        bestDistance = distance;
                        edge         = edges[i];
                    }
                }
            }
            else
            {
                // Test culling
                List <qe_RaycastHit> hits;
                Ray ray = HandleUtility.GUIPointToWorldRay(mousePosition);

                if (MeshRaycast(ray, mesh, out hits, Mathf.Infinity, Culling.FrontBack))
                {
                    // Sort from nearest hit to farthest
                    hits.Sort((x, y) => x.Distance.CompareTo(y.Distance));

                    // Find the nearest edge in the hit faces
                    Vector3[] v = mesh.vertices;

                    for (int i = 0; i < hits.Count; i++)
                    {
                        if (PointIsOccluded(mesh, mesh.transform.TransformPoint(hits[i].Point)))
                        {
                            continue;
                        }

                        foreach (qe_Edge e in mesh.faces[hits[i].FaceIndex].GetEdges())
                        {
                            float d = HandleUtility.DistancePointLine(hits[i].Point, v[e.x], v[e.y]);

                            if (d < bestDistance)
                            {
                                bestDistance = d;
                                edge         = e;
                            }
                        }

                        if (Vector3.Dot(ray.direction, mesh.transform.TransformDirection(hits[i].Normal)) < 0f)
                        {
                            break;
                        }
                    }

                    if (edge != null && HandleUtility.DistanceToLine(mesh.transform.TransformPoint(v[edge.x]), mesh.transform.TransformPoint(v[edge.y])) > MAX_EDGE_SELECT_DISTANCE)
                    {
                        edge = null;
                    }
                    else
                    {
                        edge.x = mesh.ToUserIndex(edge.x);
                        edge.y = mesh.ToUserIndex(edge.y);
                    }
                }
            }

            return(edge != null);
        }