Browsing"DotNet"

Adding mirror functionality to a custom rig

Jan 18, 2011 by     No Comments    Posted under: 3dsMax, Characters, DotNet, Maxscript, Rigging, User Controls

On our last production, I had to find a quick way of implementing a system that would allow me to set up basic mirror functions on any custom rig. Specifically, I needed a toolset that would standardise the main functions of the rig like selection tools for the current side of the body, mirror select, copy, paste and IK/FK switching.

I accomplished this with a simple custom attribute that allowed me to store the nodes of each half of the body as weak references. If you don’t already know, weak references are the golden goose of character rigging. They allow you to store arbitrary nodes within the character so that you can retrieve them at any stage without having to select the node itself.

RigGUI

In the video below, you can see how I set up a full mirror/rig selection system on a puppetshop rig. Puppetshop is great because it already has a load of good stuff already built in, so the GUI I add in the video (which is a custom dotnet interface) can simply expose functions from the puppetshop API.

The selector always knows what the opposite side of the rig is because you store each node’s opposite in the parameter block of the attribute.

So what it does is allows me to set up this feature on any rig within a minute or so. Because you can store the node assignments to XML, it is easy to mirror the nodes onto the other side of the rig for even faster setup.

I hope this video gives some insight into how automated setups can save a wealth of time in production.

If you want to try a max script that uses weak references on a rig, please read my previous post –

http://lonerobot.net/?p=158

I talk about them in a bit more detail and show you how you can control rig visibility using them.

Using HitchHiker – Building a Matte/Shadow material utility

Dec 21, 2010 by     2 Comments    Posted under: 3dsMax, DotNet, Imaging, Maxscript

This post is to show how you can use Hitchhiker to develop maxscript tools in super quick time. Any auto thumbnailer is going to have about a million uses in production in my humble opinion, as most of the development time on a utility is spend building the UI functionality. Whilst on the subject of dotnet controls, I would like to draw attention to another dotnet thumbnail control out there, written by TD Jason Labbe. It’s got a few things that Hitchhiker doesn’t have like multi select, so might be useful if Hitchhiker hasn’t quite got the functionality you need. Nice job Jason! You can read about it here

The Problem

On our last production, we had to consolidate a lot of complex sets into background renders as we were on tight deadlines. Often, the shot would need some form of contact shadow as well as masking so the obvious choice was to use the mental ray matte material. Depending on the type of shot, HD render times could be cut from 10 minutes per frame to around 45 seconds, with no perceptible loss of detail or quality.

The Solution

I wrote a utility that allowed the user to browse for the rendered backgrounds and quickly set the material up as a matte material, ready to be assigned to the background objects and rendered.

MatteHelper

This utility is a good example of what you can use HitchHiker for. The browsing window allows you to pick the map that you want, and with the new cache mode property on the latest hitchhiker, is very fast. The greatest thing was that I wrote this entire script on my train ride home one day. This was exactly why I wrote HitchHiker, a plug and play solution to speed up my deployment of production scripts.

The material setup is simple,  matte/shadow.reflection (mi) shader is made with an Environment/Background Map (mi) shader. The texturemap is then set to screen and the blur taken down. You have to option to include the alpha so that you can use the render for composition. While the script itself is simple, it’s an example of how you can speed up a common bottleneck with very small programming outlay. Suffice to say, it checks that Mental Ray is the production renderer, as the materials are only compatible with that, but if you wanted to adjust it for use with an alternative material setup, it would be very easy. There is a method called :

CreateMatteShader <texmap> <slotnumber>

This could be changed to whatever you liked.

There is another assembly that is included with this script too, called ImageBot. It is an extended picturebox that allows you to zoom in on an area by dragging a marquee with the the right mouse button. This could also be used in other scripts, for example a rendered frame buffer.

How to use the script

Make a copy of your scene and render all static elements and save the rendered background file. Start MonsterMatte and use HitchHiker to navigate to the rendered file and select it. Press ‘Create Shader’. The matte material will be created and added to the designated material slot.

Apply the material to anything in the scene that isn’t animated and render – watch how fast it goes!

Installation

