Hemesh: Create mesh from points (or alternative to HEC_ConvexHull)

Hi there,

I am currently working on a project that creates a 3D mesh from a set of points. These points have been translated from latitude/longitude coordinates and a depth. I have used a HEC_Geodesic icosahedron as a base shape, which then gradually gets deformed over time as more points get added.

I can't post the entire codebase as there's a lot more going on, but this is the important stuff.

public Globe( ArrayList<GlobePoint> points ) { this.points = points; this.creator = new HEC_Geodesic(); this.creator.setRadius( Configuration.Mesh.GlobeSize ); this.creator.setB( 1 ); this.creator.setC( 1 ); this.creator.setType( HEC_Geodesic.ICOSAHEDRON ); this.icosahedron = new HE_Mesh( creator ); this.icosahedronPoints = icosahedron.getPoints(); this.fillBuffer(); }

public WB_Point[] getPoints( ) { return this.points; }

I then use a HEC_ConvexHull to create a mesh from the points returned by the getPoints() method of the Globe class (which essentially merges the points from the Icosahedron, and the points added over time.

void drawMesh( color colour, WB_Point[] points ) { HEC_ConvexHull creatorGlobe = new HEC_ConvexHull(); WB_Render3D render = new WB_Render3D( this ); creatorGlobe.setPoints( points ); HE_Mesh globeMesh = new HE_Mesh( creatorGlobe ); noFill(); render.drawEdges( globeMesh ); render.drawPoints( globeMesh.getPoints(), 2 ); }

This is how the WB_Points are calculated. The depth is always between 0 and 1.

public static class Geography { public static WB_Point CoordinatesToWBPoint( double latitude, double longitude, double radius, double depth ) { double phi = (90-latitude)*(Math.PI/180); double theta = (longitude+180)*(Math.PI/180); double x = ((radius) * Math.sin(phi)*Math.cos(theta)); double z = ((radius) * Math.sin(phi)*Math.sin(theta)); double y = -((radius) * Math.cos(phi)); double scale = ( depth / Configuration.Data.Depth.Max ); WB_Point point = new WB_Point( x, y, z ).scale( 1 - scale ); return point; } }

Now, I suppose it's expected behaviour that the convex hull ignores any points below the surface, because they simply don't show up at all. This is just the basic Icosahedron.

Screenshot:

If I change this line however so that the scale is 1 PLUS the depth scale, instead of MINUS, the points show up again, which I guess is also expected.

WB_Point point = new WB_Point( x, y, z ).scale( 1 + scale );

Screenshot:

My question essentially is: Is there a way to easily create a mesh from a WB_Point[] array that will include/connect every point? I can't seem to find anything in the Hemesh source code that gets close to it, so I assume it's a bit more involved.

Answers

  • edited May 2018

    Not sure it will help but here is my two cents.

    If I'm not mistaken the best you can do to achieve this (connecting points from a WB_Point[] array) with the Hemesh library is using the alphaTriangulate3D() method.

    Here's a quick example, it's in Python but really easy to understand:

    add_library('hemesh')
    
    phi = (sqrt(5) + 1) / 2 - 1 
    angle = phi * 2 * PI 
    n_points, radius = 300, 200
    liste = []
    
    def setup():
        global triangles, render
        size(600, 600, P3D)
        smooth(8)
        render = WB_Render(this)
    
        for p in range(n_points):
            lon = angle * p
            lon /= 2 * PI; lon -= floor(lon); lon *= 2 * PI
            if lon > PI: lon -= 2 * PI 
            lat = asin(-1 + 2 * p / float(n_points))
            new_points = WB_Point(radius * cos(lat) * cos(lon), radius * cos(lat) * sin(lon), radius * sin(lat))
            liste.append(new_points)
    
        triangulation = WB_Triangulate.alphaTriangulate3D(liste)
        triangles = triangulation.getAlphaTriangles(radius+1)
    
        noFill()
        beginShape(TRIANGLES)
    
    def draw():
        background(255)
    
        translate(width/2, height/2)
        for i in range(0, len(triangles), 3):
            point(liste[triangles[i]].xd(), liste[triangles[i]].yd(), liste[triangles[i]].zd())
            render.drawTriangle(liste[triangles[i]], liste[triangles[i+1]], liste[triangles[i+2]])
    

    • liste is the WB_Point[] array list
    • points are projected on a Fibonacci sphere (based on jeremydouglass's script) and then triangulated with the alphaTriangulate3D(liste) method.
    • It's important to keep the threshold just above the radius to get a perfect triangulation between equidistant points: triangulation.getAlphaTriangles(radius+1)

    Now, if you want to create a mesh from an array of points distributed on a 3D plane rather than around a sphere, I'd suggest to use the Triangulate library instead. You can find a 2D example here and a 3D example here.

Sign In or Register to comment.