unsafe public OcclusionMesh(ref OcclusionMeshAsset sharedMesh, Occluder occluder)
        {
            vertexCount = sharedMesh.vertexCount;
            indexCount  = sharedMesh.indexCount;
            vertexData  = sharedMesh.vertexData;
            indexData   = sharedMesh.indexData;

            int size = UnsafeUtility.SizeOf <float4>() * vertexCount;
            var data = Memory.Unmanaged.Allocate(size, 64, Allocator.Persistent);

            transformedVertexData = BlobAssetReference <float4> .Create(data, size);

            screenMin = float.MaxValue;
            screenMax = -float.MaxValue;

            localToWorld = occluder.localTransform;
        }
        internal void EditMesh(Occluder occluder)
        {
            EditorGUI.BeginChangeCheck();

            occluder.DebugRender();

            var pos   = occluder.LocalPosition;
            var rot   = occluder.LocalRotation;
            var scale = occluder.LocalScale;

            Handles.TransformHandle(ref pos, ref rot, ref scale);
            if (EditorGUI.EndChangeCheck())
            {
                Undo.RecordObject(occluder, "Modify occluder transform");
                PrefabUtility.RecordPrefabInstancePropertyModifications(occluder);

                occluder.LocalPosition = pos;
                occluder.LocalRotation = rot;
                occluder.LocalScale    = scale;
            }
        }
        private static void RenderWireframe(OccluderVolumeEditingContext ctx, Occluder occluder, Mesh mesh, Vector3[] verts, bool frontFacing)
        {
            var transform = occluder.localTransform;

            foreach (var face in ctx.faces)
            {
                var p = transform.MultiplyPoint(face.centroid);

                if (Vector3.Dot(transform.MultiplyVector(face.normal), Camera.current.transform.position - p) < 0)
                {
                    if (!frontFacing)
                    {
                        Handles.color = Color.white;
                        for (int i = 0; i < face.vertices.Length; i++)
                        {
                            var a = verts[face.vertices[i]];
                            var b = verts[face.vertices[(i + 1) % face.vertices.Length]];
                            Handles.DrawDottedLine(transform.MultiplyPoint(a), transform.MultiplyPoint(b), 2);
                        }
                    }
                }
                else if (frontFacing)
                {
                    Handles.color = Color.white;
                    for (int i = 0; i < face.vertices.Length; i++)
                    {
                        var a = transform.MultiplyPoint(verts[face.vertices[i]]);
                        var b = transform.MultiplyPoint(verts[face.vertices[(i + 1) % face.vertices.Length]]);
                        Handles.DrawBezier(a, b, a, b, Color.white, null, 6);
                    }
                }
            }

            /*        foreach (var edge in ctx.edges)
             *      {
             *          var t1 = ctx.tris[edge.t[0]];
             *          var t2 = ctx.tris[edge.t[1]];
             *
             *          if (Vector3.Dot(t1.normal, t2.normal) > 0.99f)
             *          {
             *              continue;
             *          }
             *
             *          var n1 = occluder.localTransform.MultiplyVector(t1.normal);
             *          var n2 = occluder.localTransform.MultiplyVector(t2.normal);
             *
             *          var a = occluder.localTransform.MultiplyPoint(verts[edge.v[0]]);
             *          var b = occluder.localTransform.MultiplyPoint(verts[edge.v[1]]);
             *          var d = Camera.current.transform.position - a;
             *
             *          if (Vector3.Dot(n1, d) < 0 && Vector3.Dot(n2, d) < 0)
             *          {
             *              if (!frontFacing)
             *              {
             *                  Handles.color = Color.white;// grey;
             *                  Handles.DrawDottedLine(a, b, 2);
             *              }
             *          }
             *          else if (frontFacing)
             *          {
             *              Handles.DrawBezier(a, b, a, b, Color.white, null, 6);
             *          }
             *      }*/
        }
        internal void EditVolume(Occluder occluder)
        {
            if (occluder.Mesh == null)
            {
                return;
            }

            var ctx = occluder.Context;

            ctx.ComputeEdges();
            ctx.ComputeNormals();

            if (ctx.Dragging <= 0)
            {
                //ctx.ComputeFaces();
            }
            else
            {
                ctx.UpdateFaces();
            }

            int currentFaceId = ctx.Dragging;

            ctx.Dragging = -1;
            occluder.DebugRender();

            var mesh = occluder.Mesh;

            var verts   = mesh.vertices;
            var inverse = occluder.localTransform.inverse;

            // Render the back faces first, so that the hidden edges appear behind the handles
            RenderWireframe(ctx, occluder, mesh, verts, false);

            EditorGUI.BeginChangeCheck();

            var transform = occluder.localTransform;

            if (m_editMode == EditMode.Vertex)
            {
                EditVertices(ctx, mesh, verts, inverse, transform);
            }

            if (m_editMode == EditMode.Face)
            {
                EditFaces(ctx, currentFaceId, verts, inverse, transform);
            }

            // Render the front faces
            RenderWireframe(ctx, occluder, mesh, verts, true);

            if (EditorGUI.EndChangeCheck())
            {
                Undo.RegisterCompleteObjectUndo(occluder.Mesh, "Edit occluder volume");
                //            Undo.RecordObject(occluder.Mesh, "Edit occluder vertices");

                occluder.Mesh.SetVertices(verts);
                occluder.Mesh.RecalculateNormals();
                occluder.Mesh.RecalculateBounds();
                occluder.Mesh.MarkModified();

                PrefabUtility.RecordPrefabInstancePropertyModifications(occluder.Mesh);
            }

            if (m_editMode == EditMode.Mesh)
            {
                EditorGUI.BeginChangeCheck();
                var pos   = occluder.LocalPosition;
                var rot   = occluder.LocalRotation;
                var scale = occluder.LocalScale;

                Handles.TransformHandle(ref pos, ref rot, ref scale);

                if (EditorGUI.EndChangeCheck())
                {
                    Undo.RecordObject(occluder, "Modify occluder transform");

                    occluder.LocalPosition = pos;
                    occluder.LocalRotation = rot;
                    occluder.LocalScale    = scale;

                    PrefabUtility.RecordPrefabInstancePropertyModifications(occluder);
                }
            }
        }
        public override void OnToolGUI(EditorWindow window)
        {
            if (s_Contents == null)
            {
                s_Contents = new Contents();
            }

            Occluder occluder = (Occluder)target;

            switch (occluder.Type)
            {
            case Occluder.OccluderType.Mesh:
                EditMesh(occluder);
                break;

            case Occluder.OccluderType.Volume:
                int background = GUIUtility.GetControlID(FocusType.Passive);
                HandleUtility.AddDefaultControl(background);

                Handles.BeginGUI();
                switch (m_editMode)
                {
                case EditMode.Mesh:
                    GUILayout.BeginArea(new Rect {
                        x = 10, y = 10, width = 250, height = 85
                    }, "Mesh mode", GUI.skin.window);
                    GUILayout.Label("Use shift to align the transform gizmo");
                    GUILayout.Label("to the view");
                    break;

                case EditMode.Face:
                    GUILayout.BeginArea(new Rect {
                        x = 10, y = 10, width = 250, height = 85
                    }, "Face mode", GUI.skin.window);
                    break;

                case EditMode.Vertex:
                    GUILayout.BeginArea(new Rect {
                        x = 10, y = 10, width = 250, height = 85
                    }, "Vertex mode", GUI.skin.window);
                    GUILayout.Label("Use shift to (de)select multiple vertices.");
                    GUILayout.Label("Click and drag for marquee selection.");
                    break;
                }
                GUILayout.EndArea();

                Rect p            = window.position;
                int  toolBarWidth = 110;
                GUILayout.BeginArea(new Rect {
                    x = (p.width - toolBarWidth) / 2, y = 10, width = toolBarWidth, height = 80
                });
                using (new GUILayout.HorizontalScope())
                {
                    bool editMesh  = (m_editMode == EditMode.Mesh);
                    bool editVerts = (m_editMode == EditMode.Vertex);
                    bool editFaces = (m_editMode == EditMode.Face);

                    var newEditMesh  = !GUILayout.Toggle(!editMesh, GUIContents.editMeshIcon, "Button");
                    var newEditVerts = !GUILayout.Toggle(!editVerts, GUIContents.editVertexIcon, "Button");
                    var newEditFaces = !GUILayout.Toggle(!editFaces, GUIContents.editFaceIcon, "Button");

                    if (newEditMesh && !editMesh)
                    {
                        m_editMode = EditMode.Mesh;
                    }
                    else if (newEditVerts && !editVerts)
                    {
                        m_editMode = EditMode.Vertex;
                    }
                    else if (newEditFaces && !editFaces)
                    {
                        m_editMode = EditMode.Face;
                    }
                }
                GUILayout.EndArea();
                Handles.EndGUI();

                if (m_editMode == EditMode.Vertex)
                {
                    UpdateSelection();
                }

                EditVolume(occluder);
                break;
            }
        }
 public OccluderVolumeEditingContext(Occluder occluder)
 {
     Occluder        = occluder;
     VertexSelection = new HashSet <int>();
 }