nortikin / sverchok

Sverchok
http://nortikin.github.io/sverchok/
GNU General Public License v3.0
2.26k stars 234 forks source link

Marching_cubes with pymcubes, skimage and sverchok #1549

Closed kalwalt closed 7 years ago

kalwalt commented 7 years ago

Pymcubes is a python module with a marching cubes algorithm. In the simple example that i provide it simply plot a sphere. You can set the bounds, the number of samples in each dimension, and the iso surface level. The sphere is defined by the function f; of course you can use what function you desire. You must install the module in the python 3 location and then import it with the sys importing statement.

import sys
mcubes_path = r"/usr/local/lib/python3.5/dist-packages" #it depend on your OS but just paste the path where is mcubes
if not mcubes_path in sys.path:
    sys.path.append(mcubes_path)    
import mcubes

change your path accordingly. to install pymcubes i used pip:

pip3 install pymcubes

it requires also pycollada and cython.

pymcubes_test

"""
in bounds s d=10 n=2
in iso_val s d=8.0 n=2
in samples s d=100 n=2
out vertices v
out triangles s
"""

import numpy as np
import sys
mcubes_path = r"/usr/local/lib/python3.5/dist-packages" #it depend on your OS but just paste the path where is mcubes
if not mcubes_path in sys.path:
    sys.path.append(mcubes_path)    
import mcubes

# Create the volume
def f(x, y, z):
    return x**2 + y**2 + z**2

# Create a data volume (30 x 30 x 30)
#X, Y, Z = np.mgrid[:100, :100, :100]
# u = (X-50)**2 + (Y-50)**2 + (Z-50)**2 - 25**2

# Extract the 0-isosurface
#verts, tri = mcubes.marching_cubes(u, 0)

# Extract the 16-isosurface
verts, tri = mcubes.marching_cubes_func(
        (-bounds, -bounds, -bounds), (bounds, bounds, bounds),  # Bounds
        samples, samples, samples,              # Number of samples in each dimension
        f,                          # Implicit function
        iso_val)                         # Isosurface value

vertices, triangles = verts.tolist(), tri.tolist()

you can take the script also here

kalwalt commented 7 years ago

multi_schwarz

multi schwarz ( i think it is called so...) with just a function call. this is the formula used:

math.cos(x) + math.cos(y) + math.cos(z)

notice the isovalue used ( do not use high values).

script here

kalwalt commented 7 years ago

hyperboloid hyperboloid with function:

x**2 + y**2 - z**2 - 0.3

zeffii commented 7 years ago

it can do metaballs? :)

kalwalt commented 7 years ago

it can do metaballs? :)

maybe, i will try to add a set of multi spheres,...

kalwalt commented 7 years ago

Bingo! metaballs_test with this script:

"""
in bounds s d=10 n=2
in iso_val s d=8.0 n=2
in samples s d=100 n=2
in factor s d=0.9 n=2
out vertices v
out triangles s
"""

import numpy as np
import sys
mcubes_path = r"/usr/local/lib/python3.5/dist-packages" #it depend on your OS but just paste the path where is scipy
if not mcubes_path in sys.path:
    sys.path.append(mcubes_path)    
import mcubes
import math

# Create the volume
def f(x, y, z):

    return ((x-factor)*(x-factor)+y*y+z*z-1)*((x+factor)*(x+factor)+y*y+z*z-1)-0.3

# Extract the 16-isosurface
verts, tri = mcubes.marching_cubes_func(
        (-bounds, -bounds, -bounds), (bounds, bounds, bounds),  # Bounds
        samples, samples, samples,              # Number of samples in each dimension
        f,                          # Implicit function
        iso_val)                         # Isosurface value

vertices, triangles = verts.tolist(), tri.tolist()

This only create two spheres but it can be developed a multi spheres version. https://github.com/kalwalt/sverchok_nodes_collection/blob/master/scripts/pymcubes/metaballs_test.py

kalwalt commented 7 years ago

Scikit image module has also marching cubes functions http://scikit-image.org/docs/dev/auto_examples/edges/plot_marching_cubes.html but i didn't tryed yet. I found this modules as possible replacement for polyvox lib that i used before https://github.com/nortikin/sverchok/issues/1168 as this has some issues....

zeffii commented 7 years ago