To install, just download the script below and copy the folders to the root of your max installation. You’ll see the macroscript listed under the ‘LoneRobot’ category and is called MonsterMatte. It’s not really a monster tool, but unfortunately when I was writing this article that monster mash song kept going round my head, damn pesky irritating brain.

Merry Xmas!

download

HitchHiker Update v4.4

Oct 9, 2010 by     29 Comments    Posted under: 3dsMax, DotNet, User Controls

hh-new

I’ve been so swamped with work this last year, my planned update to Hitchhiker had to be stalled. It’s a shame really, as I have had a working version of the updated assembly for a while but no time to update the help files to show how to use it. However I’ve been pleased with the progress made in it’s place – I’ve been able to write RigStudio, Digit and Character Silo which I’m really proud of. Hopefully I will get a bit of breathing space to allow me to concentrate on next generation 3dsMax UI stuff, namely learning WPF.

There are a few updates – mainly from great feedback I’ve had from the community. I am glad people are using HitchHiker in any way to augment their Asset Browsing scripts. With the new additions that I’ve made, I am hoping this will be even better.

Please let me know if you like Hitchhiker and use it for anything useful. You feedback is critical as my time tends to be limited. So if i feel people are using the control I can spend my time improving it. I’d love to spend all my time refining this control but there are so many other project that I have to work on! But feedback on any level will always motivate me to fix and improve!

Recent Updates/Fixes –

v4.4 – 19th January 2011

Added the .buttonborder <boolean> property. If you set this to false, Hitchhiker will not render the black border around each control. If used with the .gap <integer> property set to 0, Hitchhiker will render like a seamless section of tiles.

buttonborder

Instantiating HitchHiker

I had to have a re-organisation of my namespaces as they were getting confusing. Since HitchHiker isn’t really anything to do with characters, i decided to change the default namespace to lonerobot.ui.controls. If you have any scripts that were written with the previous release of this assembly, you can just do a search and replace of ‘character’ for ‘controls’

make sure that you call dotnet.loadassembly <hitchhiker dll location> in your script before using.

if using on a dotnetform or maxform – dotNetobject “lonerobot.ui.controls.hitchhiker”

if using on a maxrollout – dotNetcontrol “lonerobot.ui.controls.hitchhiker” width:<int> height:<int>

please refer to the hitchhiker tab at the top of this site for more detailed help, all these are still valid

Additions to Version 4.4 of HitchHiker

Max file support –

Hitchiker will now support the searching of the Maxfile type. Not only this, you can render an associated thumbnail directly from the assembly to be displayed with the file when previewing it in HitchHiker.

Additional populate methods –

Hitchhiker was always designed to operate on a folder level, whatever was inside with the designated filetype was displayed. Now you have two options.

populate (by directory string)

populate (by file array)

This means you can now pass an array of filepath strings to be displayed in the hitchhiker window.

This can also be utilised with the enhanced search parameters –  PopulateFilterSearch

Hitchhiker will now allow you to display files that start with, end with or contain certain characters. So if you are doing a recursive search population of many folders, you can tell it to only display those with a particular character’s name for example.

Other options is that you could prefix or suffix a filename “Approved” or “Unapproved” and allow the showing of approved files only.

Fast Cache Display Mode

Hitchhiker is reasonably fast in realtime mode, but (like most asset browsers) can slow down when loading multiple hi-resolution images inside folders. Hitchhiker has a display state that  can be set to cache – meaning the thumbnails are stored locally on the user’s machine, meaning that the slowdown only exists the first time the populate method is called. Subsequent calls result in the control being populated very fast!

hh.cache =  (dotnetclass “lonerobot.ui.controls.hitchhiker+cachestate”).cache

Store Favourites of your commonly used directories

Hitchhiker can now add locations that you use to populate from to save specifying the folder each time

Fully integrated toolbar

Hitchhiker can be run without the toolbar and it’s behaviour controlled entirely by script, but setting the toolbar to true allows you to do everything from the menu system, set thumbnail sizes, search parameters etc, meaning it really is a pretty comprehensive asset browser straight out of the box.

A few caveats I have noticed about this release –

