Code for Affine Transformation...
Displaying 1-16 of 16 total.
1
Please enter a numerical value for the importance of this sticky.
Enter 0 to unsticky.
Omni

I had this idea for a set of affine transformation functions in Verge that would use an internal matrix. I actually set up a VC version of this but realized that there would be a huge speed increase if this could be hardcoded.

The idea for affine transformations is taken from the GBA's processing of sprites and backgrounds. For examples, you can see the descriptions and breakdown at the Tonc programming tutorials.

Sprites: http://user.chem.tue.nl/jakvijn/tonc/affobj.htm
Backgrounds: http://user.chem.tue.nl/jakvijn/tonc/affbg.htm

At any rate, the cool thing about this is that it would enable the programming to create their own image transformations using an affine matrix. They could add any combination of skew, rotate, scale, even Mode7-perspective-ish stuff.

Benefits.

1. Power. Allows programmer to create any image transformation.
2. Speed. Allows these transformations to be accomplished at C-speed rather than VC-Setpixel speed.



I went and coded an example implementation...it requires two functions, and a few internal global variables to contain the affine transformation matrix.

Unfortunately, I don't have Visual C, and I'm an absolute newbie to real compiling...I don't know how to pull this project together using something such as Dev-C++ (or even if I can).

I made a specification for the functions as well as their vc_library.cpp counterparts. Could someone check and maybe even try this out?

The argument count is kinda high, but...well...maybe I'm just not good at programming design.

My webspace is unaccessible to me right now...could I possibly email it to any interested development maintainer?


/* V3 AFFINE MATRIX
These four variables specify the 2x2 affine transformation matrix.
A B C D = 1 0 0 1 is the identity, where 1 is the equivalent of 1.0 in fixed point.
*/
int V3_AFF_A
int V3_AFF_B
int V3_AFF_C
int V3_AFF_D

/*
If XOff, YOff = 0, 0, then the center of an affine transformation is 0, 0 of the source image.
Changing these set the position in the source image that is centered in the affine transform (at the origin).
*/
int V3_AFF_XOFF
int V3_AFF_YOFF

int V3_AFF_CURY //Used for BGInterrupt displays. Internally updated with the current scanline.
int V3_AFF_SHIFT //A bitshifting value; determines the shift for fixed point on members of the affine matrix.


void dd_AffineBlit(int xpos, int ypos, int dblsize, int trans, int obeyrect, image *srcimg, image *OBimg, image *destimg)
/*
Based on the GBA affine sprite transformations.
Affine transformation of an image to the destination image using
the V3 affine matrix. Obeys the destination clipping rectangle and
_can_ obey the rectangle of the source.
*/

void dd_AffineInt(int xpos, int ypos, int dblsize, int trans, int obeyrect, string func_name,
image *srcimg, image *OBimg, image *destimg)
/*
Same as AffineBlit, but allows for a user-specified VC function
to be executed once every scanline BEFORE rendering begins.
Also keeps track of the current Y scanline rendered, so
scanline-dependent affine transforms can be accomplished
through this function
with use of a given VC "interrupt" function. (ex, Mode7-esque).
*/

Posted on 2005-12-22 23:00:29

Omni

Let me rephrase that. I have actually written the C++ code for the functions...but I don't know how to put it in myself.

Posted on 2005-12-23 08:28:29

Jesse

I think an affine transform is a great idea! How were you intending to have this available via VC? I would be in favour of something OpenGL style. What were you thinking of?

As for the code itself, I'd suggest chatting with one of the windows-devs to get Visual Studio Express up and running, so you can try it out yourself.

Posted on 2005-12-23 08:51:30

Omni

I don't quite know what OpenGL's version of affine transform is like, and I'm not entirely sure we're thinking of the exact same thing, if indeed we're discussing an OpenGL version...I'm currently trying to look up some OpenGL docs now...if we're talking about "affine transform" as in the affine-mapped polygon, then I'm afraid this certainly isn't it (though it is indeed a good idea...hmm...)

Er...I just did a quick search through the OpenGL spec for "affine" and didn't find anything of notice...so I'm not quite sure what OpenGL's affine transform capability is.

