Resizing in SFML 2.0 - c++

This may be a simple question but I'm having a hard time finding a straight answer to it: is there a way to resize a loaded Texture in SFML 2.0? For instance, if I have a 3264x2448 png and I want to scale it down to fit a 900x1200 rendered window without cropping, how would I do so?

Is there a way to scale all rendered windows to fit whatever monitor
of whatever system the application is running on?
First, here's a way to scale the image to the current RenderWindow size.
// assuming the given dimension
// change this dynamically with the myRenderWindow->getView().getSize()
sf::Vector2f targetSize(900.0f, 1200.0f);
yourSprite.setScale(
targetSize.x / yourSprite.getLocalBounds().width,
targetSize.y / yourSprite.getLocalBounds().height);
Be aware that this may stretch your image if the aspect ratio is not maintained. You might want to add code to adjust the decision for your case.
Then, if you want to stretch the RenderWindow to fill all the screen, may I suggest you use fullscreen mode?
Here's a snippet of how it's done:
// add the flag to the other ones
mStyleFlag = sf::Style::Default | sf::Style::Fullscreen;
// get the video mode (which tells you the size and BPP information of the current display
std::vector<sf::VideoMode> VModes = sf::VideoMode::getFullscreenModes();
// then create (or automatically recreate) the RenderWindow
mMainWindow.create(VModes.at(0), "My window title", mStyleFlag);

is there a way to resize a loaded Texture in SFML 2.0?
Not an sf::Texture directly. But you can use an sf::Sprite: you load load your texture, you pass it to an sf::Sprite and you play with sf::Sprite::setScale or sf::Sprite::scale.

Related

How to create and edit a bitmap

I'm trying to create a bitmap that I can change the pixels of and then update the window with that bitmap. I've tried to research a way to just create a bitmap, but that was to no avail.
I need to know how to create a blank bitmap, then change its pixels using x and y coordinates and a color, and then how to draw it to the window. I don't need to save it to the computer and I don't want to convert an existing image into a bitmap.
I'm on windows and using Visual Studio with C++
Just to specify, I need to know the syntax for creating a blank bitmap with a certain width and height, and also what function I need to use to change the pixels' colors, and then how to draw a bitmap to the window. Thank you.
There is a free library ImgSource that you can use which has a huge amount of functionality for images.
http://www.smalleranimals.com/isource.htm
It is available in MSDN, but using a library like ImgSource may be to your advantage.
It provides simple methods for rendering your image onto a device context. And there is a good support forum.

How to determine size of the drawable area of an OpenGL 3.3 window using GLFW

I'm trying to create an game / application using GLFW and OpenGL 3.3. I'd like to be able to detect collision with the sides of the window, but it seems that the drawable area of the window differs from the size of the window set using glfwCreateWindow().
So my question is, how do I get that drawable area, ie. the size of the window minus the border? I'd rather not have to use the WinAPI so as to make it more cross-platform, and glfwGetWindowFrameSize() is in GLFW 3.1, which isn't completed yet.
Edit: My question makes it seem like I need to use GLFW do accomplish this, which isn't true. I just wanted to note that I'm using GLFW as a window / input handler.
You want glfwGetFramebufferSize.
glfwGetVideoMode returns the video mode of the specified monitor, not the size of your window. For fullscreen windows, they happen to be the same, but for other windows they are likely to be very different.
From the looks of it, you do not need to know the size of the window, I'm assuming in pixels? If you want to do collision detection with the border of the window, you just need to detect the the NDC of your vertex, and once it reaches x or y = (-1, 1) then you would've had a collision. Nonetheless, if you want to get the size in pixels of your OpenGL context then use glfwGetVideoMode().

resizing QGLWidget to fit with each sprite size I have

I'm creating 2D Map editor using opengl to draw simple 32x32 sprites but it seems that I cannot resize my QGLWidget to a large size (i.e size * sprite size -> 1024 * 32), using 1024 only seems to work fine (using glwidget->setMinimumSize(...)). I've been googling for a while now about this, the only interesting thing I found is subclassing QAbstractScrollArea and setting my QGLWidget as it's viewport (That's what QGraphicsView does), I also seen all Qt opengl examples but i couldn't find anything that could help (except Image Viewer example which is not exactly what I want), I also tried the following:
horizontalScrollBar()->setMaximum(width * 32);
verticalScrollBar()->setMaximum(height * 32);
with the widget resizable set to true/false on the scrollarea but still nothing.
Any ideas how would I do that? I can show more code if you ask me to.
Using Qt v4.7.3.
I have two ideas:
If it's possible, drop the idea of using a QGLWidget and place the sprites directly in a graphics scene (QGraphicsPixmapItem). Possibly not what you want, but the graphics scene is made to handle a lot of items, so most things you need (trigger mouse events on items for example) are already implemented.
Or just place the QGLWidget in a graphics scene using a QGraphicsWidget. This should automatically tell the scene its size, which then tells the view the size of the scene. The scroll bars appear automatically if the scene doesn't fit into the view.
Update:
As described in this link, you can use OpenGL in any graphics view:
view.setViewport(new QGLWidget(QGLFormat(QGL::SampleBuffers)));
view.setViewportUpdateMode(QGraphicsView::FullViewportUpdate);

