(works on Mac OMG) Voxel problem: 'Volume Cube' equivalent in gh


I am trying to replicate a Blender geometry node tutorial, and there is a component called Volume Cube Node — Blender Manual. It looks like this is something to do with voxels (a cube made out of voxels?). The closest I can think of is Voxel mesh, but I can’t figure out how to use it (it needs points and I don’t understand where these points come from in this project).

This component appears in 11:19 in the tutorial 4D objects in Blender! - YouTube

voxel_problem.gh (17.1 KB)

Many Thanks!

I haven’t been able to find any similar projects in gh

This seems to be 3D isosurfacing ! Nothing new

. Millipede was good at it but now there are also other tools.

… and counting

1 Like

Thanks for your help! Could you please share some insights on what this ‘volume cube’ function might be doing?

I rewatched the part of the video a few times, and it seems that it is a cube made of voxels? (a bunch of voxels that group up into a big cube?)

The part I was able to replicate in gh is calculating the movement of the voxels, I think.

I can’t help you with the file you provided.
We could help if you said what you want as output. Making a copy of a blender script without any idea of the output you want is a loss of time.

This is the mesh from the Fractal machine.

And a miserable fail using Dendro.

Bad Cables.gh (27.3 KB)

1 Like

Here’s what the output looks like (also see Quan’s reply above!). The first things I thought about are: noise, growth, reaction diffusion.

However these methods don’t seem to capture the elongated/stretched-out/rotational characteristic of the shape. It makes sense because according to the video, this is generated by formula.

In the file I have so far, I have the ‘formula’ part (calculating one vector from another). I think the missing piece for my file is turning the calculation into geometry

Thanks for your reply! I agree that there are differences from the tutorial’s results; however I think your result looks great!

It looks like fractal, Chimpanzee could be the tool to generate that.

1 Like

Thanks again for your help! This resource looks like a good place to start!

I think the method I use is very wrong.

I opend the GN nodes of Fractal Machine. Though basically I don’t know what I was looking at, I guess Bad Normal used some kind of SDF method, which you can do in GH with plugins, like Jellyfish.

1 Like

Unfortunately Chimpanzee 0.4. does not support quaternion Julia set, only 2D Julia set.

I have a Grasshopper script with C# for quaternion Julia set, however the code is unoptimised yet. I might include the component in Chimpanzee 0.5.

1 Like

From the tutorial, it appears that Blender doesn’t have any such functionality either (the calculation is done by basic math modules that gh of course also have). Could you please share some insights on how ‘quaternion Julia set’ calculations fit into creating a shape similar to the above pictures, and how the use of voxels come in play (if they do at all)? (I’m still exploring the Chimpanzee plugin)


Paul Bourke reference for many 3d things

1 Like

Thank you!

Not very hard to replicate the you tube video in Grasshopper, just seems less fast

using System.Threading.Tasks;

/// <summary>
/// This class will be instantiated on demand by the Script component.
/// </summary>
public class Script_Instance : GH_ScriptInstance
#region Utility functions
  /// <summary>Print a String to the [Out] Parameter of the Script component.</summary>
  /// <param name="text">String to print.</param>
  private void Print(string text) { /* Implementation hidden. */ }
  /// <summary>Print a formatted String to the [Out] Parameter of the Script component.</summary>
  /// <param name="format">String format.</param>
  /// <param name="args">Formatting parameters.</param>
  private void Print(string format, params object[] args) { /* Implementation hidden. */ }
  /// <summary>Print useful information about an object instance to the [Out] Parameter of the Script component. </summary>
  /// <param name="obj">Object instance to parse.</param>
  private void Reflect(object obj) { /* Implementation hidden. */ }
  /// <summary>Print the signatures of all the overloads of a specific method to the [Out] Parameter of the Script component. </summary>
  /// <param name="obj">Object instance to parse.</param>
  private void Reflect(object obj, string method_name) { /* Implementation hidden. */ }

