Dark Bit Factory & Gravity

PROGRAMMING => General coding questions => Topic started by: Dr_D on August 25, 2011

Title: Aligning a matrix with a polygon normal(axis-angle)
Post by: Dr_D on August 25, 2011
Hey guys. I'm having a matrix problem here. I'm using FreeBASIC, but as this is a general math problem I put it here. Anyway... here we go. I need to align a 3d object with a polygon normal. To be more precise, I need to align the object's up vector with the polygon normal, while still allowing free rotation about it. In general this isn't a problem... if the current rotation about the up vector isn't important. For what I'm trying to do here here though, it is.

For instance, I can copy the polygon's normal to the up vector. I can then subtract the midpoint from one of the polygon's vertices and normalize to get the right vector . Then I can take the cross product of those two to get the forward vector and complete an orthogonal rotation matrix. All that sounds fine... but not when you're simulating a vehicle. I need to be able to rotate freely about up and keep the angle consistent when a new collision is detected. I tried with an axis-angle approach, but something seems to be off. Has anyone ever dealt with this before? I've been testing different methods for about a week now and it's starting to drive me nuts. :p

Title: Re: Aligning a matrix with a polygon normal(axis-angle)
Post by: Jim on August 25, 2011
If I understand it right, you're saying when you move from one triangle to another your matrix construction technique means the 'right' or 'x' vector in your new matrix depends upon the orientation of the triangle and means your vehicle jumps to a new turn orientation.

I'd solve it like this.  When you hit the new triangle, instead of starting your matrix from scratch, replace the existing matrix's 'up' or 'y' vector with the new triangle normal, then re-square the matrix, along the 'forward' or 'z' axis first (dot, subtract, unitize), and then cross product to get the 'x' vector.

