Friday, July 31, 2015

Thats what lifes about....

I just met a guy, he's a barrista at a cafe at the start of willis st. He rode 5000km accross Canada. I asked if he was a cyclist? His answer was 'no, it was a drunken idea and i went through with it'. He rode Montreal to Vancouver. What an amazing trip that would have been.
If that's not living life, i dont know what is.

Thursday, July 30, 2015

Stretch Node Maya API Plugin Comparisons

As mentioned in a previous post I had some woes querying the matrix data in my plugin. I did some simplified tests and have no implemented these tests into the node. The video below demonstrates a comparison between the matrix plug node and the transform plug node.

Stretch Node Python API Plugin demo from Tim Forbes on Vimeo.

Test stretch node plugin using matrix connections rather than channel connections. This video compares two test plugins briefly. One plugin using Matrix connections, the other using Transform channel connections. This is a test purely to look at different types of data handling and how I can use Mayas API to simplify node graphs for common rigging techniques.

Wellington - our new home

Wow. What a whirlwind the last week and a half has been. We have done so much in such a short time, and we have loved every minute of it. Setting up again in a new country is always a hard task. This is our second time at it, and I do think it makes it a bit easier having done it before, but each country is different so there are always different curve balls that are sent your way.
Welly Adventures
However NZ has been really nice to us. I get this feeling, unlike in Australia, that everyone isn't out to screw you. It just seems a bit fairer here. This may be due to the smaller population, there's still a bit more personal care. I've found companies here really helpful and transparent, at least more so than their counterparts in Australia.

Anyways, we found a nice house. After being scared that we wouldn't find a dog friendly property, we really hit the rental market hard and got offered a few properties. In the end w chose the on that felt right, and in the end it ended up being perfect to split the difference between my work and Kates work! Some things just work out right.
Wellington Botanic Gardens
We are now going through the painful task of finding a used car. I hate looking for cars. Anyways, we'll get there, but it is growing tiresome sifting through all the crap on trademe.

Kate has started working and is absolutely loving it which is just the best news, and we have been catching up with good friends from Vancouver which has been really nice.

What an life change Clooney has gone through! 8 months ago he was in a cage, no where to go. Fat forward 8 months and he's getting lots of walks and now has his own Wellington registration number. We have really given him a second look at life and it is just beautiful to have him around. Although he now associated plastic bags with walks (we always grab a few to collect his business). So now every time I grab an apple from a bag, he gets all excited and thinks it's time to go and starts whining, so that lucky dog is getting walked A LOT!
Clooney
I start at Weta next Monday and am so excited. It's going to be so amazing to be part of a team that is creating such amazing work. I am feeling very inspired and pumped to create some amazing work.
Welly Adventures

Wednesday, July 29, 2015

Maya API Matrix Research

