Commit: 75d1723518314632ef247ebe49f677856c8bf115
Author: Sergey Sharybin
Date:   Wed Jul 22 12:48:22 2015 +0200
Branches: master
https://developer.blender.org/rB75d1723518314632ef247ebe49f677856c8bf115

OpenSubdiv: Optimize speed of topology refiner construction

Now the conversion code uses mesh element mapping to speed up lookups.
Gives really nice speed improvement here, but the cost is higher memory
usage during refiner construction.

On the dragon scene here topology refiner construction time goes down
from 5 seconds to around 0.01.

It's possible to reduce the memory footprint by allocating mapping in
stages (don't allocate all of them at once, but do it on demand only
and free them after they're not needed anymore).

===================================================================

M       source/blender/blenkernel/intern/CCGSubSurf_opensubdiv_converter.c

===================================================================

diff --git a/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv_converter.c 
b/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv_converter.c
index c66425b..c4317f4 100644
--- a/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv_converter.c
+++ b/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv_converter.c
@@ -36,10 +36,16 @@
 #include "CCGSubSurf_intern.h"
 
 #include "BKE_DerivedMesh.h"
+#include "BKE_mesh_mapping.h"
 
 #include "opensubdiv_capi.h"
 #include "opensubdiv_converter_capi.h"
 
+/* Use mesh element mapping structures during conversion.
+ * Uses more memory but is much faster than naive algorithm.
+ */
+#define USE_MESH_ELEMENT_MAPPING
+
 /**
  * Converter from DerivedMesh.
  */
@@ -47,11 +53,16 @@
 typedef struct ConvDMStorage {
        CCGSubSurf *ss;
        DerivedMesh *dm;
-} ConvDMStorage;
 
-/* TODO(sergey): Optimize this by using mesh_map, so we don't
- * do full mesh lookup for every geometry primitive.
- */
+#ifdef USE_MESH_ELEMENT_MAPPING
+       MeshElemMap *vert_edge_map,
+                   *vert_poly_map,
+                   *edge_poly_map;
+       int *vert_edge_mem,
+           *vert_poly_mem,
+           *edge_poly_mem;
+#endif
+} ConvDMStorage;
 
 static OpenSubdiv_SchemeType conv_dm_get_type(
         const OpenSubdiv_Converter *converter)
@@ -140,6 +151,7 @@ static int conv_dm_get_num_edge_faces(const 
OpenSubdiv_Converter *converter,
                                       int edge)
 {
        ConvDMStorage *storage = converter->user_data;
+#ifndef USE_MESH_ELEMENT_MAPPING
        DerivedMesh *dm = storage->dm;
        const MLoop *ml = dm->getLoopArray(dm);
        const MPoly *mp = dm->getPolyArray(dm);
@@ -156,6 +168,9 @@ static int conv_dm_get_num_edge_faces(const 
OpenSubdiv_Converter *converter,
                }
        }
        return num;
+#else
+       return storage->edge_poly_map[edge].count;
+#endif
 }
 
 static void conv_dm_get_edge_faces(const OpenSubdiv_Converter *converter,
@@ -163,6 +178,7 @@ static void conv_dm_get_edge_faces(const 
OpenSubdiv_Converter *converter,
                                    int *edge_faces)
 {
        ConvDMStorage *storage = converter->user_data;
+#ifndef USE_MESH_ELEMENT_MAPPING
        DerivedMesh *dm = storage->dm;
        const MLoop *ml = dm->getLoopArray(dm);
        const MPoly *mp = dm->getPolyArray(dm);
@@ -178,6 +194,11 @@ static void conv_dm_get_edge_faces(const 
OpenSubdiv_Converter *converter,
                        }
                }
        }
