Tracker Feature Requests rotate2Dimage - ID: 2207893

Discuss about anything related to the Irrlicht Engine, or read announcements about any significant features or usage changes.
Post Reply
Ulf
Posts: 281
Joined: Mon Jun 15, 2009 8:53 am
Location: Australia

Tracker Feature Requests rotate2Dimage - ID: 2207893

Post by Ulf »

I wanted to have a go at this. It's an old request made by only one person, but I'll try since I have done it for my own project, though I may have some issues to sort out.

This quote is from the tracker page..
hybrid wrote:For the raw 2d methods this might be possible, with GUI elements we'd have to check for proper alignment rules and other stuff, so it seems too complicated ATM. the circle drawing should be possible already with the polygon command, just add enough edges.
True, circle drawing can be done with many polygon vertices.

Here is my take on it so far, please help me improve or fix it.

Here is the function declaration to go in IVideoDriver.h

Code: Select all

virtual ITexture * rotate2DImage(const IImage * image, f32 rotation, const io::path & filename) = 0;
The filename parameter is the name of the file that we would get if we had the texture (including the path I assume?). We need it to give the texture a name in the video driver.

My questions:
1. Should we return *ITexture or *IImage? If we return image we don't need the filename.
More importantly, then it could be implemented in IImage class.

2. Should this also be implemented with *ITexture as an input parameter? The texture will need to be unlocked and made into an image in the function. Then copied into the new image/texture.

3. We can draw circle with draw2DPolygon . But draw2DPolygon only draws regular polygons. Is there any request for drawing an ellipse?

4. Is there any request for a fillPolygon function? (or fill2DVertexPrimitiveList)?
One that can fill regular, non-regular and non-convex polygons with a color, and a texture if we want to go that far (can irrlicht only clip to rect boundaries?)

5. I used f32 for rotation angle, should we use f64?

6. Should the input rotation be in radians or degrees?
I can hear birds chirping
:twisted:

I live in the Eye of Insanity.
CuteAlien
Admin
Posts: 9809
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Post by CuteAlien »

Too tired already to think about it. But if you do a patch for that you might take a look at driver_npot_rotation.patch from
http://www.michaelzeilfelder.de/patches_svn808.htm

This was once a working solution, but for an older Irrlicht so it won't work any more. Not yet a clean patch as it does patch 2 things together (a solution for npot textures). But it might be a starting point.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Rotating images/textures also might not the proper way, instead drawing them rotated should be. Simply because multiple rotations would otherwise completely wreck the original image. Moreover, it's usually much faster to use the GPU for rotations and drawing, while an image rotation would use the CPU mostly. And by using RTT one could also get the rotated texture is absolutely necessary.
Ulf
Posts: 281
Joined: Mon Jun 15, 2009 8:53 am
Location: Australia

Post by Ulf »

Thanks CuteAlien. Thanks hybrid.
hybrid wrote:Rotating images/textures also might not the proper way, instead drawing them rotated should be. Simply because multiple rotations would otherwise completely wreck the original image. Moreover, it's usually much faster to use the GPU for rotations and drawing, while an image rotation would use the CPU mostly. And by using RTT one could also get the rotated texture is absolutely necessary.
Yes I understand. When I saw cutealiens answer and followed the link, that's exactly what I started thinking about.
I have implemented a rotate image type function in my engine at the moment, which is obviously software driven. I have learned first hand about hardware acceleration, or lack of it!
DirectX 9 handles the rotations and fill functions I made the best out of all the drivers. OpenGL is close, but still considerably slower.

Following the link that CuteAlien has shown, I see the solution involves more. I'll need to do it for each video driver, but we can take advantage of hardware acceleration which is a great thing. I don't know yet exactly how to, but I believe I can work it out.
I'll take some time to look and think about it, but I'll try.
hybrid wrote:And by using RTT one could also get the rotated texture is absolutely necessary.
Do you mean that we draw the rotated texture directly from the texture in GPU onto an RTT, and then draw the RTT to screen? All of this happening in hardware.
And we could also copy the rotated texture from the RTT if we wanted to keep it?

*EDIT*
Thanks vitek for the links. I'll have a look. Same to CuteAlien.