#region Members
  /// <summary>Gets the current Rhino document.</summary>
  private readonly RhinoDoc RhinoDocument;
  /// <summary>Gets the Grasshopper document that owns this script.</summary>
  private readonly GH_Document GrasshopperDocument;
  /// <summary>Gets the Grasshopper script component that owns this script.</summary>
  private readonly IGH_Component Component;
  /// <summary>
  /// Gets the current iteration count. The first call to RunScript() is associated with Iteration==0.
  /// Any subsequent call within the same solution will increment the Iteration count.
  /// </summary>
  private readonly int Iteration;

  /// <summary>
  /// This procedure contains the user code. Input parameters are provided as regular arguments,
  /// Output parameters as ref arguments. You don't have to assign output parameters,
  /// they will have a default value.
  /// </summary>
  private void RunScript(List<Point3d> pts, double w, int itterations, List<double> cValues, ref object A)

    Point4d c = new Point4d(cValues[0], cValues[1], cValues[2], cValues[3]);

    double[] cValuesOut = new double[pts.Count];
    Parallel.For(0, pts.Count, i =>
      cValuesOut[i] = Julia(new Point4d(pts[i].X, pts[i].Y, pts[i].Z, w), c, itterations);
    A = cValuesOut;

  // <Custom additional code> 

  double Julia (Point4d q, Point4d c, int itterations)
    double output = 0;
    for (int i = 0; i < itterations; i++)
      q = SquarePoint4dQuaternion(q) + c;
      if ((q.X * q.X + q.Y * q.Y + q.Z * q.Z) > 100) break;
    return Math.Sqrt(q.X * q.X + q.Y * q.Y + q.Z * q.Z);
  Point4d SquarePoint4dQuaternion(Point4d pt)
    double x = pt.X * pt.X - (pt.Y * pt.Y + pt.Z * pt.Z + pt.W * pt.W);
    double y = 2 * pt.X * pt.Y;
    double z = 2 * pt.X * pt.Z;
    double w = 2 * pt.X * pt.W;
    return new Point4d(x, y, z, w);

  // </Custom additional code> 

Hi Laurent, Thank you so much for your continued help and support! I am really really impressed by your results and honestly feel embarrassed that I’m not able to come up with results of similar quality while participating in this conversation :smiling_face:

On the optimization side, the video mentioned that, this particular shape is mirrored in both the x and y directions. Therefore, Bad Normals only did calculation for the top right corner, mirroring the rest.

This seem to speed things up a ton though, I notice that this creates ‘seams’ (or tiny crevices) on the mirroring plane in the Blender implementation

(of course, Bad Normals code also uses Keenan Crane’s code implementation, which speed things up. Coming up optimization on that side of this problem is beyond my ability at the moment)

I ran into some problems writing down this code, and I think it’s a software/systems issue, so I open a new topic for it.

I just realized Dendro don’t work for Mac. I suddenly see why people like Blender now and it’s not the price thing :melting_face:

Hi Laurent,

Sorry to bother you again. I tried to get the ‘more twisty’/doughnut-like version of the quaternion by increasing the density in the script you very kindly shared. However, there is a problem: the mesh is invalid, and I can’t do any gh operations to it (besides deconstruct mesh)(I passed it through Nautilus’s heal mesh as well as )

I notice that: (using Isosurface from Ngon, since Millipede crashes Mac)
1 when I get invalid mesh (iteration = 10, 11, 12), the output of your code is NaNs, and the points of the resulting mesh is Null Point (even though I can clearly see them in the preview?)
2 at iteration = 9, the output of your code is a lot of '+infinity"

I also tested on a Windows platform, Millipede is usable, and got invalid mesh as well (In my search for IsoSurface modules, I see you mentioned here Isosurfaces / Signed Distance Fields that Millipede does output invalid meshes and need to be fixed)
I am trying to figure out: if this is a problem with (or with me using) the IsoSurface module. Could you please take a look?

Thanks a lot!
julia 3D.gh (30.8 KB)