Finish SDL Intro, Curves




CS116b/CS216

Chris Pollett

Feb 24, 2014

Outline

Introduction

SDL2_image

New Makefile

BASE = MySdlApplication

all: $(BASE)

OS := $(shell uname -s)

ifeq ($(OS), Linux) # Science Center Linux Boxes
  CPPFLAGS = -I/home/l/i/lib175/usr/glew/include
  LDFLAGS += -L/home/l/i/lib175/usr/glew/lib -L/usr/X11R6/lib
  LIBS += -lGL -lGLU -lSDL2 -lSDL2_image
endif

ifeq ($(OS), Darwin) # Assume OS X
  CPPFLAGS += -D__MAC__ -I/usr/local/Cellar/glew/1.10.0/include/ --stdlib=libstdc++ -Wno-deprecated
  LDFLAGS += -framework SDL2 -framework SDL2_image -framework OpenGL -L/usr/local/Cellar/glew/1.10.0/lib/
endif

ifdef OPT 
  #turn on optimization
  CXXFLAGS += -O2
else 
  #turn on debugging
  CXXFLAGS += -g
endif

CXX = g++ 

OBJ = $(BASE).o ppm.o glsupport.o

$(BASE): $(OBJ)
	$(LINK.cpp) -o $@ $^ $(LIBS) -lGLEW 

clean:
	rm -f $(OBJ) $(BASE)

Changing the Books Code

onInit

bool MySdlApplication::onInit() {
    if(SDL_Init(SDL_INIT_EVERYTHING) < 0) {
        return false;
    }
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);

    /* Turn on double buffering with a 24bit Z buffer.
     * You may need to change this to 16 or 32 for your system */
    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
    SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);

    if((display = SDL_CreateWindow("My SDL Application",
        SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480,
        SDL_WINDOW_OPENGL)) == NULL) {
        return false;
    }

    /* Create our opengl context and attach it to our window */
    SDL_GLContext maincontext = SDL_GL_CreateContext(display);
    /* This makes our buffer swap syncronized with the 
      monitor's vertical refresh */
    SDL_GL_SetSwapInterval(1);

    glewInit();
    cout << (g_Gl2Compatible ?
        "Will use OpenGL 2.x / GLSL 1.0" : "Will use OpenGL 3.x / GLSL 1.3")
        << endl;
    if ((!g_Gl2Compatible) && !GLEW_VERSION_3_0)
        throw runtime_error(
            "Error: does not support OpenGL Shading Language v1.3");
    else if (g_Gl2Compatible && !GLEW_VERSION_2_0)
        throw runtime_error(
            "Error: does not support OpenGL Shading Language v1.0");

    initGLState();
    initShaders();
    initGeometry();
    initTextures();

    return true;
}

SDL Modified loadTextures

static void loadTexture(GLuint type, GLuint texHandle, const char *ppmFilename)
{
    int texWidth, texHeight;
//    vector<PackedPixel> pixData;

//    ppmRead(ppmFilename, texWidth, texHeight, pixData);
    SDL_Surface* newSurface = IMG_Load(ppmFilename); // read in image
    SDL_Surface* returnSurface;
    if(newSurface == NULL) {
        cout << ":_( Surface null" <<endl;
        return;
    }
    returnSurface = SDL_ConvertSurfaceFormat(newSurface,
        SDL_PIXELFORMAT_RGB24, 0); // need to convert to RGB from RGBA
    texWidth = returnSurface->w;
    texHeight = returnSurface->h;
    glActiveTexture(type);
    glBindTexture(GL_TEXTURE_2D, texHandle);
//    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, texWidth,
//                 texHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, &pixData[0]);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, texWidth,
                 texHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, returnSurface->pixels);
    SDL_FreeSurface(newSurface);
    SDL_FreeSurface(returnSurface);
    checkGlErrors();
}

onEvent