Occasionally the keyboard focus can be stolen by HitchHiker if you close the dialog. Make sure you call the housekeeping function in your close handler, as this will make sure max gets it’s shortcuts back.

Feel free to download at the link below. If you find any issues with using this version of Hitchhiker, please let me know and I’ll do my best to fix it. I would ordinarily like to test a release more than this one has been – But didn’t want to delay the release this to the community any longer. I hope it helps you make great utilities with minimum effort.

download

Flexible Animation System for Fingers and Hands

Oct 8, 2010 by     No Comments    Posted under: 3dsMax, Characters, DotNet, User Controls

digitui

For many years as a character animator I have wanted a system to aid with the animation of fingers. It’s one of the things that tend to be done as an afterthought when pushed for time on a production, but there is no doubting that some of the nicest animation will always have really great hand gestures. The balance is trying to find the balance between time and ease of animation. If you are really pushed for time, it would be far better that you could store hand poses that you use most of the time, with a view to having a robust toolset to allow you to refine them afterwards.

I recently wrote a system called Digit that goes some way towards addressing this issue in production. The key to this system working well was to provide a UI that was intuitive to the way people currently work in max, and making it minimal and simple enough that it didn’t need too much understanding. This article will hopefully explain the process that I undertook in planning and executing this system.

Planning the control layout

Digit-Roughs

I usually start with some sketches – i have a technical journal that I write ideas and loops into. This over the years (and much to my chagrin) has replaced my sketchbook but it does give me a kind of technical reference for everything. I will scribble UI ideas down before I code anything, as it helps me to plan in advance potential layout conflicts. It is by no means final but it gets me thinking about how everything is going to interact. The thing to remember is that it’s not something you’ll proudly display, but it helps to organise your mind and avoid any UI layout problems along the line. UI design is a hard thing to do, generally people will tell you when it is wrong in a heartbeat and not even notice if it is right. It’s one of those thankless tasks that only you can appreciate.

With Digit I felt I could deviate from the look of the max UI – firstly, square controls were simply not going to cut it, and I wanted to allow control to adjust the layout when running in either a portrait or landscape mode.  The FlowLayoutPanel is built for this task and I’ve used it extensively for my controls up to now. The layout logic was pretty simple, I didn’t want to separate the controls too much, what it gave me was two main panels – the selection interface, and the slider controls.

The critical thing for me in terms of the functionality of the system was that it was as intuitive as possible, and mimicked a lot of the same methods as the native max UI. This was mainly the use of CTRL and ALT to add and remove from selection, and the double-click hierarchy selection. My other consideration was to try to keep the dialog as minimal as possible. I had setup finger controls in the past and found, due to the nature of wanting them to be able to control individual fingers, that they can become large slider interfaces. I thought that this time i would be able to use less and still have the same level of control. Here is what I came up with in the end, they are the same UserControl, they have a hand property, Left and Right which decides what UI colour they get.

Colour profiles

Selection based curl slider

I did this by having a two stage approach, working on a specific selection or on the entire hand. If no finger element was selected, the curl slider affected the entire hand. If a particular finger had been selected, then the curl would only operate on that finger. The same went for resetting the finger position. This worked well, you could quickly set up different poses based on others.

Splay and Thumb position and rotation were different. You don’t want to splay individual fingers, it looks odd so this acts on the entire finger rig. And individual thumb position and rotation are also necessary. However the thumb curl operates on the global curl slider.

The +Thumb button was something that came from the evolution of the control and testing it on some real characters. Sometimes, you didn’t want to move the thumb but still move the fingers. This checkbutton allows you to affect the thumb curl and splay with the other fingers – as before, it is based on the selection, so you have to have no part selected for this to work.

help

Its all put in place with a bit of simple matrix rotation. You can prerotate a matrix according to an angle, so each time the slider moves, it is calling a function that supplies the current transform and returns a new transform matrix that is prerotated by the angle from the slider.

Medial,Distal and Proximal Selectors

The three selectors to the left of the fingers are to select across the first, second and third bones. I thought this gives an extra control if the automatic blended rotation of the fingers isn’t quite enough to get the hand pose you are after.

Pose Storage and Mirroring Transforms

