TRIAL VIEW You can view a portion of the guide for FREE, after sign-up. For full access, buy the PRO edition of the course.

Smoke Trails
/
Lesson 1

Course Guide

Smoke Trails

lesson 1

Getting Started

Start off by loading in your course geometry. You can easily access the provided geometry for the course by clicking the “ASSETS” button below any video in the course. In our case we are loading in missile and turret geometry for the smoke trails.

Core Objectives

arrow_right

Take our missile geometry, and set it up properly to simulate the missiles.

arrow_right

With our missiles simulated, it will form the basis for the trails that should emit from them.

arrow_right

Learn how to leverage particle simulations to do this.

Step 1: Separate Missiles and Turret Geometry

Description

Split out your missiles and turret geo using a SPLIT node. The geometry have primitive groups on them for easy selection. Then designate one output with a NULL node and call it “OUT_turret”. Then call the other output “OUT_missiles”.

Next: Viewport Setup (Optional)

arrow_right

Rearrange your pan tabs to have a broader view of your viewport on the left and then your node graph on the right. You can always select a node, and hit “P” on the keyboard to access its given parameters.

Step 2: Reference Prepped Geo

Description

The Geometry SOP where you prepared the missile and turret split can be named “prep”. And now we can create another Geometry SOP in the OBJ context and call it “animate_missiles”. Jump inside the “animate_missiles” node, and import our “OUT_missiles” by using an OBJECT MERGE node.

What’s nice about Houdini, is it’s essentially organized like a folder system on your computer. You can reference paths to different geometries. In the OBJECT MERGE node, reference the “OUT_missiles” by typing: ”../../prep/OUT_missles”

Step 3: Create Name Attributes

Description

After object merging the missiles, let’s create a name attribute for each missile. We can do that by dropping down an ATTRIBUTE_CREATE node.

Make the Class = Primitive and make the Type = String

Then for the attribute name, you can type: (using back ticks, not apostrophes)

`$OS`

Then it will use whatever the name of the node is for the name of the attribute. For example, name the node “missile_01” and then the attribute will automatically update to being called “missile_01”.

Lastly make sure you select the appropriate group to be able to separate each missile.

Step 4: Turn Missiles into Packed Geometry

Description

After doing that, you can drop down an ASSEMBLE node, and make sure to check “create packed geometry” and uncheck “create name”. This way we can pack each missile as an individual point representation — a packed point, with all its attributes.

Then we can simulate a single point and then copy the missile back onto each point later.

Drop down an ADD node, and check “delete geometry but keep points” and then pipe it into a POPNET node.

Step 5: Blast Points for Direction Attribute

Description

Next we need to create a direction that the missile points will shoot from as points in our simulation. In order to do that, on a forked path, you can drop down a BLAST node and then select the tip of a missile and then the bottom end of it, for two points total.

Step 6: VEX Code Direction V

Now that we have two specified points, we can utilize them to create a direction attribute called “v”. In Houdini, attributes that are written to the geometry are specified with a variable type, such as “v” for vector. In our case, we are additionally naming the vector “v”. This is potentially confusing, but it’ll start to make sense as we go further.

If we take the position of one point, and then subtract the position of the other point, it will create a new vector that points in the direction we want. All we need to do after that is normalize that direction so it’s unit length is equal to 1. This is standard when dealing with vectors that are treated as directions.

We want to drop down a PRIMITIVE_WRANGLE node after our last ATTRIBUTE_CREATE node and before the ASSEMBLE node. Then pipe in the blasted points into our 3rd input of the PRIMITIVE_WRANGLE. (It’s the 4th dot on top of the node, but Houdini orders the inputs starting with 0, so it’s actually specified as the 3rd input).

In the PRIMITIVE_WRANGLE, here’s the code we will need to put in:

Primitive Wrangle Code Snippet

arrow_right_alt

Group Type:

Guess From Group

arrow_right_alt

Run on:

Primitives

vector posA = point(3,"P",0);
vector posB = point(3,"P",1);

v@v = normalize(posA -
posB);

Description

Step 7: Visualize our Direction V

Description

If we middle mouse click on our PRIMITIVE_WRANGLE node now, we should see a “v” attribute on the primitive level. If you click where it’s underlined, Houdini will create a visualizer for that given attribute. In our case, it recognizes it as a vector attribute, thus rendering yellow vectors in the viewport to show which direction the attribute is pointing.

Step 8: Promote the v attribute and sim prep

Description

We need to promote our “v” attribute from the primitive level to the point level, in order to transfer them to our points when they are packed with the ASSEMBLE node. Drop down an ATTRIBUTE_PROMOTE node before the ASSEMBLE and you’ll change the primitive v attribute to a point v attribute.

