Sunday, June 11, 2017

Long time no see! Lego City is done and gone

Hi all,
I have been so caught up with work so bad that this blog has been left abandoned for a year (or 2).
I just want to update with the work I've done for Lego, the Lego City series.

I did R&D on the 2D facial rig system(from Flash created images to the 3D asset). Each part of the face (eyebrows, eyes, mouth etc.) are fully translatable, rotatable, and scalable.

Also there's a big improvement in SLR and FX. This is a big step for all of us as at Picture This Studio and it did require a huge collaboration between many people.

Here you go!

Monday, April 18, 2016

2015 Freelance work

Long time no post!
I was so lucky to be a part of these cool projects for the past year.


Phyto SC Plus Commercial(2015) - freelance
Responsibility: Rigging(Angel wings)

Smooth-E Commercial(2015) - freelance
Responsibility: Facial Rigging(Acne face)

PTT Commercial(2015) - freelance
Time: 0:05 - 0:07 (CGI bird)
Responsibility: Rigging, Technical direction
Roojai Insurance Commercial(2015) - freelance
Responsibility: Rigging(Kangkaroo)

Tuesday, August 4, 2015

Average Vertex Skin Weight 2.0 beta (Python only)

Have had some time lately to to what I wanted to do for quite some time.
While using the brush it usually screw up vertices that are modeled to be close to each other, i.e. for stylize character with hard edges or hard surface stuff.

This is an attempt to fix the problem by adding "distance between surrounding vertices" into the calculation.

 - Supports undo/redo.
 - Supports maintain max influence set on the skinCluster node.
 - Optimized (I did try, really.)
 - Big changes in calculation.
   Averaging weights will take distance between its
   surroundings into account.


Tuesday, October 7, 2014

Rearrange your geometry group for tidiness!

Haven't got much time to update lately. Been busy with work.
Still, I managed to wrote a little script when my patience was out looking at a messy geo_grp from the model department.

Just select the root geo_grp, the script will reorder all the children under it alphabetically (groups will be ordered last).

import pymel.core as pm
import maya.OpenMaya as om

def rearrangeGeoGrp(geoGrp=None):
    if not geoGrp:
            geoGrp = pm.selected(type='transform')[0]
        if not geoGrp:
            om.MGlobal.displayError('Select a geo group.')

    exit = False
    grps = [geoGrp]
    while not exit:
        nextGrps = []
        for grp in grps:
            children = grp.getChildren(type='transform')

            if not children:
                om.MGlobal.displayWarning('%s : is an empty group.' %grp.longName())

            # seperate grps and plys
            cgrps, plys = [], []
            for c in children:
                checkIfPly = False
                    shp = c.getShape(ni=True)
                    if isinstance(shp, pm.nt.Mesh):
                        checkIfPly = True

                if checkIfPly == True:

            plys = sorted(plys)
            cgrps = sorted(cgrps)

            for i, item in enumerate(plys):
                currentIndx = grp.getChildren(type='transform').index(item)
                pm.reorder(item, r=((currentIndx * -1) + i))

        if nextGrps:
            grps = nextGrps
            exit = True

Thursday, September 4, 2014

Resetting controller's transform with pymel

A tricky way to reset ctrl transform is to multiply the ctrl and the parent group matrices together and put the result to the parent then zero out ctrl transform. Whola! You got zeroed out ctrl where you put it.

import pymel.core as pm
import maya.OpenMaya as om

def resetChannelBox(obj):
cbAttr = ['tx', 'ty', 'tz', 'rx', 'ry', 'rz', 'sx', 'sy', 'sz']
for a in cbAttr:
attr = obj.attr(a)
locked = False

if attr.isLocked() == True and obj.isReferenced() == False:
locked = True
if 's' in a:
return False

if locked == True:

return True

def resetCtrlTransform(objs=[]) :
if not objs:
objs = pm.selected(type='transform')
if not objs:

for obj in objs:
offsetGrp = obj.getParent()
if not offsetGrp:
om.MGlobal.displayWarning('%s  has no parent. Continue.' %obj.nodeName())

srcMtx = obj.getMatrix()
grpMtx = offsetGrp.getMatrix()
resultMtx = srcMtx * grpMtx


if isinstance(obj, pm.nt.Joint) == True:
obj.jointOrient.set([0.0, 0.0, 0.0])


Tuesday, September 2, 2014

Average Vertex Skin Weight Brush!

    A custom brush for smoothing skin weight. It takes its surrounding vertices weights and blend it to the original weights. The result is kinda like hammer weight tool, but with brush you can paint on.

    Base on the original '' by Tom Ferstl posted on
I did a little modification. The brush now performs a little faster and supports undo/redo.
Please see: creative crash link

How to use  : 1.Put to your plugin path.
                         (ie. C:\Program Files\Autodesk\maya<Version>\bin\plug-ins)
                      2.Put to your python path.
                         (ie. C:\Documents and Settings\<username>\My Documents\maya\<Version>\scripts)
                      3.Execute the following python command.

import averageVertexSkinWeightBrush


Sunday, August 17, 2014

Mirror Mesh Deformer Plugin

