[Bf-committers] [Bf-blender-cvs] SVN commit: /data/svn/bf-blender [51356] trunk/blender: Add BMesh and WM symmetrize operators
Daniel Salazar - 3Developer.com
zanqdo at gmail.com
Tue Oct 16 03:26:55 CEST 2012
Not so fast! This is too cool to exist only as an operator. What about
a modifier? ^_^
awesomesauce
Daniel Salazar
patazstudio.com
On Mon, Oct 15, 2012 at 5:50 PM, Nicholas Bishop
<nicholasbishop at gmail.com> wrote:
> Revision: 51356
> http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=51356
> Author: nicholasbishop
> Date: 2012-10-15 23:50:09 +0000 (Mon, 15 Oct 2012)
> Log Message:
> -----------
> Add BMesh and WM symmetrize operators
>
> * The symmetrize operation makes the input mesh elements symmetrical,
> but unlike mirroring it only copies in one direction. The edges and
> faces that cross the plane of symmetry are split as needed to
> enforce symmetry.
>
> * The symmetrize operator can be controlled with the "direction"
> property, which combines the choices of symmetry plane and
> positive-negative/negative-positive. The enum for this is
> BMO_SymmDirection.
>
> * Added menu items in the top-level Mesh menu and the WKEY specials
> menu.
>
> * Documentation:
> http://wiki.blender.org/index.php/User:Nicholasbishop/Symmetrize
>
> * Reviewed by Brecht:
> https://codereview.appspot.com/6618059
>
> Modified Paths:
> --------------
> trunk/blender/release/scripts/startup/bl_ui/space_view3d.py
> trunk/blender/source/blender/bmesh/CMakeLists.txt
> trunk/blender/source/blender/bmesh/intern/bmesh_opdefines.c
> trunk/blender/source/blender/bmesh/intern/bmesh_operator_api.h
> trunk/blender/source/blender/bmesh/intern/bmesh_operators_private.h
> trunk/blender/source/blender/editors/mesh/editmesh_tools.c
> trunk/blender/source/blender/editors/mesh/mesh_intern.h
> trunk/blender/source/blender/editors/mesh/mesh_ops.c
>
> Added Paths:
> -----------
> trunk/blender/source/blender/bmesh/operators/bmo_symmetrize.c
>
> Modified: trunk/blender/release/scripts/startup/bl_ui/space_view3d.py
> ===================================================================
> --- trunk/blender/release/scripts/startup/bl_ui/space_view3d.py 2012-10-15 23:17:24 UTC (rev 51355)
> +++ trunk/blender/release/scripts/startup/bl_ui/space_view3d.py 2012-10-15 23:50:09 UTC (rev 51356)
> @@ -1668,7 +1668,7 @@
> layout.menu("VIEW3D_MT_uv_map", text="UV Unwrap...")
>
> layout.separator()
> -
> + layout.operator("mesh.symmetrize")
> layout.operator("view3d.edit_mesh_extrude_move_normal", text="Extrude Region")
> layout.operator("view3d.edit_mesh_extrude_individual_move", text="Extrude Individual")
> layout.operator("mesh.duplicate_move")
> @@ -1719,6 +1719,7 @@
> layout.operator("mesh.shape_propagate_to_all")
> layout.operator("mesh.select_vertex_path")
> layout.operator("mesh.sort_elements")
> + layout.operator("mesh.symmetrize")
>
>
> class VIEW3D_MT_edit_mesh_select_mode(Menu):
>
> Modified: trunk/blender/source/blender/bmesh/CMakeLists.txt
> ===================================================================
> --- trunk/blender/source/blender/bmesh/CMakeLists.txt 2012-10-15 23:17:24 UTC (rev 51355)
> +++ trunk/blender/source/blender/bmesh/CMakeLists.txt 2012-10-15 23:50:09 UTC (rev 51356)
> @@ -52,6 +52,7 @@
> operators/bmo_mirror.c
> operators/bmo_primitive.c
> operators/bmo_removedoubles.c
> + operators/bmo_symmetrize.c
> operators/bmo_subdivide.c
> operators/bmo_subdivide.h
> operators/bmo_triangulate.c
>
> Modified: trunk/blender/source/blender/bmesh/intern/bmesh_opdefines.c
> ===================================================================
> --- trunk/blender/source/blender/bmesh/intern/bmesh_opdefines.c 2012-10-15 23:17:24 UTC (rev 51355)
> +++ trunk/blender/source/blender/bmesh/intern/bmesh_opdefines.c 2012-10-15 23:50:09 UTC (rev 51356)
> @@ -1182,6 +1182,29 @@
> 0
> };
>
> +/*
> + * Symmetrize
> + *
> + * Mekes the mesh elements in the "input" slot symmetrical. Unlike
> + * normal mirroring, it only copies in one direction, as specified by
> + * the "direction" slot. The edges and faces that cross the plane of
> + * symmetry are split as needed to enforce symmetry.
> + *
> + * All new vertices, edges, and faces are added to the "geomout" slot.
> + */
> +static BMOpDefine bmo_symmetrize_def = {
> + "symmetrize",
> + {{BMO_OP_SLOT_ELEMENT_BUF, "input"},
> + {BMO_OP_SLOT_INT, "direction"},
> +
> + /* Outputs */
> + {BMO_OP_SLOT_ELEMENT_BUF, "geomout"},
> +
> + {0} /* null-terminating sentinel */},
> + bmo_symmetrize_exec,
> + 0
> +};
> +
> BMOpDefine *opdefines[] = {
> &bmo_automerge_def,
> &bmo_average_vert_facedata_def,
> @@ -1246,6 +1269,7 @@
> &bmo_split_def,
> &bmo_split_edges_def,
> &bmo_subdivide_edges_def,
> + &bmo_symmetrize_def,
> &bmo_transform_def,
> &bmo_translate_def,
> &bmo_triangle_fill_def,
>
> Modified: trunk/blender/source/blender/bmesh/intern/bmesh_operator_api.h
> ===================================================================
> --- trunk/blender/source/blender/bmesh/intern/bmesh_operator_api.h 2012-10-15 23:17:24 UTC (rev 51355)
> +++ trunk/blender/source/blender/bmesh/intern/bmesh_operator_api.h 2012-10-15 23:50:09 UTC (rev 51356)
> @@ -266,6 +266,16 @@
> DEL_ONLYTAGGED
> };
>
> +typedef enum {
> + BMO_SYMMETRIZE_NEGATIVE_X,
> + BMO_SYMMETRIZE_NEGATIVE_Y,
> + BMO_SYMMETRIZE_NEGATIVE_Z,
> +
> + BMO_SYMMETRIZE_POSITIVE_X,
> + BMO_SYMMETRIZE_POSITIVE_Y,
> + BMO_SYMMETRIZE_POSITIVE_Z,
> +} BMO_SymmDirection;
> +
> void BMO_op_flag_enable(BMesh *bm, BMOperator *op, const int op_flag);
> void BMO_op_flag_disable(BMesh *bm, BMOperator *op, const int op_flag);
>
>
> Modified: trunk/blender/source/blender/bmesh/intern/bmesh_operators_private.h
> ===================================================================
> --- trunk/blender/source/blender/bmesh/intern/bmesh_operators_private.h 2012-10-15 23:17:24 UTC (rev 51355)
> +++ trunk/blender/source/blender/bmesh/intern/bmesh_operators_private.h 2012-10-15 23:50:09 UTC (rev 51356)
> @@ -96,6 +96,7 @@
> void bmo_split_edges_exec(BMesh *bm, BMOperator *op);
> void bmo_split_exec(BMesh *bm, BMOperator *op);
> void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op);
> +void bmo_symmetrize_exec(BMesh *bm, BMOperator *op);
> void bmo_transform_exec(BMesh *bm, BMOperator *op);
> void bmo_translate_exec(BMesh *bm, BMOperator *op);
> void bmo_triangle_fill_exec(BMesh *bm, BMOperator *op);
>
> Added: trunk/blender/source/blender/bmesh/operators/bmo_symmetrize.c
> ===================================================================
> --- trunk/blender/source/blender/bmesh/operators/bmo_symmetrize.c (rev 0)
> +++ trunk/blender/source/blender/bmesh/operators/bmo_symmetrize.c 2012-10-15 23:50:09 UTC (rev 51356)
> @@ -0,0 +1,663 @@
> +/*
> + * ***** 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.
> + *
> + * Contributor(s): Nicholas Bishop
> + *
> + * ***** END GPL LICENSE BLOCK *****
> + */
> +
> +#include "MEM_guardedalloc.h"
> +
> +#include "BLI_array.h"
> +#include "BLI_math.h"
> +#include "BLI_utildefines.h"
> +
> +#include "bmesh.h"
> +#include "intern/bmesh_operators_private.h"
> +
> +enum {
> + SYMM_OUTPUT_GEOM = (1 << 0)
> +};
> +
> +/* Note: don't think there's much need to make these user-adjustable? */
> +#define SYMM_AXIS_THRESHOLD 0.00002f
> +#define SYMM_VERT_THRESHOLD 0.00002f
> +
> +typedef enum {
> + /* Coordinate lies on the side being copied from */
> + SYMM_SIDE_KEEP,
> + /* Coordinate lies on the side being copied from and within the
> + * axis threshold */
> + SYMM_SIDE_AXIS,
> + /* Coordinate lies on the side being copied to */
> + SYMM_SIDE_KILL
> +} SymmSide;
> +
> +typedef struct {
> + BMesh *bm;
> + BMOperator *op;
> +
> + int axis;
> + BMO_SymmDirection direction;
> +
> + /* Maps from input vertices to their mirrors. If the vertex
> + * doesn't have a mirror, it's not in this map. If the vertex is
> + * within the axis threshold, it's mapped to itself. */
> + GHash *vert_symm_map;
> +
> + /* Edges that cross the symmetry plane and are asymmetric get
> + * split. This map goes from input edges to output vertices. If an
> + * edge is not split, it's not in this map. */
> + GHash *edge_split_map;
> +} Symm;
> +
> +/* Return which side the coordinate lies on */
> +static SymmSide symm_co_side(const Symm *symm,
> + const float *co)
> +{
> + float comp = co[symm->axis];
> + if (ELEM3(symm->direction,
> + BMO_SYMMETRIZE_NEGATIVE_X,
> + BMO_SYMMETRIZE_NEGATIVE_Y,
> + BMO_SYMMETRIZE_NEGATIVE_Z))
> + {
> + comp = -comp;
> + }
> +
> + if (comp >= 0) {
> + if (comp < SYMM_AXIS_THRESHOLD)
> + return SYMM_SIDE_AXIS;
> + else
> + return SYMM_SIDE_KEEP;
> + }
> + else
> + return SYMM_SIDE_KILL;
> +}
> +
> +/* Output vertices and the vert_map array */
> +static void symm_verts_mirror(Symm *symm)
> +{
> + BMOIter oiter;
> + BMVert *src_v, *dst_v;
> +
> + symm->vert_symm_map = BLI_ghash_ptr_new(AT);
> +
> + BMO_ITER (src_v, &oiter, symm->bm, symm->op, "input", BM_VERT) {
> + SymmSide side = symm_co_side(symm, src_v->co);
> + float co[3];
> +
> + switch (side) {
> + case SYMM_SIDE_KEEP:
> + /* The vertex is outside the axis area; output its mirror */
> + copy_v3_v3(co, src_v->co);
> + co[symm->axis] = -co[symm->axis];
> +
> + dst_v = BM_vert_create(symm->bm, co, src_v);
> + BMO_elem_flag_enable(symm->bm, dst_v, SYMM_OUTPUT_GEOM);
> + BLI_ghash_insert(symm->vert_symm_map, src_v, dst_v);
> + break;
> +
> + case SYMM_SIDE_AXIS:
> + /* The vertex is within the axis area, snap to center */
> + src_v->co[symm->axis] = 0;
> + /* Vertex isn't copied, map to itself */
> + BLI_ghash_insert(symm->vert_symm_map, src_v, src_v);
> + break;
> +
> + case SYMM_SIDE_KILL:
> + /* The vertex does not lie in the half-space being
> + * copied from, nothing to do */
> + break;
> + }
> + }
> +}
> +
> +static int symm_edge_crosses_axis(const Symm *symm, const BMEdge *e)
> +{
> + const int sides[2] = {symm_co_side(symm, e->v1->co),
> + symm_co_side(symm, e->v2->co)};
> +
> + return ((sides[0] != SYMM_SIDE_AXIS) &&
> + (sides[1] != SYMM_SIDE_AXIS) &&
> + (sides[0] != sides[1]));
> +}
> +
> +/* Output edge split vertices for asymmetric edges and the edge_splits
> + * mapping array */
> +static void symm_split_asymmetric_edges(Symm *symm)
> +{
> + BMOIter oiter;
> + BMEdge *e;
> +
> + symm->edge_split_map = BLI_ghash_ptr_new(AT);
> +
> + BMO_ITER (e, &oiter, symm->bm, symm->op, "input", BM_EDGE) {
> + float flipped[3];
> +
> + copy_v3_v3(flipped, e->v1->co);
> + flipped[symm->axis] = -flipped[symm->axis];
> +
> + if (symm_edge_crosses_axis(symm, e) &&
> + (!compare_v3v3(e->v2->co, flipped, SYMM_VERT_THRESHOLD)))
> + {
> + /* Endpoints lie on opposite sides and are asymmetric */
> +
> + BMVert *v;
> + float lambda = 0, edge_dir[3], co[3];
> + float plane_co[3][3][3] = {
> + /* axis == 0 */
> + {{0, 0, 0}, {0, 1, 0}, {0, 0, 1}},
> + /* axis == 1 */
> + {{0, 0, 0}, {1, 0, 0}, {0, 0, 1}},
> + /* axis == 2 */
> + {{0, 0, 0}, {1, 0, 0}, {0, 1, 0}},
> + };
> + int r;
> +
> + /* Find intersection of edge with symmetry plane */
> + sub_v3_v3v3(edge_dir, e->v2->co, e->v1->co);
> + normalize_v3(edge_dir);
> + r = isect_ray_plane_v3(e->v1->co,
> + edge_dir,
> + plane_co[symm->axis][0],
> + plane_co[symm->axis][1],
> + plane_co[symm->axis][2],
> + &lambda, TRUE);
> + BLI_assert(r);
> +
> + madd_v3_v3v3fl(co, e->v1->co, edge_dir, lambda);
> + co[symm->axis] = 0;
> +
> + /* Edge is asymmetric, split it with a new vertex */
> + v = BM_vert_create(symm->bm, co, e->v1);
> + BMO_elem_flag_enable(symm->bm, v, SYMM_OUTPUT_GEOM);
> + BLI_ghash_insert(symm->edge_split_map, e, v);
> + }
> + }
> +}
> +
> +static void symm_mirror_edges(Symm *symm)
> +{
> + BMOIter oiter;
> + BMEdge *e;
> +
> + BMO_ITER (e, &oiter, symm->bm, symm->op, "input", BM_EDGE) {
> + BMVert *v1 = NULL, *v2 = NULL;
> + BMEdge *e_new;
> +
> + v1 = BLI_ghash_lookup(symm->vert_symm_map, e->v1);
> + v2 = BLI_ghash_lookup(symm->vert_symm_map, e->v2);
> +
> + if (v1 && v2) {
> + e_new = BM_edge_create(symm->bm, v1, v2, e, TRUE);
> + BMO_elem_flag_enable(symm->bm, e_new, SYMM_OUTPUT_GEOM);
> + }
> + else if (v1 || v2) {
>
> @@ Diff output truncated at 10240 characters. @@
> _______________________________________________
> Bf-blender-cvs mailing list
> Bf-blender-cvs at blender.org
> http://lists.blender.org/mailman/listinfo/bf-blender-cvs
More information about the Bf-committers
mailing list