You might imagine that...

Matrix m1 = ...

Matrix m2 = ...

Matrix m3 = m1 * m2;

...(I should add in C#) would give you a matrix m3 which represents the results of m1's operations FOLLOWED BY m2's. But no; it's the OPPOSITE, m2 followed by m1.

To say this is counter-intuitive is a massive understatement, and of course if it gets changed 3D worlds everywhere will turn inside out or disintegrate, so live with it we must. I say rediscovered because I remember falling down this same hole a couple of years ago.

There's probably a reasoned argument as to why it's done this way. and I seem to recall GDI+'s matrices do the same thing. Equally I also seem to recall that quaternions in C++ do the opposite; q1 * q2 is q1 followed by q2. So my top tip is next time things look wrong after a matrix calculation, flip the multiplication order and maybe all will be well without you having to write "X", "Y" and "Z" on the edges of a CD cover and invest an hour of your day experiencing the feeling that you may be going mad!

]]>If you haven't registered yet and fancy spending a Saturday chez Microsoft with your fellow .NET fans, users, critics, and of course the floating voters, you can register here. The agenda's here; it's a fantastic mix of the technical and the slightly-less-technical and we can promise you a very enjoyable and thought-provoking day, punctuated by lunch and the odd chocky bikky.

That said, the word's got round and we're close to 85% of the capacity of our three big meeting rooms, so if you would like to come along now would be a very good time to reserve your spot. If you fancy speaking at a future event, to share your experiences and insights, this would be a great opportunity too to meet Craig, Phil and Benjamin and help them shape the agenda for the next DeveloperDeveloperDeveloper; be assured they're men of integrity so cheap bribes like "I saved you the last Bourbon" won't influence them in any way :-)

We look forward to seeing you there!

]]>using Microsoft.Premises;

namespace DeveloperDeveloperDEVELOPER

{

class ByDeveloperForDeveloperEvent

{

string date = "Saturday May 14th 2005";

string location = "Microsoft

bool isRelaxedAndInformal = true;

bool isTechnologyFocusDotNet = true;

bool isLunchProvided = true;

bool arePresentersFromMicrosoft = false;

bool isOnASaturday = true;

bool isFree = true;

public void EnjoySessions()

{

for(int iTrack = 0 ; iTrack < 2 ; iTrack++)

{

for(int iSession = 0 ; iSession < 6 ; iSession++)

{

AttendSession(iTrack, iSession);

}

}

}

public void AttendSession(int iTrack, int iSession)

{

//TODO

// if (I want to share my experiences and knowledge of

// .NET with other developers)

// {

// Suggest a title for a presentation I'd like to give

// to

// }

// if (I want to hear about my peers' experiences and learnings)

// {

// Come along,listen, chat, ask questions...

// REGISTER HERE!

// }

}

}

}

]]>

My latest passion is for rabbiting about developing for Office in managed code. If your perception of Office dev is solely confined to the world of VBA macros be prepared to be very surprised - the story changes ever so slightly.. okay... hugely with Visual Studio Tools for Office (VSTO to its pals) and even hugelier (?) for the version that'll arrive very soon with Whidbey. Even the story for managed code with the less-than-current versions of Office is much richer than you might expect.

The Office products are of course COM servers, and there's a plethora of techniques that Andrew's book describes for integrating managed code, crossing the managed/unmanaged boundary safely and easily. By sharp contrast with many developer books, it's extremely well written and has a fantastically even pace - never trivialising and never bewildering. The examples (available online) are plentiful, rich, and well documented, so all in all the best £23 I've spent in a while. No, I'm not on commission, and no, we're not related - I just felt that everyone should know about a very sound dev text book!

The book's called .**NET Development for Microsoft Office** by *Andrew Whitechapel*, published by MS Press, ISBN 0735621322.

Enjoy!

]]>The manifestation is pretty nasty - you do File -> New -> Project and then pick either Excel or Word templates, and then try to build and run. So it's pretty fundamental! It's a case of software rot - it all used to work and suddenly it breaks. VB or C#, Excel or Word. An exception is thrown:

"Type 'System.Security.Cryptography.SHA1CryptoServiceProvider' in Assembly 'mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' is not marked as serializable."

Naturally you read this as being an issue with the privilege level of the associated assembly, but when you try to elevate its permission set via the .NET Framework Wizard, you're told the assembly "can't be opened". ILDASM can read it, so it can be opened! Interestingly, the Wizard now says this to every assembly, VSTO or otherwise.

I had been playing with the security settings beforehand, trying to give an Action Pane user control (what a fabulous feature that is!) privilege to hit a local database, running the Yukon beta, so it's a lot of pre-release code conspiring to wreak havoc and probably very hard to trace as a bug for that reason.

