You can subscribe to this list here.
2000 
_{Jan}

_{Feb}

_{Mar}

_{Apr}

_{May}

_{Jun}

_{Jul}
(390) 
_{Aug}
(767) 
_{Sep}
(940) 
_{Oct}
(964) 
_{Nov}
(819) 
_{Dec}
(762) 

2001 
_{Jan}
(680) 
_{Feb}
(1075) 
_{Mar}
(954) 
_{Apr}
(595) 
_{May}
(725) 
_{Jun}
(868) 
_{Jul}
(678) 
_{Aug}
(785) 
_{Sep}
(410) 
_{Oct}
(395) 
_{Nov}
(374) 
_{Dec}
(419) 
2002 
_{Jan}
(699) 
_{Feb}
(501) 
_{Mar}
(311) 
_{Apr}
(334) 
_{May}
(501) 
_{Jun}
(507) 
_{Jul}
(441) 
_{Aug}
(395) 
_{Sep}
(540) 
_{Oct}
(416) 
_{Nov}
(369) 
_{Dec}
(373) 
2003 
_{Jan}
(514) 
_{Feb}
(488) 
_{Mar}
(396) 
_{Apr}
(624) 
_{May}
(590) 
_{Jun}
(562) 
_{Jul}
(546) 
_{Aug}
(463) 
_{Sep}
(389) 
_{Oct}
(399) 
_{Nov}
(333) 
_{Dec}
(449) 
2004 
_{Jan}
(317) 
_{Feb}
(395) 
_{Mar}
(136) 
_{Apr}
(338) 
_{May}
(488) 
_{Jun}
(306) 
_{Jul}
(266) 
_{Aug}
(424) 
_{Sep}
(502) 
_{Oct}
(170) 
_{Nov}
(170) 
_{Dec}
(134) 
2005 
_{Jan}
(249) 
_{Feb}
(109) 
_{Mar}
(119) 
_{Apr}
(282) 
_{May}
(82) 
_{Jun}
(113) 
_{Jul}
(56) 
_{Aug}
(160) 
_{Sep}
(89) 
_{Oct}
(98) 
_{Nov}
(237) 
_{Dec}
(297) 
2006 
_{Jan}
(151) 
_{Feb}
(250) 
_{Mar}
(222) 
_{Apr}
(147) 
_{May}
(266) 
_{Jun}
(313) 
_{Jul}
(367) 
_{Aug}
(135) 
_{Sep}
(108) 
_{Oct}
(110) 
_{Nov}
(220) 
_{Dec}
(47) 
2007 
_{Jan}
(133) 
_{Feb}
(144) 
_{Mar}
(247) 
_{Apr}
(191) 
_{May}
(191) 
_{Jun}
(171) 
_{Jul}
(160) 
_{Aug}
(51) 
_{Sep}
(125) 
_{Oct}
(115) 
_{Nov}
(78) 
_{Dec}
(67) 
2008 
_{Jan}
(165) 
_{Feb}
(37) 
_{Mar}
(130) 
_{Apr}
(111) 
_{May}
(91) 
_{Jun}
(142) 
_{Jul}
(54) 
_{Aug}
(104) 
_{Sep}
(89) 
_{Oct}
(87) 
_{Nov}
(44) 
_{Dec}
(54) 
2009 
_{Jan}
(283) 
_{Feb}
(113) 
_{Mar}
(154) 
_{Apr}
(395) 
_{May}
(62) 
_{Jun}
(48) 
_{Jul}
(52) 
_{Aug}
(54) 
_{Sep}
(131) 
_{Oct}
(29) 
_{Nov}
(32) 
_{Dec}
(37) 
2010 
_{Jan}
(34) 
_{Feb}
(36) 
_{Mar}
(40) 
_{Apr}
(23) 
_{May}
(38) 
_{Jun}
(34) 
_{Jul}
(36) 
_{Aug}
(27) 
_{Sep}
(9) 
_{Oct}
(18) 
_{Nov}
(25) 
_{Dec}

2011 
_{Jan}
(1) 
_{Feb}
(14) 
_{Mar}
(1) 
_{Apr}
(5) 
_{May}
(1) 
_{Jun}

_{Jul}

_{Aug}
(37) 
_{Sep}
(6) 
_{Oct}
(2) 
_{Nov}

_{Dec}

2012 
_{Jan}

_{Feb}
(7) 
_{Mar}

_{Apr}
(4) 
_{May}

_{Jun}
(3) 
_{Jul}

_{Aug}

_{Sep}
(1) 
_{Oct}

_{Nov}

_{Dec}
(10) 
2013 
_{Jan}

_{Feb}
(1) 
_{Mar}
(7) 
_{Apr}
(2) 
_{May}

_{Jun}

_{Jul}
(9) 
_{Aug}

_{Sep}

_{Oct}

_{Nov}

_{Dec}

2014 
_{Jan}
(14) 
_{Feb}

_{Mar}
(2) 
_{Apr}

_{May}
(10) 
_{Jun}

_{Jul}

_{Aug}

_{Sep}

_{Oct}

_{Nov}
(3) 
_{Dec}

2015 
_{Jan}

_{Feb}

_{Mar}

_{Apr}

_{May}

_{Jun}

_{Jul}

_{Aug}

_{Sep}

_{Oct}
(12) 
_{Nov}

_{Dec}
(1) 
2016 
_{Jan}

_{Feb}
(1) 
_{Mar}
(1) 
_{Apr}
(1) 
_{May}

_{Jun}
(1) 
_{Jul}

_{Aug}
(1) 
_{Sep}

_{Oct}

_{Nov}

_{Dec}

S  M  T  W  T  F  S 





1
(7) 
2

3

4
(10) 
5
(12) 
6
(15) 
7
(2) 
8
(8) 
9
(7) 
10
(1) 
11
(6) 
12
(7) 
13
(13) 
14
(35) 
15
(17) 
16
(15) 
17
(12) 
18
(4) 
19
(13) 
20

21

22

23
(15) 
24
(6) 
25
(4) 
26
(19) 
27
(33) 
28
(16) 
29
(31) 
30
(30) 

From: Jonathan Blow <jon@nu...>  20040419 20:46:49

I do a similarinspirit decomposition in that IK/Joint Limits article, and the source code is on gdmag.com/code.htm, so if you want an alternative take on it, it's there. (The difference is, I do reach [or what is here called "alignment"] first, then twist second, since I think that is a lot easier to think about, whereas this one seems to twist then reach.) Mine would definitely give you different results for opposite vectors, so if this one doesn't for some reason, that's another difference.  Original Message  From: "John Miles" <jmiles@...> To: <gdalgorithmslist@...> Sent: Monday, April 19, 2004 4:39 PM Subject: RE: [Algorithms] Zeroing a quaternion rotation axis > Thanks! I just happened to have a use for your DecomposeTwist() routine. > > Although: do you find that this routine gives the same results for (e.g.) > rvAxis = 1,0,0 as it does for 1,0,0? I expected that passing a negative > axis would yield an inverse rotation, but when I ported your code to my math > library, the results are the same. I have to conjugate the result > explicitly if I want an inverse rotation. Not a problem in this case, but > I'm wondering if something got lost in translation. > >  jm > > > Attached are some short routines that we use extensively that may help > > you out in what you want to do. Basically it allows you to decompose a > > quaternion into two quaternions, one that rotates about an arbitrary > > axis, and the other that that makes up the remainder of the original > > rotation. To "block" rotation about a specific axis, simply discard the > > first "twist" quaternion derived by the routine. > > > > Hope that helps. > > > > Lars Wilke > > Credo Interactive Inc. > > > > > >  > This SF.Net email is sponsored by: IBM Linux Tutorials > Free Linux tutorial presented by Daniel Robbins, President and CEO of > GenToo technologies. Learn everything from fundamentals to system > administration.http://ads.osdn.com/?ad_id=1470&alloc_id=3638&op=click > _______________________________________________ > GDAlgorithmslist mailing list > GDAlgorithmslist@... > https://lists.sourceforge.net/lists/listinfo/gdalgorithmslist > Archives: > http://sourceforge.net/mailarchive/forum.php?forum_id=6188 
From: John Miles <jmiles@po...>  20040419 20:39:42

