gradientspace / geometry3Sharp

C# library for 2D/3D geometric computation, mesh algorithms, and so on. Boost license.
http://www.gradientspace.com
Boost Software License 1.0
1.7k stars 383 forks source link

random points to mesh #96

Open ghost opened 5 years ago

ghost commented 5 years ago

Hi Ryan, is it possible to generate a set of random points and then generate a concave mesh around them? I am an artist who can code a bit and i use unity c#. Problem is that i dont have the triangles when i just have random points and the delaunay triangulation is only 2d. As far as i understand you can do this with Surfacing Point Sets? But i dont get how to get my random points into the PointSet.

DMesh3 pointSet = DMesh3Builder.Build(); <- Random Points ?? PointAABBTree3 bvtree = new PointAABBTree3(pointSet, true); ...

Sorry for this simple question :) Thanks, Chris

Godatplay commented 5 years ago

Yeah Build() takes ~vertices~ points, but the part that is tripping me up is the triangles parameter.

I figured I could add three values of the ~vertex's~ point's index to the triangle list in my for loop, but that throws an out of bounds exception.

If I only add one value per vertex to the triangle list, that throws an out of bounds exception in a different place.

Godatplay commented 5 years ago

Here's my test code FWIW

      Mesh unityMesh = _meshGO.GetComponent<MeshFilter>().mesh;

      MeshUtilities.StartPointGeneration(unityMesh);

      List<Vector3d> points = new List<Vector3d>();
      List<int> tris = new List<int>();
      List<Vector3d> normals = new List<Vector3d>();
      for (int i = 0; i < pointsResolution; i++)
      {
        Vector3 normal = Vector3.one;
        Vector3 p = MeshUtilities.GetRandomPointOnMesh(pointsTowardVertsBias, out normal);

        float min = 1f - (pointsJitterAmount / 2f);
        float max = 1f + (pointsJitterAmount / 2f);
        p *= UnityEngine.Random.Range(min, max);

        points.Add(new Vector3d(p.x, p.y, p.z));
        tris.Add(i);
        tris.Add(i);
        tris.Add(i);
        normals.Add(new Vector3d(normal.x, normal.y, normal.z));
      }

      MeshUtilities.FinishPointGeneration();

      DMesh3 pointSet = DMesh3Builder.Build(points, tris, normals);
      PointAABBTree3 pointBVTree = new PointAABBTree3(pointSet, true);
      // estimate point area based on nearest-neighbour distance
      double[] areas = new double[pointSet.MaxVertexID];
      foreach (int vertID in pointSet.VertexIndices())
      {
        pointBVTree.PointFilterF = (i) => { return i != vertID; };   // otherwise vid is nearest to vid!
        int nearestVertID = pointBVTree.FindNearestPoint(pointSet.GetVertex(vertID));
        double dist = pointSet.GetVertex(vertID).Distance(pointSet.GetVertex(nearestVertID));
        areas[vertID] = Circle2d.RadiusArea(dist);
      }
      pointBVTree.FWNAreaEstimateF = (vid) => {
        return areas[vid];
      };

      MarchingCubes mc = new MarchingCubes();
      mc.Implicit = new PWNImplicit() { Spatial = pointBVTree };
      mc.IsoValue = 0.0;
      mc.CubeSize = pointBVTree.Bounds.MaxDim / implicitSurfaceCellCount;
      mc.Bounds = pointBVTree.Bounds.Expanded(mc.CubeSize * 3);
      mc.RootMode = MarchingCubes.RootfindingModes.Bisection;
      mc.Generate();
      DMesh3 resultMesh = mc.Mesh;
      g3UnityUtils.SetGOMesh(_meshGO, resultMesh);

PWNImplicit comes from http://www.gradientspace.com/tutorials/2018/9/14/point-set-fast-winding

Godatplay commented 5 years ago

Ok, I've been able to determine that my code does in fact work, but it seems only for lower sample counts. Somewhere around 64 points is when things start to break down and trigger either one of two array bounds exceptions, or it just freezes the Unity editor.

Godatplay commented 5 years ago

Ohhh k, got it. It was unclear that you need to call FastWindingNumber() first before using it for PointAABBTree3 like you do for using it with Dmesh3AABBTree3. Adding that fixed the issue.

DMesh3 pointSet = DMesh3Builder.Build(points, tris, normals);
PointAABBTree3 pointBVTree = new PointAABBTree3(pointSet, true);
pointBVTree.FastWindingNumber(Vector3d.Zero);  // build approximation also needed for points
dumitrugrl commented 4 years ago

What is the value of implicitSurfaceCellCount?