Make sure to revisit the ASSEMBLE node and transfer “v” so the points will inherit that direction. “v” in Houdini is also reserved for point velocity. So if you have a vector attribute “v” on your points, and you pipe them into a POPNET simulation, Houdini will recognize that as the speed and direction for the points to go.

Lastly, make sure you click the POPNET node, and at the Object Merge tab, type *pop * in the Object parameter. This will make it so only the points are piped out of this simulation, as opposed to any other objects like collisions.

Step 9: Dive into POPNET and What's DOPS

Description

Now dive into our POPNET node, which brings us into a simulation environment in Houdini, known as DOPS. Nodes are different in DOPS, because they are set up to work with situations. When you hit Tab, to get nodes, you’ll notice they aren’t quite the same as they are in SOPS.

Our POP_SOURCE node in this network is going to control what is coming into our simulation. The POP_OBJECT node is the node that holds our point data throughout the simulation. The POPSOLVER runs the simulation calculations over all the points each frame.

And finally, the OUTPUT node is specified because that’s the node we want to reference outside of DOPS to extract our simulation data from DOPS.

Step 10: Simulation Specifics

Description

Next, drop down a GROUND_PLANE node, and pipe it into the left side of the MERGE node.

Order matters on merges in DOPS, unless you select the MERGE node and change the relationship behavior to “Mutual”.

For our purposes, we want to change the source of our simulation to “All Points” and then change the impulse activation to:

$SF==1

This will enable the sourcing to only occur at the first simulation frame. Hence SF. It means, “Simulation Frame”. So when the simulation frame is equal to 1, source the points.

Step 11: Collision Behavior

Description

Click on the POPSOLVER node, and in the Collision Behavior tab, change the Response parameter to:

“Stop”

This will make it so the points stop once they hit the ground plane collision object.

Step 12: Pop Wrangle Vex

There’s a node in DOPS we can create called a POP_WRANGLE node. It’s essentially and ATTRIBUTE_WRANGLE, but for points inside of DOPS. Here’s we want to specify an attribute called “endv” and have it be a vector. This way we can record the direction in which each missile hits the ground when it stops.

Since we changed our Response in the Collision Behavior to “Stop”, we will have an integer attribute on our points called “stopped”. It is equal to 1 when the points collide, thus rendering them stopped.

Here’s the code we need to put in our POP_WRANGLE, and then pipe the wrangle into the last input of the MERGE node, with the POP_SOURCE node:

Pop Wrangle Code Snippet

arrow_right_alt

Group Type:

Guess From Group

arrow_right_alt

Run on:

Points

if(i@stopped==1){
v@v = v@endv;
}

Description

Step 13: Update Simulation Velocity

Description

In the POP_SOURCE node, go to the Attributes tab and change the Inherit Velocity parameter to:

20

This way, our points inherit that velocity attribute we created, but the speed is now multiplied by 20, creating a nice arc.

Step 14: Wire Outputs After Simulation

Description

If we come out of our POPNET simulation node, we need to set up a way to have our missiles move according to where their corresponding point moved.

To do this, make a NULL node called “PACKED_GEO” and connect it to our ASSEMBLE node.

Then create another NULL node called “SIMMED_POINTS” and connect it to the output of our POPNET simulation.

And last, create a 3rd NULL node called “START_POINTS” and connect it to the output of the “IN_POINTS” NULL node.

Round this step off by creating a TRANSFORM_PIECES node.

Step 15: Set V to EndV Post Sim

After the “SIMMED POINTS” node, we can create a point wrangle and set the v@v attribute to “v@endv”. This way, our points will land and hit the ground with the correct orientation.

Here’s the code for the POINT_WRANGLE node:

Point Wrangle Code Snippet

arrow_right_alt

Group Type:

Guess From Group

arrow_right_alt

Run on:

Points

v@v = v@endv;


Description

Step 16: Final Step for the Lesson

Description

Our final step for the lesson will be to wire everything up correctly. Plug the “PACKED_GEO” node into the first input of our TRANSFORM_PIECES node. Hook the POINT_WRANGLE we just used to specify v with, into the 2nd input, and our last input will have our “START_POINTS” node plugged into it.

Since our packed geometry, and our simulation and start points all have matching name attributes, the TRANSFORM_PIECES node is able to deform our missile geometry correctly over each frame, thus have animated missiles.

Our last task is to drop down an UNPACK node, to unpack the missiles so they will act as normal animated geometry. And then drop down an ATTRIBUTE_DELETE node and delete the name attribute at just the point level, NOT the primitive level. This will make things easier for further lessons, because our attributes will be set up correctly.