Thanks! I just happened to have a use for your DecomposeTwist() routine. Although: do you find that this routine gives the same results for (e.g.) rvAxis = 1,0,0 as it does for 1,0,0? I expected that passing a negative axis would yield an inverse rotation, but when I ported your code to my math library, the results are the same. I have to conjugate the result explicitly if I want an inverse rotation. Not a problem in this case, but I'm wondering if something got lost in translation.  jm > Attached are some short routines that we use extensively that may help > you out in what you want to do. Basically it allows you to decompose a > quaternion into two quaternions, one that rotates about an arbitrary > axis, and the other that that makes up the remainder of the original > rotation. To "block" rotation about a specific axis, simply discard the > first "twist" quaternion derived by the routine. > > Hope that helps. > > Lars Wilke > Credo Interactive Inc. > 
From: Tyson Jensen <twjensen@sa...>  20040419 20:02:38

To summarize the post below, realize that one of the most important rotation results is that any series of rotations no matter how long and arbitrary can be represented by a single rotation of some angle about some axis. I tend to try to think about what that angle / axis combination is going to be. It's also helpful to draw a coordinate system, rotate it, draw it, rotate it, draw it, etc. The idea here is to get an intuitive understanding of what happens. What happens to the forward vector? What happens to the up vector? What happens to the left (or right) vector? Usually, if I want to eliminate "roll" what I REALLY want to do is leave the up vector alone. I find it is a lot easier to write code to leave the up vector alone than it is to eliminate some arbitrary Euler concept. Similarly, the problem that came up here is simpler to solve as trying to figure out what happens to the forward vector with respect to a particular plane. Original Message From: gdalgorithmslistadmin@... [mailto:gdalgorithmslistadmin@...] On Behalf Of Jonathan Blow Sent: Monday, April 19, 2004 9:59 AM To: gdalgorithmslist@... Subject: Re: [Algorithms] Zeroing a quaternion rotation axis Matt wrote: > In which case you can encode the yaw and pitch directly as euler angles; > there is a definite order of operations here. Actually this is one thing I want to hammer that, now that you say this, I don't think I made clear enough in my earlier replies. Back when I was newer at 3D programming, and not so good at dealing with rotations (and transforms in general), I used to always think about rotation problems as having this order of operations. Let's go so much in this direction, *and then* so much in that direction, and we get our answer. Well, this becomes very difficult to think about for that basic reason that rotations don't commute, that your unit vectors like to move curvily around the sphere. I always found myself bogged down first of all in confusions about trying to visualize what the order of operations really should be, and then=20 second of all in actually trying to visualize that order being carried out, to verify that it was really doing what I wanted. And when it didn't work  which was very often  it was easier to just try juggling around the orders of things in the code until it worked (much like juggling minus signs around in some equation til it works), rather than sit down and really understand what was going on. Because it was so hard to visualize. Of course this led to really sloppy code that happened to work at the moment, but I knew if I tried to play with it much it would break. These days I feel I am a lot better at dealing with rotations, and there's a large class of problems I can just solve without really thinking about them, that as recently as a few years ago would have been very troublesome. One of the main differences between then and now is that now I usually don't visualize rotations in terms of some operations that must happen in a specific order (*usually*, and I'll talk about the exception in a minute). I just think about What The Answer Is, phrased in a way that is entirely nontemporal, and then come up with some steps to compute it that are also nontemporal.=20 So note that in my previous email when I expressed the solution to the problem, I didn't say "rotate around this axis by so much, then around this other axis by so much". Instead I said, "there exists this vector at these angles, and this other vector at this other angle". Because it is nontemporal, the "there exists X" form of answer does not rely on visualizing the results of subsequent rotations, which means the noncommutativity=20 problem, and the difficultyofvisualization problem, just don't come into play. You just know the answer. That suits me for most problems. I said there was one way in which I think about rotation sometimes as happening in ordered stages, and that is when I use the reach/twist formulation. This happens in two explicit steps  first you reach, then you twist. But it's still easy to visualize because the two steps do not have any dependencies between each other. In fact the first step isn't even really a rotation  you only care about the forward vector. You say, "point the forward vector in the direction of the target, but I don't really care what happens to the other two axes". This is the "reach" part. After that is done, you perform the=20 "twist" part, which says: "spin the other two axes around the forward vector until they end up in the right directions". This second phase does not change the forwardvector, so there is no real dependency between it and the first phase. Because there are no dependencies, that whole rotationsactfunnysotheyarehardtovisualize thing just doesn't come into play. =20 Leveraging just these two methods ("There exists X" and "reach/twist"), I easily solve any basic rotation problem that I encounter in making games. The only things that remain are the nonbasic problems where for some reason you really have two arbitrary rotations that get concatenated and you really want to visualize the result. Which happens very rarely. At that point you just want to switch to algebra, multiply the quaternions together and see how it comes out and what that means to you. Jonathan.  This SF.Net email is sponsored by: IBM Linux Tutorials Free Linux tutorial presented by Daniel Robbins, President and CEO of GenToo technologies. Learn everything from fundamentals to system administration.http://ads.osdn.com/?ad_id=3D1470&alloc_id=3D3638&op=3Dcli= ck _______________________________________________ GDAlgorithmslist mailing list GDAlgorithmslist@... https://lists.sourceforge.net/lists/listinfo/gdalgorithmslist Archives: http://sourceforge.net/mailarchive/forum.php?forum_id=3D6188 
From: Lars Wilke <lars@ch...>  20040419 17:48:39

