Monday, 30 December 2013

Weighted Arrays

Often you need to 'weight' the items of an array so that you can achieve a certain ratio e.g for a particle cloud 25% red, 25% blue and 50% green. The archive below contains a couple of sample scenes that show one specific technique (borrowed from Greg Turk's Graphics Gems algorithm for weighting triangles by area) for weighting an array and a couple of compounds kindly made by Dan Yargici making it easy to set up the initial weighted array and then pull data from it. The weighting doesn't have to be normalised - any ratios will work. Download the compounds and scenes here.

Clone With Index

A few months back Graham Fuller posted a great tip about how to retrieve the clones of a given point on the xsi mailing list. In this post Gustavo asks how to enumerate the individual clones so you can handle them separately. This scene shows three methods - a couple of them use variants of Graham's method whilst one uses a simple loop. They're useful techniques for creating hierarchies of particles where numerous clones can act as 'children' of a master particle.

Thursday, 18 July 2013

Faster Polygon Islands

Eric Mootz's emTools  has a suite  of compounds to manipulate polygon islands with a particle cloud. They require a pre-calculated index array mapping vertices to their island index. Doing this in ICE directly is relatively slow - quite a bit of work has been done to get these ICE compounds as fast as possible (see Guillaume Laforge's original blog post and this thread on but a C++ ice node can usually run orders of magnitude faster. In the case of the node provided here it has proved to be as much as 10-15x faster than the ICE implementations (depending on the scene). I'm sure there's scope for more optimal C++ coding to make it faster still.

You can use the node to feed data into Eric's vertex island tools (sample scene in the .rar file, remember to install emTools first) or as a standalone utility node if you're manipulating islands in your own way. It takes geometry and point positions as inputs and can output the index array of points and their island index, a per point island index and an array of island centres.  It's been compiled against 2013 SP1 64bit. Source code is included with the addon.

jj_Island_Indexer 1.0.0

Tuesday, 2 July 2013

Dart Throw Multiple Size

Dart Throw has been updated to support an input array of multiple sizes (as well as continuing to support a single input size). You can now instance a group of differently-sized objects onto your particles by creating an array of the sizes of the objects in the group. Numerous other tweaks and upgrades have been added:
  • Input an array containing multiple sizes and darts will match those sizes
  • Weight map based size adjustment now supports either absolute or scaled size
  • Randomising now supports negative variance and either absolute or scaled size
  • A new 'min size' parameter lets you control/limit the minimum size
  • Size adjustments via weights and/or randomisations can be applied to the array of input sizes
  • source code is now included in the src directory of the addon
  • Illustrative sample scenes are included in the archive
The new version of Dart Throw (2013 SP1+, 64bit)  can be downloaded here.

ICE Node Inputs

Usage Summary

This controls how many attempts are made to position a dart on the geometry. The more attempts you make the denser the packing becomes up to the point where it becomes virtually impossible for a dart to land on an empty space with sufficient room for its size.

If you look in the history log, Dart Throw reports something like the following: "Max iterations is: 41 at: 49990" (assuming an iterations setting of 50,000). This tells you that the maximum number of attempts it took to get a successful dart inserted was 41 and that happened at iteration 49990.

In a scenario where you get something like "Max iterations is: 101000 at: 899012" (assuming an iterations setting of 1m) you can see that it's taking over 100,000 attempts just to get one dart positioned. It's probably not worth waiting for that 1 extra dart and so you could reduce your iterations to 899011. In the Misc section you can use an 'Iterations Abort Threshold' parameter to set a value for how many unsuccessful dart throwing attempts the node should make before abandoning automatically. See that section below for detailed instructions.

You can input either an array or a single value here and Dart Throw will generate 'darts' that only use those size(s). The size array does not need to be in any particular order which means you can put your objects into your instance group any way you see fit.

Size Adjustment

Two different instance types with sizes adjusted by weightmap.

If you plug a weight map into the size map port you can control the size of your particles using the values in the map as an interpolant. What that means is that the weight map value between 0-1 will interpolate between the Basic::Size parameter you entered above and the Size Adjustment::Adjusted Size parameter you enter in this section.

The Adjusted Size parameter can be set as either a scaling factor for your size or as an absolute value. Depending on the weight map value your particle size will then interpolate between Size and Adjusted Size.

If you plug a weightmap into the Erase Map port then darts will only land on areas with a weightmap value on or above the threshold. All other darts will be deleted.


A single instance whose size is randomised using a variance. Version 3 supports negative variance.

The randomise option enables you to add a variance to your sizes either as an absolute value or a scaled value. Randomise assumes a variance around 0 so you'll get both negative and positive variance. This is where setting 'min size' (see below) can help ensure your smallest particles are not pushed into negative territory if you use the scaled option.


Iteration Abort Threshold
This parameter lets you specify what fraction of the total iterations have to occur without a successful dart before the node automatically stops iterating. For example if you have set 1,000,000 iterations and set this parameter to 0.1 it means that if there are 100,000 iterations without a successful dart the node will stop iterating.

Min Size
Now that the randomise feature (above) supports both absolute and scaled variances it's possible, using scaled, to scale your particles by a negative amount i.e. if your variance is set to, say, 0.5 then you will get scaling values between -0.5 and +0.5. Min Size simply sets a minimum for your particles. (If you use absolute in this scenario it means you can subtract negative values from your particle size which won't necessarily push the size into negative territory).


