Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/blenkernel/BKE_DerivedMesh.h3
-rw-r--r--source/blender/blenkernel/BKE_pbvh.h2
-rw-r--r--source/blender/blenkernel/intern/cdderivedmesh.c1187
-rw-r--r--source/blender/blenkernel/intern/pbvh.c8
-rw-r--r--source/blender/blenkernel/intern/subsurf_ccg.c813
-rw-r--r--source/blender/gpu/GPU_buffers.h56
-rw-r--r--source/blender/gpu/intern/gpu_buffers.c746
7 files changed, 1635 insertions, 1180 deletions
diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h
index 984147de3af..881b233dc3c 100644
--- a/source/blender/blenkernel/BKE_DerivedMesh.h
+++ b/source/blender/blenkernel/BKE_DerivedMesh.h
@@ -463,6 +463,9 @@ struct DerivedMesh {
void (*setMaterial)(void *userData, int matnr, void *attribs),
bool (*setFace)(void *userData, int index), void *userData);
+ struct GPUDrawObject *(*gpuObjectNew)(DerivedMesh *dm);
+ void (*copy_gpu_data)(DerivedMesh *dm, int type, float *varray, int *mat_orig_to_new, void *user_data);
+
/** Release reference to the DerivedMesh. This function decides internally
* if the DerivedMesh will be freed, or cached for later use. */
void (*release)(DerivedMesh *dm);
diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h
index 0832e2498d4..fbaf91d60bd 100644
--- a/source/blender/blenkernel/BKE_pbvh.h
+++ b/source/blender/blenkernel/BKE_pbvh.h
@@ -112,7 +112,7 @@ void BKE_pbvh_raycast_project_ray_root(
void BKE_pbvh_node_draw(PBVHNode *node, void *data);
void BKE_pbvh_draw(PBVH *bvh, float (*planes)[4], float (*face_nors)[3],
- int (*setMaterial)(int matnr, void *attribs), bool wireframe);
+ int (*setMaterial)(int matnr, void *attribs), bool wireframe, bool fast);
/* PBVH Access */
typedef enum {
diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c
index 37c3376ecdb..475233206f8 100644
--- a/source/blender/blenkernel/intern/cdderivedmesh.c
+++ b/source/blender/blenkernel/intern/cdderivedmesh.c
@@ -341,8 +341,8 @@ static void cdDM_update_normals_from_pbvh(DerivedMesh *dm)
static void cdDM_drawVerts(DerivedMesh *dm)
{
GPU_vertex_setup(dm);
- if (dm->drawObject->tot_triangle_point)
- glDrawArrays(GL_POINTS, 0, dm->drawObject->tot_triangle_point);
+ if (dm->drawObject->tot_loop_verts)
+ glDrawArrays(GL_POINTS, 0, dm->drawObject->tot_loop_verts);
else
glDrawArrays(GL_POINTS, 0, dm->drawObject->tot_loose_point);
GPU_buffer_unbind();
@@ -391,7 +391,7 @@ static void cdDM_drawEdges(DerivedMesh *dm, bool drawLooseEdges, bool drawAllEdg
if (cddm->pbvh && cddm->pbvh_draw &&
BKE_pbvh_type(cddm->pbvh) == PBVH_BMESH)
{
- BKE_pbvh_draw(cddm->pbvh, NULL, NULL, NULL, true);
+ BKE_pbvh_draw(cddm->pbvh, NULL, NULL, NULL, true, false);
return;
}
@@ -442,7 +442,7 @@ static void cdDM_drawFacesSolid(DerivedMesh *dm,
float (*face_nors)[3] = CustomData_get_layer(&dm->faceData, CD_NORMAL);
BKE_pbvh_draw(cddm->pbvh, partial_redraw_planes, face_nors,
- setMaterial, false);
+ setMaterial, false, false);
glShadeModel(GL_FLAT);
}
@@ -451,11 +451,11 @@ static void cdDM_drawFacesSolid(DerivedMesh *dm,
GPU_vertex_setup(dm);
GPU_normal_setup(dm);
+ GPU_triangle_setup(dm);
glShadeModel(GL_SMOOTH);
for (a = 0; a < dm->drawObject->totmaterial; a++) {
if (!setMaterial || setMaterial(dm->drawObject->materials[a].mat_nr + 1, NULL)) {
- glDrawArrays(GL_TRIANGLES, dm->drawObject->materials[a].start,
- dm->drawObject->materials[a].totpoint);
+ GPU_buffer_draw_elements(dm->drawObject->triangles, GL_TRIANGLES, dm->drawObject->materials[a].start, dm->drawObject->materials[a].totelements);
}
}
GPU_buffer_unbind();
@@ -473,12 +473,13 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm,
const MFace *mf = DM_get_tessface_data_layer(dm, CD_MFACE);
MTexPoly *mtexpoly = DM_get_poly_data_layer(dm, CD_MTEXPOLY);
MCol *mcol;
- int i;
- int colType, startFace = 0;
+ int i, orig;
+ int colType, start_element;
bool use_tface = (uvflag & DM_DRAW_USE_ACTIVE_UV) != 0;
- int tottri;
+ int totpoly;
int next_actualFace;
-
+ int mat_index;
+ int tot_element;
/* double lookup */
const int *index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
@@ -497,7 +498,7 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm,
if (cddm->pbvh && cddm->pbvh_draw && BKE_pbvh_type(cddm->pbvh) == PBVH_BMESH) {
if (BKE_pbvh_has_faces(cddm->pbvh)) {
GPU_set_tpage(NULL, false, false);
- BKE_pbvh_draw(cddm->pbvh, NULL, NULL, NULL, false);
+ BKE_pbvh_draw(cddm->pbvh, NULL, NULL, NULL, false, false);
}
return;
@@ -518,6 +519,7 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm,
GPU_vertex_setup(dm);
GPU_normal_setup(dm);
+ GPU_triangle_setup(dm);
if (uvflag & DM_DRAW_USE_TEXPAINT_UV)
GPU_texpaint_uv_setup(dm);
else
@@ -525,76 +527,84 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm,
if (mcol) {
GPU_color_setup(dm, colType);
}
-
- tottri = dm->drawObject->tot_triangle_point / 3;
- next_actualFace = dm->drawObject->triangle_to_mface[0];
-
+
glShadeModel(GL_SMOOTH);
/* lastFlag = 0; */ /* UNUSED */
- for (i = 0; i < tottri; i++) {
- int actualFace = next_actualFace;
- DMDrawOption draw_option = DM_DRAW_OPTION_NORMAL;
- int flush = 0;
-
- if (i != tottri - 1)
- next_actualFace = dm->drawObject->triangle_to_mface[i + 1];
-
- if (drawParams) {
- MTexPoly *tp = NULL;
- if (use_tface && mtexpoly && index_mf_to_mpoly) {
- int actualFace_poly = index_mf_to_mpoly[actualFace];
- if (actualFace_poly != ORIGINDEX_NONE) {
- tp = &mtexpoly[actualFace_poly];
+ for (mat_index = 0; mat_index < dm->drawObject->totmaterial; mat_index++) {
+ GPUBufferMaterial *bufmat = dm->drawObject->materials + mat_index;
+ next_actualFace = bufmat->polys[0];
+ totpoly = bufmat->totpolys;
+
+ tot_element = 0;
+ start_element = bufmat->start;
+
+ for (i = 0; i < totpoly; i++) {
+ int actualFace = bufmat->polys[i];
+ DMDrawOption draw_option = DM_DRAW_OPTION_NORMAL;
+ int flush = 0;
+
+ if (i != totpoly - 1)
+ next_actualFace = bufmat->polys[i + 1];
+
+ if (drawParams) {
+ MTexPoly *tp = NULL;
+ if (use_tface && mtexpoly && index_mf_to_mpoly) {
+ int actualFace_poly = index_mf_to_mpoly[actualFace];
+ if (actualFace_poly != ORIGINDEX_NONE) {
+ tp = &mtexpoly[actualFace_poly];
+ }
}
- }
- draw_option = drawParams(tp, (mcol != NULL), mf[actualFace].mat_nr);
- }
- else {
- if (index_mf_to_mpoly) {
- const int orig = DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, actualFace);
- if (orig == ORIGINDEX_NONE) {
- /* XXX, this is not really correct
- * it will draw the previous faces context for this one when we don't know its settings.
- * but better then skipping it altogether. - campbell */
- draw_option = DM_DRAW_OPTION_NORMAL;
+ draw_option = drawParams(tp, (mcol != NULL), mf[actualFace].mat_nr);
+ }
+ else {
+ if (index_mf_to_mpoly) {
+ orig = DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, actualFace);
+ if (orig == ORIGINDEX_NONE) {
+ /* XXX, this is not really correct
+ * it will draw the previous faces context for this one when we don't know its settings.
+ * but better then skipping it altogether. - campbell */
+ draw_option = DM_DRAW_OPTION_NORMAL;
+ }
+ else if (drawParamsMapped) {
+ draw_option = drawParamsMapped(userData, orig, mf[actualFace].mat_nr);
+ }
}
else if (drawParamsMapped) {
- draw_option = drawParamsMapped(userData, orig, mf[actualFace].mat_nr);
+ draw_option = drawParamsMapped(userData, actualFace, mf[actualFace].mat_nr);
}
}
- else if (drawParamsMapped) {
- draw_option = drawParamsMapped(userData, actualFace, mf[actualFace].mat_nr);
+
+ /* flush buffer if current triangle isn't drawable or it's last triangle */
+ flush = (draw_option == DM_DRAW_OPTION_SKIP) || (i == totpoly - 1);
+
+ if (!flush && compareDrawOptions) {
+ /* also compare draw options and flush buffer if they're different
+ * need for face selection highlight in edit mode */
+ flush |= compareDrawOptions(userData, actualFace, next_actualFace) == 0;
}
- }
-
- /* flush buffer if current triangle isn't drawable or it's last triangle */
- flush = (draw_option == DM_DRAW_OPTION_SKIP) || (i == tottri - 1);
-
- if (!flush && compareDrawOptions) {
- /* also compare draw options and flush buffer if they're different
- * need for face selection highlight in edit mode */
- flush |= compareDrawOptions(userData, actualFace, next_actualFace) == 0;
- }
-
- if (flush) {
- int first = startFace * 3;
- /* Add one to the length if we're drawing at the end of the array */
- int count = (i - startFace + (draw_option != DM_DRAW_OPTION_SKIP ? 1 : 0)) * 3;
-
- if (count) {
- if (mcol && draw_option != DM_DRAW_OPTION_NO_MCOL)
- GPU_color_switch(1);
- else
- GPU_color_switch(0);
-
- glDrawArrays(GL_TRIANGLES, first, count);
+
+ if (flush) {
+ if (draw_option != DM_DRAW_OPTION_SKIP)
+ tot_element += mf[actualFace].v4 ? 6 : 3;
+
+ if (tot_element) {
+ if (mcol && draw_option != DM_DRAW_OPTION_NO_MCOL)
+ GPU_color_switch(1);
+ else
+ GPU_color_switch(0);
+
+ GPU_buffer_draw_elements(dm->drawObject->triangles, GL_TRIANGLES, start_element, tot_element);
+ }
+
+ start_element = tot_element;
+ }
+ else {
+ tot_element += mf[actualFace].v4 ? 6 : 3;
}
-
- startFace = i + 1;
}
}
-
+
GPU_buffer_unbind();
glShadeModel(GL_FLAT);
@@ -747,87 +757,92 @@ static void cdDM_drawMappedFaces(DerivedMesh *dm,
}
}
else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
- int prevstart = 0;
+ int start_element = 0, tot_element;
+ int totpoly;
int tottri;
+ int mat_index;
GPU_vertex_setup(dm);
GPU_normal_setup(dm);
+ GPU_triangle_setup(dm);
if (useColors && mcol) {
GPU_color_setup(dm, colType);
}
- tottri = dm->drawObject->tot_triangle_point / 3;
glShadeModel(GL_SMOOTH);
+ tottri = dm->drawObject->tot_triangle_point / 3;
+
if (tottri == 0) {
/* avoid buffer problems in following code */
}
else if (setDrawOptions == NULL) {
/* just draw the entire face array */
- glDrawArrays(GL_TRIANGLES, 0, (tottri) * 3);
+ GPU_buffer_draw_elements(dm->drawObject->triangles, GL_TRIANGLES, 0, 3 * tottri);
}
- else {
- /* we need to check if the next material changes */
- int next_actualFace = dm->drawObject->triangle_to_mface[0];
- short prev_mat_nr = -1;
-
- for (i = 0; i < tottri; i++) {
- //int actualFace = dm->drawObject->triangle_to_mface[i];
- int actualFace = next_actualFace;
- MFace *mface = mf + actualFace;
- /*int drawSmooth = (flag & DM_DRAW_ALWAYS_SMOOTH) ? 1 : (mface->flag & ME_SMOOTH);*/ /* UNUSED */
+ else {
+ for (mat_index = 0; mat_index < dm->drawObject->totmaterial; mat_index++) {
+ GPUBufferMaterial *bufmat = dm->drawObject->materials + mat_index;
DMDrawOption draw_option = DM_DRAW_OPTION_NORMAL;
- int flush = 0;
-
- if (i != tottri - 1)
- next_actualFace = dm->drawObject->triangle_to_mface[i + 1];
-
- orig = (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, actualFace) : actualFace;
-
- if (mface->mat_nr != prev_mat_nr) {
- if (setMaterial)
- draw_option = setMaterial(mface->mat_nr + 1, NULL);
-
- prev_mat_nr = mface->mat_nr;
- }
-
- if (setDrawOptions != NULL && (orig != ORIGINDEX_NONE))
- draw_option = setDrawOptions(userData, orig);
-
- if (draw_option == DM_DRAW_OPTION_STIPPLE) {
- glEnable(GL_POLYGON_STIPPLE);
- glPolygonStipple(stipple_quarttone);
- }
-
- /* Goal is to draw as long of a contiguous triangle
+ int next_actualFace = bufmat->polys[0];
+ totpoly = bufmat->totpolys;
+
+ tot_element = 0;
+ start_element = bufmat->start;
+
+ if (setMaterial)
+ draw_option = setMaterial(bufmat->mat_nr + 1, NULL);
+
+ if (draw_option != DM_DRAW_OPTION_SKIP) {
+ for (i = 0; i < totpoly; i++) {
+ //int actualFace = dm->drawObject->triangle_to_mface[i];
+ int actualFace = next_actualFace;
+ int flush = 0;
+ draw_option = DM_DRAW_OPTION_NORMAL;
+
+ if (i != totpoly - 1)
+ next_actualFace = bufmat->polys[i + 1];
+
+ orig = (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, actualFace) : actualFace;
+
+ if (setDrawOptions != NULL && (orig != ORIGINDEX_NONE))
+ draw_option = setDrawOptions(userData, orig);
+
+ if (draw_option == DM_DRAW_OPTION_STIPPLE) {
+ glEnable(GL_POLYGON_STIPPLE);
+ glPolygonStipple(stipple_quarttone);
+ }
+
+ /* Goal is to draw as long of a contiguous triangle
* array as possible, so draw when we hit either an
* invisible triangle or at the end of the array */
-
- /* flush buffer if current triangle isn't drawable or it's last triangle... */
- flush = (ELEM(draw_option, DM_DRAW_OPTION_SKIP, DM_DRAW_OPTION_STIPPLE)) || (i == tottri - 1);
-
- /* ... or when material setting is dissferent */
- flush |= mf[actualFace].mat_nr != mf[next_actualFace].mat_nr;
-
- if (!flush && compareDrawOptions) {
- flush |= compareDrawOptions(userData, actualFace, next_actualFace) == 0;
- }
-
- if (flush) {
- int first = prevstart * 3;
- /* Add one to the length if we're drawing at the end of the array */
- int count = (i - prevstart + (draw_option != DM_DRAW_OPTION_SKIP ? 1 : 0)) * 3;
-
- if (count)
- glDrawArrays(GL_TRIANGLES, first, count);
-
- prevstart = i + 1;
-
- if (draw_option == DM_DRAW_OPTION_STIPPLE)
- glDisable(GL_POLYGON_STIPPLE);
+
+ /* flush buffer if current triangle isn't drawable or it's last triangle... */
+ flush = (ELEM(draw_option, DM_DRAW_OPTION_SKIP, DM_DRAW_OPTION_STIPPLE)) || (i == totpoly - 1);
+
+ if (!flush && compareDrawOptions) {
+ flush |= compareDrawOptions(userData, actualFace, next_actualFace) == 0;
+ }
+
+ if (flush) {
+ if (!ELEM(draw_option, DM_DRAW_OPTION_SKIP, DM_DRAW_OPTION_STIPPLE))
+ tot_element += mf[actualFace].v4 ? 6 : 3;
+
+ if (tot_element)
+ GPU_buffer_draw_elements(dm->drawObject->triangles, GL_TRIANGLES, start_element, tot_element);
+
+ start_element = tot_element;
+
+ if (draw_option == DM_DRAW_OPTION_STIPPLE)
+ glDisable(GL_POLYGON_STIPPLE);
+ }
+ else {
+ tot_element += mf[actualFace].v4 ? 6 : 3;
+ }
+ }
+
+ glShadeModel(GL_FLAT);
}
}
-
- glShadeModel(GL_FLAT);
}
GPU_buffer_unbind();
}
@@ -858,6 +873,13 @@ static void cddm_draw_attrib_vertex(DMVertexAttribs *attribs, const MVert *mvert
glVertex3fv(mvert[index].co);
}
+typedef struct {
+ DMVertexAttribs attribs;
+ int numdata;
+
+ GPUAttrib datatypes[GPU_MAX_ATTRIB]; /* TODO, messing up when switching materials many times - [#21056]*/
+} GPUMaterialConv;
+
static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm,
DMSetMaterial setMaterial,
DMSetDrawOptions setDrawOptions,
@@ -865,7 +887,6 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm,
{
CDDerivedMesh *cddm = (CDDerivedMesh *) dm;
GPUVertexAttribs gattribs;
- DMVertexAttribs attribs;
const MVert *mvert = cddm->mvert;
const MFace *mface = cddm->mface;
/* MTFace *tf = dm->getTessFaceDataArray(dm, CD_MTFACE); */ /* UNUSED */
@@ -889,7 +910,7 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm,
if (cddm->pbvh && cddm->pbvh_draw && BKE_pbvh_type(cddm->pbvh) == PBVH_BMESH) {
if (BKE_pbvh_has_faces(cddm->pbvh)) {
setMaterial(1, &gattribs);
- BKE_pbvh_draw(cddm->pbvh, NULL, NULL, NULL, false);
+ BKE_pbvh_draw(cddm->pbvh, NULL, NULL, NULL, false, false);
}
return;
@@ -906,6 +927,7 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm,
if ((GPU_type_matches(GPU_DEVICE_NVIDIA, GPU_OS_MAC, GPU_DRIVER_ANY) && (U.gameflags & USER_DISABLE_VBO)) ||
setDrawOptions != NULL)
{
+ DMVertexAttribs attribs;
DEBUG_VBO("Using legacy code. cdDM_drawMappedFacesGLSL\n");
memset(&attribs, 0, sizeof(attribs));
@@ -914,7 +936,7 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm,
for (a = 0; a < dm->numTessFaceData; a++, mface++) {
const bool smoothnormal = lnors || (mface->flag & ME_SMOOTH);
const short (*ln1)[3] = NULL, (*ln2)[3] = NULL, (*ln3)[3] = NULL, (*ln4)[3] = NULL;
- new_matnr = mface->mat_nr + 1;
+ new_matnr = mface->mat_nr;
if (new_matnr != matnr) {
glEnd();
@@ -977,214 +999,190 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm,
glEnd();
}
else {
+ GPUMaterialConv *matconv;
+ int offset;
+ int totface = dm->getNumTessFaces(dm);
+ int *mat_orig_to_new;
+ int tot_active_mat;
GPUBuffer *buffer = NULL;
- char *varray = NULL;
- int numdata = 0, elementsize = 0, offset;
- int start = 0, numfaces = 0 /* , prevdraw = 0 */ /* UNUSED */, curface = 0;
- int i;
+ char *varray;
+ int max_element_size = 0;
+ int tot_loops = 0;
const MFace *mf = mface;
- GPUAttrib datatypes[GPU_MAX_ATTRIB]; /* TODO, messing up when switching materials many times - [#21056]*/
- memset(&attribs, 0, sizeof(attribs));
GPU_vertex_setup(dm);
GPU_normal_setup(dm);
-
- for (i = 0; i < dm->drawObject->tot_triangle_point / 3; i++) {
-
- a = dm->drawObject->triangle_to_mface[i];
-
- mface = mf + a;
- new_matnr = mface->mat_nr + 1;
-
- if (new_matnr != matnr) {
- numfaces = curface - start;
- if (numfaces > 0) {
-
- if (do_draw) {
-
- if (numdata != 0) {
-
- GPU_buffer_unlock(buffer);
-
- GPU_interleaved_attrib_setup(buffer, datatypes, numdata);
- }
-
- glDrawArrays(GL_TRIANGLES, start * 3, numfaces * 3);
-
- if (numdata != 0) {
-
- GPU_buffer_free(buffer);
-
- buffer = NULL;
- }
-
- }
+ GPU_triangle_setup(dm);
+
+ tot_active_mat = dm->drawObject->totmaterial;
+
+ matconv = MEM_callocN(sizeof(*matconv) * tot_active_mat,
+ "cdDM_drawMappedFacesGLSL.matconv");
+ mat_orig_to_new = MEM_mallocN(sizeof(*mat_orig_to_new) * dm->totmat,
+ "cdDM_drawMappedFacesGLSL.mat_orig_to_new");
+
+ /* part one, check what attributes are needed per material */
+ for (a = 0; a < tot_active_mat; a++) {
+ new_matnr = dm->drawObject->materials[a].mat_nr;
+
+ /* map from original material index to new
+ * GPUBufferMaterial index */
+ mat_orig_to_new[new_matnr] = a;
+ do_draw = setMaterial(new_matnr + 1, &gattribs);
+
+ if (do_draw) {
+ int numdata = 0;
+ DM_vertex_attributes_from_gpu(dm, &gattribs, &matconv[a].attribs);
+
+ if (matconv[a].attribs.totorco && matconv[a].attribs.orco.array) {
+ matconv[a].datatypes[numdata].index = matconv[a].attribs.orco.gl_index;
+ matconv[a].datatypes[numdata].size = 3;
+ matconv[a].datatypes[numdata].type = GL_FLOAT;
+ numdata++;
}
- numdata = 0;
- start = curface;
- /* prevdraw = do_draw; */ /* UNUSED */
- do_draw = setMaterial(matnr = new_matnr, &gattribs);
- if (do_draw) {
- DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
-
- if (attribs.totorco && attribs.orco.array) {
- datatypes[numdata].index = attribs.orco.gl_index;
- datatypes[numdata].size = 3;
- datatypes[numdata].type = GL_FLOAT;
+ for (b = 0; b < matconv[a].attribs.tottface; b++) {
+ if (matconv[a].attribs.tface[b].array) {
+ matconv[a].datatypes[numdata].index = matconv[a].attribs.tface[b].gl_index;
+ matconv[a].datatypes[numdata].size = 2;
+ matconv[a].datatypes[numdata].type = GL_FLOAT;
numdata++;
}
- for (b = 0; b < attribs.tottface; b++) {
- if (attribs.tface[b].array) {
- datatypes[numdata].index = attribs.tface[b].gl_index;
- datatypes[numdata].size = 2;
- datatypes[numdata].type = GL_FLOAT;
- numdata++;
- }
- }
- for (b = 0; b < attribs.totmcol; b++) {
- if (attribs.mcol[b].array) {
- datatypes[numdata].index = attribs.mcol[b].gl_index;
- datatypes[numdata].size = 4;
- datatypes[numdata].type = GL_UNSIGNED_BYTE;
- numdata++;
- }
- }
- if (attribs.tottang && attribs.tang.array) {
- datatypes[numdata].index = attribs.tang.gl_index;
- datatypes[numdata].size = 4;
- datatypes[numdata].type = GL_FLOAT;
- numdata++;
- }
- if (numdata != 0) {
- elementsize = GPU_attrib_element_size(datatypes, numdata);
- buffer = GPU_buffer_alloc(elementsize * dm->drawObject->tot_triangle_point, false);
- if (buffer == NULL) {
- buffer = GPU_buffer_alloc(elementsize * dm->drawObject->tot_triangle_point, true);
- }
- varray = GPU_buffer_lock_stream(buffer);
- if (varray == NULL) {
- GPU_buffer_unbind();
- GPU_buffer_free(buffer);
- fprintf(stderr, "Out of memory, can't draw object\n");
- return;
- }
- }
- else {
- /* if the buffer was set, don't use it again.
- * prevdraw was assumed true but didnt run so set to false - [#21036] */
- /* prevdraw = 0; */ /* UNUSED */
- buffer = NULL;
- }
- }
- }
-
- if (do_draw && numdata != 0) {
- offset = 0;
- if (attribs.totorco && attribs.orco.array) {
- copy_v3_v3((float *)&varray[elementsize * curface * 3], (float *)attribs.orco.array[mface->v1]);
- copy_v3_v3((float *)&varray[elementsize * curface * 3 + elementsize], (float *)attribs.orco.array[mface->v2]);
- copy_v3_v3((float *)&varray[elementsize * curface * 3 + elementsize * 2], (float *)attribs.orco.array[mface->v3]);
- offset += sizeof(float) * 3;
}
- for (b = 0; b < attribs.tottface; b++) {
- if (attribs.tface[b].array) {
- MTFace *tf = &attribs.tface[b].array[a];
- copy_v2_v2((float *)&varray[elementsize * curface * 3 + offset], tf->uv[0]);
- copy_v2_v2((float *)&varray[elementsize * curface * 3 + offset + elementsize], tf->uv[1]);
-
- copy_v2_v2((float *)&varray[elementsize * curface * 3 + offset + elementsize * 2], tf->uv[2]);
- offset += sizeof(float) * 2;
+ for (b = 0; b < matconv[a].attribs.totmcol; b++) {
+ if (matconv[a].attribs.mcol[b].array) {
+ matconv[a].datatypes[numdata].index = matconv[a].attribs.mcol[b].gl_index;
+ matconv[a].datatypes[numdata].size = 4;
+ matconv[a].datatypes[numdata].type = GL_UNSIGNED_BYTE;
+ numdata++;
}
}
- for (b = 0; b < attribs.totmcol; b++) {
- if (attribs.mcol[b].array) {
- MCol *cp = &attribs.mcol[b].array[a * 4 + 0];
- GLubyte col[4];
- col[0] = cp->b; col[1] = cp->g; col[2] = cp->r; col[3] = cp->a;
- copy_v4_v4_char((char *)&varray[elementsize * curface * 3 + offset], (char *)col);
- cp = &attribs.mcol[b].array[a * 4 + 1];
- col[0] = cp->b; col[1] = cp->g; col[2] = cp->r; col[3] = cp->a;
- copy_v4_v4_char((char *)&varray[elementsize * curface * 3 + offset + elementsize], (char *)col);
- cp = &attribs.mcol[b].array[a * 4 + 2];
- col[0] = cp->b; col[1] = cp->g; col[2] = cp->r; col[3] = cp->a;
- copy_v4_v4_char((char *)&varray[elementsize * curface * 3 + offset + elementsize * 2], (char *)col);
- offset += sizeof(unsigned char) * 4;
- }
+ if (matconv[a].attribs.tottang && matconv[a].attribs.tang.array) {
+ matconv[a].datatypes[numdata].index = matconv[a].attribs.tang.gl_index;
+ matconv[a].datatypes[numdata].size = 4;
+ matconv[a].datatypes[numdata].type = GL_FLOAT;
+ numdata++;
}
- if (attribs.tottang && attribs.tang.array) {
- const float *tang = attribs.tang.array[a * 4 + 0];
- copy_v4_v4((float *)&varray[elementsize * curface * 3 + offset], tang);
- tang = attribs.tang.array[a * 4 + 1];
- copy_v4_v4((float *)&varray[elementsize * curface * 3 + offset + elementsize], tang);
- tang = attribs.tang.array[a * 4 + 2];
- copy_v4_v4((float *)&varray[elementsize * curface * 3 + offset + elementsize * 2], tang);
- offset += sizeof(float) * 4;
+ if (numdata != 0) {
+ matconv[a].numdata = numdata;
+ max_element_size = max_ii(GPU_attrib_element_size(matconv[a].datatypes, numdata), max_element_size);
}
- (void)offset;
}
- curface++;
- if (mface->v4) {
- if (do_draw && numdata != 0) {
- offset = 0;
- if (attribs.totorco && attribs.orco.array) {
- copy_v3_v3((float *)&varray[elementsize * curface * 3], (float *)attribs.orco.array[mface->v3]);
- copy_v3_v3((float *)&varray[elementsize * curface * 3 + elementsize], (float *)attribs.orco.array[mface->v4]);
- copy_v3_v3((float *)&varray[elementsize * curface * 3 + elementsize * 2], (float *)attribs.orco.array[mface->v1]);
+ }
+
+ /* part two, generate and fill the arrays with the data */
+ if (max_element_size > 0) {
+ buffer = GPU_buffer_alloc(max_element_size * dm->drawObject->tot_loop_verts, false);
+
+ if (buffer == NULL) {
+ buffer = GPU_buffer_alloc(max_element_size * dm->drawObject->tot_loop_verts, true);
+ }
+ varray = GPU_buffer_lock_stream(buffer);
+ if (varray == NULL) {
+ GPU_buffer_unbind();
+ GPU_buffer_free(buffer);
+ MEM_freeN(mat_orig_to_new);
+ MEM_freeN(matconv);
+ fprintf(stderr, "Out of memory, can't draw object\n");
+ return;
+ }
+
+ mface = mf;
+
+ for (a = 0; a < totface; a++, mface++) {
+ int i = mat_orig_to_new[mface->mat_nr];
+ offset = tot_loops * max_element_size;
+
+ if (matconv[i].numdata != 0) {
+ if (matconv[i].attribs.totorco && matconv[i].attribs.orco.array) {
+ copy_v3_v3((float *)&varray[offset], (float *)matconv[i].attribs.orco.array[mface->v1]);
+ copy_v3_v3((float *)&varray[offset + max_element_size], (float *)matconv[i].attribs.orco.array[mface->v2]);
+ copy_v3_v3((float *)&varray[offset + max_element_size * 2], (float *)matconv[i].attribs.orco.array[mface->v3]);
+ if (mface->v4) {
+ copy_v3_v3((float *)&varray[offset + max_element_size * 3], (float *)matconv[i].attribs.orco.array[mface->v4]);
+ }
offset += sizeof(float) * 3;
}
- for (b = 0; b < attribs.tottface; b++) {
- if (attribs.tface[b].array) {
- MTFace *tf = &attribs.tface[b].array[a];
- copy_v2_v2((float *)&varray[elementsize * curface * 3 + offset], tf->uv[2]);
- copy_v2_v2((float *)&varray[elementsize * curface * 3 + offset + elementsize], tf->uv[3]);
- copy_v2_v2((float *)&varray[elementsize * curface * 3 + offset + elementsize * 2], tf->uv[0]);
+ for (b = 0; b < matconv[i].attribs.tottface; b++) {
+ if (matconv[i].attribs.tface[b].array) {
+ MTFace *tf = &matconv[i].attribs.tface[b].array[a];
+ copy_v2_v2((float *)&varray[offset], tf->uv[0]);
+ copy_v2_v2((float *)&varray[offset + max_element_size], tf->uv[1]);
+ copy_v2_v2((float *)&varray[offset + max_element_size * 2], tf->uv[2]);
+ if (mface->v4) {
+ copy_v2_v2((float *)&varray[offset + max_element_size * 3], tf->uv[3]);
+ }
offset += sizeof(float) * 2;
}
}
- for (b = 0; b < attribs.totmcol; b++) {
- if (attribs.mcol[b].array) {
- MCol *cp = &attribs.mcol[b].array[a * 4 + 2];
+ for (b = 0; b < matconv[i].attribs.totmcol; b++) {
+ if (matconv[i].attribs.mcol[b].array) {
+ MCol *cp = &matconv[i].attribs.mcol[b].array[a * 4 + 0];
GLubyte col[4];
col[0] = cp->b; col[1] = cp->g; col[2] = cp->r; col[3] = cp->a;
- copy_v4_v4_char((char *)&varray[elementsize * curface * 3 + offset], (char *)col);
- cp = &attribs.mcol[b].array[a * 4 + 3];
+ copy_v4_v4_char((char *)&varray[offset], (char *)col);
+ cp = &matconv[i].attribs.mcol[b].array[a * 4 + 1];
col[0] = cp->b; col[1] = cp->g; col[2] = cp->r; col[3] = cp->a;
- copy_v4_v4_char((char *)&varray[elementsize * curface * 3 + offset + elementsize], (char *)col);
- cp = &attribs.mcol[b].array[a * 4 + 0];
+ copy_v4_v4_char((char *)&varray[offset + max_element_size], (char *)col);
+ cp = &matconv[i].attribs.mcol[b].array[a * 4 + 2];
col[0] = cp->b; col[1] = cp->g; col[2] = cp->r; col[3] = cp->a;
- copy_v4_v4_char((char *)&varray[elementsize * curface * 3 + offset + elementsize * 2], (char *)col);
+ copy_v4_v4_char((char *)&varray[offset + max_element_size * 2], (char *)col);
+ if (mface->v4) {
+ cp = &matconv[i].attribs.mcol[b].array[a * 4 + 3];
+ col[0] = cp->b; col[1] = cp->g; col[2] = cp->r; col[3] = cp->a;
+ copy_v4_v4_char((char *)&varray[offset + max_element_size * 3], (char *)col);
+ }
offset += sizeof(unsigned char) * 4;
}
}
- if (attribs.tottang && attribs.tang.array) {
- const float *tang = attribs.tang.array[a * 4 + 2];
- copy_v4_v4((float *)&varray[elementsize * curface * 3 + offset], tang);
- tang = attribs.tang.array[a * 4 + 3];
- copy_v4_v4((float *)&varray[elementsize * curface * 3 + offset + elementsize], tang);
- tang = attribs.tang.array[a * 4 + 0];
- copy_v4_v4((float *)&varray[elementsize * curface * 3 + offset + elementsize * 2], tang);
+ if (matconv[i].attribs.tottang && matconv[i].attribs.tang.array) {
+ const float *tang = matconv[i].attribs.tang.array[a * 4 + 0];
+ copy_v4_v4((float *)&varray[offset], tang);
+ tang = matconv[i].attribs.tang.array[a * 4 + 1];
+ copy_v4_v4((float *)&varray[offset + max_element_size], tang);
+ tang = matconv[i].attribs.tang.array[a * 4 + 2];
+ copy_v4_v4((float *)&varray[offset + max_element_size * 2], tang);
+ if (mface->v4) {
+ tang = matconv[i].attribs.tang.array[a * 4 + 3];
+ copy_v4_v4((float *)&varray[offset + max_element_size * 3], tang);
+ }
offset += sizeof(float) * 4;
}
- (void)offset;
}
- curface++;
- i++;
+
+ if (mface->v4) {
+ tot_loops += 4;
+ }
+ else {
+ tot_loops += 3;
+ }
}
+ GPU_buffer_unlock(buffer);
}
- numfaces = curface - start;
- if (numfaces > 0) {
+
+ for (a = 0; a < tot_active_mat; a++) {
+ new_matnr = dm->drawObject->materials[a].mat_nr;
+
+ do_draw = setMaterial(new_matnr + 1, &gattribs);
+
if (do_draw) {
- if (numdata != 0) {
- GPU_buffer_unlock(buffer);
- GPU_interleaved_attrib_setup(buffer, datatypes, numdata);
+ if (matconv[a].numdata) {
+ GPU_interleaved_attrib_setup(buffer, matconv[a].datatypes, matconv[a].numdata, max_element_size);
+ }
+ GPU_buffer_draw_elements(dm->drawObject->triangles, GL_TRIANGLES,
+ dm->drawObject->materials[a].start, dm->drawObject->materials[a].totelements);
+ if (matconv[a].numdata) {
+ GPU_interleaved_attrib_unbind();
}
- glDrawArrays(GL_TRIANGLES, start * 3, (curface - start) * 3);
}
}
+
GPU_buffer_unbind();
-
- GPU_buffer_free(buffer);
+ if (buffer)
+ GPU_buffer_free(buffer);
+
+ MEM_freeN(mat_orig_to_new);
+ MEM_freeN(matconv);
}
glShadeModel(GL_FLAT);
@@ -1223,7 +1221,7 @@ static void cdDM_drawMappedFacesMat(DerivedMesh *dm,
if (cddm->pbvh && cddm->pbvh_draw && BKE_pbvh_type(cddm->pbvh) == PBVH_BMESH) {
if (BKE_pbvh_has_faces(cddm->pbvh)) {
setMaterial(userData, 1, &gattribs);
- BKE_pbvh_draw(cddm->pbvh, NULL, NULL, NULL, false);
+ BKE_pbvh_draw(cddm->pbvh, NULL, NULL, NULL, false, false);
}
return;
@@ -1326,6 +1324,582 @@ static void cdDM_drawMappedEdges(DerivedMesh *dm, DMSetDrawOptions setDrawOption
glEnd();
}
+static void cdDM_buffer_copy_triangles(DerivedMesh *dm, float *varray_, int *mat_orig_to_new, void *UNUSED(user))
+{
+ GPUBufferMaterial *gpumat;
+ MFace *f;
+ int i, start, totface, findex = 0;
+ unsigned int *varray = (unsigned int *)varray_;
+
+ f = dm->getTessFaceArray(dm);
+
+ totface = dm->getNumTessFaces(dm);
+ for (i = 0; i < totface; i++, f++) {
+ gpumat = dm->drawObject->materials + mat_orig_to_new[f->mat_nr];
+ start = gpumat->counter;
+
+ /* v1 v2 v3 */
+ varray[start++] = findex;
+ varray[start++] = findex + 1;
+ varray[start++] = findex + 2;
+
+ if (f->v4) {
+ /* v3 v4 v1 */
+ varray[start++] = findex + 2;
+ varray[start++] = findex + 3;
+ varray[start++] = findex;
+
+ gpumat->counter += 6;
+ findex += 4;
+ }
+ else {
+ gpumat->counter += 3;
+ findex += 3;
+ }
+ }
+}
+
+static void cdDM_buffer_copy_vertex(DerivedMesh *dm, float *varray, int *UNUSED(mat_orig_to_new), void *UNUSED(user))
+{
+ MVert *mvert;
+ MFace *f;
+ int i, j, start, totface;
+
+ mvert = dm->getVertArray(dm);
+ f = dm->getTessFaceArray(dm);
+
+ start = 0;
+ totface = dm->getNumTessFaces(dm);
+ for (i = 0; i < totface; i++, f++) {
+ /* v1 v2 v3 */
+ copy_v3_v3(&varray[start], mvert[f->v1].co);
+ copy_v3_v3(&varray[start + 3], mvert[f->v2].co);
+ copy_v3_v3(&varray[start + 6], mvert[f->v3].co);
+ start += 9;
+
+ if (f->v4) {
+ /* v4 */
+ copy_v3_v3(&varray[start], mvert[f->v4].co);
+ start += 3;
+ }
+ }
+
+ /* copy loose points */
+ j = dm->drawObject->tot_triangle_point * 3;
+ for (i = 0; i < dm->drawObject->totvert; i++) {
+ if (dm->drawObject->vert_points[i].point_index >= dm->drawObject->tot_triangle_point) {
+ copy_v3_v3(&varray[j], mvert[i].co);
+ j += 3;
+ }
+ }
+}
+
+static void cdDM_buffer_copy_normal(DerivedMesh *dm, float *varray_, int *UNUSED(mat_orig_to_new), void *UNUSED(user))
+{
+ int i, totface;
+ int start;
+ float f_no[3];
+
+ short *varray = (short *)varray_;
+ const float *nors = dm->getTessFaceDataArray(dm, CD_NORMAL);
+ short (*tlnors)[4][3] = dm->getTessFaceDataArray(dm, CD_TESSLOOPNORMAL);
+ MVert *mvert = dm->getVertArray(dm);
+ MFace *f = dm->getTessFaceArray(dm);
+
+ totface = dm->getNumTessFaces(dm);
+ start = 0;
+ for (i = 0; i < totface; i++, f++) {
+ const int smoothnormal = (f->flag & ME_SMOOTH);
+
+ if (tlnors) {
+ short (*tlnor)[3] = tlnors[i];
+ /* Copy loop normals */
+ copy_v3_v3_short(&varray[start], tlnor[0]);
+ copy_v3_v3_short(&varray[start + 3], tlnor[1]);
+ copy_v3_v3_short(&varray[start + 6], tlnor[2]);
+ start += 9;
+
+ if (f->v4) {
+ copy_v3_v3_short(&varray[start], tlnor[3]);
+ start += 3;
+ }
+ }
+ else if (smoothnormal) {
+ /* copy vertex normal */
+ copy_v3_v3_short(&varray[start], mvert[f->v1].no);
+ copy_v3_v3_short(&varray[start + 4], mvert[f->v2].no);
+ copy_v3_v3_short(&varray[start + 8], mvert[f->v3].no);
+ start += 12;
+
+ if (f->v4) {
+ copy_v3_v3_short(&varray[start], mvert[f->v4].no);
+ start += 4;
+ }
+ }
+ else if (nors) {
+ /* copy cached face normal */
+ normal_float_to_short_v3(&varray[start], &nors[i * 3]);
+ normal_float_to_short_v3(&varray[start + 4], &nors[i * 3]);
+ normal_float_to_short_v3(&varray[start + 8], &nors[i * 3]);
+ start += 12;
+
+ if (f->v4) {
+ normal_float_to_short_v3(&varray[start], &nors[i * 3]);
+ start += 4;
+ }
+ }
+ else {
+ /* calculate face normal */
+ if (f->v4)
+ normal_quad_v3(f_no, mvert[f->v1].co, mvert[f->v2].co, mvert[f->v3].co, mvert[f->v4].co);
+ else
+ normal_tri_v3(f_no, mvert[f->v1].co, mvert[f->v2].co, mvert[f->v3].co);
+
+ normal_float_to_short_v3(&varray[start], f_no);
+ normal_float_to_short_v3(&varray[start + 4], f_no);
+ normal_float_to_short_v3(&varray[start + 8], f_no);
+ start += 12;
+
+ if (f->v4) {
+ normal_float_to_short_v3(&varray[start], f_no);
+ start += 4;
+ }
+ }
+ }
+}
+
+static void cdDM_buffer_copy_uv(DerivedMesh *dm, float *varray, int *UNUSED(mat_orig_to_new), void *UNUSED(user))
+{
+ int start;
+ int i, totface;
+
+ MTFace *mtface;
+ MFace *f;
+
+ if (!(mtface = DM_get_tessface_data_layer(dm, CD_MTFACE)))
+ return;
+ f = dm->getTessFaceArray(dm);
+
+ start = 0;
+ totface = dm->getNumTessFaces(dm);
+ for (i = 0; i < totface; i++, f++) {
+ /* v1 v2 v3 */
+ copy_v2_v2(&varray[start], mtface[i].uv[0]);
+ copy_v2_v2(&varray[start + 2], mtface[i].uv[1]);
+ copy_v2_v2(&varray[start + 4], mtface[i].uv[2]);
+ start += 6;
+
+ if (f->v4) {
+ /* v4 */
+ copy_v2_v2(&varray[start], mtface[i].uv[3]);
+ start += 2;
+ }
+ }
+}
+
+
+static void cdDM_buffer_copy_uv_texpaint(DerivedMesh *dm, float *varray, int *UNUSED(mat_orig_to_new), void *UNUSED(user))
+{
+ int start;
+ int i, totface;
+
+ int totmaterial = dm->totmat;
+ MTFace **mtface_base;
+ MTFace *stencil_base;
+ int stencil;
+ MFace *mf;
+
+ /* should have been checked for before, reassert */
+ BLI_assert(DM_get_tessface_data_layer(dm, CD_MTFACE));
+ mf = dm->getTessFaceArray(dm);
+ mtface_base = MEM_mallocN(totmaterial * sizeof(*mtface_base), "texslots");
+
+ for (i = 0; i < totmaterial; i++) {
+ mtface_base[i] = DM_paint_uvlayer_active_get(dm, i);
+ }
+
+ stencil = CustomData_get_stencil_layer(&dm->faceData, CD_MTFACE);
+ stencil_base = CustomData_get_layer_n(&dm->faceData, CD_MTFACE, stencil);
+
+ totface = dm->getNumTessFaces(dm);
+ start = 0;
+
+ for (i = 0; i < totface; i++, mf++) {
+ int mat_i = mf->mat_nr;
+
+ /* v1 v2 v3 */
+ copy_v2_v2(&varray[start], mtface_base[mat_i][i].uv[0]);
+ copy_v2_v2(&varray[start + 2], stencil_base[i].uv[0]);
+ copy_v2_v2(&varray[start + 4], mtface_base[mat_i][i].uv[1]);
+ copy_v2_v2(&varray[start + 6], stencil_base[i].uv[1]);
+ copy_v2_v2(&varray[start + 8], mtface_base[mat_i][i].uv[2]);
+ copy_v2_v2(&varray[start + 10], stencil_base[i].uv[2]);
+ start += 12;
+
+ if (mf->v4) {
+ /* v4 */
+ copy_v2_v2(&varray[start], mtface_base[mat_i][i].uv[3]);
+ copy_v2_v2(&varray[start + 2], stencil_base[i].uv[3]);
+ start += 4;
+ }
+ }
+
+ MEM_freeN(mtface_base);
+}
+
+
+static void copy_mcol_uc3(unsigned char *v, unsigned char *col)
+{
+ v[0] = col[3];
+ v[1] = col[2];
+ v[2] = col[1];
+}
+
+/* treat varray_ as an array of MCol, four MCol's per face */
+static void cdDM_buffer_copy_mcol(DerivedMesh *dm, float *varray_, int *UNUSED(mat_orig_to_new), void *user)
+{
+ int i, totface, start;
+ unsigned char *varray = (unsigned char *)varray_;
+ unsigned char *mcol = (unsigned char *)user;
+ MFace *f = dm->getTessFaceArray(dm);
+
+ totface = dm->getNumTessFaces(dm);
+ start = 0;
+ for (i = 0; i < totface; i++, f++) {
+ /* v1 v2 v3 */
+ copy_mcol_uc3(&varray[start], &mcol[i * 16]);
+ copy_mcol_uc3(&varray[start + 3], &mcol[i * 16 + 4]);
+ copy_mcol_uc3(&varray[start + 6], &mcol[i * 16 + 8]);
+ start += 9;
+
+ if (f->v4) {
+ /* v3 v4 v1 */
+ copy_mcol_uc3(&varray[start], &mcol[i * 16 + 12]);
+ start += 3;
+ }
+ }
+}
+
+static void cdDM_buffer_copy_edge(DerivedMesh *dm, float *varray_, int *UNUSED(mat_orig_to_new), void *UNUSED(user))
+{
+ MEdge *medge, *medge_base;
+ unsigned int *varray = (unsigned int *)varray_;
+ int i, totedge, iloose, inorm, iloosehidden, inormhidden;
+ int tot_loose_hidden = 0, tot_loose = 0;
+ int tot_hidden = 0, tot = 0;
+
+ medge_base = medge = dm->getEdgeArray(dm);
+ totedge = dm->getNumEdges(dm);
+
+ for (i = 0; i < totedge; i++, medge++) {
+ if (medge->flag & ME_EDGEDRAW) {
+ if (medge->flag & ME_LOOSEEDGE) tot_loose++;
+ else tot++;
+ }
+ else {
+ if (medge->flag & ME_LOOSEEDGE) tot_loose_hidden++;
+ else tot_hidden++;
+ }
+ }
+
+ inorm = 0;
+ inormhidden = tot;
+ iloose = tot + tot_hidden;
+ iloosehidden = iloose + tot_loose;
+
+ medge = medge_base;
+ for (i = 0; i < totedge; i++, medge++) {
+ if (medge->flag & ME_EDGEDRAW) {
+ if (medge->flag & ME_LOOSEEDGE) {
+ varray[iloose * 2] = dm->drawObject->vert_points[medge->v1].point_index;
+ varray[iloose * 2 + 1] = dm->drawObject->vert_points[medge->v2].point_index;
+ iloose++;
+ }
+ else {
+ varray[inorm * 2] = dm->drawObject->vert_points[medge->v1].point_index;
+ varray[inorm * 2 + 1] = dm->drawObject->vert_points[medge->v2].point_index;
+ inorm++;
+ }
+ }
+ else {
+ if (medge->flag & ME_LOOSEEDGE) {
+ varray[iloosehidden * 2] = dm->drawObject->vert_points[medge->v1].point_index;
+ varray[iloosehidden * 2 + 1] = dm->drawObject->vert_points[medge->v2].point_index;
+ iloosehidden++;
+ }
+ else {
+ varray[inormhidden * 2] = dm->drawObject->vert_points[medge->v1].point_index;
+ varray[inormhidden * 2 + 1] = dm->drawObject->vert_points[medge->v2].point_index;
+ inormhidden++;
+ }
+ }
+ }
+
+ dm->drawObject->tot_loose_edge_drawn = tot_loose;
+ dm->drawObject->loose_edge_offset = tot + tot_hidden;
+ dm->drawObject->tot_edge_drawn = tot;
+}
+
+static void cdDM_buffer_copy_uvedge(DerivedMesh *dm, float *varray, int *UNUSED(mat_orig_to_new), void *UNUSED(user))
+{
+ MTFace *tf = DM_get_tessface_data_layer(dm, CD_MTFACE);
+ int i, j = 0;
+
+ if (!tf)
+ return;
+
+ for (i = 0; i < dm->numTessFaceData; i++, tf++) {
+ MFace mf;
+ dm->getTessFace(dm, i, &mf);
+
+ copy_v2_v2(&varray[j], tf->uv[0]);
+ copy_v2_v2(&varray[j + 2], tf->uv[1]);
+
+ copy_v2_v2(&varray[j + 4], tf->uv[1]);
+ copy_v2_v2(&varray[j + 6], tf->uv[2]);
+
+ if (!mf.v4) {
+ copy_v2_v2(&varray[j + 8], tf->uv[2]);
+ copy_v2_v2(&varray[j + 10], tf->uv[0]);
+ j += 12;
+ }
+ else {
+ copy_v2_v2(&varray[j + 8], tf->uv[2]);
+ copy_v2_v2(&varray[j + 10], tf->uv[3]);
+
+ copy_v2_v2(&varray[j + 12], tf->uv[3]);
+ copy_v2_v2(&varray[j + 14], tf->uv[0]);
+ j += 16;
+ }
+ }
+}
+
+static void cdDM_copy_gpu_data(DerivedMesh *dm, int type, float *varray,
+ int *mat_orig_to_new, void *user_data)
+{
+ switch(type) {
+ case GPU_BUFFER_VERTEX:
+ cdDM_buffer_copy_vertex(dm, varray, mat_orig_to_new, user_data);
+ break;
+ case GPU_BUFFER_NORMAL:
+ cdDM_buffer_copy_normal(dm, varray, mat_orig_to_new, user_data);
+ break;
+ case GPU_BUFFER_COLOR:
+ cdDM_buffer_copy_mcol(dm, varray, mat_orig_to_new, user_data);
+ break;
+ case GPU_BUFFER_UV:
+ cdDM_buffer_copy_uv(dm, varray, mat_orig_to_new, user_data);
+ break;
+ case GPU_BUFFER_UV_TEXPAINT:
+ cdDM_buffer_copy_uv_texpaint(dm, varray, mat_orig_to_new, user_data);
+ break;
+ case GPU_BUFFER_EDGE:
+ cdDM_buffer_copy_edge(dm, varray, mat_orig_to_new, user_data);
+ break;
+ case GPU_BUFFER_UVEDGE:
+ cdDM_buffer_copy_uvedge(dm, varray, mat_orig_to_new, user_data);
+ break;
+ case GPU_BUFFER_TRIANGLES:
+ cdDM_buffer_copy_triangles(dm, varray, mat_orig_to_new, user_data);
+ break;
+ default:
+ break;
+ }
+}
+
+/* add a new point to the list of points related to a particular
+ * vertex */
+#ifdef USE_GPU_POINT_LINK
+
+static void cdDM_drawobject_add_vert_point(GPUDrawObject *gdo, int vert_index, int point_index)
+{
+ GPUVertPointLink *lnk;
+
+ lnk = &gdo->vert_points[vert_index];
+
+ /* if first link is in use, add a new link at the end */
+ if (lnk->point_index != -1) {
+ /* get last link */
+ for (; lnk->next; lnk = lnk->next) ;
+
+ /* add a new link from the pool */
+ lnk = lnk->next = &gdo->vert_points_mem[gdo->vert_points_usage];
+ gdo->vert_points_usage++;
+ }
+
+ lnk->point_index = point_index;
+}
+
+#else
+
+static void cdDM_drawobject_add_vert_point(GPUDrawObject *gdo, int vert_index, int point_index)
+{
+ GPUVertPointLink *lnk;
+ lnk = &gdo->vert_points[vert_index];
+ if (lnk->point_index == -1) {
+ lnk->point_index = point_index;
+ }
+}
+
+#endif /* USE_GPU_POINT_LINK */
+
+static int tri_indices[2][3] = {{0, 1, 2}, {2, 3, 0}};
+
+/* update the vert_points and triangle_to_mface fields with a new
+ * triangle */
+static void cdDM_drawobject_add_triangle(GPUDrawObject *gdo,
+ int v1, int v2, int v3, bool quad, int loopindex)
+{
+ int i, v[3] = {v1, v2, v3};
+ int *tri_i = quad ? tri_indices[1] : tri_indices[0];
+ for (i = 0; i < 3; i++)
+ cdDM_drawobject_add_vert_point(gdo, v[i], loopindex + tri_i[i]);
+}
+
+/* for each vertex, build a list of points related to it; these lists
+ * are stored in an array sized to the number of vertices */
+static void cdDM_drawobject_init_vert_points(GPUDrawObject *gdo, MFace *f, int totface, int totmat)
+{
+ GPUBufferMaterial *mat;
+ int i, *mat_orig_to_new;
+ int tot_loops = 0;
+
+ mat_orig_to_new = MEM_callocN(sizeof(*mat_orig_to_new) * totmat,
+ "GPUDrawObject.mat_orig_to_new");
+ /* allocate the array and space for links */
+ gdo->vert_points = MEM_mallocN(sizeof(GPUVertPointLink) * gdo->totvert,
+ "GPUDrawObject.vert_points");
+#ifdef USE_GPU_POINT_LINK
+ gdo->vert_points_mem = MEM_callocN(sizeof(GPUVertPointLink) * gdo->tot_triangle_point,
+ "GPUDrawObject.vert_points_mem");
+ gdo->vert_points_usage = 0;
+#endif
+
+ /* build a map from the original material indices to the new
+ * GPUBufferMaterial indices */
+ for (i = 0; i < gdo->totmaterial; i++) {
+ mat_orig_to_new[gdo->materials[i].mat_nr] = i;
+ gdo->materials[i].counter = 0;
+ }
+
+ /* -1 indicates the link is not yet used */
+ for (i = 0; i < gdo->totvert; i++) {
+#ifdef USE_GPU_POINT_LINK
+ gdo->vert_points[i].link = NULL;
+#endif
+ gdo->vert_points[i].point_index = -1;
+ }
+
+ for (i = 0; i < totface; i++, f++) {
+ mat = &gdo->materials[mat_orig_to_new[f->mat_nr]];
+
+ mat->polys[mat->counter++] = i;
+
+ /* add triangle */
+ cdDM_drawobject_add_triangle(gdo, f->v1, f->v2, f->v3, false, tot_loops);
+ mat->totelements += 3;
+
+ /* add second triangle for quads */
+ if (f->v4) {
+ cdDM_drawobject_add_triangle(gdo, f->v3, f->v4, f->v1, true, tot_loops);
+ mat->totelements += 3;
+ tot_loops += 4;
+ }
+ else {
+ tot_loops += 3;
+ }
+ }
+
+ /* map any unused vertices to loose points */
+ for (i = 0; i < gdo->totvert; i++) {
+ if (gdo->vert_points[i].point_index == -1) {
+ gdo->vert_points[i].point_index = gdo->tot_triangle_point + gdo->tot_loose_point;
+ gdo->tot_loose_point++;
+ }
+ }
+
+ MEM_freeN(mat_orig_to_new);
+}
+
+typedef struct {
+ int elements;
+ int loops;
+ int polys;
+} GPUMaterialInfo;
+
+/* see GPUDrawObject's structure definition for a description of the
+ * data being initialized here */
+static GPUDrawObject *cdDM_GPUobject_new(DerivedMesh *dm)
+{
+ GPUDrawObject *gdo;
+ MFace *mface;
+ int totmat = dm->totmat;
+ GPUMaterialInfo *mat_info;
+ int i, curmat, totelements, totface, totloops;
+
+ /* object contains at least one material (default included) so zero means uninitialized dm */
+ BLI_assert(totmat != 0);
+
+ mface = dm->getTessFaceArray(dm);
+ totface = dm->getNumTessFaces(dm);
+
+ /* get the number of points used by each material, treating
+ * each quad as two triangles */
+ mat_info = MEM_callocN(sizeof(*mat_info) * totmat, "GPU_drawobject_new.mat_orig_to_new");
+ for (i = 0; i < totface; i++) {
+ mat_info[mface[i].mat_nr].polys++;
+ if (mface[i].v4) {
+ mat_info[mface[i].mat_nr].elements += 6;
+ mat_info[mface[i].mat_nr].loops += 4;
+ }
+ else {
+ mat_info[mface[i].mat_nr].elements += 3;
+ mat_info[mface[i].mat_nr].loops += 3;
+ }
+ }
+ /* create the GPUDrawObject */
+ gdo = MEM_callocN(sizeof(GPUDrawObject), "GPUDrawObject");
+ gdo->totvert = dm->getNumVerts(dm);
+ gdo->totedge = dm->getNumEdges(dm);
+
+ /* count the number of materials used by this DerivedMesh */
+ for (i = 0; i < totmat; i++) {
+ if (mat_info[i].elements > 0)
+ gdo->totmaterial++;
+ }
+
+ /* allocate an array of materials used by this DerivedMesh */
+ gdo->materials = MEM_mallocN(sizeof(GPUBufferMaterial) * gdo->totmaterial,
+ "GPUDrawObject.materials");
+
+ /* initialize the materials array */
+ for (i = 0, curmat = 0, totelements = 0, totloops = 0; i < totmat; i++) {
+ if (mat_info[i].elements > 0) {
+ gdo->materials[curmat].start = totelements;
+ /* can set it to points now but used in cdDM_drawobject_init_vert_points as counter */
+ gdo->materials[curmat].totelements = 0;
+ gdo->materials[curmat].totloops = mat_info[i].loops;
+ gdo->materials[curmat].mat_nr = i;
+ gdo->materials[curmat].totpolys = mat_info[i].polys;
+ gdo->materials[curmat].polys = MEM_mallocN(sizeof(int) * mat_info[i].polys, "GPUBufferMaterial.polys");
+
+ totelements += mat_info[i].elements;
+ totloops += mat_info[i].loops;
+ curmat++;
+ }
+ }
+
+ gdo->tot_loop_verts = totloops;
+
+ /* store total number of points used for triangles */
+ gdo->tot_triangle_point = totelements;
+
+ cdDM_drawobject_init_vert_points(gdo, mface, totface, totmat);
+ MEM_freeN(mat_info);
+
+ return gdo;
+}
+
static void cdDM_foreachMappedVert(
DerivedMesh *dm,
void (*func)(void *userData, int index, const float co[3], const float no_f[3], const short no_s[3]),
@@ -1541,6 +2115,9 @@ static CDDerivedMesh *cdDM_create(const char *desc)
dm->drawMappedFacesGLSL = cdDM_drawMappedFacesGLSL;
dm->drawMappedFacesMat = cdDM_drawMappedFacesMat;
+ dm->copy_gpu_data = cdDM_copy_gpu_data;
+ dm->gpuObjectNew = cdDM_GPUobject_new;
+
dm->foreachMappedVert = cdDM_foreachMappedVert;
dm->foreachMappedEdge = cdDM_foreachMappedEdge;
dm->foreachMappedLoop = cdDM_foreachMappedLoop;
diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c
index 361557633cb..e5e36b24a46 100644
--- a/source/blender/blenkernel/intern/pbvh.c
+++ b/source/blender/blenkernel/intern/pbvh.c
@@ -1679,6 +1679,7 @@ void BKE_pbvh_raycast_project_ray_root(
typedef struct {
DMSetMaterial setMaterial;
bool wireframe;
+ bool fast;
} PBVHNodeDrawData;
void BKE_pbvh_node_draw(PBVHNode *node, void *data_v)
@@ -1705,7 +1706,8 @@ void BKE_pbvh_node_draw(PBVHNode *node, void *data_v)
if (!(node->flag & PBVH_FullyHidden)) {
GPU_draw_pbvh_buffers(node->draw_buffers,
data->setMaterial,
- data->wireframe);
+ data->wireframe,
+ data->fast);
}
}
@@ -1775,9 +1777,9 @@ static void pbvh_node_check_diffuse_changed(PBVH *bvh, PBVHNode *node)
}
void BKE_pbvh_draw(PBVH *bvh, float (*planes)[4], float (*face_nors)[3],
- DMSetMaterial setMaterial, bool wireframe)
+ DMSetMaterial setMaterial, bool wireframe, bool fast)
{
- PBVHNodeDrawData draw_data = {setMaterial, wireframe};
+ PBVHNodeDrawData draw_data = {setMaterial, wireframe, fast};
PBVHNode **nodes;
int a, totnode;
diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c
index cc680224c31..733cb15ea86 100644
--- a/source/blender/blenkernel/intern/subsurf_ccg.c
+++ b/source/blender/blenkernel/intern/subsurf_ccg.c
@@ -72,6 +72,7 @@
#include "GPU_draw.h"
#include "GPU_extensions.h"
#include "GPU_glew.h"
+#include "GPU_buffers.h"
#include "CCGSubSurf.h"
@@ -1734,12 +1735,25 @@ static void ccgDM_drawLooseEdges(DerivedMesh *dm)
}
}
+static void ccgDM_NormalFast(float *a, float *b, float *c, float *d, float no[3])
+{
+ float a_cX = c[0] - a[0], a_cY = c[1] - a[1], a_cZ = c[2] - a[2];
+ float b_dX = d[0] - b[0], b_dY = d[1] - b[1], b_dZ = d[2] - b[2];
+
+ no[0] = b_dY * a_cZ - b_dZ * a_cY;
+ no[1] = b_dZ * a_cX - b_dX * a_cZ;
+ no[2] = b_dX * a_cY - b_dY * a_cX;
+
+ normalize_v3(no);
+}
+
+
static void ccgDM_glNormalFast(float *a, float *b, float *c, float *d)
{
float a_cX = c[0] - a[0], a_cY = c[1] - a[1], a_cZ = c[2] - a[2];
float b_dX = d[0] - b[0], b_dY = d[1] - b[1], b_dZ = d[2] - b[2];
float no[3];
-
+
no[0] = b_dY * a_cZ - b_dZ * a_cY;
no[1] = b_dZ * a_cX - b_dX * a_cZ;
no[2] = b_dX * a_cY - b_dY * a_cX;
@@ -1749,46 +1763,35 @@ static void ccgDM_glNormalFast(float *a, float *b, float *c, float *d)
}
/* Only used by non-editmesh types */
-static void ccgDM_drawFacesSolid(DerivedMesh *dm, float (*partial_redraw_planes)[4], bool fast, DMSetMaterial setMaterial)
+static void ccgDM_buffer_copy_normal(DerivedMesh *dm, float *varray_,
+ int *UNUSED(mat_orig_to_new), void *UNUSED(user_data))
{
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
CCGSubSurf *ss = ccgdm->ss;
CCGKey key;
+ short *varray = (short *)varray_;
short (*lnors)[4][3] = dm->getTessFaceDataArray(dm, CD_TESSLOOPNORMAL);
int gridSize = ccgSubSurf_getGridSize(ss);
int gridFaces = gridSize - 1;
DMFlagMat *faceFlags = ccgdm->faceFlags;
- int step = (fast) ? gridSize - 1 : 1;
int i, totface = ccgSubSurf_getNumFaces(ss);
- int drawcurrent = 0, matnr = -1, shademodel = -1;
+ int shademodel;
+ int start = 0;
CCG_key_top_level(&key, ss);
ccgdm_pbvh_update(ccgdm);
- if (ccgdm->pbvh && ccgdm->multires.mmd && !fast) {
- if (BKE_pbvh_has_faces(ccgdm->pbvh)) {
- BKE_pbvh_draw(ccgdm->pbvh, partial_redraw_planes, NULL,
- setMaterial, false);
- glShadeModel(GL_FLAT);
- }
-
- return;
- }
-
for (i = 0; i < totface; i++) {
CCGFace *f = ccgdm->faceMap[i].face;
int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
int index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f));
- int new_matnr, new_shademodel;
short (*ln)[4][3] = NULL;
if (faceFlags) {
- new_shademodel = (lnors || (faceFlags[index].flag & ME_SMOOTH)) ? GL_SMOOTH : GL_FLAT;
- new_matnr = faceFlags[index].mat_nr;
+ shademodel = (lnors || (faceFlags[index].flag & ME_SMOOTH)) ? GL_SMOOTH : GL_FLAT;
}
else {
- new_shademodel = GL_SMOOTH;
- new_matnr = 0;
+ shademodel = GL_SMOOTH;
}
if (lnors) {
@@ -1796,86 +1799,469 @@ static void ccgDM_drawFacesSolid(DerivedMesh *dm, float (*partial_redraw_planes)
lnors += gridFaces * gridFaces * numVerts;
}
- if (shademodel != new_shademodel || matnr != new_matnr) {
- matnr = new_matnr;
- shademodel = new_shademodel;
-
- if (setMaterial)
- drawcurrent = setMaterial(matnr + 1, NULL);
- else
- drawcurrent = 1;
-
- glShadeModel(shademodel);
- }
-
- if (!drawcurrent)
- continue;
-
for (S = 0; S < numVerts; S++) {
CCGElem *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
if (ln) {
/* Can't use quad strips here... */
- glBegin(GL_QUADS);
- for (y = 0; y < gridFaces; y += step) {
- for (x = 0; x < gridFaces; x += step) {
- float *a = CCG_grid_elem_co(&key, faceGridData, x, y + 0);
- float *b = CCG_grid_elem_co(&key, faceGridData, x + step, y + 0);
- float *c = CCG_grid_elem_co(&key, faceGridData, x + step, y + step);
- float *d = CCG_grid_elem_co(&key, faceGridData, x, y + step);
-
- glNormal3sv(ln[0][1]);
- glVertex3fv(d);
- glNormal3sv(ln[0][2]);
- glVertex3fv(c);
- glNormal3sv(ln[0][3]);
- glVertex3fv(b);
- glNormal3sv(ln[0][0]);
- glVertex3fv(a);
- ln += step;
+ for (y = 0; y < gridFaces; y ++) {
+ for (x = 0; x < gridFaces; x ++) {
+ copy_v3_v3_short(&varray[start], ln[0][0]);
+ copy_v3_v3_short(&varray[start + 4], ln[0][3]);
+ copy_v3_v3_short(&varray[start + 8], ln[0][2]);
+ copy_v3_v3_short(&varray[start + 12], ln[0][1]);
+
+ start += 16;
+ ln ++;
}
}
- glEnd();
}
else if (shademodel == GL_SMOOTH) {
- for (y = 0; y < gridFaces; y += step) {
- glBegin(GL_QUAD_STRIP);
- for (x = 0; x < gridSize; x += step) {
- CCGElem *a = CCG_grid_elem(&key, faceGridData, x, y + 0);
- CCGElem *b = CCG_grid_elem(&key, faceGridData, x, y + step);
-
- glNormal3fv(CCG_elem_no(&key, a));
- glVertex3fv(CCG_elem_co(&key, a));
- glNormal3fv(CCG_elem_no(&key, b));
- glVertex3fv(CCG_elem_co(&key, b));
+ for (y = 0; y < gridFaces; y ++) {
+ for (x = 0; x < gridFaces; x ++) {
+ float *a = CCG_grid_elem_no(&key, faceGridData, x, y );
+ float *b = CCG_grid_elem_no(&key, faceGridData, x + 1, y);
+ float *c = CCG_grid_elem_no(&key, faceGridData, x + 1, y + 1);
+ float *d = CCG_grid_elem_no(&key, faceGridData, x, y + 1);
+
+ normal_float_to_short_v3(&varray[start], a);
+ normal_float_to_short_v3(&varray[start + 4], b);
+ normal_float_to_short_v3(&varray[start + 8], c);
+ normal_float_to_short_v3(&varray[start + 12], d);
+
+ start += 16;
}
- glEnd();
}
}
else {
- glBegin(GL_QUADS);
- for (y = 0; y < gridFaces; y += step) {
- for (x = 0; x < gridFaces; x += step) {
- float *a = CCG_grid_elem_co(&key, faceGridData, x, y + 0);
- float *b = CCG_grid_elem_co(&key, faceGridData, x + step, y + 0);
- float *c = CCG_grid_elem_co(&key, faceGridData, x + step, y + step);
- float *d = CCG_grid_elem_co(&key, faceGridData, x, y + step);
-
- ccgDM_glNormalFast(a, b, c, d);
-
- glVertex3fv(d);
- glVertex3fv(c);
- glVertex3fv(b);
- glVertex3fv(a);
+ for (y = 0; y < gridFaces; y ++) {
+ for (x = 0; x < gridFaces; x ++) {
+ float no[3];
+ float *a = CCG_grid_elem_co(&key, faceGridData, x, y );
+ float *b = CCG_grid_elem_co(&key, faceGridData, x + 1, y );
+ float *c = CCG_grid_elem_co(&key, faceGridData, x + 1, y + 1);
+ float *d = CCG_grid_elem_co(&key, faceGridData, x, y + 1);
+
+ ccgDM_NormalFast(a, b, c, d, no);
+
+ normal_float_to_short_v3(&varray[start], no);
+ normal_float_to_short_v3(&varray[start + 4], no);
+ normal_float_to_short_v3(&varray[start + 8], no);
+ normal_float_to_short_v3(&varray[start + 12], no);
+
+ start += 16;
}
}
- glEnd();
}
}
}
}
/* Only used by non-editmesh types */
+static void ccgDM_buffer_copy_triangles(DerivedMesh *dm, float *varray_,
+ int *mat_orig_to_new, void *UNUSED(user_data))
+{
+ GPUBufferMaterial *gpumat;
+ CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
+ CCGSubSurf *ss = ccgdm->ss;
+ CCGKey key;
+ unsigned int *varray = (unsigned int *)varray_;
+ int gridSize = ccgSubSurf_getGridSize(ss);
+ int gridFaces = gridSize - 1;
+ DMFlagMat *faceFlags = ccgdm->faceFlags;
+ int i, totface = ccgSubSurf_getNumFaces(ss);
+ int matnr = -1, start;
+ int totloops = 0;
+
+ CCG_key_top_level(&key, ss);
+
+ for (i = 0; i < totface; i++) {
+ CCGFace *f = ccgdm->faceMap[i].face;
+ int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
+ int index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f));
+
+ if (faceFlags) {
+ matnr = faceFlags[index].mat_nr;
+ }
+ else {
+ matnr = 0;
+ }
+
+ for (S = 0; S < numVerts; S++) {
+ for (y = 0; y < gridFaces; y++) {
+ for (x = 0; x < gridFaces; x++) {
+ gpumat = dm->drawObject->materials + mat_orig_to_new[matnr];
+ start = gpumat->counter;
+
+ varray[start] = totloops + 3;
+ varray[start + 1] = totloops + 2;
+ varray[start + 2] = totloops + 1;
+
+ varray[start + 3] = totloops + 3;
+ varray[start + 4] = totloops + 1;
+ varray[start + 5] = totloops;
+
+ gpumat->counter += 6;
+ totloops += 4;
+ }
+ }
+ }
+ }
+}
+
+
+/* Only used by non-editmesh types */
+static void ccgDM_buffer_copy_vertex(DerivedMesh *dm, float *varray,
+ int *UNUSED(mat_orig_to_new), void *UNUSED(user_data))
+{
+ CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
+ CCGSubSurf *ss = ccgdm->ss;
+ CCGKey key;
+ int gridSize = ccgSubSurf_getGridSize(ss);
+ int gridFaces = gridSize - 1;
+ int i, totface = ccgSubSurf_getNumFaces(ss);
+ int start = 0;
+
+ CCG_key_top_level(&key, ss);
+ ccgdm_pbvh_update(ccgdm);
+
+ for (i = 0; i < totface; i++) {
+ CCGFace *f = ccgdm->faceMap[i].face;
+ int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
+
+ for (S = 0; S < numVerts; S++) {
+ CCGElem *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
+ for (y = 0; y < gridFaces; y++) {
+ for (x = 0; x < gridFaces; x++) {
+ float *a = CCG_grid_elem_co(&key, faceGridData, x, y);
+ float *b = CCG_grid_elem_co(&key, faceGridData, x + 1, y);
+ float *c = CCG_grid_elem_co(&key, faceGridData, x + 1, y + 1);
+ float *d = CCG_grid_elem_co(&key, faceGridData, x, y + 1);
+
+ copy_v3_v3(&varray[start], a);
+ copy_v3_v3(&varray[start + 3], b);
+ copy_v3_v3(&varray[start + 6], c);
+ copy_v3_v3(&varray[start + 9], d);
+
+ start += 12;
+ }
+ }
+ }
+ }
+}
+
+static void copy_mcol_uc3(unsigned char *v, unsigned char *col)
+{
+ v[0] = col[3];
+ v[1] = col[2];
+ v[2] = col[1];
+}
+
+/* Only used by non-editmesh types */
+static void ccgDM_buffer_copy_color(DerivedMesh *dm, float *varray_,
+ int *UNUSED(mat_orig_to_new), void *user_data)
+{
+ CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
+ CCGSubSurf *ss = ccgdm->ss;
+ CCGKey key;
+ unsigned char *varray = (unsigned char *)varray_;
+ unsigned char *mcol = (unsigned char *)user_data;
+ int gridSize = ccgSubSurf_getGridSize(ss);
+ int gridFaces = gridSize - 1;
+ int i, totface = ccgSubSurf_getNumFaces(ss);
+ int start = 0;
+ int iface = 0;
+
+ CCG_key_top_level(&key, ss);
+
+
+ for (i = 0; i < totface; i++) {
+ CCGFace *f = ccgdm->faceMap[i].face;
+ int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
+
+ for (S = 0; S < numVerts; S++) {
+ for (y = 0; y < gridFaces; y++) {
+ for (x = 0; x < gridFaces; x++) {
+ copy_mcol_uc3(&varray[start], &mcol[iface * 16]);
+ copy_mcol_uc3(&varray[start + 3], &mcol[iface * 16 + 12]);
+ copy_mcol_uc3(&varray[start + 6], &mcol[iface * 16 + 8]);
+ copy_mcol_uc3(&varray[start + 9], &mcol[iface * 16 + 4]);
+
+ start += 12;
+ iface++;
+ }
+ }
+ }
+ }
+}
+
+static void ccgDM_buffer_copy_uv(DerivedMesh *dm, float *varray,
+ int *UNUSED(mat_orig_to_new), void *UNUSED(user_data))
+{
+ CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
+ CCGSubSurf *ss = ccgdm->ss;
+ CCGKey key;
+ MTFace *tf = DM_get_tessface_data_layer(dm, CD_MTFACE);
+ int gridSize = ccgSubSurf_getGridSize(ss);
+ int gridFaces = gridSize - 1;
+ int i, totface = ccgSubSurf_getNumFaces(ss);
+ int start = 0;
+
+ CCG_key_top_level(&key, ss);
+
+ for (i = 0; i < totface; i++) {
+ CCGFace *f = ccgdm->faceMap[i].face;
+ int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
+
+ for (S = 0; S < numVerts; S++) {
+ for (y = 0; y < gridFaces; y++) {
+ for (x = 0; x < gridFaces; x++) {
+ copy_v2_v2(&varray[start], tf->uv[0]);
+ copy_v2_v2(&varray[start + 2], tf->uv[3]);
+ copy_v2_v2(&varray[start + 4], tf->uv[2]);
+ copy_v2_v2(&varray[start + 6], tf->uv[1]);
+
+ tf++;
+ start += 8;
+ }
+ }
+ }
+ }
+}
+
+static void ccgDM_buffer_copy_uv_texpaint(DerivedMesh *dm, float *varray, int *UNUSED(mat_orig_to_new), void *UNUSED(user))
+{
+ CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
+ CCGSubSurf *ss = ccgdm->ss;
+ CCGKey key;
+ int gridSize = ccgSubSurf_getGridSize(ss);
+ int gridFaces = gridSize - 1;
+ int i, totface = ccgSubSurf_getNumFaces(ss);
+ int start = 0;
+ DMFlagMat *faceFlags = ccgdm->faceFlags;
+ int totmaterial = dm->totmat;
+ MTFace **mtface_base;
+ MTFace *stencil_base;
+ int stencil;
+
+ CCG_key_top_level(&key, ss);
+
+ /* should have been checked for before, reassert */
+ BLI_assert(DM_get_tessface_data_layer(dm, CD_MTFACE));
+ mtface_base = MEM_mallocN(totmaterial * sizeof(*mtface_base), "texslots");
+
+ for (i = 0; i < totmaterial; i++) {
+ mtface_base[i] = DM_paint_uvlayer_active_get(dm, i);
+ }
+
+ stencil = CustomData_get_stencil_layer(&dm->faceData, CD_MTFACE);
+ stencil_base = CustomData_get_layer_n(&dm->faceData, CD_MTFACE, stencil);
+
+ start = 0;
+
+ for (i = 0; i < totface; i++) {
+ CCGFace *f = ccgdm->faceMap[i].face;
+ int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
+ int index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f));
+ int matnr;
+
+ if (faceFlags) {
+ matnr = faceFlags[index].mat_nr;
+ }
+ else {
+ matnr = 0;
+ }
+
+ for (S = 0; S < numVerts; S++) {
+ for (y = 0; y < gridFaces; y++) {
+ for (x = 0; x < gridFaces; x++) {
+ /* divide by 16, gives us current tface */
+ unsigned int i_tf = start / 16;
+ copy_v2_v2(&varray[start], mtface_base[matnr][i_tf].uv[0]);
+ copy_v2_v2(&varray[start + 2], stencil_base[i_tf].uv[0]);
+ copy_v2_v2(&varray[start + 4], mtface_base[matnr][i_tf].uv[3]);
+ copy_v2_v2(&varray[start + 6], stencil_base[i_tf].uv[3]);
+ copy_v2_v2(&varray[start + 8], mtface_base[matnr][i_tf].uv[2]);
+ copy_v2_v2(&varray[start + 10], stencil_base[i_tf].uv[2]);
+ copy_v2_v2(&varray[start + 12], mtface_base[matnr][i_tf].uv[1]);
+ copy_v2_v2(&varray[start + 14], stencil_base[i_tf].uv[1]);
+ start += 16;
+ }
+ }
+ }
+ }
+
+ MEM_freeN(mtface_base);
+}
+
+static void ccgDM_copy_gpu_data(DerivedMesh *dm, int type, float *varray,
+ int *mat_orig_to_new, void *user_data)
+{
+ switch(type) {
+ case GPU_BUFFER_VERTEX:
+ ccgDM_buffer_copy_vertex(dm, varray, mat_orig_to_new, NULL);
+ break;
+ case GPU_BUFFER_NORMAL:
+ ccgDM_buffer_copy_normal(dm, varray, mat_orig_to_new, NULL);
+ break;
+ case GPU_BUFFER_UV:
+ ccgDM_buffer_copy_uv(dm, varray, mat_orig_to_new, NULL);
+ break;
+ case GPU_BUFFER_UV_TEXPAINT:
+ ccgDM_buffer_copy_uv_texpaint(dm, varray, mat_orig_to_new, NULL);
+ break;
+ case GPU_BUFFER_COLOR:
+ ccgDM_buffer_copy_color(dm, varray, mat_orig_to_new, user_data);
+ break;
+ case GPU_BUFFER_TRIANGLES:
+ ccgDM_buffer_copy_triangles(dm, varray, mat_orig_to_new, NULL);
+ break;
+ default:
+ break;
+ }
+}
+
+typedef struct {
+ int elements;
+ int loops;
+ int polys;
+} GPUMaterialInfo;
+
+static GPUDrawObject *ccgDM_GPUObjectNew(DerivedMesh *dm) {
+ GPUBufferMaterial *mat;
+ int *mat_orig_to_new;
+ CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
+ CCGSubSurf *ss = ccgdm->ss;
+ GPUDrawObject *gdo;
+ DMFlagMat *faceFlags = ccgdm->faceFlags;
+ int gridSize = ccgSubSurf_getGridSize(ss);
+ int gridFaces = gridSize - 1;
+ int totmat = (faceFlags) ? dm->totmat : 1;
+ GPUMaterialInfo *matinfo;
+ int i, curmat, curelement, totface;
+
+ /* object contains at least one material (default included) so zero means uninitialized dm */
+ BLI_assert(totmat != 0);
+
+ totface = ccgSubSurf_getNumFaces(ss);
+
+ matinfo = MEM_callocN(sizeof(*matinfo) * totmat, "GPU_drawobject_new.mat_orig_to_new");
+
+ if (faceFlags) {
+ for (i = 0; i < totface; i++) {
+ CCGFace *f = ccgdm->faceMap[i].face;
+ int numVerts = ccgSubSurf_getFaceNumVerts(f);
+ int index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f));
+ int new_matnr = faceFlags[index].mat_nr;
+ matinfo[new_matnr].elements += numVerts * gridFaces * gridFaces * 6;
+ matinfo[new_matnr].loops += numVerts * gridFaces * gridFaces * 4;
+ matinfo[new_matnr].polys++;
+ }
+ }
+ else {
+ for (i = 0; i < totface; i++) {
+ matinfo[0].elements += gridFaces * gridFaces * 6;
+ matinfo[0].loops += gridFaces * gridFaces * 4;
+ matinfo[0].polys++;
+ }
+ }
+
+ /* create the GPUDrawObject */
+ gdo = MEM_callocN(sizeof(GPUDrawObject), "GPUDrawObject");
+ gdo->totvert = ccgSubSurf_getNumFinalFaces(ss) * 6;
+ gdo->totedge = ccgSubSurf_getNumFinalEdges(ss) * 2;
+
+ /* count the number of materials used by this DerivedMesh */
+ for (i = 0; i < totmat; i++) {
+ if (matinfo[i].elements > 0)
+ gdo->totmaterial++;
+ }
+
+ /* allocate an array of materials used by this DerivedMesh */
+ gdo->materials = MEM_mallocN(sizeof(GPUBufferMaterial) * gdo->totmaterial,
+ "GPUDrawObject.materials");
+
+ /* initialize the materials array */
+ for (i = 0, curmat = 0, curelement = 0; i < totmat; i++) {
+ if (matinfo[i].elements > 0) {
+ gdo->materials[curmat].start = curelement;
+ gdo->materials[curmat].totelements = matinfo[i].elements;
+ gdo->materials[curmat].totloops = matinfo[i].loops;
+ gdo->materials[curmat].mat_nr = i;
+ gdo->materials[curmat].totpolys = matinfo[i].polys;
+ gdo->materials[curmat].polys = MEM_mallocN(sizeof(int) * matinfo[0].polys, "GPUBufferMaterial.polys");
+
+ curelement += matinfo[i].elements;
+ curmat++;
+ }
+ }
+
+ /* store total number of points used for triangles */
+ gdo->tot_triangle_point = curelement;
+
+ mat_orig_to_new = MEM_callocN(sizeof(*mat_orig_to_new) * totmat,
+ "GPUDrawObject.mat_orig_to_new");
+
+ /* build a map from the original material indices to the new
+ * GPUBufferMaterial indices */
+ for (i = 0; i < gdo->totmaterial; i++) {
+ mat_orig_to_new[gdo->materials[i].mat_nr] = i;
+ gdo->materials[i].counter = 0;
+ }
+
+ if (faceFlags) {
+ for (i = 0; i < totface; i++) {
+ CCGFace *f = ccgdm->faceMap[i].face;
+ int index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f));
+ int new_matnr = faceFlags[index].mat_nr;
+
+ mat = &gdo->materials[mat_orig_to_new[new_matnr]];
+ mat->polys[mat->counter++] = i;
+ }
+ }
+ else {
+ mat = &gdo->materials[0];
+ for (i = 0; i < totface; i++)
+ mat->polys[mat->counter++] = i;
+ }
+
+
+ MEM_freeN(mat_orig_to_new);
+ MEM_freeN(matinfo);
+
+ return gdo;
+}
+
+/* Only used by non-editmesh types */
+static void ccgDM_drawFacesSolid(DerivedMesh *dm, float (*partial_redraw_planes)[4], bool fast, DMSetMaterial setMaterial)
+{
+ int a;
+ CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
+
+ if (ccgdm->pbvh && ccgdm->multires.mmd) {
+ if (BKE_pbvh_has_faces(ccgdm->pbvh)) {
+ BKE_pbvh_draw(ccgdm->pbvh, partial_redraw_planes, NULL,
+ setMaterial, false, fast);
+ glShadeModel(GL_FLAT);
+ }
+
+ return;
+ }
+
+ GPU_vertex_setup(dm);
+ GPU_normal_setup(dm);
+ GPU_triangle_setup(dm);
+ glShadeModel(GL_SMOOTH);
+ for (a = 0; a < dm->drawObject->totmaterial; a++) {
+ if (!setMaterial || setMaterial(dm->drawObject->materials[a].mat_nr + 1, NULL)) {
+ GPU_buffer_draw_elements(dm->drawObject->triangles, GL_TRIANGLES, dm->drawObject->materials[a].start,
+ dm->drawObject->materials[a].totelements);
+ }
+ }
+ GPU_buffer_unbind();
+}
+
+/* Only used by non-editmesh types */
static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm,
DMSetMaterial setMaterial,
DMSetDrawOptions setDrawOptions,
@@ -2228,18 +2614,15 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
int colType = CD_TEXTURE_MCOL;
MCol *mcol = dm->getTessFaceDataArray(dm, colType);
MTFace *tf = DM_get_tessface_data_layer(dm, CD_MTFACE);
- MTFace *tf_stencil_base = NULL;
- MTFace *tf_stencil = NULL;
- MTFace *tf_base;
- short (*lnors)[4][3] = dm->getTessFaceDataArray(dm, CD_TESSLOOPNORMAL);
DMFlagMat *faceFlags = ccgdm->faceFlags;
DMDrawOption draw_option;
- int i, totface, gridSize = ccgSubSurf_getGridSize(ss);
- int gridFaces = gridSize - 1;
- int gridOffset = 0;
- int mat_nr_cache = -1;
-
- (void) compareDrawOptions;
+ int i, totpoly;
+ bool flush;
+ bool use_tface = (flag & DM_DRAW_USE_ACTIVE_UV) != 0;
+ unsigned int next_actualFace;
+ unsigned int gridFaces = ccgSubSurf_getGridSize(ss) - 1;
+ int mat_index;
+ int tot_element, start_element;
CCG_key_top_level(&key, ss);
ccgdm_pbvh_update(ccgdm);
@@ -2253,210 +2636,96 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
mcol = dm->getTessFaceDataArray(dm, colType);
}
- totface = ccgSubSurf_getNumFaces(ss);
-
- if (flag & DM_DRAW_USE_TEXPAINT_UV) {
- int stencil = CustomData_get_stencil_layer(&dm->faceData, CD_MTFACE);
- tf_stencil_base = CustomData_get_layer_n(&dm->faceData, CD_MTFACE, stencil);
+ GPU_vertex_setup(dm);
+ GPU_normal_setup(dm);
+ GPU_triangle_setup(dm);
+ if (flag & DM_DRAW_USE_TEXPAINT_UV)
+ GPU_texpaint_uv_setup(dm);
+ else
+ GPU_uv_setup(dm);
+ if (mcol) {
+ GPU_color_setup(dm, colType);
}
- for (i = 0; i < totface; i++) {
- CCGFace *f = ccgdm->faceMap[i].face;
- int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
- int drawSmooth, index = ccgDM_getFaceMapIndex(ss, f);
- int origIndex = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f));
- unsigned char *cp = NULL;
- short (*ln)[4][3] = NULL;
- int mat_nr;
+ next_actualFace = 0;
- if (faceFlags) {
- drawSmooth = (lnors || (faceFlags[origIndex].flag & ME_SMOOTH));
- mat_nr = faceFlags[origIndex].mat_nr;
- }
- else {
- drawSmooth = 1;
- mat_nr = 0;
- }
+ glShadeModel(GL_SMOOTH);
+ /* lastFlag = 0; */ /* UNUSED */
+ for (mat_index = 0; mat_index < dm->drawObject->totmaterial; mat_index++) {
+ GPUBufferMaterial *bufmat = dm->drawObject->materials + mat_index;
+ next_actualFace = bufmat->polys[0];
+ totpoly = bufmat->totpolys;
- /* texture painting, handle the correct uv layer here */
- if (flag & DM_DRAW_USE_TEXPAINT_UV) {
- if (mat_nr != mat_nr_cache) {
- tf_base = DM_paint_uvlayer_active_get(dm, mat_nr);
+ tot_element = 0;
+ start_element = bufmat->start;
- mat_nr_cache = mat_nr;
+ for (i = 0; i < totpoly; i++) {
+ int polyindex = bufmat->polys[i];
+ CCGFace *f = ccgdm->faceMap[polyindex].face;
+ int numVerts = ccgSubSurf_getFaceNumVerts(f);
+ int index = ccgDM_getFaceMapIndex(ss, f);
+ int origIndex = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f));
+ int mat_nr;
+ int facequads = numVerts * gridFaces * gridFaces;
+ int actualFace = ccgdm->faceMap[polyindex].startFace;
+
+ if (i != totpoly - 1) {
+ polyindex = bufmat->polys[i + 1];
+ next_actualFace = ccgdm->faceMap[polyindex].startFace;
}
- tf = tf_base ? tf_base + gridOffset : NULL;
- tf_stencil = tf_stencil_base ? tf_stencil_base + gridOffset : NULL;
- gridOffset += gridFaces * gridFaces * numVerts;
- }
-
- if (drawParams) {
- MTexPoly tpoly;
- if (tf) {
- ME_MTEXFACE_CPY(&tpoly, tf);
+ if (faceFlags) {
+ mat_nr = faceFlags[origIndex].mat_nr;
+ }
+ else {
+ mat_nr = 0;
}
- draw_option = drawParams(tf ? &tpoly : NULL, (mcol != NULL), mat_nr);
- }
- else if (index != ORIGINDEX_NONE)
- draw_option = (drawParamsMapped) ? drawParamsMapped(userData, index, mat_nr) : DM_DRAW_OPTION_NORMAL;
- else
- draw_option = GPU_enable_material(mat_nr, NULL) ? DM_DRAW_OPTION_NORMAL : DM_DRAW_OPTION_SKIP;
-
- if (lnors) {
- ln = lnors;
- lnors += gridFaces * gridFaces * numVerts;
- }
-
- if (draw_option == DM_DRAW_OPTION_SKIP) {
- if (tf) tf += gridFaces * gridFaces * numVerts;
- if (mcol) mcol += gridFaces * gridFaces * numVerts * 4;
- continue;
- }
-
- /* flag 1 == use vertex colors */
- if (mcol) {
- if (draw_option != DM_DRAW_OPTION_NO_MCOL)
- cp = (unsigned char *)mcol;
- mcol += gridFaces * gridFaces * numVerts * 4;
- }
-
- for (S = 0; S < numVerts; S++) {
- CCGElem *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
- CCGElem *a, *b;
-
- if (ln) {
- glShadeModel(GL_SMOOTH);
- glBegin(GL_QUADS);
- for (y = 0; y < gridFaces; y++) {
- for (x = 0; x < gridFaces; x++) {
- float *a_co = CCG_grid_elem_co(&key, faceGridData, x, y + 0);
- float *b_co = CCG_grid_elem_co(&key, faceGridData, x + 1, y + 0);
- float *c_co = CCG_grid_elem_co(&key, faceGridData, x + 1, y + 1);
- float *d_co = CCG_grid_elem_co(&key, faceGridData, x, y + 1);
-
- if (tf) glTexCoord2fv(tf->uv[1]);
- if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[1]);
- if (cp) glColor3ub(cp[7], cp[6], cp[5]);
- glNormal3sv(ln[0][1]);
- glVertex3fv(d_co);
-
- if (tf) glTexCoord2fv(tf->uv[2]);
- if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[2]);
- if (cp) glColor3ub(cp[11], cp[10], cp[9]);
- glNormal3sv(ln[0][2]);
- glVertex3fv(c_co);
-
- if (tf) glTexCoord2fv(tf->uv[3]);
- if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[3]);
- if (cp) glColor3ub(cp[15], cp[14], cp[13]);
- glNormal3sv(ln[0][3]);
- glVertex3fv(b_co);
-
- if (tf) glTexCoord2fv(tf->uv[0]);
- if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[0]);
- if (cp) glColor3ub(cp[3], cp[2], cp[1]);
- glNormal3sv(ln[0][0]);
- glVertex3fv(a_co);
- if (tf) tf++;
- if (tf_stencil) tf_stencil++;
- if (cp) cp += 16;
- ln++;
- }
+ if (drawParams) {
+ MTexPoly tpoly;
+ if (tf) {
+ ME_MTEXFACE_CPY(&tpoly, tf + actualFace);
}
- glEnd();
+
+ draw_option = drawParams((use_tface && tf) ? &tpoly : NULL, (mcol != NULL), mat_nr);
}
- else if (drawSmooth) {
- glShadeModel(GL_SMOOTH);
- for (y = 0; y < gridFaces; y++) {
- glBegin(GL_QUAD_STRIP);
- for (x = 0; x < gridFaces; x++) {
- a = CCG_grid_elem(&key, faceGridData, x, y + 0);
- b = CCG_grid_elem(&key, faceGridData, x, y + 1);
-
- if (tf) glTexCoord2fv(tf->uv[0]);
- if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[0]);
- if (cp) glColor3ub(cp[3], cp[2], cp[1]);
- glNormal3fv(CCG_elem_no(&key, a));
- glVertex3fv(CCG_elem_co(&key, a));
-
- if (tf) glTexCoord2fv(tf->uv[1]);
- if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[1]);
- if (cp) glColor3ub(cp[7], cp[6], cp[5]);
- glNormal3fv(CCG_elem_no(&key, b));
- glVertex3fv(CCG_elem_co(&key, b));
-
- if (x != gridFaces - 1) {
- if (tf) tf++;
- if (tf_stencil) tf_stencil++;
- if (cp) cp += 16;
- }
- }
+ else if (index != ORIGINDEX_NONE)
+ draw_option = (drawParamsMapped) ? drawParamsMapped(userData, index, mat_nr) : DM_DRAW_OPTION_NORMAL;
+ else
+ draw_option = DM_DRAW_OPTION_NORMAL;
- a = CCG_grid_elem(&key, faceGridData, x, y + 0);
- b = CCG_grid_elem(&key, faceGridData, x, y + 1);
+ /* flush buffer if current triangle isn't drawable or it's last triangle */
+ flush = (draw_option == DM_DRAW_OPTION_SKIP) || (i == totpoly - 1);
- if (tf) glTexCoord2fv(tf->uv[3]);
- if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[3]);
- if (cp) glColor3ub(cp[15], cp[14], cp[13]);
- glNormal3fv(CCG_elem_no(&key, a));
- glVertex3fv(CCG_elem_co(&key, a));
+ if (!flush && compareDrawOptions) {
+ /* also compare draw options and flush buffer if they're different
+ * need for face selection highlight in edit mode */
+ flush |= compareDrawOptions(userData, actualFace, next_actualFace) == 0;
+ }
- if (tf) glTexCoord2fv(tf->uv[2]);
- if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[2]);
- if (cp) glColor3ub(cp[11], cp[10], cp[9]);
- glNormal3fv(CCG_elem_no(&key, b));
- glVertex3fv(CCG_elem_co(&key, b));
+ if (flush) {
+ if (draw_option != DM_DRAW_OPTION_SKIP)
+ tot_element += facequads * 6;
- if (tf) tf++;
- if (tf_stencil) tf_stencil++;
- if (cp) cp += 16;
+ if (tot_element) {
+ if (mcol && draw_option != DM_DRAW_OPTION_NO_MCOL)
+ GPU_color_switch(1);
+ else
+ GPU_color_switch(0);
- glEnd();
+ GPU_buffer_draw_elements(dm->drawObject->triangles, GL_TRIANGLES, start_element, tot_element);
}
+
+ start_element = tot_element;
}
else {
- glShadeModel((cp) ? GL_SMOOTH : GL_FLAT);
- glBegin(GL_QUADS);
- for (y = 0; y < gridFaces; y++) {
- for (x = 0; x < gridFaces; x++) {
- float *a_co = CCG_grid_elem_co(&key, faceGridData, x, y + 0);
- float *b_co = CCG_grid_elem_co(&key, faceGridData, x + 1, y + 0);
- float *c_co = CCG_grid_elem_co(&key, faceGridData, x + 1, y + 1);
- float *d_co = CCG_grid_elem_co(&key, faceGridData, x, y + 1);
-
- ccgDM_glNormalFast(a_co, b_co, c_co, d_co);
-
- if (tf) glTexCoord2fv(tf->uv[1]);
- if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[1]);
- if (cp) glColor3ub(cp[7], cp[6], cp[5]);
- glVertex3fv(d_co);
-
- if (tf) glTexCoord2fv(tf->uv[2]);
- if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[2]);
- if (cp) glColor3ub(cp[11], cp[10], cp[9]);
- glVertex3fv(c_co);
-
- if (tf) glTexCoord2fv(tf->uv[3]);
- if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[3]);
- if (cp) glColor3ub(cp[15], cp[14], cp[13]);
- glVertex3fv(b_co);
-
- if (tf) glTexCoord2fv(tf->uv[0]);
- if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[0]);
- if (cp) glColor3ub(cp[3], cp[2], cp[1]);
- glVertex3fv(a_co);
-
- if (tf) tf++;
- if (tf_stencil) tf_stencil++;
- if (cp) cp += 16;
- }
- }
- glEnd();
+ tot_element += facequads * 6;
}
}
}
+
+
+ GPU_buffer_unbind();
}
static void ccgDM_drawFacesTex(DerivedMesh *dm,
@@ -3440,7 +3709,9 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
ccgdm->dm.drawMappedEdgesInterp = ccgDM_drawMappedEdgesInterp;
ccgdm->dm.drawMappedEdges = ccgDM_drawMappedEdges;
-
+ ccgdm->dm.gpuObjectNew = ccgDM_GPUObjectNew;
+ ccgdm->dm.copy_gpu_data = ccgDM_copy_gpu_data;
+
ccgdm->dm.release = ccgDM_release;
ccgdm->ss = ss;
diff --git a/source/blender/gpu/GPU_buffers.h b/source/blender/gpu/GPU_buffers.h
index 350ecf22e1b..07b9c60d101 100644
--- a/source/blender/gpu/GPU_buffers.h
+++ b/source/blender/gpu/GPU_buffers.h
@@ -48,6 +48,10 @@ struct GSet;
struct GPUVertPointLink;
struct PBVH;
+typedef void (*GPUBufferCopyFunc)(DerivedMesh *dm, float *varray, int *index,
+ int *mat_orig_to_new, void *user_data);
+
+
typedef struct GPUBuffer {
int size; /* in bytes */
void *pointer; /* used with vertex arrays */
@@ -58,7 +62,11 @@ typedef struct GPUBuffer {
typedef struct GPUBufferMaterial {
/* range of points used for this material */
int start;
- int totpoint;
+ int totelements;
+ int totloops;
+ int *polys; /* array of polygons for this material */
+ int totpolys; /* total polygons in polys */
+ int counter; /* general purpose counter, initialize first! */
/* original material index */
short mat_nr;
@@ -88,9 +96,7 @@ typedef struct GPUDrawObject {
GPUBuffer *colors;
GPUBuffer *edges;
GPUBuffer *uvedges;
-
- /* for each triangle, the original MFace index */
- int *triangle_to_mface;
+ GPUBuffer *triangles; /* triangle index buffer */
/* for each original vertex, the list of related points */
struct GPUVertPointLink *vert_points;
@@ -103,12 +109,15 @@ typedef struct GPUDrawObject {
#endif
int colType;
+ int index_setup; /* how indices are setup, starting from start of buffer or start of material */
GPUBufferMaterial *materials;
int totmaterial;
int tot_triangle_point;
int tot_loose_point;
+ /* different than total loops since ngons get tesselated still */
+ int tot_loop_verts;
/* caches of the original DerivedMesh values */
int totvert;
@@ -119,6 +128,19 @@ typedef struct GPUDrawObject {
int tot_edge_drawn;
} GPUDrawObject;
+/* currently unused */
+// #define USE_GPU_POINT_LINK
+
+typedef struct GPUVertPointLink {
+#ifdef USE_GPU_POINT_LINK
+ struct GPUVertPointLink *next;
+#endif
+ /* -1 means uninitialized */
+ int point_index;
+} GPUVertPointLink;
+
+
+
/* used for GLSL materials */
typedef struct GPUAttrib {
int index;
@@ -129,12 +151,24 @@ typedef struct GPUAttrib {
void GPU_global_buffer_pool_free(void);
void GPU_global_buffer_pool_free_unused(void);
-GPUBuffer *GPU_buffer_alloc(int size, bool force_vertex_arrays);
+GPUBuffer *GPU_buffer_alloc(size_t size, bool force_vertex_arrays);
void GPU_buffer_free(GPUBuffer *buffer);
-GPUDrawObject *GPU_drawobject_new(struct DerivedMesh *dm);
void GPU_drawobject_free(struct DerivedMesh *dm);
+/* flag that controls data type to fill buffer with, a modifier will prepare. */
+typedef enum {
+ GPU_BUFFER_VERTEX = 0,
+ GPU_BUFFER_NORMAL,
+ GPU_BUFFER_COLOR,
+ GPU_BUFFER_UV,
+ GPU_BUFFER_UV_TEXPAINT,
+ GPU_BUFFER_EDGE,
+ GPU_BUFFER_UVEDGE,
+ GPU_BUFFER_TRIANGLES
+} GPUBufferType;
+
+
/* called before drawing */
void GPU_vertex_setup(struct DerivedMesh *dm);
void GPU_normal_setup(struct DerivedMesh *dm);
@@ -144,8 +178,11 @@ void GPU_texpaint_uv_setup(struct DerivedMesh *dm);
void GPU_color_setup(struct DerivedMesh *dm, int colType);
void GPU_edge_setup(struct DerivedMesh *dm); /* does not mix with other data */
void GPU_uvedge_setup(struct DerivedMesh *dm);
+
+void GPU_triangle_setup(struct DerivedMesh *dm);
+
int GPU_attrib_element_size(GPUAttrib data[], int numdata);
-void GPU_interleaved_attrib_setup(GPUBuffer *buffer, GPUAttrib data[], int numdata);
+void GPU_interleaved_attrib_setup(GPUBuffer *buffer, GPUAttrib data[], int numdata, int element_size);
/* can't lock more than one buffer at once */
void *GPU_buffer_lock(GPUBuffer *buffer);
@@ -161,6 +198,9 @@ void GPU_buffer_draw_elements(GPUBuffer *elements, unsigned int mode, int start,
/* called after drawing */
void GPU_buffer_unbind(void);
+/* only unbind interleaved data */
+void GPU_interleaved_attrib_unbind(void);
+
/* Buffers for non-DerivedMesh drawing */
typedef struct GPU_PBVH_Buffers GPU_PBVH_Buffers;
@@ -196,7 +236,7 @@ void GPU_update_grid_pbvh_buffers(GPU_PBVH_Buffers *buffers, struct CCGElem **gr
/* draw */
void GPU_draw_pbvh_buffers(GPU_PBVH_Buffers *buffers, DMSetMaterial setMaterial,
- bool wireframe);
+ bool wireframe, bool fast);
/* debug PBVH draw*/
void GPU_draw_pbvh_BB(float min[3], float max[3], bool leaf);
diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c
index bcbae9958d1..ac6329910c9 100644
--- a/source/blender/gpu/intern/gpu_buffers.c
+++ b/source/blender/gpu/intern/gpu_buffers.c
@@ -69,6 +69,35 @@ typedef enum {
GPU_BUFFER_ELEMENT_STATE = (1 << 5),
} GPUBufferState;
+typedef struct {
+ GLenum gl_buffer_type;
+ int num_components; /* number of data components for one vertex */
+} GPUBufferTypeSettings;
+
+
+static int gpu_buffer_size_from_type(DerivedMesh *dm, GPUBufferType type);
+
+const GPUBufferTypeSettings gpu_buffer_type_settings[] = {
+ /* vertex */
+ {GL_ARRAY_BUFFER_ARB, 3},
+ /* normal */
+ {GL_ARRAY_BUFFER_ARB, 4}, /* we copy 3 shorts per normal but we add a fourth for alignment */
+ /* mcol */
+ {GL_ARRAY_BUFFER_ARB, 3},
+ /* uv */
+ {GL_ARRAY_BUFFER_ARB, 2},
+ /* uv for texpaint */
+ {GL_ARRAY_BUFFER_ARB, 4},
+ /* edge */
+ {GL_ELEMENT_ARRAY_BUFFER_ARB, 2},
+ /* uv edge */
+ {GL_ELEMENT_ARRAY_BUFFER_ARB, 4},
+ /* triangles, 1 point since we are allocating from tottriangle points, which account for all points */
+ {GL_ELEMENT_ARRAY_BUFFER_ARB, 1},
+ /* fast triangles */
+ {GL_ELEMENT_ARRAY_BUFFER_ARB, 1},
+};
+
#define MAX_GPU_ATTRIB_DATA 32
#define BUFFER_OFFSET(n) ((GLubyte *)NULL + (n))
@@ -221,11 +250,12 @@ void GPU_global_buffer_pool_free_unused(void)
*
* Thread-unsafe version for internal usage only.
*/
-static GPUBuffer *gpu_buffer_alloc_intern(int size, bool use_VBO)
+static GPUBuffer *gpu_buffer_alloc_intern(size_t size, bool use_VBO)
{
GPUBufferPool *pool;
GPUBuffer *buf;
- int i, bufsize, bestfit = -1;
+ int i, bestfit = -1;
+ size_t bufsize;
/* bad case, leads to leak of buf since buf->pointer will allocate
* NULL, leading to return without cleanup. In any case better detect early
@@ -290,8 +320,11 @@ static GPUBuffer *gpu_buffer_alloc_intern(int size, bool use_VBO)
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
}
else {
+ static int time = 0;
+
buf->pointer = MEM_mallocN(size, "GPUBuffer.pointer");
-
+
+ time++;
/* purpose of this seems to be dealing with
* out-of-memory errors? looks a bit iffy to me
* though, at least on Linux I expect malloc() would
@@ -308,7 +341,7 @@ static GPUBuffer *gpu_buffer_alloc_intern(int size, bool use_VBO)
}
/* Same as above, but safe for threading. */
-GPUBuffer *GPU_buffer_alloc(int size, bool force_vertex_arrays)
+GPUBuffer *GPU_buffer_alloc(size_t size, bool force_vertex_arrays)
{
GPUBuffer *buffer;
bool use_VBOs = (GLEW_ARB_vertex_buffer_object) && !(U.gameflags & USER_DISABLE_VBO) && !force_vertex_arrays;
@@ -383,197 +416,22 @@ void GPU_buffer_free(GPUBuffer *buffer)
BLI_mutex_unlock(&buffer_mutex);
}
-#if 0 /* currently unused */
-# define USE_GPU_POINT_LINK
-#endif
-
-typedef struct GPUVertPointLink {
-#ifdef USE_GPU_POINT_LINK
- struct GPUVertPointLink *next;
-#endif
- /* -1 means uninitialized */
- int point_index;
-} GPUVertPointLink;
-
-
-/* add a new point to the list of points related to a particular
- * vertex */
-#ifdef USE_GPU_POINT_LINK
-
-static void gpu_drawobject_add_vert_point(GPUDrawObject *gdo, int vert_index, int point_index)
-{
- GPUVertPointLink *lnk;
-
- lnk = &gdo->vert_points[vert_index];
-
- /* if first link is in use, add a new link at the end */
- if (lnk->point_index != -1) {
- /* get last link */
- for (; lnk->next; lnk = lnk->next) ;
-
- /* add a new link from the pool */
- lnk = lnk->next = &gdo->vert_points_mem[gdo->vert_points_usage];
- gdo->vert_points_usage++;
- }
-
- lnk->point_index = point_index;
-}
-
-#else
-
-static void gpu_drawobject_add_vert_point(GPUDrawObject *gdo, int vert_index, int point_index)
-{
- GPUVertPointLink *lnk;
- lnk = &gdo->vert_points[vert_index];
- if (lnk->point_index == -1) {
- lnk->point_index = point_index;
- }
-}
-
-#endif /* USE_GPU_POINT_LINK */
-
-/* update the vert_points and triangle_to_mface fields with a new
- * triangle */
-static void gpu_drawobject_add_triangle(GPUDrawObject *gdo,
- int base_point_index,
- int face_index,
- int v1, int v2, int v3)
-{
- int i, v[3] = {v1, v2, v3};
- for (i = 0; i < 3; i++)
- gpu_drawobject_add_vert_point(gdo, v[i], base_point_index + i);
- gdo->triangle_to_mface[base_point_index / 3] = face_index;
-}
-
-/* for each vertex, build a list of points related to it; these lists
- * are stored in an array sized to the number of vertices */
-static void gpu_drawobject_init_vert_points(GPUDrawObject *gdo, const MFace *f, int totface, int totmat)
-{
- GPUBufferMaterial *mat;
- int i, *mat_orig_to_new;
-
- mat_orig_to_new = MEM_callocN(sizeof(*mat_orig_to_new) * totmat,
- "GPUDrawObject.mat_orig_to_new");
- /* allocate the array and space for links */
- gdo->vert_points = MEM_mallocN(sizeof(GPUVertPointLink) * gdo->totvert,
- "GPUDrawObject.vert_points");
-#ifdef USE_GPU_POINT_LINK
- gdo->vert_points_mem = MEM_callocN(sizeof(GPUVertPointLink) * gdo->tot_triangle_point,
- "GPUDrawObject.vert_points_mem");
- gdo->vert_points_usage = 0;
-#endif
-
- /* build a map from the original material indices to the new
- * GPUBufferMaterial indices */
- for (i = 0; i < gdo->totmaterial; i++)
- mat_orig_to_new[gdo->materials[i].mat_nr] = i;
-
- /* -1 indicates the link is not yet used */
- for (i = 0; i < gdo->totvert; i++) {
-#ifdef USE_GPU_POINT_LINK
- gdo->vert_points[i].link = NULL;
-#endif
- gdo->vert_points[i].point_index = -1;
- }
-
- for (i = 0; i < totface; i++, f++) {
- mat = &gdo->materials[mat_orig_to_new[f->mat_nr]];
-
- /* add triangle */
- gpu_drawobject_add_triangle(gdo, mat->start + mat->totpoint,
- i, f->v1, f->v2, f->v3);
- mat->totpoint += 3;
-
- /* add second triangle for quads */
- if (f->v4) {
- gpu_drawobject_add_triangle(gdo, mat->start + mat->totpoint,
- i, f->v3, f->v4, f->v1);
- mat->totpoint += 3;
- }
- }
-
- /* map any unused vertices to loose points */
- for (i = 0; i < gdo->totvert; i++) {
- if (gdo->vert_points[i].point_index == -1) {
- gdo->vert_points[i].point_index = gdo->tot_triangle_point + gdo->tot_loose_point;
- gdo->tot_loose_point++;
- }
- }
-
- MEM_freeN(mat_orig_to_new);
-}
-
-/* see GPUDrawObject's structure definition for a description of the
- * data being initialized here */
-GPUDrawObject *GPU_drawobject_new(DerivedMesh *dm)
-{
- GPUDrawObject *gdo;
- const MFace *mface;
- int totmat = dm->totmat;
- int *points_per_mat;
- int i, curmat, curpoint, totface;
-
- /* object contains at least one material (default included) so zero means uninitialized dm */
- BLI_assert(totmat != 0);
-
- mface = dm->getTessFaceArray(dm);
- totface = dm->getNumTessFaces(dm);
-
- /* get the number of points used by each material, treating
- * each quad as two triangles */
- points_per_mat = MEM_callocN(sizeof(*points_per_mat) * totmat, "GPU_drawobject_new.mat_orig_to_new");
- for (i = 0; i < totface; i++)
- points_per_mat[mface[i].mat_nr] += mface[i].v4 ? 6 : 3;
-
- /* create the GPUDrawObject */
- gdo = MEM_callocN(sizeof(GPUDrawObject), "GPUDrawObject");
- gdo->totvert = dm->getNumVerts(dm);
- gdo->totedge = dm->getNumEdges(dm);
-
- /* count the number of materials used by this DerivedMesh */
- for (i = 0; i < totmat; i++) {
- if (points_per_mat[i] > 0)
- gdo->totmaterial++;
- }
-
- /* allocate an array of materials used by this DerivedMesh */
- gdo->materials = MEM_mallocN(sizeof(GPUBufferMaterial) * gdo->totmaterial,
- "GPUDrawObject.materials");
-
- /* initialize the materials array */
- for (i = 0, curmat = 0, curpoint = 0; i < totmat; i++) {
- if (points_per_mat[i] > 0) {
- gdo->materials[curmat].start = curpoint;
- gdo->materials[curmat].totpoint = 0;
- gdo->materials[curmat].mat_nr = i;
-
- curpoint += points_per_mat[i];
- curmat++;
- }
- }
-
- /* store total number of points used for triangles */
- gdo->tot_triangle_point = curpoint;
-
- gdo->triangle_to_mface = MEM_mallocN(sizeof(int) * (gdo->tot_triangle_point / 3),
- "GPUDrawObject.triangle_to_mface");
-
- gpu_drawobject_init_vert_points(gdo, mface, totface, totmat);
- MEM_freeN(points_per_mat);
-
- return gdo;
-}
-
void GPU_drawobject_free(DerivedMesh *dm)
{
GPUDrawObject *gdo;
+ int i;
if (!dm || !(gdo = dm->drawObject))
return;
+ for (i = 0; i < gdo->totmaterial; i++) {
+ if (gdo->materials[i].polys)
+ MEM_freeN(gdo->materials[i].polys);
+ }
+
MEM_freeN(gdo->materials);
- MEM_freeN(gdo->triangle_to_mface);
- MEM_freeN(gdo->vert_points);
+ if (gdo->vert_points)
+ MEM_freeN(gdo->vert_points);
#ifdef USE_GPU_POINT_LINK
MEM_freeN(gdo->vert_points_mem);
#endif
@@ -584,6 +442,7 @@ void GPU_drawobject_free(DerivedMesh *dm)
GPU_buffer_free(gdo->colors);
GPU_buffer_free(gdo->edges);
GPU_buffer_free(gdo->uvedges);
+ GPU_buffer_free(gdo->triangles);
MEM_freeN(gdo);
dm->drawObject = NULL;
@@ -605,20 +464,18 @@ static GPUBuffer *gpu_try_realloc(GPUBufferPool *pool, GPUBuffer *buffer, int si
return buffer;
}
-typedef void (*GPUBufferCopyFunc)(
- DerivedMesh *dm, float *varray, int *index,
- const int *mat_orig_to_new, const void *user_data);
-
static GPUBuffer *gpu_buffer_setup(DerivedMesh *dm, GPUDrawObject *object,
- int vector_size, int size, GLenum target,
- void *user, GPUBufferCopyFunc copy_f)
+ int type, void *user)
{
GPUBufferPool *pool;
GPUBuffer *buffer;
float *varray;
int *mat_orig_to_new;
- int *cur_index_per_mat;
int i;
+ const GPUBufferTypeSettings *ts = &gpu_buffer_type_settings[type];
+ GLenum target = ts->gl_buffer_type;
+ int num_components = ts->num_components;
+ int size = gpu_buffer_size_from_type(dm, type);
bool use_VBOs = (GLEW_ARB_vertex_buffer_object) && !(U.gameflags & USER_DISABLE_VBO);
GLboolean uploaded;
@@ -634,11 +491,9 @@ static GPUBuffer *gpu_buffer_setup(DerivedMesh *dm, GPUDrawObject *object,
mat_orig_to_new = MEM_mallocN(sizeof(*mat_orig_to_new) * dm->totmat,
"GPU_buffer_setup.mat_orig_to_new");
- cur_index_per_mat = MEM_mallocN(sizeof(int) * object->totmaterial,
- "GPU_buffer_setup.cur_index_per_mat");
for (i = 0; i < object->totmaterial; i++) {
/* for each material, the current index to copy data to */
- cur_index_per_mat[i] = object->materials[i].start * vector_size;
+ object->materials[i].counter = object->materials[i].start * num_components;
/* map from original material index to new
* GPUBufferMaterial index */
@@ -675,7 +530,7 @@ static GPUBuffer *gpu_buffer_setup(DerivedMesh *dm, GPUDrawObject *object,
uploaded = GL_FALSE;
/* attempt to upload the data to the VBO */
while (uploaded == GL_FALSE) {
- (*copy_f)(dm, varray, cur_index_per_mat, mat_orig_to_new, user);
+ dm->copy_gpu_data(dm, type, varray, mat_orig_to_new, user);
/* glUnmapBuffer returns GL_FALSE if
* the data store is corrupted; retry
* in that case */
@@ -692,11 +547,10 @@ static GPUBuffer *gpu_buffer_setup(DerivedMesh *dm, GPUDrawObject *object,
if (buffer) {
varray = buffer->pointer;
- (*copy_f)(dm, varray, cur_index_per_mat, mat_orig_to_new, user);
+ dm->copy_gpu_data(dm, type, varray, mat_orig_to_new, user);
}
}
- MEM_freeN(cur_index_per_mat);
MEM_freeN(mat_orig_to_new);
BLI_mutex_unlock(&buffer_mutex);
@@ -704,375 +558,6 @@ static GPUBuffer *gpu_buffer_setup(DerivedMesh *dm, GPUDrawObject *object,
return buffer;
}
-static void GPU_buffer_copy_vertex(
- DerivedMesh *dm, float *varray,
- int *index, const int *mat_orig_to_new, const void *UNUSED(user))
-{
- const MVert *mvert;
- const MFace *f;
- int i, j, start, totface;
-
- mvert = dm->getVertArray(dm);
- f = dm->getTessFaceArray(dm);
-
- totface = dm->getNumTessFaces(dm);
- for (i = 0; i < totface; i++, f++) {
- start = index[mat_orig_to_new[f->mat_nr]];
-
- /* v1 v2 v3 */
- copy_v3_v3(&varray[start], mvert[f->v1].co);
- copy_v3_v3(&varray[start + 3], mvert[f->v2].co);
- copy_v3_v3(&varray[start + 6], mvert[f->v3].co);
- index[mat_orig_to_new[f->mat_nr]] += 9;
-
- if (f->v4) {
- /* v3 v4 v1 */
- copy_v3_v3(&varray[start + 9], mvert[f->v3].co);
- copy_v3_v3(&varray[start + 12], mvert[f->v4].co);
- copy_v3_v3(&varray[start + 15], mvert[f->v1].co);
- index[mat_orig_to_new[f->mat_nr]] += 9;
- }
- }
-
- /* copy loose points */
- j = dm->drawObject->tot_triangle_point * 3;
- for (i = 0; i < dm->drawObject->totvert; i++) {
- if (dm->drawObject->vert_points[i].point_index >= dm->drawObject->tot_triangle_point) {
- copy_v3_v3(&varray[j], mvert[i].co);
- j += 3;
- }
- }
-}
-
-static void GPU_buffer_copy_normal(
- DerivedMesh *dm, float *varray, int *index,
- const int *mat_orig_to_new, const void *UNUSED(user))
-{
- int i, totface;
- int start;
- float f_no[3];
-
- const float *nors = dm->getTessFaceDataArray(dm, CD_NORMAL);
- short (*tlnors)[4][3] = dm->getTessFaceDataArray(dm, CD_TESSLOOPNORMAL);
- const MVert *mvert = dm->getVertArray(dm);
- const MFace *f = dm->getTessFaceArray(dm);
-
- totface = dm->getNumTessFaces(dm);
- for (i = 0; i < totface; i++, f++) {
- const int smoothnormal = (f->flag & ME_SMOOTH);
-
- start = index[mat_orig_to_new[f->mat_nr]];
- index[mat_orig_to_new[f->mat_nr]] += f->v4 ? 18 : 9;
-
- if (tlnors) {
- short (*tlnor)[3] = tlnors[i];
- /* Copy loop normals */
- normal_short_to_float_v3(&varray[start], tlnor[0]);
- normal_short_to_float_v3(&varray[start + 3], tlnor[1]);
- normal_short_to_float_v3(&varray[start + 6], tlnor[2]);
-
- if (f->v4) {
- normal_short_to_float_v3(&varray[start + 9], tlnor[2]);
- normal_short_to_float_v3(&varray[start + 12], tlnor[3]);
- normal_short_to_float_v3(&varray[start + 15], tlnor[0]);
- }
- }
- else if (smoothnormal) {
- /* copy vertex normal */
- normal_short_to_float_v3(&varray[start], mvert[f->v1].no);
- normal_short_to_float_v3(&varray[start + 3], mvert[f->v2].no);
- normal_short_to_float_v3(&varray[start + 6], mvert[f->v3].no);
-
- if (f->v4) {
- normal_short_to_float_v3(&varray[start + 9], mvert[f->v3].no);
- normal_short_to_float_v3(&varray[start + 12], mvert[f->v4].no);
- normal_short_to_float_v3(&varray[start + 15], mvert[f->v1].no);
- }
- }
- else if (nors) {
- /* copy cached face normal */
- copy_v3_v3(&varray[start], &nors[i * 3]);
- copy_v3_v3(&varray[start + 3], &nors[i * 3]);
- copy_v3_v3(&varray[start + 6], &nors[i * 3]);
-
- if (f->v4) {
- copy_v3_v3(&varray[start + 9], &nors[i * 3]);
- copy_v3_v3(&varray[start + 12], &nors[i * 3]);
- copy_v3_v3(&varray[start + 15], &nors[i * 3]);
- }
- }
- else {
- /* calculate face normal */
- if (f->v4)
- normal_quad_v3(f_no, mvert[f->v1].co, mvert[f->v2].co, mvert[f->v3].co, mvert[f->v4].co);
- else
- normal_tri_v3(f_no, mvert[f->v1].co, mvert[f->v2].co, mvert[f->v3].co);
-
- copy_v3_v3(&varray[start], f_no);
- copy_v3_v3(&varray[start + 3], f_no);
- copy_v3_v3(&varray[start + 6], f_no);
-
- if (f->v4) {
- copy_v3_v3(&varray[start + 9], f_no);
- copy_v3_v3(&varray[start + 12], f_no);
- copy_v3_v3(&varray[start + 15], f_no);
- }
- }
- }
-}
-
-static void GPU_buffer_copy_uv(
- DerivedMesh *dm, float *varray, int *index,
- const int *mat_orig_to_new, const void *UNUSED(user))
-{
- int start;
- int i, totface;
-
- const MTFace *mtface;
- const MFace *f;
-
- if (!(mtface = DM_get_tessface_data_layer(dm, CD_MTFACE)))
- return;
- f = dm->getTessFaceArray(dm);
-
- totface = dm->getNumTessFaces(dm);
- for (i = 0; i < totface; i++, f++) {
- start = index[mat_orig_to_new[f->mat_nr]];
-
- /* v1 v2 v3 */
- copy_v2_v2(&varray[start], mtface[i].uv[0]);
- copy_v2_v2(&varray[start + 2], mtface[i].uv[1]);
- copy_v2_v2(&varray[start + 4], mtface[i].uv[2]);
- index[mat_orig_to_new[f->mat_nr]] += 6;
-
- if (f->v4) {
- /* v3 v4 v1 */
- copy_v2_v2(&varray[start + 6], mtface[i].uv[2]);
- copy_v2_v2(&varray[start + 8], mtface[i].uv[3]);
- copy_v2_v2(&varray[start + 10], mtface[i].uv[0]);
- index[mat_orig_to_new[f->mat_nr]] += 6;
- }
- }
-}
-
-
-static void GPU_buffer_copy_uv_texpaint(
- DerivedMesh *dm, float *varray, int *index,
- const int *mat_orig_to_new, const void *UNUSED(user))
-{
- int start;
- int i, totface;
-
- int totmaterial = dm->totmat;
- const MTFace **mtface_base;
- const MTFace *stencil_base;
- int stencil;
- const MFace *mf;
-
- /* should have been checked for before, reassert */
- BLI_assert(DM_get_tessface_data_layer(dm, CD_MTFACE));
- mf = dm->getTessFaceArray(dm);
- mtface_base = MEM_mallocN(totmaterial * sizeof(*mtface_base), "texslots");
-
- for (i = 0; i < totmaterial; i++) {
- mtface_base[i] = DM_paint_uvlayer_active_get(dm, i);
- }
-
- stencil = CustomData_get_stencil_layer(&dm->faceData, CD_MTFACE);
- stencil_base = CustomData_get_layer_n(&dm->faceData, CD_MTFACE, stencil);
-
- totface = dm->getNumTessFaces(dm);
-
- for (i = 0; i < totface; i++, mf++) {
- int mat_i = mf->mat_nr;
- start = index[mat_orig_to_new[mat_i]];
-
- /* v1 v2 v3 */
- copy_v2_v2(&varray[start], mtface_base[mat_i][i].uv[0]);
- copy_v2_v2(&varray[start + 2], stencil_base[i].uv[0]);
- copy_v2_v2(&varray[start + 4], mtface_base[mat_i][i].uv[1]);
- copy_v2_v2(&varray[start + 6], stencil_base[i].uv[1]);
- copy_v2_v2(&varray[start + 8], mtface_base[mat_i][i].uv[2]);
- copy_v2_v2(&varray[start + 10], stencil_base[i].uv[2]);
- index[mat_orig_to_new[mat_i]] += 12;
-
- if (mf->v4) {
- /* v3 v4 v1 */
- copy_v2_v2(&varray[start + 12], mtface_base[mat_i][i].uv[2]);
- copy_v2_v2(&varray[start + 14], stencil_base[i].uv[2]);
- copy_v2_v2(&varray[start + 16], mtface_base[mat_i][i].uv[3]);
- copy_v2_v2(&varray[start + 18], stencil_base[i].uv[3]);
- copy_v2_v2(&varray[start + 20], mtface_base[mat_i][i].uv[0]);
- copy_v2_v2(&varray[start + 22], stencil_base[i].uv[0]);
- index[mat_orig_to_new[mat_i]] += 12;
- }
- }
-
- MEM_freeN(mtface_base);
-}
-
-
-static void copy_mcol_uc3(unsigned char *v, unsigned char *col)
-{
- v[0] = col[3];
- v[1] = col[2];
- v[2] = col[1];
-}
-
-/* treat varray_ as an array of MCol, four MCol's per face */
-static void GPU_buffer_copy_mcol(
- DerivedMesh *dm, float *varray_, int *index,
- const int *mat_orig_to_new, const void *user)
-{
- int i, totface;
- unsigned char *varray = (unsigned char *)varray_;
- unsigned char *mcol = (unsigned char *)user;
- const MFace *f = dm->getTessFaceArray(dm);
-
- totface = dm->getNumTessFaces(dm);
- for (i = 0; i < totface; i++, f++) {
- int start = index[mat_orig_to_new[f->mat_nr]];
-
- /* v1 v2 v3 */
- copy_mcol_uc3(&varray[start], &mcol[i * 16]);
- copy_mcol_uc3(&varray[start + 3], &mcol[i * 16 + 4]);
- copy_mcol_uc3(&varray[start + 6], &mcol[i * 16 + 8]);
- index[mat_orig_to_new[f->mat_nr]] += 9;
-
- if (f->v4) {
- /* v3 v4 v1 */
- copy_mcol_uc3(&varray[start + 9], &mcol[i * 16 + 8]);
- copy_mcol_uc3(&varray[start + 12], &mcol[i * 16 + 12]);
- copy_mcol_uc3(&varray[start + 15], &mcol[i * 16]);
- index[mat_orig_to_new[f->mat_nr]] += 9;
- }
- }
-}
-
-static void GPU_buffer_copy_edge(
- DerivedMesh *dm, float *varray_, int *UNUSED(index),
- const int *UNUSED(mat_orig_to_new), const void *UNUSED(user))
-{
- const MEdge *medge, *medge_base;
- unsigned int *varray = (unsigned int *)varray_;
- int i, totedge, iloose, inorm, iloosehidden, inormhidden;
- int tot_loose_hidden = 0, tot_loose = 0;
- int tot_hidden = 0, tot = 0;
-
- medge_base = medge = dm->getEdgeArray(dm);
- totedge = dm->getNumEdges(dm);
-
- for (i = 0; i < totedge; i++, medge++) {
- if (medge->flag & ME_EDGEDRAW) {
- if (medge->flag & ME_LOOSEEDGE) tot_loose++;
- else tot++;
- }
- else {
- if (medge->flag & ME_LOOSEEDGE) tot_loose_hidden++;
- else tot_hidden++;
- }
- }
-
- inorm = 0;
- inormhidden = tot;
- iloose = tot + tot_hidden;
- iloosehidden = iloose + tot_loose;
-
- medge = medge_base;
- for (i = 0; i < totedge; i++, medge++) {
- if (medge->flag & ME_EDGEDRAW) {
- if (medge->flag & ME_LOOSEEDGE) {
- varray[iloose * 2] = dm->drawObject->vert_points[medge->v1].point_index;
- varray[iloose * 2 + 1] = dm->drawObject->vert_points[medge->v2].point_index;
- iloose++;
- }
- else {
- varray[inorm * 2] = dm->drawObject->vert_points[medge->v1].point_index;
- varray[inorm * 2 + 1] = dm->drawObject->vert_points[medge->v2].point_index;
- inorm++;
- }
- }
- else {
- if (medge->flag & ME_LOOSEEDGE) {
- varray[iloosehidden * 2] = dm->drawObject->vert_points[medge->v1].point_index;
- varray[iloosehidden * 2 + 1] = dm->drawObject->vert_points[medge->v2].point_index;
- iloosehidden++;
- }
- else {
- varray[inormhidden * 2] = dm->drawObject->vert_points[medge->v1].point_index;
- varray[inormhidden * 2 + 1] = dm->drawObject->vert_points[medge->v2].point_index;
- inormhidden++;
- }
- }
- }
-
- dm->drawObject->tot_loose_edge_drawn = tot_loose;
- dm->drawObject->loose_edge_offset = tot + tot_hidden;
- dm->drawObject->tot_edge_drawn = tot;
-}
-
-static void GPU_buffer_copy_uvedge(
- DerivedMesh *dm, float *varray, int *UNUSED(index),
- const int *UNUSED(mat_orig_to_new), const void *UNUSED(user))
-{
- const MTFace *tf = DM_get_tessface_data_layer(dm, CD_MTFACE);
- int i, j = 0;
-
- if (!tf)
- return;
-
- for (i = 0; i < dm->numTessFaceData; i++, tf++) {
- MFace mf;
- dm->getTessFace(dm, i, &mf);
-
- copy_v2_v2(&varray[j], tf->uv[0]);
- copy_v2_v2(&varray[j + 2], tf->uv[1]);
-
- copy_v2_v2(&varray[j + 4], tf->uv[1]);
- copy_v2_v2(&varray[j + 6], tf->uv[2]);
-
- if (!mf.v4) {
- copy_v2_v2(&varray[j + 8], tf->uv[2]);
- copy_v2_v2(&varray[j + 10], tf->uv[0]);
- j += 12;
- }
- else {
- copy_v2_v2(&varray[j + 8], tf->uv[2]);
- copy_v2_v2(&varray[j + 10], tf->uv[3]);
-
- copy_v2_v2(&varray[j + 12], tf->uv[3]);
- copy_v2_v2(&varray[j + 14], tf->uv[0]);
- j += 16;
- }
- }
-}
-
-typedef enum {
- GPU_BUFFER_VERTEX = 0,
- GPU_BUFFER_NORMAL,
- GPU_BUFFER_COLOR,
- GPU_BUFFER_UV,
- GPU_BUFFER_UV_TEXPAINT,
- GPU_BUFFER_EDGE,
- GPU_BUFFER_UVEDGE,
-} GPUBufferType;
-
-typedef struct {
- GPUBufferCopyFunc copy;
- GLenum gl_buffer_type;
- int vector_size;
-} GPUBufferTypeSettings;
-
-const GPUBufferTypeSettings gpu_buffer_type_settings[] = {
- {GPU_buffer_copy_vertex, GL_ARRAY_BUFFER_ARB, 3},
- {GPU_buffer_copy_normal, GL_ARRAY_BUFFER_ARB, 3},
- {GPU_buffer_copy_mcol, GL_ARRAY_BUFFER_ARB, 3},
- {GPU_buffer_copy_uv, GL_ARRAY_BUFFER_ARB, 2},
- {GPU_buffer_copy_uv_texpaint, GL_ARRAY_BUFFER_ARB, 4},
- {GPU_buffer_copy_edge, GL_ELEMENT_ARRAY_BUFFER_ARB, 2},
- {GPU_buffer_copy_uvedge, GL_ELEMENT_ARRAY_BUFFER_ARB, 4}
-};
-
/* get the GPUDrawObject buffer associated with a type */
static GPUBuffer **gpu_drawobject_buffer_from_type(GPUDrawObject *gdo, GPUBufferType type)
{
@@ -1091,6 +576,8 @@ static GPUBuffer **gpu_drawobject_buffer_from_type(GPUDrawObject *gdo, GPUBuffer
return &gdo->edges;
case GPU_BUFFER_UVEDGE:
return &gdo->uvedges;
+ case GPU_BUFFER_TRIANGLES:
+ return &gdo->triangles;
default:
return NULL;
}
@@ -1101,24 +588,26 @@ static int gpu_buffer_size_from_type(DerivedMesh *dm, GPUBufferType type)
{
switch (type) {
case GPU_BUFFER_VERTEX:
- return sizeof(float) * 3 * (dm->drawObject->tot_triangle_point + dm->drawObject->tot_loose_point);
+ return sizeof(float) * gpu_buffer_type_settings[type].num_components * (dm->drawObject->tot_triangle_point + dm->drawObject->tot_loose_point);
case GPU_BUFFER_NORMAL:
- return sizeof(float) * 3 * dm->drawObject->tot_triangle_point;
+ return sizeof(short) * gpu_buffer_type_settings[type].num_components * dm->drawObject->tot_triangle_point;
case GPU_BUFFER_COLOR:
- return sizeof(char) * 3 * dm->drawObject->tot_triangle_point;
+ return sizeof(char) * gpu_buffer_type_settings[type].num_components * dm->drawObject->tot_triangle_point;
case GPU_BUFFER_UV:
- return sizeof(float) * 2 * dm->drawObject->tot_triangle_point;
+ return sizeof(float) * gpu_buffer_type_settings[type].num_components * dm->drawObject->tot_triangle_point;
case GPU_BUFFER_UV_TEXPAINT:
- return sizeof(float) * 4 * dm->drawObject->tot_triangle_point;
+ return sizeof(float) * gpu_buffer_type_settings[type].num_components * dm->drawObject->tot_triangle_point;
case GPU_BUFFER_EDGE:
- return sizeof(int) * 2 * dm->drawObject->totedge;
+ return sizeof(int) * gpu_buffer_type_settings[type].num_components * dm->drawObject->totedge;
case GPU_BUFFER_UVEDGE:
/* each face gets 3 points, 3 edges per triangle, and
* each edge has its own, non-shared coords, so each
* tri corner needs minimum of 4 floats, quads used
* less so here we can over allocate and assume all
* tris. */
- return sizeof(float) * 4 * dm->drawObject->tot_triangle_point;
+ return sizeof(int) * gpu_buffer_type_settings[type].num_components * dm->drawObject->tot_triangle_point;
+ case GPU_BUFFER_TRIANGLES:
+ return sizeof(int) * gpu_buffer_type_settings[type].num_components * dm->drawObject->tot_triangle_point;
default:
return -1;
}
@@ -1127,12 +616,9 @@ static int gpu_buffer_size_from_type(DerivedMesh *dm, GPUBufferType type)
/* call gpu_buffer_setup with settings for a particular type of buffer */
static GPUBuffer *gpu_buffer_setup_type(DerivedMesh *dm, GPUBufferType type)
{
- const GPUBufferTypeSettings *ts;
void *user_data = NULL;
GPUBuffer *buf;
- ts = &gpu_buffer_type_settings[type];
-
/* special handling for MCol and UV buffers */
if (type == GPU_BUFFER_COLOR) {
if (!(user_data = DM_get_tessface_data_layer(dm, dm->drawObject->colType)))
@@ -1143,9 +629,7 @@ static GPUBuffer *gpu_buffer_setup_type(DerivedMesh *dm, GPUBufferType type)
return NULL;
}
- buf = gpu_buffer_setup(dm, dm->drawObject, ts->vector_size,
- gpu_buffer_size_from_type(dm, type),
- ts->gl_buffer_type, user_data, ts->copy);
+ buf = gpu_buffer_setup(dm, dm->drawObject, type, user_data);
return buf;
}
@@ -1157,7 +641,7 @@ static GPUBuffer *gpu_buffer_setup_common(DerivedMesh *dm, GPUBufferType type)
GPUBuffer **buf;
if (!dm->drawObject)
- dm->drawObject = GPU_drawobject_new(dm);
+ dm->drawObject = dm->gpuObjectNew(dm);
buf = gpu_drawobject_buffer_from_type(dm->drawObject, type);
if (!(*buf))
@@ -1191,10 +675,10 @@ void GPU_normal_setup(DerivedMesh *dm)
glEnableClientState(GL_NORMAL_ARRAY);
if (dm->drawObject->normals->use_vbo) {
glBindBufferARB(GL_ARRAY_BUFFER_ARB, dm->drawObject->normals->id);
- glNormalPointer(GL_FLOAT, 0, 0);
+ glNormalPointer(GL_SHORT, 4 * sizeof(short), 0);
}
else {
- glNormalPointer(GL_FLOAT, 0, dm->drawObject->normals->pointer);
+ glNormalPointer(GL_SHORT, 4 * sizeof(short), dm->drawObject->normals->pointer);
}
GLStates |= GPU_BUFFER_NORMAL_STATE;
@@ -1248,7 +732,7 @@ void GPU_color_setup(DerivedMesh *dm, int colType)
if (!dm->drawObject) {
/* XXX Not really nice, but we need a valid gpu draw object to set the colType...
* Else we would have to add a new param to gpu_buffer_setup_common. */
- dm->drawObject = GPU_drawobject_new(dm);
+ dm->drawObject = dm->gpuObjectNew(dm);
dm->dirty &= ~DM_DIRTY_MCOL_UPDATE_DRAW;
dm->drawObject->colType = colType;
}
@@ -1322,6 +806,18 @@ void GPU_uvedge_setup(DerivedMesh *dm)
GLStates |= GPU_BUFFER_VERTEX_STATE;
}
+void GPU_triangle_setup(struct DerivedMesh *dm)
+{
+ if (!gpu_buffer_setup_common(dm, GPU_BUFFER_TRIANGLES))
+ return;
+
+ if (dm->drawObject->triangles->use_vbo) {
+ glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, dm->drawObject->triangles->id);
+ }
+
+ GLStates |= GPU_BUFFER_ELEMENT_STATE;
+}
+
static int GPU_typesize(int type)
{
switch (type) {
@@ -1352,7 +848,7 @@ int GPU_attrib_element_size(GPUAttrib data[], int numdata)
return elementsize;
}
-void GPU_interleaved_attrib_setup(GPUBuffer *buffer, GPUAttrib data[], int numdata)
+void GPU_interleaved_attrib_setup(GPUBuffer *buffer, GPUAttrib data[], int numdata, int element_size)
{
int i;
int elementsize;
@@ -1366,7 +862,10 @@ void GPU_interleaved_attrib_setup(GPUBuffer *buffer, GPUAttrib data[], int numda
else
break;
}
- elementsize = GPU_attrib_element_size(data, numdata);
+ if (element_size == 0)
+ elementsize = GPU_attrib_element_size(data, numdata);
+ else
+ elementsize = element_size;
if (buffer->use_vbo) {
glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffer->id);
@@ -1390,6 +889,18 @@ void GPU_interleaved_attrib_setup(GPUBuffer *buffer, GPUAttrib data[], int numda
attribData[numdata].index = -1;
}
+void GPU_interleaved_attrib_unbind(void)
+{
+ int i;
+ for (i = 0; i < MAX_GPU_ATTRIB_DATA; i++) {
+ if (attribData[i].index != -1) {
+ glDisableVertexAttribArrayARB(attribData[i].index);
+ }
+ else
+ break;
+ }
+ attribData[0].index = -1;
+}
void GPU_buffer_unbind(void)
{
@@ -1492,6 +1003,7 @@ void GPU_buffer_unlock(GPUBuffer *buffer)
}
}
+
/* used for drawing edges */
void GPU_buffer_draw_elements(GPUBuffer *elements, unsigned int mode, int start, int count)
{
@@ -1528,7 +1040,7 @@ typedef struct {
struct GPU_PBVH_Buffers {
/* opengl buffer handles */
- GLuint vert_buf, index_buf;
+ GLuint vert_buf, index_buf, index_buf_fast;
GLenum index_type;
/* mesh pointers in case buffer allocation fails */
@@ -2084,6 +1596,32 @@ static GLuint gpu_get_grid_buffer(int gridsize, GLenum *index_type, unsigned *to
return buffer;
}
+#define FILL_FAST_BUFFER(type_) \
+{ \
+ type_ *buffer; \
+ glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, \
+ sizeof(type_) * 6 * totgrid, NULL, \
+ GL_STATIC_DRAW_ARB); \
+ buffer = glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); \
+ if (buffer) { \
+ int i; \
+ for (i = 0; i < totgrid; i++) { \
+ int currentquad = i * 6; \
+ buffer[currentquad] = i * gridsize * gridsize; \
+ buffer[currentquad + 1] = i * gridsize * gridsize + gridsize - 1; \
+ buffer[currentquad + 2] = (i + 1) * gridsize * gridsize - gridsize; \
+ buffer[currentquad + 3] = (i + 1) * gridsize * gridsize - 1; \
+ buffer[currentquad + 4] = i * gridsize * gridsize + gridsize - 1; \
+ buffer[currentquad + 5] = (i + 1) * gridsize * gridsize - gridsize; \
+ } \
+ glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB); \
+ } \
+ else { \
+ glDeleteBuffersARB(1, &buffers->index_buf_fast); \
+ buffers->index_buf_fast = 0; \
+ } \
+} (void)0
+
GPU_PBVH_Buffers *GPU_build_grid_pbvh_buffers(int *grid_indices, int totgrid,
BLI_bitmap **grid_hidden, int gridsize)
{
@@ -2105,6 +1643,22 @@ GPU_PBVH_Buffers *GPU_build_grid_pbvh_buffers(int *grid_indices, int totgrid,
if (totquad == 0)
return buffers;
+ /* create and fill indices of the fast buffer too */
+ glGenBuffersARB(1, &buffers->index_buf_fast);
+
+ if (buffers->index_buf_fast) {
+ glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, buffers->index_buf_fast);
+
+ if (totgrid * gridsize * gridsize < USHRT_MAX) {
+ FILL_FAST_BUFFER(unsigned short);
+ }
+ else {
+ FILL_FAST_BUFFER(unsigned int);
+ }
+
+ glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
+ }
+
if (totquad == fully_visible_totquad) {
buffers->index_buf = gpu_get_grid_buffer(gridsize, &buffers->index_type, &buffers->tot_quad);
buffers->has_hidden = 0;
@@ -2619,8 +2173,9 @@ static void gpu_draw_buffers_legacy_grids(GPU_PBVH_Buffers *buffers)
}
void GPU_draw_pbvh_buffers(GPU_PBVH_Buffers *buffers, DMSetMaterial setMaterial,
- bool wireframe)
+ bool wireframe, bool fast)
{
+ bool do_fast = fast && buffers->index_buf_fast;
/* sets material from the first face, to solve properly face would need to
* be sorted in buckets by materials */
if (setMaterial) {
@@ -2651,7 +2206,9 @@ void GPU_draw_pbvh_buffers(GPU_PBVH_Buffers *buffers, DMSetMaterial setMaterial,
glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffers->vert_buf);
- if (buffers->index_buf)
+ if (do_fast)
+ glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, buffers->index_buf_fast);
+ else if (buffers->index_buf)
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, buffers->index_buf);
if (wireframe)
@@ -2668,7 +2225,10 @@ void GPU_draw_pbvh_buffers(GPU_PBVH_Buffers *buffers, DMSetMaterial setMaterial,
glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(VertexBufferFormat),
offset + offsetof(VertexBufferFormat, color));
- glDrawElements(GL_TRIANGLES, buffers->tot_quad * 6, buffers->index_type, 0);
+ if (do_fast)
+ glDrawElements(GL_TRIANGLES, buffers->totgrid * 6, buffers->index_type, 0);
+ else
+ glDrawElements(GL_TRIANGLES, buffers->tot_quad * 6, buffers->index_type, 0);
offset += buffers->gridkey.grid_area * sizeof(VertexBufferFormat);
}
@@ -2797,6 +2357,8 @@ void GPU_free_pbvh_buffers(GPU_PBVH_Buffers *buffers)
gpu_pbvh_buffer_free_intern(buffers->vert_buf);
if (buffers->index_buf && (buffers->tot_tri || buffers->has_hidden))
gpu_pbvh_buffer_free_intern(buffers->index_buf);
+ if (buffers->index_buf_fast)
+ gpu_pbvh_buffer_free_intern(buffers->index_buf_fast);
MEM_freeN(buffers);
}