2d sprite manager, for Ogre

Discussion area about developing or extending OGRE, adding plugins for it or building applications on it. No newbie questions please, use the Help forum for that.
User avatar
hmoraldo
OGRE Expert User
OGRE Expert User
Posts: 517
Joined: Tue Mar 07, 2006 11:22 pm
Location: Buenos Aires, Argentina
x 1

2d sprite manager, for Ogre

Post by hmoraldo »

edit 10/16: removed code from here, now only in the wiki to avoid code duplication in forums and wiki

This is a small code snippet, a small solution to an old issue in Ogre: lack of a simple way of drawing 2d objects to the screen, the old way. Maybe for programming a hud, maybe for doing a small mini game inside a bigger 3d game, maybe just for using Ogre for 2d programming.

Overlays are nice, and Cegui is nice, but they aren't versatile enough if you want to program, say, a Tetris, or a Mario game. Not that Ogre doesn't allow you to program in 2d using 3d primitives: but you have to use the hardware buffers, and that's a lot of hard work.

The code snippet I present here allows you to blit sprites to screen, just as you did in the old times of DirectDraw, o even before, in the days of memory copying for Dos games.

First, the code, and then some extra information about its use (in the next post):

(CODE REMOVED to avoid code duplication in forums and wiki: go to the code snippet here: http://www.ogre3d.org/wiki/index.php?ti ... eManager2d for the last version)


Hope you like it.

Best regards!
Last edited by hmoraldo on Mon Oct 16, 2006 3:37 pm, edited 4 times in total.
H. Hernan Moraldo
Personal website
User avatar
hmoraldo
OGRE Expert User
OGRE Expert User
Posts: 517
Joined: Tue Mar 07, 2006 11:22 pm
Location: Buenos Aires, Argentina
x 1

Post by hmoraldo »

Some important stuff about this code:

- Initialize the wrapper in your setup code
- End the wrapper when you are not going to use it anymore
- Once per frame, at frame start, you can use sprite blits to draw 2d figures on the screen... actually those are buffered and, at render time, they are sent to the hardware buffers and rendered. Of course, the buffer is cleared as soon as it's rendered to the screen... don't expect sprites to be persistent as meshes are in Ogre, sprites are not! you decide what to blit to the screen every frame, and each time it can be a different amount of sprites.
- The textures you use for your sprites have to be already loaded in the ogre system to work. This is important! otherwise you'll be warned with an exception.

I think with this should be enough to start coding with the wrapper.

Best regards,
H. Hernan Moraldo
Personal website
User avatar
steven
Gnoll
Posts: 657
Joined: Mon Feb 28, 2005 1:53 pm
Location: Australia - Canberra (ex - Switzerland - Geneva)

Post by steven »

Nice idea.

Could you put it on wiki or it will be quickly lost in the forum depth?

Steven
User avatar
hmoraldo
OGRE Expert User
OGRE Expert User
Posts: 517
Joined: Tue Mar 07, 2006 11:22 pm
Location: Buenos Aires, Argentina
x 1

Post by hmoraldo »

Ok, I posted it here: http://www.ogre3d.org/wiki/index.php/SpriteManager2d

And also put some extra info there.

Thank you!
H. Hernan Moraldo
Personal website
3dmacuser
Greenskin
Posts: 128
Joined: Tue Mar 22, 2005 8:18 pm

Post by 3dmacuser »

Sounds really cool!

Is there any way to modify it so that the images don't have to be previously loaded, and can come out of memory instead?

As an example, I want to render my GUI using a web framework so that the whole gui is CSS/javascript/html. I'll be rendering the gui to a bitmap in memory, and then I'd like to blit this to the screen in Ogre.

Would this be possible with your sprite manager?
User avatar
hmoraldo
OGRE Expert User
OGRE Expert User
Posts: 517
Joined: Tue Mar 07, 2006 11:22 pm
Location: Buenos Aires, Argentina
x 1

Post by hmoraldo »

Sure you can use the manager with dynamic textures. Check this: http://www.ogre3d.org/wiki/index.php/Cr ... c_textures

But are you sure you need that? why not draw your layouts directly with 2d sprites, as you would usually do when programming a 2d gui in any 2d api?

Best regards!
H. Hernan Moraldo
Personal website
3dmacuser
Greenskin
Posts: 128
Joined: Tue Mar 22, 2005 8:18 pm

Post by 3dmacuser »

Thanks, I'll look into the dynamic textures.

I want to use CSS/javascript/DHTMl so that I don't have to remake the GUI. I can use a whole bunch of javascript libraries that are already out there for use in web pages.

And now, making the GUI for the game is as simple as making a webpage! In addition, flash, etc would all work right away.

Thanks!
pasman
Gnoblar
Posts: 14
Joined: Thu Jan 12, 2006 4:42 pm
Location: Cluj, Romania

Post by pasman »

Hi, i don't know if this is a general issue but was in my case. When displaying 2 sprites from the same texture there was a problem due to the operation type so i changed it from Ogre::RenderOperation::OT_TRIANGLE_STRIP in Ogre::RenderOperation::OT_TRIANGLE_LIST in Ogre2dManager::createHardwareBuffer method and worked ok.
User avatar
hmoraldo
OGRE Expert User
OGRE Expert User
Posts: 517
Joined: Tue Mar 07, 2006 11:22 pm
Location: Buenos Aires, Argentina
x 1

Post by hmoraldo »

You are right... I had corrected it in my code but forgot to do it here. Now I corrected both the code here and in the wikis.

Thank you!
H. Hernan Moraldo
Personal website
lmas19820607
Halfling
Posts: 72
Joined: Wed Dec 06, 2006 7:35 am

Post by lmas19820607 »

When I use this to draw, it draw above the CEGUI's window. That's not what I want, can I control the render sort?

And can the Sprite render before the scene?

I know there is a param about that.
void init(Ogre::SceneManager* sceneMan, Ogre::uint8 targetQueue, bool afterQueue);

But when I change targetQueue's value to a smaller value than RENDER_QUEUE_OVERLAY, it dosn't show any thing
pasman
Gnoblar
Posts: 14
Joined: Thu Jan 12, 2006 4:42 pm
Location: Cluj, Romania

Post by pasman »

Hi, to fully control your drawing order you'll need to add a depth component to the sprite structure, pass it through the spriteBlt method and sort your sprite accordingly. That will allow you to specify the draw order for each of your sprites.

As for the overall draw order try initializing Ogre2d after CeGUI (or vice-versa, depending on your choice :) ) .

