Beispiel #1
0
    //Display a mesh, which is called from the coroutine when a mesh has changed
    public void DisplayMesh(HashSet <HalfEdgeFace3> meshDataUnNormalized, MeshFilter mf)
    {
        //Generate a mesh
        MyMesh myMesh = HalfEdgeData3.ConvertToMyMesh("Main visualization mesh", meshDataUnNormalized, MyMesh.MeshStyle.HardEdges);

        Mesh mesh = myMesh.ConvertToUnityMesh(generateNormals: true);

        mf.mesh = mesh;

        //Debug.Log(mesh.triangles.Length);
    }
    void Start()
    {
        vertices_Unity = new HashSet <UnityEngine.Vector3>();

        for (int i = 0; i < pointCount; i++)
        {
            UnityEngine.Vector3 point = srcMesh.mesh.GetRandomPointInsideNonConvex(srcMesh.GetComponent <Renderer>().bounds.center);
            vertices_Unity.Add(point);
        }



        HashSet <Vector3> points            = new HashSet <Vector3>(vertices_Unity.Select(x => x.ToMyVector3()));
        Normalizer3       normalizer        = new Normalizer3(new List <Vector3>(points));
        HashSet <Vector3> points_normalized = normalizer.Normalize(points);

        //Convex Hull


        HalfEdgeData3 convexHull_normalized = _ConvexHull.Iterative_3D(points_normalized, removeUnwantedTriangles: false, normalizer);
        //HalfEdgeData3 convexHull_unnormalized = _ConvexHull.Iterative_3D(points, removeUnwantedTriangles: false, normalizer);

        var tmp = convexHull_normalized.ConvertToMyMesh("Triangulated Points", MyMesh.MeshStyle.HardEdges);

        delaunayMesh = tmp.ConvertToUnityMesh(true);

        // if (convexHull_normalized == null)
        // {
        //     Debug.LogError("ConvexHull is null");
        //     return;
        // }
        //
        HashSet <VoronoiCell3> voronoiCells_normalized = _Voronoi.Delaunay3DToVoronoi(convexHull_normalized);

        HalfEdgeData3 convexHull = normalizer.UnNormalize(convexHull_normalized);

        MyMesh myMesh = convexHull.ConvertToMyMesh("convex hull aka delaunay triangulation", MyMesh.MeshStyle.HardEdges);

        delaunayMesh = myMesh.ConvertToUnityMesh(generateNormals: false);


        //Voronoi
        HashSet <VoronoiCell3> voronoiCells = normalizer.UnNormalize(voronoiCells_normalized);

        //Generate a mesh for each separate cell
        voronoiCellsMeshes = GenerateVoronoiCellsMeshes(voronoiCells);

        foreach (var mesh in voronoiCellsMeshes)
        {
            GameObject go         = new GameObject();
            var        meshfilter = go.AddComponent <MeshFilter>();
            var        renderer   = go.AddComponent <MeshRenderer>();
            renderer.sharedMaterial = material;
            meshfilter.mesh         = mesh;
            go.transform.parent     = gameObject.transform;
        }


        //Generate a single mesh for all cells where each vertex has a color belonging to that cell
        //Now we can display the mesh with an unlit shader where each vertex is associated with a color belonging to that cell
        //The problem is that the voronoi cell is not a flat surface on the mesh
        //But it looks flat if we are using an unlit shader
        // Mesh oneMesh = GenerateAndDisplaySingleMesh(voronoiCellsMeshes);
        //
        // if (meshFilter != null)
        // {
        //     meshFilter.mesh = oneMesh;
        // }
        // else
        // {
        //     Debug.LogError("Meshfilter is null");
        // }
    }
