/**
         * 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;
        }
Esempio n. 2
0
        /**
         * Get an array of qe_Edge from this mesh (three per-triangle).
         */
        public qe_Edge[] GetEdges()
        {
            int[] tris = cloneMesh.triangles;

            qe_Edge[] edges = new qe_Edge[tris.Length];

            for(int i = 0; i < tris.Length; i+=3)
            {
                edges[i+0] = new qe_Edge(tris[i+0], tris[i+1]);
                edges[i+1] = new qe_Edge(tris[i+1], tris[i+2]);
                edges[i+2] = new qe_Edge(tris[i+2], tris[i+0]);
            }

            return edges;
        }