+#else
+       memcpy(edge_faces,
+              storage->edge_poly_map[edge].indices,
+              sizeof(int) * storage->edge_poly_map[edge].count);
+#endif
 }
 
 static float conv_dm_get_edge_sharpness(const OpenSubdiv_Converter *converter,
@@ -194,6 +215,7 @@ static int conv_dm_get_num_vert_edges(const 
OpenSubdiv_Converter *converter,
                                       int vert)
 {
        ConvDMStorage *storage = converter->user_data;
+#ifndef USE_MESH_ELEMENT_MAPPING
        DerivedMesh *dm = storage->dm;
        const MEdge *me = dm->getEdgeArray(dm);
        int num = 0, edge;
@@ -204,6 +226,9 @@ static int conv_dm_get_num_vert_edges(const 
OpenSubdiv_Converter *converter,
                }
        }
        return num;
+#else
+       return storage->vert_edge_map[vert].count;
+#endif
 }
 
 static void conv_dm_get_vert_edges(const OpenSubdiv_Converter *converter,
@@ -211,6 +236,7 @@ static void conv_dm_get_vert_edges(const 
OpenSubdiv_Converter *converter,
                                    int *vert_edges)
 {
        ConvDMStorage *storage = converter->user_data;
+#ifndef USE_MESH_ELEMENT_MAPPING
        DerivedMesh *dm = storage->dm;
        const MEdge *me = dm->getEdgeArray(dm);
        int num = 0, edge;
@@ -220,12 +246,18 @@ static void conv_dm_get_vert_edges(const 
OpenSubdiv_Converter *converter,
                        vert_edges[num++] = edge;
                }
        }
+#else
+       memcpy(vert_edges,
+              storage->vert_edge_map[vert].indices,
+              sizeof(int) * storage->vert_edge_map[vert].count);
+#endif
 }
 
 static int conv_dm_get_num_vert_faces(const OpenSubdiv_Converter *converter,
                                       int vert)
 {
        ConvDMStorage *storage = converter->user_data;
+#ifndef USE_MESH_ELEMENT_MAPPING
        DerivedMesh *dm = storage->dm;
        const MLoop *ml = dm->getLoopArray(dm);
        const MPoly *mp = dm->getPolyArray(dm);
@@ -242,6 +274,9 @@ static int conv_dm_get_num_vert_faces(const 
OpenSubdiv_Converter *converter,
                }
        }
        return num;
+#else
+       return storage->vert_poly_map[vert].count;
+#endif
 }
 
 static void conv_dm_get_vert_faces(const OpenSubdiv_Converter *converter,
@@ -249,6 +284,7 @@ static void conv_dm_get_vert_faces(const 
OpenSubdiv_Converter *converter,
                                    int *vert_faces)
 {
        ConvDMStorage *storage = converter->user_data;
+#ifndef USE_MESH_ELEMENT_MAPPING
        DerivedMesh *dm = storage->dm;
        const MLoop *ml = dm->getLoopArray(dm);
        const MPoly *mp = dm->getPolyArray(dm);
@@ -264,11 +300,25 @@ static void conv_dm_get_vert_faces(const 
OpenSubdiv_Converter *converter,
                        }
                }
        }
+#else
+       memcpy(vert_faces,
+              storage->vert_poly_map[vert].indices,
+              sizeof(int) * storage->vert_poly_map[vert].count);
+#endif
 }
 
 static void conv_dm_free_user_data(const OpenSubdiv_Converter *converter)
 {
-       MEM_freeN(converter->user_data);
+       ConvDMStorage *user_data = converter->user_data;
+#ifdef USE_MESH_ELEMENT_MAPPING
+       MEM_freeN(user_data->vert_edge_map);
+       MEM_freeN(user_data->vert_edge_mem);
+       MEM_freeN(user_data->vert_poly_map);
+       MEM_freeN(user_data->vert_poly_mem);
+       MEM_freeN(user_data->edge_poly_map);
+       MEM_freeN(user_data->edge_poly_mem);
+#endif
+       MEM_freeN(user_data);
 }
 
 void ccgSubSurf_converter_setup_from_derivedmesh(
@@ -303,6 +353,40 @@ void ccgSubSurf_converter_setup_from_derivedmesh(
        user_data->dm = dm;
        converter->free_user_data = conv_dm_free_user_data;
        converter->user_data = user_data;
+
+#ifdef USE_MESH_ELEMENT_MAPPING
+       {
+               const MEdge *medge = dm->getEdgeArray(dm);
+               const MLoop *mloop = dm->getLoopArray(dm);
+               const MPoly *mpoly = dm->getPolyArray(dm);
+               const int num_vert = dm->getNumVerts(dm),
+                         num_edge = dm->getNumEdges(dm),
+                         num_loop = dm->getNumLoops(dm),
+                         num_poly = dm->getNumPolys(dm);
+               BKE_mesh_vert_edge_map_create(&user_data->vert_edge_map,
+                                             &user_data->vert_edge_mem,
+                                             medge,
+                                             num_vert,
+                                             num_edge);
+
+               BKE_mesh_vert_poly_map_create(&user_data->vert_poly_map,
+                                             &user_data->vert_poly_mem,
+                                             mpoly,
+                                             mloop,
+                                             num_vert,
+                                             num_poly,
+                                             num_loop);
+
+               BKE_mesh_edge_poly_map_create(&user_data->edge_poly_map,
+                                             &user_data->edge_poly_mem,
+                                             medge,
+                                             num_edge,
+                                             mpoly,
+                                             num_poly,
+                                             mloop,
+                                             num_loop);
+       }
+#endif  /* USE_MESH_ELEMENT_MAPPING */
 }
 
 /**

_______________________________________________
Bf-blender-cvs mailing list
Bf-blender-cvs@blender.org
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to