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:
authorAntony Riakiotakis <kalast@gmail.com>2015-07-14 17:48:23 +0300
committerAntony Riakiotakis <kalast@gmail.com>2015-07-14 17:48:23 +0300
commit107e34407d0ae4120cc7a12fdb208986a0b47d8e (patch)
treead19f330d4caa5d60d994b7bec9c1e2067e3bd75 /source/blender/blenkernel
parent1b8b9063f8d086b51f7e2b0ee9ca640903283cb1 (diff)
Display optimizations part 1.
This patch changes the way we draw meshes by introducing indexed drawing. This makes it possible to easily upload and rearrange faces ad lib according to any criteria. Currently we use material sorting but textured sorting and hiding will be added to optimize textured drawing and skip per face testing. It also adds support for vertex buffers for subsurf modifiers (Except from GLSL drawing), making drawing of subsurf much faster without need for bogus modifiers. Tests show that we gain approximately 20-25% performance by that for solid mode drawing with up to 50% gains for material drawing. Textured drawing should also have a small performance gain, but more substantial optimizations are possible there. Reviewers: campbellbarton Differential Revision: https://developer.blender.org/D1406
Diffstat (limited to 'source/blender/blenkernel')
-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
5 files changed, 1433 insertions, 580 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;