15 januari 2020

Houdini Community

While chatting with some people online on Discord who also use or learn Houdini, I noticed that there was a need for a few beginners challenges. Together with others I came up with some things they could make. A few examples of the exercises were a faztek (say what?), a guitar and a jenga tower (from the game). When I came up with the jenga tower, I thought about not only making the tower but also integrating the animation of stacking blocks on top of the tower. Lets get more in detail...

The faztek I wanted to try out myself (fully procedural)

Quick overview of the faztek

The Jenga tower

The first thing I did was simply recreating a simple random tower made out of blocks with no futher features. Just random stakced blocks. I started like this so I would get in the mood and already think about how to make this more advanced. Starting with a simplified version makes you thinking on how to make it advanced. Breaking the problem into smaller problems is a good way to build things. Of course there are multiple ways on handling a certain problem like stacking jenga blocks. Therefor is may be a good idea of trying them out. It makes you think in a different way. Just make sure you don't lose too much time. 

The following example is one way of building a simple tower. To make sure the total number of blocks is right... just delete the number of blocks that are too much. (depends on the way you build the tower). In my case I haven't done this.

Sneaky wrangles

One thing I was sure about was that I was going to need for loops and wrangles with feedback on each iteration in order to make the full version with animations etc. An important thing to know when working with wrangles (vex) is that values will only be assigned when a wrangle is done. For example when you do a setpointattrib(0,"P",@ptnum,newPos); , the value of "P" will only be assigned when the wrangle has ended. Maybe the next example will make things clear.

In this small example I just create a simple line of 2 points and make point 1 active and point 0 not. Then I just want to delete point 1 if that is active. In the left example I try to do this in 1 wrangle, but I fail. This is because point 1 is not set active (wrangle has not ended). In the example on the right it works perfectly and point 1 will be deleted. This is because point 1 is first set active and the wrangle has ended. In another wrangle I can delete it with no problems because I know for sure that the attribute active has been set.

Part 1: Building the base of the tower

Part 2: Removing Points/Blocks

The blocks are tied to a point, that is the important base of this project. To add functionality of removing random points we need to throw some code to the points with wrangles. This is the following workflow:

  1. The base of the tower (height of 10) is consists out of 1 line with 10 points where each point has a vector attribute called "points". In the vector 1 means that there needs to be a block and 0 means that there is no block. 
  2. Each point of the base line also has an attribute "completed" (completed row) and "id"
  3. Each frame there is a for loop that always selects 1 random point of a row that isn't completed. In that point it randomly selects a point (of the vector) and removes it (if possible, else another point).
  4. Delete the points that are holding a 0 as value in the vector. 

Part 3: Adding Points/Blocks + Reiterate on existing blocks

We can add extra features on this existing node network. That's why you must work in steps, always be sure that something works so you can fall back onto this. Now how do we add extra blocks on top and remove blocks at the same time with the same structure? Well the solution is in that sentence. Well partly.

  1. The base line currently consists out of 10 points, which was the height. Now we want to multiply that height by 3 because that will be the maximum tower height that will be possible with jenga. 
  2. The baseline now has "active points" (group), these will be used in the end to spawn blocks on. The first 10 will be set as active. Active means that a row/point has 1 or multiple blocks assigned to it.
  3. In the wrangle we remove a block by setting an index in the vector attribute point to zero. When doing that we also need to "add" a block on top. The base line (1 primitive) now gets an integer attribute named "add". When this value is 1 we need to add a block/point. Do this in a second wrangle (remember the sneaky wrangle alinea).

Part 4: Adding An Animation To Each Point/Block

This part is a little bit more tricky because of the animation. Again we build upon the existing network. Unitl now each frame of the timeline removed and added 1 point/block of the tower. Because we have an animation right now we must do this over a certain range of frames, like 20 for example. So Each 20 frames 1 point/block is going to be removed and added plus an animation is playing per block of 20 frames. 

  1. After we calculated the whole jenga (points), animationdata needs to be added. Each point/block gets extra attributes that we will use for the animation: animationStart, animationEnd and animationId.
  2. What do we need to let the point/block animate? A curve (point interpolation via the curve). To make the curve each point/block need to know the begin-and endpoint. Via those points a curve will be generated and the point will interpolate along the curve.
  3. The point position will interpolate but also the angle of the block needs to be adjusted to it always ends in the right direction.
  4. The animation will be merged with the existing framework of part 3 and BAM jenga is created.

Everything is explained very roughly but it is meant to give you a grasp of how this setup works.