Beispiel #1
0
static fixed fixisqrt(fixed v)
{
	// TODO: Proper inverse square root
	float sq = fixsqrt(v);
	
	if(sq == 0) sq = 1; // Prevent div-by-zero (yes, this crashes a PS1!)
	return fixdiv(0x10000, sq);
}
Beispiel #2
0
/* calculates the distance between two nodes */
fixed node_dist(NODE n1, NODE n2)
{
   #define SCALE  64

   fixed dx = itofix(n1.x - n2.x) / SCALE;
   fixed dy = itofix(n1.y - n2.y) / SCALE;

   return fixsqrt(fixmul(dx, dx) + fixmul(dy, dy)) * SCALE;
}
/* calculates the distance between two curve_nodes */
fixed curve_node_dist(curve_node n1, curve_node n2)
{
#define SCALE  64

    fixed dx = itofix(n1.x - n2.x) / SCALE;
    fixed dy = itofix(n1.y - n2.y) / SCALE;

    return fixsqrt(fixmul(dx, dx) + fixmul(dy, dy)) * SCALE;
}
Beispiel #4
0
int main(int argc, char* argv[])
{
	int i;
	for (i = 1000; i > 0; --i) {
		float f1 = fixed2float(fixsqrt(int2fixed(i)));
		float f2 = sqrtf(i);
		float diff = f1 - f2;
		printf("%d\t%.2f\t%.2f\t%.2f\n", i, f1, f2, diff);
		assert(fabsf(diff) < fixed2float(2));
	}
	TIMEIT(1000, for (i = 1000; i > 0; --i) fixsqrt(int2fixed(i)));
	system("pause");
	return 0;
}
Beispiel #5
0
int main(void)
{
   /* declare three 32 bit (16.16) fixed point variables */
   fixed x, y, z;

   if (allegro_init() != 0)
      return 1;

   /* convert integers to fixed point like this */
   x = itofix(10);

   /* convert floating point to fixed point like this */
   y = ftofix(3.14);

   /* fixed point variables can be assigned, added, subtracted, negated,
    * and compared just like integers, eg: 
    */
   z = x + y;
   allegro_message("%f + %f = %f\n", fixtof(x), fixtof(y), fixtof(z));

   /* you can't add integers or floating point to fixed point, though:
    *    z = x + 3;
    * would give the wrong result.
    */

   /* fixed point variables can be multiplied or divided by integers or
    * floating point numbers, eg:
    */
   z = y * 2;
   allegro_message("%f * 2 = %f\n", fixtof(y), fixtof(z));

   /* you can't multiply or divide two fixed point numbers, though:
    *    z = x * y;
    * would give the wrong result. Use fixmul() and fixdiv() instead, eg:
    */
   z = fixmul(x, y);
   allegro_message("%f * %f = %f\n", fixtof(x), fixtof(y), fixtof(z));

   /* fixed point trig and square root are also available, eg: */
   z = fixsqrt(x);
   allegro_message("fixsqrt(%f) = %f\n", fixtof(x), fixtof(z));

   return 0;
}
Beispiel #6
0
GLvoid glRotatex(GLfixed theta, GLfixed x, GLfixed y, GLfixed z) // p35 2.9.2
{
	int i, j, k;

	// Ensure we have an axis of rotation!
	if(x == 0 && y == 0 && z == 0)
		return;

	// Mark dirty
	gl_mat_gte_isdirty = GL_TRUE;

	// OPTIMISATION: If on a single axis we don't need to tweak as much
	int zeros = 0;
	if(x == 0) zeros++;
	if(y == 0) zeros++;
	if(z == 0) zeros++;

	//if(0)
	if(zeros == 2)
	{
		// Rotate around an axis
		// FIXME: get correct rotation orders
		int a, b;
		if(x != 0) { a = 1; b = 2; }
		else if(y != 0) { a = 2; b = 0; }
		else { a = 0; b = 1; }

		// Get matrix pointer
		GLint stackidx = gl_mat_stack[gl_mat_cur];
		GLfixed *rot = gl_mat_rot[gl_mat_cur][stackidx];

		// Get sin/cos
		//theta /= 360; // dropping the "degrees" requirement, using direct angles instead
		GLfixed tsin = fixsin(theta);
		GLfixed tcos = fixcos(theta);

		// Get old values
		GLfixed ta0 = rot[a*3 + 0];
		GLfixed ta1 = rot[a*3 + 1];
		GLfixed ta2 = rot[a*3 + 2];
		GLfixed tb0 = rot[b*3 + 0];
		GLfixed tb1 = rot[b*3 + 1];
		GLfixed tb2 = rot[b*3 + 2];

		// Write new values
		// TODO: get this to behave
		rot[a*3 + 0] = fixmulf(ta0, tcos) - fixmulf(tb0, tsin);
		rot[a*3 + 1] = fixmulf(ta1, tcos) - fixmulf(tb1, tsin);
		rot[a*3 + 2] = fixmulf(ta2, tcos) - fixmulf(tb2, tsin);
		rot[b*3 + 0] = fixmulf(ta0, tsin) + fixmulf(tb0, tcos);
		rot[b*3 + 1] = fixmulf(ta1, tsin) + fixmulf(tb1, tcos);
		rot[b*3 + 2] = fixmulf(ta2, tsin) + fixmulf(tb2, tcos);

		return;
	}

	//
	// GENERIC OPENGL ROTATION
	//

	// Normalise x,y,z
	GLfixed vlen2 = fixmul(x,x) + fixmul(y,y) + fixmul(z,z);
	if(vlen2 >= 0x100)
	{
		GLfixed vlen = fixsqrt(vlen2);
		x = fixdiv(x, vlen);
		y = fixdiv(y, vlen);
		z = fixdiv(z, vlen);
	} else {
		// Length is too small to get a sane result
		// Use int multiplies instead and shift later

		// FIXME get this working correctly
		vlen2 = x*x + y*y + z*z;

		// Skip if we get 0
		if(vlen2 == 0)
			return;

		GLfixed vlen = fixsqrt(vlen2)<<8;
		x = fixdiv(x, vlen);
		y = fixdiv(y, vlen);
		z = fixdiv(z, vlen);

	}

	// Get sin/cos
	theta /= 360;
	GLfixed tsin = fixsin(theta);
	GLfixed tcos = fixcos(theta);

	// Generate rotation matrix
	GLfixed itcos = 0x10000-tcos;
	GLfixed base_rot[3][3] = {
		{
			fixmulf(itcos, fixmulf(x, x))+tcos,
			fixmulf(itcos, fixmulf(x, y))-fixmulf(tsin, z),
			fixmulf(itcos, fixmulf(x, z))+fixmulf(tsin, y),
		},
		{
			fixmulf(itcos, fixmulf(y, x))+fixmulf(tsin, z),
			fixmulf(itcos, fixmulf(y, y))+tcos,
			fixmulf(itcos, fixmulf(y, z))-fixmulf(tsin, x),
		},
		{
			fixmulf(itcos, fixmulf(z, x))-fixmulf(tsin, y),
			fixmulf(itcos, fixmulf(z, y))+fixmulf(tsin, x),
			fixmulf(itcos, fixmulf(z, z))+tcos,
		},
	};

	// Apply rotation matrix
	GLint stackidx = gl_mat_stack[gl_mat_cur];
	GLfixed *rot = gl_mat_rot[gl_mat_cur][stackidx];
	//GLfixed *trn = gl_mat_trn[gl_mat_cur][stackidx];
	GLfixed oldrot[9];
	//GLfixed oldtrn[3];
	memcpy(oldrot, rot, sizeof(GLfixed)*9);
	//memcpy(oldtrn, trn, sizeof(GLfixed)*3);

	// FIXME: translate properly
	// FIXME: ensure correct order
	for(i = 0; i < 3; i++)
	for(j = 0; j < 3; j++)
	{
		GLfixed sum = 0;
		for(k = 0; k < 3; k++)
			//sum += fixmulf(oldrot[3*i + k], base_rot[k][j]);
			sum += fixmulf(oldrot[3*k + j], base_rot[i][k]);

		rot[3*i + j] = sum;
	}

	/*
	for(i = 0; i < 3; i++)
	{
		GLfixed sum = 0;
		for(k = 0; k < 3; k++)
			sum += fixmulf(oldtrn[k], rot[k*3 + i]);
			//sum += fixmulf(oldtrn[k], rot[i*3 + k]);
			//sum += fixmulf(oldtrn[k], base_rot[k][i]);
			//sum += fixmulf(oldtrn[k], base_rot[i][k]);

		//trn[i] = sum;
	}
	*/
}