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.

DS development > 2 Noob questions regarding sprite rotation - Answered

#136428 - mr_munk - Wed Aug 01, 2007 5:45 pm

Hi,

I have been working through the 'Introduction to DS Development Tutorial' Chapter six. I wondered if anyone could tell me what the following code in the tutorial is for ? (I added the comments btw)

Code:
//rotate a sprite
void rotateSprite(SpriteRotation * spriteRotation, u16 angle)
{
   s16 s = -SIN[angle & 0x1FF] >> 4; //bitmask lower 9 bits of u16 (& 0001 1111 1111)
                            //then divide Sine by 8
   s16 c =  COS[angle & 0x1FF] >> 4; //bitmask lower 9 bits of u16 (& 0001 1111 1111)
                            //then divide Cosine by 8

   spriteRotation->hdx =  c;
   spriteRotation->hdy = -s;
   spriteRotation->vdx =  s;
   spriteRotation->vdy =  c;
}


Specifically, why is it necessary to bitmask and shift the incoming U16 var angle?

My second question regards the ATTR1_ROTDATA(n) constant, from the #define in ndslib/video.h I think that this sets the upper 7 bitsof a sprite entry register (?) but what does this mean for the sprites attributes ?

Any help appreciated - I just want to develop my understanding of what the code I am writing actually does.


Last edited by mr_munk on Wed Aug 01, 2007 8:00 pm; edited 1 time in total

#136431 - Cearn - Wed Aug 01, 2007 7:17 pm

mr_munk wrote:
Specifically, why is it necessary to bitmask and shift the incoming U16 var angle?
For rotation, you need cons and cosine data. Because the C functions for these are slow (very slow), libnds uses 512-entry look-up tables instead. The angle is simply the index for the tables. Since reading beyond the boundaries of an array is bad, we take angle%LUTSIZE -- because LUTSIZE is a power of two here, this can be done with an AND instead of a costly modulo. The shift by 4 is required because the NDS affine registers are in 8.8 fixed point format, but the arrays are in 4.12.

mr_munk wrote:
My second question regards the ATTR1_ROTDATA(n) constant, from the #define in ndslib/video.h I think that this sets the upper 7 bits of a sprite entry register (?) but what does this mean for the sprites attributes ?
There are 32 available affine matrices for sprites, and you can select which one a particular sprite uses with bits 8-13 from attribute 1. The ATTR1_ROTDATA() macro just assumes you don't try to use an index over 31.

For more details, see tonc:affine matrix and tonc: affine objects. Yes, those are for GBA, but the NDS has much of the same hardware.

#136434 - mr_munk - Wed Aug 01, 2007 8:00 pm

Excellent, many thanks Cearn :)

For anyone else searching this topic, I found this tutorial on fixed-point a little easier to understand as a beginner.

#141118 - jonezer4 - Sat Sep 22, 2007 8:25 am

To resurrect an old topic, I'm having a bit of trouble with this section.

I think I understand it pretty clearly, however, when I feed an angle into the rotatesprite function, I get unexpected rotations.

For instance, 90 will result in what appears to be around a 45?.
135 looks like about 100?.
180 looks like 135?.
And so on.

Am I missing something? I'm using patatersoft's demo as a basis, but I have changed from rotscale_double sprites to just rotscale, is that the problem?

Pertinent code:

Code:
   for (int n = 0; n < NUM_SPRITES; n++)
   {
   spriteEntry[n].attribute[0] =     ATTR0_COLOR_256
                           | ATTR0_ROTSCALE   //_DOUBLE
                           | 0;            //Setting Y to zero for now
                           
   spriteEntry[n].attribute[1] =     ATTR1_ROTDATA(n)   //Giving each sprite a unique rot value
                           | ATTR1_SIZE_64      //sprite size is 64
                           | 0;            //Setting X to zero for now
            
   spriteEntry[n].attribute[2] = spriteGfxID * n;

   setSpritePriority(&spriteEntry[n],1);            //setting all sprites to lowest priority
   
   dmaCopy(cards_bin+4096*n,   
   &SPRITE_GFX[64*64/2 * n],                     // div. by 2 because of 16bit addressing
   64*64);
   
   hideSprite(&spriteEntry[n], true);               //hide all sprites upon initialization

   rotateSprite(&spriteRotation[n], 135);


   }


Code:
void rotateSprite(SpriteRotation * spriteRotation, u16 angle)
{

   s16 s = -SIN[angle & 0x1FF] >> 4;            
   s16 c =  COS[angle & 0x1FF] >> 4;                                 
   spriteRotation->hdx =  c;
   spriteRotation->hdy = -s;
   spriteRotation->vdx =  s;
   spriteRotation->vdy =  c;
}

#141120 - Corsix - Sat Sep 22, 2007 9:29 am

You seem to be making the assumption that angle is given in degrees.

#141123 - jonezer4 - Sat Sep 22, 2007 10:10 am

Corsix wrote:
You seem to be making the assumption that angle is given in degrees.


I thought it was? I tried rads and that didn't appear to work out either.

1.57 rotates them just barely, which to my understanding would equate to 90? degrees. 3.14 rotates them just a hair more, which would be 180?, right?

I've also tried 157, thinking maybe the u16 is an int that wants rads not in floating point form, but that doesn't work either, looks like about 120? then.

#141134 - Cearn - Sat Sep 22, 2007 1:09 pm

The libnds LUTs for sines and cosines divide the circle into 512 units, not 360 or 2π (powers of two are easier to deal with, that's why). Don't think in terms of degrees, but in circle-fractions: a full rotation is 512 (0x200), half rotation is 256 (0x100), etc. 45? is an eighth of a circle, so that's 64 (0x40).

#141137 - jonezer4 - Sat Sep 22, 2007 1:44 pm

Cearn wrote:
The libnds LUTs for sines and cosines divide the circle into 512 units, not 360 or 2π (powers of two are easier to deal with, that's why). Don't think in terms of degrees, but in circle-fractions: a full rotation is 512 (0x200), half rotation is 256 (0x100), etc. 45? is an eighth of a circle, so that's 64 (0x40).


Ah great, thank you! I think I recall now a 512 actually being in there at some point, don't know how that got lost, but thanks very much.

#141158 - tepples - Sat Sep 22, 2007 7:17 pm

Previous discussion: brads
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.