Planet Tech Art
Last update: December 10, 2016 07:09 AM
December 09, 2016

Amazing Optimizers, or Compile Time Tests

I wrote some tests to verify sorting/batching behavior in rendering code, and they were producing different results on Windows (MSVC) vs Mac (clang). The tests were creating a “random fake scene” with a random number generator, and at first it sounded like our “get random normalized float” function was returning slightly different results between platforms (which would be super weird, as in how come no one noticed this before?!).

So I started digging into random number generator, and the unit tests it has. This is what amazed me.

Here’s one of the unit tests (we use a custom native test framework that started years ago on an old version of UnitTest++):

TEST (Random01_WithSeed_RestoredStateGenerateSameNumbers)
{
	Rand r(1234);
	Random01(r);
	RandState oldState = r.GetState();
	float prev = Random01(r);
	r.SetState(oldState);
	float curr = Random01(r);
	CHECK_EQUAL (curr, prev);
}

Makes sense, right?

Here’s what MSVC 2010 compiles this down into:

push        rbx  
sub         rsp,50h  
mov         qword ptr [rsp+20h],0FFFFFFFFFFFFFFFEh  
	Rand r(1234);
	Random01(r);
	RandState oldState = r.GetState();
	float prev = Random01(r);
movss       xmm0,dword ptr [__real@3f47ac02 (01436078A8h)]  
movss       dword ptr [prev],xmm0  
	r.SetState(oldState);
	float curr = Random01(r);
mov         eax,0BC5448DBh  
shl         eax,0Bh  
xor         eax,0BC5448DBh  
mov         ecx,0CE6F4D86h  
shr         ecx,0Bh  
xor         ecx,eax  
shr         ecx,8  
xor         eax,ecx  
xor         eax,0CE6F4D86h  
and         eax,7FFFFFh  
pxor        xmm0,xmm0  
cvtsi2ss    xmm0,rax  
mulss       xmm0,dword ptr [__real@34000001 (01434CA89Ch)]  
movss       dword ptr [curr],xmm0  
	CHECK_EQUAL (curr, prev);
call        UnitTest::CurrentTest::Details (01420722A0h)
; ...

There’s some bit operations going on (the RNG is Xorshift 128), looks fine on the first glance.

But wait a minute; this seems like it only has code to generate a random number once, whereas the test is supposed to call Random01 three times?!

Turns out the compiler is smart enough to see through some of the calls, folds down all these computations and goes, “yep, so the 2nd call to Random01 will produce 0.779968381 (0x3f47ac02)“. And then it kinda partially does actual computation of the 3rd Random01 call, and eventually checks that the result is the same.

Oh-kay!

Now, what does clang (whatever version Xcode 8.1 on Mac has) do on this same test?

pushq  %rbp
movq   %rsp, %rbp
pushq  %rbx
subq   $0x58, %rsp
movl   $0x3f47ac02, -0xc(%rbp)   ; imm = 0x3F47AC02 
movl   $0x3f47ac02, -0x10(%rbp)  ; imm = 0x3F47AC02 
callq  0x1002b2950               ; UnitTest::CurrentTest::Results at CurrentTest.cpp:7
; ...

Whoa. There’s no code left at all! Everything just became an “is 0x3F47AC02 == 0x3F47AC02” test. It became a compile-time test.

w(☆o◎)w

By the way, the original problem I was looking into? Turns out RNG is fine (phew!). What got me was code in my own test that I should have known better about; it was roughly like this:

transform.SetPosition(Vector3f(Random01(), Random01(), Random01()));

See what’s wrong?

.

.

.

The function argument evaluation order in C/C++ is unspecified.

(╯°□°)╯︵ ┻━┻

Newer languages like C# or Java have guarantees that arguments are evaluated from left to right. Yay sanity.

by at December 09, 2016 05:38 AM


December 04, 2016

November Tool: Center of Mass

Apologies on being a couple days late on this one.

This months tool is inspired by a workflow laid out by Richard Lico in this video:

Center of mass script from Richard Lico on Vimeo.

His idea is really clever and the workflow is great for hunting down elusive physicality issues that come from having your root not be necessarily where the character’s center of gravity is all the time.

The script is an attempt to automate this set-up in a generic way that should hopefully work with most characters. I’ve tested it on a handful of free rigs, but every rig is different and so it’s very probable that it wont work perfectly for everyone. Ideally the way it works is you select the root control of your puppet, and then run the tool either to create a locator which is constrained to the center of mass, or to transfer animation from the root to a center of mass locator. I wanted it to be as streamlined as possible.

It’s also using a very rough approximation to calculate the relative masses. I think I’ll try some different approaches in the future, but for the time being, it simply looks for visible geometry that is being driven by the root, and then tries to discover a skinCluster in the history of that geometry. It uses the skinCluster weights to get the surface area of the mesh that is being affected by each joint, and then uses those surface area values to weight a point constraint. So for simple characters this seems to work pretty well, but for example if your character has a lot of hair geometry, there will be a lot more relative surface area on the head, and so it will be assumed to be more massive. If you hide geo that you don’t want included in the calculation, that should solve that problem.

It also may have trouble finding the appropriate geometry to use. It will have the best success if your rig scene is referenced, so consider referencing your rig if that is a problem.

Anyway, I consider this to be pretty beta since there’s a lot of different rigs out there, give it a try and let me know if you get any useful sounding errors, or especially if you can share a scene that has issues.

Special thanks to Richard Lico, wherever you are! And to my Patreon supporters!

Center Of Mass
Center Of Mass
ml_centerOfMass.py
Version: 1
17.9 KiB
0 Downloads
Details

Create a locator that approximates the Center of Mass for the character. This locator can be live and simply used as reference, or you can transfer the root animation of your character to the center of mass, and then back again after you've adjusted any motion. This workflow is helpful for debugging action animation when a characters body needs to move in a believable way.

Category:Animation Scripts
Date:5 December, 2016

Also note that this requires the latest ml_utilities script:

Ml Utilities
Ml Utilities
ml_utilities.py
Version: 26
70.7 KiB
4801 Downloads
Details

ml_utilities isn't a stand alone tool, but rather it's a collection of support functions that are required by several of the tools in this library. The individual tools will tell you if this script is required.

Category:Animation Scripts
Date:23 February, 2014

Enjoy!

by Morgan Loomis at December 04, 2016 01:26 PM


December 03, 2016

Guest Post: Working on Cloudy With a Chance of Meatballs 2

We have a great guest post for all of you for 3December 2016 In this second part of my blog series where I go over projects that I’ve worked on, with a focus on how I used Python, I’ll be analyzing Cloudy With A Chance of Meatballs 2. This was my first animated feature film, […]

The post Guest Post: Working on Cloudy With a Chance of Meatballs 2 appeared first on Rigging Dojo.

by Rigging Dojo at December 03, 2016 02:30 PM


November 27, 2016

poseDeformer & fstretch 2017 builds for windows

I was asked to do some poseDeformer and fstretch plugin builds for maya 2017. I've added maya 2017 builds for windows to the zip files on the downloads page. But be warned. I have not started using 2017 yet so I cannot guarantee that these will actually work, so if you download them and try them […]

by david at November 27, 2016 05:54 AM