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).
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.
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
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.
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)
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. */ }
#endregion
#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;
#endregion
/// <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
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)
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?