Archive: new method of doing 3d rotation


27th June 2003 18:03 UTC

new method of doing 3d rotation
As far as I know this hasn't been discovered before. I found a new way to do 3d rotation that runs a little faster than the usual method. I attatched two SSCs, one that uses old method and one that uses new method, and both are the same otherwise i think. n=10000. The new one runs 5 fps faster on my comp than the old one. This should work for DMs as well. This is how it works:


per Frame:

sx=-sin(xa);
cxcz=cos(xa)*cos(za);
cxsz=cos(xa)*sin(za);
cxcy=cos(xa)*cos(ya);
cxsy=cos(xa)*sin(ya);
sysxczmcysz=sin(ya)*sin(xa)*cos(za)-cos(ya)*sin(za);
sysxszpcycz=sin(ya)*sin(xa)*sin(za)+cos(ya)*cos(za);
cysxczpsysz=cos(ya)*sin(xa)*cos(za)+sin(xa)*sin(za);
cysxszmsycz=cos(ya)*sin(xa)*sin(za)-sin(ya)*cos(za);

Per Point:

x1=what you want x coord to be;
y1=what you want y coord to be;
z1=what you want z coord to be;
x3=x1*cxcz+y1*cxsz+z1*sx;
y3=x1*sysxczmcysz+y1*sysxszpcycz+z1*cxsy;
z3=x1*cysxczpsysz+y1*cysxszmsycz+z1*cxcy;

xa is the angle that x is rotated by
ya is the angle that y is rotated by
za is the angle that z is rotated by


I know it's only a small performance boost, but 3d rotation is used in so many presets that I think it's worthwhile. There may be more ways to optimize this method, but I'm too happy about my neat new method to care right now.

27th June 2003 18:12 UTC

afaik that's just a slightly compiled version of the normal rotation matrices w/calculations done in per frame - but i don't like it for two reasons: it's hard to read/understand by eyeballing it, and it's much harder to tweak than regular rotation matrices. good job with it tho, never thought of trying to compile rotation matrices :igor:


27th June 2003 18:21 UTC

yeah, that's exactly what it is.

Look here to see the math.

Why would you ever want to tweak rotation matrices? They do what they're supposed to do already.

And also, most people couldn't "read/understand by eyeballing" the other way either, so there's no real difference.

But I guess that nobody cares about my wonderful new method :( :cry:


27th June 2003 18:34 UTC

Just a slight optimisation

per Frame:

sx=sin(xa); sy=sin(ya); sz=sin(za);
cx=cos(xa); cy=cos(ya); cz=cos(za); sax=-sx;
cxcz=cx*cz; cxsz=cx*sa;
cxcy=cx*cy; cxsy=cx*sy;
sysxczmcysz=sy*sx*cz-cy*sz;
sysxszpcycz=sy*sx*sz+cy*cz;
cysxczpsysz=cy*sx*cz+sx*sz;
cysxszmsycz=cy*sx*sz-sy*cz;

Per Point:

x1=what you want x coord to be;
y1=what you want y coord to be;
z1=what you want z coord to be;
x3=x1*cxcz+y1*cxsz+z1*sax;
y3=x1*sysxczmcysz+y1*sysxszpcycz+z1*cxsy;
z3=x1*cysxczpsysz+y1*cysxszmsycz+z1*cxcy;

xa is the angle that x is rotated by
ya is the angle that y is rotated by
za is the angle that z is rotated by

27th June 2003 18:57 UTC

Yes, I thought of that, but isn't it too many variables for too little improvement? 6 variables used and just 23 sin() or cos() operations less per frame. But waaaiiit a minute...


per Frame:

sx=sin(xa); sy=sin(ya); sz=sin(za);
cx=cos(xa); cy=cos(ya); cz=cos(za);
sysxczmcysz=sy*sx*cz-cy*sz;
sysxszpcycz=sy*sx*sz+cy*cz;
cysxczpsysz=cy*sx*cz+sx*sz;
cxsxszmsycz=cy*sx*sz-sy*cz;
cz=cx*cz;
sz=cx*sz;
cy=cx*cy;
cx=cx*sy;
sx=-sx;

Per Point:

x1=what you want x coord to be;
y1=what you want y coord to be;
z3=what you want z coord to be;
x3=x1*cz+y1*sz+z3*sx;
y3=x1*sysxczmcysz+y1*sysxszpcycz+z3*cx;
z3=x1*cysxczpsysz+y1*cysxszmsycz+z3*cy;

xa is the angle that x is rotated by
ya is the angle that y is rotated by
za is the angle that z is rotated by


Now there's the same number of variables as we began with. We make a great team raz.

edit: one small mistake...

27th June 2003 19:05 UTC

Very interesting technique, especially after Raz's tweaks.


27th June 2003 19:27 UTC

Too bad we don't have the AVS source code. Then we could just replace the sin and cos functions with matrices that, although less accurate, would be much quicker. It wouldn't be difficult either. Just something like this:

float sin[360];
float cos[360];

for(int x=0;x<360;x++)
{
sin[x]=sin(x);
cos[x]=cos(x);
}

and then when you say sin(1) it would actually multiply 1 by pi/180 to convert radians to degrees and then convert to an int an use that number as the matrix index. This would be much much quicker than the actual sin() and cos() are. Especially when there are 23 sin() and cos() calls per frame in an optimized version of that.


27th June 2003 19:44 UTC

lol... take a look at this... I do all that work programming the new method, and now I find that there's another, newer method that is slightly more optimized :p

Here it is:


Frame:
xa=xa+cxa;
ya=ya+cya;
za=za+cza;
cx=cos(xa*.5);
zapya=(za+ya)*.5;
e0=cos(zapya)*cx;
e3=sin(zapya)*cx;
cx=sin(xa*.5);
zapya=(za-ya)*.5;
e1=sin(zapya)*cx;
e2=cos(zapya)*cx;
zoom=e0*e0;
cx=e1*e1;
zapya=e2*e2;
e3sqr=e3*e3;
a11=zoom+cx-zapya-e3sqr;
a22=zoom-cx+zapya-e3sqr;
e3sqr=zoom-cx-zapya+e3sqr;
zoom=2*e1*e2;
cx=2*e0*e3;
zapya=2*e1*e3;
a12=zoom+cx;
a21=zoom-cx;
zoom=2*e0*e2;
a13=zapya-zoom;
zapya=zapya+zoom;
zoom=2*e2*e3;
cx=2*e0*e1;
a23=zoom+cx;
zoom=zoom-cx;

Point:

cx=x coord;
y1=y coord;
z3=z coord;
x3=cx*a11+y1*a12+z3*a13;
y3=cx*a21+y1*a22+z3*a23;
z3=cx*zapya+y1*zoom+z3*e3sqr;


Unfortunately, it actually turned out a tiny bit slower than the method posted earlier, and it's a lot more complicated. But if anyone can find more ways to optimize though then it might end up being better.

anubis: I think it would be better to keep the real sin and cos and then provide sin2 and cos2 that do what you say. Then people could pick and choose weather they want accuracy or speed. But this belongs in wishlist, not in this topic. And there aren't 26 sin and cos calls in the optimized version, there's 26 less than in the original... I didn't know that sin and cos were big hits on the performance.

28th June 2003 00:57 UTC

sin and cos both take a lot of processing power to compute. I'm not sure exactly how much that optimization would work, but I know it does help a good bit as I've seen it done in many open-source video games.