Jim
Title: Re: Aligning a matrix with a polygon normal(axis-angle)
Post by: Dr_D on August 27, 2011
Yep, you understand it right. However, I'm still not able to get it aligned properly with that technique. I've even tried rotating a point about the up vector at whatever angle my vehicle's current steer angle is and still no dice. That's probably where it's failing... How exactly would you go about constructing the new forward vector?
Title: Re: Aligning a matrix with a polygon normal(axis-angle)
Post by: hellfire on August 27, 2011
If your polygon represents the ground (and you don't want loopings) I'd start from a 2d rotation around (0,1,0) and re-orthogonalize with the given normal:
Code: [Select]
Vector y= normal
Vector z= y cross Vector( cos(rot), 0, sin(rot) )
Vector x= y cross z
Title: Re: Aligning a matrix with a polygon normal(axis-angle)
Post by: Dr_D on August 27, 2011
Well. I actually do need to be able to set it from any orientation. Do you know of the old driving game called Stunts? My friend and I are re-making that for Nintendo DS. So... it can be pretty much any arbitrary vector for up.
Title: Re: Aligning a matrix with a polygon normal(axis-angle)
Post by: hellfire on August 27, 2011
I see. Since you already have an axis-angle (http://en.wikipedia.org/wiki/Axis-angle_representation) representation you can build the matrix (http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToMatrix/index.htm) directly from it.
Title: Re: Aligning a matrix with a polygon normal(axis-angle)
Post by: Dr_D on August 28, 2011
That method is what I tried using in the original test. Actually, here's my axis-angle matrix creation function:


Code: [Select]
sub mat33_axisangle( matrix as number ptr, v as vec3 ptr, angle as number )

dim as number tc = cos(angle)
dim as number ts = sin(angle)
dim as number tt = 1.0 - tc

vec3_normalize( v )

with *v
matrix[0]  = tc + .x*.x*tt
matrix[5]  = tc + .y*.y*tt
matrix[10] = tc + .z*.z*tt
dim as number tmp1 = .x*.y*tt
dim as number tmp2 = .z*ts
matrix[4] = tmp1 + tmp2
matrix[1] = tmp1 - tmp2
tmp1 = .x*.z*tt
tmp2 = .y*ts
matrix[8] = tmp1 - tmp2
matrix[2] = tmp1 + tmp2
tmp1 = .y*.z*tt
tmp2 = .x*ts
matrix[9] = tmp1 + tmp2
matrix[6] = tmp1 - tmp2
end with

end sub


It seems to fail at certain angles though... it's hard to explain. I guess it's possible that I'm using a bad method to find the axis and angle? I had this method working a long time ago for a go-kart game, but I've lost that code and apparently the knowledge along with it. :p

Anyway... this is how I calculate the axis and angle:


Code: [Select]
dim as vec3 r, u, axis

u = poly.normal 'polygon normal
r = vIntersection 'intersection point
vec3_normalize( @r )

vec3_cross( @axis, @r, @u )  'return the cross product of the normal and the normalized intersection point
dim as single rot = vec3_dot( @u, @r ) 'calculate the angle between them

mat44_axisangle( @tMatrix(0), @axis, rot )

mat44_loadidentity( @oMatrix(0) )
oMatrix(12)=position.x
oMatrix(13)=position.y
oMatrix(14)=position.z

mat44_mul_mat44( @oMatrix(0), @tMatrix(0) )
mat44_rotate( @oMatrix(0), 0, angle, 0 )

Title: Re: Aligning a matrix with a polygon normal(axis-angle)
Post by: Dr_D on September 23, 2011
Hey guys... I haven't worked on it for a while, but I was wondering if anyone had any other suggestions or spots anything funky in my code?
Title: Re: Aligning a matrix with a polygon normal(axis-angle)
Post by: Jim on September 25, 2011
Isn't part of the problem this bit ?
Code: [Select]
rot = vec3_dot( @u, @r )That will only give you an angle between -90 and +90.

Jim
Title: Re: Aligning a matrix with a polygon normal(axis-angle)
Post by: relsoft on September 30, 2011
New game from Da Doc?!!! Wooohoooo!!!!!!

You have a DS binary I could play with?

Title: Re: Aligning a matrix with a polygon normal(axis-angle)
Post by: rain_storm on September 30, 2011
I think I know what the good doctor is trying to achieve, I've come across similor loss of freedom before. You've solved gimbal lock by forcing all axis to be perpendicular to each other by rotating by an angle then correcting the other axis by applying the crossproduct then normalizing. But now you can no longer rotate one axis freely without it effecting all three? If this is correct then you have not taken maticulous care with exactly which axis you need to correct using the crossproduct.

If you need to rotate only the oriented x axis, it will effect the oriented yz plane. the x axis remains unaffected. so you rotate the y axis conventionally then correct the z axis using crossproduct, finally you normalize z to remove rounding errors. Here is my working code it allows free rotation in yaw, pitch, roll seperately but there is a cost in that you have now lost your euler representation and are working directly in vectors...


Code: [Select]
// the rotation matrix...
float  xx = 1.0f, xy = 0.0f, xz = 0.0f;
float  yx = 0.0f, yy = 1.0f, yz = 0.0f;
float  zx = 0.0f, zy = 0.0f, zz = 1.0f;

// the rotation routine...
bool CameraTransform(float x, float y, float z)
{
    float cx = cos(x), sx = sin(x);
    float cy = cos(y), sy = sin(y);
    float cz = cos(z), sz = sin(z);
    float pn;
   
    // rotate x (affects yz) transform y conventionally, normalize, correct z using crossproduct
    yx = yx*cx + zx*sx;
    yy = yy*cx + zy*sx;
    yz = yz*cx + zz*sx;
    pn = 1.0f / sqrt(yx*yx + yy*yy + yz*yz);
    yx *= pn;
    yy *= pn;
    yz *= pn;
    zx = xy*yz - xz*yy;
    zy = xz*yx - xx*yz;
    zz = xx*yy - xy*yx;
   
    // rotate y (affects zx) transform z conventionally, normalize, correct x using crossproduct
    zx = zx*cy + xx*sy;
    zy = zy*cy + xy*sy;
    zz = zz*cy + xz*sy;
    pn = 1.0f / sqrt(zx*zx + zy*zy + zz*zz);
    zx *= pn;
    zy *= pn;
    zz *= pn;
    xx = yy*zz - yz*zy;
    xy = yz*zx - yx*zz;
    xz = yx*zy - yy*zx;
   
    // rotate z (affects xy) transform x conventionally, normalize, correct y using crossproduct
    xx = xx*cz + yx*sz;
    xy = xy*cz + yy*sz;
    xz = xz*cz + yz*sz;
    pn = 1.0f / sqrt(xx*xx + xy*xy + xz*xz);
    xx *= pn;
    xy *= pn;
    xz *= pn;
    yx = zy*xz - zz*xy;
    yy = zz*xx - zx*xz;
    yz = zx*xy - zy*xx;
   
    // to rotate a vertex using this matrix reduces to the following...
    //newx = xx*posx + yx*posy + zx*posz;
    //newy = xy*posx + yy*posy + zy*posz;
    //newz = xz*posx + yz*posy + zz*posz;
    return true;
}
Title: Re: Aligning a matrix with a polygon normal(axis-angle)
Post by: Dr_D on September 30, 2011
Thanks, rain_storm... I'll test it out when I have a chance. Thanks Jim, and you're right, but that isn't actually the problem. Somehow my matrix was becoming non-orthogonal.

Rel, it's that game I've been working on with Mysoft. I jhaven't actually worked on it for a while though. Been working on that Squealers mini-golf game.  :D