So after my last post I have delved into Maya to test out some Matrix data queries to determine where my node was going wrong. The test I set up in Maya was simple.
Build a locator. Move it somewhere other than the origin (origin is fine but the data would just read 0.0,0.0,0.0. I wanted something in there as it makes it easier to verify that the data is returning correctly.

I then started writing some API code that would:
#get the active selection
#loop through selected nodes and for each node
     #find the plug for the matrix attribute
     #get that plug as matrix data
     #extract the transformation data
     #print the x,y and z coordinates.

I chose this test as that is exactly what is going on in my stretch node. In the node the .matrix attr is connected into the node, and from that plug I try to retrieve the x,y and z position. However it is returning incorrectly.

So the code in my Maya test scene is working, so the error must be in the creation of the node attribute, or the way in which I extract the data from the data block. Anyways, here is the code I used to the the t.x,t.y and t.z of a selected object from the matrix plug. I hope you find it useful.

import maya.OpenMaya as OpenMaya
dagPathFn = OpenMaya.MDagPath()
#get active selection
mSelList = OpenMaya.MSelectionList()
OpenMaya.MGlobal.getActiveSelectionList(mSelList)
selItr = OpenMaya.MItSelectionList(mSelList)
#iterate through selection and get the world space positon from the matrix plug
while not selItr.isDone():
     selItr.getDagPath(dagPathFn)
     nObj = dagPathFn.node()
     #we got the node from the dagPathFn#now we get the dependency node
     objDepNodeFn = OpenMaya.MFnDependencyNode(nObj)
     #find the .matrix plug
     mxPlug = objDepNodeFn.findPlug('matrix')
     print mxPlug.name()
     print objDepNodeFn.name()
     #get plug as MObject which we will attach MFnMatrixData to.
     mxObj = mxPlug.asMObject()
     mxDataFn = OpenMaya.MFnMatrixData(mxObj)
     #query the transformation, returns MTransformationMatrix
     trfnMX = mxDataFn.transformation()
     #get the translate in world space
     v = trfnMX.getTranslation(OpenMaya.MSpace.kWorld)
     #print it out!
     print v.x,v.y,v.z
     selItr.next()

Positon From Matrix

I am currently switching my stretchNode over to work on a matrix input rather than a vector input. I was having issues when querying the dataBlock of the MPxNode to return the matrix data. Pretty much I wasn't getting the correct information. The way this connection was made was the ".worldMatrix" attribute was connected to the '.inMatrix' attribute on my stretchNode. I accesed this with:

startMXDataH = block.inputValue(stretchNodeMX.aStartMX).asMatrix()

Now this was not playing nce with me. As I went further down the track I was not getting the correct information returned.

So here's what I have..I'll delve deeper tomorrow...

def compute(self,plug,block):
#method 1
#get matrix and translate from finding the dependency node and working from there
#returns the correct t.x,t.y and t.z
#-12.0540640814 5.6978884254 7.7806477623

sNode = self.thisMObject()
plugArray = OpenMaya.MPlugArray()
depNodeFn = OpenMaya.MFnDependencyNode(sNode)
startPlug = depNodeFn.findPlug(stretchNodeMX.aStartMX)
startPlug.connectedTo(plugArray,True,False)
stObjMx = OpenMaya.MMatrix()
if plugArray.length()>0:
for i in range(0,plugArray.length()):
stObj = plugArray[i].node()
stDagNodeFn = OpenMaya.MFnDagNode(stObj)
stObjMx = stDagNodeFn.transformationMatrix()
stP = OpenMaya.MTransformationMatrix(stObjMx)
vec = stP.getTranslation(OpenMaya.MSpace.kWorld)
print vec.x,vec.y,vec.z

#method 2
#get the matrix data from the input plug and work from there
#returns the incorrrect t.x,t.y and t.z
#5.26354424712e-315 0.0 0.0078125

startMXDataH = block.inputValue(stretchNodeMX.aStartMX)
startMX = startMXDataH.asMatrix()
#just print the "translate" parts of the matrix - does not return what I'd expect.
print startMX(0,0),startMX(0,1),startMX(0,2)

#method 3
#returns the incorrrect t.x,t.y and t.z
#0.0 5.26354424712e-315 0.0

#get the transformation matrix to query the translation from there. Once again it returns the incorrect imformation
mxData = OpenMaya.MFnMatrixData()
mxData.create(startMX)
stPTransformationMatrix = mxData.transformation()
stPTranslation = stPTransformationMatrix.getTranslation(OpenMaya.MSpace.kWorld)
print stPTranslation.x,stPTranslation.y,stPTranslation.z

block.setClean(plug)

Obviously something's going screwy with my coding here, and my use of the API. But anyways, it's all about digging through it and working out whats wrong...to be continued tomorrow. Something's going wrong with either my creation of the matrix attribute and the kind of data there..but I'm pretty sure thats good. So it must be in the way I am querying the data from the dataBlock...hmmm.

TBC...

Tuesday, July 28, 2015

Stretch Node

This afternoon I have been working on a MPxNode. As mentioned in previous posts, I am planning to learn the Maya API, and as a part of my studies I am going to build some tools that will make my rigging workflow more efficient. So I have started somewhere simple. We all build stretchy joints into our characters for one reason or another. The standard setup is as such: two input points have the world position connected into a distanceBetween node. The output of the distance between node is divided by the full length of the joint chain before it starts stretching. This is normally done in a multiplyDivide node. Now if you want to build global scalability into your rig, you need to divide the initial output from the distanceBetween node by a global scale parameter. This requires another multiplyDivide node.So here we have 5 nodes to calculate something very simple. What I decided to do was build a node that would require two input points only. Therefore the setup will use 3 nodes, 2 inputs and the custom node.

The node is really very easy to write, and the longest part of it is actually setting up the attributes on the node and how they affect each other. Once you have a template for a MPxNode you can just copy and paste it as a starting point. However it is always nice to write this out and make sure you understand it rather than just copying and pasting it.

So this stretch node has 3 inputs. the startPoint and endPoint, as well as a length attribute which the user sets to the length at which stretching will start. There are then two outputs. Distance, which just returns the distance between the two in points at any given time (useful for determining the point at which stretching will occur), and the main output which outputs the final stretch value which will generally get piped into the scaleX of the necessary joints.

What awesome things did I learn when writing this plugin. The attribute that enables MPoint to return the distance between two points.

posA = OpenMaya.MVector()
posB = OpenMaya.MVector()
p0 = OpenMaya.MPoint(posA)
p1 = OpenMaya.MPoint(posB)
distance = p0.distanceTo(p1)#returns double

Next awesome thing.In the initialize() function we call this:
plugin = OpenMayaMPx.MFnPlugin(obj,'Tim Forbes','0.0','Any')
We then register the plugin type. Now this is different depending on what plugin you are creating, and will require different input data. Somewhere to get caught out, especially if you copy your template from a OpenMayaMPx.MPxCommand type plugin...like I did :p
The differences here are below:
OpenMayaMPx.MPxCommand will be plugin.registerCommand('command name', creator)
The command only requires the command name and the creator function, however the node requires a few extra things as seen below.
OpenMayaMPx.MPxCommand will be plugin.registerNode('stretchNode', stretchNode.kPluginNodeId,creator,initialize)

Because we are creating a node that will be connected to the dependency graph we need a unique node ID, we need the node name, the creator function and also the initialize function. The initialize function is where all the node attributes are added. The creator function is where our pointer is created to access the plugin within maya.
The unique Node Id is created using the inbuilt maya function: kPluginNodeId = OpenMaya.MTypeId(0x00000882)
For home use I have generated an arbitrary ID, however in production you would want to make sure you used an ID that would not clash with in house node IDs.Currently I built the node to take on the translates of the two input points. This was for ease of building and proof of concept. My next version will take wither the world matrix or transforms, thus making the node more adaptable to different rigging scenarios. Anyway, I built this node into a rig and you can view it working below.

Stretch Node from Tim Forbes on Vimeo.

Maya Python API Stretch Node


Next Up. Add in matrix connections to the StretchNode. Following that I'm going to make a MPxCommand plugin that traverses the dependency graph to find connected skin clusters. This will be useful in a convoluted node graph if you need to manupulate the skin cluster in a specific way, or really any specific node I guess:-)

Monday, July 27, 2015

Interesting Things with the Maya Python Api

I have found the API becomes a lot easier to understand as you realise how attributes are inherited between classes. Also, if you read this and see that I am incorrect, please correct me. I am writing this as I learn and this is being written down as best as I understand. Writing it almost helps unravel my thought process and break the concepts and problems down into their raw data. Thus making the information easier to understand.
So I was writing a default dependency node template. As I am writing this I am trying to understand why each of the pieces of a node are there, and what they do. Each time I need to use a piece of code, I will refer to the API guide and understand where the command or attribute had come from and how it is returning the data.
The interesting one I just came accross was when working with a MFnNumericAttribute class. I was using this in the initialize() function where the different attributes are built for the dependency node.
What I found was when I came to set the attribute to keyable, storable etc, I could not find any information relating to these attributes in the documentation for MFnNumericAttribute. This is where I realised that these attributes were being inherited from the parent class, MFnAttribute. So by creating a MFnNumericAtribute, I had access to all the attributes associated with this command, but I also had access to everything above. So:

nAttr = OpenMaya.MFnNumericAttribute()
nAttr.create('longName','shortName',OpenMaya.MFnNumericData)
#now you can access attributes from MFnAttribute
nAttr.setKeyable(True)
#or attributes from MFnNumericAttribute
nAttr.setMin(1.0)

Ok I know this is super novice. But one thing I realised when I was starting to learn, is these little things can really help learn how to read the documentation, and I couldn't find that info anywhere out there, a lot of it was assumed knowledge. That being said, to find the information for yourself means that you will always remember it and understand how to apply that same knowledge to different scenarios.
Once I'm done with my default node template I'll bang it up here. Cheers.

Learning the Maya Python API

This is something that I have been meaning to do for some time. As always I haven't found the time, or need, to do so. I have constantly been so busy with work that hasn't really required the development of API tools, or that I haven't been able to justify the time expense to convert the work to an API based toolset.
I think that a time comes when you realise it is time to learn some things. Coding is like learning a language. Without the right mindset or need, it is very difficult. But when offered a good practical reason to learn, new concepts and knowledge seem to be learnt a lot more fluidly. I feel this is where I am now. My python coding has got to a certain point in Maya, and I now see a use for the power that I can harness through the API. Although slow, I am picking it up a lot better than last time I started reading the API.
I find one of the biggest things is realising how to read the help docs, and being able to read the C++ documentation and convert it to python. This will prove useful when delving into C++. For the moment I am learning the Maya Python API so I can focus on learning the API toolset, and not have to worry so much about syntax. Once I have that sorted I will start moving accross to C++.
For the time being my goal is to work though David Goulds Maya Programming Books, and as I do so to build some simple nodes and commands that package up some commonly used rigging node graphs that I often build.
Keep checking back for my progress.

Sunday, July 26, 2015

The road to recovery!

It is happening! Slowly but surely I'm starting to run. Twice this week, making a total run time of 10 mins this week :-) It's a darn sight better than it has been. Baby steps, nothing stupid and just easing into it. Today is a lot better than earlier in the week. The pain hasn't come back the same way, and what pain did come back has subsided really quickly.
In a few weeks we move to our new home! The commute to work is about 13kms. My plan is to be running that a few times a week in a couple of months. like I said, baby steps, but the will is there and I know I'll get there. I just need to be smart about it!

First Days In Wellington

I can't believe it's already been a week in Wellington. It has been so much fun and so inspiring to be in a new city again. We have done so much exploring, met so many cool people and really just tried to immerse ourselves within the city. This morning I hit up Lulu Lemons free yoga class which was nice, and then followed it up with brekky with our friends from Vancouver Jonathon, Evelyn and their new bubs, Mara. We headed to Loretta and it was amazing!
Last night we had pizza and beers at our pad with Nick and Emma. Some more friends from Vancouver. It is so good to catch up with our friends that we made when we were overseas. It's like we never left!
Having Clooney here has been a blessing. It has really forced us to get outside. We have been walking him a lot and he has been charming everyone. We took him on a big walk through the Botanic Gardens last night, and then he just chilled like a good old dog when Nick and Emma came over for dinner! Funnily enough, he is such a pleasant dog, he has been getting loads of comments while walking around the city. Everyone loves him :-)
Wellington Botanic Gardens
Clooney
Wellington
Wellington Botanic Gardens
Wellington