void MySdlApplication::onEvent(SDL_Event* event) {
    switch(event->type)
    {
        case SDL_QUIT:
            running = false;
            break;
        case SDL_KEYUP:
            keyboard(SDL_GetKeyName(event->key.keysym.sym));
            break;
        case SDL_MOUSEBUTTONDOWN:
            mouse(event->button);
            break;
        case SDL_MOUSEBUTTONUP:
            mouse(event->button);
            break;
        case SDL_MOUSEMOTION:
            motion(event->motion.x, event->motion.y);
            break;
    }
}

void MySdlApplication::keyboard(const char* key)
{
    switch (key[0])
    {
        case 27: //ESC
            exit(0);
        case 'H':
            cout << " ============== H E L P ==============\n\n"
            << "h\t\thelp menu\n"
            << "s\t\tsave screenshot\n"
            << "t\t\ttoggle between shaders\n"
            << "drag left mouse to rotate\n" << endl;
            break;
        case 'S':
            glFlush();
            writePpmScreenshot(g_windowWidth, g_windowHeight, "out.ppm");
            break;
        case 'T':
            g_activeShader++;
            if(g_activeShader >= g_numShaders) {
                g_activeShader = 0;
            }
            break;
    }
}

void MySdlApplication::mouse(SDL_MouseButtonEvent button)
{
    g_mouseClickX = button.x;
    g_mouseClickY = g_windowHeight - button.y - 1;

    g_mouseLClickButton |= (button.button == SDL_BUTTON_LEFT &&
                            button.state == SDL_PRESSED);
    g_mouseRClickButton |= (button.button == SDL_BUTTON_RIGHT &&
                            button.state == SDL_PRESSED);
    g_mouseMClickButton |= (button.button == SDL_BUTTON_MIDDLE &&
                            button.state == SDL_PRESSED);

    g_mouseLClickButton &= !(button.button == SDL_BUTTON_LEFT &&
                            button.state == SDL_RELEASED);
    g_mouseRClickButton &= !(button.button == SDL_BUTTON_RIGHT &&
                             button.state == SDL_RELEASED);
    g_mouseMClickButton &= !(button.button == SDL_BUTTON_MIDDLE &&
                             button.state == SDL_RELEASED);

    g_mouseClickDown = g_mouseLClickButton || g_mouseRClickButton ||
        g_mouseMClickButton;
}

void MySdlApplication::motion(const int x, const int y)
{
    const double dx = x - g_mouseClickX;
    const double dy = g_windowHeight - y - 1 - g_mouseClickY;

    Matrix4 m;
    if (g_mouseLClickButton && !g_mouseRClickButton) {
        // left button down?
        m = Matrix4::makeXRotation(-dy) * Matrix4::makeYRotation(dx);
    } else if (g_mouseRClickButton && !g_mouseLClickButton) {
        // right button down?
        m = Matrix4::makeTranslation(Cvec3(dx, dy, 0) * 0.01);
    } else if (g_mouseMClickButton ||
               (g_mouseLClickButton && g_mouseRClickButton)) {
        // middle or (left and right) button down?
        m = Matrix4::makeTranslation(Cvec3(0, 0, -dy) * 0.01);
    }

    if (g_mouseClickDown) {
        g_objectRbt[0] *= m; // Simply right-multiply is WRONG
    }

    g_mouseClickX = x;
    g_mouseClickY = g_windowHeight - y - 1;
}

onRender

void MySdlApplication::onRender() {
    glUseProgram(g_shaderStates[g_activeShader]->program);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    // clear framebuffer color&depth
    drawStuff();
    
    SDL_GL_SwapWindow(display);
    checkGlErrors();
}

Quiz

Which of the following statements is true?

  1. The similarity dimension of an object in `k`-dimensions is always an integer value.
  2. The Perlin noise approach to random terrain generation might involve using Bezier curves or patches.
  3. SDL is a modern replacement for OpenGL and DirectX.

Bezier curves and their Friends

Bezier Curve Refresher

A Cubic Bezier Curve

More Bezier Curve Refresher

Curves in Space