Tuesday, 23 September 2025

 So it finally happened, the URL that I used for 15+ years to reference sin math went down.

For posterity, i'll paste it here:


Fun with Sin


To create the sine wave curve pictured in the first example below, consider the illustration above. Imagine the hypotenuse, C, of the triangle sweeping around the circle in a counter-clockwise rotation. At each point along the sweep, you get back the length of A on the Y axis. The circle is 1 unit in radius, so the value goes from 0 to 1, then back to 0, then 0 to -1 and back to 0 again.The reason you get the "sine wave" curve below is that you are progressing through the values of the 'sweep' over time.

The sin() function uses as its input the angle, , of the counter-clockwise 'sweep', in radians, not degrees.
There are 2* PI radians in 360 degrees.
radians = degrees * (PI / 180)
degrees = radians * (180 / PI)
More easily, in MEL you can convert using the commands "deg_to_rad" and "rad_to_deg".

In these examples, Maya's predefined attribute called "time" (the current time in seconds) is input to the sin function. This means at 3.1415927 seconds, we've gone 180 degrees around the circle, which gives the progression from 0 to 1 and back to 0. At 6.28 seconds we are the rest of the way around (0 to -1 to 0) and the cycle repeats.

Note: the curves graphed below are the result of baking the expressions into keyframes. You won't see these curves in the graph editor when using expressions.

functiondescriptionexample
sin( )

returns the sine of the given value.
The sine ratio is a value between -1 and 1.

With a steadily increasing or decreasing argument, the cos function returns steadily increasing or decreasing values between -1 and 1. This is useful for creating rhythmic, oscillating changes in attribute values.

translateY = sin(time);

you can change the frequency of the sine wave:
translateY = sin(time*5);

you can change the amplitude:
translateY = sin(time) * 2;

and offset the value:
translateY = sin(time) + 6;

or use all in one expression:
translateY = (sin(time * frequencyMultiplier) * amplitude) + offset;

cos( )

The cosine ratio is a value between -1 and 1.

The cos function works like the sin function except its return values are 90 degrees, or pi/2, out of phase.

translateY = cos(time);

The cos function is very handy for making an "opposing" action to an object being controlled by the sin function.
abs( )Returns the absolute value of number. The absolute value of an integer or floating point number is the number without its positive or negative sign. The absolute value of a vector is a vector with components stripped of negative signs.translateY = abs( sin(time) );

the absolute value of the sine wave makes for a good bouncing action.
max( )Returns the larger of two floating point numbers.

float max(float number, float number)

number is a number you want to compare.

translateY = max( 0, sin(time) );

max works like a clamp. The sine wave is not allowed to go below 0.
min( )Returns the lesser of two floating point numbers.

float min( float number, float number)

number is a number you want to compare.

translateY = min( 0, sin(time) );

The sine wave is not allowed to go above 0.
Consider also you can use min and max combined together for some uses that need clipping on both high and low values:
translateY = 
min( 0.5, max( 0, sin(time) ) );

linstep( )Returns a value from 0 to 1 that represents a parameter's proportional distance between a minimum and maximum value. This function lets you increase an attribute such as opacity from 0 to 1 linearly over a time range.

float linstep(float start, float end, float parameter)

start and end specifies the minimum and maximum values.

parameter is the value you want to use to generate the proportional number.

If parameter is less than start, linstep returns 0.

If parameter is greater than end, linstep returns 1.

translateY = linstep( 0, 1, sin(time) );

The result is very similar to "max" above, but keep in mind that the first two values are the upper and lower 'thresholds' that are allowable, and when one or the other is reached, the output is limited between 0 and 1 ONLY.
For example:
translateY = linstep( 0, 0.25, sin(time) );

Wednesday, 3 September 2025

VsCode - auto path completion/autocompletion

The Problem: 

For a while it haunted me that my custom repos/packages weren't auto-completing, not ctrl+mouse hover to see what a function did.

 The Fix:

F1 > Preferences: Open Workspace Settings (JSON)

 

Ensure you have "settings", if not, add it.

