0

I am struggling with loading src/up.bmp and showing it in 2D overlaid on my 3D environment. But nothing does appear. Where is my mistake?

#define SDL_MAIN_HANDLED

#include <math.h>
#include <SDL.h>
#include <iostream>
#include <GL/freeglut.h>

using namespace std;

int w_width = 800;
int w_height = 500;
string w_title = "Model viewer";
float line_width = 2.0f;
float camera_radius = 100.0f;
float axis_size = 20.0;

SDL_Surface* button1;
GLuint TextureID;


void draw_button(SDL_Surface* button)
{

    glGenTextures(1, &TextureID);
    glBindTexture(GL_TEXTURE_2D, TextureID);
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);

    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    gluBuild2DMipmaps(GL_TEXTURE_2D, 3, button->w, button->h, GL_RGB, GL_UNSIGNED_BYTE, button->pixels);
}

void display()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glClearColor(1.0f, 1.0f, 1.0f, 1.0f);

    const float ratio = (float)glutGet(GLUT_SCREEN_WIDTH) / (float)glutGet(GLUT_SCREEN_HEIGHT);
    static double t = 0.0;
    const float deg2rad = 3.1415926f / 180.0f;
    float cam_x = camera_radius*float(cos(20.0f*deg2rad))*float(cos(0.5235*deg2rad));
    float cam_y = camera_radius*float(sin(20.f*deg2rad))*float(cos(0.5235*deg2rad));
    float cam_z = camera_radius*float(sin(0.5235*deg2rad));

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(90, ratio, 0.01, 10000);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    gluLookAt(cam_x, cam_y, cam_z, 0, 0, 0, 0, 0, 1);

    // sphere
    glPushMatrix();
    glColor3ub(255, 0, 0);
    glTranslated(
        0,
        0,
        0);
    glutSolidSphere(1, 20, 20);
    glPopMatrix();

    draw_button(button1);

    glFlush();
    glutSwapBuffers();
}

void timer_event(int value)
{
    glutPostRedisplay();
    glutTimerFunc(100, timer_event, value);
}

int main(int argc, char *argv[])
{
    glutInit(&argc, argv);
    glutSetOption(GLUT_MULTISAMPLE, 8);
    glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE | GLUT_MULTISAMPLE);

    glutTimerFunc(30, timer_event, 1);
    glutInitWindowSize(w_width, w_height);
    glutInitWindowPosition(10, 10);
    glutCreateWindow(argv[0]);
    glutSetWindowTitle(w_title.c_str());
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glEnable(GL_BLEND);


    glutDisplayFunc(display);

    glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE,
        GLUT_ACTION_GLUTMAINLOOP_RETURNS);

    glEnable(GL_COLOR_MATERIAL);
    glEnable(GL_TEXTURE_2D);
    button1 = SDL_LoadBMP("src/up.bmp");
    if (button1 == NULL)
    {
        cout << "Image not found" << endl;
        exit(1);
    }
    glutMainLoop();

    SDL_FreeSurface(button1);

    return 0;
}
klutt
  • 30,332
  • 17
  • 55
  • 95