Saturday, July 25, 2015

Interesting Blog Written By My Uncle!

My Uncle wrote a very interesting article, in which I feature. It was nice to read and happened to sum up my career so far, which was nice to read, as I feel you never take a step back and acknowledge your own successes as someone else may. So reading this article made me realise that I have been lucky and have worked hard to enable myself to work on some amazing work, at some great companies, with amazing artists all over the world.
Life is good and I am blessed to be leading the life I am. Check the article below.
My nephew just got a job with Weta

Creature TD Reel

Tim Forbes Creature TD Reel 2015 from Tim Forbes on Vimeo.

My latest Creature TD reel with my favorite work. Latest additions to the reel are Chappie and TMNT. I hope to add some more updated personal work soon.

Big props to all the crew at Image Engine for the amazing work.

Music By Arcade Fire. "Sprawl 1" from album "The Suburbs".

Friday, July 24, 2015

Moving To Wellington

WOW. About a month ago Kate and I landed jobs in Wellington, NZ. It was such a bizarre scenario, that both parties of a relationship landed amazing opportunities in the same overseas city. We would have been stupid to not jump at the opportunity. And jump we did. From discovering we had jobs to leaving Adelaide it was literally 4.5 weeks. In that 4.5 weeks we had to get our house ready to rent, get our house rented, pack up everything in our house and store it somehow, deal with 2 cars, deal with a dog that had to somehow get to Wellington, resign from two jobs, tell our parents we'd be leaving...again, and leave the house we just bought and absolutely love.
Needless to say, that 4.5 weeks was brutally busy, but as Kate and I always do, we smashed it out and got everything done. I worked up to the friday (3 days before we left), which made it difficult to do a lot, so my weekends and after work hours got really busy, but it was fun and finally gave me something to do!
What helped....well, Go Box helped for storing our stuff. Pretty much Go Box delivers a shipping container to your door. You fill it with your stuff (see 3D Tetris Post), then they take it away. Filling that box sucked. I think I am looking forward to unpacking it even more. Gum Tree helped a lot. The amount of shit we sold / gave away is amazing. The saying "One mans trash is another mans treasure" is truly accurate. I feel sorry for the dude that took our lawn mower. That bad boy weighed about a tonne and would have cost a boat load to ditch. We stashed a shitty old clam babies bath on the footpath...it was gone in like 10 mins???
We smashed the cleaning, got the house looking gleaming and employed Toop and Toop to rent our beautiful house. They were onto it and found a tenant within a week of advertising it!
The last few nights in our house were spent on a blow up matress. We had to stay with the house as Clooney needed somewhere to stay up until his departure (about 5 hours after us) on Monday the 20th. So we vacated on the 20th at 3am to the airport and left Clooney in the backyard. Kates parents then came down to make sure that Dogtainers Adelaide picked him up at 9am and took him on his merry way. We arrived in Wellington later on the 20th, after some delays and running to the plane in Melbourne due to a huge delay due to iced up planes...yes, iced up planes in Melbs!
Koa from Weta was there to pick us up, hook us up with a car, take us to the phone dealership to get sim cards and then drop us to our accom. Clooney flew on Tues the 21st, spent the night in Auckland and then arrived in Wellington on Wed the 22nd in the afternoon to a relieved Kate. He's loving it and I don't think he misses Adelaide.
Now we have found a place and are searching for a car. I have another week off and Kate starts on Monday. It has been a hectic week and we have seen a lot of Wellington while looking for housing. This city rocks! It is so beautiful and vibrant. It feels way bigger than the population leads you to believe. I'm now eagerly awaiting starting at Weta. I am so pumped to do some amazing work and to work with an amazing team.
There have been some stressful times, but we are so stoked to be here. So far the move has been so worthwhile and has broken us out of a rut that we had got into in Adelaide. Good times!
Packing Up
Wellington,NZ
Wellington,NZ
Wellington,NZ
First Days In Wellington