Ensure you have "python.analysis.extraPaths" : ["your paths here"], if not, add it. 

    "settings": {
        "git.ignoreLimitWarning": true,
        "python.analysis.extraPaths": [
            "C:\\Users\\a_tav\\3D work and portfolio\\AT_autorig",
            "C:\\Users\\a_tav\\3D work and portfolio\\scripts",
            "C:\\Users\\a_tav\\3D work and portfolio"
        ],
        "python.analysis.autoImportCompletions": true,
        "python.analysis.completeFunctionParens": true,
        "python.analysis.useLibraryCodeForTypes": true,
        "editor.definitionLinkOpensInPeek": true,
        "files.associations": {
            "random": "cpp"
        },

 

Tuesday, 10 June 2025

Selecting a mesh selects the shape, not the transform

 Here's a weird one...

The Problem:

When I select a mesh/curve, it selects the shape - not the transform!

The Fix:

Turn off 'Enable Overrides' of the shape. Normally transforms are part of display layers, and when an object is added to a display layer, it links the display layer 'Display Type' to the objects 'Display Type'. However, adding a transform does not add the shape. Therefore, if you have a Display Layer set to reference, you may still be able to select a layer object's shape if 'Enabled overrides' on the shape is turned on and set to 'Normal'. 

Friday, 24 January 2025

Models grey in viewport

The Problem:

My models are grey in the Maya viewport, even though they have a material with colour assigned!

The Fix:

At the top of the viewport window...:

Shading > Use Default Material (uncheck)

Friday, 20 December 2024

Mothman - incredible portfolio/rigs/guy

Every so often you come across a portfolio website that absolutely blows your mind, and this is one of them:

 https://www.mothman-td.com/

The website is so slick and professional, and the actual work is of extremely high quality, check it out!

Wednesday, 18 December 2024

Morgan Loomis - Anim & Rig Tools

 I came across a pretty cool new zealander who is hosting a lot of his tools on his own personal website. Thought it was worth a link :) 

http://morganloomis.com/tools/

Tuesday, 17 December 2024

Kuadro – Reference Image Tool


So here’s a cool little tool for helping organise reference images on screen – Kuadro. You can open up any image files and arrange them on screen without all of the messy borders/tools that the default image displayers use. Really handy for modelling rigging or animation. You can also save your organised layout for next time you resume working. A great little free software package! 

Monday, 22 April 2024

Python3 comparison operators

Meditate on this 🙏

'foo' is 'foo'
True

'foo' == 'foo'
True

'foo' is 'foo2'[:-1]
False

'foo' == 'foo2'[:-1]
True

'foo' is 'Foo'.lower()
False

'foo' == 'Foo'.lower()
True

0 == 0.0
True

0 is 0.0
False

0 is False
False

0 == False
True

not 0
True

Thanks to Joe Hornsby for providing these excellent examples.

Thursday, 18 April 2024

Free, Opensource Animation Picker - Dreamwall

So, "it ain't 2005 anymore", and quite rightly so. 

Why spend time creating a bespoke tool, if there's something out there already that's free, great, and gets the job done?

Dreamwall Anim Picker is a free and intuitive tool that allows the construction of an animation picker for rigs within Maya. It's really good, and I think it will save you a lot of time, check it out here:

 https://github.com/DreamWall-Animation/dwpicker



Thursday, 28 March 2024

Can't undo in Maya

The Issue:

// Error: line 1: The undo queue is turned off.

:(


The Fix:

In script editor, on a python tab, run:

cmds.undoInfo(state=True)

:)

Thursday, 7 March 2024

Cool Maya Time Slider Preference!

 I discovered a new time slider preference today that blew my mind slightly;

'Snap to whole frames'.



When you turn this off, as you scrub through the time slider you are able to see how your frames interpolate from one, to the other. Particularly useful if you're trying to debug euler/gimbal issues!

Friday, 16 February 2024

Prune weights not working

The Issue:

Hey! My prune weights aren't working! :(

The Fix:

Yeah? Have you tried unlocking your weights? 

Friday, 27 October 2023

Python debug tip

 Want to know a secret?

"*"*100 takes me about 1 second to type.

Why not wrap it in a print?

 

print("*"*100)

print("var_a:", var_a) 

print("var_b:", var_b) 

print("var_c:", var_c)  

Result:

//****************************************************************************************************

// var_a: pineapple

// var_b: 64