I have been using XML for a while now to store any sort of pose when I use a reference transform monitor to store a node. Most of my facial animation systems and rig setups use these. Once the directory is specified, you can store the local transform of each node and that’s all you need. I use an XMLLayoutPanel to handle the files. Its a dotnet user control I released a while ago that handles all the layout and even lets you specify a custom thumbnail. Check my previous blog post if you want to have a go at using it.

When you apply it back on the hand later, you multiply the current finger’s parent transform with the XML preset’s local transform and you have applied your stored preset. Because you extract the local transform, the pose is the same, even when applied to a different hand position as you are making a new transform matrix from the current parent’s position. When you want to mirror the transform to the other hand, that is a little more involved.

You start by reading the local transform of the finger nodes. Then, you Mirror the transform matrices of all bones, by creating a mirrored transform around a common parent (like the character’s root). However the other arm is not necessarily in the same position. So, you need to create a mirrored transform of the hand too. Once you have this, you can get the mirrored bones local transform matrix. This becomes the one you use, as you can then multiply this mirrored local transform onto the current location of the parent (i.e. the opposite hand) With this you can paste a hand pose from one arm to the other, regardless of the arm position. I was grateful for all of the brilliant examples on the CGTalk board to help with this, specifically from Paul Neale.

Setup

It is possible to set up a character with this complete hand animation system without any Maxscript. This works on Bipeds, CATrigs, Puppetshop rigs and custom bone rigs, so hopefully it will be useful for many projects to come.

Loving LINQ is easy because it’s beautiful

Oct 7, 2010 by     6 Comments    Posted under: 3dsMax, Characters, DotNet, Technical Research, User Controls

One thing is certain, XML is prolific. I wanted to research the most efficient way of using this versatile language in future systems I develop for 3dsmax animation pipelines.

One of my latest research projects is looking at various options for storing information about characters in a project. There are many different types of data that is useful to be able to pull up, from node information to walk cycle data. What i haven’t had before is a unified method for storage and retrieval. I have been using XML in my character tools for some years quite successfully, from Lipsync storage to Walk Cycles.

I’m sure most studios out there are using some form of database, whether it be for asset tracking etc, and I’m sure that this is a perfect solution. However for this problem, after looking at SQL server configurations and methods I found a different approach that could span my need for database-like data handling and the transparency of storing to XML.

XML Verbosity

I’ll hold my hat up, part of this might be because I went to art school and didn’t pay enough attention in Maths, but there was something distinctly hit and miss about using XML within a dotnet assembly. The Document Object Model (DOM) felt quite cumbersome and wasn’t like the elegant OOP approach I was looking for. What was a transparent user experience with intellisense in visual studio, using XML on an object level became a clunky affair. With my last post about RigStudio, my dynamic character selection framework, I integrated a custom XML serlializer to take the guesswork out of the XML parsing and creation.

The Microsoft Language Integrated Query framework (or LINQ) is one of the more recent introductions to the dotnet framework and allows XML data to finally be treated like data. You can now perform queries and operations on the XML tree in a proper object orientated approach. If you go the whole hog, you can also build an XML schema from an existing XML template and have intellisense support for the XML document. Most importantly, the Linq XML classes are enumerable classes, meaning you can iterate then easily, meaning you can extract, merge and join portions of the whole document tree into other branches and documents.

Also available to the VB programmer are XML Literals. Basically, this means you can begin typing a variable directly into an xml tree – so your code actually resembles an XML document and allows you to integrate variables into the tree dynamically, so you can loop object collections to build complex XML documents completely via code.

Xelement

As you can see, you can format it exactly like an XML document directly from the variable declaration. To add a variable into the document, you can use :

<%= your variable here %>

This allows one to pass another XElement at this point to nest more complex trees. This is certainly far simpler to set up than a custom serliazation class.

Where LINQ fits in with 3dsMax

In terms of max, you can’t really perform the query commands that are the really useful part of LINQ (Well not to my initial research). The main class you will want to use with LINQ to XML is the XElement. In raw dotnetclass form within 3dsmax, you are using it in a similar way to how XML was previously treated – i.e. the DOM model. However, providing a class library that utilises the LINQ query methods could be worthwhile. Visual Studio is a mature development environment, and you are adding something to max. In terms of the deployment, I have no problem adding a dll to the max startup. I met with the 3dsMax design team a while back through work and they assured me dotnet is going to be with max for a long time to come.

