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.

Friday, 21 December 2012

Convex Hull Using CGAL Library













Although Guillaume Laforge has posted the definitive Convex Hull node for ICE, I thought it would be an interesting exercise to try and hook into the CGAL geometry library and see if it was possible to use their Convex Hull (Qhull) algorithm in an ICE node. It turned out to be relatively straightforward. The Addon and C++ source is here (2013SP1, 64bit only. Only tested on a couple of machines, let me know if there are any floating dependencies I may have missed).

Sunday, 18 November 2012

More Even Spacing













Softimage 2012 gave us the ability to create ICE Attributes directly via scripting and populate them with data. Guillaume Laforge used this ability extensively in CrowdFX and I've recently been using it as a mechanism to easily store large datasets in place of Blobs (e.g. for storing animated curve data from Flame GMasks).

As a simple example, I created a script which takes an input curve and creates an ICE Attribute on that curve containing evenly-spaced point positions. The relationship is 'live' so you can manipulate the curve and alter the number of evenly spaced 'ICE' points. You could then go on to feed that ICE data into another ICE tree.

In the same archive I've also included a script to generate a 'real' curve with a live link to the original curve - the new curve has evenly spaced points* and can be any degree you choose and/or constrained to the original. (*This even spacing becomes more accurate the higher your resolution).

The archive is here.

Using Generate Sample Set to Avoid Repeat Loops

Oleg Bliznuk, the author of Exocortex's Implosia FX, posted a tip for avoiding repeat loops a few months back using Generate Sample Set. It's a great tip and one which can generate good time savings over repeat loops. I wanted to test just how much of a saving the tip could provide by calculating a cumulative sum array i.e. given an array of integers, produce another array which gave you the cumulative sum of all elements in the array at any given point.

The conventional way to do that would be to use a simple repeat loop, but as is always the case with ICE, repeat loops are not necessarily the best way to achieve your desired results as ICE's multithreading isn't optimised in that scenario.

Oleg's brilliantly lateral idea was to generate a sample for each array member and create an array on that sample the same size as the element's index. You can then populate that array with all the members of your original array up to that point and perform tasks on that segment of the original array.

I decided to set up a test scene to compare the performance of a conventional repeat loop and Oleg's  method. In that test scene, Oleg's method was twice as fast as a repeat loop which is a significant gain.

But, there is a downside -  you pay in RAM usage, sometimes to the point where you might end up paging memory. In my sample scene, the repeat loop method used 200Mb RAM for an array of size 50k whereas in the Generate Sample Set scene RAM  usage shot up to nearly 10 Gigabytes!  The stepping in terms of RAM usage relative to array size (on my machine) went: 5,000: 373Mb; 10,000: 849Mb; 20,000: 2.6Gig; 30,000: 5.5Gig and so on. It looks like there's a step in RAM usage between 10,000 and 20,000 although I'm guessing this might be machine dependent.

It's clear that if you're going to use this method in a compound you need to be careful about the maximum array size you're going to allow and possibly switch over to a conventional repeat loop over a certain threshold.

If you'd like to play with the scene or do your own timings to verify these results it can be downloaded here along with the Cumulative Array Sum compound (2013 SP1).

Monday, 30 January 2012

ICE Modeled Camera Grid
















I was way too slow to post this compound to the XSI Mailing list in response to a thread on the creation of a camera plane but here it is anyway! It dynamically creates an ICE modeled grid and places it inside the camera frustum at a specified distance from the camera. At the same time it creates an ICE-based texture projection. Sample scene and compound is here.

Filtering Arrays

Stephen Blair has been posting some great articles on the eX-SI Support Blog about how to create array patterns i.e ordered sequences like (0,1,2,3,0,1,2,3) or (0,0,0,1,1,1,2,2,2). The creation of this type of sequence can be useful in creating  the points of a grid and also for avoiding the use of repeat loops in certain circumstances.

On the XSI mailing list a few weeks back Dan Yargici posted a question about how to reconfigure a simple non-regular pattern like (1,1,5,5,5,5,8,9,9,9,10,10) into (1,1,2,2,2,2,3,4,4,4,5,5). In the resultant thread Martin Chatterjee came back with a brilliant solution without using repeats. Martin's solution touched on some of the inherent functionality in ICE arrays that's worth expanding upon.

I'm going to try and illustrate some of these with a sample scene that contains an ICE tree that shows several different methods for firstly creating a pattern array and then using that pattern to manipulate an array. If that all sounds abstract it's based on Dan's problem above but with the added wrinkle that the initial pattern is not numerically ascending i.e. it looks something like this: (8,8,2,2,2,14,3,3,1,16,11,11).

Sunday, 25 July 2010

Dart Throwing with Weight Maps


