[Bf-blender-cvs] [c691551] master: Optimize tessellation code (min 20% better, up to 300% with some CD layers to tessellate).
Bastien Montagne
noreply at git.blender.org
Tue Jan 21 16:36:19 CET 2014
Commit: c691551249f3fe3982c43e4c75be40a19503dd26
Author: Bastien Montagne
Date: Tue Jan 21 16:32:36 2014 +0100
https://developer.blender.org/rBc691551249f3fe3982c43e4c75be40a19503dd26
Optimize tessellation code (min 20% better, up to 300% with some CD layers to tessellate).
The main idea is to store (during tessellation) or recreate (during tessdata update) a tessfaceverts-to-loops mapping, and then update all tessdata
in one pass, instead of calling `BKE_mesh_loops_to_mface_corners` repeatedly for all tfaces!
Differential Revision: https://developer.blender.org/D226
Reviewed by Campbell, thanks a lot!
===================================================================
M source/blender/blenkernel/BKE_mesh.h
M source/blender/blenkernel/BKE_mesh_mapping.h
M source/blender/blenkernel/intern/DerivedMesh.c
M source/blender/blenkernel/intern/mesh_evaluate.c
M source/blender/editors/sculpt_paint/paint_vertex.c
===================================================================
diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h
index e82689e..302f71e 100644
--- a/source/blender/blenkernel/BKE_mesh.h
+++ b/source/blender/blenkernel/BKE_mesh.h
@@ -215,6 +215,9 @@ void BKE_mesh_loops_to_mface_corners(
const int polyindex, const int mf_len,
const int numTex, const int numCol,
const bool hasPCol, const bool hasOrigSpace);
+void BKE_mesh_loops_to_tessdata(
+ struct CustomData *fdata, struct CustomData *ldata, struct CustomData *pdata,
+ int *polyindices, unsigned int (*loopindices)[4], const int num_faces);
int BKE_mesh_recalc_tessellation(
struct CustomData *fdata, struct CustomData *ldata, struct CustomData *pdata,
struct MVert *mvert,
diff --git a/source/blender/blenkernel/BKE_mesh_mapping.h b/source/blender/blenkernel/BKE_mesh_mapping.h
index ee9e63e..f3f6b55 100644
--- a/source/blender/blenkernel/BKE_mesh_mapping.h
+++ b/source/blender/blenkernel/BKE_mesh_mapping.h
@@ -129,4 +129,13 @@ int *BKE_mesh_calc_smoothgroups(
const struct MLoop *mloop, const int totloop,
int *r_totgroup, const bool use_bitflags);
+/* No good (portable) way to have exported inlined functions... */
+#define BKE_MESH_TESSFACE_VINDEX_ORDER(_mf, _v) ( \
+ (CHECK_TYPE_INLINE(_mf, MFace *), CHECK_TYPE_INLINE(_v, unsigned int)), \
+ ((_mf->v1 == _v) ? 0 : \
+ (_mf->v2 == _v) ? 1 : \
+ (_mf->v3 == _v) ? 2 : \
+ (_mf->v4 && _mf->v4 == _v) ? 3 : -1) \
+ )
+
#endif /* __BKE_MESH_MAPPING_H__ */
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c
index ee7d890..c142438 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.c
+++ b/source/blender/blenkernel/intern/DerivedMesh.c
@@ -56,6 +56,7 @@
#include "BKE_key.h"
#include "BKE_modifier.h"
#include "BKE_mesh.h"
+#include "BKE_mesh_mapping.h"
#include "BKE_object.h"
#include "BKE_object_deform.h"
#include "BKE_paint.h"
@@ -431,16 +432,11 @@ void DM_update_tessface_data(DerivedMesh *dm)
CustomData *pdata = dm->getPolyDataLayout(dm);
CustomData *ldata = dm->getLoopDataLayout(dm);
- const int numTex = CustomData_number_of_layers(pdata, CD_MTEXPOLY);
- const int numCol = CustomData_number_of_layers(ldata, CD_MLOOPCOL);
- const int hasPCol = CustomData_has_layer(ldata, CD_PREVIEW_MLOOPCOL);
- const int hasOrigSpace = CustomData_has_layer(ldata, CD_ORIGSPACE_MLOOP);
-
- int *polyindex = CustomData_get_layer(fdata, CD_ORIGINDEX);
-
const int totface = dm->getNumTessFaces(dm);
int mf_idx;
- int ml_idx[4];
+
+ int *polyindex = CustomData_get_layer(fdata, CD_ORIGINDEX);
+ unsigned int (*loopindex)[4];
/* Should never occure, but better abort than segfault! */
if (!polyindex)
@@ -448,36 +444,35 @@ void DM_update_tessface_data(DerivedMesh *dm)
CustomData_from_bmeshpoly(fdata, pdata, ldata, totface);
- for (mf_idx = 0; mf_idx < totface; mf_idx++, mf++) {
- const int mf_len = mf->v4 ? 4 : 3;
- int i, not_done;
-
- /* Find out loop indices. */
- /* XXX Is there a better way to do this? */
- /* NOTE: This assumes tessface are valid and in sync with loop/poly... Else, most likely, segfault! */
- for (i = mp[polyindex[mf_idx]].loopstart, not_done = mf_len; not_done; i++) {
- MLoop *tml = &ml[i];
- if (tml->v == mf->v1) {
- ml_idx[0] = i;
- not_done--;
- }
- else if (tml->v == mf->v2) {
- ml_idx[1] = i;
- not_done--;
- }
- else if (tml->v == mf->v3) {
- ml_idx[2] = i;
- not_done--;
+ if (CustomData_has_layer(fdata, CD_MTFACE) ||
+ CustomData_has_layer(fdata, CD_MCOL) ||
+ CustomData_has_layer(fdata, CD_PREVIEW_MCOL) ||
+ CustomData_has_layer(fdata, CD_ORIGSPACE))
+ {
+ loopindex = MEM_mallocN(sizeof(*loopindex) * totface, __func__);
+
+ for (mf_idx = 0; mf_idx < totface; mf_idx++, mf++) {
+ const int mf_len = mf->v4 ? 4 : 3;
+ unsigned int *ml_idx = loopindex[mf_idx];
+ int i, not_done;
+
+ /* Find out loop indices. */
+ /* NOTE: This assumes tessface are valid and in sync with loop/poly... Else, most likely, segfault! */
+ for (i = mp[polyindex[mf_idx]].loopstart, not_done = mf_len; not_done; i++) {
+ const int tf_v = BKE_MESH_TESSFACE_VINDEX_ORDER(mf, ml[i].v);
+ if (tf_v != -1) {
+ ml_idx[tf_v] = i;
+ not_done--;
+ }
}
- else if (mf_len == 4 && tml->v == mf->v4) {
- ml_idx[3] = i;
- not_done--;
+ if (mf_len == 3) {
+ ml_idx[3] = 0;
}
}
- BKE_mesh_loops_to_mface_corners(fdata, ldata, pdata,
- ml_idx, mf_idx, polyindex[mf_idx],
- mf_len,
- numTex, numCol, hasPCol, hasOrigSpace);
+
+ BKE_mesh_loops_to_tessdata(fdata, ldata, pdata, polyindex, loopindex, totface);
+
+ MEM_freeN(loopindex);
}
if (G.debug & G_DEBUG)
diff --git a/source/blender/blenkernel/intern/mesh_evaluate.c b/source/blender/blenkernel/intern/mesh_evaluate.c
index 7759e53..d1b1c5c 100644
--- a/source/blender/blenkernel/intern/mesh_evaluate.c
+++ b/source/blender/blenkernel/intern/mesh_evaluate.c
@@ -1155,6 +1155,72 @@ void BKE_mesh_loops_to_mface_corners(
}
/**
+ * Convert all CD layers from loop/poly to tessface data.
+ * @loopindices is an array of an int[4] per tessface, mapping tessface's verts to loops indices.
+ */
+void BKE_mesh_loops_to_tessdata(CustomData *fdata, CustomData *ldata, CustomData *pdata,
+ int *polyindices, unsigned int (*loopindices)[4], const int num_faces)
+{
+ const int numTex = CustomData_number_of_layers(pdata, CD_MTEXPOLY);
+ const int numCol = CustomData_number_of_layers(ldata, CD_MLOOPCOL);
+ const bool hasPCol = CustomData_has_layer(ldata, CD_PREVIEW_MLOOPCOL);
+ const bool hasOrigSpace = CustomData_has_layer(ldata, CD_ORIGSPACE_MLOOP);
+ int findex, i, j;
+ int *pidx;
+ unsigned int (*lidx)[4];
+
+ for (i = 0; i < numTex; i++) {
+ MTFace *texface = CustomData_get_layer_n(fdata, CD_MTFACE, i);
+ MTexPoly *texpoly = CustomData_get_layer_n(pdata, CD_MTEXPOLY, i);
+ MLoopUV *mloopuv = CustomData_get_layer_n(ldata, CD_MLOOPUV, i);
+
+ for (findex = 0, pidx = polyindices, lidx = loopindices;
+ findex < num_faces;
+ pidx++, lidx++, findex++, texface++)
+ {
+ ME_MTEXFACE_CPY(texface, &texpoly[*pidx]);
+
+ for (j = (*lidx)[3] ? 4 : 3; j--;) {
+ copy_v2_v2(texface->uv[j], mloopuv[(*lidx)[j]].uv);
+ }
+ }
+ }
+
+ for (i = 0; i < numCol; i++) {
+ MCol (*mcol)[4] = CustomData_get_layer_n(fdata, CD_MCOL, i);
+ MLoopCol *mloopcol = CustomData_get_layer_n(ldata, CD_MLOOPCOL, i);
+
+ for (findex = 0, lidx = loopindices; findex < num_faces; lidx++, findex++, mcol++) {
+ for (j = (*lidx)[3] ? 4 : 3; j--;) {
+ MESH_MLOOPCOL_TO_MCOL(&mloopcol[(*lidx)[j]], &(*mcol)[j]);
+ }
+ }
+ }
+
+ if (hasPCol) {
+ MCol (*mcol)[4] = CustomData_get_layer(fdata, CD_PREVIEW_MCOL);
+ MLoopCol *mloopcol = CustomData_get_layer(ldata, CD_PREVIEW_MLOOPCOL);
+
+ for (findex = 0, lidx = loopindices; findex < num_faces; lidx++, findex++, mcol++) {
+ for (j = (*lidx)[3] ? 4 : 3; j--;) {
+ MESH_MLOOPCOL_TO_MCOL(&mloopcol[(*lidx)[j]], &(*mcol)[j]);
+ }
+ }
+ }
+
+ if (hasOrigSpace) {
+ OrigSpaceFace *of = CustomData_get_layer(fdata, CD_ORIGSPACE);
+ OrigSpaceLoop *lof = CustomData_get_layer(ldata, CD_ORIGSPACE_MLOOP);
+
+ for (findex = 0, lidx = loopindices; findex < num_faces; lidx++, findex++, of++) {
+ for (j = (*lidx)[3] ? 4 : 3; j--;) {
+ copy_v2_v2(of->uv[j], lof[(*lidx)[j]].uv);
+ }
+ }
+ }
+}
+
+/**
* Recreate tessellation.
*
* use_poly_origindex sets whether or not the tessellation faces' origindex
@@ -1168,10 +1234,8 @@ void BKE_mesh_loops_to_mface_corners(
*
* \return number of tessellation faces.
*/
-int BKE_mesh_recalc_tessellation(CustomData *fdata,
- CustomData *ldata, CustomData *pdata,
- MVert *mvert, int totface, int totloop,
- int totpoly,
+int BKE_mesh_recalc_tessellation(CustomData *fdata, CustomData *ldata, CustomData *pdata,
+ MVert *mvert, int totface, int totloop, int totpoly,
/* when tessellating to recalculate normals after
* we can skip copying here */
const bool do_face_nor_cpy)
@@ -1182,9 +1246,6 @@ int BKE_mesh_recalc_tessellation(CustomData *fdata,
#define USE_TESSFACE_SPEEDUP
#define USE_TESSFACE_QUADS // NEEDS FURTHER TESTING
-#define TESSFACE_SCANFILL (1 << 0)
-#define TESSFACE_IS_QUAD (1 << 1)
-
const int looptris_tot = poly_to_tri_count(totpoly, totloop);
MPoly *mp, *mpoly;
@@ -1192,13 +1253,9 @@ int BKE_mesh_recalc_tessellation(CustomData *fdata,
MFace *mface, *mf;
MemArena *arena = NULL;
int *mface_to_poly_map;
- int lindex[4]; /* only ever use 3 in this case */
- int poly_index, j, mface_index;
-
- const int numTex = CustomData_number_of_layers(pdata, CD_MTEXPOLY);
- const int numCol = CustomData_number_of_layers(ldata, CD_MLOOPCOL);
- const bool hasPCol = CustomData_has_layer(ldata, CD_PREVIEW_MLOOPCOL);
- const bool hasOrigSpace = CustomData_has_layer(ldata, CD_ORIGSPACE_MLOOP);
+ unsigned int (*lindices)[4];
+ int poly_index, mface_index;
+ unsigned int j;
mpoly = CustomData_get_layer(pdata, CD_MPOLY);
mloop = CustomData_get_layer(ldata, CD_MLOOP);
@@ -1208,12 +1265,16 @@ int BKE_mesh_recalc_tessellation(CustomData *fdata,
/* take care. we are _not_ calloc'ing so be sure to initialize each field */
mface_to_poly_map = MEM_mallocN(sizeof(*mface_to_poly_map) * (size_t)looptris_tot, __func__);
mface = MEM_mallocN(sizeof(*mface) * (size_t)looptris_tot, __func__);
+ lindices = MEM_mallocN(sizeof(*lindices) * (size_t)looptris_tot, __func__);
mface_index = 0;
mp = mpoly;
for (poly_index = 0; poly_index < totpoly; poly_index++, mp++) {
const unsigned int mp_loopstart = (unsigned int)mp->loopstart
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list