Lizzy Hawker-Runner

I am currently reading the book Runner, A short story about a long run. Written by the dominating female Ultra Runner Lizzy Hawker, it looks into her amazing career, and delves into the psyche of an ultra runner.
She quotes famous people throughout the book, and one quote that really stood out to me was from extreme skiier Andreas Fransson.
"You can choose to create whatever reality you like! Life goes on and how we want it to go on is a choice.....so we might as well make right now awesome."
Happy saturday!

Wednesday, July 15, 2015

On the road to recovery.

Injury has offered salvation. As an endurance athlete, injuries suck. They make your life feel like it is falling to pieces and you're just not sure how you are going to be able to continue! Very melodromatic I know, but if you are a fellow athlete, you'll know what I mean.
However, all that being said, this injury was one of the best things to happen to me. It forced me to break out of a bad rut that I was in. An endless cycle of exercise to maintain some unknown level of fitness that I had set myself as a goal to maintain, for no particular reason.
In hindsight, this was waiting to happen, and all the signs were there, I just had tunnle vision and and avoided listening to any warning signs.
Now, 10 weeks later, or there abouts, I can still barely run, but I can now cycle, which is a blessing. It feels great to go for a ride again, especially with the garmin turned off. No caring about pace, time or distance. Just doing it because it is fun.
I am starting to try run/walk sessions, with little success, but atleast the pain afterwards now subsides fairly quickly. Hopefully it's only a month or so until I can start running properly.