Where the XElement class is useful, is that it can encompass many different XML files, or a single branch within a particular file. If you had a selection of XML documents that stored the scene nodes of a different scenes,You could use a LINQ query to get the filenames where a specific object resided. But my purposes, whilst similar was to get this working within a character pipeline.

My idea was to create a type of XML Database that I called Silo. This would be setup in Max using managedservices.MaxsciptSDK functions to pass object names into the assembly that could then be written to XML. It could also integrate RigStudio into the same file. What this means is there is a front end that can quickly store node data about a character rig which can then be queried, giving access potentially to any data applicable to the characters within a particular project, whether this would entail node data, mirroring information, Lipsync, Walk Cycle footstep length – the possibilities are endless.

Most of the time, animators want to be able to control visibility of characters at various points, some times you want to see the controls for speed, sometimes the mesh for previews. Having different layers for each of these types is fine, but when you have a lot of characters, it can mean navigating the layer manager is more involved. Wouldn’t it be great to just store these relationships in a datasource and keep the entire character on one layer? In fact, you could have ALL characters on a single layer if you wanted, the database could then handle all node interaction.

The front end on my prototype looks like this, I’m still trying to work out the best layout at the moment, as it feels a little thrown on to me. However it’s enough to quickly setup a multiple character database that can be automatically bound to my Rigselector control. Each tab allows me to store selected elements of the rig into the various sections.

SiloConsole

Here’s a useful class that you can use within a dotnet assembly – I needed a way of getting the selected object names into the dotnet assembly in order to save them to XML

Public Class MaxOps
    Public Function GetCurrentSelection(ByVal SingleNode As Boolean) As List(Of String)
        Dim NodeList As New List(Of String)
        Dim Selectioncount As Integer = ManagedServices.MaxscriptSDK.ExecuteIntMaxscriptQuery("Selection.count")
        If SingleNode Then
            If Selectioncount = 1 Then
                NodeList.Add(ManagedServices.MaxscriptSDK.ExecuteStringMaxscriptQuery("Selection[1].name"))
                Return NodeList
            Else
                Return Nothing
            End If
        ElseIf Selectioncount > 0 Then
            For i As Integer = 1 To Selectioncount
                NodeList.Add(ManagedServices.MaxscriptSDK.ExecuteStringMaxscriptQuery("Selection[" & i.ToString & "].name"))
            Next
            Return NodeList
        Else
            Return Nothing
        End If
    End Function
End Class

The final tab updates RigStudio for Silo compatibility. You can now build a rig selector directly from silo, or import a previous version.

One option with Silo is you can specify a species for the character, so that you can control visibility of different types of characters. For example you can use LINQ to combine types of queries. A literal translation would be to ask –

“Unhide all animation control nodes that reside in the animal species”

With LINQ, this command would look a bit like this –

query

You can see the use of XML style parentheses in the query. These are known as axis constraints that return the xml nodes of ANY character with the same branch name. This means you are using the XML nodes like objects.

Another thing to remember, is that within max a system.array with be cast into a max array type. So if you are using dotnet lists and specialized.collections within the assembly, that is fine, but in order to avoid extra code in maxscript it’s best to make sure the function has the appropriate return type.

Hooking up the XML Database

dbclass

This is a breakdown of the SiloDatabase class – This uses LINQ to consolidate an XML file into a queryable dotnetobject in 3dsMax. As you can see, there are many methods, all of which can be hardwired into other assemblies, as you would only usually be running a single instance of this class. This means I can bind other assemblies to use the database without any maxscript interaction. This is always my goal, maximum flexibility with minimal deployment. The deployment for this whole database pipeline within a project? a couple of lines in max startup. It grows with the project and all the selection logic is built into the controls, not the deployment code, so can evolve and improve as the project goes on. The core of the database object isn’t really a database of course, its a collection of XML files. But when max instantiates the Silo Database dotnetobject, it appears and acts like one because of the LINQ query methods.