private static void EditFaces(OccluderVolumeEditingContext ctx, int currentFaceId, Vector3[] verts, Matrix4x4 inverse, Matrix4x4 transform)
        {
            foreach (var face in ctx.faces)
            {
                var id = GUIUtility.GetControlID(FocusType.Passive);

                var centroid = transform.MultiplyPoint(face.centroid);
                var normal   = Vector3.Normalize(transform.MultiplyVector(face.normal));

                if (currentFaceId != id && Vector3.Dot(normal, Camera.current.transform.position - centroid) < 0)
                {
                    continue;
                }

                float   size = HandleUtility.GetHandleSize(centroid) * 0.5f;
                Vector3 snap = Vector3.one * 0.5f;

                Handles.color = Color.yellow;

                // draw a small X at the arrow origin to make it easier to see where it starts
                var u = Vector3.Cross(normal, transform.GetColumn(1));
                if (Vector3.SqrMagnitude(u) < 0.1f)
                {
                    u = Vector3.Cross(normal, transform.GetColumn(0));
                }
                u = Vector3.Normalize(u);
                var v = Vector3.Normalize(Vector3.Cross(normal, u));

                Handles.DrawLine(centroid - (u + v) * 0.1f, centroid + (u + v) * 0.1f);
                Handles.DrawLine(centroid - (u - v) * 0.1f, centroid + (u - v) * 0.1f);
                Handles.CircleHandleCap(-1, centroid, Quaternion.LookRotation(normal, u), 0.1f * Mathf.Sqrt(2), EventType.Repaint);

                var newCentroid = Handles.Slider(id, centroid, normal, size * 1.5f, Handles.ArrowHandleCap, 0.5f);

                if (GUIUtility.hotControl == id)
                {
                    ctx.Dragging = id;
                }

                newCentroid = centroid + math.dot(newCentroid - centroid, normal) * normal;
                var dn = inverse.MultiplyVector(newCentroid - centroid);

                for (int i = 0; i < face.vertices.Length; i++)
                {
                    verts[face.vertices[i]] += dn;
                }
            }
        }
        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);
             *          }
             *      }*/
        }
        private void EditVertices(OccluderVolumeEditingContext ctx, Mesh mesh, Vector3[] verts, Matrix4x4 inverse, Matrix4x4 transform)
        {
            var transformed = new Vector3[mesh.vertexCount];

            var marqueeSize = (marqueeEnd - marqueeStart);

            marqueeSize.Set(Mathf.Abs(marqueeSize.x), Mathf.Abs(marqueeSize.y));

            Rect marqueeRect = new Rect
            {
                x      = Mathf.Min(marqueeStart.x, marqueeEnd.x),
                y      = Mathf.Min(marqueeStart.y, marqueeEnd.y),
                width  = marqueeSize.x,
                height = marqueeSize.y
            };

            for (int i = 0; i < mesh.vertexCount; i++)
            {
                var p = transform.MultiplyPoint(verts[i]);
                transformed[i] = p;
            }

            if (marqueeSelectionEnded)
            {
                marqueeSelectionEnded = false;

                for (int i = 0; i < mesh.vertexCount; i++)
                {
                    var screenPoint = HandleUtility.WorldToGUIPoint(transformed[i]);
                    if (marqueeRect.Contains(screenPoint))
                    {
                        ctx.VertexSelection.Add(i);
                    }
                }
            }

            for (int i = 0; i < mesh.vertexCount; i++)
            {
                var p = transformed[i];

                float   size = HandleUtility.GetHandleSize(p) * 0.5f;
                Vector3 snap = Vector3.one * 0.5f;

                bool isSelected = ctx.VertexSelection.Contains(i);
                Handles.color = isSelected ? Handles.selectedColor : Color.grey;

                if (marqueeSelection)
                {
                    var screenPoint = HandleUtility.WorldToGUIPoint(p);
                    if (marqueeRect.Contains(screenPoint))
                    {
                        Handles.color = Handles.preselectionColor;
                    }
                }

                if (isSelected)
                {
                    size *= 1.2f;
                }

                if (Handles.Button(p, Quaternion.identity, 0.5f * size, size, Handles.SphereHandleCap))
                {
                    if (Event.current.modifiers == EventModifiers.Shift)
                    {
                        if (isSelected)
                        {
                            // deselect in a multiselection
                            ctx.VertexSelection.Remove(i);
                        }
                        else
                        {
                            ctx.VertexSelection.Add(i);
                        }
                    }
                    else
                    {
                        ctx.VertexSelection.Clear();
                        if (!isSelected)
                        {
                            ctx.VertexSelection.Add(i);
                        }
                    }
                }

                verts[i] = inverse.MultiplyPoint(p);
            }

            var selectedVertexCount = ctx.VertexSelection.Count;

            if (selectedVertexCount > 0)
            {
                var center = Vector3.zero;
                foreach (var v in ctx.VertexSelection)
                {
                    center += transformed[v];
                }
                center /= selectedVertexCount;

                float   size = HandleUtility.GetHandleSize(center) * 0.5f;
                Vector3 snap = Vector3.one * 0.5f;

                foreach (var v in ctx.VertexSelection)
                {
                    var p = transformed[v];
                    Handles.color = Color.magenta;
                    Handles.DrawDottedLine(p, center, 1);
                }


                var delta = Vector3.zero;

                foreach (var v in ctx.VertexSelection)
                {
                    var p = transformed[v];

                    Handles.color = Color.red;
                    var newX = Handles.Slider(p, transform.GetColumn(0), size * 1.5f, Handles.ArrowHandleCap, 0.5f);
                    Handles.color = Color.green;
                    var newY = Handles.Slider(p, transform.GetColumn(1), size * 1.5f, Handles.ArrowHandleCap, 0.5f);
                    Handles.color = Color.blue;
                    var newZ = Handles.Slider(p, transform.GetColumn(2), size * 1.5f, Handles.ArrowHandleCap, 0.5f);

                    delta += newX + newY + newZ - p * 3;
                }

                delta = inverse.MultiplyVector(delta);
                foreach (var v in ctx.VertexSelection)
                {
                    verts[v] += delta;
                }
            }
        }