i'd like to see an example of multi verts for metaballs. very cool stuff.

kalwalt commented 7 years ago

i'd like to see an example of multi verts for metaballs. very cool stuff.

i will do later if i can.

nortikin commented 7 years ago

hm, will try at home just essentially needed stuff

kalwalt commented 7 years ago

ok thank you. I'm looking for the multi metaballs example. one difficult is that the function f must be in the form f(x, y, z) as described in the struct of the pywrapper.ccp:

struct PythonToCFunc
{
    PyObject* func;
    PythonToCFunc(PyObject* func) {this->func = func;}
    double operator()(double x, double y, double z)
    {
        PyObject* res = PyObject_CallFunction(func, "(d,d,d)", x, y, z); // py::extract<double>(func(x,y,z));
        if(res == NULL)
            return 0.0;

        double result = PyFloat_AsDouble(res);
        Py_DECREF(res);
        return result;
    }
};

https://github.com/pmneila/PyMCubes/blob/master/mcubes/src/pywrapper.cpp#L8

scorpion451 commented 7 years ago

anyone know a reason the script would fail to load mcubes on Windows? I swapped out the file path to "C:\Program Files\Python36\Lib\site-packages" but it keeps giving me an error about not being able to find mcube._mcube

enzyme69 commented 7 years ago

can it remesh Particles into something meshy?

kalwalt commented 7 years ago

@scorpion451 i don't know. But where is mcubes folder? in

C:\Program Files\Python36\Lib\site-packages

?

in my mcubes folder i have three files:

exporter.py
__init__.py
_mcubes.cpython-35m-x86_64-linux-gnu.so  # _this in Windows should be a .dll file_

can it remesh Particles into something meshy?

really i don't know @enzyme69: i'm testing the lib for now.

zeffii commented 7 years ago

@scorpion451 i suspect the problem could also be a mismatch between python 3.5 and your 3.6

kalwalt commented 7 years ago

TorusIso

pymcubes_torus

"""
in bounds s d=10 n=2
in iso_val s d=8.0 n=2
in samples s d=100 n=2
in r_i s d=5.0 n=2
in r_o s d=1.0 n=2
out vertices v
out triangles s
"""

import numpy as np
import sys
mcubes_path = r"/usr/local/lib/python3.5/dist-packages" #it depend on your OS but just paste the path where is mcubes
if not mcubes_path in sys.path:
    sys.path.append(mcubes_path)    
import mcubes
import math

# Create the volume
def f(x, y, z):

    # (sqrt(x*x+y*y)-3)^2+z*z-1 formula from MathMod
    res=(math.sqrt(x*x+y*y)-r_i)**2+z*z-r_o

    return res

# Extract the 16-isosurface

verts, tri = mcubes.marching_cubes_func(
    (-bounds, -bounds, -bounds), (bounds, bounds, bounds),  # Bounds
    samples, samples, samples,              # Number of samples in each dimension
    f,                          # Implicit function
    iso_val)                         # Isosurface value

vertices, triangles = [verts.tolist()], [tri.tolist()]

https://github.com/kalwalt/sverchok_nodes_collection/blob/master/scripts/pymcubes/torus_iso.py

kalwalt commented 7 years ago

Testing the scikit marching_cubes function: ellipsoid_skimage_test Example taken from here: http://scikit-image.org/docs/dev/auto_examples/edges/plot_marching_cubes.html Skimage marching cubes documentation: http://scikit-image.org/docs/dev/api/skimage.measure.html#marching-cubes The script i used:

"""
in sp s d=0.0 n=2
in iso_val s d=0.0 n=2
in step s d=1 n=2
in a s d=6 n=2
in b s d=10 n=2
in c s d=16 n=2
out vertices v
out faces s
"""

import numpy as np
import sys
scikit_path = r"/usr/local/lib/python3.5/dist-packages" # it depend on your OS but just paste the path where is scikit
if not scikit_path in sys.path:
    sys.path.append(scikit_path)
from skimage import measure
from skimage.draw import ellipsoid