Attached are some short routines that we use extensively that may help you out in what you want to do. Basically it allows you to decompose a quaternion into two quaternions, one that rotates about an arbitrary axis, and the other that that makes up the remainder of the original rotation. To "block" rotation about a specific axis, simply discard the first "twist" quaternion derived by the routine. Hope that helps. Lars Wilke Credo Interactive Inc. //  // DecomposeTwist static void DecomposeTwist( Mgc::Quaternion* pqTwist, Mgc::Quaternion* pqNoTwist, const Mgc::Quaternion& rqRotate, const Mgc::Vector3& rvAxis ) { /* From Chris Welman * * Purpose: * This routine decomposes quaternion q into two parts. One * part is the component of q which twists about the unit * vector 'axis', the other part is whatever is left over * after removing this twist from q. * * To find the twist component of q: * * o apply q to the axis to get a new rotated axis * o use this vRotatedAxis to derive an aligning quaternion * which takes axis into this new rotated axis ( with no twist ). * o the twist component of q is just the quaternion * difference between the aligning quaternion and q. */ Mgc::Vector3 vRotatedAxis = rqRotate * rvAxis; *pqNoTwist = Align( rvAxis, vRotatedAxis ); *pqTwist = pqNoTwist>Inverse() * rqRotate; } //  // Align static Mgc::Quaternion Align( const Mgc::Vector3& v1, const Mgc::Vector3& v2 ) { /* From Chris Welman * * Purpose: * This routine will calculate the quaternion which, when applied * to the normalized vector v1, will yield the vector v2. * Note that this operation is inherently illdefined since twist * is not considered at all, but this routine is still useful * * * Take the normalized bisector of the two vectors. * The angle of rotation is the dot product of this * with the original vector v1. * The axis of rotation is the cross product of * the bisector and v1 * * Why the bisector, you ask? Remember that the * quaternion that rotates by N degrees is a * function of N/2. Using the bisector avoids * having to do an inverse trig function, dividing * by 2, and calling another trig function! * * Note: v1 & v2 must be normalized for this to work. */ Mgc::Vector3 vBisector = v1 + v2; vBisector.Unitize(); // normalize float ww = vBisector.Dot( v1 ); Mgc::Vector3 vv; /* * Watch for the special case where v1 and v2 * are opposite vectors. In this case a * rotation of 180 in any direction will * perform the desired alignment. */ if ( ww != 0 ) { vv = v1.Cross( vBisector ); } else { /* * Pick any direction other than v1 or v2. * We can do this by exchanging the elements * of v2. */ Mgc::Vector3 vAnydir( v2.z, v2.x, v2.y ); vv = v1.UnitCross( vAnydir ); } return Mgc::Quaternion( ww, vv.x, vv.y, vv.z ); } > Original Message > From: gdalgorithmslistadmin@... > [mailto:gdalgorithmslistadmin@...] On > Behalf Of Chris Haarmeijer > Sent: Saturday, April 17, 2004 9:10 AM > To: gdalgorithms > Subject: [Algorithms] Zeroing a quaternion rotation axis > > > Hi, > > I have a quaternion representing a rotation. I now want to be > able to block > the rotation around a specific axis (x, y or z). Is this > possible, and if > so, how? > > Chris >  > Keep IT Simple Software > Van Alphenstraat 12 > 7514 DD Enschede > > W: http://www.keepitsimple.nl > E: mailto:info@... > T: +31 53 4356687 > > > 
From: Jonathan Blow <jon@nu...>  20040419 16:59:22