This is my personal test project. The aim is to create a node that can mirror mesh deformation from left to right (for blendShape, maybe?). Yes, we have a bunch of scripts out there that does the job fine, but this is my personal challange to be able to have them deform together in real-time. And, yes, I just wanna practice.

I wrote this plugin in Python first because that's the only language I know (except MEL which I don't really consider a programming language). And when it comes to a LOT of vertices python kinda sucks. It lag so hard. So I spent a few weeks studying basic C++ just enough to get the plugin to be translate to C++. I found translating pretty easy since I already got all the algorithm working fine just a bit off this and that that C++ needs.


Fluid deformation on 100k+ vertices!
You can try it out for free. I just did this for fun so there'll be errors and cause unpredicted behaviour to Maya, of course. (Maya2012 64 bit only)

DOWNLOAD: mirrorMesh.mll

    -  Put mirrorMesh.mll in the Maya's plugin directory(wherever it is). Load the plugin.
    -  Select a polygon, Create the deformer. (cmds.deformer(type='mirrorMesh')
    -  Connect "outMesh" of the mesh you'd consider it the "base" to the "baseMesh" attribute on the node.
    -  Connect "outMesh" of the mesh you'd consider it the "Original" to the "origMesh" attribute on the node.
    -  Tweak(lower) the tolerance value on the node if you have a very dense mesh so the node can match vertices on each side

Have fun.

Friday, June 13, 2014

Corrective Sculpter beta

Hi, folks

    Since we all know linear skinning has been the backbone of rigging for quite some time then the fancy dual-quaternion has came out, but hasn't really play very well in practice and also setting up muscle system is quite heavy and can sometime be an overkill for such mid-end project. The only solution left was to setup driven key, or connections using joint's rotation to drive a blendShape or joint. As for elbows and knees, they're fine because they only rotate on 1 axis. But, for the shoulders and upper legs, this method will eventually FLIP at some point due to the euler angle calcualtion.

    I'd like to introduce my new tool for sculpting corrective shapes - 'Corrective Sculpter'. The tool was written in PyMel, again I'm too lazy not to use it. The idea is "when bad deformation happens, sculpt it!".

This is how it's designed to use.
- Provide the skin mesh, the buffer mesh(the blendShape target for the skin mesh)
- Select a body part to do shape correcting. In the clip is the upper-arm. Load joints.
- Pose to where the deformation looks bad, hit create target.
- Hit sculpt. Modify the shape as you like, then hit apply.

    Yeah, people have done it before, Michel Comet's PSD has a very great reputation for this kind of work. But,...I really  don't wanna have any custom node in my rig.

    Thanks to THIS TUTORIAL by Macro Giordano, I have recently learned how to set up a 'cone pose reader' using just Maya's standard nodes. The good thing is IT WILL NOT FLIP! Yeah, that's what I was looking for.

   And...thanks to Chad Vernon's cvShapeInverter link. Some part of the code in my script was taken from his code. The plugin does extract the modification from a deformed mesh. IE. You bend the arm, duplicate it, sculpt the duplicate, select original mesh select sculpted mesh, hit the script, BAM. It gives you the new mesh that can be use as front-of-chain corrective blendshape.

    That's it. Not really my work, isn't it. Just pieces of other people's work put together. Again BIG THANKS TO THOSE PEOPLE! *respect*

PS. The tool is still under development. I'm thinking of adding more functionality to it.

Wednesday, May 28, 2014

SOLVED: Scaling issue on rig with skinned polygon as influence object

    If you have to rig a model that's very dense with the random awful edge flow, weighting becomes your worst nightmare and you just can't do nothing about having some modeller to fix it or anything.
    Some would say, ok, dude, build a low-res proxy mesh, skin it, weight it, copy weights... In some cases - fine. But, not if the mesh has 'thickness' and requires a very wide range of motion like this dragon wing here. (Sorry, I can't show the full view of the model)

    With a very short deadline I had, that's when the influence object comes in. I modeled a simple low-res plane that matches the shape of the wing and sits right in the center of the real mesh thickness.

    I skin the plane to some joints. Painting weights on this was a piece of cake compared to the one before.
Then I added the plane as the influence object of the real wing. (Select the real mesh, then the plane. Go to skin>edit smooth skin>add influence with 'use geometry' checked)
Everything worked great except for when I scale the whole rig - this is what I got.

    When you scale the rig down the influenced area become thicker, and when you scale it up it becomes thinner. Normally, if the influence object is not skinned to any joint this problem shouldn't occur. I used to end up leave it as is and inform animator or whoever using it that scaling's not gonna work and I have no idea how to fix it (SHAME).

Eventually, I found the solution and I'm very proud to share it with you guys. 
1. Don't skin the influence object. Duplicate it, skin the duplicate instead.
2. The influence mesh and the base mesh have to scale with the rig. (parent, scale constraint)
3. Pipe the deformation using blend shape from the duplicated mesh to the influence 
    mesh with origin option set to 'world' not 'local'.
4. F***, the solution sits right under my nose for years. 

Now, you should have a scalable rig with influence poly object working correctly!