# Generate a level set about zero of two identical ellipsoids in 3D
ellip_base = ellipsoid(a, b, c, 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
verts, faces, normals, values = measure.marching_cubes(
    ellip_double, level=iso_val,spacing=(sp, sp, sp), step_size=step)

vertices, faces = [verts.tolist()], [faces.tolist()]

https://github.com/kalwalt/sverchok_nodes_collection/blob/master/scripts/skimage/ellipsoid_skimage.py

scorpion451 commented 7 years ago

@kalwalt double checked, and I do have mcubes in my C:\Program Files\Python36\Lib\site-packages folder, with

exporter.py
__init__.py
_mcubes.cp36-win_amd64.pyd # .pyd is theoretically a "better dll" format for windows python

I just updated Python, so I'm going to try rolling back to 3.5.2, see if that makes any difference. EDIT: Turns out blender had been launching using my old python install because the update didn't change the path properly. Problem maybe solved.

scorpion451 commented 7 years ago

Okay, so now that I've got it working and played with it for a while: How can we make f = (interpolation/lerp/closest vertex/etc of an existing mesh)? Add that and a quadder to this, and I am seeing the holy grail of retopo tools here.

kalwalt commented 7 years ago

Okay, so now that I've got it working and played with it for a while:

@scorpion451 Happy, that you got it working!

How can we make f = (interpolation/lerp/closest vertex/etc of an existing mesh)?

This is sure possible. Probably given the Bounding Box of the mesh you can calculate the distance of every vertex from the center of the BB, so finding the values for the marching cubes algorithm. This is a feature that would fine have with Sverchok. but for now we can only develop some script or macro, because pymcubes can't be installed in blender python. I suggest also to try the scikit-image module as mentioned in a previous post in this issue. For now I'm testing the two modules to see what is more convenient to use.

nortikin commented 7 years ago
Unexpected error: <class 'ImportError'>
on line:  2
Traceback (most recent call last):
  File "/home/ololo/.config/blender/2.78/scripts/addons/sverchok/nodes/generator/script1_lite.py", line 348, in process_script
    exec(self.script_str, locals(), locals())
  File "<string>", line 16, in <module>
ImportError: No module named 'mcubes._mcubes'
mcubes_path = r"/usr/lib/python3.6/site-packages/" #it depend on your OS but just paste the path where is scipy
if not mcubes_path in sys.path:
    sys.path.append(mcubes_path)    
import mcubes

the same 3.6

kalwalt commented 7 years ago

@nortikin i think should match the python versions. Blender use python 3.5 (at least 2.78a) your system python installed is as i can see 3.6.

nortikin commented 7 years ago

the same 3.6 problem, i see

kalwalt commented 7 years ago

if you can you should install python 3.5 on your system and after thepymcubes module

nortikin commented 7 years ago
Traceback (most recent call last):
  File "/home/ololo/.config/blender/2.78/scripts/addons/sverchok/nodes/generator/script1_lite.py", line 348, in process_script
    exec(self.script_str, locals(), locals())
  File "<string>", line 16, in <module>
ImportError: No module named 'mcubes._mcubes'

have now 3.5

nortikin commented 7 years ago

how to point blender on locan python?

kalwalt commented 7 years ago

@nortikin now how is your mcubes_path?

nortikin commented 7 years ago

@kalwalt r"/usr/lib/python3.5/site-packages/mcubes/"

nortikin commented 7 years ago
  File "/usr/lib/python3.5/site-packages/mcubes/__init__.py", line 2, in <module>
    from ._mcubes import marching_cubes, marching_cubes_func
ImportError: No module named 'mcubes._mcubes'

from ._mcubes import marching_cubes, marching_cubes_func from .exporter import export_mesh, export_obj cannot see this file, only _mcubes.cpython-35m-x86_64-linux-gnu.so

kalwalt commented 7 years ago

try:

-r"/usr/lib/python3.5/site-packages/"
+r"/usr/lib/python3.5/site-packages"
nortikin commented 7 years ago

@kalwalt the problem in clean python3.5 under bash also, the same. It is something with python itself

  File "/home/ololo/.config/blender/2.78/scripts/addons/sverchok/nodes/generator/script1_lite.py", line 348, in process_script
    exec(self.script_str, locals(), locals())
  File "<string>", line 16, in <module>
ImportError: No module named 'mcubes._mcubes'
zeffii commented 7 years ago

try doing the imports directly in the Blender text editor, maybe snlite is not showing the full Exception.

kalwalt commented 7 years ago

Are you saying that you have this problem also outside sverchok/Blender? Did you try the pymcubes example? and from a python3.5 idle what you get running import mcubes?

nortikin commented 7 years ago
ololo@ololo:~/Downloads/blender-2.78-linux-glibc211-i686/2.78$ python3.5
Python 3.5.3 (default, Apr 22 2017, 20:09:34) 
[GCC 6.3.1 20170306] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import mcubes
>>> 

it is ok in outside

kalwalt commented 7 years ago

but your addon sverchok is in .config/blender/2.78/scripts/addons/sverchok my is in home/walter/blender2,78/scripts/addons could make a difference?

kalwalt commented 7 years ago

try to test the import in the blender python console.

kalwalt commented 7 years ago

with all theimport sys stuff, of course.

nortikin commented 7 years ago

import from blender console couse: ImportError: No module named 'mcubes._mcubes'

kalwalt commented 7 years ago

i would suggest to copy the mcubes folder to /path/to/blender-2.78/2.78/python/lib/python3.5/site-packages but i think it won't works because needs of Cython...

nortikin commented 7 years ago

import cython works, but not mcubes inside blender. all numpy, scipy import works, manjaro linux fails with blender + mcubes (((

kalwalt commented 7 years ago

i'm sad for this maybe open an issue on pymcubes github.

scorpion451 commented 7 years ago

What's your pythonpath set to? I could still launch blender when I had the path pointed to 3.6- I just got that error every time I tried to load mcubes. As soon as I changed my global pythonpath to 3.5 and installed mcubes there, everything worked fine,

nortikin commented 7 years ago

yes, it handles latest python, see now. Investigating dark side of linux now. numpy installation on python3.5 with pip go wrong, not see muiltiarray and so on

kalwalt commented 7 years ago

Investigating dark side of linux now. numpy installation on python3.5 with pip go wrong, not see muiltiarray and so on

never had this problems in Ubuntu, that's really strange. But you installed with sudo pip install? on Ubuntu64 for python3.5 should be sudo pip3 install 'module'

nortikin commented 7 years ago

used pip3.5 install pymcubes

kalwalt commented 7 years ago

Maybe pip it is not installing in the right location, try as suggested here: http://stackoverflow.com/questions/35261468/how-to-use-pip-with-python3-5-after-upgrade-from-3-4 python3.5 -m pip install package If blender had the option to install at least with pip, this process should be a lot easier and without isssues of this kind...

nortikin commented 7 years ago

changed yesturday the path in linux for python 3.5, o it uses site-packages 3.5, it fails import mcubes in bash also. so, mcubes or something installed wrong (maybe about environment verables was not set) continue to have this confrontation with linux

kalwalt commented 7 years ago

@nortikin i think it'is a issue related to path or the installation process. To be sure of the path where mcubes is: run pip show pymcubes in the console. Could be also an issue with permissions or conflict with a previuos installation.

kalwalt commented 7 years ago

pymcubes with noise array

...alias for voxel terrain creation

image

"""
in bounds s d=10 n=2
in iso_val s d=8.0 n=2
in noise s d=[] n=0
out vertices v
out triangles s
"""

import numpy as np
import random
import sys
mcubes_path = r"/usr/local/lib/python3.5/dist-packages" #it depend on your OS but just paste the path where is scipy
if not mcubes_path in sys.path:
    sys.path.append(mcubes_path)    
import mcubes

# Create a data volume
X, Y, Z = np.mgrid[:bounds, :bounds, :bounds]
n = np.array(noise)
u = np.reshape(n, (bounds,bounds,bounds))
v = Z * u

# Extract the 0-isosurface
verts, tri = mcubes.marching_cubes(v, iso_val)

vertices, triangles = [verts.tolist()], [tri.tolist()]

It's not the best solution but it something that is very near to a terrain, To do this we need a 3d grid of points for create a 3d noise texture, we can't use a plane node to create that grid nor the box node so i used the range float nodes to vectorize, and after a list repeater. Maybe we can devekop a script for a grid mesh.

zeffii commented 7 years ago

@kalwalt i made np grids a whileback.. https://github.com/nortikin/sverchok/issues/942#issuecomment-262976864

kalwalt commented 7 years ago

@kalwalt i made np grids a whileback.. #942 (comment)

Good to know, this is exactly what i need!