I've just finished a new version of Dart Throwing with weight map control for spacing (spacing maps) and point deletion (erase maps). It uses it's own internal scheme for computing the barycentric weights from weight map values at vertices. Spacing maps allow you to modulate the density of the points using the weight map as an interpolant between the spacing radius and max spacing radius. Erase maps have a threshold parameter which lets you control at what point between 0 and 1 on the weight map the point should be deleted.

There's also a new 'Iteration Abort' parameter which specifies the number of tries (as a normalised percentage of the total iterations) the plugin should make before it aborts. This is for scenarios where you set a huge number of iterations but the number of successful darts becomes very low i.e. if you set 1,000,000 iterations and you only get an additional 1 dart added in the last 500,000 'tries' then you can see that aborting after 500,000 might be handy. The message window gets logged with the maximum number of iterations for a single try as a reference.

Changes in the way multiphase/element generator plugins work in the SDK mean that this version is only available for the very latest version of Autodesk Softimage - 2011 SP1. The Addon has been compiled for both 32 and 64bit Windows.

Download Dart Throw v002 Addon

A Vimeo clip is here.

Saturday, 17 July 2010

Context Switching Using Set Nodes and Filter


In the roll object compound below I use the Set nodes to move between point context and object context. Combined with filter, it's a powerful way to access an individual component in a specific context and make it available to all other components in that context.

On the list here (and on several occasions before), Ciaran Moloney has suggested a technique for using Set nodes, Filter and the Repeat node for gathering data in one context and turning it into an object context array. It's a great technique and one which deserves a closer look.

Whenever you use a specific context node e.g. point, node, polygon in the branch of an ICE Tree its context takes precedence over any object context nodes in the same branch. As soon as you try and set any data in that branch it will always be in the more granular context. Using the Get Set xx nodes, however, acts as a switch to the context of the branch and turns it back into object context. Put simply if you start off in 'polygon position' context you can finish the branch with a Get xx in Set node which provides you with a single piece of object context data e.g. maximum in set.

Ciaran's trick involves using this switching ability to continually iterate over each point, polygon or node and isolate a single item each time - pushing that item onto an object context array.

In the tree above I construct an object context array of all the node positions. You can see that the tree starts in node context but then each node has a repeat loop iterating over itself matching it's own element index with the list of all node element indexes. When it finds a match the output is a single node still in node context. Pumping this into Get Maximum in Set - a filtered set of one - simply switches the output to object context and the node position gets pushed onto an object context array.

The downside is obviously iteration time as each node has to iterate NbNodes times over itself and with large numbers of nodes, polygons etc. this could be slow. However, it seems like the only surefire way to construct robust object context arrays of node positions, polygon positions etc.

Friday, 16 July 2010

Even Spacing on Curve/Normalised U on Curve



Following on from a post by Brad Gabe on the mailing list it looked like the existing normalised u compounds on The Area didn't seem to take an array of u values as an input so I decided to revisit Even Spacing on Curve and reformulate so that the user could input an array of (or a single) normalised U value. In the process, I fixed some bugs and hopefully cleaned up the trees a bit. The resulting two compounds are here:

http://www.exch.demon.co.uk/xsi/files/Evenly%20Spaced%20Curve%20Positions.2.0.rar

http://www.exch.demon.co.uk/xsi/files/Normalised%20U%20to%20Curve%20Position.rar

For even spacing points on a curve, Helge's Strand Tools provide a much better solution. I don't think there's another compound that accepts an array of normalised U values so the second compound may be useful.

Let me know if you find any errors.

Monday, 28 September 2009

Meshless Deformations in ICE

I've just posted a preview of an implementation of meshless deformations in ICE. The system deforms a polygonal mesh using particles and shape matching. It seems like a fairly efficient way of generating various types of soft body deformations whilst preserving the volume of the original mesh.

http://www.vimeo.com/6794261

I'd love to release the compound soon but the whole area of collision and soft-body/soft-body collision is huge and is definitely going to take some time to implement before it's user friendly!

Saturday, 26 September 2009

Dart Throw Update

