gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

Beginners > Rotating sprites

#41100 - ymalik - Mon Apr 25, 2005 3:57 am

Hello,
I'm having trouble with rotating a sprite. I am dealing with one rotating sprite and one regular sprite. Here is the code to generate the look-up tables:
Code:

#include <math.h>
#define PI 3.14159265
#define DEGREES    360      // Full circle
#define FIX_SCALEF 256.0f

typedef signed long FIXED;
FIXED SIN[DEGREES], COS[DEGREES];

// A really simple (and slow and wasteful) LUT builder
// from Cearn's TONC tutorial

int main()
{
   int ii;
   const double conv= 2*PI/DEGREES;

   for(ii=0; ii<DEGREES; ii++)
   {
      SIN[ii]= (FIXED)(sin(conv*ii)*FIX_SCALEF);
      COS[ii]= (FIXED)(cos(conv*ii)*FIX_SCALEF);
   }

   printf("#include \"gba.h\"\nFIXED SIN[360] = {");

   for(ii = 0; ii<DEGREES; ii++)
      printf("\n%i,", SIN[ii]);

   printf("};\n\n");

   printf("FIXED COS[360] = {");

   for(ii = 0; ii<DEGREES; ii++)
      printf("\n%i,", COS[ii]);

   printf("};\n");
}


And here's the relevant code from the GBA program:

OAM structs
Code:

typedef struct tagOAMEntry
{
   u16 attribute[3];
   u16 filler;
}OAMEntry,*pOAMEntry;

typedef struct tagRotData
{

   u16 filler1[3];
   u16 pa;

   u16 filler2[3];
   u16 pb;

   u16 filler3[3];
   u16 pc;

   u16 filler4[3];
   u16 pd;
}RotData,*pRotData;

OAMEntry sprites[128];
RotData *rotData = (RotData *) sprites;


Sprite initializations. Sprite 0 is the rotating sprite.
Code:

   sprites[0].attribute[0] = COLOR_16 | TALL | ROTATION_FLAG | 12;
   sprites[0].attribute[1] = SIZE_8 | ROTDATA(0) | 16;
   sprites[0].attribute[2] = 16 | SPRITE_PRIORITY;

   sprites[4].attribute[0] = COLOR_16 | SQUARE | 240;
   sprites[4].attribute[1] = SIZE_16 | 160;
   sprites[4].attribute[2] = 0 | SPRITE_PRIORITY;


And the code to store the data into the affine matrix
Code:

      rotData->pa = COS[angle] >> 8;
      rotData->pb = -SIN[angle] >> 8;
      rotData->pc =  SIN[angle] >> 8;
      rotData->pd =  COS[angle] >> 8;


Sprite 4 is being generated fine. Instead of seeing a rotating arrow, I am seeing a rectangle of the same dimensions for sprite 0.

Thank you,
Yasir

#41110 - Cearn - Mon Apr 25, 2005 8:51 am

ymalik wrote:
Hello,

Code:

#define FIX_SCALEF 256.0f

typedef signed long FIXED;
FIXED SIN[DEGREES], COS[DEGREES];

int main()
{
   const double conv= 2*PI/DEGREES;

   for(ii=0; ii<DEGREES; ii++)
   {
      SIN[ii]= (FIXED)(sin(conv*ii)*FIX_SCALEF);
      COS[ii]= (FIXED)(cos(conv*ii)*FIX_SCALEF);
   }
   // <snip>
}


<snip>

And the code to store the data into the affine matrix
Code:

      rotData->pa = COS[angle] >> 8;
      rotData->pb = -SIN[angle] >> 8;
      rotData->pc =  SIN[angle] >> 8;
      rotData->pd =  COS[angle] >> 8;


The generated table is already in .8 fixed format ; when you shift down later the range you put in the affine elements are effectively normal integers in the range [0,1] (in fact, 0 everywhere except possibly at 90? intervals). The GBA still thinks they're .8 fixeds though, and therefore scales it by 256/0 or 256/1. Remove the shifts and it should work.

#41118 - ymalik - Mon Apr 25, 2005 2:35 pm

Much thanks.

I decided to use a 360 degree lut, even though 512 entry lut makes sense, because I am getting the angles from a GPS satellite, which gives values in 360 degree circles.