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:
        try:
            geoGrp = pm.selected(type='transform')[0]
        except:
            pass
        if not geoGrp:
            om.MGlobal.displayError('Select a geo group.')
            return

    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
                try:
                    shp = c.getShape(ni=True)
                    if isinstance(shp, pm.nt.Mesh):
                        checkIfPly = True
                except:
                    pass

                if checkIfPly == True:
                    plys.append(c)
                else:
                    cgrps.append(c)
                    nextGrps.append(c)

            plys = sorted(plys)
            cgrps = sorted(cgrps)
            plys.extend(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
        else:
            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:
attr.unlock()
locked = True
try:
if 's' in a:
attr.set(1.00)
else:
attr.set(0.00)
except:
return False

if locked == True:
attr.lock()

return True


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

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

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

offsetGrp.setMatrix(resultMtx)
resetChannelBox(obj)

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


resetCtrlTransform()

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 'tf_smoothSkinWeight.py' by Tom Ferstl posted on createivecrash.com
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 averageVertexSkinWeightCmd.py to your plugin path.
                         (ie. C:\Program Files\Autodesk\maya<Version>\bin\plug-ins)
                      2.Put averageVertexSkinWeightBrush.py to your python path.
                         (ie. C:\Documents and Settings\<username>\My Documents\maya\<Version>\scripts)
                      3.Execute the following python command.

import averageVertexSkinWeightBrush
reload(averageVertexSkinWeightBrush)
averageVertexSkinWeightBrush.paint()

Enjoy!
DOWNLOAD

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.

AND YES...IT RUNS DAMN FAST!

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

HOW TO USE:
    -  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!




Tuesday, May 6, 2014

Tentacles!!

Hi yall,

I was assigned to do some R&D on a project, which has, some kinda 'tentacle flame' element in it.
The tentacles have to move, slide and grow along in a predictable and animatable path. After the animation is done the FX department come in and generate dynamic flame out of the tubes!

The thing is, due to what I have learn, the director is pretty much a picky person(of course, most of em are).
It came to me to think that it's gonna be a pain to go back and forth between me and animators. So, what if, I let the animators rig it themselves!

Here come the tool. Draw a curve. Tweak some parameter. Boom! DONE. You have a animatable tentacle that slides through path. Nothing fancy at all, the script draw joints along the path for the path and the tentacle, apply a spline ik, create controls and hook up some connections.

PS. I'can't share the script for now, sorry.


Friday, April 18, 2014

If you're feeling lazy painting skin weights

Let's create facial blendshape targets....hmmm...I'm lazy to move verts around let's put some joints on the face and move it....hmmm....damn....to many joints....damn....too lazy to paint all those weights!!!

ทำเบลนเชปหน้ากันเถอะ....อืม...ขี้คร้านนั่งจัด vertex ใช้จ๊อยละกัน.....อืมมม...เชี่ย..วางไปวางมาจ๊อยเยอะเกิน....อืม....ขี้เกียจเพ้นเวท...


THIS IS EXACTLY WHAT YOU WANT AT THE TIME LIKE THIS.
สิ่งนี้ช่วยคุณได้...

Tutorial  http://www.kimonmatara.com/maya-deformation-smoothing/.
by Kimon-Matara


Tutorial : Volume preservation using joint and some node connections.

    I would like to share with you guys some trick I just learned about volume preservation on a bounded mesh. There are many ways to correct bad deformation, corrective blendshapes, helper joint with SDK, pose space deformer and etc. This is a simple way using joints and nodes to kinda 'push' out to restore the lost volume. This trick applys for any bend area. I tried it on elbow, finger, wrist, upper leg, worked just fine.


This is what we usually get...



With a couple of extra joints,
I ended up with this.



    To automate the push motion of the extra joint, I did a little node connection instead of set driven key, which of course, can be easily scripted. The idea is to have the extra joint properly aimed out from the bending spot.

The node connection.
On your far left is the upper arm(parent) joint. Next is the elbow(bend) joint.
On your far right is the extra joint and its parent group.


HOW TO DO:
1. Duplicate the bend_jnt(in this case: elbow_jnt). Will call this 'corrective_jnt'. 
2. Create 2 empty groups. 1. cons_grp' 2.'zero_grp .
   Snap the zero_grp to the elbow_joint (both translate and rotate).
   Parent the cons_grp under zero_grp.
3. Move the corrective_jnt over a little in the direction you want it to push the mesh out so it does not
   stays exactly at where the bend joint is. Depends on your joint orientation and your mesh, in my case,
   I moved transalteZ 0.3.
4. Parent the corrective_jnt to the cons_grp.
5. Point constraint the cons_grpto the parent_jnt(shoulder_jnt).
6. Orient constraint the cons_grp to both the parent_jnt and the bend_jnt with maintain offset checked.
7. Add a float attribute called 'multiplier' with the minimum value of 0 at the bend_jnt. This attribute is
   there to tweak how far the 'push' will go.
8. Create 3 multDoubleLinear nodes. 1.devideDegree_mdl 2.multiplier_mdl 3.inverseValue_mdl
9. Connect bend_jnt.roateX(in this case the axis is X) to the multiplider_mdl.input1.
10. Connect bend_jnt.multiplier to the devideDegree_mdl.input1 and set its input2 to 1/360(0.002778).
11 Connect devideDegree_mdl.output to multiplier_mdl.input2.
12 Connect multiplier_mdl output to inverseValue_mdlinput 1 and set its input2 to -1
13 Create a condition node set its second term to 0 and operation to 'less than'.
14 Connect multipliler_mdl.output to the conditon's firstTerm and colorIfFalseR.
15. Connect inverseValue_mdl.output to the condition node's colorIfTrueR.
16. Create a addDoubleLiner node, call it addTranslate_adl. Set its input2 to whatever value the
    corrective_jnt.translateZ(in this case the axis is Z) currently is.
17. Connect the conditon node's outColorR to addTranslate_adl.input1.
18. Connect addTranslate_adl.output to corrective_jnt.translateZ.

    We're done. Try adding the corrective_jnt to influence the mesh and tweak some weights. You can control how far the joint will push the mesh out by tweaking the multiplier attribute you added on the bend_jnt.
    You will end up with only one group which is the corrective_jnt parent group which should be parented under all mover control to move and scale with the whole rig. It's my personal preference to have this extra joint separated from the main joint heirachy.
    I'm planing on doing a little adjustment to have the joint push motion kick in exponentialy. Maybe add some limit to it(clamp?).


EXAMPLE FILE:
download


That's it! Have fun.
If you have any question, feel free to put them in the comment below.

Thursday, April 17, 2014

shoulder/rib cage deform rig

http://petershipkov.com/development/shoulderrig/shoulderrig.htm

Old technic. Sounded promising.
Example file in the link at the bottom.

ริกหัวไหล่ ช่วงซี่โครง (ตัวด้านบน)
นี่เป็นเทคนิคเก่าแล้ว แต่ดูเหมือนจะเวิร์ค
ไฟล์ตัวอย่างอยู่ในลิ้ง ล่างๆ

Sunday, April 6, 2014

R&H Voodoo

http://www.cgmeetup.net/home/rhythm-hues-oscar-winning-technology-voodoo/

Oh yeah, from what I can see, this is definitely VOODOO.

ใช่แล้ว framework เมพแบบนี้มันต้องเป็นเวทย์มนต์วูดูแน่ๆ

Thursday, April 3, 2014

Rio2 Behind the scenes: RIGGING! ริโอภาค2 เบื้อหลังRigging!

http://vimeo.com/90634433

This lady really got it. *RESPECT*

แม่นางท่านนี้วิทยายุทธสูงส่ง *คาราวะ*

Wednesday, April 2, 2014

Placing a follicle - the smart way.

He shows a very interesting technic about re-positioning a joint after it was bound to a mesh without effecting the mesh deformation and still maintaining skin weight painted.

But, that's not what I wanna talk about here.

Placing follicle on a mesh is kinda hard to get it at the exact point(of course, the mesh must not have overlap UVs). You have to tweak the U and V values around until it goes where you want, still, not the 'exact' point that you had in mind. In the tutorial he talked about his script(his comment) that place a follicle at exactly the point specified on the mesh or the closest possible. I wasn't be able to use it, because it was written using Maya python API 2.0. So, I dig into his code and modify some part of it to use the old python API and to better suite my needs. Take a look at my code. I commented on almost every line of it for you.

To run it just execute the whole function once select a vertex or 2 transforms(1.the mesh 2.any locator) and type:
    createFollicleFromPosition()

PS. the script requires PyMel.

ไปเจอ tutorial นี้ ของคุณ .
ในคลิปเขาแนะนำเทคนิคน่าสนใจมากเกี่ยวกับการย้ายตำแหน่ง joint หลังจากที่ bind skin ไปแล้ว โดยที่ไม่ต้องเพ้นเวทใหม่(ย้ายเอาดื้อๆเลย) น่าสนใจมาก

แต่..นั่นไม่ใช่ที่จะพูดถึงวันนี้

การแปะ follice บนโพลิกอนนั้นค่อนข้างยากที่จะวางในตำแน่งที่เราต้องการเป๊ะๆ(โพลีก้อนต้องไม่มี UV ซ้อนนะ) เราต้องนั่งปรับค่า U กับ V ไปทีละเล็กละน้อย เรื่อยๆ จนมันไปอยู่ในที่ๆเราต้องการ แต่ก็ยังไม่ "เป๊ะ" ในคลิปเขาพูดถึงสคริปของเขา(ในcomment) ที่เป็นสคริปสำหรับวาง follice บนจุดที่กำหนดบนผิวของโพลีก้อน(หรือถ้าไม่ใช่ก็ใกล้เคียงที่สุด) ผมเอาสคริปมาโมนิดหน่อย เนื่องจากเขาเขียนใช้ Maya Python API 2.0 ผมเลยโมให้มันใช้ API ตัวเก่า(เผื่อไว้) และก็โมส่วนอื่นๆให้มันใช้ง่ายขึ้นสำหรับผม
ลองอ่านสคริปดูครับ ผมคอมเมนต์ไว้เกือบทุกบรรทัดแล้ว

วิธีใช้ก็ execute ทั้งฟังก์ชั่นก่อนทีนึง แล้ว เลือก vertex หรือ เลือก transform 2 อัน(อันแรกคือ mesh อันสองคือ locator หรือกรุ๊ปอะไรก็ได้) แล้วพิม
     createFollicleFromPosition()


ปล. จะใช้สคริปต้องมี PyMel นะเออ


THE LINK TO THE SCRIPT

Pixar presto demonstration

MOMMMMMMMMM! I WANT THIS!!!

Our animator here at Picture This would jump around with joy while animating if we have something like this. Check it out.

แอนิเมเตอร์ที่ออฟฟิศผมคงเริงร่า ยิ้มแป้นไม่มีหุบแน่เลย ถ้าเรามีซอฟต์แวร์แบบนี้ไว้ใช้ ลองดูครับ

Tuesday, April 1, 2014

Blendshape...chop off the head!

From this useful post by Janifer Conley (http://www.lessthanthreesetdrivenkey.com/)

    I just wanna share this to you guys who didn't know this trick.Connecting blendShape  from  a mesh to another especially from the head (with facial expressions) to the full-body mesh can be troblesome and often require a heavy heavy wrap deformer have the full body mesh deforms with the head mesh.

    You'll end up with tons and tons of full body meshes all over your scene if you just duplicate the whole mesh to do blendShape targets.

WHY NOT JUST THE  "HEAD"?
warning: by using this method, the mesh topology will change. Make sure it won't effect other ppl in the pipeline.

1. Select the face components you want to do blendshape sculpt out of the full body mesh.
2. Go to Mesh>Extract. Then, delete history. Now, we have the head separated from the body.
3. Duplicate the head mesh. This will be our default blendshape head.
4. Combine the head mesh and the body mesh together.
     **IMPORTANT** You must select the head first then the body. Go to Mesh>Combine.
5. Merge vertices on the edge of the combined mesh. Delete history.

    Now, you're set! Try blendshape from the duplicated head mesh to the combined mesh with 'check topology' checkbox turned OFF. Now, turn the blendshape weight to 1 and try moving vertices on the head mesh around. The full body mesh should deform along.Whola! this works like a charm, if not, go back and read every line carefully. *face slap*

If you're feeling lazy, go grab my script at the download page. It' called separateReorderMesh.py

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
จากโพสนี้ post ของคุณ Janifer Conley (http://www.lessthanthreesetdrivenkey.com/)

    ผมอยากจะแบ่งปันเคล็ดลับนี้ให้กับคนที่ยังไม่รู้ การทำเบลนเชปส่วน facial expression ห้กับคาแรคเตอร์ที่โมเดลมาชิ้นเดียว(หัวกับตัวติดกัน) ในอดีตเราจะตัดส่วนหัวออกมาแล้วใช้ wrap deformer ห่อ โมเดลเต็มตัว ให้ตามโมเดลส่วนหัวที่มีเบลนเชป ซึ่งมัน...หนัก... หรือไม่ เราก็จะยอม duplicate ออกมาดื้อๆทั้งตัว แล้วทำเบลนเชปซึ่งมันก็...หนัก...

แล้วทำไม่มีทำเบลนเชปแค่ "ส่วนหัว" ล่ะ?

คำเตือน: ใช้วิธีนี้แล้ว topology เปลี่ยนนะจ๊ะ ระวังกระทบคนอื่นๆที่ทำงานด้วย เดี๋ยวงานเข้า

1. เลือก face ที่ต้องการจะตัด
2. ไปที่ Mesh>Extract แล้ว delete history ตอนนี้เราแยกหัวกับตัวออกจากกันละ
3. Duplicate ชิ้นหัวเก็บไว้ ชิ้นนี้จะเป็นชิ้นที่เราจะต่อเบลนเชปหาชิ้นตัว
4. Combine หัว กับ ตัว เข้าด้วยกัน
     **สำคัญมาก** ต้องเลือกชิ้นหัวก่อน แล้วตามด้วยตัว แล้วเลือก Mesh>Combine.
5. Merge จุดบริเวณรอยต่อที่ combine แล้ว delete history

   เสร็จแล้ว! ลองเบลนเชปจากชิ้นหัวไปหาชิ้นที่เรา combine ดู โดยใน option box ของเบลนเชปให้ติ๊ก check topology ออก แล้วเปิดเบนเชปเป็น 1 โมเดลต้องนิ่งสนิท ลองดัดๆ vertex ชิ้นหัวไปมา ชิ้นที่เป็นตัวก็ต้องขยับตาม หากเปิดแล้วพัง *ตบ* กลับไปอ่านข้อ 1 ใหม่

ถ้าขี้เกียจทำซ้ำๆหลายๆรอบไปโหลดสคริปได้ที่ download page. สคริปชื่อ separateReorderMesh.py

Monday, March 31, 2014

Hello world, for the first time.

First post. Nothing fancy. Just wanna say hi.
This blog is about me - as a person, animation(rigging, scripting, blah blah) and...everything I'd love to share.