Hope that helps
User avatar
hmoraldo
OGRE Expert User
OGRE Expert User
Posts: 517
Joined: Tue Mar 07, 2006 11:22 pm
Location: Buenos Aires, Argentina
x 1

Post by hmoraldo »

Both for cegui and for the 2d sprite manager you can decide what queue to use. If you are not using overlays, you can set both to RENDER_QUEUE_OVERLAY, and start cegui telling it to go after queue (I think it's the default behaviour), and the 2d manager with afterQueue=false.

In that case, the 2d manager will render first, then overlays, then Cegui.

If you use values different than RENDER_QUEUE_OVERLAY for the queue, I think you have first to tell ogre to create it.

Varying the initialization order wouldn't solve your problem, as it wouldn't affect the rendering order for cegui and the 2d sprite man.

Hope it helps,
H. Hernan Moraldo
Personal website
lmas19820607
Halfling
Posts: 72
Joined: Wed Dec 06, 2006 7:35 am

Post by lmas19820607 »

hmoraldo, thank you very much.
I do what you tell, and it works well.
lmas19820607
Halfling
Posts: 72
Joined: Wed Dec 06, 2006 7:35 am

Post by lmas19820607 »

I was going on my work and met new problem.

When I use Sprite2DManager to draw, I can't draw with clear pixel.
All the pixels looks unclearly. And when I use openGL RendererSystem, what is strange, it shows more clearly than D3D, but not clearly enough.

I wrote this for test:
m_ogre2dManager->spriteBltFull("test.png", -1.0, 1.0, 1.0, -1.0);

test.png is a 1024 * 768 png file, and my OgreApp start with 1024 * 768 *32bit video mode.

Could it be showed clearly just like DDraw did ?
User avatar
hmoraldo
OGRE Expert User
OGRE Expert User
Posts: 517
Joined: Tue Mar 07, 2006 11:22 pm
Location: Buenos Aires, Argentina
x 1

Post by hmoraldo »

Check Sinbad's comment here: http://www.ogre3d.org/phpBB2/viewtopic. ... engl+pixel

Best regards,
H. Hernan Moraldo
Personal website
lmas19820607
Halfling
Posts: 72
Joined: Wed Dec 06, 2006 7:35 am

Post by lmas19820607 »

Thank you very much.
It helps, but it is not clear enough.
This is the source picture.
Image
This is the OgreD3DMode screen capture.
Image
This is my code.
RenderSystem* rs = Root::getSingleton().getRenderSystem();
Viewport* vp = rs->_getViewport();
Real hOffset = rs->getHorizontalTexelOffset() / (0.5 * vp->getActualWidth());
Real vOffset = rs->getVerticalTexelOffset() / (0.5 * vp->getActualHeight());
m_ogre2dManager->spriteBltFull("test.png", -1 + hOffset, 1 - vOffset, 1 + hOffset, -1 - vOffset);
lmas19820607
Halfling
Posts: 72
Joined: Wed Dec 06, 2006 7:35 am

Post by lmas19820607 »

I found that when I set all TextureUnitFilter to FO_NONE, it looked clearly.
But it still isn't as clear as the source picture.

And I found that the vertical line looked good, but the horizontal line looked bad. So it must be something wrong with y axis.

Then I tried OpenGL mode, which has no TexelOffset, the result is same. So I think the problem is nothing about the texelOffset.

This is all my relative code.
void Ogre2dManager::prepareForRender()
{
...
rs->_setTextureUnitFiltering(0, Ogre::FO_NONE, Ogre::FO_NONE, Ogre::FO_NONE);
...
}

Ogre::RenderSystem * rs = Root::getSingleton().getRenderSystem();
Viewport* vp = rs->_getViewport();
Real hoffset = rs->getHorizontalTexelOffset() / (0.5 * vp->getActualWidth());
Real voffset = rs->getVerticalTexelOffset() / (0.5 * vp->getActualHeight());

m_ogre2dManager->spriteBltFull("test3.png", -1 + hoffset, 1 - voffset, 1 + hoffset, -1 - voffset);
User avatar
hmoraldo
OGRE Expert User
OGRE Expert User
Posts: 517
Joined: Tue Mar 07, 2006 11:22 pm
Location: Buenos Aires, Argentina
x 1

Post by hmoraldo »

It seems you found the solution here already: http://www.ogre3d.org/phpBB2/viewtopic. ... highlight= (am I right?)
H. Hernan Moraldo
Personal website
User avatar
jestermax
Kobold
Posts: 37
Joined: Tue Jun 27, 2006 8:18 pm
Location: Canada

SpriteManager2D

Post by jestermax »

is there a way to work with the sprite textures in memory? for example, set a colour in the texture to be transparent or perform enhancements to the texture such as a colour invert?
User avatar
hmoraldo
OGRE Expert User
OGRE Expert User
Posts: 517
Joined: Tue Mar 07, 2006 11:22 pm
Location: Buenos Aires, Argentina
x 1

Post by hmoraldo »

What you need to do if you need that, is to lock your textures and write to them. Check http://www.ogre3d.org/docs/manual/manual_57.html and check in the code snippets as there are explanations and code of how to modify your textures in real time.
H. Hernan Moraldo
Personal website
Eternius
Gnoblar
Posts: 15
Joined: Fri Aug 11, 2006 9:43 am

Post by Eternius »

Hiya,
This looks to be exactly what I need, however I am having trouble putting it to use because I am very much a newbie with Ogre. Any chance an a sample project demonstrating use?

I also have two questions regarding this. Firstly, the textures are referenced by filename when drawing. Is it not slow to pass a string as an argument to the (potentially heavily used) blit function? Could I replace it by some sort of numeric handle? Secondly I saw complaints about loss of pixel-perfect quality at non power of 2 textures. How would I automate the creation of a larger texture to fit these? I read somwhere that Ogre does this automatically and this is somehow the cause of the quality loss. This makes no sense to me; I have in a previously used engine loaded any size images onto larger power of 2 textures and drawn them at pixel perfect quality with no problems.

Thanks in advance!
User avatar
hmoraldo
OGRE Expert User
OGRE Expert User
Posts: 517
Joined: Tue Mar 07, 2006 11:22 pm
Location: Buenos Aires, Argentina
x 1

Post by hmoraldo »

Eternius wrote:Any chance an a sample project demonstrating use?
Sorry I haven't a sample project for this.
Eternius wrote:Firstly, the textures are referenced by filename when drawing. Is it not slow to pass a string as an argument to the (potentially heavily used) blit function?
I could have used references to strings (I guess I forgot to), but anyway the code later does some string copies, and other stuff like that. Anyway, it won't make a difference unless you do a real huge amount of blits per frame. I think these would be very special needs, not the case for this simple sprite manager.

Yes, you can use a numeric handle if you want.
Eternius wrote:How would I automate the creation of a larger texture to fit these? I read somwhere that Ogre does this automatically and this is somehow the cause of the quality loss. This makes no sense to me; I have in a previously used engine loaded any size images onto larger power of 2 textures and drawn them at pixel perfect quality with no problems.
First, this is only a problem if your video card (or your user's) doesn't support non-power of two textures. Second, to do this I guess you'd have to create a texture by yourself, with power of two dimensions, and do a manual initialization of its contents. But it is a lot of work for something that, otherwise, Ogre handles by itself.
H. Hernan Moraldo
Personal website
Eternius
Gnoblar
Posts: 15
Joined: Fri Aug 11, 2006 9:43 am

Post by Eternius »

Thank you for the answers.
I'm still having no luck whatsoever putting this to use...

Edit: here's what I'm doing..
I took the framework of basic tutorial 4 on the wiki, and added the code for 2d sprite manager to the header file and cpp file, followed by original tutorial code.
Load a texture on createScene
Attempt to blit a sprite on frameStarted
Call sprite manager init code on TutorialFrameListener creation

When running it crashes. After prodding around I found that I get the same crash if I completely comment out the sprite manager init code, so I'm guessing I didn't place it where it should be?
User avatar
hmoraldo
OGRE Expert User
OGRE Expert User
Posts: 517
Joined: Tue Mar 07, 2006 11:22 pm
Location: Buenos Aires, Argentina
x 1

Post by hmoraldo »

What is your problem? Maybe I can help.
H. Hernan Moraldo
Personal website
Eternius
Gnoblar
Posts: 15
Joined: Fri Aug 11, 2006 9:43 am

Post by Eternius »

I edited my previous post with a description of the problem.
The problematic code is here
When it runs, it crashes and breaks in list.h at

Code: Select all

	iterator end()
		{	// return iterator for end of mutable sequence
		return (iterator(_Myhead, this));
		}