Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » matrix_sprite()

This thread is locked; no one can reply to it. rss feed Print
matrix_sprite()
Kibiz0r
Member #6,203
September 2005
avatar

So, I thought I was doing myself a favor by providing a common interface for drawing, scaling, rotating, shearing, and allowing for hierarchical drawing by concatenating matrices.

Turns out, I've created a monster instead.

Here's the code for matrix_sprite()

1typedef boost::numeric::ublas::matrix<double> Mat;
2 
3void matrix_sprite(BITMAP* bmp, BITMAP* sprite, Mat& m)
4{
5 Mat to(3, 1);
6 to.clear();
7 Mat from(3, 1);
8 from(1, 0) = 0;
9 from(2, 0) = 1;
10 for (int i = 0; i < sprite->h; i++, from(1, 0)++)
11 {
12 from(0, 0) = 0;
13 for (int j = 0; j < sprite->w; j++, from(0, 0)++)
14 {
15 to = prod(m, from);
16 _putpixel(bmp, (int) to(0, 0), (int) to(1, 0), _getpixel(sprite, j, i));
17 }
18 }
19}

I probably misused _putpixel and _getpixel; this is my first time doing this low-level stuff.

It takes a 3x3 matrix that represents 2d position, along with rotation, scaling, and shearing. It multiplies that matrix and the 3x1 from matrix, which grabs pixels from the sprite, to get a 3x1 matrix that represents the position on the buffer to draw the pixel to.

It is, however, quite slow.

1969ms for 100 calls to matrix_sprite()
vs
31ms for 100 calls to rotate_scaled_sprite()
(no optimization)

2 problems:

1) The call to prod (a Boost/uBLAS function) is ridiculously expensive.

If I comment out just that line, it costs only 219ms to make the call. 9x faster.

2) Scaled sprites don't get interpolated at all, so they show up as just as many pixels

{"name":"524883949_0857a844fa_o.png","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/d\/7\/d777046dce63597efff50b74cc17b66d.png","w":806,"h":632,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/d\/7\/d777046dce63597efff50b74cc17b66d"}524883949_0857a844fa_o.png

vs.

{"name":"524804670_0e5207cffb_o.png","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/6\/a\/6a67b70ea224c0d1c7685222985bf77a.png","w":806,"h":632,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/6\/a\/6a67b70ea224c0d1c7685222985bf77a"}524804670_0e5207cffb_o.png

So.

  • Find another matrix library?

  • Scrap the function and just use rotate_scaled_sprite and keep a bunch of extra data members handy?

  • Apply one of those magical algorithms that everyone but me knows about and achieve a call time of -1 ms?

  • Await the apocalypse and just forget about this "programming" stuff?

Kris Asick
Member #1,424
July 2001

Considering all the trouble you're going through, I think perhaps you should just switch to AllegroGL or OpenLayer. They provide hardware acceleration and thus will get around some of the issues you're describing without having to do all the work you're doing.

For what you want, OpenLayer is a better, easier choice. AllegroGL will give you much more control but you'll have to do much of it manually using the OpenGL state system.

--- Kris Asick (Gemini)
--- http://www.pixelships.com

--- Kris Asick (Gemini)
--- http://www.pixelships.com

Kibiz0r
Member #6,203
September 2005
avatar

Hm. I suppose OpenLayer looks good. I've been wanting to give AllegroGL a try for a while, too...

The main thing I would like to accomplish by taking a leap like that, though, is to have some framework code I can plug my logic and rendering into. From the BerliOS description, it claims it's a framework, but I see nothing in the documentation to back that up. Perhaps I have a different expectation of what a "framework" is.

I expected something like

OLSetCallbackFrameMove(MyGame::OnUpdateGame);
OLSetCallbackFrameRender(MyGame::OnRender);

...to appear at some point.

Of course, most of the benefits to this kind of structure are psychological; thinking there's a library there to muscle through the menial labor and give your game the cue when it's time to do what you want to do.

Still, I thought OpenLayer would be to Allegro what the DirectX Framework is to DirectX.

Go to: