I am trying to convert floating point to fixed point because the hardware does not have floating point acceleration. I cannot seem to find my mistake for the variable screen_X
the value is always 320.0. The precision is Q38,26 (edit useful bits are Q6.26, 64 bit variables are used for mul and div compatibility).
#define fixed_precision 26
#define CONV_F(A) (A*conv_fixed_precision)
#define CONV_DF(A) (A/(1<<fixed_precision))
#define MUL38_26(A, B)((long long)(A*B)>>fixed_precision)
#define DIV38_26(A, B)((long long)(A<<fixed_precision)/B)
// global variable
double conv_fixed_precision = (1 << fixed_precision);
The floating point code is the following :
void draw_balls(VGA& vga) {
int i;
for (i = 0; i < NB_BALL; i++) {
if (R_Ball[i] == 0) continue; // the pearl has already been found
double screen_X = X_Ball[i];
double screen_Y = Y_Ball[i];
screen_X -= X_position;
screen_Y -= Y_position;
screen_X *= Scale;
screen_Y *= Scale;
double screen_Radius = R_Ball[i] * Scale;
if ((screen_X * screen_X + screen_Y * screen_Y <= screen_Radius * screen_Radius)) {
//La perle est trouvee
R_Ball[i] = 0;
int time = get_time();
printf("Found %i pearl(s) at time %i\n", ++found_pearl, time);
}
double tmp_X = screen_X;
double tmp_Y = screen_Y;
screen_X = (tmp_X * cosAngle - tmp_Y * sinAngle) * 240 + 320;
screen_Y = (tmp_X * sinAngle + tmp_Y * cosAngle) * 240 + 240;
screen_Radius *= 240;
if (screen_X + screen_Radius < 0) break;
if (screen_X - screen_Radius >= 640) break;
if (screen_Y + screen_Radius < 0) break;
if (screen_Y - screen_Radius >= 480) break;
drawBall3D(vga, screen_X, screen_Y, screen_Radius, i % 7);
}
#ifdef USE_OPEN_GL
glFlush();
#endif
and the fixed point code is the following:
void draw_balls(VGA & vga) {
int i;
long long cosAngF = CONV_F(cosAngle);
long long sinAngF = CONV_F(sinAngle);
long long scaleF = CONV_F(Scale);
long long xPosF = CONV_F(X_position);
long long yPosF = CONV_F(Y_position);
for (i = 0; i < NB_BALL; i++) {
if (R_Ball[i] == 0) continue; // the pearl has already been found
long long screen_X = CONV_F(X_Ball[i]);
long long screen_Y = CONV_F(Y_Ball[i]);
screen_X -= xPosF;
screen_Y -= yPosF;
screen_X = MUL38_26(screen_X, scaleF);
screen_Y = MUL38_26(screen_Y, scaleF);
long long screen_Radius = CONV_F(R_Ball[i] * Scale);
if ((MUL38_26(screen_X, screen_X) + MUL38_26(screen_Y, screen_Y)) <= MUL38_26(screen_Radius, screen_Radius)) {
//La perle est trouvee
R_Ball[i] = 0;
int time = get_time();
printf("Found %i pearl(s) at time %i\n", ++found_pearl, time);
}
long long tmp_X = screen_X;
long long tmp_Y = screen_Y;
long long F240 = ((long long)240)<<fixed_precision;
long long F320 = ((long long)320) << fixed_precision;
screen_X = MUL38_26(MUL38_26(tmp_X, cosAngF) - MUL38_26(tmp_Y, sinAngF), F240) + F320;
screen_Y = MUL38_26(MUL38_26(tmp_X, sinAngF) + MUL38_26(tmp_Y, cosAngF), F240) + F240;
screen_Radius = MUL38_26(screen_Radius, F240);
long long F640 = ((long long)640) << fixed_precision;
long long F480 = ((long long)480) << fixed_precision;
if (screen_X + screen_Radius < 0) break;
if (screen_X - screen_Radius >= F640) break;
if (screen_Y + screen_Radius < 0) break;
if (screen_Y - screen_Radius >= F480) break;
drawBall3D(vga, screen_X>>fixed_precision, screen_Y >> fixed_precision, screen_Radius >> fixed_precision, i % 7);
}
#ifdef USE_OPEN_GL
glFlush();
#endif
#endif
}