Matt wrote: > In which case you can encode the yaw and pitch directly as euler angles; > there is a definite order of operations here. Actually this is one thing I want to hammer that, now that you say this, I don't think I made clear enough in my earlier replies. Back when I was newer at 3D programming, and not so good at dealing with rotations (and transforms in general), I used to always think about rotation problems as having this order of operations. Let's go so much in this direction, *and then* so much in that direction, and we get our answer. Well, this becomes very difficult to think about for that basic reason that rotations don't commute, that your unit vectors like to move curvily around the sphere. I always found myself bogged down first of all in confusions about trying to visualize what the order of operations really should be, and then second of all in actually trying to visualize that order being carried out, to verify that it was really doing what I wanted. And when it didn't work  which was very often  it was easier to just try juggling around the orders of things in the code until it worked (much like juggling minus signs around in some equation til it works), rather than sit down and really understand what was going on. Because it was so hard to visualize. Of course this led to really sloppy code that happened to work at the moment, but I knew if I tried to play with it much it would break. These days I feel I am a lot better at dealing with rotations, and there's a large class of problems I can just solve without really thinking about them, that as recently as a few years ago would have been very troublesome. One of the main differences between then and now is that now I usually don't visualize rotations in terms of some operations that must happen in a specific order (*usually*, and I'll talk about the exception in a minute). I just think about What The Answer Is, phrased in a way that is entirely nontemporal, and then come up with some steps to compute it that are also nontemporal. So note that in my previous email when I expressed the solution to the problem, I didn't say "rotate around this axis by so much, then around this other axis by so much". Instead I said, "there exists this vector at these angles, and this other vector at this other angle". Because it is nontemporal, the "there exists X" form of answer does not rely on visualizing the results of subsequent rotations, which means the noncommutativity problem, and the difficultyofvisualization problem, just don't come into play. You just know the answer. That suits me for most problems. I said there was one way in which I think about rotation sometimes as happening in ordered stages, and that is when I use the reach/twist formulation. This happens in two explicit steps  first you reach, then you twist. But it's still easy to visualize because the two steps do not have any dependencies between each other. In fact the first step isn't even really a rotation  you only care about the forward vector. You say, "point the forward vector in the direction of the target, but I don't really care what happens to the other two axes". This is the "reach" part. After that is done, you perform the "twist" part, which says: "spin the other two axes around the forward vector until they end up in the right directions". This second phase does not change the forwardvector, so there is no real dependency between it and the first phase. Because there are no dependencies, that whole rotationsactfunnysotheyarehardtovisualize thing just doesn't come into play. Leveraging just these two methods ("There exists X" and "reach/twist"), I easily solve any basic rotation problem that I encounter in making games. The only things that remain are the nonbasic problems where for some reason you really have two arbitrary rotations that get concatenated and you really want to visualize the result. Which happens very rarely. At that point you just want to switch to algebra, multiply the quaternions together and see how it comes out and what that means to you. Jonathan. 
From: Jonathan Blow <jon@nu...>  20040419 16:38:24

> Another perfectly valid reason might be for a camera that can change heading > and pitch but we don't want it to roll. Such a camera is not uncommon  the viewpoint in a firstperson shooter is often like this. (Though actually, if you start to put in stuff like leaning, you tend to have some roll, but the basic simplest thing that you would first program probably wouldn't have roll). Now, Euler angles are okay for 2DOF problems like this, as they only become truly messed up when you go to 3DOF. But they really don't give you any advantages either, so there's no reason to actually use them. It's better to just throw them out in order to simplify your conceptual framework. If you want to make such a camera, I would recommend conceptualizing it as "there's a forwardvector that has this angle theta when projected onto XY, and this angle phi of elevation up from that plane. And the leftvector is theta plus 90 degrees in the XY plane". The End, and it is all clear. The Euler angle formulation just introduces extra complications, and hides things from you. One can argue that when writing this math out, you get the same thing that you get when using Euler angles. Which is sort of true (if you manage to use the Eulers correctly!), except that in shedding the complications and in being very explicit and clear about what you want, it becomes a lot easier to write bugfree code that you understand and that is really going to work. I'm not trying to say that using a generalized Euler angle approach for this stuff is not "valid"; I'm just saying it's not good. Lots of notgood things are still valid, in that they function. To get back to Megan's suggestion, I wouldn't recommend using them to do joint limits in a physics engine for a few reasons. First of all, Eulerangle clamping isn't very expressive (there are lots of limit shapes that you just can't specify), but also, there are some pretty big performance penalties. (You have to convert to Euler and back every time you want to do a fricking joint limit check). Jeff Lander brought up this problem a few years ago, and it bothered me so much that I spent some time working on it and did a Game Developer article about how to do more generalized joint limits in a way that is much, much faster. (It's "Inverse Kinematics with Quaternion Joint Limits" though of course the joint limit part can apply to forward kinematics as well. The page is linked off of http://numbernone.com/product/). Jonathan.  Original Message  From: "George Warner" <geowar@...> To: <gdalgorithmslist@...> Cc: "Jonathan Blow" <jon@...> Sent: Monday, April 19, 2004 11:51 AM Subject: Re: [Algorithms] Zeroing a quaternion rotation axis > On Sat, 17 Apr 2004 12:47:15 0400, "Jonathan Blow" <jon@...> > wrote: > > >> This isn't a particularly useful answer  he may well have a perfectly valid > >> reason for doing what he's doing. Maybe he's attempting to limit the > >> degrees of freedom of a ball joint in a physics engine? > > Another perfectly valid reason might be for a camera that can change heading > and pitch but we don't want it to roll. > >  > Enjoy, > George Warner, > Schizophrenic Optimization Scientists > Apple Developer Technical Support (DTS) > > > >  > This SF.Net email is sponsored by: IBM Linux Tutorials > Free Linux tutorial presented by Daniel Robbins, President and CEO of > GenToo technologies. Learn everything from fundamentals to system > administration.http://ads.osdn.com/?ad_id=1470&alloc_id=3638&op=click > _______________________________________________ > GDAlgorithmslist mailing list > GDAlgorithmslist@... > https://lists.sourceforge.net/lists/listinfo/gdalgorithmslist > Archives: > http://sourceforge.net/mailarchive/forum.php?forum_id=6188 
From: Mat Noguchi \(BUNGIE\) <matthewn@mi...>  20040419 16:28:14

