#!BPY """ Name: 'Taper & Twist' Blender: 232 Group: 'Misc' Tooltips: 'Taper or/and twist on selected vertices' """ # taper & Twist release 1.0 by flippyneck # 27th january 2004 # this script should be fairly self-explanatory. # Select a single mesh object (it must be a mesh), # and follow the instructions on the GUI. # WARNING! This script currently overwrites your mesh; # copy it or save your file before you run the script. # If this script proves popular I will correct this in the next # version. import Blender from Blender import Draw, BGL, NMesh, Object from math import sin, cos, sqrt, pi # ------------------------------------ # some handy definitions and functions. # thanks to theeth who's matrix functions (vecf.py) i # either used as a basis for my own, or plundered # wholesale. zero = 0.0000000001 mesh = [] meOr = [] def matrix4x4(): ''' Returns an empty 4x4 matrix (all vals==0) ''' mat=[] for n in range(0, 4): mat.append([0 for n in range(0, 4)]) return mat def idmatrix4x4(): ''' ... ''' mat=matrix4x4() for n in range(0, 4): mat[n][n]=1 return mat #nicked from theeth's vecf.py... def makeRotMtx(axis, angle): if axis=='X' or axis == 'x': rs, rc = sin(angle), cos(angle) mtx = [[1.0, 0.0, 0.0], [0.0, rc, rs], [0.0, -rs, rc] ] elif axis=='Y' or axis == 'y': rs, rc = sin(angle), cos(angle) mtx = [ [ rc, 0.0, -rs], [0.0, 1.0, 0.0], [ rs, 0.0, rc] ] else: rs, rc = sin(angle), cos(angle) mtx = [ [ rc, rs, 0.0], [-rs, rc, 0.0], [0.0, 0.0, 1.0] ] return mtx def vecxmat(v, m): ''' multiplies homogenous 3d vector by 4x4 matrix ''' r=[0,0,0] r[0]=(v[0]*m[0][0])+(v[1]*m[1][0])+(v[2]*m[2][0])#+(v[3]*m[3][0]) r[1]=(v[0]*m[0][1])+(v[1]*m[1][1])+(v[2]*m[2][1])#+(v[3]*m[3][1]) r[2]=(v[0]*m[0][2])+(v[1]*m[1][2])+(v[2]*m[2][2])#+(v[3]*m[3][2]) #r[3]=(v[0]*m[0][3])+(v[1]*m[1][3])+(v[2]*m[2][3])#+(v[3]*m[3][3]) return r def homovec(v): ''' converts vector to homogenous vector ''' hv=[] for c in v: hv.append(c) hv.append(1) return hv def lscalematrix4x4(scale_factor): ''' if tuple given, returns local scale matrix using (sx, sy, sz) ''' sm=idmatrix4x4() sm[0]=[scale_factor[0], 0, 0, 0] sm[1]=[0, scale_factor[1], 0, 0] sm[2]=[0, 0, scale_factor[2], 0] sm[3]=[0, 0, 0, 1] return sm def interpolateLinear(min, max, val): ''' returns 0.0 <= val <=1.0 ''' return val/float((max-min)) def interpolateSin(min, max, val): n=interpolateLinear(min, max, val) return sin(n) def interpolateCos(min, max, val): n=interpolateLinear(min, max, val) return cos(n) def interpolateSquared(min, max, val): n=interpolateLinear(min, max, val) return n**2 def interpolateRoot(min, max, val): n=interpolateLinear(min, max, val) return sqrt(n) def axisExtremes(mesh, axis): ''' takes a mesh object and returns a 3-tuple containing the two extremes of the bbox along that axis along with the distance betwen them ''' if axis == 'x': i=0 elif axis == 'y': i = 1 elif axis == 'z': i=2 min=max=0 for v in mesh.verts: if v.co[i] < min: min=v.co[i] if v.co[i] > max: max=v.co[i] # find length along axis length=max-min return (min, max, length) # taper and twist funcs ---------------------------------------- def taper(axis, startdef, enddef, interfunc): ''' tapers the selected mesh along the given axis according to provided args ''' global obj, mesh, meOr # obj=Blender.Object.GetSelected()[0] # mesh = obj.getData() ae = axisExtremes(meOr, axis) min = ae[0] max = ae[1] axis_length = ae[2] if axis == 'x': i=0 elif axis == 'y': i = 1 elif axis == 'z': i=2 Vsel = getSelectedVerts(meOr) for v in Vsel: dist=v.co[i]-min if -zero < dist < zero: dist=zero sf=interfunc(0, axis_length, dist) sf=startdef+(sf*(enddef-startdef)) sf=1-sf if axis == 'x': sf = (1,sf, sf) elif axis == 'y': sf = (sf, 1, sf) else: sf = (sf, sf, 1) sm=lscalematrix4x4(sf) hv=homovec(v.co) new=vecxmat(hv, sm) mesh.verts[v.index].co[0]=new[0] mesh.verts[v.index].co[1]=new[1] mesh.verts[v.index].co[2]=new[2] NMesh.PutRaw(mesh,mesh.name) #mesh.update() obj.makeDisplayList() def twist(axis, startdef, enddef, interfunc): ''' twists the selected mesh along the given axis according to provided args ''' global obj, mesh, meOr # obj=Blender.Object.GetSelected()[0] # mesh = obj.getData() ae = axisExtremes(meOr, axis) min = ae[0] max = ae[1] axis_length = ae[2] if axis == 'x': i=0 elif axis == 'y': i = 1 elif axis == 'z': i=2 Vsel = getSelectedVerts(meOr) for v in Vsel: dist=v.co[i]-min if -zero < dist < zero: dist=zero ang=interfunc(0, axis_length, dist) ang=startdef+(ang*(enddef-startdef)) ang=1-ang rm=makeRotMtx(axis, ang*2*pi) hv=homovec(v.co) new=vecxmat(hv, rm) mesh.verts[v.index].co[0]=new[0] mesh.verts[v.index].co[1]=new[1] mesh.verts[v.index].co[2]=new[2] NMesh.PutRaw(mesh,mesh.name) #mesh.update() obj.makeDisplayList() ########################## def getSelectedVerts(me):# ########################## theSelVerts = [] for v in me.verts: if v.sel: theSelVerts.append(v) return theSelVerts ###################### def InfoObj(): # # ###################### global obj, mesh, meOr, notObj, calque obj = Object.GetSelected()[0] print "Obj =", obj if (obj != []): if (obj.getType() == 'Mesh'): calque = obj.Layer # Le "layer" de l'object selectionne if obj.getType() == 'Mesh': mename = obj.getData().name mesh = obj.getData() meOr = obj.getData() notObj = 0 return (obj,mename,mesh) else: #print "Not a Mesh object" notObj = 1 return (notObj,0,0) else: print "No object selected" notObj = 1 return (notObj,0,0) ############## def Apply(): # # ############## global obj, mesh, meOr, startdef, enddef, notObj, calque meOr = obj.getData() obj.makeDisplayList() startdef.val = 0.0 enddef.val = 0.0 # Gui Stuff --------------------------------------------------------------------- startdef = Draw.Create(0.1) enddef = Draw.Create(0.9) taperx = Draw.Create(1) tapery = Draw.Create(0) taperz = Draw.Create(0) intlin = Draw.Create(1) intsin = Draw.Create(0) intsquare = Draw.Create(0) intcos=Draw.Create(0) introot=Draw.Create(0) BGet = Draw.Create(0) TTapTwi = Draw.Create(0) TTapTwiTEXT = "Taper" def gui(): global startdef, enddef, TTapTwi, TTapTwiTEXT global taperx, tapery, taperz global intlin, intsin, intsquare, intcos, introot BGL.glClearColor(0.75, 0.75, 0.75, 1.0) BGL.glClear(BGL.GL_COLOR_BUFFER_BIT) BGL.glColor3f(0.0,0.0,0.0) BGL.glRasterPos2i(5,420) Draw.Text("Taper and twist: v1.0 by flippyneck") BGL.glColor3f(1.0,0.25,0.0) BGL.glRasterPos2i(5,400) Draw.Text("WARNING!:") BGL.glRasterPos2i(5,385) Draw.Text("This script will overwrite your mesh") BGL.glRasterPos2i(5,370) Draw.Text("Copy it or save your file first!") BGL.glColor3f(0.0,0.0,0.0) BGL.glRasterPos2i(5,330) Draw.Text("(1) Select a single MESH object:") BGL.glRasterPos2i(5,300) Draw.Text("(2) Select LOCAL axis to deform along:") taperx = Draw.Toggle("X", 41, 5, 270, 15, 15, taperx.val, "Deform along local x axis") tapery = Draw.Toggle("Y", 42, 25, 270, 15, 15, tapery.val, "Deform along local y axis") taperz = Draw.Toggle("Z", 43, 45, 270, 15, 15, taperz.val, "Deform along local z axis") BGL.glRasterPos2i(5,240) Draw.Text("(3) Adjust extent of deform at start and end:") startdef = Draw.Slider("Start: ", 10, 5, 210, 150, 15, startdef.val, 0.0, 1.0, 0, 'deformation extent at start') enddef = Draw.Slider("End: ", 10, 5, 190, 150, 15, enddef.val, 0.0, 1.0, 0, 'deformation extent at end') BGL.glRasterPos2i(5,150) Draw.Text("(4) Choose an interpolation type:") intlin=Draw.Toggle("Linear", 20, 5, 120, 50, 15, intlin.val, "Deform object linearly along chosen axis") intsin=Draw.Toggle("Sin", 21, 60, 120, 50, 15, intsin.val, "Deform object by sinoidal progression along chosen axis") intcos=Draw.Toggle("Cos", 22, 115, 120, 50, 15, intcos.val, "Deform object by cosinal progression along chosen axis") intsquare=Draw.Toggle("Square", 23, 5, 100, 50, 15, intsquare.val, "Deform object by squared progression along chosen axis") introot=Draw.Toggle("Root", 24, 60, 100, 50, 15, introot.val, "Deform object by square root progression along chosen axis") BGL.glRasterPos2i(5,60) Draw.Text("(5) Go for it:") BGet = Draw.Button("Get Sel", 31, 5, 20, 50, 30, "Get selected object") TTapTwi = Draw.Toggle(TTapTwiTEXT, 32, 65, 20, 50, 30, TTapTwi.val, "Taper or Twist the selected object") Draw.Button("Apply", 35, 125, 20, 50, 30, "Apply transformation") Draw.Button("Quit", 34, 185, 20, 50, 30, "Quit this script") def event(evt, val): global obj, mesh, meOr if evt == Draw.ESCKEY and not val: if mesh: NMesh.PutRaw(meOr,mesh.name) obj.makeDisplayList() Draw.Exit() def bevent(evt): global obj, mesh, meOr, startdef, enddef, TTapTwi, TTapTwiTEXT if evt == 34: if mesh: NMesh.PutRaw(meOr,mesh.name) obj.makeDisplayList() Draw.Exit() if evt == 35: if mesh == []: InfoObj() Apply() Draw.Register(gui, event, bevent) elif evt != 34 and evt != 35: if evt == 20: intsin.val=intcos.val=intsquare.val=introot.val=0 Draw.Register(gui, event, bevent) elif evt == 21: intlin.val=intcos.val=intsquare.val=introot.val=0 Draw.Register(gui, event, bevent) elif evt == 22: intlin.val=intsin.val=intsquare.val=introot.val=0 Draw.Register(gui, event, bevent) elif evt == 23: intlin.val=intsin.val=intcos.val=introot.val=0 Draw.Register(gui, event, bevent) elif evt == 24: intlin.val=intsin.val=intcos.val=intsquare.val=0 Draw.Register(gui, event, bevent) elif evt == 31: InfoObj() elif evt == 32: if TTapTwi.val == 0: TTapTwiTEXT = "Taper" Draw.Register(gui, event, bevent) elif TTapTwi.val == 1: TTapTwiTEXT = "Twist" Draw.Register(gui, event, bevent) elif evt == 41: tapery.val = taperz.val = 0 Draw.Register(gui, event, bevent) elif evt == 42: taperx.val = taperz.val = 0 Draw.Register(gui, event, bevent) elif evt == 43: taperx.val = tapery.val = 0 Draw.Register(gui, event, bevent) if mesh == []: InfoObj() if taperx.val: axis_to_use = 'x' elif tapery.val: axis_to_use = 'y' else: axis_to_use = 'z' if intlin.val: interpolation_to_use = interpolateLinear elif intsin.val: interpolation_to_use = interpolateSin elif intcos.val: interpolation_to_use = interpolateCos elif intsquare.val: interpolation_to_use = interpolateSquared elif introot.val: interpolation_to_use = interpolateRoot if TTapTwi.val == 1: twist(axis_to_use, startdef.val, enddef.val, interpolation_to_use) elif TTapTwi.val == 0: taper(axis_to_use, startdef.val, enddef.val, interpolation_to_use) Draw.Register(gui, event, bevent)