Sculpt Branch:
* Fallback code in case VBO allocation fails.
This commit is contained in:
@@ -386,8 +386,22 @@ typedef struct {
|
||||
} VertexBufferFormat;
|
||||
|
||||
typedef struct {
|
||||
/* opengl buffer handles */
|
||||
GLuint vert_buf, index_buf;
|
||||
GLenum index_type;
|
||||
|
||||
/* mesh pointers in case buffer allocation fails */
|
||||
MFace *mface;
|
||||
MVert *mvert;
|
||||
int *face_indices;
|
||||
int totface;
|
||||
|
||||
/* grid pointers */
|
||||
DMGridData **grids;
|
||||
int *grid_indices;
|
||||
int totgrid;
|
||||
int gridsize;
|
||||
|
||||
unsigned int tot_tri, tot_quad;
|
||||
} GPU_Buffers;
|
||||
|
||||
@@ -398,21 +412,34 @@ void GPU_update_mesh_buffers(void *buffers_v, MVert *mvert,
|
||||
VertexBufferFormat *vert_data;
|
||||
int i;
|
||||
|
||||
/* Build VBO */
|
||||
glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffers->vert_buf);
|
||||
glBufferDataARB(GL_ARRAY_BUFFER_ARB,
|
||||
sizeof(VertexBufferFormat) * totvert,
|
||||
NULL, GL_STATIC_DRAW_ARB);
|
||||
vert_data = glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
|
||||
if(buffers->vert_buf) {
|
||||
/* Build VBO */
|
||||
glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffers->vert_buf);
|
||||
glBufferDataARB(GL_ARRAY_BUFFER_ARB,
|
||||
sizeof(VertexBufferFormat) * totvert,
|
||||
NULL, GL_STATIC_DRAW_ARB);
|
||||
vert_data = glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
|
||||
|
||||
for(i = 0; i < totvert; ++i) {
|
||||
MVert *v = mvert + vert_indices[i];
|
||||
VertexBufferFormat *out = vert_data + i;
|
||||
if(vert_data) {
|
||||
for(i = 0; i < totvert; ++i) {
|
||||
MVert *v = mvert + vert_indices[i];
|
||||
VertexBufferFormat *out = vert_data + i;
|
||||
|
||||
copy_v3_v3(out->co, v->co);
|
||||
memcpy(out->no, v->no, sizeof(short) * 3);
|
||||
copy_v3_v3(out->co, v->co);
|
||||
memcpy(out->no, v->no, sizeof(short) * 3);
|
||||
}
|
||||
|
||||
glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
|
||||
}
|
||||
else {
|
||||
glDeleteBuffersARB(1, &buffers->vert_buf);
|
||||
buffers->vert_buf = 0;
|
||||
}
|
||||
|
||||
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
|
||||
}
|
||||
glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
|
||||
|
||||
buffers->mvert = mvert;
|
||||
}
|
||||
|
||||
void *GPU_build_mesh_buffers(GHash *map, MVert *mvert, MFace *mface,
|
||||
@@ -431,47 +458,61 @@ void *GPU_build_mesh_buffers(GHash *map, MVert *mvert, MFace *mface,
|
||||
for(i = 0, tottri = 0; i < totface; ++i)
|
||||
tottri += mface[face_indices[i]].v4 ? 2 : 1;
|
||||
|
||||
/* Generate index buffer object */
|
||||
glGenBuffersARB(1, &buffers->index_buf);
|
||||
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, buffers->index_buf);
|
||||
glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB,
|
||||
sizeof(unsigned short) * tottri * 3, NULL, GL_STATIC_DRAW_ARB);
|
||||
if(buffers->index_buf) {
|
||||
/* Generate index buffer object */
|
||||
glGenBuffersARB(1, &buffers->index_buf);
|
||||
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, buffers->index_buf);
|
||||
glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB,
|
||||
sizeof(unsigned short) * tottri * 3, NULL, GL_STATIC_DRAW_ARB);
|
||||
|
||||
/* Fill the triangle buffer */
|
||||
tri_data = glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
|
||||
for(i = 0; i < totface; ++i) {
|
||||
MFace *f = mface + face_indices[i];
|
||||
int v[3] = {f->v1, f->v2, f->v3};
|
||||
/* Fill the triangle buffer */
|
||||
tri_data = glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
|
||||
if(tri_data) {
|
||||
for(i = 0; i < totface; ++i) {
|
||||
MFace *f = mface + face_indices[i];
|
||||
int v[3] = {f->v1, f->v2, f->v3};
|
||||
|
||||
for(j = 0; j < (f->v4 ? 2 : 1); ++j) {
|
||||
for(k = 0; k < 3; ++k) {
|
||||
void *value, *key = SET_INT_IN_POINTER(v[k]);
|
||||
int vbo_index;
|
||||
for(j = 0; j < (f->v4 ? 2 : 1); ++j) {
|
||||
for(k = 0; k < 3; ++k) {
|
||||
void *value, *key = SET_INT_IN_POINTER(v[k]);
|
||||
int vbo_index;
|
||||
|
||||
value = BLI_ghash_lookup(map, key);
|
||||
vbo_index = GET_INT_FROM_POINTER(value);
|
||||
value = BLI_ghash_lookup(map, key);
|
||||
vbo_index = GET_INT_FROM_POINTER(value);
|
||||
|
||||
if(vbo_index < 0) {
|
||||
vbo_index = -vbo_index +
|
||||
tot_uniq_verts - 1;
|
||||
if(vbo_index < 0) {
|
||||
vbo_index = -vbo_index +
|
||||
tot_uniq_verts - 1;
|
||||
}
|
||||
|
||||
*tri_data = vbo_index;
|
||||
++tri_data;
|
||||
}
|
||||
v[0] = f->v4;
|
||||
v[1] = f->v1;
|
||||
v[2] = f->v3;
|
||||
}
|
||||
|
||||
*tri_data = vbo_index;
|
||||
++tri_data;
|
||||
}
|
||||
v[0] = f->v4;
|
||||
v[1] = f->v1;
|
||||
v[2] = f->v3;
|
||||
glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB);
|
||||
}
|
||||
else {
|
||||
glDeleteBuffersARB(1, &buffers->index_buf);
|
||||
buffers->index_buf = 0;
|
||||
}
|
||||
}
|
||||
glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB);
|
||||
|
||||
/* Build VBO */
|
||||
glGenBuffersARB(1, &buffers->vert_buf);
|
||||
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
|
||||
}
|
||||
|
||||
if(buffers->vert_buf)
|
||||
glGenBuffersARB(1, &buffers->vert_buf);
|
||||
GPU_update_mesh_buffers(buffers, mvert, vert_indices, totvert);
|
||||
|
||||
buffers->tot_tri = tottri;
|
||||
|
||||
buffers->mface = mface;
|
||||
buffers->face_indices = face_indices;
|
||||
buffers->totface = totface;
|
||||
|
||||
return buffers;
|
||||
}
|
||||
|
||||
@@ -485,18 +526,31 @@ void GPU_update_grid_buffers(void *buffers_v, DMGridData **grids,
|
||||
totvert= gridsize*gridsize*totgrid;
|
||||
|
||||
/* Build VBO */
|
||||
glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffers->vert_buf);
|
||||
glBufferDataARB(GL_ARRAY_BUFFER_ARB,
|
||||
sizeof(DMGridData) * totvert,
|
||||
NULL, GL_STATIC_DRAW_ARB);
|
||||
vert_data = glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
|
||||
|
||||
for(i = 0; i < totgrid; ++i) {
|
||||
DMGridData *grid= grids[grid_indices[i]];
|
||||
memcpy(vert_data, grid, sizeof(DMGridData)*gridsize*gridsize);
|
||||
vert_data += gridsize*gridsize;
|
||||
if(buffers->vert_buf) {
|
||||
glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffers->vert_buf);
|
||||
glBufferDataARB(GL_ARRAY_BUFFER_ARB,
|
||||
sizeof(DMGridData) * totvert,
|
||||
NULL, GL_STATIC_DRAW_ARB);
|
||||
vert_data = glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
|
||||
if(vert_data) {
|
||||
for(i = 0; i < totgrid; ++i) {
|
||||
DMGridData *grid= grids[grid_indices[i]];
|
||||
memcpy(vert_data, grid, sizeof(DMGridData)*gridsize*gridsize);
|
||||
vert_data += gridsize*gridsize;
|
||||
}
|
||||
glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
|
||||
}
|
||||
else {
|
||||
glDeleteBuffersARB(1, &buffers->vert_buf);
|
||||
buffers->vert_buf = 0;
|
||||
}
|
||||
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
|
||||
}
|
||||
glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
|
||||
|
||||
buffers->grids = grids;
|
||||
buffers->grid_indices = grid_indices;
|
||||
buffers->totgrid = totgrid;
|
||||
buffers->gridsize = gridsize;
|
||||
|
||||
//printf("node updated %p\n", buffers_v);
|
||||
}
|
||||
@@ -514,57 +568,75 @@ void *GPU_build_grid_buffers(DMGridData **grids,
|
||||
|
||||
/* Generate index buffer object */
|
||||
glGenBuffersARB(1, &buffers->index_buf);
|
||||
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, buffers->index_buf);
|
||||
if(buffers->index_buf) {
|
||||
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, buffers->index_buf);
|
||||
|
||||
if(totquad < USHRT_MAX) {
|
||||
unsigned short *quad_data;
|
||||
if(totquad < USHRT_MAX) {
|
||||
unsigned short *quad_data;
|
||||
|
||||
buffers->index_type = GL_UNSIGNED_SHORT;
|
||||
glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB,
|
||||
sizeof(unsigned short) * totquad * 4, NULL, GL_STATIC_DRAW_ARB);
|
||||
buffers->index_type = GL_UNSIGNED_SHORT;
|
||||
glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB,
|
||||
sizeof(unsigned short) * totquad * 4, NULL, GL_STATIC_DRAW_ARB);
|
||||
|
||||
/* Fill the quad buffer */
|
||||
quad_data = glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
|
||||
for(i = 0; i < totgrid; ++i) {
|
||||
for(j = 0; j < gridsize-1; ++j) {
|
||||
for(k = 0; k < gridsize-1; ++k) {
|
||||
*(quad_data++)= offset + j*gridsize + k;
|
||||
*(quad_data++)= offset + (j+1)*gridsize + k;
|
||||
*(quad_data++)= offset + (j+1)*gridsize + k+1;
|
||||
*(quad_data++)= offset + j*gridsize + k+1;
|
||||
/* Fill the quad buffer */
|
||||
quad_data = glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
|
||||
if(quad_data) {
|
||||
for(i = 0; i < totgrid; ++i) {
|
||||
for(j = 0; j < gridsize-1; ++j) {
|
||||
for(k = 0; k < gridsize-1; ++k) {
|
||||
*(quad_data++)= offset + j*gridsize + k;
|
||||
*(quad_data++)= offset + (j+1)*gridsize + k;
|
||||
*(quad_data++)= offset + (j+1)*gridsize + k+1;
|
||||
*(quad_data++)= offset + j*gridsize + k+1;
|
||||
}
|
||||
}
|
||||
|
||||
offset += gridsize*gridsize;
|
||||
}
|
||||
glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB);
|
||||
}
|
||||
else {
|
||||
glDeleteBuffersARB(1, &buffers->index_buf);
|
||||
buffers->index_buf = 0;
|
||||
}
|
||||
|
||||
offset += gridsize*gridsize;
|
||||
}
|
||||
glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB);
|
||||
}
|
||||
else {
|
||||
unsigned int *quad_data;
|
||||
else {
|
||||
unsigned int *quad_data;
|
||||
|
||||
buffers->index_type = GL_UNSIGNED_INT;
|
||||
glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB,
|
||||
sizeof(unsigned int) * totquad * 4, NULL, GL_STATIC_DRAW_ARB);
|
||||
buffers->index_type = GL_UNSIGNED_INT;
|
||||
glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB,
|
||||
sizeof(unsigned int) * totquad * 4, NULL, GL_STATIC_DRAW_ARB);
|
||||
|
||||
/* Fill the quad buffer */
|
||||
quad_data = glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
|
||||
for(i = 0; i < totgrid; ++i) {
|
||||
for(j = 0; j < gridsize-1; ++j) {
|
||||
for(k = 0; k < gridsize-1; ++k) {
|
||||
*(quad_data++)= offset + j*gridsize + k;
|
||||
*(quad_data++)= offset + (j+1)*gridsize + k;
|
||||
*(quad_data++)= offset + (j+1)*gridsize + k+1;
|
||||
*(quad_data++)= offset + j*gridsize + k+1;
|
||||
/* Fill the quad buffer */
|
||||
quad_data = glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
|
||||
|
||||
if(quad_data) {
|
||||
for(i = 0; i < totgrid; ++i) {
|
||||
for(j = 0; j < gridsize-1; ++j) {
|
||||
for(k = 0; k < gridsize-1; ++k) {
|
||||
*(quad_data++)= offset + j*gridsize + k;
|
||||
*(quad_data++)= offset + (j+1)*gridsize + k;
|
||||
*(quad_data++)= offset + (j+1)*gridsize + k+1;
|
||||
*(quad_data++)= offset + j*gridsize + k+1;
|
||||
}
|
||||
}
|
||||
|
||||
offset += gridsize*gridsize;
|
||||
}
|
||||
glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB);
|
||||
}
|
||||
else {
|
||||
glDeleteBuffersARB(1, &buffers->index_buf);
|
||||
buffers->index_buf = 0;
|
||||
}
|
||||
|
||||
offset += gridsize*gridsize;
|
||||
}
|
||||
glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB);
|
||||
|
||||
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
|
||||
}
|
||||
|
||||
/* Build VBO */
|
||||
glGenBuffersARB(1, &buffers->vert_buf);
|
||||
if(buffers->index_buf)
|
||||
glGenBuffersARB(1, &buffers->vert_buf);
|
||||
GPU_update_grid_buffers(buffers, grids, grid_indices, totgrid, gridsize);
|
||||
|
||||
buffers->tot_quad = totquad;
|
||||
@@ -576,20 +648,70 @@ void GPU_draw_buffers(void *buffers_v)
|
||||
{
|
||||
GPU_Buffers *buffers = buffers_v;
|
||||
|
||||
glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffers->vert_buf);
|
||||
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, buffers->index_buf);
|
||||
if(buffers->vert_buf && buffers->index_buf) {
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
|
||||
if(buffers->tot_quad) {
|
||||
glVertexPointer(3, GL_FLOAT, sizeof(DMGridData), 0);
|
||||
glNormalPointer(GL_FLOAT, sizeof(DMGridData), (void*)offsetof(DMGridData, no));
|
||||
glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffers->vert_buf);
|
||||
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, buffers->index_buf);
|
||||
|
||||
glDrawElements(GL_QUADS, buffers->tot_quad * 4, buffers->index_type, 0);
|
||||
if(buffers->tot_quad) {
|
||||
glVertexPointer(3, GL_FLOAT, sizeof(DMGridData), (void*)offsetof(DMGridData, co));
|
||||
glNormalPointer(GL_FLOAT, sizeof(DMGridData), (void*)offsetof(DMGridData, no));
|
||||
|
||||
glDrawElements(GL_QUADS, buffers->tot_quad * 4, buffers->index_type, 0);
|
||||
}
|
||||
else {
|
||||
glVertexPointer(3, GL_FLOAT, sizeof(VertexBufferFormat), (void*)offsetof(VertexBufferFormat, co));
|
||||
glNormalPointer(GL_SHORT, sizeof(VertexBufferFormat), (void*)offsetof(VertexBufferFormat, no));
|
||||
|
||||
glDrawElements(GL_TRIANGLES, buffers->tot_tri * 3, buffers->index_type, 0);
|
||||
}
|
||||
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_NORMAL_ARRAY);
|
||||
}
|
||||
else {
|
||||
glVertexPointer(3, GL_FLOAT, sizeof(VertexBufferFormat), 0);
|
||||
glNormalPointer(GL_SHORT, sizeof(VertexBufferFormat), (void*)offsetof(VertexBufferFormat, no));
|
||||
else if(buffers->totface) {
|
||||
/* fallback if we are out of memory */
|
||||
int i;
|
||||
|
||||
glDrawElements(GL_TRIANGLES, buffers->tot_tri * 3, buffers->index_type, 0);
|
||||
for(i = 0; i < buffers->totface; ++i) {
|
||||
MFace *f = buffers->mface + buffers->face_indices[i];
|
||||
|
||||
glBegin((f->v4)? GL_QUADS: GL_TRIANGLES);
|
||||
glNormal3sv(buffers->mvert[f->v1].no);
|
||||
glVertex3fv(buffers->mvert[f->v1].co);
|
||||
glNormal3sv(buffers->mvert[f->v2].no);
|
||||
glVertex3fv(buffers->mvert[f->v2].co);
|
||||
glNormal3sv(buffers->mvert[f->v3].no);
|
||||
glVertex3fv(buffers->mvert[f->v3].co);
|
||||
if(f->v4) {
|
||||
glNormal3sv(buffers->mvert[f->v4].no);
|
||||
glVertex3fv(buffers->mvert[f->v4].co);
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
}
|
||||
else if(buffers->totgrid) {
|
||||
int i, x, y, gridsize = buffers->gridsize;
|
||||
|
||||
for(i = 0; i < buffers->totgrid; ++i) {
|
||||
DMGridData *grid = buffers->grids[buffers->grid_indices[i]];
|
||||
|
||||
for(y = 0; y < gridsize-1; y++) {
|
||||
glBegin(GL_QUAD_STRIP);
|
||||
for(x = 0; x < gridsize; x++) {
|
||||
DMGridData *a = &grid[y*gridsize + x];
|
||||
DMGridData *b = &grid[(y+1)*gridsize + x];
|
||||
|
||||
glNormal3fv(a->no);
|
||||
glVertex3fv(a->co);
|
||||
glNormal3fv(b->no);
|
||||
glVertex3fv(b->co);
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -598,8 +720,10 @@ void GPU_free_buffers(void *buffers_v)
|
||||
if(buffers_v) {
|
||||
GPU_Buffers *buffers = buffers_v;
|
||||
|
||||
glDeleteBuffersARB(1, &buffers->vert_buf);
|
||||
glDeleteBuffersARB(1, &buffers->index_buf);
|
||||
if(buffers->vert_buf)
|
||||
glDeleteBuffersARB(1, &buffers->vert_buf);
|
||||
if(buffers->index_buf)
|
||||
glDeleteBuffersARB(1, &buffers->index_buf);
|
||||
|
||||
MEM_freeN(buffers);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user