6
$\begingroup$

UPDATE: Simulation nodes are now available in B3.6β!

In the recent week the Blender community became crazy on the particular geonodes hack, that allows you to create a simulation in Geometry Nodes alone:

1 NENGHUO on Youtube: Breakthrough! !" For Loop" in the blender geometry nodes.

3 GifCo on Twitter: Geonode simulations are all the rage these days!!

1 Default Cube on Youtube: FINALLY! NEW Loop Node

1 Seanterelle on Youtube: Geometry Nodes Differential Growth Simulation Tutorial

This is not a forum to vent one's frustration, so let me just say a better¹ technique exists at least since I started using GN in Blender 3.0, so I decided to share, in Q&A fashion. Everyone is welcome to post his alternative technique - perhaps one involving physics - I've done something very limited in geonodes+cloth here:

7 Create Curve from Path of an Object Using Geometry Nodes

¹ - Maybe some people hate Python so much, they would rather use a dirty hack relying on Blender failing to protect from circular reference, which can hang the program, is not officially supported, is not a designed feature: exists in memory only as a temporary evaluated object without any representation in .blend datablocks, therefore can't be saved or maybe even restored with ✲ CtrlZ undo [not sure, haven't tested], runs an erratic number of times (I think on each depsgraph update?) and so runs in a single frame rather than with one step (or a fixed number of substeps) per frame, and can stop working (be fixed) in future versions of Blender.

$\endgroup$
5
  • 1
    $\begingroup$ This is a very interesting Q&A ! However I would have replaced the "python" tag with the "simulation" tag. Tags should describe the question, not orient the answers. I'm sure non-python related answers have their place here and the tag might refrain people from exploring them. Just my 2 cents :) $\endgroup$
    – Gorgious
    Commented Nov 17, 2022 at 10:44
  • $\begingroup$ @Gorgious good argument, I removed the [python] tag, and I agree in regards to the simulation tag, except there is no simulation tag! So when I wanted to add one, I saw instead 5 tags to choose from: [fluid-simulation], [cloth-simulation], [smoke-simulation], [ ocean-simulation], [rigid-body-simulation]. Do you think I should jast add fluid, cloth, smoke and ocean variants, as the rigid body one would actually be tricky to do in geonodes? $\endgroup$ Commented Nov 17, 2022 at 10:49
  • $\begingroup$ hehe I didn't know there wasn't a dedicated simulation tag :/ I'd say cloth and rigid body are good candidates, but in the future I can see all the other ones being possible :) $\endgroup$
    – Gorgious
    Commented Nov 17, 2022 at 12:44
  • $\begingroup$ Not just simulation itself ? Useful for procedural geometry/ textures which are the result? eg the results of growth, erosion, flow .. etc $\endgroup$
    – Robin Betts
    Commented Nov 17, 2022 at 19:24
  • 1
    $\begingroup$ @RobinBetts define "simulation" - in the context of Blender I believe it's basically exactly that, it's a continuous process relying on access to previous frame data. I think your examples fit well into the existing pool of simulations like fluid and smoke. $\endgroup$ Commented Nov 17, 2022 at 20:53

1 Answer 1

6
$\begingroup$

Geometry Nodes are planned to support a simulation out of the box one day:

1 Geometry Nodes Post BCON22 Workshop

Meanwhile, you can use a Python script like this:

import bpy
from bpy import context as C, data as D
from bpy.types import SpaceView3D

loop_mapping = {
    'single vert B': 'single vert A'
}
evaluated_frames = 0


def simulate():
    global evaluated_frames
    if C.area.type != 'VIEW_3D':
        return
    # hard-coded to start at frame 1
    if evaluated_frames + 1 != C.scene.frame_current:
        return
    dg = C.evaluated_depsgraph_get()
    
    for ob_from_name, ob_to_name in loop_mapping.items():
        me_from = D.objects[ob_from_name].evaluated_get(dg).data
        ob_to = D.objects[ob_to_name]
        me_to_old = ob_to.data
        ob_to.data = me_from.copy()
        D.meshes.remove(me_to_old)    
    
    evaluated_frames += 1


try:
    SpaceView3D.draw_handler_remove(SpaceView3D.my_handler, 'WINDOW')
except (AttributeError, ValueError):
    pass

SpaceView3D.my_handler = SpaceView3D.draw_handler_add(simulate, (), 'WINDOW', 'PRE_VIEW')
C.scene.frame_set(1)
bpy.ops.screen.animation_play()

This script is simply evaluating single vert B, and saving it as single vert A's mesh data on each frame. You can add more object pairs to the mapping. You can build on top of this technique by for example not removing the old mesh data me_to_old and setting each mesh'es name to end with the frame number it was evaluated for - this way you could add another check to simulate, that restored one of the already evaluated meshes if a frame was already evaluated (current frame < evaluated_frames+1). You could also program in substeps, which would simply loop the part that evaluates an object and moves it to the other object, and you could add any arbitrary Python shenanigans. Some of those techniques I teach here:

1 Distributed interaction visualization

On the geonodes part, Create the two objects, and for the single vert B (the former in the mapping pair, the dictionary key) add your simulation logic:

This example is very simple just to present the point: Sample the noise texture at current position, offset to be on average 0 (so the sphere you will see in a moment is less likely to run away), normalize to ensure the sphere actually moves, and use a switch to really ensure the sphere actually moves in case a $(0, 0, 0)$ vector was produced. Scale it, because $1$ meter movement per frame is too much for a usual camera.

Now either hook something to that vertex, or create another geonodes setup that uses the simulated data. Of course you could directly display the simulated mesh, but I went for separating the simulation logic and the appearance, so a simple sphere will be centered on that simulated vertex:

Now you can set the animation to last a very long time (99999 frames), run the script, and modify the simulation parameters as you go:

Rendering

Here's another example, this time making it possible to render, though it crashed for me after 500 frames. Maybe it has something to do with this note. To render, open the file, run the script, and then render the animation.

tested on v3.4β

$\endgroup$
3
  • 2
    $\begingroup$ I like this approach! Just an idea for the list of most wanted nodes: "Bake to Cache" (output node, write to file/memory). Instead of outputting the geometry at the group output, the data of each frame is written to a cache, and can be read by other geometry nodes per frame with "Read from Cache" (input node). Would something like this be theoritically realizable as a custom node? $\endgroup$
    – quellenform
    Commented Nov 17, 2022 at 0:32
  • $\begingroup$ Geonodes are CPU based so EVERYTHING could be realizable… I wish rather than going for everything nodes, Blender would go for everything WASM (webassembly) which is a safe programming interface allowing to safely import third party code. Even within the node context it seems being able to write a custom node would explode the practical possibilities. $\endgroup$ Commented Nov 17, 2022 at 10:14
  • $\begingroup$ Here's a tweet and a gumroad page for a 9 months old solution, very similar to mine. $\endgroup$ Commented Nov 17, 2022 at 16:27

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .