[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [51459] trunk/blender/source/blender: bmesh decimator support for loop & edge customdata.
Campbell Barton
ideasman42 at gmail.com
Sat Oct 20 19:31:07 CEST 2012
Revision: 51459
http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=51459
Author: campbellbarton
Date: 2012-10-20 17:31:07 +0000 (Sat, 20 Oct 2012)
Log Message:
-----------
bmesh decimator support for loop & edge customdata. (most importantly UVs and vertex colors).
Modified Paths:
--------------
trunk/blender/source/blender/blenkernel/BKE_customdata.h
trunk/blender/source/blender/blenkernel/intern/customdata.c
trunk/blender/source/blender/bmesh/intern/bmesh_decimate.c
trunk/blender/source/blender/modifiers/intern/MOD_decimate.c
Modified: trunk/blender/source/blender/blenkernel/BKE_customdata.h
===================================================================
--- trunk/blender/source/blender/blenkernel/BKE_customdata.h 2012-10-20 16:48:54 UTC (rev 51458)
+++ trunk/blender/source/blender/blenkernel/BKE_customdata.h 2012-10-20 17:31:07 UTC (rev 51459)
@@ -81,6 +81,11 @@
*/
int CustomData_layer_has_math(struct CustomData *data, int layer_n);
+/**
+ * Checks if any of the customdata layers has math.
+ */
+int CustomData_has_math(struct CustomData *data);
+
/* copies the "value" (e.g. mloopuv uv or mloopcol colors) from one block to
* another, while not overwriting anything else (e.g. flags). probably only
* implemented for mloopuv/mloopcol, for now.*/
@@ -205,8 +210,8 @@
void CustomData_interp(const struct CustomData *source, struct CustomData *dest,
int *src_indices, float *weights, float *sub_weights,
int count, int dest_index);
-void CustomData_bmesh_interp(struct CustomData *data, void **src_blocks,
- float *weights, float *sub_weights, int count,
+void CustomData_bmesh_interp(struct CustomData *data, void **src_blocks,
+ const float *weights, const float *sub_weights, int count,
void *dest_block);
Modified: trunk/blender/source/blender/blenkernel/intern/customdata.c
===================================================================
--- trunk/blender/source/blender/blenkernel/intern/customdata.c 2012-10-20 16:48:54 UTC (rev 51458)
+++ trunk/blender/source/blender/blenkernel/intern/customdata.c 2012-10-20 17:31:07 UTC (rev 51459)
@@ -2477,12 +2477,26 @@
if (typeInfo->equal && typeInfo->add && typeInfo->multiply &&
typeInfo->initminmax && typeInfo->dominmax)
{
- return 1;
+ return TRUE;
}
- return 0;
+ return FALSE;
}
+int CustomData_has_math(struct CustomData *data)
+{
+ int i;
+
+ /* interpolates a layer at a time */
+ for (i = 0; i < data->totlayer; ++i) {
+ if (CustomData_layer_has_math(data, i)) {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
/* copies the "value" (e.g. mloopuv uv or mloopcol colors) from one block to
* another, while not overwriting anything else (e.g. flags)*/
void CustomData_data_copy_value(int type, void *source, void *dest)
@@ -2580,8 +2594,8 @@
memcpy(dest, source, typeInfo->size);
}
-void CustomData_bmesh_interp(CustomData *data, void **src_blocks, float *weights,
- float *sub_weights, int count, void *dest_block)
+void CustomData_bmesh_interp(CustomData *data, void **src_blocks, const float *weights,
+ const float *sub_weights, int count, void *dest_block)
{
int i, j;
void *source_buf[SOURCE_BUF_SIZE];
Modified: trunk/blender/source/blender/bmesh/intern/bmesh_decimate.c
===================================================================
--- trunk/blender/source/blender/bmesh/intern/bmesh_decimate.c 2012-10-20 16:48:54 UTC (rev 51458)
+++ trunk/blender/source/blender/bmesh/intern/bmesh_decimate.c 2012-10-20 17:31:07 UTC (rev 51459)
@@ -36,6 +36,8 @@
#include "BLI_quadric.h"
#include "BLI_heap.h"
+#include "BKE_customdata.h"
+
#include "bmesh.h"
#include "bmesh_structure.h"
#include "bmesh_decimate.h"
@@ -49,7 +51,13 @@
#define BOUNDARY_PRESERVE_WEIGHT 100.0f
+typedef enum CD_UseFlag {
+ CD_DO_VERT,
+ CD_DO_EDGE, /* not used yet */
+ CD_DO_LOOP
+} CD_UseFlag;
+
/* BMesh Helper Functions
* ********************** */
@@ -322,40 +330,146 @@
/* Edge Collapse Functions
* *********************** */
+#ifdef USE_CUSTOMDATA
+
/**
+ * \param v is the target to merge into.
+ */
+static void bm_edge_collapse_loop_customdata(BMesh *bm, BMLoop *l, BMVert *v_clear, BMVert *v_other, const float customdata_fac)
+{
+ /* these don't need to be updated, since they will get removed when the edge collapses */
+ BMLoop *l_clear, *l_other;
+ const int is_manifold = BM_edge_is_manifold(l->e);
+ int side;
+
+ /* l defines the vert to collapse into */
+
+ /* first find the loop of 'v_other' thats attached to the face of 'l' */
+ if (l->v == v_clear) {
+ l_clear = l;
+ l_other = l->next;
+ }
+ else {
+ l_clear = l->next;
+ l_other = l;
+ }
+
+ BLI_assert(l_clear->v == v_clear);
+ BLI_assert(l_other->v == v_other);
+
+ /* now we have both corners of the face 'l->f' */
+ for (side = 0; side < 2; side++) {
+ int is_seam = FALSE;
+ void *src[2];
+ BMFace *f_exit = is_manifold ? l->radial_next->f : NULL;
+ BMEdge *e_prev = l->e;
+ BMLoop *l_first;
+ BMLoop *l_iter;
+ float w[2];
+
+ if (side == 0) {
+ l_iter = l_first = l_clear;
+ src[0] = l_clear->head.data;
+ src[1] = l_other->head.data;
+
+ w[0] = customdata_fac;
+ w[1] = 1.0f - customdata_fac;
+ }
+ else {
+ l_iter = l_first = l_other;
+ src[0] = l_other->head.data;
+ src[1] = l_clear->head.data;
+
+ w[0] = 1.0f - customdata_fac;
+ w[1] = customdata_fac;
+ }
+
+ /* WATCH IT! - should NOT reference (_clear or _other) vars for this while loop */
+
+ /* walk around the fan using 'e_prev' */
+ while (((l_iter = BM_vert_step_fan_loop(l_iter, &e_prev)) != l_first) && (l_iter != NULL)) {
+ int i;
+ /* quit once we hit the opposite face, if we have one */
+ if (f_exit && UNLIKELY(f_exit == l_iter->f)) {
+ break;
+ }
+
+ /* break out unless we find a match */
+ is_seam = TRUE;
+
+ /* ok. we have a loop. now be smart with it! */
+ for (i = 0; i < bm->ldata.totlayer; i++) {
+ if (CustomData_layer_has_math(&bm->ldata, i)) {
+ int offset = bm->ldata.layers[i].offset;
+ int type = bm->ldata.layers[i].type;
+ void *cd_src, *cd_iter;
+
+ /* todo, make nicer macros for this */
+ cd_src = (char *)src[0] + offset;
+ // cd_dst = (char *)src[1] + offset; // UNUSED
+ cd_iter = (char *)l_iter->head.data + offset;
+
+ /* detect seams */
+ if (CustomData_data_equals(type, cd_src, cd_iter)) {
+ CustomData_bmesh_interp(&bm->ldata, src, w, NULL, 2, l_iter->head.data);
+ is_seam = FALSE;
+ }
+ }
+ }
+
+ if (is_seam) {
+ break;
+ }
+ }
+ }
+
+ /* first walk around the fan until we hit a seam */
+
+
+
+ /* last, interpolate ourselves */
+
+
+}
+#endif /* USE_CUSTOMDATA */
+
+/**
* special, highly limited edge collapse function
* intended for speed over flexibiliy.
* can only collapse edges connected to (1, 2) tris.
*
* Important - dont add vert/edge/face data on collapsing!
*
- * \param ke_other let caller know what edges we remove besides \a ke
+ * \param e_clear_other let caller know what edges we remove besides \a e_clear
+ * \param customdata_flag merge factor, scales from 0 - 1 ('v_clear' -> 'v_other')
*/
-static int bm_edge_collapse(BMesh *bm, BMEdge *ke, BMVert *kv, int ke_other[2],
+static int bm_edge_collapse(BMesh *bm, BMEdge *e_clear, BMVert *v_clear, int r_e_clear_other[2],
#ifdef USE_CUSTOMDATA
+ const CD_UseFlag customdata_flag,
const float customdata_fac
#else
+ const CD_UseFlag UNUSED(customdata_flag),
const float UNUSED(customdata_fac)
#endif
)
{
- BMVert *v_other = BM_edge_other_vert(ke, kv);
+ BMVert *v_other = BM_edge_other_vert(e_clear, v_clear);
BLI_assert(v_other != NULL);
- if (BM_edge_is_manifold(ke)) {
+ if (BM_edge_is_manifold(e_clear)) {
BMLoop *l_a, *l_b;
BMEdge *e_a_other[2], *e_b_other[2];
int ok;
- ok = BM_edge_loop_pair(ke, &l_a, &l_b);
+ ok = BM_edge_loop_pair(e_clear, &l_a, &l_b);
BLI_assert(ok == TRUE);
BLI_assert(l_a->f->len == 3);
BLI_assert(l_b->f->len == 3);
- /* keep 'kv' 0th */
- if (BM_vert_in_edge(l_a->prev->e, kv)) {
+ /* keep 'v_clear' 0th */
+ if (BM_vert_in_edge(l_a->prev->e, v_clear)) {
e_a_other[0] = l_a->prev->e;
e_a_other[1] = l_a->next->e;
}
@@ -364,7 +478,7 @@
e_a_other[0] = l_a->next->e;
}
- if (BM_vert_in_edge(l_b->prev->e, kv)) {
+ if (BM_vert_in_edge(l_b->prev->e, v_clear)) {
e_b_other[0] = l_b->prev->e;
e_b_other[1] = l_b->next->e;
}
@@ -390,20 +504,27 @@
return FALSE;
}
- ke_other[0] = BM_elem_index_get(e_a_other[0]);
- ke_other[1] = BM_elem_index_get(e_b_other[0]);
+ r_e_clear_other[0] = BM_elem_index_get(e_a_other[0]);
+ r_e_clear_other[1] = BM_elem_index_get(e_b_other[0]);
#ifdef USE_CUSTOMDATA
- /* TODO, loops */
- // const float w[2] = {customdata_fac, 1.0f - customdata_fac};
-
/* before killing, do customdata */
- BM_data_interp_from_verts(bm, v_other, kv, v_other, customdata_fac);
+ if (customdata_flag & CD_DO_VERT) {
+ BM_data_interp_from_verts(bm, v_other, v_clear, v_other, customdata_fac);
+ }
+ if (customdata_flag & CD_DO_EDGE) {
+ BM_data_interp_from_edges(bm, e_a_other[1], e_a_other[0], e_a_other[1], customdata_fac);
+ BM_data_interp_from_edges(bm, e_b_other[1], e_b_other[0], e_b_other[1], customdata_fac);
+ }
+ if (customdata_flag & CD_DO_LOOP) {
+ bm_edge_collapse_loop_customdata(bm, e_clear->l, v_clear, v_other, customdata_fac);
+ bm_edge_collapse_loop_customdata(bm, e_clear->l->radial_next, v_clear, v_other, customdata_fac);
+ }
#endif
- BM_edge_kill(bm, ke);
+ BM_edge_kill(bm, e_clear);
- BM_vert_splice(bm, kv, v_other);
+ BM_vert_splice(bm, v_clear, v_other);
BM_edge_splice(bm, e_a_other[0], e_a_other[1]);
BM_edge_splice(bm, e_b_other[0], e_b_other[1]);
@@ -412,17 +533,17 @@
return TRUE;
}
- else if (BM_edge_is_boundary(ke)) {
+ else if (BM_edge_is_boundary(e_clear)) {
/* same as above but only one triangle */
BMLoop *l_a;
BMEdge *e_a_other[2];
- l_a = ke->l;
+ l_a = e_clear->l;
BLI_assert(l_a->f->len == 3);
- /* keep 'kv' 0th */
- if (BM_vert_in_edge(l_a->prev->e, kv)) {
+ /* keep 'v_clear' 0th */
+ if (BM_vert_in_edge(l_a->prev->e, v_clear)) {
e_a_other[0] = l_a->prev->e;
e_a_other[1] = l_a->next->e;
}
@@ -431,20 +552,25 @@
e_a_other[0] = l_a->next->e;
}
- ke_other[0] = BM_elem_index_get(e_a_other[0]);
- ke_other[1] = -1;
+ r_e_clear_other[0] = BM_elem_index_get(e_a_other[0]);
+ r_e_clear_other[1] = -1;
#ifdef USE_CUSTOMDATA
- /* TODO, loops */
- // const float w[2] = {customdata_fac, 1.0f - customdata_fac};
-
/* before killing, do customdata */
- BM_data_interp_from_verts(bm, v_other, kv, v_other, customdata_fac);
+ if (customdata_flag & CD_DO_VERT) {
+ BM_data_interp_from_verts(bm, v_other, v_clear, v_other, customdata_fac);
+ }
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list