Log inRegister an accountBrowse CSDbHelp & documentationFacts & StatisticsThe forumsAvailable RSS-feeds on CSDbSupport CSDb Commodore 64 Scene Database
You are not logged in - nap
CSDb User Forums


Forums > C64 Coding > 2D Bitmap rotation with interpolation
2015-07-28 10:27
Trap

Registered: Jul 2010
Posts: 223
2D Bitmap rotation with interpolation

Hi,

I need subject function. I've been doing some goosearching on the subject but so far I only found algorithms that do not use interpolation. So, can some kind soul please point me in the right direction?

So far I only found rotation by shearing to make interpolation but the algorithm i found is too sketchy for me to be able to convert it to something executable.

thanks

Trap
2015-07-28 16:56
Mixer

Registered: Apr 2008
Posts: 452
heh, I wrote a long answer, but time outed. Happens often.

Anyway, shear rotation is about first shearing rows by x depending on the angle and distance to origin. Once that is done, the resulting image columns are shifted same way depending on the angle and distance from origin. Pixels can only be shifted one full pixel at a time, so the pixel movement is quantized. Shear rotation actually works just because of this and the assumption that the pixel is square.

Adding interpolation to above is about subpixels, i.e. the x or y shift by angle is actually some fraction, for instance by 2.4 pixels. In that case, one would shift a row full 2 pixels and then interpolate the color between the adjacent pixels by that 0.4 fraction. Once row shearing is done for the whole image, one would interpolate row colors by fraction and once column shearing is done, one would interpolate y color.

How to do this on c-64? I know how to do shear rotation, but have never tried interpolation. How to shift a bit by a fraction? I guess that in multicolor one can use 00 01 10 11 bit pairs with a gradient color to portray subpixel interpolated fractions and then one could use some lookuptables to do that quickly.

There are demos that have subpixel scrollers and images and there are rotozoomers that use "hidden pixels" to give the impression of interpolation.

Is this on the right track?
2015-07-28 17:01
Trap

Registered: Jul 2010
Posts: 223
Well yes and no. I do understand the theory behind shearing and interpolation but I am not sure if this is the 'best' algorithmic approach (given that I prioritize quality over speed).
2015-07-28 18:04
Oswald

Registered: Apr 2002
Posts: 5094
from the topy of my head:

work with subpixels, that is each pixel's midle is at #.5 so middle of pixel 3,5 is 3.5 and 5.5

now apply rotation keep it all nice floating point, work with pixel's middle point's!!


now after a pixel is rotated you will see how far it is off from the middle point of the pixel it fell into.

now you can use any of the usual texture filter methods to calculate the pixel's color. bilinear, anisotropic, bicubic, etc. all these methods work basically by checking how far you are off from the pixel middle point iirc.
2015-07-28 18:08
Oswald

Registered: Apr 2002
Posts: 5094
ok I see the problem, I guess its a good idea to rotate neighbour pixels and interpolate those according how much each falls off from the middle point of the DST pixel.
2015-07-28 18:10
JackAsser

Registered: Jun 2002
Posts: 2014
Simple z-rotation? Quality before speed? if yes & yes:

From the top of my head:
a = angle;

// UV-vector
ux = cos(a);
uy = sin(a);
vx = -sin(a);
vy = cos(a);

// Center
cx = width/2;
cy = height/2;

for (y=0; y<height; y++) {
    for (x=0; x<width; x++) {
        texel = bitmap[(x-cx)*ux + (y-cy)*uy][(x-cx)*vx + (y-cy)*vy];
        plot(x,y,texel);
    }
}

2015-07-28 18:24
Mixer

Registered: Apr 2008
Posts: 452
If one has 2 squares, one rotated by some angle and puts them on top of each other, they overlap depending on their orientation. Assume one is source and the other is destination.

If these were grids, one destination grid square could overlap with many source grid regions depending on their orientation.

If destination pixel overlaps with many "rotated" grid pixels, what should the destination pixel color be set to?
2015-07-28 18:38
ChristopherJam

Registered: Aug 2004
Posts: 1409
Well, it's basically a resampling problem.

