2
$\begingroup$

for my current project i try to solve the following problem:

My starting point is an arbitrary point cloud consisting of 3D-Coordinates that is to be voxelized to form a regular scalar field.

--> From this regular scalar field the extraction of an isosurface should be performed within Blender.

The hurdle to overcome is that i am not going to use the Marching Cubes algorithm, which is perfectly working as it is implemented in the skimage.measures module of python and can be achieved by running the following code. (The package skimage has to be copied to the following path 'Blender Foundation\Blender\2.77\python\lib\site-packages'). Maybe also the package scipy.

import numpy as np
import bpy
from skimage import measure
from skimage.draw import ellipsoid

def createMeshFromData(name, origin, verts, faces):
    # Create mesh and object
    me = bpy.data.meshes.new(name+'Mesh')
    ob = bpy.data.objects.new(name, me)
    ob.location = origin
    ob.show_name = True

    # Link object to scene and make active
    scn = bpy.context.scene
    scn.objects.link(ob)
    scn.objects.active = ob
    ob.select = True

    # Create mesh from given verts, faces.
    me.from_pydata(verts, [], faces)
    # Update mesh with new data
    me.update()    
    return ob

#http://scikit-image.org/docs/dev/auto_examples/plot_marching_cubes.html
# Generate a level set about zero of two identical ellipsoids in 3D
ellip_base = ellipsoid(6, 10, 16, levelset=True)
ellip_double = np.concatenate((ellip_base[:-1, ...],
                               ellip_base[2:, ...]), axis=0)
# Use marching cubes to obtain the surface mesh of these ellipsoids
isovalue = 0.5
# MC
verts, faces = measure.marching_cubes(ellip_double, isovalue)
# faces has to be of type int not int32numpy
ob = createMeshFromData('marching_cubes',(0,-30,0),verts,(faces.astype(int)).tolist())

# workaround to REMESH the MC-Mesh
ob2 = createMeshFromData('dual_contouring',(0,0,0),verts,(faces.astype(int)).tolist())

bpy.ops.object.modifier_add(type='REMESH')
bpy.context.object.modifiers["Remesh"].octree_depth = 5
bpy.context.object.modifiers["Remesh"].mode = 'SMOOTH'

My goal is now to substitute the Marching Cubes Algorithm by the Dual Contouring Algorithm by Ju, 2002. and extract an isosurface based on a certain isovalue from the voxelgrid.

The dual contouring source code is already available as c++ code written by the author of the paper here (https://github.com/aewallin/dualcontouring).

An extended version of the algorithm (Polymender - 'http://www.cs.wustl.edu/~taoju/code/polymender.htm') ) is also already implemented in the source code in form of the remesh modifier by Nicholas Bishop here (C:\blender-2.77a\intern\dualcon\intern)

The problem is that as the modifiers name connotes it needs a polygonal mesh as input and remeshes it using the Dual Contouring algorithm. It works basically in this three steps:

1. Scan-conversion: Embed the input model (figure 2 (a)) in a uniformly spaced grid, and mark edges on the grid that intersect the polygons as intersection edges. For efficiency, cells containing intersection edges are stored in an octree (figure 2 (b)).
2. Sign generation: At the grid points, generate signs that are consistent with the intersection edges, so that each cell edge intersecting the model should exhibit a sign change (figure 2 (c)).
3. Surface reconstruction: Reconstruct a closed surface on the signed grid by contouring. Dual contouring can be used to reproduce sharp features when Hermite data is stored on the intersection edges (figure 2 (d)).

The readme file from the Polymender software says the pure dual contouring c++ code files can take two kinds of input:

.dcf (Dual Contouring Format) and .sog (Signed Octree with Geometry).

Both formats store an octree grid with inside/outside signs. DCF contains intersection points and normals on grid edges, whereas SOG contains a single point location within each non-empty grid cell. Both formats can be produced from a polygonal model, via scan-conversion, using the Polymender software (Ju).

Is there any possibility to use at least parts of the already implemented source code in order to only extract an isosurface with dual contouring from a point cloud?

That means to jump in at for example step 3, the surface reconstruction, by for example providing the intersection points or the signed grid as .dcf or .sog file.

My initial thoughts were to calculate the interpolated intersections based on the isovalue from the voxelgrid and write them as Ju did in the octree grid as .dcf or .sog. After that maybe only the DC-code can be used to contour the grid.

Another general question regarding the way to achieve a project like this one is: What do you think is the most sophisticated way to access already existing c++ code within Blender? May i try to reuse/rewrite/abbreviate some of the already existing source code? or access the c++ library via ctypes in a python addon? I would like to hear your suggestions.

I hope anyone of you maybe has already done something with dual contouring in Blender too and is able to give me some advide. Thank you in advance!

Regards, Lukas

$\endgroup$

closed as off-topic by sambler, someonewithpc, Ray Mairlot, iKlsR Jun 3 '16 at 21:11

  • This question does not appear to be about Blender within the scope defined in the help center.
If this question can be reworded to fit the rules in the help center, please edit the question.

  • 3
    $\begingroup$ Questions about blender's code base are off-topic and better suited to stackoverflow. This is more of a "should I use python or c/c++ to do..." than asking for help with a python addon. $\endgroup$ – sambler Jun 3 '16 at 13:56
2
$\begingroup$

I would suggest looking at openvdb (which blender is starting to use) - it can perform volume to mesh and mesh to volume conversions. It may be that you can help finish incorporating openvdb support and directly use methods from openvdb to add what you want.

Another source would be the cubesurfer addon, it can take a particle system and make a surface mesh. This addon uses cython to generate c-code that gets compiled into a python module, making it a good example if you want to incorporate c/c++ code using an addon.

An addon has some limits - it cannot define a new modifier and it does not have access to every function available in blender's source code, this may be overcome using ctypes or cython but that level of work may mean that working within blender's code base will be just as easy.

If you are going to start working on blender's code and you want your work to be added to future versions of blender, I suggest talking to a developer on IRC at #blendercoders and get some feedback as to whether the work is a feature they would accept as well as get some tips on getting it accepted.

$\endgroup$

Not the answer you're looking for? Browse other questions tagged or ask your own question.