2
$\begingroup$

I want to calculate the velocity of each point on an object's surface in world coordinates and store that in a named attribute so that particles emitted from this surface can inherit the velocity of the surface. This surface velocity needs to be based on world space - ie include the whole object's translational velocity and rotations that contribute to the velocity. I want to use simulation nodes rather than Blender's built in particles as there are other effects I need to add in on top of this.

Current File:

$\endgroup$
2
  • 1
    $\begingroup$ Could you provide a Blender file using blend-exchange.com as a starting point with a GN modifier where "only" the velocity computation is to update ? $\endgroup$ Commented Apr 26 at 10:40
  • $\begingroup$ Done. The file has a basic emitter setup... but I think the solution will require some transfer of velocity data from the base mesh to the emitting particles so will be more complex than this file suggests. $\endgroup$
    – David M
    Commented Apr 26 at 11:43

2 Answers 2

0
$\begingroup$

(Using Blender 3.6.8)

Approach

The velocity in the world coordinates of the emitting object is computed and stored as an attribute by a GeometryNodes modifier attached to this object. The achieved field is processed by an other object, using an other GeometryNodes modifier.

Results

This figure illustrates the "Object to track" motion while it is translating along the Y axis and rotating around the Z axis, starting from the world origin. Elongated cones are visualizing the instantaneous velocity vector in world coordinates of each corner of the cube. Tetrahedra are visualizing the successive position of the initial top right corner sampled every 5 frames. The velocity vector must be tangent to such a trajectory, and its magnitude must be proportional to the distance between two adjacent tetrahedra.

Animation

GeometryNodes modifiers

Emitter: GN Compute velocity

The above GN graph, attached to the emitting object, is only storing named attributes. The velocity is computed as the difference between positions at two successive frames using a Simulation Zone.
1. The previous frame position is stored in Point domain as an attribute named "old". It is initialized with the Position at frame 1, upstream of the Simulation Zone.
2. Accordingly, the named attribute "velocity" is initialized null.
3. The instantaneous Location and Rotation of the emitting object are recovered in the world coordinates, using an Object Info node connected to a Self Object node. To do so, the Transform Space is set to Original.
4. The emitting object, whose geometry is invariant in its own GeometryNodes modifier, is rotated then translated using a Transform Geometry node.
5. This transformed geometry is not connected to the Group Output node. It is instead used to transfer, to the simulation zone, the instantaneous Position of the emitting object vertices, using a Sample Index node.
6. To these current positions are subtracted the "old" ones to compute the "velocity".
7. Eventually, current positions are stored as "old" for the next frame.

Observer: GN Viewer

The above GN graph is attached to a fixed object acting as an observer, taking advantage of the vertices position and of the "velocity" field of the emitting object.
About the position: (part in green)
1. A tetrahedron (i.e. a Cone with 3 vertices) is dynamically added to the output geometry using a Simulation Zone made of a single Join Geometry node.
2. Sampling is controlled with a Switch node. A new tetrahedron is added every 5 frames, identified with a Modulo math node, starting at frame 1.
3. The tetrahedron position is set using an Instance on Points node.
4. This position is copied from the emitting object vertex of Index 0. This single point is chosen through the Selection socket connected to an Equal compare node.
5. The Geometry of the emitting object (and so the current position of its vertices) is recovered through an Object Info node. The Transform Space is set to Relative "to maintain the relative position between the two objects in the scene". Because the observer is fixed while the emitting object is moving, the current position of the seeding point is changing in time.
About the velocity: (part in blue)
6. An elongated cone is positioned, downstream of the Simulation Zone, at each vertex of the emitting object using as previously an Instance on Points node connected to an Object Info node set in Relative Transform Space.
7. Using an Align Euler to Vector node, the Z axis of instanced cones is aligned to the "velocity" vector recovered from the point they are attached to, through a Named Attribute node.
8. The same attribute is used to scale instanced cones Z axis, to make these length proportional to the "velocity" magnitude (NB: The factor 30 to scale the length was adjusted to fit the demonstration case ; it has no meaning).
9. Because the observer is fixed in the scene, this illustrates that the "velocity" field stored as attribute in the emitting object is indeed in the world coordinates, and not in the object coordinates. The resulting animation is insensitive to the position and the rotation of the observer.

Resources


Benchmark

Lutzi proposal is based on vector algebra instead of a Transform Geometry node to apply rotation and translation. The following GeometryNodes graph is timing both approaches when the objective is to store a position field as an attribute. It is attached to a point cloud with 100.000 elements.

Vector algebra: Vector algebra

1. The rotation is computed with a Vector Rotate node.
2. The translation is computed with an Add vector math node, providing the sought field.

Geometry transformation: Transform Geometry

1. The rotation, then the translation, are computed by a single Transform Geometry node.
2. The sought field is recovered through a Sample Index node set in Point domain and connected to a Position node.

Conclusion:
Repeated runs show that the "Geometry transformation" approach is 1.5 to 2.0 times faster than the "Vector algebra" one. One explanation is that for a uniform transformation (i.e. with the same parameters for all vertices), the Transform Geometry node is optimized, counterbalancing the extra Sample Index node cost. But it can not apply a "per vertex" specific transformation as its Translation, Rotation and Scale sockets are not fields.

Benchmark Blender file:

$\endgroup$
1
$\begingroup$

My answer is probably equivalent to the one of StefLAncien.

Requirements

The object using these geometry nodes should have a scale of 1. If it is not the case : Ctrl+A> Apply Scale

Global position (rotation included)

First let's build a group node for the global position. The process is to take the object position and add to it the Position which is the local position. This Position won't take into account Transforms (location, rotation, scale). So we can rotate the Position with the object rotation. We get :

enter image description here

Store global velocity

Let's say we are at frame $i$, we have the global position at each frame $\vec{x_i}$ and we want to compute the velocity $\vec{v_i}$. Then the general process to store the velocity is :

  1. Compute the velocity, which is simply : $\vec{v_i} = \vec{x_i} - \vec{x_{i-1}}$. Note that this means we won't have any velocity at frame 1.
  2. Store the current position for the next frame $lastPosition:=\vec{x_i}$

And the node tree is :

enter image description here

Notes and blend file

I have added a visualization of the velocity, quite the same as StefLAncien, as a debugging tool. You can enable/disable this in the Modifier tab.

enter image description here

$\endgroup$

You must log in to answer this question.

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