I de- and re-installed Whidbey; no change. De-installing Yukon requires a reboot at every stage and Coronation Street was looming closer so time was against me. I decided that re-installing the .NET Framework 2.0 Beta might do the trick, but Framework 2 Beta doesn't appear in "Add/Remove Programs" nor in Windows Components.

Hence I am indebted to Sam Gentile's blog entry which outlines a very blunt way of de-installing Fx 2.0 and indeed the other beta bits:

"To remove Microsoft .NET Framework 2.0 Beta

msiexec.exe /x {71F8EFBF-09AF-418D-91F1-52707CDFA274}

If that fails, try:

msizap.exe TWA {71F8EFBF-09AF-418D-91F1-52707CDFA274}"

The first option did it for me - I reinstalled from the MSDN distribution and all is now fine. Sam, I owe you a beer.

]]>After an excellent session about AI in games, I went to the exhibition book stall and invested in a copy of Nils Nilsson's "Artificial Intelligence: A New Synthesis", (Morgan Kaufmann, ISBN 1 55860 535 5) which I thoroughly enjoyed reading (back then when we still had sunshine). In conversation at the event, I realised I was some kind of alien – fancy not knowing what an A-Star search is – but now I do know and can spout forth at the slightest provocation, which may explain why my social life has dwindled. If anyone can point me to other digestible books about AI I’d be very grateful to hear, besides which life as a hermit quite suits me.

In games, as they say, vehicles are the new

My first foray into game physics was via David Bourg’s “Physics for Games Developers” (O’Reilly, ISBN 0 596 00006 5) which is a superb introduction to the principles and maths, and is very well written too.

Further research led me to The Book – one of the reviewers said that no games programmer today would use more than 25% of the principles it outlined, so clearly this had to appear on my shelf as well. It’s David Eberly’s “Game Physics” (Morgan Kaufmann, ISBN 1 55860 740 4). My feedback to David would be that it’s a little light on jokes, but it more than makes up for that with its extraordinarily well- and tightly-woven descriptions, equations and code. It’s a superb piece of work, backed up by very portable C++ examples that run over DirectX and OpenGL (putting an abstraction layer over the two of them incidentally – now there’s an idea for a Standards committee to get hold of!) as well as a living web site with yet more descriptive text and code.

Suffice to say, I now feel equipped to write code for a world where some objects aren’t round and travelling solely in one dimension.

I’m a Microsoft employee, and therefore should tread very carefully around anything that could be construed as a recommendation, particularly where software’s concerned, so I must stress that what I’m about to write in no way constitues a recommendation by the Microsoft corporate body, it doesn’t point to any commercial or other relationship with or endorsement of the vendor, it doesn’t suggest that other vendors and Microsoft are or aren’t doing this stuff… you get the idea – this is purely personal, okay? I just liked it. Right, here we go. If you’ve any doubt that physics is going to be very big in gaming (and I suspect all other UI too) you need to take a look at Novodex’s Rocket demo (http://www.novodex.com/). Top tips – you can pick up pretty much anything with the right mouse key (including the rocket) and the space bar fires balls. For all their simplicity, the Jenga games are enormously satisfying!

Coming full circle, and with all the same caveats, if you’re interested in AI, the demo’s and

So. Books. Inevitably, I did weaken and buy some graphics texts too. One was the second in editor Wolfgang Engel’s Shader X series – “Shader X2, Shader Programming Tips and Tricks with DirectX 9” (Wordware, ISBN 1 55622 988 7). Excellent reading and inspirational, it draws together a series of articles that show how to do jolly clever things with the High Level Shader Language, amongst them an article by Microsoft’s own

My final purchase was a book that caught my eye as one of the authors is Joseph Laviola, Jr. of

I digress! The book itself is “3D User Interfaces” by Doug Bowman, Ernst Kruiff, Ivan Poupyrev and Joseph Laviola (Addison Wesley, ISBN 0 201 75867 9). I’ve always been interested in stereo vision and 3D, so it’s great to have a book that outlines the state of the art and weighs up the pro’s and con’s of many different approaches to working with three dimensions. I cling on (sometimes in desperation) to the belief that mainstream computing will eventually wake up to the huge value that sophisticated graphics could add even to traditional applications – every day I see people struggling with two-dimensional spreadsheets, trying to get a grip on multi-dimensional data – when a simple walk-through visualisation could highlight any issues hiding in the data immediately. I’m searching for a pithy phrase along the lines of “A mesh can paint a thousand spreadsheets” – if you’re feeling creative (and/or pithy) do help me out.

So is this all I’ve read since September? Actually no – there’s one more technical book I want to rave about, but that’s on a different theme, so more of that later!

]]>I know I promised not to be so dull in future, but enough people seem to share my curiosity about what goes on inside DirectX matrices for it to be worth publishing the details of DX's other pre-defined matrix form, the XYZ matrix.