PS. Give me a bit of time, I have a few new things to work out. If I get stuck or have no idea I'll ask. But I know how to start for now.
Last edited by Ulf on Sat Dec 05, 2009 4:12 am, edited 2 times in total.
I can hear birds chirping
:twisted:

I live in the Eye of Insanity.
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

You should be able to use the code here or here to get what you want, or at least as a starting point.

Travis
Ulf
Posts: 281
Joined: Mon Jun 15, 2009 8:53 am
Location: Australia

Post by Ulf »

I sorted out my problems with my software version of rotating images.

I'll start working on an Irrlicht implementation of draw2DImage with rotation. I'll implement it for all drivers and submit it.
Should be good. I think! lol. I'm excited. :D

If I can get that working well, then I have a few other things I'd like to implement, such as making a version of draw2DVertexPrimitiveList that can fill polygons, and drawing ellipses. But let's not worry until I get the first bit done.
I can hear birds chirping
:twisted:

I live in the Eye of Insanity.
Ulf
Posts: 281
Joined: Mon Jun 15, 2009 8:53 am
Location: Australia

Post by Ulf »

Thanks for the answer CuteAlien. Works well.
I am implementing it with the draw2DImage that takes a destRect.
So both scaling and rotation can be implemented.

Code: Select all

virtual void draw2DImage(const video::ITexture* texture, const core::rect<s32>& destRect,
 const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect = 0,
 const video::SColor * const colors=0, bool useAlphaChannelOfTexture=false,
 f32 angleInDegree=0.f) = 0;
I need some help.
I have linking errors with the direct3D version.

Code: Select all

Linking...
CD3D9Driver.obj : error LNK2001: unresolved external symbol _D3DXMatrixRotationZ@8
CD3D9Driver.obj : error LNK2001: unresolved external symbol _D3DXMatrixTranslation@16
CD3D9Driver.obj : error LNK2001: unresolved external symbol _D3DXMatrixMultiply@12
..\..\bin\Win32-visualstudio\Irrlicht.dll : fatal error LNK1120: 3 unresolved externals
I originally was thinking about implementing the software driver versions. But now I know they will be practically useless if the rotation is used, or if the destRect is a different size from the sourceRect.
That's why the draw2DImage with a destRect is currently not implemented for the software drivers.

It's easier to do a check in your code for software driver version, and then call the appropriate draw2DImage function.
(Only being able to scale and rotate with the openGL and d3d drivers)

Rescaling and rotating every image on every call to draw2DImage is ridiculous.

But I would still like Irrlicht to have a function that can rotate and scale an IImage or ITexture, returning a pointer to the rotated image or texture.
Maybe it should return an IImage, leaving it up to the user to create a texture if they want and add to the video driver...?

Then at least we have an in-built ability to rotate and scale with any driver. When using the software drivers, if the rotation is not constantly changing, the programmer will be able to keep track of whether the rotation is up to date, and only create a new transformed texture when the rotation changes, dropping the old transformed texture and removing it from the video driver.

Does anyone have a suggestion of where we should put an IImage rotation and scaling function? In the IVideoDriver?

Can anyone help with the linking errors?
I can hear birds chirping
:twisted:

I live in the Eye of Insanity.
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

If you want to do anything near to a solution that could be integrated with the engine you should remove the d3dx calls. That lib is only used for shaders in Irrlicht, all the rest needs to be made differently!
Ulf
Posts: 281
Joined: Mon Jun 15, 2009 8:53 am
Location: Australia

Post by Ulf »

hybrid wrote:If you want to do anything near to a solution that could be integrated with the engine you should remove the d3dx calls.
Ok, thanks.
I used the irrlicht matrix4 class.
So I just changed CuteAliens version into this:

Code: Select all

if (angleInDegree != 0.f)
{
	f32 cx = (vtx[0].Pos.X + vtx[2].Pos.X) / 2;
	f32 cy = (vtx[0].Pos.Y + vtx[2].Pos.Y) / 2;

	core::matrix4 mtrans1;
	core::matrix4 mRotation;
	core::matrix4 mtrans2;
	core::matrix4 mAllTogetherNow;

	mtrans1.setTranslation(core::vector3df(cx, cy, 0.0));
	mRotation.setRotationRadians(core::vector3df(0.0, 0.0, core::degToRad(angleInDegree)));
	mtrans2.setTranslation(core::vector3df(-cx, -cy, 0.0));
	mAllTogetherNow = mtrans1 * mRotation * mtrans2;

	pID3DDevice->SetTransform( D3DTS_WORLD, (D3DMATRIX*)((void*)mAllTogetherNow.pointer()) );
} 
No link errors now. Works fine.