(Note: there's an updated version of this node for 2011 SP1 and above here.)

I've updated the Dart Throw ICE node to version 0.9b. The new version utilises the new port dirty state features in the SDK to prevent the compound firing when you make changes in the overall tree. I've also added a cancel button and re-wired the evaluation cycle. All in all, this version is more stable and usable. Big thanks to Amaan Akram for help and advice with the code.

http://www.exch.demon.co.uk/xsi/files/dart_throw_0.9b.rar

Please note that due to limitations in the SDK when you cancel an evaluation in progress, the values in the PPG cannot be reset to their original values. CTRL-Z will restore those values.

Tuesday, 8 September 2009

Dart Throw Custom ICE Node for Softimage 2010

(Note: there's an updated version of this node for 2011 SP1 and above here.)

I've just finished off a custom ICE node in C++ utilising the new geometry features in the 2010 SDK. The node will let you position random, non-overlapping points on any polygonal geometry. The more iterations you use, the more 'packed' the distribution will be.

http://www.vimeo.com/6483842

The nodes are packaged in a RAR file as an Addon with a sample scene here:

0.9b (Latest version)
http://www.exch.demon.co.uk/xsi/files/dart_throw_0.9b.rar

0.8b
http://www.exch.demon.co.uk/xsi/files/dart_throw_0.8b.rar

It's a beta release a the moment, so please let me know if you have any problems/suggestions. Since it uses features only available in Softimage 2010, it won't work in earlier versions.

Tuesday, 19 May 2009

Roll Object Compound and Sample Scene

I've just finished cleaning up and, hopefully, optimising the roll object compound. The new compound removes expensive geometry queries in favour of filter and min/max in set. I think it's quicker on larger datasets although the downside is I've had to use more nodes!

The lowest point in Y on the object at simulation start becomes the virtual floor. There are many other ways to do this but it seems like a sensible way to keep the compound fairly general. If you want other objects to contact the same floor then their lowest point in Y also needs to be at floor level.

The Distance to Angle Ratio parameter controls the ratio of angular change to the distance the driving object travels each frame - higher values rotate the object more, lower values slow down the rotation.

Let me know if you have any suggestions, improvements or performance tweaks or if you find any bugs.

Scene: http://www.exch.demon.co.uk/xsi/files/roll_object_scene_v001.rar
Compound: http://www.exch.demon.co.uk/xsi/files/roll_object_compound_v001.rar

Thanks to Helge and Martin Chatterjee for their resources on similar operators:
Helge's Roll Tutorial
Martin's BallRoll SCOP

Thursday, 14 May 2009

Rolling Cube Rig in ICE

Just implemented a rolling cube rig in ICE. The video is here:

http://vimeo.com/4647214

It's a deformer rather than a kinematics operator. It also handles irregular shaped objects as this video shows:

http://www.vimeo.com/4662525

Friday, 13 March 2009

Constrain Null To ICE Particle's Transform

This script constrains a null's position and rotation to an ICE particle via a SCOP. Tag some points in your point cloud, run the script and each tagged point will now be followed by a Null. Get's very slow however with multiple Nulls on a cloud.

ice_track_particle_v1.0.3.rar

Plot ICE Particles To Curves

This script plots tagged ICE particles to curves. For each point cloud it creates a null at the scene root and places the curves under that null. To use, just tag points and run the script. A dialogue will let you select the frame range and step size.

ice_particle_plot_v1.0.0.rar

Thursday, 5 March 2009

Neighbour Points Plus 1.6

Neighbour Points Plus 1.6 expands on the PointNeighbors attribute that's native to ICE by letting you select 'n' levels of neighbouring points. You can select the number of levels you want, filter the results and/or exclude the original points.

Neighbour Points Plus 1.6

Big thanks to Todd Akita for cleaning up the code and resolving an issue with duplicate locations.

Deduplicate Array 1.2

This compound takes an array as input and removes any duplicates. It's broken out from my Point Neighbours Plus compound as it has some utility in its own right. Works fine with integer, scalar, location and vector arrays. Deduped elements don't have to be sequential - the compound removes any duplicate it finds.

Deduplicate Array 1.2

Index to Location

Building on the previous posts, it's easy to see how you can implement functionality in ICE that isn't there natively. One example is the limitation of the ID to Location node - it only works for particle IDs and not geometry indices.

The tree below constructs object context arrays of point locations and their indices. From then on, whatever context you're in you have access to these arrays and can query the location of any other index on the mesh. The only slight twist is that you need to use 'Find in Array' as lists of locations can't be conventionally sorted.

Repeat Loops And Redundant Attribute Declaration

The Repeat loop in the image below iterates 20 times and creates a column of particles - the counter increments the Y height by 1 unit each time. In Python, I'd normally create the array for the resultant positions and the counter itself outside of the loop and, for a while, this is how I constructed loops in ICE:



It turns out that ICE is much cleverer than that. Put plainly, you can 'Get' an attribute before you 'Set' an attribute. I know this doesn't sound too earth shattering but it confused me for a while. In a conventional scripting language you can't usually work with a variable/attribute before you've declared it. In ICE, however, you can. If I remove the initial Set Data on both the Counter and the Array in the tree:



The tree still works even though, ostensibly, for the very first iteration of the loop it looks like you're requesting Counter and Array before you've assigned any value to them. It seems that ICE pre-processes attributes before the tree is evaluated and initialises them to a default value - in this case on the very first iteration of the loop ICE knows that array is an array of 3D vectors and inserts a default vector value of (0,0,0) and Counter is a scalar and inserts 0.

Saves a lot of unnecessary tree clutter.