[Bf-extensions-cvs] SVN commit: /data/svn/bf-extensions [3245] contrib/py/scripts/addons/ mesh_bevel_round.py: Initial commit of bmesh bevel, based on Ruby code for Sketchup by Fredo6.
Howard Trickey
howard.trickey at gmail.com
Wed Apr 11 16:07:27 CEST 2012
Revision: 3245
http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-extensions&revision=3245
Author: howardt
Date: 2012-04-11 14:07:27 +0000 (Wed, 11 Apr 2012)
Log Message:
-----------
Initial commit of bmesh bevel, based on Ruby code for Sketchup by Fredo6.
Not very well tested, and a few known bugs, but wanted to get something
out there for people to try.
As well as bugs, still have to put in code to interpolate UVs, etc.
Added Paths:
-----------
contrib/py/scripts/addons/mesh_bevel_round.py
Added: contrib/py/scripts/addons/mesh_bevel_round.py
===================================================================
--- contrib/py/scripts/addons/mesh_bevel_round.py (rev 0)
+++ contrib/py/scripts/addons/mesh_bevel_round.py 2012-04-11 14:07:27 UTC (rev 3245)
@@ -0,0 +1,2798 @@
+# ##### 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.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# <pep8 compliant>
+
+# Ported from RoundCorner Ruby program for Sketchup by Fredo6
+# Fredo6 gave permission to port and distribute with Blender
+
+bl_info = {
+ "name": "Bevel Round",
+ "author": "Fredo6, Howard Trickey",
+ "version": (0, 1),
+ "blender": (2, 6, 3),
+ "location": "View3D > Tools",
+ "description": "Bevel selected edges, possibly rounded",
+ "warning": "",
+ "wiki_url": \
+ "TODO",
+ "tracker_url": \
+ "TODO",
+ "category": "Mesh"}
+
+import math
+import functools
+import bpy
+import bmesh
+import mathutils
+from bpy.props import (BoolProperty,
+ EnumProperty,
+ IntProperty,
+ FloatProperty,
+ )
+from mathutils import Vector
+
+EPSILON = 1e-6
+
+class BevelRound(bpy.types.Operator):
+ bl_idname = "mesh.bevel_round"
+ bl_label = "Bevel Round"
+ bl_description = "Bevel selected edges, possibly rounded"
+ bl_options = {'REGISTER', 'UNDO'}
+
+ bevel_kind = EnumProperty(name="Bevel Kind",
+ description="Style for beveling edges and corners",
+ items=[
+ ('ROUND', "Round",
+ "Round edges and corners"),
+ ('SHARP', "Sharp",
+ "Round edges, peaked corners"),
+ ('BEVEL', "Bevel",
+ "Flat edges and corners")
+ ],
+ default='BEVEL')
+
+ offset_amount = FloatProperty(name="Offset",
+ description="Amount to offset edges along faces",
+ default=0.2,
+ min=0.0,
+ max=1000.0,
+ soft_min=0.0,
+ soft_max=10.0,
+ unit='LENGTH')
+
+ segments = IntProperty(name="Segments",
+ description="How many segments on bevel profile",
+ min=1,
+ max=100,
+ default=1)
+
+ strict_offset = BoolProperty(name="Strict Offset",
+ description="Keep offset the same on all faces",
+ default=True)
+
+ rounding = BoolProperty(name="Inner Rounding",
+ description="Round inside faces at concave corners",
+ default=True)
+
+ @classmethod
+ def poll(cls, context):
+ obj = context.active_object
+ return (obj and obj.type == 'MESH' and context.mode == 'EDIT_MESH')
+
+ def draw(self, context):
+ layout = self.layout
+ box = layout.box()
+ box.label("Bevel Round Options:")
+ box.prop(self, "bevel_kind")
+ box.prop(self, "offset_amount")
+ box.prop(self, "segments")
+ box.prop(self, "strict_offset")
+ box.prop(self, "rounding")
+
+ def invoke(self, context, event):
+ self.action(context)
+ return {'FINISHED'}
+
+ def execute(self, context):
+ self.action(context)
+ return {'FINISHED'}
+
+ def action(self, context):
+ obj = bpy.context.active_object
+ bm = bmesh.from_edit_mesh(obj.data)
+ # make sure vert, edge, face indexes match their positions
+ bm.verts.index_update()
+ bm.edges.index_update()
+ bm.faces.index_update()
+ algo = BevelRoundAlgo(bm, self.bevel_kind, self.offset_amount,
+ self.segments, self.strict_offset, self.rounding)
+ algo.execute()
+ # Force mesh data recalculation
+ bpy.ops.object.editmode_toggle()
+ bpy.ops.object.editmode_toggle()
+
+
+class BevelRoundAlgo(object):
+ def __init__(self, bm, kind, offset, num_seg, strict, round):
+ # The bmesh object
+ self.bm = bm
+
+ # How much to move offset edges
+ # (projected onto 90deg angle planes, unless strict_offset)
+ self.offset = offset
+
+ # How many segments in the profile of an edge
+ self.num_seg = num_seg
+
+ # Cache of profiles in standard position, keyed by "kind-numseg"
+ # Kind will be one of 'C' or 'P', for now
+ self.hsh_profile_pts = {}
+
+ # bmesh Edge index -> BEdge for it
+ # Will have one for all the edges in the bevel selection
+ self.hsh_ed = {}
+
+ # bmesh Vertex index -> BCorner for it
+ # Will have one for all ends of edges in hsh_ed
+ self.hsh_corners = {}
+
+ # bmesh Face index -> BFace for it
+ self.hsh_faces = {}
+
+ # List of [Vector, Vector], each a border line segment (for display only?)
+ self.lpt_borders = []
+
+ # Catenas are chains of edges with related offsets
+ # Each has eds, a list of BEdges;
+ # chain, a list of [BEdge, face index]l
+ # nbsmall: seems to be some kind of edge count
+ self.lst_catenas = []
+
+ # List of Vector, pivot points for star corners
+ self.lst_mark_points = []
+
+ # lst_triangulate is list of [vd, ed1, ed2, seg1, seg2]
+ # for each vd for a vert with only two edges and >=3 pairs
+ self.lst_triangulated = []
+
+ # List of BCorner, those signaled as errors (pair lines don't cross (?))
+ self.hsh_error_vertex = {}
+
+ # Edge index -> bmesh Edge for edges to bevel
+ self.hash_edges = {}
+
+ # hash_edges_extra : Edge index -> bmesh Edge added for valence >= 4 reasons
+ self.hash_edges_extra = {}
+
+ # Vertex index -> list of bmesh edges to bevel attached
+ self.hsh_vertex_edges = {}
+
+ # Vertex index -> list of all bmesh edges attached to it
+ self.hsh_vertex_info = {}
+
+ # Map from point to BMVert
+ self.points = Points(self.bm)
+
+ # Used to orient asymmetric corner mesh patterns
+ self.golden_axis = Vector([0.0, 0.0, 1.0])
+
+ # Profile spec for edges: [string, number]
+ # where string is 'C' for quarter circle, 'CR' for concave quarter circle,
+ # 'BZ' for Bezier, 'P' for 'perso' (?, some kind of multi-bezier).
+ # number is number of line segments in profile (so 1 means just
+ # a single straight line from start to end)
+ if kind == 'BEVEL':
+ self.profile_type = ['C', 1]
+ self.num_seg = 1
+ else:
+ self.profile_type = ['C', num_seg]
+
+ # Controls whether or not to use a round profile in certain disagreeing cases (?)
+ self.mode_profile = 1
+
+ # Corners come to peaks if mode_sharp
+ self.mode_sharp = True if kind == 'SHARP' else False
+
+ # Forces offset along faces to be uniform rather than adjusted
+ # to make them uniform when projected on 90deg-meeting-faces
+ self.strict_offset = strict
+
+ # Should we round the edges in the faces themselves too?
+ self.mode_rounding = round
+
+ def execute(self):
+ bm = self.bm
+
+ # Add the bmesh edges and compute everything
+ # needed for bevel
+ self.build_model(bm)
+
+ # print("after build:")
+ # self.print()
+
+ # Initialization for geometry making
+ self.prepare_geometry()
+
+ # print("after prepare_geometry")
+ # self.print()
+
+ self.lst_corners = list(self.hsh_corners.values())
+ self.nb_corners = len(self.lst_corners) - 1
+ self.lst_eds = list(self.hsh_ed.values())
+ self.nb_eds = len(self.lst_eds) - 1
+ self.hsh_edge_erase = {}
+ self.nb_borders = len(self.lpt_borders) // 2 - 1
+
+ # Process geometry
+
+ self.lst_edge_erase = []
+ self.nb_edge_erase = -1
+
+ # Creating the rounding faces
+ for k in range(0, self.nb_eds + 1):
+ ed = self.lst_eds[k]
+ if ed.vmesh:
+ self.create_geometry_vmesh(ed.vmesh)
+
+ # Creating the triangulated vmesh if any
+ self.create_geometry_vmesh(self.lst_vmesh_triangulated)
+ self.create_geometry_vborders(self.lst_vborders_triangulated)
+
+ # Creating the corner round faces
+ for k in range(0, self.nb_corners + 1):
+ vd = self.lst_corners[k]
+ if vd.vmesh:
+ self.create_geometry_vmesh(vd.vmesh)
+
+ # Creating the new faces
+ for fc in self.hsh_faces.values():
+ lv = []
+ for i in range(len(fc.bmverts)):
+ npl = fc.newpts[i]
+ if npl:
+ lv.extend(self.get_bmverts(npl))
+ else:
+ lv.append(fc.bmverts[i])
+ self.bm.faces.new(lv)
+
+ # Deleting the unneeded geometry
+ for f in self.hsh_faces.values():
+ if f.face.is_valid:
+ fedges = f.face.edges[::]
+ self.bm.faces.remove(f.face)
+ for e in fedges:
+ if e.is_valid:
+ if e.is_wire:
+ self.bm.edges.remove(e)
+ for k in range(0, self.nb_corners + 1):
+ vd = self.lst_corners[k]
+ if len(vd.leds) == 1:
+ edge = vd.leds[0].edge
+ if edge.is_valid:
+ self.bm.edges.remove(edge)
+ else:
+ # print("remove edges:", vd.vertex.link_edges)
+ pass # is there stuff to do here?
+ if vd.vertex.is_valid:
+ self.bm.verts.remove(vd.vertex)
+
+ # Prepare the geometry
+ def prepare_geometry(self):
+ # Compute the corners
+ for vd in self.hsh_corners.values():
+ self.corner_compute(vd)
+
+ # Compute the edge roundings
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-extensions-cvs
mailing list