PDA

View Full Version : Computing Shear Value From Degrees For Matrix



robosport
02-19-2006, 11:22 PM
I am shearing the Y value of vertices in a mesh along the Z axis. I am using glMultMatrixf to apply the shearing matrix which works great. (I sure wish there was a glShearf though so I could avoid this on the CPU ) ;)

My question is this: I have an angle in degrees called theta. I want to know how to convert theta to the value of shear in the matrix required so the resulting geometry is sheared to theta degrees.

I tried cos(theta) with the appropriate conversion to/from radians but the geometry angle appears to be off by roughly 10 degrees after the shear.

Any pointers are much appreciated. Thanks!

RigidBody
02-19-2006, 11:31 PM
a matrix for shear along the y-axis looks like

[cos(theta) 0 0]
[sin(theta) 1 0]
[ 0 0 1]

maybe you forgot the sinus?

another thought- maybe you're using something like glOrtho(-1., 1., -1., 1., -1., 1.). if your window's width is not equal to its height, you'll get wrong angles.

robosport
02-20-2006, 08:24 AM
I think you may have hit the nail on the head. I didn't realize I needed the sin.

Do you happen to know where sin goes on a matrix shearing Y along Z axis?

Right now I have the following which is shearing the right way but only off by about 10 degrees:


| 1 0 0 0 |
| |
| 0 1 0 0 |
| |
| 0 cos 1 0 |
| |
| 0 0 0 1 |
| |Thanks!

RigidBody
02-20-2006, 08:56 AM
try this:

[1 0 0 0]
[0 cos 0 0]
[0 sin 1 0]
[0 0 0 1]

robosport
02-20-2006, 09:19 AM
No change from my previous matrix. Still off by the same amount.

I'm curious about your other comment regarding the projection. What does the view projection have to do with this modelview matrix shearing the geometry?

You are correct that my width and height on the view are not equal. I adjust the height based on the width to maintain the proper aspect ratio even when the window shape changes. Just for the record the window shape changing doesn't seem to affect how much it is off by. I'd be appreciative in hearing more about that possible problem and or a fix for when the glOrtho width is different than the height.

Thanks!

RigidBody
02-20-2006, 09:46 AM
in case your window's width W is not equal to its height H, you should use glOrtho(left,right,bottom,top,near,far) with appropriate values, so that (left-right)/(bottom-top) is in relation to W/H. otherwise squares will look like rectangles, circles like ellipsoids, and angles between lines- with exception of 90, of course- will be wrong.

try something like

int W, H; // WINDOW WIDTH/HEIGHT
float ratio = (float)H/(float)W;

glOrtho(-10., 10., -10.*ratio, 10.*ratio, -1., 1.);

robosport
02-20-2006, 12:40 PM
No I must have misunderstood. I already have a proper aspect in my views. I thought there was something else you said about the ortho having to be square which made no sense. We are already on the same page with the view.

Unfortunately I still need to figure out why the shear is slightly and consistently off.

Thanks for your help.

robosport
03-31-2006, 12:08 AM
Okay. I figured it out and thought I'd post the results here in case anyone in the future has a similar question.

The posts by me and RigidBody above have some misinformation.

I found a Shear Matrix description on the Matrix and Quaternions FAQ here:
http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q43

After reading it a couple times I realized, unlike rotation, shearing only requires one distance value - not a sin value and cos value. You place the distance value in the appropriate spot in the matrix to shear one axis along another axis.

I was using cos/sin to rotate a unit point to find the distance I needed to shear. The reason my shear was always a little off is because the resulting distance needs to be normalized and I didn't realize it until tonight. Here is an example.


// caclulate Y shearing distance based on angle theta
// (already converted from degrees to radians for this example)
float x = 1.0;
float y = 0.0;

float rotatedX = ( cos(theta) * x ) - ( sin(theta) * y );
float rotatedY = ( sin(theta) * x ) + ( cos(theta) * y );

// now normalize Y to find where it is at when X crosses over the 1.0 unit mark
// this is the part I was missing before
shearDistanceY = ( 1.0f / rotatedX ) * rotatedY;

shearMatrix.setIdentity();
shearMatrix.SetValue( 2, 1, shearDistanceY );Works great!