javin
  • 3
  • 1
  • You load the image in a surface but never show this surface on the screen, take a look to `SDL_Flip()` – David Ranieri Oct 27 '17 at 05:29
  • @KeineLust, many thanks, however still error: `'SDL_Flip': identifier not found` – javin Oct 27 '17 at 05:41
  • @javin what are you trying to do? You create new texture on each frame (which basically means you'll run out of memory fairly quickly) but never use it. You need to e.g. draw a quad with adequate texture coordinates & texturing enabled. Even more, your `draw_button` function don't take position - so where should it draw, exactly? Look at any "opengl textured triangle" articles (probably leagacy ones, as you don't seem to be using shaders). Or even start with untextured triangle/quad at the place you want it to be. SDL_Flip have absolutely no purpose here as you don't have SDL-managed window. – keltar Oct 27 '17 at 06:21
  • @keltar, I will. However, for the current code, what is the solution? – javin Oct 27 '17 at 06:28

1 Answers1

0

Here is a minimal example I can come up with:

#define SDL_MAIN_HANDLED

#include <math.h>
#include <SDL.h>
#include <iostream>
#include <GL/gl.h>
#include <GL/freeglut.h>

using namespace std;

int w_width = 800;
int w_height = 500;
string w_title = "Model viewer";
float line_width = 2.0f;
float camera_radius = 100.0f;
float axis_size = 20.0;

SDL_Surface* button1;
GLuint TextureID;


static void prepare_texture(SDL_Surface *button)
{
    glGenTextures(1, &TextureID);
    glBindTexture(GL_TEXTURE_2D, TextureID);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    // convert surface to RGB8
    SDL_Surface *rgb = SDL_CreateRGBSurface(0, button->w, button->h, 24, 0xff, 0xff00, 0xff0000, 0);
    SDL_BlitSurface(button, NULL, rgb, NULL);

    gluBuild2DMipmaps(GL_TEXTURE_2D, 3, button->w, button->h, GL_RGB, GL_UNSIGNED_BYTE, rgb->pixels);

    SDL_FreeSurface(rgb);
}

static void draw_button()
{
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
    glBindTexture(GL_TEXTURE_2D, TextureID);
    glBegin(GL_QUADS);
        glTexCoord2f(0.0f, 1.0f);
        glVertex2f(0.1f, 0.1f);
        glTexCoord2f(0.0f, 0.0f);
        glVertex2f(0.1f, 0.2f);
        glTexCoord2f(1.0f, 0.0f);
        glVertex2f(0.2f, 0.2f);
        glTexCoord2f(1.0f, 1.0f);
        glVertex2f(0.2f, 0.1f);
    glEnd();
}

void display()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glClearColor(1.0f, 1.0f, 1.0f, 1.0f);

    const float ratio = (float)glutGet(GLUT_SCREEN_WIDTH) / (float)glutGet(GLUT_SCREEN_HEIGHT);
    static double t = 0.0;
    const float deg2rad = 3.1415926f / 180.0f;
    float cam_x = camera_radius*float(cos(20.0f*deg2rad))*float(cos(0.5235*deg2rad));
    float cam_y = camera_radius*float(sin(20.f*deg2rad))*float(cos(0.5235*deg2rad));
    float cam_z = camera_radius*float(sin(0.5235*deg2rad));

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(90, ratio, 0.01, 10000);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    gluLookAt(cam_x, cam_y, cam_z, 0, 0, 0, 0, 0, 1);

    // sphere
    glPushMatrix();
    glColor3ub(255, 0, 0);
    glTranslated(
            0,
            0,
            0);
    glutSolidSphere(1, 20, 20);
    glPopMatrix();

    draw_button();

    glFlush();
    glutSwapBuffers();
}

void timer_event(int value)
{
    glutPostRedisplay();
    glutTimerFunc(100, timer_event, value);
}

int main(int argc, char *argv[])
{
    glutInit(&argc, argv);
    glutSetOption(GLUT_MULTISAMPLE, 8);
    glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE | GLUT_MULTISAMPLE);

    glutTimerFunc(30, timer_event, 1);
    glutInitWindowSize(w_width, w_height);
    glutInitWindowPosition(10, 10);
    glutCreateWindow(argv[0]);
    glutSetWindowTitle(w_title.c_str());
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glEnable(GL_BLEND);


    glutDisplayFunc(display);

    glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE,
            GLUT_ACTION_GLUTMAINLOOP_RETURNS);

    glEnable(GL_COLOR_MATERIAL);
    glEnable(GL_TEXTURE_2D);
    button1 = SDL_LoadBMP("up.bmp");
    if (button1 == NULL)
    {
        cout << "Image not found" << endl;
        exit(1);
    }

    prepare_texture(button1);
    SDL_FreeSurface(button1);

    glutMainLoop();

    return 0;
}

Note identity projection, which maps screen to [-1,1] range; you may want something more like gluOrtho2D.

keltar
  • 17,711
  • 2
  • 37
  • 42