Author Topic: Aligning a matrix with a polygon normal(axis-angle)  (Read 3930 times)

0 Members and 1 Guest are viewing this topic.

Offline Dr_D

  • Atari ST
  • ***
  • Posts: 151
  • Karma: 29
    • View Profile
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

The Dr. is INsane!!!

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: Aligning a matrix with a polygon normal(axis-angle)
« Reply #1 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
Challenge Trophies Won:

Offline Dr_D

  • Atari ST
  • ***
  • Posts: 151
  • Karma: 29
    • View Profile
Re: Aligning a matrix with a polygon normal(axis-angle)
« Reply #2 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?
The Dr. is INsane!!!

Offline hellfire

  • Sponsor
  • Pentium
  • *******
  • Posts: 1289
  • Karma: 466
    • View Profile
    • my stuff
Re: Aligning a matrix with a polygon normal(axis-angle)
« Reply #3 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
Challenge Trophies Won:

Offline Dr_D

  • Atari ST
  • ***
  • Posts: 151
  • Karma: 29
    • View Profile
Re: Aligning a matrix with a polygon normal(axis-angle)
« Reply #4 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.
The Dr. is INsane!!!

Offline hellfire

  • Sponsor
  • Pentium
  • *******
  • Posts: 1289
  • Karma: 466
    • View Profile
    • my stuff
Re: Aligning a matrix with a polygon normal(axis-angle)
« Reply #5 on: August 27, 2011 »
I see. Since you already have an axis-angle representation you can build the matrix directly from it.
Challenge Trophies Won:

Offline Dr_D

  • Atari ST
  • ***
  • Posts: 151
  • Karma: 29
    • View Profile
Re: Aligning a matrix with a polygon normal(axis-angle)
« Reply #6 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 )

The Dr. is INsane!!!

Offline Dr_D

  • Atari ST
  • ***
  • Posts: 151
  • Karma: 29
    • View Profile
Re: Aligning a matrix with a polygon normal(axis-angle)
« Reply #7 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?
The Dr. is INsane!!!

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: Aligning a matrix with a polygon normal(axis-angle)
« Reply #8 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
Challenge Trophies Won:

Offline relsoft

  • DBF Aficionado
  • ******
  • Posts: 3303
  • Karma: 47
    • View Profile
Re: Aligning a matrix with a polygon normal(axis-angle)
« Reply #9 on: September 30, 2011 »
New game from Da Doc?!!! Wooohoooo!!!!!!

You have a DS binary I could play with?

Challenge Trophies Won:

Offline rain_storm

  • Here comes the Rain
  • DBF Aficionado
  • ******
  • Posts: 3088
  • Karma: 182
  • Rain never hurt nobody
    • View Profile
    • org_100h
Re: Aligning a matrix with a polygon normal(axis-angle)
« Reply #10 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;
}
« Last Edit: September 30, 2011 by rain_storm »

Challenge Trophies Won:

Offline Dr_D

  • Atari ST
  • ***
  • Posts: 151
  • Karma: 29
    • View Profile
Re: Aligning a matrix with a polygon normal(axis-angle)
« Reply #11 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
The Dr. is INsane!!!