99% of texture mapping hardware just does bilinear interpolation of the original texture (at least for the instance where there is no scaling, only rotation in the 2d plane), so all you're doing is computing for each destination pixel a fractional position in the source texture, then interpolating the colours from the four corners of the square you land in.

Photoshop defaults to using bicubic interpolation for resampling images instead, which works well for photographs but can overshoot for anything with hard edges..

Here, have some code for reading from sub-pixel locations using bilinear:
http://www.scratchapixel.com/old/lessons/3d-advanced-lessons/in..
http://rosettacode.org/wiki/Bilinear_interpolation


Replace the texel = bitmap... line from JackAsser's post above with one of the routines just linked, and there you go.
2015-07-28 23:04
Trap

Registered: Jul 2010
Posts: 223
this is excellent. Thank you guys.

I will take a look at all the great info tomorrow.

/Trap
2015-07-29 09:10
Axis/Oxyron
Account closed

Registered: Apr 2007
Posts: 91
Basically what JackAsser said.

If you do the interpolation with floating point or fixed point with atleast 16 fraction bits, your rendering should be subpixel and subtexel correct.
In simple words: When zooming into the image, your texels build correct rotated quads without any artifacts at the texel-borders. And If you move or rotate slowly the texel-borders move smoothly and do not jump full pixel-wise.

If you are there, you need to solve the resampling problem.

There are 2 possible ways: antialias or trilinear filtering.

Antialias is very CPU-intensive, because it just means to calculate the effect in a virtual higher resolution and accumulate all the calculated sub-pixels.

The triliniear filtering approach (or gfx-card-approach) is a combination of bilinear filtering and mip-mapping.

In bilinear filtering a 2x2 array of texels around the UV texel coordinate is fetched from the texture. These 4 texel colors are then linear interpolated based on the fraction of U and V. E.g. first interpolate the 2 left and the 2 right texels based with the V-fraction and then interpolate the 2 results based on the U-fraction.

Linear interpolation just means: result=value1+(value2-value1)*fraction.

In Mip-mapping a pyramid of textures is calculated. Every next mip-map has half the resolution on both axes (E.g. 16x16, 8x8, 4x4, 2x2, 1x1). The correct mip-map is choosen from the zoom-scale. This avoids the usual flickering on zooming out.

In trilinear filtering you just do the bilinear filtering for 2 succeeding mip-maps and again linear interpolate the results based on the fraction of your mip-map choose parameter (zoom-scale). This last interpolation removes the popping that appears when switching between mip-maps.

Major drawback of this algorithm is that the resulting image gets a little bit blurry.
If you use the tools from Microsoft or NVidia to generate your mip-maps, they do some extra magic (something like a sharpening filter) to overcome that problem.
2015-07-29 22:31
HCL

Registered: Feb 2003
Posts: 728
Excuse me sir, this is far off-topic from anything c-64 related. Impossible to code in 8 bits and far too many multiplications to be calculated in more than a 4x4 pixel screen.

What i'm trying to say is.. i wish i knew stuff like this, and it is very interesting reading!! Why didn't i do some 10 years in the Amiga or PC-sceen!? Then perhaps i would have known something about common computer graphics :P. Give me my life back!! ;)
2015-07-30 04:03
Oswald

Registered: Apr 2002
Posts: 5094
even a 060 amiga is not powerfull enough :) well, maybe a cube :)
2015-07-30 06:49
Axis/Oxyron
Account closed

Registered: Apr 2007
Posts: 91
I guess, if quality is the most important goal, the intention was more about making PC-tools to generate animations or tables than realtime rendering.
2015-07-30 06:59
Oswald

Registered: Apr 2002
Posts: 5094
scripting a paint editor to rotate a picture can do that
2015-07-30 07:18
Axis/Oxyron
Account closed

Registered: Apr 2007
Posts: 91
Hehe, but scripting a paint editor is half the fun. ;o)

And true, 060 is not fast enough for this. Tried it back in the 90´s. The muls are not the problem. But 060 is slow on memory. So accessing 8 texels per pixel is not a good idea at all. When zooming out or your poly rotates 90° everything breaks down, due to bad cache coherence.
2015-07-30 07:34
Shine

Registered: Jul 2012
Posts: 369
Maybe offtopic:
FU-Script / GIMP is most powerful! ;)
2015-07-30 08:13
ChristopherJam