I will add a new tracker item in Feature Requests (request for draw2DImage to be able to scale and rotate) and submit my patch in next few days.
I decided to make the software drivers work with draw2DImage which takes a destRect (as it currently does nothing), but it will be extremely slow if the rotation is used, or if the destRect is not same size as sourceRect. It will be the basis for my image rotation function that I want to create.
I can hear birds chirping
:twisted:

I live in the Eye of Insanity.
Ulf
Posts: 281
Joined: Mon Jun 15, 2009 8:53 am
Location: Australia

Post by Ulf »

Here you go...
https://sourceforge.net/support/tracker.php?aid=2918221

Someone can test it... please! lol.

Rotation for software drivers coming soon.

**EDIT**
In the tracker system, what does it mean if I assign the article to one of the admin?
I mean, is that my job? To assign it to somebody so they put it in the engine? I don't understand....

Who will decide if it goes in the engine? Or if my solution is good.. or good enough. Who will decide which of the draw2DImage overloads should be modified? (I already chose one anyway)

Who is in control?
I can hear birds chirping
:twisted:

I live in the Eye of Insanity.
Ulf
Posts: 281
Joined: Mon Jun 15, 2009 8:53 am
Location: Australia

Software Driver Rotate and Scale. Issues or Imperfections?

Post by Ulf »

I have uploaded a final patch to the tracker.
https://sourceforge.net/support/tracker.php?aid=2918221

The software drivers can also rotate and scale on the fly. It's extremely slow of course since they must repeatedly create and delete new images for every frame rendered.

The software drivers have issues with rotation due to the pixel step that is witnessed to varying degrees with different angles.

I created a web page with images of the rotated textures using software driver 1 for the example. I also have some questions on the web page.
http://sites.google.com/site/projectulf ... waredriver

P.S. Don't bother looking around my project style web site, it's a template, I haven't set it up yet. Only made the page (link above) with the rotated and scaled images.
I can hear birds chirping
:twisted:

I live in the Eye of Insanity.
CuteAlien
Admin
Posts: 9809
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Post by CuteAlien »

Thanks for the patch.
Ulf wrote:**EDIT**
In the tracker system, what does it mean if I assign the article to one of the admin?
I mean, is that my job? To assign it to somebody so they put it in the engine? I don't understand....

Who will decide if it goes in the engine? Or if my solution is good.. or good enough. Who will decide which of the draw2DImage overloads should be modified? (I already chose one anyway)

Who is in control?
You don't need to assign it to anyone. If anyone in the team finds time to add rotation he will assign it to himself. And there is no formal process for adding code, but usually a team-member decides how much feedback he needs from others before he changes stuff.

Concrete for this patch ... we are not blind to the fact that this is a major feature-wish which was proposed 3 times just within the last weeks (and to my knowledge several time over the last years). But please be also aware that we have right now over 40 open bugs and more than 50 open features wishes and this is the newest one. So it might take a little until someone finds time for it (as you can see from the date of the other features wishes... we're not ignoring those intentionally). I often wish people would help more by writing tests and patches for the bugs instead of adding even more features, but well, I also realize what's more fun ;-)

I'm not too deep into driver drawing right now myself. Still I guess in this case the question is most likely if any of the drawing functions should really get another parameter (as soon as you get above 5 parameters you should think _really_ hard about that) or if it wouldn't be possible to make rotations easier by adding an extra rotation state-function which then would work with _all_ drawing functions. This is for example something I also didn't think of back when I did my own patch. Well, I didn't _have_ to think about it back then because I just needed it for a single project and not for the engine and that's always easier to solve. Anyway - right now I simply don't know yet enough about the topic to give really good feedback. I hope I find more time some day and then this is certainly a feature with a high priority. Or maybe (I hope so) someone else in the team is faster :-)
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Ulf
Posts: 281
Joined: Mon Jun 15, 2009 8:53 am
Location: Australia

Post by Ulf »

