#15650 - garfunkalow - Tue Jan 27, 2004 3:46 am
Hello,
I have decided to use the GBA for my CSCI410 Computer Graphics class since everyone else is coding in java i decided to be different.
Ok i got a sprite on the screen, moved it a around with the Dpad and got it to rotate and zoom
my question is how can i shear the image and do reflections?
i know the math behind it but i can't seem to get a handle to the sprites.
I have read chapter 3 from the pern project and the zooming/rotation seems pretty straight forward...
_________________
Computers are to Computer Science as Telescopes are to Astronomers
Last edited by garfunkalow on Tue Jan 27, 2004 9:31 am; edited 1 time in total
#15651 - garfunkalow - Tue Jan 27, 2004 4:11 am
<-- figured it out.. just made another function and also created a TAN array...
_________________
Computers are to Computer Science as Telescopes are to Astronomers
#15660 - garfunkalow - Tue Jan 27, 2004 9:29 am
ok.. stuck again...
i wrote a function to shear a sprite as follows
void ShearSprite(int rotDataIndex, int sheer, FIXED x_scale,FIXED y_scale)
//this should shear the sprite
{
FIXED pa, pb, pc, pd;
pa = ((x_scale) * COS[0])>>8;
pb = ((y_scale) * SIN[0])>>8;
pc = ((x_scale) * TAN[shear])>>8;
pd = ((y_scale) * COS[0])>>8;
rotData[rotDataIndex].pa = pa;
rotData[rotDataIndex].pb = pb;
rotData[rotDataIndex].pc = pc;
rotData[rotDataIndex].pd = pd;
}
the only problem i am then having i am calling this from the main() after i call the RotateSprite function (from the PERN project) the shear works but then the RotateSprite function doesn't work.
For a quick and nasty workaround i decided to make a fucntion called
void IfRotateorShear()
{
if(oldshear == shear)
{
RotateSprite(0,angle,zoom,zoom);
}
else
{
ShearSprite(0, shear, zoom,zoom);
}
}
where oldshear starts out as zero then when the start key is pressed i then assign oldshear the value of shear, increment shear (decrements for the select key), test for undefined (tan 90, etc, etc)
this value is then passed into the IfRotatedorShear function, i figured if the oldshear and shear are the same then i didn't press the start button. and i should call rotate incase i rotated the sprite.
if oldshear and shear do NOT equal eachother that would mean i did press the start (or select) button so i should shear the image.
the problem is:
after i shear the image i can no longer rotate it. Another thing is i can rotate the sprite first then shear it (although it resets the sprite for some reason), but after i shear it i can no longer rotate it. i can still move it around and zoom in and out.
so to put simply the nasty workaround isn't working the way i thought it would :(
any help would be much appreciated
_________________
Computers are to Computer Science as Telescopes are to Astronomers
#15661 - sajiimori - Tue Jan 27, 2004 10:04 am
I don't quite understand. Are you trying to do both effects simultaneously?
#15662 - garfunkalow - Tue Jan 27, 2004 10:12 am
sure, that would work.
Basically i would like when i press start (or select) along with the either R or L that the sprite both rotates and shears
sorry if this is confusing.. kinda hard to explain.
_________________
Computers are to Computer Science as Telescopes are to Astronomers
#15665 - Cearn - Tue Jan 27, 2004 12:13 pm
I think I know what's going on, but first things first.
For transforming sprites and backgrounds the GBA uses a matrix P that defines the affine transformation from screen space to object/background space. That's why to increase the size by s you need to use 1/s.
There are three 2d affine transformations: rotation R, scaling S and shear H. I'm assuming you know what these matrices look like.
Pern's rotation/scale function results in
(1) P = R * S, i.e. a rotation followed by a scaling. (No, not the other way around. Use sx != sy to see what I mean)
Your ShearSprite gives
(2) P = H * S (shear, then scale)
garfunkalow wrote: |
the problem is:
after i shear the image i can no longer rotate it. Another thing is i can rotate the sprite first then shear it (although it resets the sprite for some reason), but after i shear it i can no longer rotate it. i can still move it around and zoom in and out.
|
I'm assuming you have a function that increases or decreases the angle and shear when you press the appropriate buttons. As long as you rotate the angle increases and your P changes accordingly. But when you change to a shear your IfRotateorShear function switches to a your shear matrix. And only your shear matrix, as given by eq 2. That's why it seems reset. If you want to shear the already rotated sprite you have to concatenate the current matrix with the shear like so
(3) P = P * H
As for why you can't rotate after a shear, uhm, when's oldshear updated exactly? Are you sure oldshear != shear when you start rotating? Check
in memory or print out both values if you're not sure.
I think I have a demo which does what you are after. (freely, rotate,
shear and scale a sprite). If you want it I could mail it to you.
#15676 - sajiimori - Tue Jan 27, 2004 7:52 pm
In plain English, if your RotateSprite looks anything like your ShearSprite (creating new values for pa-pd from scratch), then whichever you call last will decide what the sprite looks like.
Maybe that's obvious to you, but I don't know what's happening without seeing more code. (Also, post code using the [code] tags.)
#15679 - garfunkalow - Tue Jan 27, 2004 9:29 pm
well here is the code
is is pretty much line by line the 3rd project over at PERN
Code: |
void RotateSprite(int rotDataIndex, int angle, FIXED x_scale,FIXED y_scale);
void ShearSprite(int rotDataIndex, int angle, FIXED x_scale,FIXED y_scale);
void IfRotateorShear();
///these are global so i do not have to pass them to GetInput
FIXED angle = 0;
FIXED shear = 0;
FIXED oldshear = 0;
FIXED zoom = 1<<8;
FIXED SIN[360];
FIXED COS[360];
FIXED TAN[360];
int main(void)
{
int index = 0; //some looping variables for loops :)
u16 loop;
for(loop = 0; loop < 360; loop++)
{
SIN[loop] = (FIXED)(sin(RADIAN(loop)) * 256); //sin and cos are computed and cast to //fixed
COS[loop] = (FIXED)(cos(RADIAN(loop)) * 256);
TAN[loop] = (FIXED)(tan(RADIAN(loop)) * 256);
}
SetMode(MODE_2 | OBJ_ENABLE | OBJ_MAP_1D); //set mode 2 and enable sprites and 1d mapping
for(loop = 0; loop < 256; loop++)
{
OBJPaletteMem[loop] = smileyPalette[loop]; //loop through and store the palette from your pict
}
//palette into obj palette mem OBJPaletteMem is
//defined in gba.h. sprite1Palette is from
//pcx2gba tool sprite1.h.
InitializeSprites(); //set all 128 sprites to offscreen
sprites[0].attribute0 = COLOR_256 | SQUARE| ROTATION_FLAG | y;
sprites[0].attribute1 = SIZE_64 |ROTDATA(0)|x;
sprites[0].attribute2 = char_number;
for(index = 0; index < 256*8; index++)
{
OAMData[index] = smileyData[index];
}//end index loop
while(1)
{
GetInput();
MoveSprite(&sprites[0],x,y);
IfRotateorShear();
// RotateSprite(0,angle,zoom,zoom);
// ShearSprite(0,shear, zoom,zoom);
WaitForVsync(); //wait for screen to stop drawing
CopyOAM(); //copy sprite into OAM memory
}
}
void IfRotateorShear()
{
if(oldshear == shear)
{
RotateSprite(0,angle,zoom,zoom);
}
else
{
ShearSprite(0, shear, zoom,zoom);
//oldshear = shear;
}
}
//sets sprites to off screen
void GetInput(void)
{
//the D pad will move in the proper direction
if(!(*KEYS & KEY_UP))//up on the D pad
{
y--;
}
if(!(*KEYS & KEY_DOWN))//down on the D pad
{
y++;
}
if(!(*KEYS & KEY_LEFT))//left on the D pad
{
x--;
}
if(!(*KEYS & KEY_RIGHT))//right on the D pad
{
x++;
}
if(!(*KEYS & KEY_L))//Left shoulder button will rotate clockwise
{
angle--;
if(angle<0)
angle = 359;
}
if(!(*KEYS & KEY_R))//Right shoulder button will rotate counter-clockwise
{
angle++;
if(angle > 359)
angle = 0;
}
if(!(*KEYS & KEY_A))//A key will zoom out
{
zoom--;
}
if(!(*KEYS & KEY_B))//B key will zoom in
{
zoom++;
}
if(!(*KEYS & KEY_START))
{
oldshear = shear;
shear++;
if(shear > 359)
{
shear = 0;
}
else if(shear == 90)//to take care of tan 90 undefined
{
shear = 91;
}
else if(shear == 270)//to take care of tan 270 undefined
{
shear = 271;
}
}
if(!(*KEYS & KEY_SELECT))
{
oldshear = shear;
shear--;
if(shear < 0)
{
shear = 359;
}
else if(shear == 90)//to take care of tan 90 undefined
{
shear = 89;
}
else if(shear == 270)//to take care of tan 270 undefined
{
shear = 269;
}
}
}
void RotateSprite(int rotDataIndex, int angle, FIXED x_scale,FIXED y_scale)
{
FIXED pa, pb, pc, pd;
pa = ((x_scale) * COS[angle])>>8; //(do my fixed point multiplies and shift back down)
pb = ((y_scale) * SIN[angle])>>8;
pc = ((x_scale) * -SIN[angle])>>8;
pd = ((y_scale) * COS[angle])>>8;
rotData[rotDataIndex].pa = pa; //put them in my data struct
rotData[rotDataIndex].pb = pb;
rotData[rotDataIndex].pc = pc;
rotData[rotDataIndex].pd = pd;
}
void ShearSprite(int rotDataIndex, int sheer, FIXED x_scale,FIXED y_scale)
//this should shear the sprite
{
FIXED pa, pb, pc, pd;
pa = ((x_scale) * COS[0])>>8;
pb = ((y_scale) * SIN[0])>>8;
pc = ((x_scale) * TAN[shear])>>8;
pd = ((y_scale) * COS[0])>>8;
rotData[rotDataIndex].pa = pa; //put them in my data struct
rotData[rotDataIndex].pb = pb;
rotData[rotDataIndex].pc = pc;
rotData[rotDataIndex].pd = pd;
}
|
i have included the rotatesprite() (from PERN)
, ShearSprite(), and IfRotateorShear()
i believe i could do this without the IfRotateorShear()
i basically want to shear, rotate, translate, and zoom 1 sprite...
so i will be taking in consideration what Cearn has said
also sajiimori thank-you for telling me about the code tag, i should have been more aware of it and used it from the beginning
_________________
Computers are to Computer Science as Telescopes are to Astronomers
#15682 - sajiimori - Tue Jan 27, 2004 10:10 pm
Well, if you were expecting the sprite to be sheared and rotated at the same time (you only said "sure, that would work"), that can never happen with your code. ShearSprite and RotateSprite are inventing their own versions of pa-pd, totally overwriting what was already there.
If you're only trying to do one effect at a time, well... I don't understand your oldshear logic. Why don't you just use a state variable?
Code: |
enum { EF_SHEAR, EF_ROTATE };
int current_effect;
void do_current_effect()
{
switch(current_effect)
{
case EF_SHEAR:
ShearSprite(...);
break;
case EF_ROTATE:
RotateSprite(...);
break;
}
}
|
#15683 - garfunkalow - Tue Jan 27, 2004 10:20 pm
cool, i will try that. What approach should i use to get it to shear and rotate at the same time?
... i could always do both transformations at the time time right? with just the angle?
anyway i will try this
kinda fun programming on this, a lot different than the norm i have been using (Java)
reminds back when i took a x86 ASM course.
once again thanks to everyone who has replied!
_________________
Computers are to Computer Science as Telescopes are to Astronomers
#15685 - sajiimori - Tue Jan 27, 2004 11:00 pm
Quote: |
What approach should i use to get it to shear and rotate at the same time?
|
You could replace RotateSprite and ShearSprite with something like SetupSprite that combines both effects. Sorry, I don't know what the exact math would be. Perhaps Cearn's demo can show you that.
Quote: |
... i could always do both transformations at the time time right? with just the angle?
|
Well, obviously it has to know how much to rotate and how much to shear.
#15709 - garfunkalow - Wed Jan 28, 2004 8:48 am
well..i put both the rotation and shearing as part of the same matrix and it works!
just shearing goes REALLY fast...
_________________
Computers are to Computer Science as Telescopes are to Astronomers
#15792 - Cearn - Fri Jan 30, 2004 1:03 pm
garfunkalow wrote: |
well..i put both the rotation and shearing as part of the same matrix and it works! just shearing goes REALLY fast... |
Maybe that's because you're using tan() in your shear. At 60 frames per second you're passing the asymptote at 90 degrees after 1.5 seconds. You could slow it down by either counting fractions of degrees via fixed point math like this
Code: |
pc = ((x_scale) * TAN[shear>>2])>>8;
|
or do away with the tangens function altogether. In fact, you don't need any trigonometry in it (cos(0)= 1 and sin(0)= 0, remember?). Yer basic shear matrix is
Code: |
| 1 0 |
| |
| hy 1 |
|
You're using hy= tan(shear) right now, which increases quickly when you approach 90 degrees. Very quickly. If you just use a linear increasing number it'll look better. Even hy= shear would work then.
sajimori wrote: |
In plain English...
|
Is this better? Sorry if the previous post was a little, uhm, technical. It's just that If I'd seen what I had written in a tutorial somewhere I would have understood the rotation/scale/shear thing a whole lot sooner.
#15802 - garfunkalow - Fri Jan 30, 2004 5:22 pm
nice, i will try this!
_________________
Computers are to Computer Science as Telescopes are to Astronomers
#15814 - sajiimori - Fri Jan 30, 2004 8:54 pm
Quote: |
Sorry if the previous post was a little, uhm, technical.
|
It's just that before the issues of rotation speed or matrix overlays, it seemed to me that there was a simpler problem barring the way: memory registers can't hold 2 things at once. ;-)
#15855 - Cearn - Sun Feb 01, 2004 8:27 pm
Just for the record, when it comes to combining different transformations you have to be really really REALLY careful what you're after. For example, if you rotate by, say, 45 degrees and then scale in the y direction only you get a very different result than when you scale first, then rotate. In the latter case the principle axes of your sprite will still be perpendicular, but in the former the end-result will look sheared as well. My demo shows this and I would list it here now, if I hadn't forgot to bring it with me :(. Maybe tomorrow.
Bottom line, though, be very sure of what you mean when you say
garfunkalow wrote: |
What approach should i use to get it to shear and rotate at the same time? |
because in truth there's no such thing. It's either shear-then-rotate or rotate-then-shear.
#15859 - garfunkalow - Sun Feb 01, 2004 8:58 pm
true, as to when i asked which way i should rotate on shear at the same time, i know this cannot actually be done at the same time, but i will try some of the stuff mentioned earlier when i get back to school on monday...
i would again like to thank everyone who has helped me... i already turned in my assignment and i don't think the professor will be able to understand all the code (aside from my documentation) so... i am pretty sure i'll get a good grade since it is new and different.. and most importantly it works :)[/quote]
_________________
Computers are to Computer Science as Telescopes are to Astronomers