diff options
Diffstat (limited to 'release/scripts/bevel_center.py')
-rw-r--r-- | release/scripts/bevel_center.py | 462 |
1 files changed, 462 insertions, 0 deletions
diff --git a/release/scripts/bevel_center.py b/release/scripts/bevel_center.py new file mode 100644 index 00000000000..eef2f630cea --- /dev/null +++ b/release/scripts/bevel_center.py @@ -0,0 +1,462 @@ +#!BPY + +""" Registration info for Blender menus +Name: 'Bevel Center' +Blender: 232 +Group: 'Mesh' +Tip: 'Bevel selected vertices.' +""" + +###################################################################### +# Bevel Center v1 for Blender +# +# This script lets you bevel the selected vertices and control the +# thickness of the bevel +# +# (c) 2004 Loïc Berthe (loic.berthe@lilotux.net) +# released under Blender Artistic License +# +###################################################################### + +import Blender +from Blender import NMesh +from Blender.Draw import * +from Blender.BGL import * + +from math import pi, sin, sqrt + +###################################################################### +# Functions to handle the global structures of the script NV, NE and NC +# which contain informations about the vertices, faces and corners to be +# created + +class Dir: + def __init__(self, co): + self.co = co + +def add_to_NV(old,co,new): + dir = Dir(co) + # + if old in NV.keys(): + NV[old][dir] = new + else: + NV[old] = {dir:new} + +def is_in_NV(old,co): + if old in NV.keys(): + for dir in NV[old]: + if dir.co == co : return NV[old][dir] + # + return False + +def add_to_NE(old, new): + ind1 = old[0].index + ind2 = old[1].index + if ind1 > ind2: + new.reverse() + ind1,ind2 = ind2,ind1 + id = str(ind1)+"_"+str(ind2) + if id in NE.keys(): + [NE[id].append(v) for v in new] + else: + NE[id] = new + +def add_to_NC(old,edge): + if old in NC.keys(): + NC[old].append(edge) + else: + NC[old] = [edge] + +###################################################################### +# Geometric functions + +def norm(vec): + n = sqrt(vec[0]**2+vec[1]**2+vec[2]**2) + return [vec[0]/n,vec[1]/n,vec[2]/n] + +def parall_coord(old, dir): + co = old.co + vec = [0.0,0.0,0.0] + nco = [0.0,0.0,0.0] + # + if len(dir) == 1: + for i in range(3): vec[i] = dir[0].co[i] - co[i] + vec = norm(vec) + # + elif len(dir) == 2: + vec1 = [0.0,0.0,0.0] + vec2 = [0.0,0.0,0.0] + for i in range(3): + vec1[i] = dir[0].co[i] - co[i] + vec2[i] = dir[1].co[i] - co[i] + vec1 = norm(vec1) + vec2 = norm(vec2) + for i in range(3) : vec[i] = vec1[i]+vec2[i] + # + for i in range(3): nco[i] = co[i] + dist.val*vec[i] + return (nco,vec) + +def get_vert(old, dir): + """ Look in NV if a vertice corresponding to the vertex old and the + direction dir already exists, and create one otherwise""" + (nco, vec) = parall_coord(old, dir) + v = is_in_NV(old,vec) + if v: return v + # + v = NMesh.Vert(nco[0],nco[1],nco[2]) + v.sel = 1 + me.verts.append(v) + add_to_NV(old,vec,v) + return v + +###################################################################### +# Functions to create the differents faces + +def make_NF(): + """ Analyse the mesh, sort the faces containing selected vertices and + create a liste NF : NF = [[flag, vertlist, old_face]]. Flag describes the + topology of the face.""" + # + for f in me.faces: + V = f.v + v_sel = [x.sel for x in V] + nb_sel = sum(v_sel) + if nb_sel == 0 : + pass + else: + nb_v = len(V) + # + if nb_v == 4: + # + if nb_sel == 4: + NF.append([1,V,f]) + # + elif nb_sel == 3: + if v_sel == [0,1,1,1]: V = [V[1],V[2],V[3],V[0]] + elif v_sel == [1,0,1,1]: V = [V[2],V[3],V[0],V[1]] + elif v_sel == [1,1,0,1]: V = [V[3],V[0],V[1],V[2]] + NF.append([2,V,f]) + # + elif nb_sel == 2: + if v_sel == [1,0,1,0] or v_sel == [0,1,0,1]: + if v_sel == [0,1,0,1]: V = [V[1],V[2],V[3],V[0]] + NF.append([5,[V[0],V[1],V[3]],f]) + NF.append([5,[V[2],V[1],V[3]]]) + else: + if v_sel == [0,1,1,0]: V = [V[1],V[2],V[3],V[0]] + elif v_sel == [0,0,1,1]: V = [V[2],V[3],V[0],V[1]] + elif v_sel == [1,0,0,1]: V = [V[3],V[0],V[1],V[2]] + NF.append([3,V,f]) + # + else: + if v_sel == [0,1,0,0]: V = [V[1],V[2],V[3],V[0]] + elif v_sel == [0,0,1,0]: V = [V[2],V[3],V[0],V[1]] + elif v_sel == [0,0,0,1]: V = [V[3],V[0],V[1],V[2]] + NF.append([4,V,f]) + # + elif nb_v == 3: + # + if nb_sel == 3: + NF.append([6,V,f]) + # + elif nb_sel == 2: + if v_sel == [0,1,1]: V = [V[1],V[2],V[0]] + elif v_sel == [1,0,1]: V = [V[2],V[0],V[1]] + NF.append([7,V,f]) + # + else: + if v_sel == [0,1,0]: V = [V[1],V[2],V[0]] + elif v_sel == [0,0,1]: V = [V[2],V[0],V[1]] + NF.append([5,V,f]) + +def make_faces(): + """ Make the new faces according to NF """ + # + for N in NF: + cas = N[0] + V = N[1] + # + if cas < 6: + new_v = [0,0,0,0] + if cas == 1: # v_sel = [1,1,1,1] + for i in range(-1,3): + new_v[i] = get_vert(V[i],[V[i-1],V[i+1]]) + new_f = NMesh.Face(new_v) + me.faces.append(new_f) + for i in range(-1,3): + add_to_NE([V[i],V[i+1]],[new_v[i],new_v[i+1]]) + # + elif cas == 2: # v_sel = [1,1,1,0] + new_v[0] = get_vert(V[0],[V[3]]) + new_v[1] = get_vert(V[1],[V[0],V[2]]) + new_v[2] = get_vert(V[2],[V[3]]) + new_v[3] = V[3] + # + new_f = NMesh.Face(new_v) + me.faces.append(new_f) + # + add_to_NE([V[0],V[1]],[new_v[0],new_v[1]]) + add_to_NE([V[1],V[2]],[new_v[1],new_v[2]]) + # + elif cas == 3: # v_sel = [1,1,0,0] + new_v[0] = get_vert(V[0],[V[3]]) + new_v[1] = get_vert(V[1],[V[2]]) + new_v[2] = V[2] + new_v[3] = V[3] + # + new_f = NMesh.Face(new_v) + me.faces.append(new_f) + # + add_to_NE([V[0],V[1]],[new_v[0],new_v[1]]) + # + elif cas == 4: # v_sel = [1,0,0,0] + new_v[0] = get_vert(V[0],[V[3]]) + new_v[1] = get_vert(V[0],[V[1]]) + new_v[2] = V[1] + new_v[3] = V[3] + # + new_f = NMesh.Face(new_v) + me.faces.append(new_f) + # + add_to_NC(V[0], new_v[0:2]) + # + new_v[0] = V[1] + new_v[1] = V[2] + new_v[2] = V[3] + # + new_f = NMesh.Face(new_v[:3]) + me.faces.append(new_f) + # + else: # v_sel = [1,0,0] + new_v[0] = get_vert(V[0],[V[2]]) + new_v[1] = get_vert(V[0],[V[1]]) + new_v[2] = V[1] + new_v[3] = V[2] + # + new_f = NMesh.Face(new_v) + me.faces.append(new_f) + # + add_to_NC(V[0], new_v[0:2]) + # + else: + new_v = [0,0,0] + # + if cas == 6: # v_sel = [1,1,1] + for i in range(-1,2): + new_v[i] = get_vert(V[i],[V[i-1],V[i+1]]) + new_f = NMesh.Face(new_v) + me.faces.append(new_f) + for i in range(-1,2): + add_to_NE([V[i],V[i+1]],[new_v[i],new_v[i+1]]) + # + elif cas == 7: # v_sel = [1,1,0] + new_v[0] = get_vert(V[0],[V[2]]) + new_v[1] = get_vert(V[1],[V[2]]) + new_v[2] = V[2] + # + new_f = NMesh.Face(new_v) + me.faces.append(new_f) + add_to_NE([V[0],V[1]],[new_v[0],new_v[1]]) + +def make_edges(): + """ Make the faces corresponding to selected edges """ + # + for l in NE.values(): + if len(l) == 4: + f = NMesh.Face([l[0],l[1],l[3],l[2]]) + me.faces.append(f) + +def make_corners(): + """ Make the faces corresponding to selected corners """ + # + for v in NV.keys(): + V = NV[v].values() + nb_v = len(V) + # + if nb_v < 3: + pass + # + elif nb_v == 3: + new_f = NMesh.Face(V) + me.faces.append(new_f) + # + else: + # We need to know which are the edges around the corner. + # First, we look for the quads surrounding the corner. + q = [NE[id] for id in NE.keys() if str(v.index) in id.split('_')] + # + # We will put the associated edges in the list eed + is_in_v = lambda x:x in V + eed = [filter(is_in_v, l) for l in q] + # + # We will add the edges coming from faces where only one vertice is selected. + # They are stocked in NC. + if v in NC.keys(): + eed = eed+NC[v] + b = eed.pop() + # b will contain the sorted list of vertices + # + while eed: + for l in eed: + if l[0] == b[-1]: + b.append(l[1]) + eed.remove(l) + break + elif l[1] == b[-1]: + b.append(l[0]) + eed.remove(l) + break + # Now we can create the faces + if nb_v == 4: + new_f = NMesh.Face(b[:4]) + me.faces.append(new_f) + # + else: + co = [0.0, 0.0,0.0] + vec = [0.0, 0.0,0.0] + for x in V: + co[0] += x[0] + co[1] += x[1] + co[2] += x[2] + # + for dir in NV[v]: + vec[0] += dir.co[0] + vec[1] += dir.co[1] + vec[2] += dir.co[2] + # + co = [x/nb_v for x in co] + vec = [x/nb_v for x in vec] + center = NMesh.Vert(co[0],co[1],co[2]) + center.sel = 1 + me.verts.append(center) + add_to_NV(v,vec,center) + # + for k in range(nb_v): + new_f = NMesh.Face([center, b[k], b[k+1]]) + me.faces.append(new_f) + # + +def clear_old(): + """ Erase old faces and vertices """ + for F in NF: + if len(F) == 3: + me.faces.remove(F[2]) + # + for v in NV.keys(): + me.verts.remove(v) + +###################################################################### +# Interface +# +global dist +dist = Create(0.2) +left = Create(0.0) +right = Create(1.0) +num = Create(2) + +# Events +EVENT_NOEVENT = 1 +EVENT_BEVEL = 2 +EVENT_UPDATE = 3 +EVENT_RECURS = 4 +EVENT_EXIT = 5 + +def draw(): + global dist, left, right, num + global EVENT_NOEVENT, EVENT_BEVEL, EVENT_UPDATE, EVENT_RECURS, EVENT_EXIT + + glClear(GL_COLOR_BUFFER_BIT) + Button("Bevel",EVENT_BEVEL,10,100,280,25) + left=Number('', EVENT_NOEVENT,10,70,45, 20,left.val,0,right.val,'Set the minimum of the slider') + right = Number("",EVENT_NOEVENT,245,70,45,20,right.val,left.val,200,"Set the maximum of the slider") + dist=Slider("Thickness ",EVENT_UPDATE,60,70,180,20,dist.val,left.val,right.val,0,"Thickness of the bevel") + glRasterPos2d(8,40) + Text('To finish, you can use recursive bevel to smooth it') + num=Number('', EVENT_NOEVENT,10,10,40, 16,num.val,1,100,'Recursion level') + Button("Recursive",EVENT_RECURS,55,10,100,16) + Button("Exit",EVENT_EXIT,210,10,80,20) + +def event(evt, val): + if (evt == QKEY and not val): + Exit() + +def bevent(evt): + if evt == EVENT_EXIT : + Exit() + # + elif evt == EVENT_BEVEL: + bevel() + # + elif evt == EVENT_UPDATE: + try: + bevel_update() + except NameError: + pass + # + elif evt == EVENT_RECURS: + recursive() + +Register(draw, event, bevent) + +###################################################################### +def bevel(): + """ The main function, which creates the bevel """ + global me,NF,NV,NE,NC, old_dist + # + objects = Blender.Object.GetSelected() + me = NMesh.GetRaw(objects[0].data.name) + # + NF = [] + NV = {} + NE = {} + NC = {} + # + make_NF() + make_faces() + make_edges() + make_corners() + clear_old() + # + old_dist = dist.val + # + me.update(1) + Blender.Redraw() + +def bevel_update(): + """ Use NV to update the bevel """ + global dist, old_dist + fac = dist.val - old_dist + old_dist = dist.val + # + for old_v in NV.keys(): + for dir in NV[old_v].keys(): + for i in range(3): + NV[old_v][dir].co[i] += fac*dir.co[i] + # + me.update(1) + Blender.Redraw() + +def recursive(): + """ Make a recursive bevel... still experimental """ + global dist + # + if num.val > 1: + a = pi/4 + ang = [] + for k in range(num.val): + ang.append(a) + a = (pi+2*a)/4 + # + l = [2*(1-sin(x))/sin(2*x) for x in ang] + R = dist.val/sum(l) + l = [x*R for x in l] + # + dist.val = l[0] + bevel_update() + # + for x in l[1:]: + dist.val = x + bevel() + +# vim:set ts=4 sw=4: + |