Registered: Aug 2004
Posts: 1409
Quote: Hehe, but scripting a paint editor is half the fun. ;o)

And true, 060 is not fast enough for this. Tried it back in the 90´s. The muls are not the problem. But 060 is slow on memory. So accessing 8 texels per pixel is not a good idea at all. When zooming out or your poly rotates 90° everything breaks down, due to bad cache coherence.


Heh, improved cache coherence is half the reason the memory layout the PS2 uses for texture ram is such a bastard; they interleave the address bits to ensure that neighbouring texels are usually in the same set of cache lines regardless of orientation.

(of course, then they lightly scattered things a little to try and avoid multiple TMUs from trying to read the same word at the same time, but I digress.. Google ps2 texture swizzling if you want to melt your brain)
2015-07-30 08:25
Trap

Registered: Jul 2010
Posts: 223
Sorry to take this back on to the original subject :)

I am not sure how I should read this. Mind you, I'm not particularly good at math and university was lightyears ago.

So, how exactly do I read this line:

texel = bitmap[(x-cx)*ux + (y-cy)*uy][(x-cx)*vx + (y-cy)*vy];

I believe [] means 'absolute', so unsigned right?

however, I'm not seeing an operator between the two sets of []. I'm guessing this implies something - just not sure what? My guess would be x and y coordinates respectively (of the source bitmap). On track?
2015-07-30 08:35
Shine

Registered: Jul 2012
Posts: 369
Quoting Trap

So, how exactly do I read this line:
texel = bitmap[(x-cx)*ux + (y-cy)*uy][(x-cx)*vx + (y-cy)*vy];
I believe [] means 'absolute', so unsigned right?


I am unsure right now ... but [][] seems to me like the dimensions of an array (possibly list).
2015-07-30 08:35
ChristopherJam

Registered: Aug 2004
Posts: 1409
In this instance, [] means array access.

so texel[y][x] is like

peek(texture_address+y*texture_width+x)

(assuming one byte per pixel..)

I suspect it was also intended to be

[cy+(x-cx)*ux + (y-cy)*uy][cx+(x-cx)*vx + (y-cy)*vy]

to get a rotation around the centre of the texture.
2015-07-30 17:21
Axis/Oxyron
Account closed

Registered: Apr 2007
Posts: 91
@ChristopherJam: Yes, swizzling or tiling of the texture would have helped on the 060. I think all modern AGA demo-engines do that. I even heard of some S3-style texture compression mappers.
2015-07-30 21:52
Trap

Registered: Jul 2010
Posts: 223
Thank you all for your help. I believe I have enough to keep me up for the next couple of evenings :)

/Trap
RefreshSubscribe to this thread:

You need to be logged in to post in the forum.

Search the forum:
Search   for   in  
All times are CET.
Search CSDb
Advanced
Users Online
goto80/HT
csabanw
Guests online: 100
Top Demos
1 Next Level  (9.7)
2 13:37  (9.7)
3 Mojo  (9.7)
4 Coma Light 13  (9.6)
5 Edge of Disgrace  (9.6)
6 What Is The Matrix 2  (9.6)
7 The Demo Coder  (9.6)
8 Uncensored  (9.6)
9 Comaland 100%  (9.6)
10 Wonderland XIV  (9.6)
Top onefile Demos
1 No Listen  (9.6)
2 Layers  (9.6)
3 Cubic Dream  (9.6)
4 Party Elk 2  (9.6)
5 Copper Booze  (9.6)
6 Dawnfall V1.1  (9.5)
7 Rainbow Connection  (9.5)
8 Onscreen 5k  (9.5)
9 Morph  (9.5)
10 Libertongo  (9.5)
Top Groups
1 Performers  (9.3)
2 Booze Design  (9.3)
3 Oxyron  (9.3)
4 Triad  (9.3)
5 Censor Design  (9.3)
Top Musicians
1 Rob Hubbard  (9.7)
2 Mutetus  (9.7)
3 Jeroen Tel  (9.7)
4 Linus  (9.6)
5 Stinsen  (9.6)

Home - Disclaimer
Copyright © No Name 2001-2024
Page generated in: 0.072 sec.