Position Array
This is the array of successful dart positions.

Size Array/Size Per Point
This is the array/per point output of sizes associated with those output positions. Be aware that the size output needs to be treated differently depending on whether you're using intrinsic ice objects like sphere, cube, cone etc. or geometry instances. In the case of intrinsic ice objects you should use this output directly to control the size. In the case of instances you need to divide the output size by the input size to work out a scaling factor for your instances. See the sample scenes for examples.

Size Index Array/Size Index Per Point
If you're using an input array of sizes this is either an array or per point output specifying the index into the input size array for each position. For example, your input size array will match the sequence of sizes in your instance group. When Dart Throw allocates a size to a point you will need to know for each point which size it has selected. This output tells you the index of that size so that you can pick the correct instance from the instance group.

Friday, 21 June 2013

Texture UV To Location

I was motivated by this thread on the mailing list (and Gustavo's excellent Motion Tools) to work on a C++ ice node to provide a quick way of finding positions from an input texture uv array (the factory-installed UV to Location node doesn't work on polygonal geometry). The method doesn't require triangulated geometry.

Since we don't have access to pointlocators in the ICE SDK,  the node doesn't actually get locations directly but it does generate a position on the polygonal surface from an input UV. The custom ice node is built into a compound that then takes the output positions and generates locations using Get Closest Location. You have the option of using the position directly or using the location port.

The addon is below for 2013 SP1 (64bit only) and contains C++ source code with comments on the barycentric and triangulation methods as well as notes on some of the problems/choices related to building a custom ice node. A sample scene is also included. If you find a circumstance where it doesn't work correctly I'd be very interested in the scene file.

Updated 28 June 2013:
Crash when no geometry under UV fixed.
Texture UV To Location v1.1

Wednesday, 9 January 2013

Place Specular Highlights

Updated 22nd January. The fifth beta (v0.9b) of a  tool using the Custom Tool SDK to interactively place specular highlights on objects is now available. The (updated for v0.9b) movie here shows what the tool can do.

The tool allows the  user to select any pre-existing light, lightroot or object in the scene and that object will be manipulated. If no light or object is selected a spotlight will be created. This means existing VRay and Arnold lights are now supported.

The main features of v0.9b are now:
  • Place specular highlights from lights directly where you position cursor over an object.
  • Place any object, not just lights, along the reflection vector.
  • Place multiple objects simultaneously.
  • Original distance(s) to incident point is/are retained.
  • Distance to point can be manipulated with the Shift key.
  • The cursor can be placed back on the 'specular' point by holding down Shift + CTRL.
v0.9b also introduced some significant performance enhancements to the underlying pick routines.