Beispiel #3
0
    //Generates points, delaunay triangulation, and voronoi diagram
    public void Generate()
    {
        if (radius <= 0f)
        {
            radius = 0.01f;
        }
        if (numberOfPoints < 4)
        {
            numberOfPoints = 4;
        }

        //Get random points in 3d space
        points_Unity = TestAlgorithmsHelpMethods.GenerateRandomPointsOnSphere(seed, radius, numberOfPoints);

        //To MyVector3
        HashSet <MyVector3> points = new HashSet <MyVector3>(points_Unity.Select(x => x.ToMyVector3()));

        //Normalize
        Normalizer3 normalizer = new Normalizer3(new List <MyVector3>(points));

        HashSet <MyVector3> points_normalized = normalizer.Normalize(points);


        System.Diagnostics.Stopwatch timer = new System.Diagnostics.Stopwatch();


        //
        // Generate the convex hull, which is the same as the Delaunay triangulation of points on the sphere
        //

        //Iterative algorithm
        timer.Start();

        HalfEdgeData3 convexHull_normalized = _ConvexHull.Iterative_3D(points_normalized, removeUnwantedTriangles: false, normalizer);

        timer.Stop();

        Debug.Log($"Generated a 3d convex hull in {timer.ElapsedMilliseconds / 1000f} seconds");

        if (convexHull_normalized == null)
        {
            return;
        }



        //
        // Generate the voronoi diagram from the delaunay triangulation
        //
        timer.Restart();

        HashSet <VoronoiCell3> voronoiCells_normalized = _Voronoi.Delaunay3DToVoronoi(convexHull_normalized);

        timer.Stop();

        Debug.Log($"Generated a 3d voronoi diagram in {timer.ElapsedMilliseconds / 1000f} seconds");

        if (voronoiCells_normalized == null)
        {
            return;
        }


        //
        // Display
        //

        //Delaunay
        HalfEdgeData3 convexHull = normalizer.UnNormalize(convexHull_normalized);

        MyMesh myMesh = convexHull.ConvertToMyMesh("convex hull aka delaunay triangulation", MyMesh.MeshStyle.HardEdges);

        delaunayMesh = myMesh.ConvertToUnityMesh(generateNormals: false);


        //Voronoi
        HashSet <VoronoiCell3> voronoiCells = normalizer.UnNormalize(voronoiCells_normalized);

        //Generate a mesh for each separate cell
        voronoiCellsMeshes = GenerateVoronoiCellsMeshes(voronoiCells);

        //Generate a single mesh for all cells where each vertex has a color belonging to that cell
        //Now we can display the mesh with an unlit shader where each vertex is associated with a color belonging to that cell
        //The problem is that the voronoi cell is not a flat surface on the mesh
        //But it looks flat if we are using an unlit shader
        Mesh oneMesh = GenerateAndDisplaySingleMesh(voronoiCellsMeshes);

        if (meshFilter != null)
        {
            meshFilter.mesh = oneMesh;
        }
    }
    public void SimplifyMesh()
    {
        //Has to be sharedMesh if we are using Editor tools
        Mesh meshToSimplify = meshFilterToSimplify.sharedMesh;


        //
        // Change data structure and normalize
        //

        //Mesh -> MyMesh
        MyMesh myMeshToSimplify = new MyMesh(meshToSimplify);

        //Normalize to 0-1
        Normalizer3 normalizer = new Normalizer3(myMeshToSimplify.vertices);

        //We only need to normalize the vertices
        myMeshToSimplify.vertices = normalizer.Normalize(myMeshToSimplify.vertices);

        HalfEdgeData3 myMeshToSimplify_HalfEdge = new HalfEdgeData3(myMeshToSimplify, HalfEdgeData3.ConnectOppositeEdges.Fast);



        //
        // Simplify
        //

        System.Diagnostics.Stopwatch timer = new System.Diagnostics.Stopwatch();

        timer.Start();

        HalfEdgeData3 mySimplifiedMesh_HalfEdge = MeshSimplification_QEM.Simplify(myMeshToSimplify_HalfEdge, maxEdgesToContract: 2400, maxError: Mathf.Infinity, normalizeTriangles: true);

        timer.Stop();

        Debug.Log($"It took {timer.ElapsedMilliseconds / 1000f} seconds to simplify the mesh");



        //
        // Change data structure and un-normalize
        //

        timer.Reset();
        timer.Start();

        //From half-edge to mesh
        MyMesh mySimplifiedMesh = mySimplifiedMesh_HalfEdge.ConvertToMyMesh("Simplified mesh", MyMesh.MeshStyle.HardEdges);

        //Un-Normalize
        mySimplifiedMesh.vertices = normalizer.UnNormalize(mySimplifiedMesh.vertices);

        //Convert to global space
        Transform trans = meshFilterToSimplify.transform;

        mySimplifiedMesh.vertices = mySimplifiedMesh.vertices.Select(x => trans.TransformPoint(x.ToVector3()).ToMyVector3()).ToList();

        //Convert to mesh
        Mesh unitySimplifiedMesh = mySimplifiedMesh.ConvertToUnityMesh(generateNormals: true, meshName: "simplified mesh");

        //Attach to new game object
        meshFilterToShowSimplifiedMesh.mesh = unitySimplifiedMesh;

        timer.Stop();

        Debug.Log($"It took {timer.ElapsedMilliseconds / 1000f} seconds to finalize the mesh after simplifying");
    }
    //Called from editor script
    public void GenerateHull()
    {
        //Get random points in 3d space
        HashSet <Vector3> points_Unity = TestAlgorithmsHelpMethods.GenerateRandomPoints3D(seed, halfMapSize, numberOfPoints);

        //HashSet<Vector3> points_Unity = GetCubeTestPoints();

        //Points from a mesh

        /*
         * Transform meshTrans = constructHullFromThisMesh.transform;
         *
         * List<Vector3> vertices = new List<Vector3>(constructHullFromThisMesh.sharedMesh.vertices);
         *
         * //Local to global space
         * List<Vector3> verticesGlobal = vertices.Select(x => meshTrans.TransformPoint(x)).ToList();
         *
         * HashSet<Vector3> points_Unity = new HashSet<Vector3>(verticesGlobal);
         */

        //To stress-test these algorithms, generate points on a sphere because all of those should be on the hull
        //HashSet<Vector3> points_Unity = TestAlgorithmsHelpMethods.GenerateRandomPointsOnSphere(seed, radius: 1f, numberOfPoints);

        //To MyVector3
        HashSet <MyVector3> points = new HashSet <MyVector3>(points_Unity.Select(x => x.ToMyVector3()));

        //Normalize
        Normalizer3 normalizer = new Normalizer3(new List <MyVector3>(points));

        HashSet <MyVector3> points_normalized = normalizer.Normalize(points);



        //
        // Generate the convex hull
        //

        //Algorithm 1. Iterative algorithm

        System.Diagnostics.Stopwatch timer = new System.Diagnostics.Stopwatch();

        timer.Start();

        HalfEdgeData3 convexHull_normalized = _ConvexHull.Iterative_3D(points_normalized, removeUnwantedTriangles, normalizer);

        timer.Stop();

        Debug.Log($"Generated a 3d convex hull in {timer.ElapsedMilliseconds / 1000f} seconds with {convexHull_normalized.faces.Count} triangles");



        //
        // Display
        //

        //Points
        //TestAlgorithmsHelpMethods.DisplayPoints(points_Unity, 0.01f, Color.black);


        //Hull mesh
        if (convexHull_normalized != null)
        {
            HalfEdgeData3 convexHull = normalizer.UnNormalize(convexHull_normalized);

            MyMesh myMesh = convexHull.ConvertToMyMesh("convex hull", MyMesh.MeshStyle.HardEdges);

            //To unity mesh
            Mesh convexHullMesh = myMesh.ConvertToUnityMesh(generateNormals: false, myMesh.meshName);

            //Using gizmos to display mesh in 3d space gives a bad result
            //TestAlgorithmsHelpMethods.DisplayMeshWithRandomColors(convexHullMesh, 0);

            //Better to add it to a gameobject
            //Use Shaded Wireframe to see the triangles
            meshFilter.mesh = convexHullMesh;

            //Points on the hull
            //These are shining thorugh the mesh
            //TestAlgorithmsHelpMethods.DisplayMeshCorners(convexHullMesh, 0.01f, Color.black);
        }
    }