In which case you can encode the yaw and pitch directly as euler angles; there is a definite order of operations here. MSN Original Message From: gdalgorithmslistadmin@... [mailto:gdalgorithmslistadmin@...] On Behalf Of George Warner Sent: Monday, April 19, 2004 8:52 AM To: gdalgorithmslist@... Cc: Jonathan Blow Subject: Re: [Algorithms] Zeroing a quaternion rotation axis On Sat, 17 Apr 2004 12:47:15 0400, "Jonathan Blow" <jon@...> wrote: >> This isn't a particularly useful answer  he may well have a perfectly valid >> reason for doing what he's doing. Maybe he's attempting to limit the >> degrees of freedom of a ball joint in a physics engine? Another perfectly valid reason might be for a camera that can change heading and pitch but we don't want it to roll. =20 Enjoy, George Warner, Schizophrenic Optimization Scientists Apple Developer Technical Support (DTS)  This SF.Net email is sponsored by: IBM Linux Tutorials Free Linux tutorial presented by Daniel Robbins, President and CEO of GenToo technologies. Learn everything from fundamentals to system administration.http://ads.osdn.com/?ad_id=3D1470&alloc_id=3D3638&op=3Dcli= ck _______________________________________________ GDAlgorithmslist mailing list GDAlgorithmslist@... https://lists.sourceforge.net/lists/listinfo/gdalgorithmslist Archives: http://sourceforge.net/mailarchive/forum.php?forum_id=3D6188 
From: George Warner <geowar@ap...>  20040419 15:51:46

On Sat, 17 Apr 2004 12:47:15 0400, "Jonathan Blow" <jon@...> wrote: >> This isn't a particularly useful answer  he may well have a perfectly valid >> reason for doing what he's doing. Maybe he's attempting to limit the >> degrees of freedom of a ball joint in a physics engine? Another perfectly valid reason might be for a camera that can change heading and pitch but we don't want it to roll.  Enjoy, George Warner, Schizophrenic Optimization Scientists Apple Developer Technical Support (DTS) 
From: <Paul_Firth@sc...>  20040419 12:14:01