EDIT: I found something on affine transformation here: http://www.cosc.brocku.ca/Offerings/3P98/course/lectures/2d_3d_xforms/. Generally I know the term "affine transformation" to mean such a transformation that preserves parallel lines and changes the coordinate system...so...pretty much, take OpenGL's affine matrix capabilities, but remove the 3rd dimension.



Anyway, the style here is inspired directly by the GBA's affine capabilities, and is quite simple: we have a source image, we have a destination, and we have the transformation matrix (a simple 2x2). The transformation matrix takes a position in the destination matrix and transforms it to look up the correct pixel in the source image. Simple as that. Quite simple. It becomes more impressive when we can create our own transformations by altering the matrix, and by creating scanline-specific transformations (using the AffineInt() function).

One minor problem -- AffineInt() requires being able to call

vc->ExecuteFunctionString()

So as to call the user-specified VC "interrupt" function. I hope that's alright...



Implementation requires eight global variables (of the V3_AFF_* nature): 4 elements for the two by two matrix, 2 for the X/Y offset into the source image, and the two functions themselves.

The programmer sets the affine matrix as he wishes (I've created some VC routines to transform 2x2 matrices as I see fit, which are very useful...you could of course set the matrix by hand) then calls the AffineBlit or AffineInt functions with the correct parameters. That's it.

For each unique affine transform, you'd have to reset the matrix. It is somewhat advanced for a VC-newbie, but it can allow you to do very powerful things with images without having to bother with SetPixel.



What is Visual Studio Express? Time to google...

Posted on 2005-12-23 09:22:23 (last edited on 2005-12-23 09:28:27)

Jesse

Quote:
Originally posted by Omni

The programmer sets the affine matrix as he wishes (I've created some VC routines to transform 2x2 matrices as I see fit, which are very useful...you could of course set the matrix by hand) then calls the AffineBlit or AffineInt functions with the correct parameters. That's it.



Sorry; I should have been more explicit what I meant about OpenGL. I was trying to get at your point above; how the VC can manipulate the matrix. I would be in favour of something (OpenGL-like) where you could call methods such as:

AffineIdentity(); // resets affine transform
AffineScale(int x_scale, int y_scale); // adds a scale transform
AffineRotate(int deg, int x_center, int y_center); // adds a rotation transform
AffineTranslate(int x, int y); // adds a translation
AffineSet(...); // set all the matrix values
(etc.)


And then your AffineBlit function, which uses the matrix they've set up with the other calls. I'm not exactly sure what AffineInt is doing; you're calling the interrupt function for each scanline of the dest image? Is this useful for anything other than Mode7? (Because if not, we should just support Mode7 directly, and give the ability to tile the image, etc.)

One last thing. I'm used to 2D affine transforms being represented by 3x3 matrices (homogeneous coordinates.) This lets you represent translations in the matrix with the other transforms, and so (I think) simplifies some of the implementation.

Posted on 2005-12-23 10:20:28

Omni

Aha. My VC set for controlling the affine matrix is very similar to what you suggest (Rotate, Scale, Skew, Set, Identity, Multiply, Inverse functions, etc). This _could_ be hardcoded...it isn't strictly necessary that it be so, and I suppose this would be a developer preference.

AffineInt does exactly what you think it does -- it simply calls the Interrupt function every scanline _before_ normal affine matrix rendering. Allowing you to modify the affine matrix each scanline. The only _direct_ use I can think of this is indeed Mode7-esque transformations; however, it is certainly possible to create your own special scanline-dependent transformations (what these would be I do not know, but it _would_ be possible).

This is also used because it would be somewhat redundant to have two functions sets, one for affine transforms and one for Mode7 transforms, when they both basically do the exact same thing (and having Mode7 transforms alone would of course be less flexible, when having the affine transforms would enable Mode7-esque transforms and so much more). That's why I suggested it be incorporated into the affine capability instead of a separate Mode7 functionality.

As for incorporating translations into the matrix: I believe this would be possible. So a 3x3 matrix would indeed be possible.

For some reason I prefer not to have the internal affine matrix be an array. So I would suggest

V3_AFF_A, V3_AFF_B, V3_AFF_C
V3_AFF_D, V3_AFF_E, V3_AFF_F
V3_AFF_G, V3_AFF_H, V3_AFF_I

This would require me to recode the Affine functions slightly, as I did not originally account for a 3x3 transform. I'm still relatively new to this, but I believe I could do that.

Note that incorporating this would remove the need for V3_AFF_XOFF and V3_AFF_YOFF, as they would be incorporated into the matrix.

I am looking into Visual Studio Express now. It seems quite spiffy. When I get some time in the next few days, I will attempt to compile pure Verge3, and then try to add the affine capability.

Posted on 2005-12-23 10:40:48

CrazyAznGamer

Awesome.
In any case, this would really help those VERGE developers out there wanting to make a Mario Kart Klone. :D
(Not me, just clarifying, though it'd be cool to see somebody do it.)

Example of scanline dependent transformation (that I can recall): death sequence of the Phantoom in Super Metroid.

Interesting articles. I'm wondering if the capabilities are really worth the time, but it's cool, so how bad can it be?
*cough* (>_> next thing you know, hardcoded particles) *cough*
Excuse my cold.

Posted on 2005-12-23 11:35:01

blues_zodiakos

Interestingly enough, I'm already studying hardcoded particles...

Posted on 2005-12-23 12:42:18

Overkill

Quote:
Originally posted by Omni

I am looking into Visual Studio Express now. It seems quite spiffy. When I get some time in the next few days, I will attempt to compile pure Verge3, and then try to add the affine capability.



When you do download Visual C++ Express 2005, you'll need the DirectX 9 SDK, and the Microsoft Platform SDK as well. Then it should compile.

Then to add builtins, you just, open vc_builtins.cpp and add stuff to the function hash table, open vc_library.cpp and add your functions to the switch statement (look at examples of other library functions to figure out how arguments/returns are handled), open up opcodes.h, change the function count, and compile and you're set!

Posted on 2005-12-23 19:08:20

vecna

Im curious what you mean by you already have the C++ code. Adding VC functions is fairly easy.. adding a blitter builtin is quite a bit harder, since theoretically you need like 6 different versions of each blitter. Tho that's not to say you can't just write one slow version.

Posted on 2005-12-23 19:38:48

CrazyAznGamer

I figured it was that easy, but what about builtin variables?

Hehehe, as soon as I can compile this, I'll be addin a couple of SuperSecretThingy(int,int,int,int,int)s of my own. ;D

Posted on 2005-12-23 22:28:33

Omni

Vecna: I basically mean I already wrote a slow C++ version of the blitter using PutPixel. I just wanted to test it out. Er...which I'll try to do. Soon. Hope that's alright.

Overkill: I figured it was...something like that. Another question though. How can I add built-in global variables that are accessible from the VC side?

Posted on 2005-12-24 10:27:58 (last edited on 2005-12-24 10:29:08)

Overkill

The variable handling code is in vc_core.cpp, under VCCore::ReadInt and VCCore::WriteInt, and you probably do something similar with opcodes.h and the vc_builtins.cpp. I'm not sure what you'd do for strings though.

Posted on 2005-12-24 12:09:32

Omni

Hey, thanks. I really like the comment that I found in the struct processing code HandleAssign() under vc_compiler.cpp: "Might wanna grab a coke before you try to figure this out..." Not sure why but that struck me as very amusing.

Posted on 2005-12-24 12:31:57

Gayo

This would be sexy as hell.

Posted on 2005-12-26 14:16:10

Omni

Just so we're clear, I'm at my third attempt trying to download the DirectX SDK. Bloody 4 hour download and having to clear games off my harddrive to make room for all this stuff. Sure seems like overkill just to add maybe 300 lines of code.

Posted on 2005-12-30 14:14:20


Displaying 1-16 of 16 total.
1
 
Newest messages

Ben McGraw's lovingly crafted this website from scratch for years.
It's a lot prettier this go around because of Jon Wofford.
Verge-rpg.com is a member of the lunarnet irc network, and would like to take this opportunity to remind you that regardless how babies taste, it is wrong to eat them.