Sign in to follow this  
TSCrusader

Quaternion

Recommended Posts

TSCrusader    122
Hi all... My game is progressing well and I will be able to show first screenshots in a few weeks maybe, but I have a problem with these damn quaternions. Could you check my quaternion functions or give me some that work 100% ?

D3DXVECTOR4 QuatSlerp(D3DXVECTOR4 &from, D3DXVECTOR4 &to, float t)
{
	float        to1[4];
	float        omega, cosom, sinom, scale0, scale1;

	// calc cosine
	cosom = ((from.x * to.x) + (from.y * to.y) + (from.z * to.z) + (from.w * to.w));
	
	// adjust signs (if necessary)
	if ( cosom <0.0 )
	{ 
		  cosom = -cosom; 
		  to1[0] = - to.x;
          to1[1] = - to.y;
          to1[2] = - to.z;
          to1[3] = - to.w;
	} 
	else 
	{
          to1[0] = to.x;
          to1[1] = to.y;
          to1[2] = to.z;
          to1[3] = to.w;
	}

	 // calculate coefficients
	if ( (1.0 - cosom) > DELTA )
	{
          // standard case (slerp)
          omega = (float)acos(cosom);
          sinom = (float)sin(omega);
          scale0 = (float)sin((1.0 - t) * omega) / sinom;
          scale1 = (float)sin(t * omega) / sinom;

	} 
	else
	{        
      // "from" and "to" quaternions are very close 
      //  ... so we can do a linear interpolation
          scale0 = 1.0f - t;
          scale1 = t;
	}

	D3DXVECTOR4 res;
	// calculate final values
	res.x = scale0 * from.x + scale1 * to1[0];
	res.y = scale0 * from.y + scale1 * to1[1];
	res.z = scale0 * from.z + scale1 * to1[2];
	res.w = scale0 * from.w + scale1 * to1[3];

	return res;
}


void MatrixFromQuat( D3DXMATRIX &m, D3DXVECTOR4 &quat )
{
	float wx, wy, wz, xx, yy, yz, xy, xz, zz, x2, y2, z2;
             
	// calculate coefficients
    
	x2 = quat.x + quat.x; 
	y2 = quat.y + quat.y; 
	z2 = quat.z + quat.z;
	xx = quat.x * x2;   xy = quat.x * y2;   xz = quat.x * z2;
	yy = quat.y * y2;   yz = quat.y * z2;   zz = quat.z * z2;
	wx = quat.w * x2;   wy = quat.w * y2;   wz = quat.w * z2;

	m.m[0][0] = 1.f - (yy + zz);
	m.m[1][0] = xy - wz;
	m.m[2][0] = xz + wy;
                  
	m.m[0][1] = xy + wz;
	m.m[1][1] = 1.f - (xx + zz);
	m.m[2][1] = yz - wx;

	m.m[0][2] = xz - wy;
	m.m[1][2] = yz + wx;
	m.m[2][2] = 1.f - (xx + yy);
}

void QuatFromMatrix( D3DXVECTOR4 &quat, D3DXMATRIX &m )
{
	float  tr, s, q[4];
	int    i, j, k;
	int    nxt[3] = {1, 2, 0};  

	tr = m._11 + m._22 + m._33;

	// check the diagonal
	if (tr > 0.0)
	{
		s = (float)sqrt (tr + 1.f);
		quat.w = s / 2.0f;
		s = 0.5f / s;
		quat.x = (m.m[2][1] - m.m[1][2]) * s;
		quat.y = (m.m[0][2] - m.m[2][0]) * s;
		quat.z = (m.m[1][0] - m.m[0][1]) * s;
	} 
	else
	{                
		// diagonal is negative
		i = 0;
		if (m._22 > m._11) i = 1;
		if (m._33 > m.m[i][i]) i = 2;
		j = nxt[i];
		k = nxt[j];

	    s = (float)sqrt (m.m[i][i] - m.m[j][j] + m.m[k][k] + 1.0);
                       
		q[i] = s * (float)0.5;
                             
		if (s != 0.0f) s = 0.5f / s;

		q[3] = (((m.m[j][k]) - m.m[k][j])) * s;
		q[j] = (((m.m[i][j]) + m.m[j][i])) * s;
		q[k] = (((m.m[i][k]) + m.m[k][i])) * s;

		quat.x = q[0];
		quat.y = q[1];
		quat.z = q[2];
		quat.w = q[3];
	}
}


Share this post


Link to post
Share on other sites
Evil Steve    2017
There's nothing wrong with D3DX. The only real reasons you wouldn't want to use it is if you want to learn how to do things yourself (D3DX will almost always be faster than hand-rolled code, since it makes use of extended CPU features like SSE2 and 3DNow), or if your math functions need to be cross platform (E.g if you're developing for consoles or MacOS/Linux).

I always use D3DX as much as possible.

Share this post


Link to post
Share on other sites
TSCrusader    122
So my render calculation (md3 models) now looks like this:



pol = mod->pol; // interpolation factor

// Get this frame's position
position.x = mod->Tags[mod->Frame * mod->Header.numTags + i].position[0];
position.y = mod->Tags[mod->Frame * mod->Header.numTags + i].position[1];
position.z = mod->Tags[mod->Frame * mod->Header.numTags + i].position[2];

// Get this frame's rotation matrix (in row major form)
for (int row=0; row < 4; row++)
for (int col=0; col < 4; col++)
matrix.m[row][col] = mod->Tags[mod->Frame * mod->Header.numTags + i].rotation[col][row];

// Get the next frame's position
nextposition.x = mod->Tags[mod->NextFrame * mod->Header.numTags + i].position[0];
nextposition.y = mod->Tags[mod->NextFrame * mod->Header.numTags + i].position[1];
nextposition.z = mod->Tags[mod->NextFrame * mod->Header.numTags + i].position[2];

// Get the next frame's rotation matrix (in row major form)
for (row=0; row < 4; row++)
for (int col=0; col < 4; col++)
nextmatrix.m[row][col] = mod->Tags[mod->NextFrame * mod->Header.numTags + i].rotation[col][row];

// Convert the matrices to quaternions
D3DXQuaternionRotationMatrix(&quat1, &matrix);
D3DXQuaternionRotationMatrix(&quat2, &nextmatrix);

// Do a slerp between the quaternions
D3DXQUATERNION res;
D3DXQuaternionSlerp(&res, &quat1, &quat2, pol);

// Convert the interpolated quaternion into a matrix
D3DXMatrixRotationQuaternion(&m, &res);

// Interpolate the frame positions and store it in the matrix
m.m[3][0] = SP_LERP(pol, position.x, nextposition.x);
m.m[3][1] = SP_LERP(pol, position.y, nextposition.y);
m.m[3][2] = SP_LERP(pol, position.z, nextposition.z);
m.m[3][3] = 1.0f;

m *= oldmat; // multiply the matrix by the previous transformation matrix

/*D3DXMATRIX d3dmat;
D3DXMatrixIdentity(&d3dmat);
d3dmat =m;*/



device->SetTransform(D3DTS_WORLD, &m);






But now the death animation and some other animations rotate exactly in the wrong direction. So when they should turn left they turn right... How can i change this??? (Sorry, i have nearly no idea of quaternions)


GOT IT:

just tried the function D3DXQuaternionInverse as it sounded as it could inverse the direction and now it works just fine :D

THANKS for the great help :D (also it were only 6 words ;) )

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this