I have recently started coding in C++ for the in-take assignment I need to make for my next school, and I'm seeing a big problem now and I don't know how to fix it. As soon as I try to run my code it said "Project.exe has stopped working". I tried to find solutions on the internet but I haven't found anything that solves my problem. This is my code (the SDL part are not the parts causing trouble, but I included them anyway for the completeness of the code):
//Using SDL and standard IO
#include <SDL.h>
#include <stdio.h>
//Screen dimension constants
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
class particle {
public:
void setxPos(int xx){
xP=xx;
};
void setyPos(int yy){
yP=yy;
};
void setxVel(int xv){
xVel=xv;
};
void setyVel(int yv){
yVel=yv;
};
int getxPos(){
return (xP);
};
int getyPos(){
return (yP);
};
protected:
int xP, yP;
int xVel = 0;
int yVel = 0;
};
void draw(SDL_Renderer* tempRend, particle drawJelly[6][4]){ //Function created for drawing the lines between the particles
SDL_RenderDrawLine( tempRend, drawJelly[1][1].getxPos(), drawJelly[1][1].getyPos(), drawJelly[2][1].getxPos(), drawJelly[2][1].getyPos() );
SDL_RenderDrawLine( tempRend, drawJelly[2][1].getxPos(), drawJelly[2][1].getyPos(), drawJelly[3][1].getxPos(), drawJelly[3][1].getyPos() );
SDL_RenderDrawLine( tempRend, drawJelly[3][1].getxPos(), drawJelly[3][1].getyPos(), drawJelly[4][1].getxPos(), drawJelly[4][1].getyPos() );
SDL_RenderDrawLine( tempRend, drawJelly[4][1].getxPos(), drawJelly[4][1].getyPos(), drawJelly[5][1].getxPos(), drawJelly[5][1].getyPos() );
SDL_RenderDrawLine( tempRend, drawJelly[5][1].getxPos(), drawJelly[5][1].getyPos(), drawJelly[6][1].getxPos(), drawJelly[6][1].getyPos() );
SDL_RenderDrawLine( tempRend, drawJelly[6][1].getxPos(), drawJelly[6][1].getyPos(), drawJelly[6][2].getxPos(), drawJelly[6][2].getyPos() );
SDL_RenderDrawLine( tempRend, drawJelly[6][2].getxPos(), drawJelly[6][2].getyPos(), drawJelly[6][3].getxPos(), drawJelly[6][3].getyPos() );
SDL_RenderDrawLine( tempRend, drawJelly[6][3].getxPos(), drawJelly[6][3].getyPos(), drawJelly[6][4].getxPos(), drawJelly[6][4].getyPos() );
SDL_RenderDrawLine( tempRend, drawJelly[6][4].getxPos(), drawJelly[6][4].getyPos(), drawJelly[5][4].getxPos(), drawJelly[5][4].getyPos() );
SDL_RenderDrawLine( tempRend, drawJelly[5][4].getxPos(), drawJelly[5][4].getyPos(), drawJelly[4][4].getxPos(), drawJelly[4][4].getyPos() );
SDL_RenderDrawLine( tempRend, drawJelly[4][4].getxPos(), drawJelly[4][4].getyPos(), drawJelly[3][4].getxPos(), drawJelly[3][4].getyPos() );
SDL_RenderDrawLine( tempRend, drawJelly[3][4].getxPos(), drawJelly[3][4].getyPos(), drawJelly[2][4].getxPos(), drawJelly[2][4].getyPos() );
SDL_RenderDrawLine( tempRend, drawJelly[2][4].getxPos(), drawJelly[2][4].getyPos(), drawJelly[1][4].getxPos(), drawJelly[1][4].getyPos() );
SDL_RenderDrawLine( tempRend, drawJelly[1][4].getxPos(), drawJelly[1][4].getyPos(), drawJelly[1][3].getxPos(), drawJelly[1][3].getyPos() );
SDL_RenderDrawLine( tempRend, drawJelly[1][3].getxPos(), drawJelly[1][3].getyPos(), drawJelly[1][2].getxPos(), drawJelly[1][2].getyPos() );
SDL_RenderDrawLine( tempRend, drawJelly[1][2].getxPos(), drawJelly[1][2].getyPos(), drawJelly[1][1].getxPos(), drawJelly[1][1].getyPos() );
SDL_RenderPresent( tempRend );
SDL_Delay(100); //Wait .5 seconds for clarity of the drawing
}
void position(particle posJelly[6][4]){
int a=0;
while (a<6){ //Give all the jelly particles a position in the 20x20 grid
int b=0;
while(b<4){
posJelly[a][b].setxPos((20*a));
posJelly[a][b].setyPos((20*b));
b--;
}
a--;
}
}
int main( int argc, char* args[] )
{
SDL_Window* window = NULL;
SDL_Renderer* renderer = NULL;
SDL_Surface* surface = NULL;
SDL_Init( SDL_INIT_VIDEO );
window = SDL_CreateWindow( "Jelly Game", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN );
renderer = SDL_CreateRenderer( window, -1, 0);
surface = SDL_GetWindowSurface( window );
SDL_SetRenderDrawColor( renderer, 0, 255, 0, 255 );
SDL_RenderPresent( renderer );
particle jelly[6][4]; //New object from class "particle" with name jelly
position(jelly); //Run function "position()" on particle jelly to set starting coördinates
bool inGame=true; //Start the game-loop
while(inGame){
draw(renderer, jelly);
inGame=false;
}
SDL_Delay( 2000 ); //Wait 2 seconds
SDL_DestroyWindow( window ); //Destroy the window "window"
SDL_Quit(); //Quit SDL
return 0; //End the program
}
Now, I already found where the cause lies, and that is in this part:
void position(particle posJelly[6][4]){
int a=0;
while (a<6){ //Give all the jelly particles a position in the 20x20 grid
int b=0;
while(b<4){
posJelly[a][b].setxPos((20*a));
posJelly[a][b].setyPos((20*b));
b--;
}
a--;
}
}
Because when I delete
position(jelly);
or remove
posJelly[a][b].setxPos((20*a));
posJelly[a][b].setyPos((20*b));
inside the position function, it doesn't give the error. (It doesnt work properly because it has no correct coordinates to draw from and to, but it 'works')
Again, I have searched in a lot of other articles and tutorials why this doesn't work or how this can be made work-able, but have found nothing yet.
The 'game' will be about a blob of jelly, made up out of 24 particles (6x4 but only the outer particles will be painted on the screen) that have a desirable distance to their neigbors, and then when they move closer or further away from eachother they will be drawn/pushed back to that distance, thus creating the 'bouncing' effect a blob of jelly has.
Please help!
Also, I know the Draw() function isn't very proffessional, but it's not going to be a full-release game anyway, and since the blob is always going to be 6 by 4, this is just a way easier way of drawing than finding the outer particles by loops and stuff.
You are trying to access the arrays with a negative index. You set b to 0 in the first iteration and than then you decrement it to make it -1. Then you use b in the next iteration the program goes boom. You probably meant to use ++ instead of --.
In this case the error has to do with negative values to array indexes.
You see an error like that when you program has raised an exeption and you don't handle it.
You should change:
a-- and b-- for a++ and b++
The first time your code reach the lines:
posJelly[a][b].setxPos((20*a));
posJelly[a][b].setyPos((20*b));
a==0 and b==0 but the second time (after a-- and b--) you would have something like this:
posJelly[-1][-1].setxPos((20*a)); // illegal C++ no negative inidices are allowed
posJelly[-1][-1].setyPos((20*b)); // illegal C++ no negative inidices are allowed
replace a decrementing operator with an increment: a-- and b-- with a++ andb++, respectively.
Related
I am in the process of learning OpenGL on Linux but I can't get mode switching working (windowed to full screen and back).
The window appears to be going into full screen but but not looking correct. To switch modes a new window is being created and old one destroyed.
void OpenGLWindow::FullScreen(bool fullScreen, int width, int height)
{
GLFWwindow *oldHandle = m_window;
m_fullscreen = fullScreen;
m_width = width;
m_height = height;
m_window = glfwCreateWindow(width, height, m_caption.c_str(),
fullScreen ? m_monitor : NULL, m_window);
if (m_window == NULL)
{
glfwTerminate();
throw std::runtime_error("Failed to recreate window.");
}
glfwDestroyWindow(oldHandle);
m_camera->Invalidate();
// Use entire window for rendering.
glViewport(0, 0, width, height);
glfwMakeContextCurrent(m_window);
glfwSwapInterval(1);
if (m_keyboardHandler) SetKeyboardHandler(m_keyboardHandler);
}
Initial Window
Full Screen (incorrect)
Return to Windowed
Updates to Question
I have updated the code to use your code and getting the same issue. On your suggestion I am now updating the camera, but again no avail :(
void OpenGLCamera::Invalidate()
{
RecalculateProjection(m_perspProjInfo->Width(), m_perspProjInfo->Height());
m_recalculateViewMatrix = true;
m_recalculatePerspectiveMatrix = true;
m_recalculateProjectionMatrix = true;
}
void OpenGLCamera::RecalculateProjection(int width, int height)
{
float aspectRatio = float(width) / height;
float frustumYScale = cotangent(degreesToRadians(
m_perspProjInfo->FieldOfView() / 2));
float frustumXScale = frustumYScale;
if (width > height)
{
// Shrink the x scale in eye-coordinate space, so that when geometry is
// projected to ndc-space, it is widened out to become square.
m_projectionMatrix[0][0] = frustumXScale / aspectRatio;
m_projectionMatrix[1][1] = frustumYScale;
}
else {
// Shrink the y scale in eye-coordinate space, so that when geometry is
// projected to ndc-space, it is widened out to become square.
m_projectionMatrix[0][0] = frustumXScale;
m_projectionMatrix[1][1] = frustumYScale * aspectRatio;
}
}
Rabbid : When I resize:
Rabbid : When I go to full screen:
In the following, I'll describe a small but handy class, which deals with resizing a GLFW window and handles switch fullscreen window on and off.
All the used GLFW functions are well documented in the GLFW documentation.
#include <GL/gl.h>
#include <GLFW/glfw3.h>
#include <array>
#include <stdexcept>
class OpenGLWindow
{
private:
std::array< int, 2 > _wndPos {0, 0};
std::array< int, 2 > _wndSize {0, 0};
std::array< int, 2 > _vpSize {0, 0};
bool _updateViewport = true;
GLFWwindow * _wnd = nullptr;
GLFWmonitor * _monitor = nullptr;
void Resize( int cx, int cy );
public:
void Init( int width, int height );
static void CallbackResize(GLFWwindow* window, int cx, int cy);
void MainLoop ( void );
bool IsFullscreen( void );
void SetFullScreen( bool fullscreen );
};
When creating the window, then the user function pointer (glfwSetWindowUserPointer) is set to the window management class. And the resize callback is set by glfwSetWindowSizeCallback. After the window is created its current size and position can be get by glfwGetWindowPos and glfwGetWindowSize.
void OpenGLWindow::Init( int width, int height )
{
_wnd = glfwCreateWindow( width, height, "OGL window", nullptr, nullptr );
if ( _wnd == nullptr )
{
glfwTerminate();
throw std::runtime_error( "error initializing window" );
}
glfwMakeContextCurrent( _wnd );
glfwSetWindowUserPointer( _wnd, this );
glfwSetWindowSizeCallback( _wnd, OpenGLWindow::CallbackResize );
_monitor = glfwGetPrimaryMonitor();
glfwGetWindowSize( _wnd, &_wndSize[0], &_wndSize[1] );
glfwGetWindowPos( _wnd, &_wndPos[0], &_wndPos[1] );
_updateViewport = true;
}
When the resize notification occurs, then the pointer to the window management class can be get by glfwGetWindowUserPointer:
static void OpenGLWindow::CallbackResize(GLFWwindow* window, int cx, int cy)
{
void *ptr = glfwGetWindowUserPointer( window );
if ( OpenGLWindow *wndPtr = static_cast<OpenGLWindow*>( ptr ) )
wndPtr->Resize( cx, cy );
}
Any change of the window size is notified and the new window size is stored (glfwGetWindowSize):
void OpenGLWindow::Resize( int cx, int cy )
{
_updateViewport = true;
}
When the window size has changed, then the viewport has to be suited to the window size (glViewport). This can be done in the main loop of the application:
void OpenGLWindow::MainLoop ( void )
{
while (!glfwWindowShouldClose(_wnd))
{
if ( _updateViewport )
{
glfwGetFramebufferSize( _wnd, &_vpSize[0], &_vpSize[1] );
glViewport( 0, 0, _vpSize[0], _vpSize[1] );
_updateViewport = false;
}
// ..... render the scene
glfwSwapBuffers(_wnd);
glfwPollEvents();
}
}
If the current window is in full screen mode, can be achieved by asking for the monitor that the window uses for full screen mode (glfwGetWindowMonitor):
bool OpenGLWindow::IsFullscreen( void )
{
return glfwGetWindowMonitor( _wnd ) != nullptr;
}
To switch the full screen mode on and off, glfwSetWindowMonitor has to be called, either with the monitor for the full screen mode, or with nullptr:
void OpenGLWindow::SetFullScreen( bool fullscreen )
{
if ( IsFullscreen() == fullscreen )
return;
if ( fullscreen )
{
// backup window position and window size
glfwGetWindowPos( _wnd, &_wndPos[0], &_wndPos[1] );
glfwGetWindowSize( _wnd, &_wndSize[0], &_wndSize[1] );
// get resolution of monitor
const GLFWvidmode * mode = glfwGetVideoMode(_monitor);
// switch to full screen
glfwSetWindowMonitor( _wnd, _monitor, 0, 0, mode->width, mode->height, 0 );
}
else
{
// restore last window size and position
glfwSetWindowMonitor( _wnd, nullptr, _wndPos[0], _wndPos[1], _wndSize[0], _wndSize[1], 0 );
}
_updateViewport = true;
}
I recommend you to not create a new Window with glfwCreateWindow when you just want to switch between windowed and fullscreen. Use glfwSetWindowMonitor instead.
When you create a window with fullscreen enabled, you have to pass arguments which are compatible with a video mode on the monitor. You can get the standard video mode on the primary monitor like this:
GLFWmonitor *monitor = glfwGetPrimaryMonitor();
const GLFWvidmode *mode = glfwGetVideoMode(monitor);
and to switch to fullscreen:
glfwSetWindowMonitor(window, monitor, 0, 0, mode->width, mode->height, mode->refreshRate);
Just pass a nullptr-mode and your own values of course:
glfwSetWindowMonitor(window, nullptr, 0, 0, windowWidth, windowHeight, windowRefreshRate);
And don't forget to resize the viewport and update the camera.
Are you resizing the viewport and updating the camera when the user resizes the window?
There are a couple of issues with your code:
Assuming that glfwCreateWindow will set the resolution to width * height in fullscreen mode is not correct. The GLFW documentation states (emphasis mine):
For full screen windows, the specified size becomes the resolution of the window's desired video mode. As long as a full screen window is not iconified, the supported video mode most closely matching the desired video mode is set for the specified monitor.
Assuming that the window size is specified in "pixels" is not correct either.Quoting the relevant part of the documentation again:
While the size of a window is measured in screen coordinates, OpenGL works with pixels. The size you pass into glViewport, for example, should be in pixels. On some machines screen coordinates and pixels are the same, but on others they will not be. There is a second set of functions to retrieve the size, in pixels, of the framebuffer of a window.
Issues 1 and 2 can be solved by simply calling glfwGetFramebufferSize after the window was created. This leaves us with issue 3:
You call glViewport without having a current GL context -
resulting in undefined behavior, and especially in not setting the viewport at all. Now that is actually an interesting one, because the initial viewport for the new context will be the full new window, so that your mistakes 1 and 2 have no direct effect. They still might have some effect later if your code relies on m_width and m_height containing useful values, though.
im trying to show two different animations made with two functions, one render and two threads.
Im getting different kind of error each time i run the code.
Such as: segmentation default in the refresh function (line SDL_RenderPresent(w1.renderer);) and other strange errors too. Everytime is different.
I know its about using the render in both different threads. But i dont know how to solve this problem.
When i run with just one of the threads everything its ok. But not with the two of them.
I just want to show different graphics playing around the window. (always using sdl2).
Here is my code:
window.h:
class Window
{
public:
SDL_Window *window1;
int background,windowWidth,windowHeight,windowXcoord,windowYcoord;
SDL_Renderer * renderer;
SDL_Renderer * renderer2;
Window();
};
void refresh();
extern Window w1;
window.cpp:
Window w1;
Window::Window()
{
window1=nullptr;
background = 0xffffff;
windowWidth=700; windowHeight=500;
windowXcoord = 650; windowYcoord = 0;
this->window1 =
SDL_CreateWindow("Window",windowXcoord,windowYcoord,
windowWidth,windowHeight, SDL_WINDOW_SHOWN);
this->renderer = SDL_CreateRenderer( this->window1, -1 ,
SDL_RENDERER_ACCELERATED);
SDL_SetRenderDrawColor( this->renderer, 255, 255, 255, 255 );
SDL_RenderClear( this->renderer );
SDL_RenderPresent(this->renderer);
}
// this function is called everytime an object or function want to "refresh" the window.
void refresh(){
// clearing the window
SDL_SetRenderDrawColor( w1.renderer, 255, 255, 255,0 );
SDL_RenderClear( w1.renderer );
// r1, the first Rects object to animate.
SDL_SetRenderDrawColor( w1.renderer,255,0,0,255);
SDL_RenderFillRect( w1.renderer, &r1.rect );
// r2, the second Rects.
SDL_SetRenderDrawColor( w1.renderer,255,0,255,255);
SDL_RenderFillRect( w1.renderer, &r2.rect );
SDL_RenderPresent(w1.renderer);
}
rects.h:
class Rects
{
public:
SDL_Rect rect;
Rects();
};
extern Rects r1, r2;
void moveR1();
void moveR2();
rects.cpp:
Rects::Rects()
{ }
Rects r1,r2;
// moveR1 and moveR2, (just some dumm animations-example)
void moveR1(){
r1.rect.x=400; r1.rect.y=100;
r1.rect.w =40; r1.rect.h =10;
SDL_SetRenderDrawColor( w1.renderer,255,0,0,255);
SDL_RenderFillRect( w1.renderer, &r1.rect );
{
for (int u = 1; u<=5;u++){
r1.rect.x=200; r1.rect.y=100;
r1.rect.w =50; r1.rect.h =50;
refresh();
for (int i = 1; i <=200; i++){
r1.rect.x-=1;
usleep (7000);
refresh();
}
}
}
}
void moveR2(){
r2.rect.x=200; r2.rect.y=100;
r2.rect.w =40; r2.rect.h =10;
SDL_SetRenderDrawColor( w1.renderer,255,255,0,255);
SDL_RenderFillRect( w1.renderer, &r2.rect );
{
for (int u = 1; u<=5;u++){
check
r2.rect.x=200; r2.rect.y=100;
r2.rect.w =50; r2.rect.h =50;
refresh();
for (int i = 1; i <=200; i++){
r2.rect.x+=1; r2.rect.y+=1;
usleep (7000);
refresh();
}
}
}
}
and the main:
int main()
{
thread t1(moveR1);
t1.detach();
thread t2(moveR2);
t2.detach();
// sleep instead of showing a loop.
sleep (10);
return 0;
}
any polite help is welcome, im here to learn.
When i run with just one of the threads everything its ok. But not with the two of them.
According to the documentation for 2D accelerated rendering (also known as SDL_render.h, in other terms the place where SDL_RenderPresent lives):
This API is not designed to be used from multiple threads, see SDL bug #1995 for details.
You won't be able to do that any time soon. By looking at the description of the error, it looks like an UB and the link to the bug gives you all the details probably.
I just want to show different graphics playing around the window.
You don't need to use two threads to do that.
You can just update positions, animations and whatever is needed for your graphics and show them from the same thread. Nothing prevents you from calling the same function (as an example SDL_RenderCopy) more than once before to invoke SDL_RenderPresent.
If you needed a thread per graphic, what about a game with thousands of polygons on video?
// thanks to skypjack, i am able to solve the problem
// HOW TO PRESENT TWO (OR MORE) GRAPHICS WITH SDL_RENDERER WITHOUT USING THREADS.
// The two rectangle animation are just and example.
// It could be whatever we want to show.
// In this case, just two rectangles moving around.
#include <unistd.h>
#include <SDL.h>
using namespace std;
SDL_Window *window1;
int background, windowWidth, windowHeight,windowXcoord,
windowYcoord;
SDL_Rect rectangle1;
SDL_Rect rectangle2;
SDL_Renderer *renderer;
int sequence1;
int sequence2;
void moveRectangle1(), moveRectangle2();
int main()
{
window1=nullptr;
background = 0xffffff;
windowWidth=700; windowHeight=500;
windowXcoord = 650; windowYcoord = 0;
window1 = SDL_CreateWindow("Main
Window",windowXcoord,windowYcoord, windowWidth,windowHeight,
SDL_WINDOW_SHOWN);
renderer = SDL_CreateRenderer( window1, -1 ,
SDL_RENDERER_ACCELERATED);
SDL_SetRenderDrawColor( renderer, 255, 255, 255, 255 );
SDL_RenderClear( renderer );
SDL_RenderPresent(renderer);
rectangle1.x = 100; rectangle1.y = 100; rectangle1.h = 40;
rectangle1.w = 40;
rectangle2.x = 100; rectangle2.y = 100; rectangle2.h = 40;
rectangle2.w = 40;
for (int i = 1;i<500;i++){
SDL_SetRenderDrawColor( renderer, 255, 255, 255,0 );
SDL_RenderClear( renderer );
// chequear return (cerrar programa)
moveRectangle1();
moveRectangle2();
SDL_RenderPresent(renderer);
usleep (12000);
}
return 0;
}
void moveRectangle1(){
sequence1++;
if (sequence1 <= 50){ rectangle1.x++; }
else if (sequence1 <= 100){ rectangle1.x--; }
else { sequence1 = 0; }
SDL_SetRenderDrawColor(renderer,255,0,0,255);
SDL_RenderFillRect(renderer, &rectangle1 );
}
void moveRectangle2(){
sequence2++;
if (sequence2 <= 100){ rectangle2.y++; }
else if (sequence2 <= 200){ rectangle2.y--; }
else { sequence2 = 0; }
SDL_SetRenderDrawColor(renderer,0,200,0,255);
SDL_RenderFillRect( renderer, &rectangle2 );
}
I am doing my code for a simple game using SDL library. I have 2 questions regarding this:
If I don't put a breakpoint and let the program runs by itself, the memory usage going high (like 20-30x compared to the beginning). However, if I stop the loop (main loop of the game) and click by myself, the memory usage stay same after around 100 clicks(?). Why?
So I decided to use instrument to analyze the reason why since I think in the loop I might adding new element without destroying it. And everytime I hit record in Instrument, the app goes on for 5 seconds and shutdowns with a crash report (The app runs perfectly, with the memory stuff, in xcode)
Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0 org.libsdl.SDL2 0x0000000100f5bea9 0x100ee9000 + 470697
1 Spike 10 0x0000000100ea40cc imageTexture::render() + 50 (imageTexture.cpp:37)
2 Spike 10 0x0000000100ea2b70 GUI::renderImage() + 40 (GUI.cpp:140)
3 Spike 10 0x0000000100ea30b2 GUI::run() + 1258 (GUI.cpp:172)
4 Spike 10 0x0000000100ea439e main + 36 (main.cpp:15)
5 libdyld.dylib 0x00007fff8c60f5ad start + 1
These are some codes that I think might related:
For number 3: //imageVector is just a vector contain all the imageVector pointer
SDL_RenderClear( gRenderer );
for (int i = 0; i < imageVector.size(); i++) {
imageVector[i]->render();
}
For number 2:
//set rendering space and render to screen
SDL_Rect temp = {x, y, width, height};
//render to the screen
SDL_RenderCopy(gRenderer, texture, NULL, &temp);
After a long try disable/enable code around to find what happen, I still have no idea what's wrong.
This is my current loop:
while (true) {
textVector[0]->setInput(system->output());
renderImage();
renderText();
SDL_RenderPresent( gRenderer );
}
Some code for it:
void textTexture::setInput(std::string newText) {
gText = newText;
}
void GUI::renderImage() {
SDL_RenderClear( gRenderer );
for (int i = 0; i < imageVector.size(); i++) {
imageVector[i]->render();
}
}
void GUI::renderText() {
for (int i = 0; i < textVector.size(); i++) {
textVector[i]->render();
}
}
void textTexture::render() {
//set rendering space and render to screen
SDL_Rect temp = {x, y, width, height};
//recreate the texture
createTextureFromRenderedText(gText);
//render to the screen
SDL_RenderCopy(gRenderer, texture, NULL, &temp);
}
void textTexture::createTextureFromRenderedText(std::string text) {
if (text != "") {
SDL_Surface* textSurface = TTF_RenderText_Blended_Wrapped(gFont, text.c_str(), textColor, 600);
if( textSurface == NULL )
{
printf( "Unable to render text surface! SDL_ttf Error: %s\n", TTF_GetError() );
}
else
{
//Create texture from surface pixels
texture = SDL_CreateTextureFromSurface( gRenderer, textSurface );
if( texture == NULL )
{
printf( "Unable to create texture from rendered text! SDL Error: %s\n", SDL_GetError() );
}
else
{
//Get image dimensions
width = textSurface->w;
height = textSurface->h;
}
//Get rid of old surface
SDL_FreeSurface( textSurface );
}
}
}
Find the problem. I copy the style of lazyfoo and try to implement in mine so when I render new textTexture, it actually create new texture without destroying it. By using SDL_DestroyTexture, everything works fine
Found the answer here:
https://stackoverflow.com/questions/24938695/memory-leak-sdl-while-using-sdl-createtexturefromsurface
I have a problem with SDL. When i run the following code it is not responding. I have .bmp in same folder as the executable file.Is problem in code or where.....?
#include "SDL/SDL.h"
int main( int argc, char* args[] )
{
SDL_Surface* robot = NULL;
SDL_Surface* screen = NULL;
SDL_Init( SDL_INIT_EVERYTHING );
screen = SDL_SetVideoMode( 640, 480, 32, SDL_SWSURFACE );
robot = SDL_LoadBMP( "robot.bmp" );
SDL_BlitSurface( robot, NULL, screen, NULL );
SDL_Flip( screen );
SDL_Delay( 12*1000 );
SDL_FreeSurface( robot );
SDL_Quit();
return 0;
}
SDL_Delay( 12*1000 ); will halt the current thread for 12 seconds. The issue is that the thread which is halted is the "video" thread, the one in charge of displaying your image. After 12 secons the window will close and the program will exit.
In order to see the image and exit at will, you need to wait on a specific event of your choice like a keyboard event. See here how to make basic event loop with SDL.
I'm trying to fit facedetect from openCV on my QT code, all run fine until i decided to create a thread for my openCV code so I can run another things while the face detect is on.
the problem is if i call class->start(); my program breaks in the while loop in the run() but if i call the class.run(); (like a normal function) it runs as usual! what can be wrong?
code:
faceTracker::faceTracker()
{
qDebug("teste1");
filename = "/Users/marcomartins/Documents/QT/DisplUM/haarcascades/haarcascade_frontalface_alt_tree.xml";
/* load the classifier
note that I put the file in the same directory with this code */
cascade = ( CvHaarClassifierCascade* )cvLoad( filename, 0, 0, 0 );
/* setup memory buffer; needed by the face detector */
storage = cvCreateMemStorage( 0 );
/* initialize camera */
capture = cvCaptureFromCAM( 0 );
/* always check */
assert( cascade && storage && capture );
/* create a window */
cvNamedWindow( "video DisplUM", 1 );
}
void faceTracker::detectFaces( IplImage *img )
{
/* detect faces */
faces = cvHaarDetectObjects(
img,
cascade,
storage,
1.1,
3,
0 /*CV_HAAR_DO_CANNY_PRUNNING*/,
cvSize( 40, 40 ) );
/* for each face found, draw a red box */
for( i = 0 ; i < ( faces ? faces->total : 0 ) ; i++ ) {
CvRect *r = ( CvRect* )cvGetSeqElem( faces, i );
cvRectangle( img,
cvPoint( r->x, r->y ),
cvPoint( r->x + r->width, r->y + r->height ),
CV_RGB( 255, 0, 0 ), 1, 8, 0 );
qDebug("caras: %d", faces->total);
}
/* display video */
cvShowImage( "video", img );
}
void faceTracker::run( )
{
qDebug("teste2");
while( key != 'q' ) {
/* get a frame */
frame = cvQueryFrame( capture );
qDebug("teste3");
/* always check */
if( !frame ) break;
/* 'fix' frame */
cvFlip( frame, frame, 1 );
frame->origin = 0;
/* detect faces and display video */
detectFaces( frame );
/* quit if user press 'q' */
key = cvWaitKey( 10 );
}
/* free memory */
cvReleaseCapture( &capture );
cvDestroyWindow( "video" );
cvReleaseHaarClassifierCascade( &cascade );
cvReleaseMemStorage( &storage );
}
main code:
int main(int argc, char *argv[])
{
faceTracker * ft = new faceTracker();
ft->start();
}
thanks a lot!
The loop will only break if cvQueryFrame() returns a NULL frame or if the user presses q on the keyboard.
Add a debug so you know when the first situation happens:
frame = cvQueryFrame( capture );
if( !frame )
{
qDebug("cvQueryFrame failed!");
break;
}
Are you sure cvCaptureFromCAM(0) works ? Depending on the OS I have to pass -1 for it. But the fact is that you'll never know if cvCaptureFromCAM(0)succeeded because you don't check the return, and this might be the problem!
capture = cvCaptureFromCAM(0);
if (!capture)
{
qDebug("cvCaptureFromCAM failed!");
//exit(0); or whatever
}
EDIT:
Pay huge attention to this: you are creating a window named "video DisplUM" but you are trying to display the frames on a different window, named "video".
Anyway, it's also better if you change the window creation function to use the appropriate enum:
cvNamedWindow("video DisplUM", CV_WINDOW_AUTOSIZE);
and on faceTracker::run( ) comment detectFaces() for now and add a call to cvShowImage( "video DisplUM", frame );
Always be sure your application works with the minimum requirements before adding fancy stuffs, like face detection. My final suggestion is: write enough code just to capture the images from one thread and display them on a window, and then go from there.
Solution:
I can't create windows outside the main thread, that is why it was crashing. If i comment the window creation all works good (face detection included)
I ran into a similar issue. What I found is that I had to rebuild OpenCV and include the TBB libraries. This adds threading support to OpenCV. Once I did this, I was able to pop up windows in any thread I chose. I've tested this on versions 2.1 and 2.2, using both C and C++ implementations.