Bitmap rotation1

07/01/2010

(for the not leaking version see Bitmap rotation2)

When working with tiles and sprites  you can rotate the sprite easily, because rotation is a property of the sprite. But we are working in the bitmapmode.

We can copy images to a background without a problem, but rotating the image is somewhat complicated.

The first solution is to do a simnple rotation of points:

within the loop of the pixels of the image:

//minus point of rotation
float x = (float)j – height/2.0;
float y = (float)i – width/2.0;
//rotating matrix
float newX = x*cosine-y*sine;
float newY = x*sine+y*cosine;
//plus point of rotation
int newIntX = (int)newX + height/2.0;
int newIntY = (int)newY + width/2.0;

but the you notice that some pixels due to approximations are not drawn. Some pixel locations are not reached:


The trick is to work from the destination bitmap and ask for the pixel color of the source…

see this link:

http://www.codeguru.com/cpp/g-m/bitmap/specialeffects/article.php/c1743/

but here the rotation is done from the corner point (0,0) and the use of the double buffer has to be considered for nds programming.

we solve these problems in this way:

float cosine = cos(angle);
float sine = sin(angle);

// Compute dimensions of the resulting bitmap, but now using four points and transforming these

int cx = width/2; //point of rotation
int cy = height/2;

int x0 = (int)(0 – cx); //four points minus point of rotation
int y0 = (int)(0 – cy);
int x1 = (int)(width – cx);
int y1 = (int)(0 – cy);
int x2 = (int)(width – cx);
int y2 = (int)(height – cy);
int x3 = (int)(0 – cx);
int y3 = (int)(height – cy);
int x0N = (int)(x0 * cosine – y0 * sine) + cx; //transform the points of rotation
int y0N = (int)(y0 * cosine + x0 * sine) + cy;
int x1N = (int)(x1 * cosine – y1 * sine) + cx;
int y1N = (int)(y1 * cosine + x1 * sine) + cy;
int x2N = (int)(x2 * cosine – y2 * sine) + cx;
int y2N = (int)(y2 * cosine + x2 * sine) + cy;
int x3N = (int)(x3 * cosine – y3 * sine) + cx;
int y3N = (int)(y3 * cosine + x3 * sine) + cy;

int minx = min(x0N,min(x1N, min(x2N,x3N))) ; //find the limiting bounding box
int miny = min(y0N,min(y1N, min(y2N,y3N))) ;
int maxx = max(x0N,max(x1N, max(x2N,x3N))) ;
int maxy = max(y0N,max(y1N, max(y2N,y3N))) ;

//then we do the trick:

int x,y;
for(  y = miny; y < maxy; y++ )
{
for(  x = minx; x < maxx; x++ )
{ //same as in the link
int sourcex = (int)(( x – cx )*cosine + ( y – cy )*sine) + cx; //only consider the point of rotation
int sourcey = (int)(( y – cy )*cosine – ( x – cx )*sine) + cy;


//now find out if point is in the original rectangle using a method finding out if a point is in a triangle

//we use this 2 times to get the point in the rectangle

int intBool1 = pointInTriangle ( x0N,x1N,x2N,y0N,y1N,y2N,x, y) ;
int intBool2 = pointInTriangle ( x2N,x3N,x0N,y2N,y3N,y0N,x, y) ;

//now if point is in triangle1 or triangle 2:

if ( intBool1 == 1 || intBool2 == 1 )
{
if ( bufferX + x>0 && bufferX + x < 256  && bufferY + y>0 && bufferY + y < 192) //if in field
{
index = ((bitmapY + sourcey) * width) + bitmapX + sourcex;
drawPixel(video_buffer_Dest, bufferX + x, bufferY + y, PIXEL(bitmap[index]));
}
}
else //if not in the rectangle restore the old pixel coming from the hidden double buffer
{
u16 backColor = getPixel(video_buffer_Source, bufferX + x, bufferY + y);
drawPixel(video_buffer_Dest, bufferX + x, bufferY + y, backColor );
}
}
}

without blanks, but you see the rotation effect on the paperclip

Ok, eating is the proof of the pudding: (a sketch just showing the rotation of a rather big bitmap to get a good view of the effect)

http://cid-58814201e79976dd.skydrive.live.com/self.aspx/iepro/bitmapRotation%5E_DB.zip

You can see the image is somewhat leaking at the corners, which can possible be solved by restoring from a slightly bigger range from the hidden buffer.

