REFACTOR : begin consolidating common code for OpenGL HUD interfaces

This commit is contained in:
Aaron Culliney 2015-04-11 00:30:23 -07:00
parent 5712850e84
commit e876cd03b6
9 changed files with 433 additions and 373 deletions

View File

@ -10,6 +10,9 @@ android {
targetSdkVersion 10
versionCode 1
versionName "0.9.1"
ndk {
moduleName "apple2ix"
}
}
signingConfigs {
release {
@ -27,6 +30,7 @@ android {
}
debug {
debuggable true
jniDebuggable true
}
}
productFlavors {

View File

@ -59,10 +59,15 @@
#import <CoreFoundation/CoreFoundation.h>
#endif
// custom annotations
#define INPARM
#define OUTPARM
#define INOUT
#if VIDEO_OPENGL
#include "video_util/glUtil.h"
#define CRASH_APP_ON_LOAD_BECAUSE_YAY_GJ_APPLE 0
// 2014/11/29 -- Yay GJ Apple! ... you would think that early app lifecycle calls to glGetError() would not segfault on Macs
// 2015/04/01 ... early calls to glGetError()--before a context exists--causes segfaults on MacOS X
extern bool safe_to_do_opengl_logging;
static inline GLenum safeGLGetError(void) {
if (safe_to_do_opengl_logging) {

View File

@ -64,7 +64,7 @@ extern void (*joydriver_setTouchButtonValues)(char button0Val, char button1Val);
extern void (*joydriver_setTouchAxisType)(touchjoy_axis_type_t axisType);
// set the axis button parameters (7bit ASCII characters or MOUSETEXT values)
extern void (*joydriver_setTouchAxisValues)(char up, char left, char right, char down);
extern void (*joydriver_setTouchAxisValues)(char north, char west, char east, char south);
#endif // TOUCH_JOYSTICK

View File

@ -73,8 +73,8 @@ static void _create_message_model(void) {
messageObj->positionSize = 4; // x,y,z coordinates
messageObj->positionArraySize = sizeof(messageObj_positions);
messageObj->texcoords = malloc(sizeof(messageObj_texcoords));
memcpy(messageObj->texcoords, &messageObj_texcoords[0], sizeof(messageObj_texcoords));
messageObj->texCoords = malloc(sizeof(messageObj_texcoords));
memcpy(messageObj->texCoords, &messageObj_texcoords[0], sizeof(messageObj_texcoords));
messageObj->texcoordType = GL_FLOAT;
messageObj->texcoordSize = 2; // s,t coordinates
messageObj->texcoordArraySize = sizeof(messageObj_texcoords);
@ -89,7 +89,7 @@ static void _create_message_model(void) {
messageObj->elementType = GL_UNSIGNED_SHORT;
messageObj->elementArraySize = sizeof(indices);
mdlDestroyModel(cpuMessageObjModel);
mdlDestroyModel(&cpuMessageObjModel);
cpuMessageObjModel = messageObj;
}
@ -124,13 +124,13 @@ static void _create_message_VAO_VBOs(const GLModel *messageModel, GLuint *messag
0); // What is the offset in the VBO to the position data?
#endif
if (messageModel->texcoords) {
if (messageModel->texCoords) {
// Create a VBO to store texcoords
glGenBuffers(1, texcoordBufferName);
glBindBuffer(GL_ARRAY_BUFFER, *texcoordBufferName);
// Allocate and load texcoord data into the VBO
glBufferData(GL_ARRAY_BUFFER, messageModel->texcoordArraySize, messageModel->texcoords, GL_STATIC_DRAW);
glBufferData(GL_ARRAY_BUFFER, messageModel->texcoordArraySize, messageModel->texCoords, GL_STATIC_DRAW);
#if USE_VAO
// Enable the texcoord attribute for this VAO
@ -269,7 +269,7 @@ static void cpuanim_destroy(void) {
cpuMessageObjTexcoordBufferName = UNINITIALIZED_GL;
cpuMessageObjElementBufferName = UNINITIALIZED_GL;
mdlDestroyModel(cpuMessageObjModel);
mdlDestroyModel(&cpuMessageObjModel);
cpuMessageObjModel = NULL;
}

View File

@ -12,6 +12,8 @@
#include "common.h"
#include "video/glvideo.h"
#define MODEL_DEPTH -0.03125
#define AXIS_TEMPLATE_COLS 5
#define AXIS_TEMPLATE_ROWS 5
@ -45,6 +47,8 @@ enum {
TOUCHED_BOTH,
};
// general configurations
static bool isAvailable = false;
static bool isEnabled = true;
static bool isVisible = true;
@ -66,6 +70,7 @@ static glanim_t touchjoyAnimation = { 0 };
static int viewportWidth = 0;
static int viewportHeight = 0;
#warning FIXME TODO ... consolidate these into internal structs ....
static int axisSideX = 0;
static int axisSideXMax = 0;
static int axisSideY = 0;
@ -79,250 +84,47 @@ static int buttSideYMax = 0;
// touch axis variables
static GLModel *touchAxisObjModel = NULL;
static GLuint touchAxisObjVAOName = UNINITIALIZED_GL;
static GLuint touchAxisObjTextureName = UNINITIALIZED_GL;
static GLuint touchAxisObjPosBufferName = UNINITIALIZED_GL;
static GLuint touchAxisObjTexcoordBufferName = UNINITIALIZED_GL;
static GLuint touchAxisObjElementBufferName = UNINITIALIZED_GL;
static uint8_t touchAxisObjFB[AXIS_FB_WIDTH * AXIS_FB_HEIGHT] = { 0 };
static uint8_t touchAxisObjPixels[AXIS_FB_WIDTH * AXIS_FB_HEIGHT * 4] = { 0 };// RGBA8888
static bool axisTextureDirty = true;
static bool axisModelDirty = true;
static int axisCenterX = 480;
static int axisCenterY = 320;
static int axisCenterX = 240;
static int axisCenterY = 160;
static int trackingAxisIndex = TOUCHED_NONE;
static struct timespec axisTimingBegin = { 0 };
static touchjoy_axis_type_t touchjoy_axisType = AXIS_EMULATED_DEVICE;
static uint8_t northChar = MOUSETEXT_UP;
static uint8_t westChar = MOUSETEXT_LEFT;
static uint8_t eastChar = MOUSETEXT_RIGHT;
static uint8_t southChar = MOUSETEXT_DOWN;
// button object variables
static GLModel *buttonObjModel = NULL;
static GLuint buttonObjVAOName = UNINITIALIZED_GL;
static GLuint buttonObjTextureName = UNINITIALIZED_GL;
static GLuint buttonObjPosBufferName = UNINITIALIZED_GL;
static GLuint buttonObjTexcoordBufferName = UNINITIALIZED_GL;
static GLuint buttonObjElementBufferName = UNINITIALIZED_GL;
static uint8_t buttonObjFB[BUTTON_FB_WIDTH * BUTTON_FB_HEIGHT] = { 0 };
static uint8_t buttonObjPixels[BUTTON_FB_WIDTH * BUTTON_FB_HEIGHT * 4] = { 0 };// RGBA8888
static bool buttonTextureDirty = true;
static bool buttonModelDirty = true;
static int buttonCenterX = 480;
static int buttonCenterY = 320;
static int buttonCenterX = 240;
static int buttonCenterY = 160;
static int trackingButtonIndex = TOUCHED_NONE;
static int touchDownButton = TOUCHED_BUTTON0;
static int upButtonAxisButton = TOUCHED_BOTH;
static int downButtonAxisButton = TOUCHED_BUTTON1;
static int buttonSwitchThreshold = BUTTON_SWITCH_THRESHOLD_DEFAULT;
static struct timespec buttonTimingBegin = { 0 };
// configurables for current touchjoy
static int touchDownButton = TOUCHED_BUTTON0;
static int northButton = TOUCHED_BOTH;
static int southButton = TOUCHED_BUTTON1;
static uint8_t button0Char = MOUSETEXT_OPENAPPLE;
static uint8_t buttonActiveChar = MOUSETEXT_OPENAPPLE;
static uint8_t button1Char = MOUSETEXT_CLOSEDAPPLE;
static uint8_t buttonBothChar = '+';
static touchjoy_axis_type_t touchjoy_axisType = AXIS_EMULATED_DEVICE;
static uint8_t upChar = MOUSETEXT_UP;
static uint8_t leftChar = MOUSETEXT_LEFT;
static uint8_t rightChar = MOUSETEXT_RIGHT;
static uint8_t downChar = MOUSETEXT_DOWN;
static uint8_t buttonActiveChar = MOUSETEXT_OPENAPPLE;
static int buttonSwitchThreshold = BUTTON_SWITCH_THRESHOLD_DEFAULT;
// ----------------------------------------------------------------------------
static GLModel *_create_model(GLfloat skew_x, GLfloat skew_y, GLfloat obj_w, GLfloat obj_h) {
/* 2...3
* .
* .
* .
* 0...1
*/
const GLfloat obj_positions[] = {
skew_x, skew_y, -0.03125, 1.0,
skew_x+obj_w, skew_y, -0.03125, 1.0,
skew_x, skew_y+obj_h, -0.03125, 1.0,
skew_x+obj_w, skew_y+obj_h, -0.03125, 1.0,
};
const GLfloat obj_texcoords[] = {
0.0, 1.0,
1.0, 1.0,
0.0, 0.0,
1.0, 0.0,
};
const GLushort indices[] = {
0, 1, 2, 2, 1, 3
};
GLModel *obj = calloc(1, sizeof(GLModel));
obj->numVertices = 4;
obj->numElements = 6;
obj->positions = malloc(sizeof(obj_positions));
memcpy(obj->positions, &obj_positions[0], sizeof(obj_positions));
obj->positionType = GL_FLOAT;
obj->positionSize = 4; // x,y,z coordinates
obj->positionArraySize = sizeof(obj_positions);
obj->texcoords = malloc(sizeof(obj_texcoords));
memcpy(obj->texcoords, &obj_texcoords[0], sizeof(obj_texcoords));
obj->texcoordType = GL_FLOAT;
obj->texcoordSize = 2; // s,t coordinates
obj->texcoordArraySize = sizeof(obj_texcoords);
obj->normals = NULL;
obj->normalType = GL_NONE;
obj->normalSize = GL_NONE;
obj->normalArraySize = 0;
obj->elements = malloc(sizeof(indices));
memcpy(obj->elements, &indices[0], sizeof(indices));
obj->elementType = GL_UNSIGNED_SHORT;
obj->elementArraySize = sizeof(indices);
return obj;
}
static void _create_VAO_VBOs(const GLModel *model, GLuint *vaoName, GLuint *posBufferName, GLuint *texcoordBufferName, GLuint *elementBufferName) {
// Create a vertex array object (VAO) to cache model parameters
#if USE_VAO
glGenVertexArrays(1, vaoName);
glBindVertexArray(*vaoName);
#endif
// Create a vertex buffer object (VBO) to store positions and load data
glGenBuffers(1, posBufferName);
glBindBuffer(GL_ARRAY_BUFFER, *posBufferName);
glBufferData(GL_ARRAY_BUFFER, model->positionArraySize, model->positions, GL_DYNAMIC_DRAW);
#if USE_VAO
// Enable the position attribute for this VAO
glEnableVertexAttribArray(POS_ATTRIB_IDX);
// Get the size of the position type so we can set the stride properly
GLsizei posTypeSize = _get_gl_type_size(model->positionType);
// Set up parmeters for position attribute in the VAO including,
// size, type, stride, and offset in the currenly bound VAO
// This also attaches the position VBO to the VAO
glVertexAttribPointer(POS_ATTRIB_IDX, // What attibute index will this array feed in the vertex shader (see buildProgram)
model->positionSize, // How many elements are there per position?
model->positionType, // What is the type of this data?
GL_FALSE, // Do we want to normalize this data (0-1 range for fixed-pont types)
model->positionSize*posTypeSize, // What is the stride (i.e. bytes between positions)?
0); // What is the offset in the VBO to the position data?
#endif
if (model->texcoords) {
// Create a VBO to store texcoords
glGenBuffers(1, texcoordBufferName);
glBindBuffer(GL_ARRAY_BUFFER, *texcoordBufferName);
// Allocate and load texcoord data into the VBO
glBufferData(GL_ARRAY_BUFFER, model->texcoordArraySize, model->texcoords, GL_DYNAMIC_DRAW);
#if USE_VAO
// Enable the texcoord attribute for this VAO
glEnableVertexAttribArray(TEXCOORD_ATTRIB_IDX);
// Get the size of the texcoord type so we can set the stride properly
GLsizei texcoordTypeSize = _get_gl_type_size(model->texcoordType);
// Set up parmeters for texcoord attribute in the VAO including,
// size, type, stride, and offset in the currenly bound VAO
// This also attaches the texcoord VBO to VAO
glVertexAttribPointer(TEXCOORD_ATTRIB_IDX, // What attibute index will this array feed in the vertex shader (see buildProgram)
model->texcoordSize, // How many elements are there per texture coord?
model->texcoordType, // What is the type of this data in the array?
GL_TRUE, // Do we want to normalize this data (0-1 range for fixed-point types)
model->texcoordSize*texcoordTypeSize, // What is the stride (i.e. bytes between texcoords)?
0); // What is the offset in the VBO to the texcoord data?
#endif
}
// Create a VBO to vertex array elements
// This also attaches the element array buffer to the VAO
glGenBuffers(1, elementBufferName);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, *elementBufferName);
// Allocate and load vertex array element data into VBO
glBufferData(GL_ELEMENT_ARRAY_BUFFER, model->elementArraySize, model->elements, GL_DYNAMIC_DRAW);
GL_ERRLOG("gltouchjoy finished creating VAO/VBOs");
}
static void _destroy_VAO_VBOs(GLuint vaoName, GLuint posBufferName, GLuint texcoordBufferName, GLuint elementBufferName) {
// Bind the VAO so we can get data from it
#if USE_VAO
glBindVertexArray(vaoName);
// For every possible attribute set in the VAO
for (GLuint index = 0; index < 16; index++) {
// Get the VBO set for that attibute
GLuint bufName = 0;
glGetVertexAttribiv(index , GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, (GLint*)&bufName);
// If there was a VBO set...
if (bufName) {
//...delete the VBO
glDeleteBuffers(1, &bufName);
}
}
// Get any element array VBO set in the VAO
{
GLuint bufName = 0;
glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, (GLint*)&bufName);
// If there was a element array VBO set in the VAO
if (bufName) {
//...delete the VBO
glDeleteBuffers(1, &bufName);
}
}
// Finally, delete the VAO
glDeleteVertexArrays(1, &vaoName);
#else
glDeleteBuffers(1, &posBufferName);
glDeleteBuffers(1, &texcoordBufferName);
glDeleteBuffers(1, &elementBufferName);
#endif
GL_ERRLOG("gltouchjoy destroying VAO/VBOs");
}
static GLuint _create_texture(GLvoid *pixels, int w, int h) {
GLuint texName = UNINITIALIZED_GL;
// Create a texture object to apply to model
glGenTextures(1, &texName);
glBindTexture(GL_TEXTURE_2D, texName);
// Set up filter and wrap modes for this texture object
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
// Indicate that pixel rows are tightly packed
// (defaults to stride of 4 which is kind of only good for
// RGBA or FLOAT data types)
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
// register texture with OpenGL
glTexImage2D(GL_TEXTURE_2D, /*level*/0, /*internal format*/GL_RGBA, w, h, /*border*/0, /*format*/GL_RGBA, GL_UNSIGNED_BYTE, pixels);
GL_ERRLOG("gltouchjoy texture");
return texName;
}
static void _setup_object(char *submenu, unsigned int cols, unsigned int rows, uint8_t *fb, unsigned int fb_w, unsigned int fb_h, uint8_t *pixels) {
// render template into indexed fb
@ -347,18 +149,18 @@ static void _setup_object(char *submenu, unsigned int cols, unsigned int rows, u
}
static void _setup_axis_object(void) {
axisTemplate[0][2] = upChar;
axisTemplate[2][0] = leftChar;
axisTemplate[2][4] = rightChar;
axisTemplate[4][2] = downChar;
_setup_object(axisTemplate[0], AXIS_TEMPLATE_COLS, AXIS_TEMPLATE_ROWS, touchAxisObjFB, AXIS_FB_WIDTH, AXIS_FB_HEIGHT, touchAxisObjPixels);
axisTextureDirty = true;
axisTemplate[0][2] = northChar;
axisTemplate[2][0] = westChar;
axisTemplate[2][4] = eastChar;
axisTemplate[4][2] = southChar;
_setup_object(axisTemplate[0], AXIS_TEMPLATE_COLS, AXIS_TEMPLATE_ROWS, touchAxisObjFB, AXIS_FB_WIDTH, AXIS_FB_HEIGHT, touchAxisObjModel->texPixels);
touchAxisObjModel->texDirty = true;
}
static void _setup_button_object(void) {
buttonTemplate[0][0] = buttonActiveChar;
_setup_object(buttonTemplate[0], BUTTON_TEMPLATE_COLS, BUTTON_TEMPLATE_ROWS, buttonObjFB, BUTTON_FB_WIDTH, BUTTON_FB_HEIGHT, buttonObjPixels);
buttonTextureDirty = true;
_setup_object(buttonTemplate[0], BUTTON_TEMPLATE_COLS, BUTTON_TEMPLATE_ROWS, buttonObjFB, BUTTON_FB_WIDTH, BUTTON_FB_HEIGHT, buttonObjModel->texPixels);
buttonObjModel->texDirty = true;
}
static inline void _screen_to_model(float x, float y, float *screenX, float *screenY) {
@ -373,12 +175,7 @@ static void _model_to_screen(float screenCoords[4], GLModel *model) {
float x1 = -1.0;
float y1 = -1.0;
#if PERSPECTIVE
#error TODO FIXME we really should do it this way regardless of whether we are using PERSPECTIVE ...
// project models to screen space for touch handling
GLfloat mvp[16];
#else
#warning TODO FIXME ... should really use matrix calculations (assuming identity/orthographic for now)
#warning NOTE: we possibly should use matrix calculations (but assuming HUD elements are identity/orthographic for now)
GLfloat *positions = (GLfloat *)(model->positions);
unsigned int stride = model->positionSize;
unsigned int len = model->positionArraySize/_get_gl_type_size(model->positionType);
@ -399,7 +196,6 @@ static void _model_to_screen(float screenCoords[4], GLModel *model) {
y1 = y;
}
}
#endif
// OpenGL screen origin is bottom-left (Android is top-left)
float yFlip0 = viewportHeight - (y1 * viewportHeight);
@ -414,49 +210,28 @@ static void _model_to_screen(float screenCoords[4], GLModel *model) {
static void gltouchjoy_init(void) {
LOG("gltouchjoy_init ...");
mdlDestroyModel(touchAxisObjModel);
mdlDestroyModel(buttonObjModel);
mdlDestroyModel(&touchAxisObjModel);
mdlDestroyModel(&buttonObjModel);
touchAxisObjModel = _create_model(-1.05, -1.0, AXIS_OBJ_W, AXIS_OBJ_H);
touchAxisObjVAOName = UNINITIALIZED_GL;
touchAxisObjPosBufferName = UNINITIALIZED_GL;
touchAxisObjTexcoordBufferName = UNINITIALIZED_GL;
touchAxisObjElementBufferName = UNINITIALIZED_GL;
_create_VAO_VBOs(touchAxisObjModel, &touchAxisObjVAOName, &touchAxisObjPosBufferName, &touchAxisObjTexcoordBufferName, &touchAxisObjElementBufferName);
if (touchAxisObjPosBufferName == UNINITIALIZED_GL || touchAxisObjTexcoordBufferName == UNINITIALIZED_GL || touchAxisObjElementBufferName == UNINITIALIZED_GL)
{
touchAxisObjModel = mdlCreateQuad(-1.05, -1.0, AXIS_OBJ_W, AXIS_OBJ_H, MODEL_DEPTH, AXIS_FB_WIDTH, AXIS_FB_HEIGHT, GL_RGBA); // RGBA8888
if (!touchAxisObjModel) {
LOG("gltouchjoy not initializing axis");
return;
}
touchAxisObjTextureName = _create_texture(touchAxisObjPixels, AXIS_FB_WIDTH, AXIS_FB_HEIGHT);
if (touchAxisObjTextureName == UNINITIALIZED_GL) {
LOG("gltouchjoy not initializing axis: texture error");
return;
}
_setup_axis_object();
// button object
buttonObjModel = _create_model(1.05-BUTTON_OBJ_W, -1.0, BUTTON_OBJ_W, BUTTON_OBJ_H);
buttonObjVAOName = UNINITIALIZED_GL;
buttonObjPosBufferName = UNINITIALIZED_GL;
buttonObjTexcoordBufferName = UNINITIALIZED_GL;
buttonObjElementBufferName = UNINITIALIZED_GL;
_create_VAO_VBOs(buttonObjModel, &buttonObjVAOName, &buttonObjPosBufferName, &buttonObjTexcoordBufferName, &buttonObjElementBufferName);
if (buttonObjPosBufferName == UNINITIALIZED_GL || buttonObjTexcoordBufferName == UNINITIALIZED_GL || buttonObjElementBufferName == UNINITIALIZED_GL)
{
buttonObjModel = mdlCreateQuad(1.05-BUTTON_OBJ_W, -1.0, BUTTON_OBJ_W, BUTTON_OBJ_H, MODEL_DEPTH, BUTTON_FB_WIDTH, BUTTON_FB_HEIGHT, GL_RGBA); // RGBA8888
if (!buttonObjModel) {
LOG("gltouchjoy not initializing buttons");
return;
}
buttonObjTextureName = _create_texture(buttonObjPixels, BUTTON_FB_WIDTH, BUTTON_FB_HEIGHT);
if (buttonObjTextureName == UNINITIALIZED_GL) {
LOG("not initializing buttons: texture error");
return;
}
_setup_button_object();
clock_gettime(CLOCK_MONOTONIC, &axisTimingBegin);
clock_gettime(CLOCK_MONOTONIC, &buttonTimingBegin);
isAvailable = true;
}
@ -468,34 +243,17 @@ static void gltouchjoy_destroy(void) {
isAvailable = false;
glDeleteTextures(1, &touchAxisObjTextureName);
touchAxisObjTextureName = UNINITIALIZED_GL;
_destroy_VAO_VBOs(touchAxisObjVAOName, touchAxisObjPosBufferName, touchAxisObjTexcoordBufferName, touchAxisObjElementBufferName);
touchAxisObjVAOName = UNINITIALIZED_GL;
touchAxisObjPosBufferName = UNINITIALIZED_GL;
touchAxisObjTexcoordBufferName = UNINITIALIZED_GL;
touchAxisObjElementBufferName = UNINITIALIZED_GL;
mdlDestroyModel(touchAxisObjModel);
touchAxisObjModel = NULL;
glDeleteTextures(1, &buttonObjTextureName);
buttonObjTextureName = UNINITIALIZED_GL;
_destroy_VAO_VBOs(buttonObjVAOName, buttonObjPosBufferName, buttonObjTexcoordBufferName, buttonObjElementBufferName);
buttonObjVAOName = UNINITIALIZED_GL;
buttonObjPosBufferName = UNINITIALIZED_GL;
buttonObjTexcoordBufferName = UNINITIALIZED_GL;
buttonObjElementBufferName = UNINITIALIZED_GL;
mdlDestroyModel(buttonObjModel);
buttonObjModel = NULL;
mdlDestroyModel(&touchAxisObjModel);
mdlDestroyModel(&buttonObjModel);
}
static void _render_object(GLModel *model, GLuint vaoName, GLuint posBufferName, GLuint texcoordBufferName, GLuint elementBufferName) {
static void _render_object(GLModel *model) {
// Bind our vertex array object
#if USE_VAO
glBindVertexArray(vaoName);
glBindVertexArray(model->vaoName);
#else
glBindBuffer(GL_ARRAY_BUFFER, posBufferName);
glBindBuffer(GL_ARRAY_BUFFER, model->posBufferName);
GLsizei posTypeSize = _get_gl_type_size(model->positionType);
GLsizei texcoordTypeSize = _get_gl_type_size(model->texcoordType);
@ -512,7 +270,7 @@ static void _render_object(GLModel *model, GLuint vaoName, GLuint posBufferName,
// Set up parmeters for texcoord attribute in the VAO including, size, type, stride, and offset in the currenly
// bound VAO This also attaches the texcoord VBO to VAO
glBindBuffer(GL_ARRAY_BUFFER, texcoordBufferName);
glBindBuffer(GL_ARRAY_BUFFER, model->texcoordBufferName);
glVertexAttribPointer(TEXCOORD_ATTRIB_IDX, // What attibute index will this array feed in the vertex shader (see buildProgram)
model->texcoordSize, // How many elements are there per texture coord?
model->texcoordType, // What is the type of this data in the array?
@ -521,11 +279,11 @@ static void _render_object(GLModel *model, GLuint vaoName, GLuint posBufferName,
0); // What is the offset in the VBO to the texcoord data?
glEnableVertexAttribArray(TEXCOORD_ATTRIB_IDX);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBufferName);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, model->elementBufferName);
#endif
// Draw the object
glDrawElements(GL_TRIANGLES, model->numElements, model->elementType, 0);
glDrawElements(model->primType, model->numElements, model->elementType, 0);
GL_ERRLOG("gltouchjoy render");
}
@ -540,6 +298,7 @@ static void gltouchjoy_render(void) {
return;
}
// NOTE : show these HUD elements beyond the framebuffer dimensions
glViewport(0, 0, viewportWidth, viewportHeight);
struct timespec now = { 0 };
@ -564,18 +323,18 @@ static void gltouchjoy_render(void) {
glUniform1f(alphaValue, alpha);
glActiveTexture(TEXTURE_ACTIVE_TOUCHJOY_AXIS);
glBindTexture(GL_TEXTURE_2D, touchAxisObjTextureName);
if (axisTextureDirty) {
axisTextureDirty = false;
glTexImage2D(GL_TEXTURE_2D, /*level*/0, /*internal format*/GL_RGBA, AXIS_FB_WIDTH, AXIS_FB_HEIGHT, /*border*/0, /*format*/GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid *)touchAxisObjPixels);
glBindTexture(GL_TEXTURE_2D, touchAxisObjModel->textureName);
if (touchAxisObjModel->texDirty) {
touchAxisObjModel->texDirty = false;
glTexImage2D(GL_TEXTURE_2D, /*level*/0, /*internal format*/GL_RGBA, AXIS_FB_WIDTH, AXIS_FB_HEIGHT, /*border*/0, /*format*/GL_RGBA, GL_UNSIGNED_BYTE, touchAxisObjModel->texPixels);
}
if (axisModelDirty) {
axisModelDirty = false;
glBindBuffer(GL_ARRAY_BUFFER, touchAxisObjPosBufferName);
glBindBuffer(GL_ARRAY_BUFFER, touchAxisObjModel->posBufferName);
glBufferData(GL_ARRAY_BUFFER, touchAxisObjModel->positionArraySize, touchAxisObjModel->positions, GL_DYNAMIC_DRAW);
}
glUniform1i(uniformTex2Use, TEXTURE_ID_TOUCHJOY_AXIS);
_render_object(touchAxisObjModel, touchAxisObjVAOName, touchAxisObjPosBufferName, touchAxisObjTexcoordBufferName, touchAxisObjElementBufferName);
_render_object(touchAxisObjModel);
// draw button(s)
@ -594,18 +353,18 @@ static void gltouchjoy_render(void) {
glUniform1f(alphaValue, alpha);
glActiveTexture(TEXTURE_ACTIVE_TOUCHJOY_BUTTON);
glBindTexture(GL_TEXTURE_2D, buttonObjTextureName);
if (buttonTextureDirty) {
buttonTextureDirty = false;
glTexImage2D(GL_TEXTURE_2D, /*level*/0, /*internal format*/GL_RGBA, BUTTON_FB_WIDTH, BUTTON_FB_HEIGHT, /*border*/0, /*format*/GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid *)buttonObjPixels);
glBindTexture(GL_TEXTURE_2D, buttonObjModel->textureName);
if (buttonObjModel->texDirty) {
buttonObjModel->texDirty = false;
glTexImage2D(GL_TEXTURE_2D, /*level*/0, /*internal format*/GL_RGBA, BUTTON_FB_WIDTH, BUTTON_FB_HEIGHT, /*border*/0, /*format*/GL_RGBA, GL_UNSIGNED_BYTE, buttonObjModel->texPixels);
}
if (buttonModelDirty) {
buttonModelDirty = false;
glBindBuffer(GL_ARRAY_BUFFER, buttonObjPosBufferName);
glBindBuffer(GL_ARRAY_BUFFER, buttonObjModel->posBufferName);
glBufferData(GL_ARRAY_BUFFER, buttonObjModel->positionArraySize, buttonObjModel->positions, GL_DYNAMIC_DRAW);
}
glUniform1i(uniformTex2Use, TEXTURE_ID_TOUCHJOY_BUTTON);
_render_object(buttonObjModel, buttonObjVAOName, buttonObjPosBufferName, buttonObjTexcoordBufferName, buttonObjElementBufferName);
_render_object(buttonObjModel);
}
static void gltouchjoy_reshape(int w, int h) {
@ -701,15 +460,15 @@ static inline void _move_button_axis(int x, int y) {
if ((y < -buttonSwitchThreshold) || (y > buttonSwitchThreshold)) {
if (y < 0) {
//LOG("\tbutton neg y threshold (%d)", y);
if (upButtonAxisButton == TOUCHED_BUTTON0) {
if (northButton == TOUCHED_BUTTON0) {
joy_button0 = 0x80;
joy_button1 = 0;
_setup_button_object_with_char(button0Char);
} else if (upButtonAxisButton == TOUCHED_BUTTON1) {
} else if (northButton == TOUCHED_BUTTON1) {
joy_button0 = 0;
joy_button1 = 0x80;
_setup_button_object_with_char(button1Char);
} else if (upButtonAxisButton == TOUCHED_BOTH) {
} else if (northButton == TOUCHED_BOTH) {
joy_button0 = 0x80;
joy_button1 = 0x80;
_setup_button_object_with_char(buttonBothChar);
@ -719,15 +478,15 @@ static inline void _move_button_axis(int x, int y) {
}
} else {
//LOG("\tbutton pos y threshold (%d)", y);
if (downButtonAxisButton == TOUCHED_BUTTON0) {
if (southButton == TOUCHED_BUTTON0) {
joy_button0 = 0x80;
joy_button1 = 0;
_setup_button_object_with_char(button0Char);
} else if (downButtonAxisButton == TOUCHED_BUTTON1) {
} else if (southButton == TOUCHED_BUTTON1) {
joy_button0 = 0;
joy_button1 = 0x80;
_setup_button_object_with_char(button1Char);
} else if (downButtonAxisButton == TOUCHED_BOTH) {
} else if (southButton == TOUCHED_BOTH) {
joy_button0 = 0x80;
joy_button1 = 0x80;
_setup_button_object_with_char(buttonBothChar);
@ -881,11 +640,11 @@ static void gltouchjoy_setTouchAxisType(touchjoy_axis_type_t axisType) {
_setup_axis_object();
}
static void gltouchjoy_setTouchAxisValues(char up, char left, char right, char down) {
upChar = up;
leftChar = left;
rightChar = right;
downChar = down;
static void gltouchjoy_setTouchAxisValues(char north, char west, char east, char south) {
northChar = north;
westChar = west;
eastChar = east;
southChar = south;
if (touchjoy_axisType == AXIS_EMULATED_KEYBOARD) {
_setup_axis_object();
}
@ -910,10 +669,5 @@ static void _init_gltouchjoy(void) {
}
void gldriver_joystick_reset(void) {
#warning FIXME
#warning TODO
#warning expunge
#warning this
#warning API
#warning ...
#warning FIXME TODO expunge this olde API ...
}

View File

@ -96,8 +96,8 @@ static void _create_CRT_model(void) {
crt->positionSize = 4; // x,y,z coordinates
crt->positionArraySize = sizeof(crt_positions);
crt->texcoords = malloc(sizeof(crt_texcoords));
memcpy(crt->texcoords, &crt_texcoords[0], sizeof(crt_texcoords));
crt->texCoords = malloc(sizeof(crt_texcoords));
memcpy(crt->texCoords, &crt_texcoords[0], sizeof(crt_texcoords));
crt->texcoordType = GL_FLOAT;
crt->texcoordSize = 2; // s,t coordinates
crt->texcoordArraySize = sizeof(crt_texcoords);
@ -112,7 +112,7 @@ static void _create_CRT_model(void) {
crt->elementType = GL_UNSIGNED_SHORT;
crt->elementArraySize = sizeof(indices);
mdlDestroyModel(crtModel);
mdlDestroyModel(&crtModel);
crtModel = crt;
}
@ -176,13 +176,13 @@ static void _create_VAO_VBOs(void) {
}
#endif
if (crtModel->texcoords) {
if (crtModel->texCoords) {
// Create a VBO to store texcoords
glGenBuffers(1, &texcoordBufferName);
glBindBuffer(GL_ARRAY_BUFFER, texcoordBufferName);
// Allocate and load texcoord data into the VBO
glBufferData(GL_ARRAY_BUFFER, crtModel->texcoordArraySize, crtModel->texcoords, GL_STATIC_DRAW);
glBufferData(GL_ARRAY_BUFFER, crtModel->texcoordArraySize, crtModel->texCoords, GL_STATIC_DRAW);
#if USE_VAO
// Enable the texcoord attribute for this VAO
@ -564,7 +564,7 @@ static void gldriver_init_common(void) {
#if USE_VAO
// We're using VBOs we can destroy all this memory since buffers are
// loaded into GL and we've saved anything else we need
mdlDestroyModel(crtModel);
mdlDestroyModel(&crtModel);
crtModel = NULL;
#endif
@ -625,7 +625,7 @@ static void gldriver_shutdown(void) {
a2TextureName = UNINITIALIZED_GL;
_destroy_VAO(crtVAOName);
crtVAOName = UNINITIALIZED_GL;
mdlDestroyModel(crtModel);
mdlDestroyModel(&crtModel);
crtModel = NULL;
glDeleteProgram(program);
program = UNINITIALIZED_GL;

View File

@ -25,7 +25,8 @@
// VAO optimization (may not be available on all platforms)
#ifdef ANDROID
#include "glanimation.h"
#warning Certain Android and Android-ish devices (*cough* Kindle *cough*) have buggy OpenGL VAO support ...
// NOTE : 2015/04/01 ... Certain Android and Android-ish devices (*cough* Kindle *cough*) have buggy OpenGL VAO support,
// so don't rely on it. Is it the future yet?
#define USE_VAO 0
#elif !defined(USE_VAO)
#define USE_VAO 1

View File

@ -52,7 +52,7 @@ GLModel *mdlLoadModel(const char *filepathname) {
FILE *curFile = fopen(filepathname, "r");
if (!curFile) {
mdlDestroyModel(model);
mdlDestroyModel(&model);
return NULL;
}
@ -60,19 +60,19 @@ GLModel *mdlLoadModel(const char *filepathname) {
sizeRead = fread(&header, 1, sizeof(modelHeader), curFile);
if (sizeRead != sizeof(modelHeader)) {
fclose(curFile);
mdlDestroyModel(model);
mdlDestroyModel(&model);
return NULL;
}
if (strncmp(header.fileIdentifier, "AppleOpenGLDemoModelWWDC2010", sizeof(header.fileIdentifier))) {
fclose(curFile);
mdlDestroyModel(model);
mdlDestroyModel(&model);
return NULL;
}
if (header.majorVersion != 0 && header.minorVersion != 1) {
fclose(curFile);
mdlDestroyModel(model);
mdlDestroyModel(&model);
return NULL;
}
@ -80,13 +80,13 @@ GLModel *mdlLoadModel(const char *filepathname) {
sizeRead = fread(&toc, 1, sizeof(modelTOC), curFile);
if (sizeRead != sizeof(modelTOC)) {
fclose(curFile);
mdlDestroyModel(model);
mdlDestroyModel(&model);
return NULL;
}
if (toc.attribHeaderSize > sizeof(modelAttrib)) {
fclose(curFile);
mdlDestroyModel(model);
mdlDestroyModel(&model);
return NULL;
}
@ -94,14 +94,14 @@ GLModel *mdlLoadModel(const char *filepathname) {
error = fseek(curFile, toc.byteElementOffset, SEEK_SET);
if (error < 0) {
fclose(curFile);
mdlDestroyModel(model);
mdlDestroyModel(&model);
return NULL;
}
sizeRead = fread(&attrib, 1, toc.attribHeaderSize, curFile);
if (sizeRead != toc.attribHeaderSize) {
fclose(curFile);
mdlDestroyModel(model);
mdlDestroyModel(&model);
return NULL;
}
@ -121,7 +121,7 @@ GLModel *mdlLoadModel(const char *filepathname) {
sizeRead = fread(uiElements, 1, model->elementArraySize, curFile);
if (sizeRead != model->elementArraySize) {
fclose(curFile);
mdlDestroyModel(model);
mdlDestroyModel(&model);
return NULL;
}
@ -130,7 +130,7 @@ GLModel *mdlLoadModel(const char *filepathname) {
// can't handle this model if an element is out of the UNSIGNED_INT range
if (((GLuint *)uiElements)[elemNum] >= 0xFFFF) {
fclose(curFile);
mdlDestroyModel(model);
mdlDestroyModel(&model);
return NULL;
}
@ -147,7 +147,7 @@ GLModel *mdlLoadModel(const char *filepathname) {
if (sizeRead != model->elementArraySize) {
fclose(curFile);
mdlDestroyModel(model);
mdlDestroyModel(&model);
return NULL;
}
}
@ -156,7 +156,7 @@ GLModel *mdlLoadModel(const char *filepathname) {
sizeRead = fread(&attrib, 1, toc.attribHeaderSize, curFile);
if (sizeRead != toc.attribHeaderSize) {
fclose(curFile);
mdlDestroyModel(model);
mdlDestroyModel(&model);
return NULL;
}
@ -164,26 +164,26 @@ GLModel *mdlLoadModel(const char *filepathname) {
model->positionType = attrib.datatype;
model->positionSize = attrib.sizePerElement;
model->numVertices = attrib.numElements;
model->positions = (GLubyte*) malloc(model->positionArraySize);
model->positions = (GLubyte*)malloc(model->positionArraySize);
sizeRead = fread(model->positions, 1, model->positionArraySize, curFile);
if (sizeRead != model->positionArraySize) {
fclose(curFile);
mdlDestroyModel(model);
mdlDestroyModel(&model);
return NULL;
}
error = fseek(curFile, toc.byteTexcoordOffset, SEEK_SET);
if (error < 0) {
fclose(curFile);
mdlDestroyModel(model);
mdlDestroyModel(&model);
return NULL;
}
sizeRead = fread(&attrib, 1, toc.attribHeaderSize, curFile);
if (sizeRead != toc.attribHeaderSize) {
fclose(curFile);
mdlDestroyModel(model);
mdlDestroyModel(&model);
return NULL;
}
@ -194,23 +194,23 @@ GLModel *mdlLoadModel(const char *filepathname) {
// must have the same number of texcoords as positions
if (model->numVertices != attrib.numElements) {
fclose(curFile);
mdlDestroyModel(model);
mdlDestroyModel(&model);
return NULL;
}
model->texcoords = (GLubyte*) malloc(model->texcoordArraySize);
model->texCoords = (GLubyte*)malloc(model->texcoordArraySize);
sizeRead = fread(model->texcoords, 1, model->texcoordArraySize, curFile);
sizeRead = fread(model->texCoords, 1, model->texcoordArraySize, curFile);
if (sizeRead != model->texcoordArraySize) {
fclose(curFile);
mdlDestroyModel(model);
mdlDestroyModel(&model);
return NULL;
}
error = fseek(curFile, toc.byteNormalOffset, SEEK_SET);
if (error < 0) {
fclose(curFile);
mdlDestroyModel(model);
mdlDestroyModel(&model);
return NULL;
}
@ -218,7 +218,7 @@ GLModel *mdlLoadModel(const char *filepathname) {
if (sizeRead != toc.attribHeaderSize) {
fclose(curFile);
mdlDestroyModel(model);
mdlDestroyModel(&model);
return NULL;
}
@ -229,16 +229,16 @@ GLModel *mdlLoadModel(const char *filepathname) {
// must have the same number of normals as positions
if (model->numVertices != attrib.numElements) {
fclose(curFile);
mdlDestroyModel(model);
mdlDestroyModel(&model);
return NULL;
}
model->normals = (GLubyte*) malloc(model->normalArraySize );
model->normals = (GLubyte*)malloc(model->normalArraySize );
sizeRead = fread(model->normals, 1, model->normalArraySize , curFile);
if (sizeRead != model->normalArraySize) {
fclose(curFile);
mdlDestroyModel(model);
mdlDestroyModel(&model);
return NULL;
}
@ -247,7 +247,7 @@ GLModel *mdlLoadModel(const char *filepathname) {
return model;
}
GLModel *mdlLoadQuadModel() {
GLModel *mdlLoadQuadModel(void) {
GLfloat posArray[] = {
-200.0f, 0.0f, -200.0f,
200.0f, 0.0f, -200.0f,
@ -289,8 +289,8 @@ GLModel *mdlLoadQuadModel() {
model->texcoordType = GL_FLOAT;
model->texcoordSize = 2;
model->texcoordArraySize = sizeof(texcoordArray);
model->texcoords = (GLubyte*)malloc(model->texcoordArraySize);
memcpy(model->texcoords, texcoordArray, model->texcoordArraySize );
model->texCoords = (GLubyte*)malloc(model->texcoordArraySize);
memcpy(model->texCoords, texcoordArray, model->texcoordArraySize );
model->normalType = GL_FLOAT;
model->normalSize = 3;
@ -311,16 +311,288 @@ GLModel *mdlLoadQuadModel() {
return model;
}
void mdlDestroyModel(GLModel *model) {
if (!model) {
static void _quadCreateVAOAndVBOs(GLModel *model) {
// Create a vertex array object (VAO) to cache model parameters
#if USE_VAO
glGenVertexArrays(1, &(model->vaoName));
glBindVertexArray(model->vaoName);
#endif
// Create a vertex buffer object (VBO) to store positions and load data
glGenBuffers(1, &(model->posBufferName));
glBindBuffer(GL_ARRAY_BUFFER, model->posBufferName);
glBufferData(GL_ARRAY_BUFFER, model->positionArraySize, model->positions, GL_DYNAMIC_DRAW);
#if USE_VAO
// Enable the position attribute for this VAO
glEnableVertexAttribArray(POS_ATTRIB_IDX);
// Get the size of the position type so we can set the stride properly
GLsizei posTypeSize = _get_gl_type_size(model->positionType);
// Set up parmeters for position attribute in the VAO including,
// size, type, stride, and offset in the currenly bound VAO
// This also attaches the position VBO to the VAO
glVertexAttribPointer(POS_ATTRIB_IDX, // What attibute index will this array feed in the vertex shader (see buildProgram)
model->positionSize, // How many elements are there per position?
model->positionType, // What is the type of this data?
GL_FALSE, // Do we want to normalize this data (0-1 range for fixed-pont types)
model->positionSize*posTypeSize, // What is the stride (i.e. bytes between positions)?
0); // What is the offset in the VBO to the position data?
#endif
if (model->texCoords) {
// Create a VBO to store texcoords
glGenBuffers(1, &(model->texcoordBufferName));
glBindBuffer(GL_ARRAY_BUFFER, model->texcoordBufferName);
// Allocate and load texcoord data into the VBO
glBufferData(GL_ARRAY_BUFFER, model->texcoordArraySize, model->texCoords, GL_DYNAMIC_DRAW);
#if USE_VAO
// Enable the texcoord attribute for this VAO
glEnableVertexAttribArray(TEXCOORD_ATTRIB_IDX);
// Get the size of the texcoord type so we can set the stride properly
GLsizei texcoordTypeSize = _get_gl_type_size(model->texcoordType);
// Set up parmeters for texcoord attribute in the VAO including,
// size, type, stride, and offset in the currenly bound VAO
// This also attaches the texcoord VBO to VAO
glVertexAttribPointer(TEXCOORD_ATTRIB_IDX, // What attibute index will this array feed in the vertex shader (see buildProgram)
model->texcoordSize, // How many elements are there per texture coord?
model->texcoordType, // What is the type of this data in the array?
GL_TRUE, // Do we want to normalize this data (0-1 range for fixed-point types)
model->texcoordSize*texcoordTypeSize, // What is the stride (i.e. bytes between texcoords)?
0); // What is the offset in the VBO to the texcoord data?
#endif
}
// Create a VBO to vertex array elements
// This also attaches the element array buffer to the VAO
glGenBuffers(1, &(model->elementBufferName));
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, model->elementBufferName);
// Allocate and load vertex array element data into VBO
glBufferData(GL_ELEMENT_ARRAY_BUFFER, model->elementArraySize, model->elements, GL_DYNAMIC_DRAW);
GL_ERRLOG("quad creation of VAO/VBOs");
}
static GLuint _quadCreateTexture(GLModel *model) {
GLuint texName = UNINITIALIZED_GL;
// Create a texture object to apply to model
glGenTextures(1, &texName);
glBindTexture(GL_TEXTURE_2D, texName);
// Set up filter and wrap modes for this texture object
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
// Indicate that pixel rows are tightly packed
// (defaults to stride of 4 which is kind of only good for
// RGBA or FLOAT data types)
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
// register texture with OpenGL
glTexImage2D(GL_TEXTURE_2D, /*level*/0, /*internal format*/model->texFormat, model->texWidth, model->texHeight, /*border*/0, /*format*/model->texFormat, GL_UNSIGNED_BYTE, model->texPixels);
GL_ERRLOG("quad texture creation");
return texName;
}
GLModel *mdlCreateQuad(GLfloat skew_x, GLfloat skew_y, GLfloat obj_w, GLfloat obj_h, GLfloat z, GLsizei tex_w, GLsizei tex_h, GLenum tex_format) {
/* 2...3
* .
* .
* .
* 0...1
*/
const GLfloat obj_positions[] = {
skew_x, skew_y, z, 1.0,
skew_x+obj_w, skew_y, z, 1.0,
skew_x, skew_y+obj_h, z, 1.0,
skew_x+obj_w, skew_y+obj_h, z, 1.0,
};
const GLfloat obj_texcoords[] = {
0.f, 1.f,
1.f, 1.f,
0.f, 0.f,
1.f, 0.f,
};
const GLushort indices[] = {
0, 1, 2, 2, 1, 3
};
GLModel *model = NULL;
do {
model = calloc(1, sizeof(GLModel));
if (!model) {
break;
}
model->numVertices = 4;
model->numElements = 6;
model->primType = GL_TRIANGLES;
model->positions = malloc(sizeof(obj_positions));
if (!(model->positions)) {
break;
}
memcpy(model->positions, &obj_positions[0], sizeof(obj_positions));
model->positionType = GL_FLOAT;
model->positionSize = 4; // x,y,z coordinates
model->positionArraySize = sizeof(obj_positions);
if (tex_w > 0 && tex_h > 0) {
model->texCoords = malloc(sizeof(obj_texcoords));
if (!(model->texCoords)) {
break;
}
memcpy(model->texCoords, &obj_texcoords[0], sizeof(obj_texcoords));
model->texcoordType = GL_FLOAT;
model->texcoordSize = 2; // s,t coordinates
model->texcoordArraySize = sizeof(obj_texcoords);
}
{
// NO NORMALS for now
model->normals = NULL;
model->normalType = GL_NONE;
model->normalSize = GL_NONE;
model->normalArraySize = 0;
}
model->elements = malloc(sizeof(indices));
if (!(model->elements)) {
break;
}
memcpy(model->elements, &indices[0], sizeof(indices));
model->elementType = GL_UNSIGNED_SHORT;
model->elementArraySize = sizeof(indices);
model->custom = NULL;
#if USE_VAO
model->vaoName = UNINITIALIZED_GL;
#endif
model->posBufferName = UNINITIALIZED_GL;
model->texcoordBufferName = UNINITIALIZED_GL;
model->elementBufferName = UNINITIALIZED_GL;
_quadCreateVAOAndVBOs(model);
if (model->posBufferName == UNINITIALIZED_GL || model->texcoordBufferName == UNINITIALIZED_GL || model->elementBufferName == UNINITIALIZED_GL) {
LOG("Error creating model buffers!");
break;
}
model->texDirty = true;
model->texWidth = tex_w;
model->texHeight = tex_h;
model->texFormat = tex_format;
if (tex_format == GL_RGBA) {
model->texPixels = (GLvoid *)calloc(tex_w*tex_h*4, 1);
} else {
ERRQUIT("non-GL_RBGA format textures untested ... FIXME!");
}
if (model->texPixels == NULL) {
break;
}
model->textureName = _quadCreateTexture(model);
if (model->textureName == UNINITIALIZED_GL) {
LOG("Error creating model texture!");
break;
}
GL_ERRLOG("quad creation");
return model;
} while (0);
ERRLOG("error in quad creation");
if (model) {
mdlDestroyModel(&model);
}
return NULL;
}
void mdlDestroyModel(INOUT GLModel **model) {
if (!model || (!*model)) {
return;
}
free(model->elements);
free(model->positions);
free(model->normals);
free(model->texcoords);
GLModel *m = *model;
free(model);
FREE(m->elements);
FREE(m->positions);
FREE(m->normals);
FREE(m->texCoords);
FREE(m->texPixels);
if (m->textureName != UNINITIALIZED_GL) {
glDeleteTextures(1, &(m->textureName));
m->textureName = UNINITIALIZED_GL;
}
#if USE_VAO
if (m->vaoName != UNINITIALIZED_GL) {
glBindVertexArray(m->vaoName);
// For every possible attribute set in the VAO
for (GLuint index = 0; index < 16; index++) {
// Get the VBO set for that attibute
GLuint bufName = 0;
glGetVertexAttribiv(index , GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, (GLint*)&bufName);
// If there was a VBO set...
if (bufName) {
//...delete the VBO
glDeleteBuffers(1, &bufName);
}
}
// Get any element array VBO set in the VAO
{
GLuint bufName = 0;
glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, (GLint*)&bufName);
// If there was a element array VBO set in the VAO
if (bufName) {
//...delete the VBO
glDeleteBuffers(1, &bufName);
}
}
// Finally, delete the VAO
glDeleteVertexArrays(1, &(m->vaoName));
}
#else
if (m->posBufferName != UNINITIALIZED_GL) {
glDeleteBuffers(1, &(m->posBufferName));
m->posBufferName = UNINITIALIZED_GL;
}
if (m->texcoordBufferName != UNINITIALIZED_GL) {
glDeleteBuffers(1, &(m->texcoordBufferName));
m->texcoordBufferName = UNINITIALIZED_GL;
}
if (m->elementBufferName != UNINITIALIZED_GL) {
glDeleteBuffers(1, &(m->elementBufferName));
m->elementBufferName = UNINITIALIZED_GL;
}
#endif
if (m->custom) {
m->custom->dtor(&(m->custom));
}
FREE(*model);
}

View File

@ -14,10 +14,15 @@
#ifndef __MODEL_UTIL_H__
#define __MODEL_UTIL_H__
#include "glUtil.h"
#include "common.h"
#define UNINITIALIZED_GL 31337
typedef struct GLCustom {
void (*dtor)(INOUT struct GLCustom **custom); // custom data destructor
// overridden objects must at least implement interface methods
} GLCustom;
typedef struct GLModel {
GLuint numVertices;
@ -26,7 +31,7 @@ typedef struct GLModel {
GLuint positionSize;
GLsizei positionArraySize;
GLvoid *texcoords;
GLvoid *texCoords;
GLenum texcoordType;
GLuint texcoordSize;
GLsizei texcoordArraySize;
@ -41,14 +46,33 @@ typedef struct GLModel {
GLuint numElements;
GLsizei elementArraySize;
GLsizei texWidth;
GLsizei texHeight;
GLsizei texFormat;
GLvoid *texPixels;
bool texDirty;
GLenum primType;
// GL generated data
#if USE_VAO
GLuint vaoName;
#endif
GLuint textureName;
GLuint posBufferName;
GLuint texcoordBufferName;
GLuint elementBufferName;
// Custom
GLCustom *custom;
} GLModel;
GLModel *mdlLoadModel(const char *filepathname);
GLModel *mdlLoadQuadModel();
void mdlDestroyModel(GLModel *model);
GLModel *mdlCreateQuad(GLfloat skew_x, GLfloat skew_y, GLfloat obj_w, GLfloat obj_h, GLfloat z, GLsizei tex_w, GLsizei tex_h, GLenum tex_format);
void mdlDestroyModel(INOUT GLModel **model);
#endif //__MODEL_UTIL_H__