How to take reliable QGLWidget snapshot

In my application I take snapshots of a QGLWidget's contents for two purposes:
Not redraw the scene all the time when only an overlay changes, using a cached pixmap instead
Lat the user take screenshots of the particular plots (3D scene)
The first thing I tried is grabFrameBuffer(). It is natural to use this function as for the first application, what is currently visible in the widget is exactly what I want to cache.
PROBLEM: On some hardware (e.g. Intel integrade graphics, Mac OS X with GeForce graphics), the image obtained does not contain the current screen content, but the content before that. So if the scene would be drawn two times, on the screen you see the second drawing, in the image you see the first drawing (which should be the content of the backbuffer?).
The second thing I tried is renderToPixmap(). This renders using paintGL(), but not using paint(). I have all my stuff in paint(), as I use Qt's painting functionality and only a small piece of the code uses native GL (beginNativePainting(), endNativePainting()).
I also tried the regular QWidget's snapshot capability (QPixmap::fromWidget(), or what it is called), but there the GL framebuffer is black.
Any ideas on how to resolve the issue and get a reliable depiction of the currently drawn scene?
How to take reliable QGLWidget snapshot
Render current scene to framebuffer, save data from framebuffer to file. Or grab current backbuffer after glFlush. Anything else might include artifacts or incomplete scene.
It seems that QGLWidget::grabFrameBuffer() internally calls glReadPixels() from OpenGL. On double-bufferd configurations the initial mode reads the back buffer (GL_BACK), switch with the OpenGL call glReadBuffer(GL_FRONT) to the front buffer before using QGLWidget::grabFrameBuffer() displaying an image on the screen.
The result of QGLWidget::grabFrameBuffer(), like every other OpenGL calls, depends on the video driver. Qt merely forwards your call to the driver and grabs the image it returns, but the content of the image is not under Qt's control. Other than making sure you have installed the latest driver for your video card, there is not much you can do except report a bug to your video card manufacturer and pray.
I use paintGL(); and glFlush(); before using grabFrameBuffer(). The paintGL helps to draw current frame again before grab the frame buffer, which makes an exact copy of what is currently showing.

Any way to speed up/reduce CPU usage when drawing with Cairo?

I wrote an app that uses Cairo to draw things on screen (on a Gtk::DrawingArea, to be exact). It needs to redraw everything frequently. It turns out, that despite the draphics drawn are very simple, the X server uses LOTS of CPU when redrawing, and the applications works terribly slow. Is there any way to speed this up? Or maybe I shouldn't use DrawingArea and some other widget?
What I draw is set of rectangles, which user can move around by dragging them with mouse. The whole drawing is done withing on_expose_event, but as the mouse pointer moves around (with button pressed), I call queue_draw() to refresh drawing.
Just a couple things to check:
Is your drawing done in the expose event?
Draw your image to a Cairo Surface, and then in the expose event simply copy from that surface to the widget's surface.
Are you clipping and drawing only the region necessary?
The expose event gives you an X, Y, width, height of the area that needs to be redrawn. In cairo, create a rectangle on your surface with these dimensions and call clip so that you aren't wasting time redrawing stuff that doesn't need to be.
Drawing is expensive, especially text drawing has become the most CPU expensive task of a GUI.
The only way to speed this up is to reduce the amount of drawn items. Check if you really only draw the items that are necessary. The expose-event is giving you a rectangle. Only refresh this part of the widget.
Maybe cache items in a bitmap.
For smooth scrolling for example it can help to draw the content into a bitmap that is for example 500 pixels larger so that in most cases you just need to copy the image and don't draw anything at all (you usually get expose rectangles that are just 5 to 10 pixels high during scrolling).
But you need to give us more information what you are drawing and what the system load is to get a better answer.
I found this article about threaded drawing in cairo to solve the speed-problem, maybe that helps:
http://cairographics.org/threaded_animation_with_cairo/
About the high CPU usage:
Do you have proper hardware accelerated drivers installed for X?
I finally forced to use maximally 25 fps, by using a lock flag.
bool lock = 0;
bool needs_redraw = 0;
void Redraw(){
if(lock){
needs_redraw = 1;
return;
}
//draw image to a surface
needs_redraw = 0;
lock = 1;
Glib::signal_timeout().connect(Unlock, 20);
queue_draw();
}
bool Unlock(){
lock = 0;
if(needs_redraw) Redraw();
return false;
}
void on_expose_event(something){
//copy image from surface to widget's context
}
This is a sample code, but that's the idea. It will disallow redraw to be done more often then once per 20 ms.