So, if I create rotation matrices for a rotation about X by x radians (and call it Rx), about Y by y, and about Z by z, and multiply them together Rx * Ry * Rz, I wind up with the following:

Cos(y).Cos(z) | Cos(y).Sin(z) | -Sin(y) |

Sin(x).Sin(y).Cos(z) + Cos(x).-Sin(z) | Sin(x).Sin(y).Sin(z) + Cos(x).Cos(z) | Sin(x).Cos(y) |

Cos(x).Sin(y).Cos(z) + Sin(x).Sin(z) | Cos(x).Sin(y).Sin(z) + -Sin(x).Cos(z) | Cos(x).Cos(y) |

....and if, as before, I want to look at a matrix and work out what single set of x, y, z rotations would get me to the same orientation, the code below will do the trick.

Like the roll-pitch-yaw case, the numbers go loopy when the rotation about Y is an odd multiple of ninety degrees, so there's a crude test in there to spot that happening and go to a plan B.

(Same disqualifier too - if you're concerned for numerical stability and being able to guarantee getting the same matrix back that you started with, there is a more reliable route which avoids the setting of the angle about z to being zero ["gimbal lock"] and again I'd point you to The Right Way to Calculate Stuff by Don Hatch).

static public void DecomposeXYZRotationMatrix(Matrix mx, out double rx, out double ry, out double rz)

{

ry = Math.Asin(-mx.M13);

double threshold = 0.001;

if(Math.Cos(ry) > threshold)

{

rx = Math.Atan2(mx.M23, mx.M33);

rz = Math.Atan2(mx.M12, mx.M11);

}

else

{

rx = Math.Atan2(mx.M21, mx.M22);

rz = 0.0;

}

}

{

ry = Math.Asin(-mx.M13);

double threshold = 0.001;

if(Math.Cos(ry) > threshold)

{

rx = Math.Atan2(mx.M23, mx.M33);

rz = Math.Atan2(mx.M12, mx.M11);

}

else

{

rx = Math.Atan2(mx.M21, mx.M22);

rz = 0.0;

}

}

My next blog will be about Managed DirectX and the Effects framework, so if you think that's dull too, apologies!!

Cos(y) | 0 | -Sin(y) |

0 | 1 | 0 |

Sin(y) | 0 | Cos(y) |

Cos(z) | Sin(z) | 0 |

-Sin(z) | Cos(z) | 0 |

0 | 0 | 1 |

Cos(z).Cos(y) + Sin(z).Sin(x).Sin(y) | Sin(z).Cos(x) | Cos(z).-Sin(y) + Sin(z).Sin(x).Cos(y) |

-Sin(z).Cos(y) + Cos(z).Sin(x).Sin(y) | Cos(z).Cos(x) | Sin(z).Sin(y) + Cos(z).Sin(x).Cos(y) |

Cos(x).Sin(y) | -Sin(x) | Cos(x).Cos(y) |

Hence the C# code below for Managed DirectX will allow us to look at a rotation matrix and get back to one set of YawPitchRoll angles that would give rise to it. The DirectX Matrix structure exposes elements called M*ij* (e.g. M32, M21 etc.) where the first digit is the row, and the second the column (remember "Rock Cakes" for **r**ow followed by **c**olumn). This being maths there are gotcha's - when the cosine of the pitch angle gets small, (for a pitch of 90-ish degrees, say) numerically things go bananas, so you can take an arbitrary decision about the yaw angle (here I've set it to zero) and deduce a roll. This is okay except where numerical consistency is important (flying jet fighters. guiding satellites and so on) where you can't just swizzle your object in space to make the sums work. If you're looking for the "proper" way to do this, I can recommend a piece I stumbled on called The Right Way to Calculate Stuff by Don Hatch. If you want the code and layout for the XYZ equivalent, holler - I'll be interested to see whether anyone out there got this far before sleep overwhelmed them.

static public void DecomposeRollPitchYawZXYMatrix(Matrix mx, out double xPitch, out double yYaw, out double zRoll)

{

xPitch = Math.Asin(-mx.M32);

double threshold = 0.001; // Hardcoded constant - burn him, he's a witch

double test = Math.Cos(xPitch);

if(test > threshold) {

zRoll = Math.Atan2(mx.M12, mx.M22);

yYaw = Math.Atan2(mx.M31, mx.M33);

}

else {

zRoll = Math.Atan2(-mx.M21, mx.M11);

yYaw = 0.0;

}

}

Thanks for your patience, O blogosphere - will try to be less turgid in future.

]]>