Removed texture-atlas.c and vertex-buffer.c
This commit is contained in:
parent
b211fd956a
commit
ee9e888c5a
20
ftgl/mat4.h
20
ftgl/mat4.h
@ -30,30 +30,30 @@ mat4 *mat4_new(void);
|
||||
|
||||
void mat4_set_identity(mat4 *self);
|
||||
|
||||
void mat4_set_zero(mat4 *self);
|
||||
// mat4_set_zero(mat4 *self);
|
||||
|
||||
void mat4_multiply(mat4 *self, mat4 *other);
|
||||
//void mat4_multiply(mat4 *self, mat4 *other);
|
||||
|
||||
void mat4_set_orthographic(mat4 *self, float left, float right, float bottom,
|
||||
float top, float znear, float zfar);
|
||||
|
||||
void mat4_set_perspective(mat4 *self, float fovy, float aspect, float zNear,
|
||||
float zFar);
|
||||
/*void mat4_set_perspective(mat4 *self, float fovy, float aspect, float zNear,
|
||||
float zFar); */
|
||||
|
||||
void mat4_set_frustum(mat4 *self, float left, float right, float bottom,
|
||||
float top, float znear, float zfar);
|
||||
|
||||
void mat4_set_rotation(mat4 *self, float angle, float x, float y, float z);
|
||||
//void mat4_set_rotation(mat4 *self, float angle, float x, float y, float z);
|
||||
|
||||
void mat4_set_translation(mat4 *self, float x, float y, float z);
|
||||
//void mat4_set_translation(mat4 *self, float x, float y, float z);
|
||||
|
||||
void mat4_set_scaling(mat4 *self, float x, float y, float z);
|
||||
//void mat4_set_scaling(mat4 *self, float x, float y, float z);
|
||||
|
||||
void mat4_rotate(mat4 *self, float angle, float x, float y, float z);
|
||||
//void mat4_rotate(mat4 *self, float angle, float x, float y, float z);
|
||||
|
||||
void mat4_translate(mat4 *self, float x, float y, float z);
|
||||
//void mat4_translate(mat4 *self, float x, float y, float z);
|
||||
|
||||
void mat4_scale(mat4 *self, float x, float y, float z);
|
||||
//void mat4_scale(mat4 *self, float x, float y, float z);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -1,257 +0,0 @@
|
||||
/* Freetype GL - A C OpenGL Freetype engine
|
||||
*
|
||||
* Distributed under the OSI-approved BSD 2-Clause License. See accompanying
|
||||
* file `LICENSE` for more details.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include "texture-atlas.h"
|
||||
|
||||
// ------------------------------------------------------ texture_atlas_new ---
|
||||
texture_atlas_t *texture_atlas_new(const size_t width, const size_t height,
|
||||
const size_t depth)
|
||||
{
|
||||
texture_atlas_t *self = (texture_atlas_t *) malloc(sizeof(texture_atlas_t));
|
||||
|
||||
// We want a one pixel border around the whole atlas to avoid any artefact
|
||||
// when sampling texture
|
||||
ivec3 node = { { 1, 1, width - 2 } };
|
||||
|
||||
assert((depth == 1) || (depth == 3) || (depth == 4));
|
||||
if (self == NULL)
|
||||
{
|
||||
fprintf(stderr, "line %d: No more memory for allocating data\n",
|
||||
__LINE__);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
self->nodes = vector_new(sizeof(ivec3));
|
||||
self->used = 0;
|
||||
self->width = width;
|
||||
self->height = height;
|
||||
self->depth = depth;
|
||||
self->id = 0;
|
||||
self->dirty = 1;
|
||||
|
||||
vector_push_back(self->nodes, &node);
|
||||
self->data =
|
||||
(unsigned char *) calloc(width * height * depth, sizeof(unsigned char));
|
||||
|
||||
if (self->data == NULL)
|
||||
{
|
||||
fprintf(stderr, "line %d: No more memory for allocating data\n",
|
||||
__LINE__);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
// --------------------------------------------------- texture_atlas_delete ---
|
||||
void texture_atlas_delete(texture_atlas_t *self)
|
||||
{
|
||||
assert(self);
|
||||
vector_delete(self->nodes);
|
||||
if (self->data)
|
||||
{
|
||||
free(self->data);
|
||||
}
|
||||
free(self);
|
||||
}
|
||||
|
||||
// ----------------------------------------------- texture_atlas_set_region ---
|
||||
void texture_atlas_set_region(texture_atlas_t *self, const size_t x,
|
||||
const size_t y, const size_t width,
|
||||
const size_t height, const unsigned char *data,
|
||||
const size_t stride)
|
||||
{
|
||||
size_t i;
|
||||
size_t depth;
|
||||
size_t charsize;
|
||||
|
||||
assert(self);
|
||||
assert(x > 0);
|
||||
assert(y > 0);
|
||||
assert(x < (self->width - 1));
|
||||
assert((x + width) <= (self->width - 1));
|
||||
assert(y < (self->height - 1));
|
||||
assert((y + height) <= (self->height - 1));
|
||||
|
||||
// prevent copying data from undefined position
|
||||
// and prevent memcpy's undefined behavior when count is zero
|
||||
assert(height == 0 || (data != NULL && width > 0));
|
||||
|
||||
depth = self->depth;
|
||||
charsize = sizeof(char);
|
||||
for (i = 0; i < height; ++i)
|
||||
{
|
||||
memcpy(self->data + ((y + i) * self->width + x) * charsize * depth,
|
||||
data + (i * stride) * charsize, width * charsize * depth);
|
||||
}
|
||||
self->dirty = 1;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------ texture_atlas_fit ---
|
||||
int texture_atlas_fit(texture_atlas_t *self, const size_t index,
|
||||
const size_t width, const size_t height)
|
||||
{
|
||||
ivec3 *node;
|
||||
int x, y, width_left;
|
||||
size_t i;
|
||||
|
||||
assert(self);
|
||||
|
||||
node = (ivec3 *) (vector_get(self->nodes, index));
|
||||
x = node->x;
|
||||
y = node->y;
|
||||
width_left = width;
|
||||
i = index;
|
||||
|
||||
if ((x + width) > (self->width - 1))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
y = node->y;
|
||||
while (width_left > 0)
|
||||
{
|
||||
node = (ivec3 *) (vector_get(self->nodes, i));
|
||||
if (node->y > y)
|
||||
{
|
||||
y = node->y;
|
||||
}
|
||||
if ((y + height) > (self->height - 1))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
width_left -= node->z;
|
||||
++i;
|
||||
}
|
||||
return y;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------- texture_atlas_merge ---
|
||||
void texture_atlas_merge(texture_atlas_t *self)
|
||||
{
|
||||
ivec3 *node, *next;
|
||||
size_t i;
|
||||
|
||||
assert(self);
|
||||
|
||||
for (i = 0; i < self->nodes->size - 1; ++i)
|
||||
{
|
||||
node = (ivec3 *) (vector_get(self->nodes, i));
|
||||
next = (ivec3 *) (vector_get(self->nodes, i + 1));
|
||||
if (node->y == next->y)
|
||||
{
|
||||
node->z += next->z;
|
||||
vector_erase(self->nodes, i + 1);
|
||||
--i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------- texture_atlas_get_region ---
|
||||
ivec4 texture_atlas_get_region(texture_atlas_t *self, const size_t width,
|
||||
const size_t height)
|
||||
{
|
||||
int y, best_index;
|
||||
size_t best_height, best_width;
|
||||
ivec3 *node, *prev;
|
||||
ivec4 region = { { 0, 0, width, height } };
|
||||
size_t i;
|
||||
|
||||
assert(self);
|
||||
|
||||
best_height = UINT_MAX;
|
||||
best_index = -1;
|
||||
best_width = UINT_MAX;
|
||||
for (i = 0; i < self->nodes->size; ++i)
|
||||
{
|
||||
y = texture_atlas_fit(self, i, width, height);
|
||||
if (y >= 0)
|
||||
{
|
||||
node = (ivec3 *) vector_get(self->nodes, i);
|
||||
if (((y + height) < best_height) ||
|
||||
(((y + height) == best_height) &&
|
||||
(node->z > 0 && (size_t) node->z < best_width)))
|
||||
{
|
||||
best_height = y + height;
|
||||
best_index = i;
|
||||
best_width = node->z;
|
||||
region.x = node->x;
|
||||
region.y = y;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (best_index == -1)
|
||||
{
|
||||
region.x = -1;
|
||||
region.y = -1;
|
||||
region.width = 0;
|
||||
region.height = 0;
|
||||
return region;
|
||||
}
|
||||
|
||||
node = (ivec3 *) malloc(sizeof(ivec3));
|
||||
if (node == NULL)
|
||||
{
|
||||
fprintf(stderr, "line %d: No more memory for allocating data\n",
|
||||
__LINE__);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
node->x = region.x;
|
||||
node->y = region.y + height;
|
||||
node->z = width;
|
||||
vector_insert(self->nodes, best_index, node);
|
||||
free(node);
|
||||
|
||||
for (i = best_index + 1; i < self->nodes->size; ++i)
|
||||
{
|
||||
node = (ivec3 *) vector_get(self->nodes, i);
|
||||
prev = (ivec3 *) vector_get(self->nodes, i - 1);
|
||||
|
||||
if (node->x < (prev->x + prev->z))
|
||||
{
|
||||
int shrink = prev->x + prev->z - node->x;
|
||||
node->x += shrink;
|
||||
node->z -= shrink;
|
||||
if (node->z <= 0)
|
||||
{
|
||||
vector_erase(self->nodes, i);
|
||||
--i;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
texture_atlas_merge(self);
|
||||
self->used += width * height;
|
||||
return region;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------- texture_atlas_clear ---
|
||||
void texture_atlas_clear(texture_atlas_t *self)
|
||||
{
|
||||
ivec3 node = { { 1, 1, 1 } };
|
||||
|
||||
assert(self);
|
||||
assert(self->data);
|
||||
|
||||
vector_clear(self->nodes);
|
||||
self->used = 0;
|
||||
// We want a one pixel border around the whole atlas to avoid any artefact
|
||||
// when sampling texture
|
||||
node.z = self->width - 2;
|
||||
|
||||
vector_push_back(self->nodes, &node);
|
||||
memset(self->data, 0, self->width * self->height * self->depth);
|
||||
}
|
@ -1,619 +0,0 @@
|
||||
/* Freetype GL - A C OpenGL Freetype engine
|
||||
*
|
||||
* Distributed under the OSI-approved BSD 2-Clause License. See accompanying
|
||||
* file `LICENSE` for more details.
|
||||
*/
|
||||
#pragma GCC diagnostic ignored "-Wformat"
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "vec234.h"
|
||||
#include "platform.h"
|
||||
#include "vertex-buffer.h"
|
||||
|
||||
/**
|
||||
* Buffer status
|
||||
*/
|
||||
#define CLEAN (0)
|
||||
#define DIRTY (1)
|
||||
#define FROZEN (2)
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
vertex_buffer_t *vertex_buffer_new(const char *format)
|
||||
{
|
||||
size_t i, index = 0, stride = 0;
|
||||
const char *start = 0, *end = 0;
|
||||
GLchar *pointer = 0;
|
||||
|
||||
vertex_buffer_t *self = (vertex_buffer_t *) malloc(sizeof(vertex_buffer_t));
|
||||
if (!self)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
self->format = strdup(format);
|
||||
|
||||
for (i = 0; i < MAX_VERTEX_ATTRIBUTE; ++i)
|
||||
{
|
||||
self->attributes[i] = 0;
|
||||
}
|
||||
|
||||
start = format;
|
||||
do
|
||||
{
|
||||
char *desc = 0;
|
||||
vertex_attribute_t *attribute;
|
||||
GLuint attribute_size = 0;
|
||||
end = (char *) (strchr(start + 1, ','));
|
||||
|
||||
if (end == NULL)
|
||||
{
|
||||
desc = strdup(start);
|
||||
}
|
||||
else
|
||||
{
|
||||
desc = strndup(start, end - start);
|
||||
}
|
||||
attribute = vertex_attribute_parse(desc);
|
||||
start = end + 1;
|
||||
free(desc);
|
||||
attribute->pointer = pointer;
|
||||
|
||||
switch (attribute->type)
|
||||
{
|
||||
case GL_BOOL:
|
||||
attribute_size = sizeof(GLboolean);
|
||||
break;
|
||||
case GL_BYTE:
|
||||
attribute_size = sizeof(GLbyte);
|
||||
break;
|
||||
case GL_UNSIGNED_BYTE:
|
||||
attribute_size = sizeof(GLubyte);
|
||||
break;
|
||||
case GL_SHORT:
|
||||
attribute_size = sizeof(GLshort);
|
||||
break;
|
||||
case GL_UNSIGNED_SHORT:
|
||||
attribute_size = sizeof(GLushort);
|
||||
break;
|
||||
case GL_INT:
|
||||
attribute_size = sizeof(GLint);
|
||||
break;
|
||||
case GL_UNSIGNED_INT:
|
||||
attribute_size = sizeof(GLuint);
|
||||
break;
|
||||
case GL_FLOAT:
|
||||
attribute_size = sizeof(GLfloat);
|
||||
break;
|
||||
default:
|
||||
attribute_size = 0;
|
||||
}
|
||||
stride += attribute->size * attribute_size;
|
||||
pointer += attribute->size * attribute_size;
|
||||
self->attributes[index] = attribute;
|
||||
index++;
|
||||
} while (end && (index < MAX_VERTEX_ATTRIBUTE));
|
||||
|
||||
for (i = 0; i < index; ++i)
|
||||
{
|
||||
self->attributes[i]->stride = stride;
|
||||
}
|
||||
|
||||
#ifdef FREETYPE_GL_USE_VAO
|
||||
self->VAO_id = 0;
|
||||
#endif
|
||||
|
||||
self->vertices = vector_new(stride);
|
||||
self->vertices_id = 0;
|
||||
self->GPU_vsize = 0;
|
||||
|
||||
self->indices = vector_new(sizeof(GLuint));
|
||||
self->indices_id = 0;
|
||||
self->GPU_isize = 0;
|
||||
|
||||
self->items = vector_new(sizeof(ivec4));
|
||||
self->state = DIRTY;
|
||||
self->mode = GL_TRIANGLES;
|
||||
return self;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void vertex_buffer_delete(vertex_buffer_t *self)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
assert(self);
|
||||
|
||||
for (i = 0; i < MAX_VERTEX_ATTRIBUTE; ++i)
|
||||
{
|
||||
if (self->attributes[i])
|
||||
{
|
||||
vertex_attribute_delete(self->attributes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef FREETYPE_GL_USE_VAO
|
||||
if (self->VAO_id)
|
||||
{
|
||||
glDeleteVertexArrays(1, &self->VAO_id);
|
||||
}
|
||||
self->VAO_id = 0;
|
||||
#endif
|
||||
|
||||
vector_delete(self->vertices);
|
||||
self->vertices = 0;
|
||||
if (self->vertices_id)
|
||||
{
|
||||
glDeleteBuffers(1, &self->vertices_id);
|
||||
}
|
||||
self->vertices_id = 0;
|
||||
|
||||
vector_delete(self->indices);
|
||||
self->indices = 0;
|
||||
if (self->indices_id)
|
||||
{
|
||||
glDeleteBuffers(1, &self->indices_id);
|
||||
}
|
||||
self->indices_id = 0;
|
||||
|
||||
vector_delete(self->items);
|
||||
|
||||
if (self->format)
|
||||
{
|
||||
free(self->format);
|
||||
}
|
||||
self->format = 0;
|
||||
self->state = 0;
|
||||
free(self);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
const char *vertex_buffer_format(const vertex_buffer_t *self)
|
||||
{
|
||||
assert(self);
|
||||
|
||||
return self->format;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
size_t vertex_buffer_size(const vertex_buffer_t *self)
|
||||
{
|
||||
assert(self);
|
||||
|
||||
return vector_size(self->items);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void vertex_buffer_print(vertex_buffer_t *self)
|
||||
{
|
||||
int i = 0;
|
||||
static char *gltypes[9] = {
|
||||
"GL_BOOL", "GL_BYTE", "GL_UNSIGNED_BYTE",
|
||||
"GL_SHORT", "GL_UNSIGNED_SHORT", "GL_INT",
|
||||
"GL_UNSIGNED_INT", "GL_FLOAT", "GL_VOID"
|
||||
};
|
||||
|
||||
assert(self);
|
||||
|
||||
fprintf(stderr, "%ld vertices, %ld indices\n", vector_size(self->vertices),
|
||||
vector_size(self->indices));
|
||||
while (self->attributes[i])
|
||||
{
|
||||
int j = 8;
|
||||
switch (self->attributes[i]->type)
|
||||
{
|
||||
case GL_BOOL:
|
||||
j = 0;
|
||||
break;
|
||||
case GL_BYTE:
|
||||
j = 1;
|
||||
break;
|
||||
case GL_UNSIGNED_BYTE:
|
||||
j = 2;
|
||||
break;
|
||||
case GL_SHORT:
|
||||
j = 3;
|
||||
break;
|
||||
case GL_UNSIGNED_SHORT:
|
||||
j = 4;
|
||||
break;
|
||||
case GL_INT:
|
||||
j = 5;
|
||||
break;
|
||||
case GL_UNSIGNED_INT:
|
||||
j = 6;
|
||||
break;
|
||||
case GL_FLOAT:
|
||||
j = 7;
|
||||
break;
|
||||
default:
|
||||
j = 8;
|
||||
break;
|
||||
}
|
||||
fprintf(stderr, "%s : %dx%s (+%p)\n", self->attributes[i]->name,
|
||||
self->attributes[i]->size, gltypes[j],
|
||||
self->attributes[i]->pointer);
|
||||
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void vertex_buffer_upload(vertex_buffer_t *self)
|
||||
{
|
||||
size_t vsize, isize;
|
||||
|
||||
if (self->state == FROZEN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!self->vertices_id)
|
||||
{
|
||||
glGenBuffers(1, &self->vertices_id);
|
||||
}
|
||||
if (!self->indices_id)
|
||||
{
|
||||
glGenBuffers(1, &self->indices_id);
|
||||
}
|
||||
|
||||
vsize = self->vertices->size * self->vertices->item_size;
|
||||
isize = self->indices->size * self->indices->item_size;
|
||||
|
||||
// Always upload vertices first such that indices do not point to non
|
||||
// existing data (if we get interrupted in between for example).
|
||||
|
||||
// Upload vertices
|
||||
glBindBuffer(GL_ARRAY_BUFFER, self->vertices_id);
|
||||
if (vsize != self->GPU_vsize)
|
||||
{
|
||||
glBufferData(GL_ARRAY_BUFFER, vsize, self->vertices->items,
|
||||
GL_DYNAMIC_DRAW);
|
||||
self->GPU_vsize = vsize;
|
||||
}
|
||||
else
|
||||
{
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, vsize, self->vertices->items);
|
||||
}
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
|
||||
// Upload indices
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self->indices_id);
|
||||
if (isize != self->GPU_isize)
|
||||
{
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, isize, self->indices->items,
|
||||
GL_DYNAMIC_DRAW);
|
||||
self->GPU_isize = isize;
|
||||
}
|
||||
else
|
||||
{
|
||||
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, isize,
|
||||
self->indices->items);
|
||||
}
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void vertex_buffer_clear(vertex_buffer_t *self)
|
||||
{
|
||||
assert(self);
|
||||
|
||||
self->state = FROZEN;
|
||||
vector_clear(self->indices);
|
||||
vector_clear(self->vertices);
|
||||
vector_clear(self->items);
|
||||
self->state = DIRTY;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void vertex_buffer_render_setup(vertex_buffer_t *self, GLenum mode)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
#ifdef FREETYPE_GL_USE_VAO
|
||||
// Unbind so no existing VAO-state is overwritten,
|
||||
// (e.g. the GL_ELEMENT_ARRAY_BUFFER-binding).
|
||||
glBindVertexArray(0);
|
||||
#endif
|
||||
|
||||
if (self->state != CLEAN)
|
||||
{
|
||||
vertex_buffer_upload(self);
|
||||
self->state = CLEAN;
|
||||
}
|
||||
|
||||
#ifdef FREETYPE_GL_USE_VAO
|
||||
if (self->VAO_id == 0)
|
||||
{
|
||||
// Generate and set up VAO
|
||||
|
||||
glGenVertexArrays(1, &self->VAO_id);
|
||||
glBindVertexArray(self->VAO_id);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, self->vertices_id);
|
||||
|
||||
for (i = 0; i < MAX_VERTEX_ATTRIBUTE; ++i)
|
||||
{
|
||||
vertex_attribute_t *attribute = self->attributes[i];
|
||||
if (attribute == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
vertex_attribute_enable(attribute);
|
||||
}
|
||||
}
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
|
||||
if (self->indices->size)
|
||||
{
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self->indices_id);
|
||||
}
|
||||
}
|
||||
|
||||
// Bind VAO for drawing
|
||||
glBindVertexArray(self->VAO_id);
|
||||
#else
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, self->vertices_id);
|
||||
|
||||
for (i = 0; i < MAX_VERTEX_ATTRIBUTE; ++i)
|
||||
{
|
||||
vertex_attribute_t *attribute = self->attributes[i];
|
||||
if (attribute == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
vertex_attribute_enable(attribute);
|
||||
}
|
||||
}
|
||||
|
||||
if (self->indices->size)
|
||||
{
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self->indices_id);
|
||||
}
|
||||
#endif
|
||||
|
||||
self->mode = mode;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void vertex_buffer_render_finish(vertex_buffer_t *self)
|
||||
{
|
||||
#ifdef FREETYPE_GL_USE_VAO
|
||||
glBindVertexArray(0);
|
||||
#else
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_VERTEX_ATTRIBUTE; ++i)
|
||||
{
|
||||
vertex_attribute_t *attribute = self->attributes[i];
|
||||
if (attribute == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
glDisableVertexAttribArray(attribute->index);
|
||||
}
|
||||
}
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void vertex_buffer_render_item(vertex_buffer_t *self, size_t index)
|
||||
{
|
||||
ivec4 *item = (ivec4 *) vector_get(self->items, index);
|
||||
assert(self);
|
||||
assert(index < vector_size(self->items));
|
||||
|
||||
if (self->indices->size)
|
||||
{
|
||||
size_t start = item->istart;
|
||||
size_t count = item->icount;
|
||||
glDrawElements(self->mode, count, GL_UNSIGNED_INT,
|
||||
(void *) (start * sizeof(GLuint)));
|
||||
}
|
||||
else if (self->vertices->size)
|
||||
{
|
||||
size_t start = item->vstart;
|
||||
size_t count = item->vcount;
|
||||
glDrawArrays(self->mode, start * self->vertices->item_size, count);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void vertex_buffer_render(vertex_buffer_t *self, GLenum mode)
|
||||
{
|
||||
size_t vcount = self->vertices->size;
|
||||
size_t icount = self->indices->size;
|
||||
|
||||
vertex_buffer_render_setup(self, mode);
|
||||
if (icount)
|
||||
{
|
||||
glDrawElements(mode, icount, GL_UNSIGNED_INT, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
glDrawArrays(mode, 0, vcount);
|
||||
}
|
||||
vertex_buffer_render_finish(self);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void vertex_buffer_push_back_indices(vertex_buffer_t *self,
|
||||
const GLuint *indices, const size_t icount)
|
||||
{
|
||||
assert(self);
|
||||
|
||||
self->state |= DIRTY;
|
||||
vector_push_back_data(self->indices, indices, icount);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void vertex_buffer_push_back_vertices(vertex_buffer_t *self,
|
||||
const void *vertices, const size_t vcount)
|
||||
{
|
||||
assert(self);
|
||||
|
||||
self->state |= DIRTY;
|
||||
vector_push_back_data(self->vertices, vertices, vcount);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void vertex_buffer_insert_indices(vertex_buffer_t *self, const size_t index,
|
||||
const GLuint *indices, const size_t count)
|
||||
{
|
||||
assert(self);
|
||||
assert(self->indices);
|
||||
assert(index < self->indices->size + 1);
|
||||
|
||||
self->state |= DIRTY;
|
||||
vector_insert_data(self->indices, index, indices, count);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void vertex_buffer_insert_vertices(vertex_buffer_t *self, const size_t index,
|
||||
const void *vertices, const size_t vcount)
|
||||
{
|
||||
size_t i;
|
||||
assert(self);
|
||||
assert(self->vertices);
|
||||
assert(index < self->vertices->size + 1);
|
||||
|
||||
self->state |= DIRTY;
|
||||
|
||||
for (i = 0; i < self->indices->size; ++i)
|
||||
{
|
||||
if (*(GLuint *) (vector_get(self->indices, i)) > index)
|
||||
{
|
||||
*(GLuint *) (vector_get(self->indices, i)) += index;
|
||||
}
|
||||
}
|
||||
|
||||
vector_insert_data(self->vertices, index, vertices, vcount);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void vertex_buffer_erase_indices(vertex_buffer_t *self, const size_t first,
|
||||
const size_t last)
|
||||
{
|
||||
assert(self);
|
||||
assert(self->indices);
|
||||
assert(first < self->indices->size);
|
||||
assert((last) <= self->indices->size);
|
||||
|
||||
self->state |= DIRTY;
|
||||
vector_erase_range(self->indices, first, last);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void vertex_buffer_erase_vertices(vertex_buffer_t *self, const size_t first,
|
||||
const size_t last)
|
||||
{
|
||||
size_t i;
|
||||
assert(self);
|
||||
assert(self->vertices);
|
||||
assert(first < self->vertices->size);
|
||||
assert(last <= self->vertices->size);
|
||||
assert(last > first);
|
||||
|
||||
self->state |= DIRTY;
|
||||
for (i = 0; i < self->indices->size; ++i)
|
||||
{
|
||||
if (*(GLuint *) (vector_get(self->indices, i)) > first)
|
||||
{
|
||||
*(GLuint *) (vector_get(self->indices, i)) -= (last - first);
|
||||
}
|
||||
}
|
||||
vector_erase_range(self->vertices, first, last);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
size_t vertex_buffer_push_back(vertex_buffer_t *self, const void *vertices,
|
||||
const size_t vcount, const GLuint *indices,
|
||||
const size_t icount)
|
||||
{
|
||||
return vertex_buffer_insert(self, vector_size(self->items), vertices,
|
||||
vcount, indices, icount);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
size_t vertex_buffer_insert(vertex_buffer_t *self, const size_t index,
|
||||
const void *vertices, const size_t vcount,
|
||||
const GLuint *indices, const size_t icount)
|
||||
{
|
||||
size_t vstart, istart, i;
|
||||
ivec4 item;
|
||||
assert(self);
|
||||
assert(vertices);
|
||||
assert(indices);
|
||||
|
||||
self->state = FROZEN;
|
||||
|
||||
// Push back vertices
|
||||
vstart = vector_size(self->vertices);
|
||||
vertex_buffer_push_back_vertices(self, vertices, vcount);
|
||||
|
||||
// Push back indices
|
||||
istart = vector_size(self->indices);
|
||||
vertex_buffer_push_back_indices(self, indices, icount);
|
||||
|
||||
// Update indices within the vertex buffer
|
||||
for (i = 0; i < icount; ++i)
|
||||
{
|
||||
*(GLuint *) (vector_get(self->indices, istart + i)) += vstart;
|
||||
}
|
||||
|
||||
// Insert item
|
||||
item.x = vstart;
|
||||
item.y = vcount;
|
||||
item.z = istart;
|
||||
item.w = icount;
|
||||
vector_insert(self->items, index, &item);
|
||||
|
||||
self->state = DIRTY;
|
||||
return index;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void vertex_buffer_erase(vertex_buffer_t *self, const size_t index)
|
||||
{
|
||||
ivec4 *item;
|
||||
int vstart;
|
||||
size_t vcount, istart, icount, i;
|
||||
|
||||
assert(self);
|
||||
assert(index < vector_size(self->items));
|
||||
|
||||
item = (ivec4 *) vector_get(self->items, index);
|
||||
vstart = item->vstart;
|
||||
vcount = item->vcount;
|
||||
istart = item->istart;
|
||||
icount = item->icount;
|
||||
|
||||
// Update items
|
||||
for (i = 0; i < vector_size(self->items); ++i)
|
||||
{
|
||||
ivec4 *item = (ivec4 *) vector_get(self->items, i);
|
||||
if (item->vstart > vstart)
|
||||
{
|
||||
item->vstart -= vcount;
|
||||
item->istart -= icount;
|
||||
}
|
||||
}
|
||||
|
||||
self->state = FROZEN;
|
||||
vertex_buffer_erase_indices(self, istart, istart + icount);
|
||||
vertex_buffer_erase_vertices(self, vstart, vstart + vcount);
|
||||
vector_erase(self->items, index);
|
||||
self->state = DIRTY;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user