Add an option to mesh.calc_tessface() to get rid of polygons and loops
authorSergey Sharybin <sergey.vfx@gmail.com>
Wed, 18 Feb 2015 17:47:23 +0000 (22:47 +0500)
committerSergey Sharybin <sergey.vfx@gmail.com>
Fri, 13 Mar 2015 12:39:21 +0000 (17:39 +0500)
The purpose of this change is to add extra possibility to render engines and
export scripts to reduce peak memory footprint during their operation.

This new argument should be used with care since it'll leave mesh in not really
compatible with blender format, but it's ok to be used on temp meshes.

Unfortunately, it's hard to get scene where it'll show huge benefit because
in my tests with cycles peak memory is reached in MEM_printmemlist_stats().

However, in the file with sintel dragon it gives around 1gig of memory benefit
after removing the polys which would allow other heavy to compute stuff such as
hair (or even pointiness calculation) to not be a peak memory usage.

In any case, this change is nice to have IMO, and only means more parts of
scene export code should be optimized memory-wise.

Reviewers: campbellbarton

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

intern/cycles/blender/blender_util.h
source/blender/editors/include/ED_mesh.h
source/blender/editors/mesh/mesh_data.c
source/blender/makesrna/intern/rna_mesh_api.c
source/blenderplayer/bad_level_call_stubs/stubs.c

index 64fc352893a796074ce9d4cd774d9d90c5d256af..9f7181cc564440565bf7ae6fd70066fadac5e780 100644 (file)
@@ -47,7 +47,7 @@ static inline BL::Mesh object_to_mesh(BL::BlendData data, BL::Object object, BL:
                if (me.use_auto_smooth()) {
                        me.calc_normals_split();
                }
-               me.calc_tessface();
+               me.calc_tessface(true);
        }
        return me;
 }
index 8eb7fdf0c409c496ff762dfaad854ebe0d0359d8..ccf9722111296f8004f0552387ad6dc976ac3bb8 100644 (file)
@@ -256,7 +256,7 @@ void ED_mesh_faces_remove(struct Mesh *mesh, struct ReportList *reports, int cou
 void ED_mesh_edges_remove(struct Mesh *mesh, struct ReportList *reports, int count);
 void ED_mesh_vertices_remove(struct Mesh *mesh, struct ReportList *reports, int count);
 
-void ED_mesh_calc_tessface(struct Mesh *mesh);
+void ED_mesh_calc_tessface(struct Mesh *mesh, bool free_mpoly);
 void ED_mesh_update(struct Mesh *mesh, struct bContext *C, int calc_edges, int calc_tessface);
 
 void ED_mesh_uv_texture_ensure(struct Mesh *me, const char *name);
index 30e9a85d083f5274ccea285f7032c0cc020abdf0..86991d7dfeb93bb3468719aba31e9ca6bf470da4 100644 (file)
@@ -1235,7 +1235,7 @@ void ED_mesh_polys_add(Mesh *mesh, ReportList *reports, int count)
        mesh_add_polys(mesh, count);
 }
 
-void ED_mesh_calc_tessface(Mesh *mesh)
+void ED_mesh_calc_tessface(Mesh *mesh, bool free_mpoly)
 {
        if (mesh->edit_btmesh) {
                BKE_editmesh_tessface_calc(mesh->edit_btmesh);
@@ -1243,6 +1243,17 @@ void ED_mesh_calc_tessface(Mesh *mesh)
        else {
                BKE_mesh_tessface_calc(mesh);
        }
+       if (free_mpoly) {
+               CustomData_free(&mesh->ldata, mesh->totloop);
+               CustomData_free(&mesh->pdata, mesh->totpoly);
+               mesh->totloop = 0;
+               mesh->totpoly = 0;
+               mesh->mloop = NULL;
+               mesh->mloopcol = NULL;
+               mesh->mloopuv = NULL;
+               mesh->mpoly = NULL;
+               mesh->mtpoly = NULL;
+       }
 }
 
 void ED_mesh_report_mirror_ex(wmOperator *op, int totmirr, int totfail,
index 3f487698420a6018cd99934f4a090bf685f1114b..a994bf5e9d104e365eb7086af11bf1d247142ec2 100644 (file)
@@ -141,6 +141,11 @@ static void rna_Mesh_free_tangents(Mesh *mesh)
        CustomData_free_layers(&mesh->ldata, CD_MLOOPTANGENT, mesh->totloop);
 }
 
+static void rna_Mesh_calc_tessface(Mesh *mesh, int free_mpoly)
+{
+       ED_mesh_calc_tessface(mesh, free_mpoly != 0);
+}
+
 static void rna_Mesh_calc_smooth_groups(Mesh *mesh, int use_bitflags, int *r_poly_group_len,
                                         int **r_poly_group, int *r_group_total)
 {
@@ -269,8 +274,12 @@ void RNA_api_mesh(StructRNA *srna)
        func = RNA_def_function(srna, "free_tangents", "rna_Mesh_free_tangents");
        RNA_def_function_ui_description(func, "Free tangents");
 
-       func = RNA_def_function(srna, "calc_tessface", "ED_mesh_calc_tessface");
+       func = RNA_def_function(srna, "calc_tessface", "rna_Mesh_calc_tessface");
        RNA_def_function_ui_description(func, "Calculate face tessellation (supports editmode too)");
+       RNA_def_boolean(func, "free_mpoly", 0, "Free MPoly", "Free data used by polygons and loops. "
+                       "WARNING: This destructive operation removes regular faces, "
+                       "only used on temporary mesh data-blocks to reduce memory footprint of render "
+                       "engines and export scripts.");
 
        func = RNA_def_function(srna, "calc_smooth_groups", "rna_Mesh_calc_smooth_groups");
        RNA_def_function_ui_description(func, "Calculate smooth groups from sharp edges");
index e4319632797c35c5b1b2fb0bf48f78a62266e2b6..0856b50c19b0b722d9b32652c23e0bcd697198ea 100644 (file)
@@ -673,7 +673,7 @@ int collada_export(struct Scene *sce,
                    BC_export_transformation_type export_transformation_type,
                    int open_sim) RET_ZERO
 
-void ED_mesh_calc_tessface(struct Mesh *mesh) RET_NONE
+void ED_mesh_calc_tessface(struct Mesh *mesh, bool free_mpoly) RET_NONE
 
 /* bpy/python internal api */
 void operator_wrapper(struct wmOperatorType *ot, void *userdata) RET_NONE