3d tetris!

Moving again! I thought we were finished with doing this. I guess once a nomad, always a nomad!

I feel my life for the past days has been one frantic game of 3 dimensional tetris. However if you lose, all your posessions end up broken, damaged, dank and smelly or just not packed. Not packed isn't really an option, and the other consequencs aren't really preferable either.

At about 11:30 today I find out if I won the game! I teally hope I did!

Monday, July 6, 2015

Still Injured

Yep, I well and truly ruined myself this time! Still unable to run, and only able to put in a half arsed kick in the pool. However I have discovered that bike riding is OK so that has been a saviour to be able to get outside and enjoy some activity again.

So I tried running on Sat morning. The aim was a run walk session. 1min on, a fee mins off repeated for say 20 mins. I lasted 1 block! Boooo. I'm gonna guess a good month of rest yet.

After this failed run however I decided to do some different exercises. As i was in my gear i was in the mood to work out. So some core was followed by jump rope and burpies. I have to say running training never made me almost puke. Two days later and my legs are nailed! I know it seems strange I can do jump rope but csnt run. On the spot is fine, it's the push/pull part of the foot strike that is causing the issues as the hammys engage.

Anyways, when I can finally start running it's gonna be pretty sweet!

Beginning of a new era.

When one door closes, another one opens. Kate and I have opened a new door, started a new chapter, turned over a new leaf. Sorry for all the cliched phrases.

Exciting times lie ahead for us. I think we have truly cemented our nomad lifestyle now. We have well and truly rejected the status quo, which i had thought we has fallen into in a big way. Big opportunities don't present themselves all the time. You only live once and it's the opportunities that you don't act upon that you'll always remember.

What do I remember about whistler....a lot of good things but i'll always remember that I didn't hit Air Jordan! I missed that boat now. 

My good buddy Heisler has just stepped well and truly out of the corporate rat race and is now pursuing a fewardi g wholesome lifestyle. I have such admiration for this move and it was a huge inspiration for me. No Regrets.

Wednesday, July 1, 2015

End of an era

I remember back in 92 when my dad bought our subie! What a work horse she was. Such a great car. Beautiful to drive, reliable, so many great adventures.

Anyways, after being in the family for 22 years it finally became time to pass her on. Our NZ reloction is requiring us to sell our car and declutter a bit. Otherwise it just costs too much to store everything.

Subie was passed onto a very eager lad. He said it was the best GL wagon he'd seen. I hope that he continues to have rad adventures in her. 

Subie, we'll miss you! Thanks for the good times.