Ok thanks CuteAlien.
I understand about the priorities. No rush.
Later when I know more what I'm doing I will try to help with tracker items.
CuteAlien wrote:Still I guess in this case the question is most likely if any of the drawing functions should really get another parameter (as soon as you get above 5 parameters you should think _really_ hard about that) or if it wouldn't be possible to make rotations easier by adding an extra rotation state-function which then would work with _all_ drawing functions.
Personally, I think that making a rotation state variable would be worse, and a function that sets a rotation matrix or that does anything would really be wasted effort.
It would mean that you must set the rotation for every individual object before drawing it, even if the object rotation is 0. Objects normally have no rotation and if there is rotation, each rotation could be different so you just need to set it every time.
Adding the extra rotation state does not make it easier.

Created 1 new draw2DImage function
In my latest patch I made a new draw2DImage function that has the rotation as the 2nd parameter (before the destRect). I use the destRect to scale the image at the same time.
The function works by rotating the sourceRect of the image, and then scaling it up by the ratio of the destRect (size) divided by the sourceRect (size). It draws the center of the new rotated and scaled image to the center of the destRect.

Created 3 new functions in IImage
copyToScaling : copies part of the image and scales that part, putting the result in the target parameter.
createScaledImage : copies part of the image and scales it, returning the resulting image.
createRotatedImage : copies part of the image and rotates it, returning the resulting image.

Modified two createImage functions in IVideoDriver/CNullDriver
They can now take a rotation parameter which is 0 by default, so it doesn't break the engine.

The draw2DImage functions are near complete.
OpenGL and DirectX versions are working perfectly as far as I have tested them.

I need some help with my new createRotatedImage function in IImage.
I have been busting my brain all over the place trying to get it to work properly.
I don't understand translation well enough to see my flaws.
There are minor rounding errors.
When I de-transform to find the source coordinate from the destination coordinate, I don't get an exact 1-1 mapping. I can't tell by looking, but it's as if some pixels round up when they should round down, and vice versa. It is evident around the border where you see the erratic pixel step.

I have searched the net and tried various methods. None of them seem to work exactly, except when they are using openGL, directX or .NET classes to do the drawing. Is it something to do with using float tcoords?
I don't understand that yet.

Can anyone provide some insight or references?

P.S. I have tried transforming the pixels from the source to the destination, but this leaves gaps everywhere in the destination. I have also read many times that it cannot be done this way. Everyone seems to reverse translate from the destination to find the relative source pixel.

**EDIT**
I have discovered a fundamental flaw in my code. Fixing this may fix everything. I messed up the rectangles for the textures, and the way they relate to image size. I had mix ups all over the place so I'm just fixing them all now. I wasn't even drawing the boundary in the correct place.
I can hear birds chirping
:twisted:

I live in the Eye of Insanity.
Ulf
Posts: 281
Joined: Mon Jun 15, 2009 8:53 am
Location: Australia

Post by Ulf »

I have been trying to fix the software versions in my rotation patch.
I put up my 5th version of my rotation patch on the tracker.

It fixes some misunderstandings that I was having about the destRect and sourceRect.

Also, I perform scaling before rotation. I wanted to do it the other way around as it would be faster to rotate a smaller image, then scale it.
But this doesn't seem to work accurately. At least not the way I am doing it.

**Note**
I kept the 2 changes that I made to the createImage functions in NullDriver and IVideoDriver, even though I don't use them in my implementations.

But I believe (it's possible) they may be useful in the future.
Because then each Video Driver could implement it's own version of creating a rotated image.
It could be extended to also include a scaling variable.

I believe that my implementation for the software drivers is not the most efficient method of doing it. I have to look into it more.

Basically, the software versions must create a new image if it is scaled, and then create another new image if it is rotated. Then draw it to the renderTarget and drop the created images.

Maybe it is possible to directly scale and rotate into the software driver render target (hence the altered createImage functions in IVideoDriver).

In reference to the IImage class function createRotatedImage, I need to fix it a little bit more. It's now quite close to accurate, but I have some rounding issues that are plaguing me.

The way I understand, I shouldn't be using the material settings and 3D type functions to do things in draw2DImage. So my implementations are purely 2D and don't try to take advantage of the 3D settings.
This makes sense to me, and I don't know anything about the 3D stuff yet anyway.

I'm going to look at the new 1.7 and see if the way 2D is done has changed.
I can hear birds chirping
:twisted:

I live in the Eye of Insanity.
Post Reply