Convert MBC_ API to Mesh (instead of derived mesh) and move it to mesh_render
authorDalai Felinto <dfelinto@gmail.com>
Wed, 25 Jan 2017 08:16:29 +0000 (09:16 +0100)
committerDalai Felinto <dfelinto@gmail.com>
Wed, 25 Jan 2017 09:01:48 +0000 (10:01 +0100)
This includes a few fixes in the MBC_ api.

The idea here is for this to be the only interface the render engines
will deal with for the meshes.

If we need to expose special options for sculpting engine we refactor
this accordingly. But for now we are shaping this in a per-case base.

Note:
* We still need to hook up to the depsgraph to force clear/update of
batch_cache when mesh changes

(I'm waiting for Sergey Sharybin's depsgraph update for this though)

* Also ideally we could/should use BMesh directly instead of
DerivedMesh, but this will do for now.

Note 2:
In the end I renamed the `BKE_mesh_render` functions to `static
mesh_render`. We can re-expose them as BKE_* later once we need it.

Reviewers: merwin

Subscribers: fclem

Differential Revision: https://developer.blender.org/D2476

source/blender/blenkernel/BKE_DerivedMesh.h
source/blender/blenkernel/BKE_mesh_render.h [new file with mode: 0644]
source/blender/blenkernel/CMakeLists.txt
source/blender/blenkernel/intern/DerivedMesh.c
source/blender/blenkernel/intern/mesh.c
source/blender/blenkernel/intern/mesh_render.c [new file with mode: 0644]
source/blender/editors/space_view3d/drawobject.c
source/blender/gpu/gawain/batch.h
source/blender/makesdna/DNA_mesh_types.h

index 059f7309cf588b740921edaa2b615da8db739597..784c76bffd320b6da6ccf9c13295390872b1d06e 100644 (file)
@@ -145,10 +145,6 @@ typedef DMDrawOption (*DMSetDrawOptions)(void *userData, int index);
 typedef DMDrawOption (*DMSetDrawOptionsMappedTex)(void *userData, int origindex, int mat_nr);
 typedef DMDrawOption (*DMSetDrawOptionsTex)(struct MTexPoly *mtexpoly, const bool has_vcol, int matnr);
 
-/* Cleanup callback type */
-typedef void (*DMCleanupBatchCache)(void *batchCache);
-void DM_set_batch_cleanup_callback(DMCleanupBatchCache);
-
 typedef enum DMDrawFlag {
        DM_DRAW_USE_COLORS          = (1 << 0),
        DM_DRAW_ALWAYS_SMOOTH       = (1 << 1),
@@ -176,6 +172,8 @@ typedef enum DMDirtyFlag {
 
        /* check this with modifier dependsOnNormals callback to see if normals need recalculation */
        DM_DIRTY_NORMALS = 1 << 2,
+
+       DM_MESH_BATCH_CACHE = 1 << 3,
 }  DMDirtyFlag;
 
 typedef struct DerivedMesh DerivedMesh;
@@ -187,7 +185,6 @@ struct DerivedMesh {
        int deformedOnly; /* set by modifier stack if only deformed from original */
        BVHCache *bvhCache;
        struct GPUDrawObject *drawObject;
-       void *batchCache;
        DerivedMeshType type;
        float auto_bump_scale;
        DMDirtyFlag dirty;
diff --git a/source/blender/blenkernel/BKE_mesh_render.h b/source/blender/blenkernel/BKE_mesh_render.h
new file mode 100644 (file)
index 0000000..8a2b3f9
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2017 by Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation, Mike Erwin, Dalai Felinto
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef __BKE_MESH_RENDER_H__
+#define __BKE_MESH_RENDER_H__
+
+/** \file BKE_mesh_render.h
+ *  \ingroup bke
+ */
+
+struct Batch;
+struct Mesh;
+
+void BKE_mesh_batch_cache_free(struct Mesh *me);
+struct Batch *BKE_mesh_batch_cache_get_all_edges(struct Mesh *me);
+struct Batch *BKE_mesh_batch_cache_get_all_triangles(struct Mesh *me);
+struct Batch *BKE_mesh_batch_cache_get_all_verts(struct Mesh *me);
+struct Batch *BKE_mesh_batch_cache_get_fancy_edges(struct Mesh *me);
+struct Batch *BKE_mesh_batch_cache_get_overlay_edges(struct Mesh *me);
+
+#endif /* __BKE_MESH_RENDER_H__ */
index 2ccbed58b04c1fe23da9236dd3ce8d209aabc717..f3bab55b47daf88c82f398038a26b192f804b168 100644 (file)
@@ -133,6 +133,7 @@ set(SRC
        intern/mesh_evaluate.c
        intern/mesh_mapping.c
        intern/mesh_remap.c
+       intern/mesh_render.c
        intern/mesh_validate.c
        intern/modifier.c
        intern/modifiers_bmesh.c
@@ -257,6 +258,7 @@ set(SRC
        BKE_mesh.h
        BKE_mesh_mapping.h
        BKE_mesh_remap.h
+       BKE_mesh_render.h
        BKE_modifier.h
        BKE_movieclip.h
        BKE_multires.h
index fb0087aefac1e1aa32ad08b9094b86da2862a3f5..e0bbe345fc452aba915746b999e747bcce182429 100644 (file)
@@ -260,12 +260,6 @@ static CustomData *dm_getPolyCData(DerivedMesh *dm)
        return &dm->polyData;
 }
 
-static DMCleanupBatchCache cleanupBatchCache = NULL;
-void DM_set_batch_cleanup_callback(DMCleanupBatchCache func)
-{
-       cleanupBatchCache = func;
-}
-
 /**
  * Utility function to initialize a DerivedMesh's function pointers to
  * the default implementation (for those functions which have a default)
@@ -324,8 +318,6 @@ void DM_init(
 
        DM_init_funcs(dm);
 
-       dm->batchCache = NULL; /* necessary? dm->drawObject is not set to NULL yet it works fine */
-
        dm->needsFree = 1;
        dm->auto_bump_scale = -1.0f;
        dm->dirty = 0;
@@ -385,10 +377,7 @@ int DM_release(DerivedMesh *dm)
        if (dm->needsFree) {
                bvhcache_free(&dm->bvhCache);
                GPU_drawobject_free(dm);
-               if (dm->batchCache && cleanupBatchCache) {
-                       cleanupBatchCache(dm->batchCache);
-                       dm->batchCache = NULL;
-               }
+
                CustomData_free(&dm->vertData, dm->numVertData);
                CustomData_free(&dm->edgeData, dm->numEdgeData);
                CustomData_free(&dm->faceData, dm->numTessFaceData);
index af02e02b017ec0f44db27aed5a1e691fe1ddfd25..134173580aed09f7710f68b235d59862b34228f8 100644 (file)
@@ -48,6 +48,7 @@
 #include "BKE_DerivedMesh.h"
 #include "BKE_global.h"
 #include "BKE_mesh.h"
+#include "BKE_mesh_render.h"
 #include "BKE_displist.h"
 #include "BKE_library.h"
 #include "BKE_library_query.h"
@@ -435,6 +436,8 @@ void BKE_mesh_free(Mesh *me)
 {
        BKE_animdata_free(&me->id, false);
 
+       BKE_mesh_batch_cache_free(me);
+
        CustomData_free(&me->vdata, me->totvert);
        CustomData_free(&me->edata, me->totedge);
        CustomData_free(&me->fdata, me->totface);
@@ -522,6 +525,7 @@ Mesh *BKE_mesh_copy(Main *bmain, Mesh *me)
        BKE_mesh_update_customdata_pointers(men, do_tessface);
 
        men->edit_btmesh = NULL;
+       men->batch_cache = NULL;
 
        men->mselect = MEM_dupallocN(men->mselect);
        men->bb = MEM_dupallocN(men->bb);
diff --git a/source/blender/blenkernel/intern/mesh_render.c b/source/blender/blenkernel/intern/mesh_render.c
new file mode 100644 (file)
index 0000000..f90783a
--- /dev/null
@@ -0,0 +1,619 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2017 by Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation, Mike Erwin, Dalai Felinto
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenkernel/intern/mesh_render.c
+ *  \ingroup bke
+ *
+ * \brief Mesh API for render engines
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+
+#include "BKE_customdata.h"
+#include "BKE_depsgraph.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_editmesh.h"
+#include "BKE_mesh.h"
+#include "BKE_mesh_render.h"
+
+#include "GPU_batch.h"
+
+/* ---------------------------------------------------------------------- */
+/* Mesh Interface */
+
+#define MESH_RENDER_FUNCTION(func_name)     \
+       if (me->edit_btmesh) {                  \
+           return mesh_bmesh_##func_name(me);  \
+       }                                       \
+       else {                                  \
+           return mesh_struct_##func_name(me); \
+       }
+
+
+/* Mesh Implementation */
+
+static int mesh_struct_get_num_edges(Mesh *me)
+{
+       return me->totedge;
+}
+
+static int mesh_struct_get_num_verts(Mesh *me)
+{
+       return me->totvert;
+}
+
+static int mesh_struct_get_num_faces(Mesh *me)
+{
+       BKE_mesh_tessface_ensure(me);
+       return me->totface;
+}
+
+static int mesh_struct_get_num_polys(Mesh *me)
+{
+       return me->totpoly;
+}
+
+static MEdge *mesh_struct_get_array_edge(Mesh *me)
+{
+       return CustomData_get_layer(&me->edata, CD_MEDGE);
+}
+
+static MFace *mesh_struct_get_array_face(Mesh *me)
+{
+       BKE_mesh_tessface_ensure(me);
+       return CustomData_get_layer(&me->fdata, CD_MFACE);
+}
+
+static MLoop *mesh_struct_get_array_loop(Mesh *me)
+{
+       return me->mloop;
+}
+
+static MPoly *mesh_struct_get_array_poly(Mesh *me)
+{
+       return me->mpoly;
+}
+
+static MVert *mesh_struct_get_array_vert(Mesh *me)
+{
+       return CustomData_get_layer(&me->vdata, CD_MVERT);
+}
+
+/* BMesh Implementation */
+
+/* NOTE: we may want to get rid of Derived Mesh and
+ * access BMesh directly */
+
+static int mesh_bmesh_get_num_verts(Mesh *me)
+{
+       BMEditMesh *bm = me->edit_btmesh;
+       DerivedMesh *dm = bm->derivedFinal;
+       return dm->getNumVerts(dm);
+}
+
+static int mesh_bmesh_get_num_edges(Mesh *me)
+{
+       BMEditMesh *bm = me->edit_btmesh;
+       DerivedMesh *dm = bm->derivedFinal;
+       return dm->getNumEdges(dm);
+}
+
+static int mesh_bmesh_get_num_faces(Mesh *me)
+{
+       BMEditMesh *bm = me->edit_btmesh;
+       DerivedMesh *dm = bm->derivedFinal;
+       return dm->getNumTessFaces(dm);
+}
+
+static int mesh_bmesh_get_num_polys(Mesh *me)
+{
+       BMEditMesh *bm = me->edit_btmesh;
+       DerivedMesh *dm = bm->derivedFinal;
+       return dm->getNumPolys(dm);
+}
+
+static MEdge *mesh_bmesh_get_array_edge(Mesh *me)
+{
+       BMEditMesh *bm = me->edit_btmesh;
+       DerivedMesh *dm = bm->derivedFinal;
+       return dm->getEdgeArray(dm);
+}
+
+static MFace *mesh_bmesh_get_array_face(Mesh *me)
+{
+       BMEditMesh *bm = me->edit_btmesh;
+       DerivedMesh *dm = bm->derivedFinal;
+       return dm->getTessFaceArray(dm);
+}
+
+static MLoop *mesh_bmesh_get_array_loop(Mesh *me)
+{
+       BMEditMesh *bm = me->edit_btmesh;
+       DerivedMesh *dm = bm->derivedFinal;
+       return dm->getLoopArray(dm);
+}
+
+static MPoly *mesh_bmesh_get_array_poly(Mesh *me)
+{
+       BMEditMesh *bm = me->edit_btmesh;
+       DerivedMesh *dm = bm->derivedFinal;
+       return dm->getPolyArray(dm);
+}
+
+static MVert *mesh_bmesh_get_array_vert(Mesh *me)
+{
+       BMEditMesh *bm = me->edit_btmesh;
+       DerivedMesh *dm = bm->derivedFinal;
+       return dm->getVertArray(dm);
+}
+
+/* Mesh API */
+
+static int mesh_render_get_num_edges(Mesh *me)
+{
+       MESH_RENDER_FUNCTION(get_num_edges);
+}
+
+static int mesh_render_get_num_faces(Mesh *me)
+{
+       MESH_RENDER_FUNCTION(get_num_faces);
+}
+
+static int mesh_render_get_num_polys(Mesh *me)
+{
+       MESH_RENDER_FUNCTION(get_num_polys);
+}
+
+static int mesh_render_get_num_verts(Mesh *me)
+{
+       MESH_RENDER_FUNCTION(get_num_verts);
+}
+
+static MEdge *mesh_render_get_array_edge(Mesh *me)
+{
+       MESH_RENDER_FUNCTION(get_array_edge);
+}
+
+static MFace *mesh_render_get_array_face(Mesh *me)
+{
+       MESH_RENDER_FUNCTION(get_array_face);
+}
+
+static MLoop *mesh_render_get_array_loop(Mesh *me)
+{
+       MESH_RENDER_FUNCTION(get_array_loop);
+}
+
+static MPoly *mesh_render_get_array_poly(Mesh *me)
+{
+       MESH_RENDER_FUNCTION(get_array_poly);
+}
+
+static MVert *mesh_render_get_array_vert(Mesh *me)
+{
+       MESH_RENDER_FUNCTION(get_array_vert);
+}
+
+/* ---------------------------------------------------------------------- */
+/* Mesh Batch Cache */
+
+typedef struct MeshBatchCache {
+       VertexBuffer *pos_in_order;
+       ElementList *edges_in_order;
+       ElementList *triangles_in_order;
+
+       Batch *all_verts;
+       Batch *all_edges;
+       Batch *all_triangles;
+
+       Batch *fancy_edges; /* owns its vertex buffer (not shared) */
+       Batch *overlay_edges; /* owns its vertex buffer */
+
+       /* TODO: settings, before DEPSGRAPH update */
+       int tot_edges;
+       int tot_faces;
+       int tot_polys;
+       int tot_verts;
+       bool is_editmode;
+} MeshBatchCache;
+
+static bool mesh_batch_cache_valid(Mesh *me)
+{
+       MeshBatchCache *cache = me->batch_cache;
+
+       if (cache == NULL) {
+               return false;
+       }
+
+       if (cache->is_editmode != (me->edit_btmesh != NULL)) {
+               return false;
+       }
+
+       if (cache->is_editmode) {
+               DerivedMesh *dm = me->edit_btmesh->derivedFinal;
+               if ((dm->dirty & DM_MESH_BATCH_CACHE) == 0) {
+                       return false;
+               }
+       }
+
+       /* TODO: temporary check, waiting for depsgraph update */
+       if ((cache->tot_edges != mesh_render_get_num_edges(me)) ||
+           (cache->tot_faces != mesh_render_get_num_faces(me)) ||
+           (cache->tot_polys != mesh_render_get_num_polys(me)) ||
+           (cache->tot_verts != mesh_render_get_num_verts(me)))
+       {
+               return false;
+       }
+
+       return true;
+}
+
+static void mesh_batch_cache_init(Mesh *me)
+{
+       MeshBatchCache *cache = me->batch_cache;
+       cache->is_editmode = me->edit_btmesh != NULL;
+
+       cache->tot_edges = mesh_render_get_num_edges(me);
+       cache->tot_faces = mesh_render_get_num_faces(me);
+       cache->tot_polys = mesh_render_get_num_polys(me);
+       cache->tot_verts = mesh_render_get_num_verts(me);
+
+       if (cache->is_editmode) {
+               DerivedMesh *dm = me->edit_btmesh->derivedFinal;
+               dm->dirty |= DM_MESH_BATCH_CACHE;
+       }
+}
+
+static MeshBatchCache *mesh_batch_cache_get(Mesh *me)
+{
+       if (!mesh_batch_cache_valid(me)) {
+               BKE_mesh_batch_cache_free(me);
+               me->batch_cache = MEM_callocN(sizeof(MeshBatchCache), "MeshBatchCache");
+               mesh_batch_cache_init(me);
+       }
+       return me->batch_cache;
+}
+
+static VertexBuffer *mesh_batch_cache_get_pos_in_order(Mesh *me)
+{
+       MeshBatchCache *cache = mesh_batch_cache_get(me);
+
+       if (cache->pos_in_order == NULL) {
+               static VertexFormat format = { 0 };
+               static unsigned pos_id;
+               if (format.attrib_ct == 0) {
+                       /* initialize vertex format */
+                       pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+               }
+
+               const int vertex_ct = mesh_render_get_num_verts(me);
+               const MVert *verts = mesh_render_get_array_vert(me);
+
+               cache->pos_in_order = VertexBuffer_create_with_format(&format);
+               VertexBuffer_allocate_data(cache->pos_in_order, vertex_ct);
+#if 0
+               const unsigned stride = (verts + 1) - verts; /* or sizeof(MVert) */
+               fillAttribStride(cache->pos_in_order, pos_id, stride, &verts[0].co);
+#else
+               for (int i = 0; i < vertex_ct; ++i) {
+                       setAttrib(cache->pos_in_order, pos_id, i, &verts[i].co);
+               }
+#endif
+       }
+
+       return cache->pos_in_order;
+}
+
+static ElementList *mesh_batch_cache_get_edges_in_order(Mesh *me)
+{
+       MeshBatchCache *cache = mesh_batch_cache_get(me);
+
+       if (cache->edges_in_order == NULL) {
+               const int vertex_ct = mesh_render_get_num_verts(me);
+               const int edge_ct = mesh_render_get_num_edges(me);
+               const MEdge *edges = mesh_render_get_array_edge(me);
+
+               ElementListBuilder elb;
+               ElementListBuilder_init(&elb, GL_LINES, edge_ct, vertex_ct);
+               for (int i = 0; i < edge_ct; ++i) {
+                       const MEdge *edge = edges + i;
+                       add_line_vertices(&elb, edge->v1, edge->v2);
+               }
+               cache->edges_in_order = ElementList_build(&elb);
+       }
+
+       return cache->edges_in_order;
+}
+
+static ElementList *mesh_batch_cache_get_triangles_in_order(Mesh *me)
+{
+       MeshBatchCache *cache = mesh_batch_cache_get(me);
+
+       if (cache->triangles_in_order == NULL) {
+               const int vertex_ct = mesh_render_get_num_verts(me);
+               const int tessface_ct = mesh_render_get_num_faces(me);
+               MFace *tessfaces = mesh_render_get_array_face(me);
+
+               ElementListBuilder elb;
+               ElementListBuilder_init(&elb, GL_TRIANGLES, tessface_ct * 2, vertex_ct); /* up to 2 triangles per tessface */
+               for (int i = 0; i < tessface_ct; ++i) {
+                       const MFace *tess = tessfaces + i;
+                       add_triangle_vertices(&elb, tess->v1, tess->v2, tess->v3);
+
+                       if (tess->v4) {
+                               add_triangle_vertices(&elb, tess->v1, tess->v3, tess->v4);
+                       }
+               }
+               cache->triangles_in_order = ElementList_build(&elb);
+       }
+
+       /* NOTE: we are reallocating, it would be interesting to reallocating the memory once we
+        * know the exactly triangle count (like in BKE_mesh_batch_cache_get_overlay_edges) */
+
+       return cache->triangles_in_order;
+}
+
+void BKE_mesh_batch_cache_free(Mesh *me)
+{
+       MeshBatchCache *cache = me->batch_cache;
+       if (!cache) {
+               return;
+       }
+
+       if (cache->all_verts) Batch_discard(cache->all_verts);
+       if (cache->all_edges) Batch_discard(cache->all_edges);
+       if (cache->all_triangles) Batch_discard(cache->all_triangles);
+
+       if (cache->pos_in_order) VertexBuffer_discard(cache->pos_in_order);
+       if (cache->edges_in_order) ElementList_discard(cache->edges_in_order);
+       if (cache->triangles_in_order) ElementList_discard(cache->triangles_in_order);
+
+       if (cache->fancy_edges) {
+               Batch_discard_all(cache->fancy_edges);
+       }
+
+       if (cache->overlay_edges) {
+               Batch_discard_all(cache->overlay_edges);
+       }
+
+       MEM_freeN(cache);
+       me->batch_cache = NULL;
+}
+
+Batch *BKE_mesh_batch_cache_get_all_edges(Mesh *me)
+{
+       MeshBatchCache *cache = mesh_batch_cache_get(me);
+
+       if (cache->all_edges == NULL) {
+               /* create batch from Mesh */
+               cache->all_edges = Batch_create(GL_LINES, mesh_batch_cache_get_pos_in_order(me), mesh_batch_cache_get_edges_in_order(me));
+       }
+
+       return cache->all_edges;
+}
+
+Batch *BKE_mesh_batch_cache_get_all_triangles(Mesh *me)
+{
+       MeshBatchCache *cache = mesh_batch_cache_get(me);
+
+       if (cache->all_triangles == NULL) {
+               /* create batch from DM */
+               cache->all_triangles = Batch_create(GL_TRIANGLES, mesh_batch_cache_get_pos_in_order(me), mesh_batch_cache_get_triangles_in_order(me));
+       }
+
+       return cache->all_triangles;
+}
+
+Batch *BKE_mesh_batch_cache_get_all_verts(Mesh *me)
+{
+       MeshBatchCache *cache = mesh_batch_cache_get(me);
+
+       if (cache->all_verts == NULL) {
+               /* create batch from DM */
+               cache->all_verts = Batch_create(GL_POINTS, mesh_batch_cache_get_pos_in_order(me), NULL);
+               Batch_set_builtin_program(cache->all_verts, GPU_SHADER_3D_POINT_FIXED_SIZE_UNIFORM_COLOR);
+       }
+
+       return cache->all_verts;
+}
+
+Batch *BKE_mesh_batch_cache_get_fancy_edges(Mesh *me)
+{
+       MeshBatchCache *cache = mesh_batch_cache_get(me);
+
+       if (cache->fancy_edges == NULL) {
+               /* create batch from DM */
+               static VertexFormat format = { 0 };
+               static unsigned pos_id, n1_id, n2_id;
+               if (format.attrib_ct == 0) {
+                       /* initialize vertex format */
+                       pos_id = add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
+
+#if USE_10_10_10 /* takes 1/3 the space */
+                       n1_id = add_attrib(&format, "N1", COMP_I10, 3, NORMALIZE_INT_TO_FLOAT);
+                       n2_id = add_attrib(&format, "N2", COMP_I10, 3, NORMALIZE_INT_TO_FLOAT);
+#else
+                       n1_id = add_attrib(&format, "N1", COMP_F32, 3, KEEP_FLOAT);
+                       n2_id = add_attrib(&format, "N2", COMP_F32, 3, KEEP_FLOAT);
+#endif
+               }
+               VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
+
+               const MVert *verts = mesh_render_get_array_vert(me);
+               const MEdge *edges = mesh_render_get_array_edge(me);
+               const MPoly *polys = mesh_render_get_array_poly(me);
+               const MLoop *loops = mesh_render_get_array_loop(me);
+               const int edge_ct = mesh_render_get_num_edges(me);
+               const int poly_ct = mesh_render_get_num_polys(me);
+
+               /* need normal of each face, and which faces are adjacent to each edge */
+               typedef struct {
+                       int count;
+                       int face_index[2];
+               } AdjacentFaces;
+
+               float (*face_normal)[3] = MEM_mallocN(poly_ct * 3 * sizeof(float), "face_normal");
+               AdjacentFaces *adj_faces = MEM_callocN(edge_ct * sizeof(AdjacentFaces), "adj_faces");
+
+               for (int i = 0; i < poly_ct; ++i) {
+                       const MPoly *poly = polys + i;
+
+                       BKE_mesh_calc_poly_normal(poly, loops + poly->loopstart, verts, face_normal[i]);
+
+                       for (int j = poly->loopstart; j < (poly->loopstart + poly->totloop); ++j) {
+                               AdjacentFaces *adj = adj_faces + loops[j].e;
+                               if (adj->count < 2)
+                                       adj->face_index[adj->count] = i;
+                               adj->count++;
+                       }
+               }
+
+               const int vertex_ct = edge_ct * 2; /* these are GL_LINE verts, not mesh verts */
+               VertexBuffer_allocate_data(vbo, vertex_ct);
+               for (int i = 0; i < edge_ct; ++i) {
+                       const MEdge *edge = edges + i;
+                       const AdjacentFaces *adj = adj_faces + i;
+
+#if USE_10_10_10
+                       PackedNormal n1value = { .x = 0, .y = 0, .z = +511 };
+                       PackedNormal n2value = { .x = 0, .y = 0, .z = -511 };
+
+                       if (adj->count == 2) {
+                               n1value = convert_i10_v3(face_normal[adj->face_index[0]]);
+                               n2value = convert_i10_v3(face_normal[adj->face_index[1]]);
+                       }
+
+                       const PackedNormal *n1 = &n1value;
+                       const PackedNormal *n2 = &n2value;
+#else
+                       const float dummy1[3] = { 0.0f, 0.0f, +1.0f };
+                       const float dummy2[3] = { 0.0f, 0.0f, -1.0f };
+
+                       const float *n1 = (adj->count == 2) ? face_normal[adj->face_index[0]] : dummy1;
+                       const float *n2 = (adj->count == 2) ? face_normal[adj->face_index[1]] : dummy2;
+#endif
+
+                       setAttrib(vbo, pos_id, 2 * i, &verts[edge->v1].co);
+                       setAttrib(vbo, n1_id, 2 * i, n1);
+                       setAttrib(vbo, n2_id, 2 * i, n2);
+
+                       setAttrib(vbo, pos_id, 2 * i + 1, &verts[edge->v2].co);
+                       setAttrib(vbo, n1_id, 2 * i + 1, n1);
+                       setAttrib(vbo, n2_id, 2 * i + 1, n2);
+               }
+
+               MEM_freeN(adj_faces);
+               MEM_freeN(face_normal);
+
+               cache->fancy_edges = Batch_create(GL_LINES, vbo, NULL);
+       }
+
+       return cache->fancy_edges;
+}
+
+static bool edge_is_real(const MEdge *edges, int edge_ct, int v1, int v2)
+{
+       /* TODO: same thing, except not ridiculously slow */
+
+       for (int e = 0; e < edge_ct; ++e) {
+               const MEdge *edge = edges + e;
+               if ((edge->v1 == v1 && edge->v2 == v2) || (edge->v1 == v2 && edge->v2 == v1)) {
+                       return true;
+               }
+       }
+
+       return false;
+}
+
+static void add_overlay_tri(
+        VertexBuffer *vbo, unsigned pos_id, unsigned edgeMod_id, const MVert *verts,
+        const MEdge *edges, int edge_ct, int v1, int v2, int v3, int base_vert_idx)
+{
+       const float edgeMods[2] = { 0.0f, 1.0f };
+
+       const float *pos = verts[v1].co;
+       setAttrib(vbo, pos_id, base_vert_idx + 0, pos);
+       setAttrib(vbo, edgeMod_id, base_vert_idx + 0, edgeMods + (edge_is_real(edges, edge_ct, v2, v3) ? 1 : 0));
+
+       pos = verts[v2].co;
+       setAttrib(vbo, pos_id, base_vert_idx + 1, pos);
+       setAttrib(vbo, edgeMod_id, base_vert_idx + 1, edgeMods + (edge_is_real(edges, edge_ct, v3, v1) ? 1 : 0));
+
+       pos = verts[v3].co;
+       setAttrib(vbo, pos_id, base_vert_idx + 2, pos);
+       setAttrib(vbo, edgeMod_id, base_vert_idx + 2, edgeMods + (edge_is_real(edges, edge_ct, v1, v2) ? 1 : 0));
+}
+
+Batch *BKE_mesh_batch_cache_get_overlay_edges(Mesh *me)
+{
+       MeshBatchCache *cache = mesh_batch_cache_get(me);
+
+       if (cache->overlay_edges == NULL) {
+               /* create batch from DM */
+               static VertexFormat format = { 0 };
+               static unsigned pos_id, edgeMod_id;
+
+               if (format.attrib_ct == 0) {
+                       /* initialize vertex format */
+                       pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+                       edgeMod_id = add_attrib(&format, "edgeWidthModulator", GL_FLOAT, 1, KEEP_FLOAT);
+               }
+               VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
+
+               const int edge_ct = mesh_render_get_num_edges(me);
+               const int tessface_ct = mesh_render_get_num_faces(me);
+               const MVert *verts = mesh_render_get_array_vert(me);
+               const MEdge *edges = mesh_render_get_array_edge(me);
+               const MFace *tessfaces = mesh_render_get_array_face(me);
+
+               VertexBuffer_allocate_data(vbo, tessface_ct * 6); /* up to 2 triangles per tessface */
+
+               int gpu_vert_idx = 0;
+               for (int i = 0; i < tessface_ct; ++i) {
+                       const MFace *tess = tessfaces + i;
+                       add_overlay_tri(vbo, pos_id, edgeMod_id, verts, edges, edge_ct, tess->v1, tess->v2, tess->v3, gpu_vert_idx);
+                       gpu_vert_idx += 3;
+                       /* tessface can be triangle or quad */
+                       if (tess->v4) {
+                               add_overlay_tri(vbo, pos_id, edgeMod_id, verts, edges, edge_ct, tess->v3, tess->v2, tess->v4, gpu_vert_idx);
+                               gpu_vert_idx += 3;
+                       }
+               }
+
+               /* in some cases all the faces are quad, so no need to reallocate */
+               if (vbo->vertex_ct != gpu_vert_idx) {
+                       VertexBuffer_resize_data(vbo, gpu_vert_idx);
+               }
+
+               cache->overlay_edges = Batch_create(GL_TRIANGLES, vbo, NULL);
+       }
+
+       return cache->overlay_edges;
+}
+
+#undef MESH_RENDER_FUNCTION
index b00a7346e59c9dfb5a5b3af5fc509bcd144c968b..1692d3a7372e891b71bfcc693adc5c29ffe8b1d6 100644 (file)
@@ -65,6 +65,7 @@
 #include "BKE_lattice.h"
 #include "BKE_main.h"
 #include "BKE_mesh.h"
+#include "BKE_mesh_render.h"
 #include "BKE_material.h"
 #include "BKE_mball.h"
 #include "BKE_modifier.h"
@@ -214,340 +215,6 @@ typedef struct drawBMSelect_userData {
        bool select;
 } drawBMSelect_userData;
 
-typedef struct {
-       VertexBuffer *pos_in_order;
-       ElementList *edges_in_order;
-       ElementList *triangles_in_order;
-
-       Batch *all_verts;
-       Batch *all_edges;
-       Batch *all_triangles;
-
-       Batch *fancy_edges; /* owns its vertex buffer (not shared) */
-       Batch *overlay_edges; /* owns its vertex buffer */
-} MeshBatchCache;
-
-static void MBC_discard(MeshBatchCache *cache)
-{
-       if (cache->all_verts) Batch_discard(cache->all_verts);
-       if (cache->all_edges) Batch_discard(cache->all_edges);
-       if (cache->all_triangles) Batch_discard(cache->all_triangles);
-
-       if (cache->pos_in_order) VertexBuffer_discard(cache->pos_in_order);
-       if (cache->edges_in_order) ElementList_discard(cache->edges_in_order);
-       if (cache->triangles_in_order) ElementList_discard(cache->triangles_in_order);
-
-       if (cache->fancy_edges) {
-               Batch_discard_all(cache->fancy_edges);
-       }
-
-       if (cache->overlay_edges) {
-               Batch_discard_all(cache->overlay_edges);
-       }
-
-       MEM_freeN(cache);
-}
-
-static MeshBatchCache *MBC_get(DerivedMesh *dm)
-{
-       if (dm->batchCache == NULL) {
-               /* create cache */
-               dm->batchCache = MEM_callocN(sizeof(MeshBatchCache), "MeshBatchCache");
-               /* init everything to 0 is ok for now */
-
-
-               /* tell DerivedMesh how to clean up these caches (just once) */
-               /* TODO: find a better place for this w/out exposing internals to DM */
-               /* TODO (long term): replace DM with something less messy */
-               static bool first = true;
-               if (first) {
-                       DM_set_batch_cleanup_callback((DMCleanupBatchCache)MBC_discard);
-                       first = false;
-               }
-       }
-
-       return dm->batchCache;
-}
-
-static VertexBuffer *MBC_get_pos_in_order(DerivedMesh *dm)
-{
-       MeshBatchCache *cache = MBC_get(dm);
-
-       if (cache->pos_in_order == NULL) {
-               static VertexFormat format = { 0 };
-               static unsigned pos_id;
-               if (format.attrib_ct == 0) {
-                       /* initialize vertex format */
-                       pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
-               }
-
-               const int vertex_ct = dm->getNumVerts(dm);
-               const MVert *verts = dm->getVertArray(dm);
-               const unsigned stride = (verts + 1) - verts; /* or sizeof(MVert) */
-
-               cache->pos_in_order = VertexBuffer_create_with_format(&format);
-               VertexBuffer_allocate_data(cache->pos_in_order, vertex_ct);
-#if 0
-               fillAttribStride(cache->pos_in_order, pos_id, stride, &verts[0].co);
-#else
-               for (int i = 0; i < vertex_ct; ++i) {
-                       setAttrib(cache->pos_in_order, pos_id, i, &verts[i].co);
-               }
-#endif
-       }
-
-       return cache->pos_in_order;
-}
-
-static Batch *MBC_get_all_verts(DerivedMesh *dm)
-{
-       MeshBatchCache *cache = MBC_get(dm);
-
-       if (cache->all_verts == NULL) {
-               /* create batch from DM */
-               cache->all_verts = Batch_create(GL_POINTS, MBC_get_pos_in_order(dm), NULL);
-               Batch_set_builtin_program(cache->all_verts, GPU_SHADER_3D_POINT_FIXED_SIZE_UNIFORM_COLOR);
-       }
-
-       return cache->all_verts;
-}
-
-static ElementList *MBC_get_edges_in_order(DerivedMesh *dm)
-{
-       MeshBatchCache *cache = MBC_get(dm);
-
-       if (cache->edges_in_order == NULL) {
-               const int vertex_ct = dm->getNumVerts(dm);
-               const int edge_ct = dm->getNumEdges(dm);
-               const MEdge *edges = dm->getEdgeArray(dm);
-               ElementListBuilder elb;
-               ElementListBuilder_init(&elb, GL_LINES, edge_ct, vertex_ct);
-               for (int i = 0; i < edge_ct; ++i) {
-                       const MEdge *edge = edges + i;
-                       add_line_vertices(&elb, edge->v1, edge->v2);
-               }
-               cache->edges_in_order = ElementList_build(&elb);
-       }
-
-       return cache->edges_in_order;
-}
-
-static ElementList *MBC_get_triangles_in_order(DerivedMesh *dm)
-{
-       MeshBatchCache *cache = MBC_get(dm);
-
-       if (cache->triangles_in_order == NULL) {
-               const int vertex_ct = dm->getNumVerts(dm);
-               const int tessface_ct = dm->getNumTessFaces(dm);
-               const MFace *tessfaces = dm->getTessFaceArray(dm);
-               ElementListBuilder elb;
-               ElementListBuilder_init(&elb, GL_TRIANGLES, tessface_ct, vertex_ct);
-               for (int i = 0; i < tessface_ct; ++i) {
-                       const MFace *tess = tessfaces + i;
-                       add_triangle_vertices(&elb, tess->v1, tess->v2, tess->v3);
-                       /* tessface can be triangle or quad */
-                       if (tess->v4) {
-                               add_triangle_vertices(&elb, tess->v3, tess->v2, tess->v4);
-                       }
-               }
-               cache->triangles_in_order = ElementList_build(&elb);
-       }
-
-       return cache->triangles_in_order;
-}
-
-static Batch *MBC_get_all_edges(DerivedMesh *dm)
-{
-       MeshBatchCache *cache = MBC_get(dm);
-
-       if (cache->all_edges == NULL) {
-               /* create batch from DM */
-               cache->all_edges = Batch_create(GL_LINES, MBC_get_pos_in_order(dm), MBC_get_edges_in_order(dm));
-       }
-
-       return cache->all_edges;
-}
-
-static Batch *MBC_get_all_triangles(DerivedMesh *dm)
-{
-       MeshBatchCache *cache = MBC_get(dm);
-
-       if (cache->all_triangles == NULL) {
-               /* create batch from DM */
-               cache->all_triangles = Batch_create(GL_TRIANGLES, MBC_get_pos_in_order(dm), MBC_get_triangles_in_order(dm));
-       }
-
-       return cache->all_triangles;
-}
-
-static Batch *MBC_get_fancy_edges(DerivedMesh *dm)
-{
-       MeshBatchCache *cache = MBC_get(dm);
-
-       if (cache->fancy_edges == NULL) {
-               /* create batch from DM */
-               static VertexFormat format = { 0 };
-               static unsigned pos_id, n1_id, n2_id;
-               if (format.attrib_ct == 0) {
-                       /* initialize vertex format */
-                       pos_id = add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
-
-#if USE_10_10_10 /* takes 1/3 the space */
-                       n1_id = add_attrib(&format, "N1", COMP_I10, 3, NORMALIZE_INT_TO_FLOAT);
-                       n2_id = add_attrib(&format, "N2", COMP_I10, 3, NORMALIZE_INT_TO_FLOAT);
-#else
-                       n1_id = add_attrib(&format, "N1", COMP_F32, 3, KEEP_FLOAT);
-                       n2_id = add_attrib(&format, "N2", COMP_F32, 3, KEEP_FLOAT);
-#endif
-               }
-               VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
-
-               const MVert *verts = dm->getVertArray(dm);
-               const MEdge *edges = dm->getEdgeArray(dm);
-               const MPoly *polys = dm->getPolyArray(dm);
-               const MLoop *loops = dm->getLoopArray(dm);
-               const int edge_ct = dm->getNumEdges(dm);
-               const int poly_ct = dm->getNumPolys(dm);
-
-               /* need normal of each face, and which faces are adjacent to each edge */
-               typedef struct {
-                       int count;
-                       int face_index[2];
-               } AdjacentFaces;
-
-               float (*face_normal)[3] = MEM_mallocN(poly_ct * 3 * sizeof(float), "face_normal");
-               AdjacentFaces *adj_faces = MEM_callocN(edge_ct * sizeof(AdjacentFaces), "adj_faces");
-
-               for (int i = 0; i < poly_ct; ++i) {
-                       const MPoly *poly = polys + i;
-
-                       BKE_mesh_calc_poly_normal(poly, loops + poly->loopstart, verts, face_normal[i]);
-
-                       for (int j = poly->loopstart; j < (poly->loopstart + poly->totloop); ++j) {
-                               AdjacentFaces *adj = adj_faces + loops[j].e;
-                               if (adj->count < 2)
-                                       adj->face_index[adj->count] = i;
-                               adj->count++;
-                       }
-               }
-
-               const int vertex_ct = edge_ct * 2; /* these are GL_LINE verts, not mesh verts */
-               VertexBuffer_allocate_data(vbo, vertex_ct);
-               for (int i = 0; i < edge_ct; ++i) {
-                       const MEdge *edge = edges + i;
-                       const AdjacentFaces *adj = adj_faces + i;
-
-#if USE_10_10_10
-                       PackedNormal n1value = { .x = 0, .y = 0, .z = +511 };
-                       PackedNormal n2value = { .x = 0, .y = 0, .z = -511 };
-
-                       if (adj->count == 2) {
-                               n1value = convert_i10_v3(face_normal[adj->face_index[0]]);
-                               n2value = convert_i10_v3(face_normal[adj->face_index[1]]);
-                       }
-
-                       const PackedNormal *n1 = &n1value;
-                       const PackedNormal *n2 = &n2value;
-#else
-                       const float dummy1[3] = { 0.0f, 0.0f, +1.0f };
-                       const float dummy2[3] = { 0.0f, 0.0f, -1.0f };
-
-                       const float *n1 = (adj->count == 2) ? face_normal[adj->face_index[0]] : dummy1;
-                       const float *n2 = (adj->count == 2) ? face_normal[adj->face_index[1]] : dummy2;
-#endif
-
-                       setAttrib(vbo, pos_id, 2 * i, &verts[edge->v1].co);
-                       setAttrib(vbo, n1_id, 2 * i, n1);
-                       setAttrib(vbo, n2_id, 2 * i, n2);
-
-                       setAttrib(vbo, pos_id, 2 * i + 1, &verts[edge->v2].co);
-                       setAttrib(vbo, n1_id, 2 * i + 1, n1);
-                       setAttrib(vbo, n2_id, 2 * i + 1, n2);
-               }
-
-               MEM_freeN(adj_faces);
-               MEM_freeN(face_normal);
-
-               cache->fancy_edges = Batch_create(GL_LINES, vbo, NULL);
-       }
-
-       return cache->fancy_edges;
-}
-
-static bool edge_is_real(const MEdge *edges, int edge_ct, int v1, int v2)
-{
-       /* TODO: same thing, except not ridiculously slow */
-
-       for (int e = 0; e < edge_ct; ++e) {
-               const MEdge *edge = edges + e;
-               if ((edge->v1 == v1 && edge->v2 == v2) || (edge->v1 == v2 && edge->v2 == v1)) {
-                       return true;
-               }
-       }
-
-       return false;
-}
-
-static void add_overlay_tri(VertexBuffer *vbo, unsigned pos_id, unsigned edgeMod_id, const MVert *verts, const MEdge *edges, int edge_ct, int v1, int v2, int v3, int base_vert_idx)
-{
-       const float edgeMods[2] = { 0.0f, 1.0f };
-
-       const float *pos = verts[v1].co;
-       setAttrib(vbo, pos_id, base_vert_idx + 0, pos);
-       setAttrib(vbo, edgeMod_id, base_vert_idx + 0, edgeMods + (edge_is_real(edges, edge_ct, v2, v3) ? 1 : 0));
-
-       pos = verts[v2].co;
-       setAttrib(vbo, pos_id, base_vert_idx + 1, pos);
-       setAttrib(vbo, edgeMod_id, base_vert_idx + 1, edgeMods + (edge_is_real(edges, edge_ct, v3, v1) ? 1 : 0));
-
-       pos = verts[v3].co;
-       setAttrib(vbo, pos_id, base_vert_idx + 2, pos);
-       setAttrib(vbo, edgeMod_id, base_vert_idx + 2, edgeMods + (edge_is_real(edges, edge_ct, v1, v2) ? 1 : 0));
-}
-
-static Batch *MBC_get_overlay_edges(DerivedMesh *dm)
-{
-       MeshBatchCache *cache = MBC_get(dm);
-
-       if (cache->overlay_edges == NULL) {
-               /* create batch from DM */
-               static VertexFormat format = { 0 };
-               static unsigned pos_id, edgeMod_id;
-               if (format.attrib_ct == 0) {
-                       /* initialize vertex format */
-                       pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
-                       edgeMod_id = add_attrib(&format, "edgeWidthModulator", GL_FLOAT, 1, KEEP_FLOAT);
-               }
-               VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
-
-               const int vertex_ct = dm->getNumVerts(dm);
-               const int edge_ct = dm->getNumEdges(dm);
-               const int tessface_ct = dm->getNumTessFaces(dm);
-               const MVert *verts = dm->getVertArray(dm);
-               const MEdge *edges = dm->getEdgeArray(dm);
-               const MFace *tessfaces = dm->getTessFaceArray(dm);
-
-               VertexBuffer_allocate_data(vbo, tessface_ct * 6); /* up to 2 triangles per tessface */
-
-               int gpu_vert_idx = 0;
-               for (int i = 0; i < tessface_ct; ++i) {
-                       const MFace *tess = tessfaces + i;
-                       add_overlay_tri(vbo, pos_id, edgeMod_id, verts, edges, edge_ct, tess->v1, tess->v2, tess->v3, gpu_vert_idx);
-                       gpu_vert_idx += 3;
-                       /* tessface can be triangle or quad */
-                       if (tess->v4) {
-                               add_overlay_tri(vbo, pos_id, edgeMod_id, verts, edges, edge_ct, tess->v3, tess->v2, tess->v4, gpu_vert_idx);
-                               gpu_vert_idx += 3;
-                       }
-               }
-
-               VertexBuffer_resize_data(vbo, gpu_vert_idx);
-
-               cache->overlay_edges = Batch_create(GL_TRIANGLES, vbo, NULL);
-       }
-
-       return cache->overlay_edges;
-}
 
 static void drawcube_size(float size, unsigned pos);
 static void drawcircle_size(float size, unsigned pos);
@@ -4370,11 +4037,10 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d,
 }
 
 static void draw_em_fancy_new(Scene *UNUSED(scene), ARegion *ar, View3D *UNUSED(v3d),
-                              Object *UNUSED(ob), BMEditMesh *UNUSED(em), DerivedMesh *cageDM, DerivedMesh *UNUSED(finalDM), const char UNUSED(dt))
+                              Object *UNUSED(ob), Mesh *me, BMEditMesh *UNUSED(em), DerivedMesh *UNUSED(cageDM), DerivedMesh *UNUSED(finalDM), const char UNUSED(dt))
 {
        /* for now... something simple! */
-
-       Batch *surface = MBC_get_all_triangles(cageDM);
+       Batch *surface = BKE_mesh_batch_cache_get_all_triangles(me);
 
        glEnable(GL_DEPTH_TEST);
        glDepthFunc(GL_LEQUAL);
@@ -4408,7 +4074,7 @@ static void draw_em_fancy_new(Scene *UNUSED(scene), ARegion *ar, View3D *UNUSED(
        Batch_draw(surface);
 
        if (GLEW_VERSION_3_2) {
-               Batch *overlay = MBC_get_overlay_edges(cageDM);
+               Batch *overlay = BKE_mesh_batch_cache_get_overlay_edges(me);
                Batch_set_builtin_program(overlay, GPU_SHADER_EDGES_OVERLAY);
                Batch_Uniform2f(overlay, "viewportSize", ar->winx, ar->winy);
                Batch_draw(overlay);
@@ -4426,7 +4092,7 @@ static void draw_em_fancy_new(Scene *UNUSED(scene), ARegion *ar, View3D *UNUSED(
 #endif
        }
        else {
-               Batch *edges = MBC_get_all_edges(cageDM);
+               Batch *edges = BKE_mesh_batch_cache_get_all_edges(me);
                Batch_set_builtin_program(edges, GPU_SHADER_3D_UNIFORM_COLOR);
                Batch_Uniform4f(edges, "color", 0.0f, 0.0f, 0.0f, 1.0f);
                glEnable(GL_LINE_SMOOTH);
@@ -4436,7 +4102,7 @@ static void draw_em_fancy_new(Scene *UNUSED(scene), ARegion *ar, View3D *UNUSED(
        }
 
 #if 0 /* looks good even without points */
-       Batch *verts = MBC_get_all_verts(cageDM);
+       Batch *verts = MBC_get_all_verts(me);
        glEnable(GL_BLEND);
 
        Batch_set_builtin_program(verts, GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_SMOOTH);
@@ -4474,7 +4140,7 @@ void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm) /* LEGAC
        }
 }
 
-static void draw_mesh_object_outline_new(View3D *v3d, RegionView3D *rv3d, Object *ob, DerivedMesh *dm, const bool is_active)
+static void draw_mesh_object_outline_new(View3D *v3d, RegionView3D *rv3d, Object *ob, Mesh *me, const bool is_active)
 {
        if ((v3d->transp == false) &&  /* not when we draw the transparent pass */
            (ob->mode & OB_MODE_ALL_PAINT) == false) /* not when painting (its distracting) - campbell */
@@ -4486,7 +4152,7 @@ static void draw_mesh_object_outline_new(View3D *v3d, RegionView3D *rv3d, Object
                UI_GetThemeColor4fv((is_active ? TH_ACTIVE : TH_SELECT), outline_color);
 
 #if 1 /* new version that draws only silhouette edges */
-               Batch *fancy_edges = MBC_get_fancy_edges(dm);
+               Batch *fancy_edges = BKE_mesh_batch_cache_get_fancy_edges(me);
 
                if (rv3d->persp == RV3D_ORTHO) {
                        Batch_set_builtin_program(fancy_edges, GPU_SHADER_EDGES_FRONT_BACK_ORTHO);
@@ -5009,7 +4675,7 @@ static void draw_mesh_fancy_new(Scene *scene, ARegion *ar, View3D *v3d, RegionVi
 
 #if 1 /* fancy wireframes */
 
-               Batch *fancy_edges = MBC_get_fancy_edges(dm);
+               Batch *fancy_edges = BKE_mesh_batch_cache_get_fancy_edges(me);
 
                if (rv3d->persp == RV3D_ORTHO) {
                        Batch_set_builtin_program(fancy_edges, GPU_SHADER_EDGES_FRONT_BACK_ORTHO);
@@ -5069,7 +4735,7 @@ static void draw_mesh_fancy_new(Scene *scene, ARegion *ar, View3D *v3d, RegionVi
                    !(G.f & G_PICKSEL || (draw_flags & DRAW_FACE_SELECT)) &&
                    (draw_wire == OBDRAW_WIRE_OFF))
                {
-                       draw_mesh_object_outline_new(v3d, rv3d, ob, dm, (ob == OBACT));
+                       draw_mesh_object_outline_new(v3d, rv3d, ob, me, (ob == OBACT));
                }
 
                if (draw_glsl_material(scene, ob, v3d, dt) && !(draw_flags & DRAW_MODIFIERS_PREVIEW)) {
@@ -5136,7 +4802,7 @@ static void draw_mesh_fancy_new(Scene *scene, ARegion *ar, View3D *v3d, RegionVi
                                    (draw_wire == OBDRAW_WIRE_OFF) &&
                                    (ob->sculpt == NULL))
                                {
-                                       draw_mesh_object_outline_new(v3d, rv3d, ob, dm, (ob == OBACT));
+                                       draw_mesh_object_outline_new(v3d, rv3d, ob, me, (ob == OBACT));
                                }
 
                                /* materials arent compatible with vertex colors */
@@ -5161,7 +4827,7 @@ static void draw_mesh_fancy_new(Scene *scene, ARegion *ar, View3D *v3d, RegionVi
                            (ob->sculpt == NULL))
                        {
                                /* TODO: move this into a separate pass */
-                               draw_mesh_object_outline_new(v3d, rv3d, ob, dm, (ob == OBACT));
+                               draw_mesh_object_outline_new(v3d, rv3d, ob, me, (ob == OBACT));
                        }
 
                        glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW);
@@ -5310,7 +4976,7 @@ static bool draw_mesh_object_new(Scene *scene, ARegion *ar, View3D *v3d, RegionV
                        GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl, NULL);
                }
 
-               draw_em_fancy_new(scene, ar, v3d, ob, em, cageDM, finalDM, dt);
+               draw_em_fancy_new(scene, ar, v3d, ob, me, em, cageDM, finalDM, dt);
 
                if (use_material) {
                        GPU_end_object_materials();
index c2768377a96512d6daed51b80232d1192faa87b7..932ee18270321c52427b2b6622fe16884f4f52a9 100644 (file)
@@ -21,7 +21,7 @@ typedef enum {
        READY_TO_DRAW
 } BatchPhase;
 
-typedef struct {
+typedef struct Batch{
        // geometry
        VertexBuffer* verts;
        ElementList* elem; // NULL if element list not needed
index 39e56925903b582bb26963b27096d758a7a490e8..15ea3d4d37a090f15e58174dad87b98f714fc82f 100644 (file)
@@ -127,6 +127,7 @@ typedef struct Mesh {
        short totcol;
 
        struct Multires *mr DNA_DEPRECATED; /* deprecated multiresolution modeling data, only keep for loading old files */
+       void *batch_cache;
 } Mesh;
 
 /* deprecated by MTFace, only here for file reading */