[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 04:28:36 CEST 2012


mind = blown

Daniel Salazar
patazstudio.com


On Mon, Oct 15, 2012 at 7:39 PM, Nicholas Bishop
<nicholasbishop at gmail.com> wrote:
> I agree a modifier version would be nice. I've been thinking though
> that as new BMesh tools are added, there might be room for a lot of
> new modifiers. (For example, the convex hull operator I added in the
> last release would also work well as a modifier.) Perhaps it would be
> better to create a generic BMesh modifier that applies a BMesh
> operator to the input?
>
> -Nicholas
>
> On Mon, Oct 15, 2012 at 9:26 PM, Daniel Salazar - 3Developer.com
> <zanqdo at gmail.com> wrote:
>> 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
>> _______________________________________________
>> Bf-committers mailing list
>> Bf-committers at blender.org
>> http://lists.blender.org/mailman/listinfo/bf-committers
> _______________________________________________
> Bf-committers mailing list
> Bf-committers at blender.org
> http://lists.blender.org/mailman/listinfo/bf-committers


More information about the Bf-committers mailing list