On 19/04/2004 12:19:28 gdalgorithmslistadmin wrote: > One thing though, about normal maps... I never tried to create some more > compressionfriendly normal maps...someone should try this. ;) > Normal maps at the moment represent the whole surface area...even if it's > not actually necessary as you already have part of your basic normal > informations on your lowpoly model. Yeah, this is why tangentspace maps palettise so well, since you only encode a hemisphere of normals rather than an entire sphere. And even then you are only encoding the changes from the vertex normal... Cheers, Paul. ********************************************************************** This email and any files transmitted with it are confidential and intended solely for the use of the individual or entity to whom they are addressed. If you have received this email in error please notify postmaster@... This footnote also confirms that this email message has been checked for all known viruses. ********************************************************************** SCEE 2004 
From: Emanuele Salvucci <info@fo...>  20040419 11:19:33

 Original Message  From: <Paul_Firth@...> To: <gdalgorithmslist@...> Sent: Monday, April 19, 2004 12:48 PM Subject: Re: [Algorithms] low order SH vs Half Life 2 "Radiosity Normal Mapping" > On 19/04/2004 10:59:55 gdalgorithmslistadmin wrote: > > > Really this technique is just an extension of directional lighting, a kind > of half > way house between SH PRT and N.L directional. > > I guess for a point source where intensity has fallen off you do run into > problems > as you mention. I imagine you have the same problems with SH PRT too > (possibly the same solutions, though I haven't thought about it too much). Well, I'm not into SH or PRT...but Rad.N.Mapping is well suited to supply this "missing" representation of GI using normal maps. > > Another question... are your three normal maps lightdependant when > > generated? (i.e. exactly like lightmaps they have to be unique, not > > tileable..etc.) > > They aren't light dependant, they simply represent a light transport > function > over the surface, so you could tile them if you wanted (but I'm not sure > you'd > ever want to since they're pretty tied to the surrounding geometry). Uhmm...actually reusing or tiling normal maps is the greatest advantage of using them, together with highpoly representation. You may tile mapped geometry or tile n.maps as in Doom3. One thing though, about normal maps... I never tried to create some more compressionfriendly normal maps...someone should try this. ;) Normal maps at the moment represent the whole surface area...even if it's not actually necessary as you already have part of your basic normal informations on your lowpoly model. Assuming DXT compression treats "black" pixels "better" compressionwise...normal maps could include only those "differences" with the interpolated lowpoly surface normal...leaving just the details to compress. You can then rebuild the whole normal information within the pixel shader.(and converting the "add/subtract" needed operation with a multiply operation) ...just a thought...hoping it makes sense!;) Best, Emanuele. 
From: <Paul_Firth@sc...>  20040419 10:48:11