Also looking at the method parameters (far too much!), you see this is crying for a struct “around the image”, having members like

  • imagename (start array of pixels
  • imageWidth
  • imageHeight
  • posX
  • posY
  • rotationAngle
  • rotationPosX
  • rotationPosY



Doubly-Linked List in C

07/01/2010

Since there wasn’t a good Linked List in C, I’ve created one. With a Linked List you can make dynamic array’s without throwing away memory. Normally you have to know the size of an array, but since this isn’t always known (for instance: if it depends on user input) it’s easier to use a Linked List.

It’s using the following concept (doubly linked) which is faster to add/edit/remove from a list:

How to create a list:

You will have to create a Header, this is the first element of the list, it’s the “start point” and “end point” of the list. You can create it like this:

struct CList *list;		// Will be the header
list = malloc(sizeof(struct CList));
CListCreate(list);

Now you can add values to the list (this can also be 32bits pointers). To add values, use the AddLast or AddFirst function:

CListAddLast(1, list);
CListAddLast(2, list);
CListAddLast(3, list);

You can iterate the list using the iterate function. It uses two variables to get it running. The first variable is used to store the current position of the iterator, and the second one is your return variable.

int iter = NULL;	// Empty iterator which stores the position of the iterator
struct CList *item;	// Empty pointer which will be filled using CListIterator
while(item = CListIterator(&iter, list))
{
	printf("val: %d ... \n", item->pointer);
}

To free the memory and destroy the list you can do this:

// Destroy list (and free it)
CListDestroy(list);
printf("size: %d ... \n", CListSize(list)); // Size should be 0
free(list);

Bugs?

Find them, fix them and store them in the comments 🙂

Download:

[ Download ]

Changelog:
– Removed “warnings” 07/01/2010 @ 14.30


New on Iepro: Leo

24/12/2009

Hey der,

ijm nieuw on dis blog joe no wat ij mien?

So I’m one of the students that’s following Iepro, Leo:

Leo

My first plan is to learn a lot more about programming for the nds, and one of the first things I want to produce is a movable button, that is build from an object/image/something.

Today I allready successfully compiled a working example, so I have to learn a lot!


(Quick) C: Data types

24/12/2009

Here a quick table of data types you can use. It’s more C related, but it might be helpfully if you want to put the number “129” in a char.

Type
Bytes
Range
Keyword
(Signed) char
8
-128 to 127
char
Unsigned char
8
0 to 255
unsigned char / u8
(Signed) int
16
-32768 to 32767
int
unsigned int
16
0 to 65535
unsigned int / u16
(Signed) short (int)
8
-128 to 127
short int / short
Unsigned short (int)
8
0 to 255
unsigned short int / unsigned short
(Signed) long (int)
32
-2147483648 to 2147483647
long int / long
Unsigned long (int)
32
0 to 4294967295
unsigned long int / unsigned long / u32
Float
32
3.4e-38 to 3.4e+38
float
Double
64
1.7e-308 to 1.7e+308
double

Memory banks 2

24/12/2009

One of the most elusive subjects of nds programming is the mapping of video memory. When you have found out the configuration you need, most of the time there is no need to change it for a long time so you don’t learn much news about this mapping.

You have to realize that the memory is not equally divided, the main screen has more space than the sub screen. Also the memory is not fixed, you can add more banks if you think you need more space.

on this page: http://dev-scene.com/NDS/NDS_Tutorials_VramTable you can clearly see that the
Main Background can be configured using
VRAM Bank A (VRAM_A) 128KB
VRAM Bank B (VRAM_B) 128KB
VRAM Bank C (VRAM_C) 128KB
VRAM Bank D (VRAM_D) 128KB

The sub screen can only use

VRAM Bank C (VRAM_C) 128KB
and can have

0x06200000 (Sub Background)
but then this C background is not available anymore for the MAIN

what is left: BANK e etc is much smaller. These banks are mainly used for palettes and sprites
and tiles, in a mode we don’t use at the moment.
We are trying to do all in bitmapmode, mode 5.

On this page:
http://dev-scene.com/NDS/DOCgraphicmodes#One_CR_For_Each_Background

you get the same table, but also the functions to set and restore the backgrounds.
Mind the VRAM_X_TYPE….with X = A, B, C, D

with these two pages and some examples the bitmapmode, Mode 5 should be comprehensible.


Three examples on images

12/12/2009

First looking at making backgounds and doing some scribbling.

iepro example backgrounds and scribbling

Using a third screen we let a ball bounce and recover the background from the third screen. The lower screen is slowly replaced by the third screen as the image of the ball on the lower screen is updated. The upper screen shows the normal behavior, where the ball if moving like a sprite.

iepro example bouncing ball

The third example shows a splash, than clicking twice at the lower screen two words are copied to the upper screen and an explanation is given with a special image that serves as a font. This is an imitation of a typewriter where the characters are not on one line anymore.

After the explanation the upper screen is wiped clean and one can choose two other words.

iepro example between lines

There are some tricks shown in these examples:
for instance

  • the way to make your own character set and use it with a transparent color.
  • for instance download this bmp
  • the difference between dmacopy and copying of bits
  • a way to use a double buffer to get a bouncing ball updated
  • <!–


Memory banks example

03/12/2009

The use of Video and Screens in combination with memory pointers like BG_BMP_RAM(0)  , BG_MAP_BASE(0) and vramSetBankA is often unclear when starting with the nds.

I made an example which illustrates the use of the memorybanks and the vramSetBank setting, touching with the stylus on the lower screen.

You can use the HelloWorld example Makefile.

You can experiment commenting out vramSetBankC(VRAM_C_MAIN_BG_0x06040000);
etc
and see what happens.

The prog writes the memory for a screen in one color and then a screen in the next color and a third part of memory in a third color. We steer the “viewing” screen using the touch.px, we “see” the colored memory pass the real screen.

the code in a textfile for a single screen steered by the stylus

the code in a textfile for a double screen: move stylus in x and in y direction

links for vram video and memory:

http://dev-scene.com/NDS/NDS_Tutorials_VramTable

http://www.devkitpro.org/libnds/a00110.html

http://nocash.emubase.de/gbatek.htm#dsvideobgmodescontrol