CS116b/CS216
Chris Pollett
Feb 24, 2014
#ifndef _MYSDLAPPLICATION_H_
#define _MYSDLAPPLICATION_H_
#include <iostream>
#include <SDL2/SDL.h>
#ifdef __WIN32__
#undef main
#include <SDL2/SDL_image.h>
#else
#include <SDL2_image/SDL_image.h>
#endif
class MySdlApplication
{
private:
bool running;
SDL_Window* display;
void keyboard(const char * key);
void mouse(SDL_MouseButtonEvent button);
void motion(const int x, const int y);
public:
MySdlApplication();
int onExecute();
bool onInit();
void onEvent(SDL_Event* Event);
void onLoop();
void onRender();
void onCleanup();
};
#endif
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)
int MySdlApplication::onExecute() {
if(onInit() == false) {
return -1;
}
SDL_Event Event;
while(running) {
while(SDL_PollEvent(&Event)) {
onEvent(&Event);
}
onLoop();
onRender();
}
onCleanup();
return 0;
}
int main(int argc, const char * argv[])
{
MySdlApplication application;
return application.onExecute();
}
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;
}
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();
}
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;
}
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();
}
Which of the following statements is true?