Files
game-physics/AntTweakBar/examples/TwGLCoreSDL.c
2017-10-11 15:01:05 +02:00

411 lines
15 KiB
C

// ---------------------------------------------------------------------------
//
// @file TwGLCoreSDL.c
// @brief An example that uses AntTweakBar with OpenGL Core Profile
// and SDL 1.3.
//
// AntTweakBar: http://anttweakbar.sourceforge.net/doc
// OpenGL: http://www.opengl.org
// SDL: http://www.libsdl.org
//
// @author Philippe Decaudin
//
// ---------------------------------------------------------------------------
#include <AntTweakBar.h>
#ifdef _WIN32
// MiniSDL13.h is provided to avoid the need of having SDL installed to
// recompile this example. Do not use it in your own programs, better
// install and use the actual SDL library SDK.
# define USE_MINI_SDL
#endif
//#define GL3_PROTOTYPES 1 ////
//#include <GL3/gl3.h> ////
#ifdef USE_MINI_SDL
# include "../src/MiniSDL13.h"
#else
# include <SDL/SDL.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#ifdef _WIN32
# include <windows.h> // required by gl.h
#endif
#include <GL/gl.h>
#include <GL/glu.h>
// In this example, we draw a simple rotating square using the OpenGL core profile
// (which requires much more code than with the compatibility profile).
// A tweak bar is created to allow the user to change the color of the
// rectangle and see its rotation.
// Part of OpenGL core interface is not directly accessible from the common
// OpenGL header and library (at least on windows) so we have to retrieve the
// core functions using glGetProcAddress. These functions are prefixed by
// underscore to avoid possible confict if a modified gl.h has been installed.
#ifdef _WIN32
# define glGetProcAddress wglGetProcAddress
#else
# define GLX_GLXEXT_LEGACY
# include <GL/glx.h>
# define glGetProcAddress glXGetProcAddressARB
#endif
#ifndef APIENTRY
# define APIENTRY
#endif
typedef GLuint (APIENTRY *PFNGLCreateShader)(GLenum type);
typedef void (APIENTRY *PFNGLDeleteShader)(GLuint shader);
typedef void (APIENTRY *PFNGLShaderSource)(GLuint shader, GLsizei count, const char* *str, const GLint *length);
typedef void (APIENTRY *PFNGLCompileShader)(GLuint shader);
typedef void (APIENTRY *PFNGLAttachShader)(GLuint program, GLuint shader);
typedef GLuint (APIENTRY *PFNGLCreateProgram)(void);
typedef void (APIENTRY *PFNGLLinkProgram)(GLuint program);
typedef void (APIENTRY *PFNGLUseProgram)(GLuint program);
typedef void (APIENTRY *PFNGLDeleteProgram)(GLuint program);
typedef void (APIENTRY *PFNGLGenBuffers)(GLsizei n, GLuint *buffers);
typedef void (APIENTRY *PFNGLBindBuffer)(GLenum target, GLuint buffer);
typedef void (APIENTRY *PFNGLVertexAttribPointer)(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer);
typedef void (APIENTRY *PFNGLEnableVertexAttribArray)(GLuint index);
typedef void (APIENTRY *PFNGLGenVertexArrays)(GLsizei n, GLuint *arrays);
typedef void (APIENTRY *PFNGLBindVertexArray)(GLuint array);
typedef void (APIENTRY *PFNGLDeleteVertexArrays)(GLsizei n, const GLuint *arrays);
typedef GLint (APIENTRY *PFNGLGetAttribLocation)(GLuint program, const char *name);
typedef GLint (APIENTRY *PFNGLGetUniformLocation)(GLuint program, const char *name);
typedef void (APIENTRY *PFNGLUniform1f)(GLint location, GLfloat v0);
typedef void (APIENTRY *PFNGLUniform3f)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
typedef void (APIENTRY *PFNGLBufferData)(GLenum target, ptrdiff_t size, const GLvoid *data, GLenum usage);
typedef void (APIENTRY *PFNGLDeleteBuffers)(GLsizei n, const GLuint *buffers);
PFNGLCreateShader _glCreateShader;
PFNGLDeleteShader _glDeleteShader;
PFNGLShaderSource _glShaderSource;
PFNGLCompileShader _glCompileShader;
PFNGLAttachShader _glAttachShader;
PFNGLCreateProgram _glCreateProgram;
PFNGLLinkProgram _glLinkProgram;
PFNGLUseProgram _glUseProgram;
PFNGLDeleteProgram _glDeleteProgram;
PFNGLGenBuffers _glGenBuffers;
PFNGLBindBuffer _glBindBuffer;
PFNGLVertexAttribPointer _glVertexAttribPointer;
PFNGLEnableVertexAttribArray _glEnableVertexAttribArray;
PFNGLGenVertexArrays _glGenVertexArrays;
PFNGLBindVertexArray _glBindVertexArray;
PFNGLDeleteVertexArrays _glDeleteVertexArrays;
PFNGLGetAttribLocation _glGetAttribLocation;
PFNGLGetUniformLocation _glGetUniformLocation;
PFNGLUniform1f _glUniform1f;
PFNGLUniform3f _glUniform3f;
PFNGLBufferData _glBufferData;
PFNGLDeleteBuffers _glDeleteBuffers;
#ifndef GL_ARRAY_BUFFER
# define GL_ARRAY_BUFFER 0x8892
#endif
#ifndef GL_STATIC_DRAW
# define GL_STATIC_DRAW 0x88E4
#endif
#ifndef GL_VERTEX_SHADER
# define GL_VERTEX_SHADER 0x8B31
#endif
#ifndef GL_FRAGMENT_SHADER
# define GL_FRAGMENT_SHADER 0x8B30
#endif
int LoadGLCoreFunctions()
{
_glCreateShader = (PFNGLCreateShader)glGetProcAddress("glCreateShader");
_glDeleteShader = (PFNGLDeleteShader)glGetProcAddress("glDeleteShader");
_glShaderSource = (PFNGLShaderSource)glGetProcAddress("glShaderSource");
_glCompileShader = (PFNGLCompileShader)glGetProcAddress("glCompileShader");
_glAttachShader = (PFNGLAttachShader)glGetProcAddress("glAttachShader");
_glCreateProgram = (PFNGLCreateProgram)glGetProcAddress("glCreateProgram");
_glLinkProgram = (PFNGLLinkProgram)glGetProcAddress("glLinkProgram");
_glUseProgram = (PFNGLUseProgram)glGetProcAddress("glUseProgram");
_glDeleteProgram = (PFNGLDeleteProgram)glGetProcAddress("glDeleteProgram");
_glGenBuffers = (PFNGLGenBuffers)glGetProcAddress("glGenBuffers");
_glBindBuffer = (PFNGLBindBuffer)glGetProcAddress("glBindBuffer");
_glVertexAttribPointer = (PFNGLVertexAttribPointer)glGetProcAddress("glVertexAttribPointer");
_glEnableVertexAttribArray = (PFNGLEnableVertexAttribArray)glGetProcAddress("glEnableVertexAttribArray");
_glGenVertexArrays = (PFNGLGenVertexArrays)glGetProcAddress("glGenVertexArrays");
_glBindVertexArray = (PFNGLBindVertexArray)glGetProcAddress("glBindVertexArray");
_glDeleteVertexArrays = (PFNGLDeleteVertexArrays)glGetProcAddress("glDeleteVertexArrays");
_glGetAttribLocation = (PFNGLGetAttribLocation)glGetProcAddress("glGetAttribLocation");
_glGetUniformLocation = (PFNGLGetUniformLocation)glGetProcAddress("glGetUniformLocation");
_glUniform1f = (PFNGLUniform1f)glGetProcAddress("glUniform1f");
_glUniform3f = (PFNGLUniform3f)glGetProcAddress("glUniform3f");
_glBufferData = (PFNGLBufferData)glGetProcAddress("glBufferData");
_glDeleteBuffers = (PFNGLDeleteBuffers)glGetProcAddress("glDeleteBuffers");
if (_glCreateShader == NULL || _glDeleteShader == NULL || _glShaderSource == NULL || _glCompileShader == NULL
|| _glAttachShader == NULL || _glCreateProgram == NULL || _glLinkProgram == NULL || _glUseProgram == NULL
|| _glDeleteProgram == NULL || _glGenBuffers == NULL || _glBindBuffer == NULL || _glVertexAttribPointer == NULL
|| _glEnableVertexAttribArray == NULL || _glGenVertexArrays == NULL || _glBindVertexArray == NULL
|| _glDeleteVertexArrays == NULL || _glGetAttribLocation == NULL || _glGetUniformLocation == NULL
|| _glUniform1f == NULL || _glUniform3f == NULL || _glBufferData == NULL || _glDeleteBuffers == NULL)
return 0;
else
return 1;
}
// Shaders globals
GLuint vshader, fshader, program, varray, buffer;
GLint cosa, sina, colorloc;
float angle = 0, quat[4];
float color[] = {0.8f, 1.0f, 0.2f};
float FLOAT_PI = 3.14159265f;
void InitRender()
{
// Vertex shader
char *vsource[] = {
"#version 150 core\n"
"uniform float cosa, sina;"
"in vec3 vertex;"
"void main() { gl_Position = vec4(cosa*vertex.x-sina*vertex.y, sina*vertex.x+cosa*vertex.y, 0, 1); }"
};
// Fragment shader
char *fsource[] = {
"#version 150 core\n"
"uniform vec3 color;"
"out vec4 fcolor;"
"void main() { fcolor = vec4(color, 1); }"
};
// Geometry vertex array
GLfloat vertices[] = {
-0.5f, 0.5f, 0,
-0.5f, -0.5f, 0,
0.5f, 0.5f, 0,
0.5f, -0.5f, 0
};
GLint vlocation;
// Compile and bind shaders
vshader = _glCreateShader(GL_VERTEX_SHADER);
fshader = _glCreateShader(GL_FRAGMENT_SHADER);
program = _glCreateProgram();
_glShaderSource(vshader, 1, vsource, NULL);
_glShaderSource(fshader, 1, fsource, NULL);
_glCompileShader(vshader);
_glCompileShader(fshader);
_glAttachShader(program, vshader);
_glAttachShader(program, fshader);
_glLinkProgram(program);
_glUseProgram(program);
cosa = _glGetUniformLocation(program, "cosa");
sina = _glGetUniformLocation(program, "sina");
colorloc = _glGetUniformLocation(program, "color");
// Create and bind vertex buffer
_glGenVertexArrays(1, &varray);
_glBindVertexArray(varray);
_glGenBuffers(1, &buffer);
_glBindBuffer(GL_ARRAY_BUFFER, buffer);
_glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
vlocation = _glGetAttribLocation(program, "vertex");
_glVertexAttribPointer(vlocation, 3, GL_FLOAT, GL_TRUE, 0, NULL);
_glEnableVertexAttribArray(vlocation);
// GL states
glDisable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
}
void UninitRender()
{
_glDeleteProgram(program);
_glDeleteShader(fshader);
_glDeleteShader(vshader);
_glDeleteBuffers(1, &buffer);
_glDeleteVertexArrays(1, &varray);
}
void Render()
{
_glUniform1f(cosa, (float)cos(angle));
_glUniform1f(sina, (float)sin(angle));
_glUniform3f(colorloc, color[0], color[1], color[2]);
_glBindVertexArray(varray);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
TwBar *CreateTweakBar()
{
TwBar *bar;
// Create a tweak bar
bar = TwNewBar("TweakBar");
TwDefine(" GLOBAL help='This example shows how to integrate AntTweakBar with SDL and OpenGL Core Profile.\n' "); // Message added to the help bar.
// Add variables
TwAddVarRW(bar, "Rotation", TW_TYPE_QUAT4F, &quat, " opened=true help='Rectangle rotation' ");
TwAddVarRW(bar, "Color", TW_TYPE_COLOR3F, &color, " opened=true help='Rectangle color' ");
return bar;
}
// SDL redefines main
#ifdef main
# undef main
#endif
int main()
{
const SDL_VideoInfo* video = NULL;
int width = 480, height = 480;
int bpp, flags;
int quit = 0;
// Initialize SDL, then get the current video mode and use it to create a SDL window.
if (SDL_Init(SDL_INIT_VIDEO) < 0)
{
fprintf(stderr, "Video initialization failed: %s\n", SDL_GetError());
SDL_Quit();
exit(1);
}
video = SDL_GetVideoInfo();
if (!video)
{
fprintf(stderr, "Video query failed: %s\n", SDL_GetError());
SDL_Quit();
exit(1);
}
// Request GL context to be OpenGL 3.2 Core Profile
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
// Other GL attributes
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
//SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
bpp = video->vfmt->BitsPerPixel;
flags = SDL_OPENGL | SDL_HWSURFACE;
if (!SDL_SetVideoMode(width, height, bpp, flags))
{
fprintf(stderr, "Video mode set failed: %s\n", SDL_GetError());
SDL_Quit();
exit(1);
}
SDL_WM_SetCaption("AntTweakBar example using OpenGL Core Profile and SDL", "AntTweakBar+GLCore+SDL");
// Enable SDL unicode and key-repeat
SDL_EnableUNICODE(1);
SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
// Load some OpenGL core functions
if (!LoadGLCoreFunctions())
{
fprintf(stderr, "OpenGL 3.2 not supported.\n");
SDL_Quit();
exit(1);
}
// Initialize AntTweakBar
if (!TwInit(TW_OPENGL_CORE, NULL)) {
fprintf(stderr, "AntTweakBar initialization failed: %s\n", TwGetLastError());
SDL_Quit();
exit(1);
}
// Tell the window size to AntTweakBar
TwWindowSize(width, height);
// Create a tweak bar
CreateTweakBar();
// Set OpenGL viewport
glViewport(0, 0, width, height);
// Prepare GL shaders and programs for drawing
InitRender();
// Main loop:
// - Draw scene
// - Process events
while (!quit)
{
SDL_Event event;
int handled;
GLenum error;
// Clear screen
glClearColor(0.5f, 0.75f, 0.8f, 1);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
// Update angle and draw geometry
angle = (float)SDL_GetTicks()/25.0f * (FLOAT_PI/180.0f);
quat[0] = quat[1] = 0;
quat[2] = (float)sin(angle/2.0f);
quat[3] = (float)cos(angle/2.0f);
Render();
// Draw tweak bars
TwDraw();
// Present frame buffer
SDL_GL_SwapBuffers();
// Process incoming events
while (SDL_PollEvent(&event))
{
// Send event to AntTweakBar
handled = TwEventSDL(&event, SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
// If event has not been handled by AntTweakBar, process it
if (!handled)
{
switch (event.type)
{
case SDL_QUIT: // Window is closed
quit = 1;
break;
case SDL_VIDEORESIZE: // Window size has changed
// Resize SDL video mode
width = event.resize.w;
height = event.resize.h;
if (!SDL_SetVideoMode(width, height, bpp, flags))
fprintf(stderr, "WARNING: Video mode set failed: %s\n", SDL_GetError());
// Resize OpenGL viewport
glViewport(0, 0, width, height);
// Restore OpenGL states
InitRender();
// TwWindowSize has been called by TwEventSDL,
// so it is not necessary to call it again here.
break;
}
}
}
while ((error = glGetError()) != GL_NO_ERROR)
fprintf(stderr, "GL error detected: 0x%04X\n", error);
} // End of main loop
// Terminate AntTweakBar
TwTerminate();
// Delete GL shaders and buffer
UninitRender();
// Terminate SDL
SDL_Quit();
return 0;
}