On 19/04/2004 10:59:55 gdalgorithmslistadmin wrote: > Original Message  > From: <Paul_Firth@...> > To: <gdalgorithmslist@...> > Sent: Monday, April 19, 2004 11:35 AM > Subject: RE: [Algorithms] low order SH vs Half Life 2 "Radiosity Normal > Mapping" > > > > On 16/04/2004 20:21:56 gdalgorithmslistadmin wrote: > > At runtime, I simply dot the light vector against each colour channel > > vector which transforms > > the incoming light into outgoing light ala my transport function (the > > normal maps). > > > > So: > > > > R = Nr.L > > G = Ng.L > > B = Nb.L > > > > Where Nr,Ng,Nb are three normal maps and L is my light vector in object > > space/tangent space/ > > whatever. > > > > And this works with direct lighting...as your L vector is any lightsource... > but how do you represent GI, since there's no actual L vector defined for > Global Illumination? > > Say for instance there's no active light in the current volume/sector of the > world...because of direct lights intensity falloff...yet you should still > have GI lighting, which doesn't seem possible with your method(?!) > (...Gary's technique instead can represent it anyway, anywhere) Really this technique is just an extension of directional lighting, a kind of half way house between SH PRT and N.L directional. I guess for a point source where intensity has fallen off you do run into problems as you mention. I imagine you have the same problems with SH PRT too (possibly the same solutions, though I haven't thought about it too much). > Another question... are your three normal maps lightdependant when > generated? (i.e. exactly like lightmaps they have to be unique, not > tileable..etc.) They aren't light dependant, they simply represent a light transport function over the surface, so you could tile them if you wanted (but I'm not sure you'd ever want to since they're pretty tied to the surrounding geometry). Cheers, Paul. ********************************************************************** This email and any files transmitted with it are confidential and intended solely for the use of the individual or entity to whom they are addressed. If you have received this email in error please notify postmaster@... This footnote also confirms that this email message has been checked for all known viruses. ********************************************************************** SCEE 2004 
From: Emanuele Salvucci <info@fo...>  20040419 10:00:00

 Original Message  From: <Paul_Firth@...> To: <gdalgorithmslist@...> Sent: Monday, April 19, 2004 11:35 AM Subject: RE: [Algorithms] low order SH vs Half Life 2 "Radiosity Normal Mapping" > On 16/04/2004 20:21:56 gdalgorithmslistadmin wrote: > At runtime, I simply dot the light vector against each colour channel > vector which transforms > the incoming light into outgoing light ala my transport function (the > normal maps). > > So: > > R = Nr.L > G = Ng.L > B = Nb.L > > Where Nr,Ng,Nb are three normal maps and L is my light vector in object > space/tangent space/ > whatever. > And this works with direct lighting...as your L vector is any lightsource... but how do you represent GI, since there's no actual L vector defined for Global Illumination? Say for instance there's no active light in the current volume/sector of the world...because of direct lights intensity falloff...yet you should still have GI lighting, which doesn't seem possible with your method(?!) (...Gary's technique instead can represent it anyway, anywhere) Another question... are your three normal maps lightdependant when generated? (i.e. exactly like lightmaps they have to be unique, not tileable..etc.) Best, Emanuele. 
From: <Paul_Firth@sc...>  20040419 09:36:40

On 16/04/2004 20:21:56 gdalgorithmslistadmin wrote: >Each lightmap has a color value that represents incoming lighting data > for three different directions. There is a single tangent space normal > map. We don't actually compress our lightmaps since we update them > dynamically in some cases (switcahble lights/flickering lights. .these > work really well with this technique). We have 910MB of uncompressed > lightmap data in a typical level. > > Here are the slides: > http://www.ati.com/developer/gdc/D3DTutorial10_HalfLife2_Shading.pdf > > One correction to the slides is that: > > float3 diffuseLighting = > saturate( dot( normal, bumpBasis[0] ) ) * lightmapColor1 + > saturate( dot( normal, bumpBasis[1] ) ) * lightmapColor2 + > saturate( dot( normal, bumpBasis[2] ) ) * lightmapColor3; > > should be: > > float d[3]; > d[0] = saturate( dot( normal, bumpBasis[0] ) ); > d[1] = saturate( dot( normal, bumpBasis[1] ) ); > d[2] = saturate( dot( normal, bumpBasis[2] ) ); > > float3 diffuseLighting = > ( d[0] * d[0] ) * lightmapColor1 + > ( d[1] * d[1] ) * lightmapColor2 + > ( d[2] * d[2] ) * lightmapColor3; > > A really good thing about this technique is that this equation is > expressible in a ps_1_1 shader. Certainly looks cool! > > Can you explain your technique more? Sure, I have three normal maps which (together) represent the total potential irradiance per texel. In the simplest case these maps are in world space, but for skinning etc they can be in tangent space. At runtime, I simply dot the light vector against each colour channel vector which transforms the incoming light into outgoing light ala my transport function (the normal maps). So: R = Nr.L G = Ng.L B = Nb.L Where Nr,Ng,Nb are three normal maps and L is my light vector in object space/tangent space/ whatever. Its worth noting that the normal maps can also represent microfacet normals (like for approximating a high poly model as a low poly + normal map), since the preprocessor only cares about having an initial normal for a texel which can be from any source. Mmmm, all of this talk makes me think I should actually implement this... :) Cheers, Paul. ********************************************************************** This email and any files transmitted with it are confidential and intended solely for the use of the individual or entity to whom they are addressed. If you have received this email in error please notify postmaster@... This footnote also confirms that this email message has been checked for all known viruses. ********************************************************************** SCEE 2004 