// var_c: <__main__.Dog object at 0x00000248A53D7748> # 

//************************************************************************************************

 

Isn't that easier to read?

How to change all paths in Houdini scene file

The Problem:

I need to change all paths in a Houdini scene file due to a drive change - oh no! All my nodes are invalid, my scene is broken and everything is on fire. Or is it? No its not, i'll tell you why:

The Fix:

 1.) Windows > Hscript Textport

 

2.) Type opchange YOUROLDLOCATION YOURNEWLOCATION

(press enter)













And there you go, all nodes referencing YOUROLDLOCATION will have search'n'replaced it with YOURNEWLOCATION. Magic. Everything fixed. :)


Monday, 23 October 2023

How to install numpy for Maya

I needed to install numpy for Maya the other day because its a dependancy of a package that I use.
But how? How do you install numpy for Maya?

Like this:
1.) Press windows, type in cmd and press enter
2.) type in: cd C:\Program Files\Autodesk\Maya20??\bin
3.) type in: mayapy -m pip install numpy

Obviously, replace the ?? in your Maya install directory with your version number.
And there you go - numpy installed! :)

Monday, 3 April 2023

Maya Rigging: Joint-based collision detection using Maya muscle nodes

 I recently found a great tutorial on created live-collision joints using Mayas in-built muscle system nodes. I thought this was a really clever solution as it is importantly real-time, meaning animators can see the output immediately, and it utilises nodes already existing within Maya.


To read up on how to create this awesome looking system, take a look here:

http://www.rihamtoulan.com/blog/2018/3/24/faking-collisions-with-joints-based-setup-8snd2

Thursday, 23 March 2023

Python Generators - using yields and generators

Python generators were something that alluded me for quite a while. A spooky concept that didn't seem necessary. However after using Coroutines in C#, it sort of became a little more clear. 

Then, recently I stumbled across an excellent blog post explaining what generators do, how and when to use them:

https://github.com/qingkaikong/blog-1/blob/f453d320c06ac5b1a8d43380f9e6f9d9cf8c3022/content/2013-04-07-improve-your-python-yield-and-generators-explained.md

Check it out!

Monday, 9 January 2023

FrancoJam Gamejam Winners 2022!

Towards the end of last year I took part in Creative Assembly's GameJam, and it just got announced that our team won! Hooray!

This year's theme was 'Animal Rescue' inspired by Creative Assembly's charity of the year, so we decided to put a spin on the theme and make a game about an animal (Noah the pigeon) rescuing humans onto his ark. We had a total of 48 hours to make the game.

The idea for the gameplay is to launch Noah the pigeon via a catapult click & drag mechanic to connect a tightrope to pins scattered throughout the level, thus creating a path for the humans to walk across and board the Ark.


We created the game in Unity, and used other DCC's such as Maya and Photoshop to help create the assets. I'm really pleased with the way this game turned out, and even more proud of our team that took home the trophy! Good job Team Kinematic!

Credits:

Alex Tavener(me) - Art (pigeon, ark, background)

Ross Harrop - Art (humans, environment)

Chris Kemp - Programming

Chris Kozlowski - Audio

William Fynn - Moral support & ideas consultant


GG!


Monday, 14 November 2022

Houdini: Linking/connecting multiple parameters

 Let's say you have a subnet, with near identical parameters to multiple sub-nodes within. How do we go about linking them all? We could tediously, arduously right click > copy > right click > paste relative references for every attribute we want to copy, or...

1.) Open up 'parameter interface' of the subnet, and go to the 'channels' tab

2.) Under 'Linked Channels', type subNode/subNodeparameterName  Do this with all nodes you want to link. I found that you can quickly iterate through nodes using a simple IDE/text editor. ONCE FINISHED TYPING, PRESS ENTER! THIS IS INCREDIBLY IMPORTANT!

3.) Click 'Apply' - That's it, all your nodes are now linked via the main subnet node.

For multiparms this functions a little differently, insofar that these 'connections' must be made during attribute instantiation on the master node. If you try to edit/append/remove after the instantiation of the multiparm master attribute, it will not make any changes to the sub node attibutes. I can only assume this is a bug.

Also, occasionally these 'Linked Channels' will appear on the 'Parameter' tab instead of 'Channels'. Pesky Houdini.