Interactive ‘Formula’ deformation tool
#-----------------------------------------------------------------
#_Distort mesh with formulae from math import *
#_Distort mesh with noise from Blender.Noise import *
#!BPY
"""
Name: 'Formula deformation tool'
Blender: 233
Group: 'Mesh'
Tip: 'Distort sellected mesh with formulae and noise'
"""
##################################################################
# Jimmy Hazevoet July 2004
#-----------------------------------------------------------------
# Interactive 'Formula' deformation tool -------------------------
#-----------------------------------------------------------------
#_Distort mesh with formulae from math import *
#_Distort mesh with noise from Blender.Noise import *
#-----------------------------------------------------------------
# A few simple examples:
#
#EXAMPLE 1:
# d: sin(x*y*z)*2
#
#EXAMPLE 2:
# d: x*sin(u*4*pi) + y*cos(u*4*pi)
#
#EXAMPLE 3:
# d: exp(u*4*pi)*2
#
#EXAMPLE 4:turbulence((x,y,z),depth,soft/hard,basisnoise,amp,freq)
# d: turbulence((x,y,z), 2, 0, 3, 0.5, 2.0)
#
###################################################################
#_Interactive mesh deform function copied from: #
# Taper and Twist.py ( 'flippyneck' / '_Ph_' ). #
#_Save and Load file function copied from: #
# Tessalate.py ( 'JMS' ). #
###################################################################
import Blender
from Blender import *
from Blender.Draw import *
from Blender.BGL import *
from Blender.Noise import *
from math import *
#------------------------------------------------------------------
save_load_as = 'formtest 01.form'
#------------------------------------------------------------------
infotext = ""
dirpath=Blender.sys.dirname(Blender.Get('filename'))
print dirpath.replace('\\','/')+'/'
form_Path=dirpath.replace('\\','/')+'/'
#-------------------
class buttons:
global form_Path
def __init__(self):
self.Record={}
self.Record['Save']=Create(0)
self.Record['Load']=Create(0)
self.Record['SaveAs']=Create(save_load_as)
self.path=form_Path
self.buttonslist=[]
self.Effecttype = Create(2)
self.SIZx = Create(1.0)
self.SIZy = Create(1.0)
self.SIZz = Create(1.0)
self.Fdstring = Create("sin(u*2*pi)") # preset formula #
self.Fxstring = Create("0")
self.Fystring = Create("0")
self.Fzstring = Create("0")
#------------------------------------------------------------------------
def prf_dump(self):
global infotext
n0=dir(self)
f=open(self.path+self.Record['SaveAs'].val,'w')
for n in n0:
#print n0,
if (n.find('__')!=0 and n.find('prf_dump')==-1
and n.find('prf_load')==-1 and n.find('prf_save')==-1
and n.find('path')==-1) and n.find('Record')==-1:
exec """l1=str(type(self.%s))"""%n
l0=n+';'+l1+'
'
f.write(l0)
exec """f.write(str(self.%s))"""%n
infotext = " File Saved !"
f.write('
')
f.close()
#---------------------
def prf_load(self):
global infotext
try:
f=open(self.path+self.Record['SaveAs'].val,'r')
buffer=f.readlines()
f.close()
for n in range(0,len(buffer),2):
var=buffer[n].split(';')
if var[0] not in self.buttonslist:
self.buttonslist.append(var[0])
if buffer[n].find("""<type 'str""")!=-1:
exec """self.%s='''%s'''"""%(var[0],buffer[n+1][:-1])
elif buffer[n].find("""<type 'dict'>""")!=-1:
exec """provdict=%s"""%buffer[n+1][:-1]
for d in provdict.keys():
l00="""self.%s['%s'].val=%s"""%(var[0],d,provdict[d])
exec l00
elif buffer[n].find("""<type 'Button'>""")!=-1:
exec """self.%s.val=%s"""%(var[0],buffer[n+1][:-1])
infotext = " File Loaded !"
except:
infotext = "Load file: FAILED !"
B=buttons()
#-----------------------------------------------------------------------
def form_input_fu(x,y,z):
global B, infotext
x = (x-x/2)/B.SIZx.val
y = (y-y/2)/B.SIZy.val
z = (z-z/2)/B.SIZz.val
dfunc = B.Fdstring.val
xfunc = B.Fxstring.val
yfunc = B.Fystring.val
zfunc = B.Fzstring.val
try:
if (B.Effecttype.val==1): # manual
u = sqrt((x-x/2)**2+(y-y/2)**2)
v = sqrt((y-y/2)**2+(z-z/2)**2)
w = sqrt((z-z/2)**2+(x-x/2)**2)
d = eval(dfunc)
x = eval(xfunc)
y = eval(yfunc)
z = eval(zfunc)
if B.Effecttype.val==2: # spherical
u = sqrt((x-x/2)**2+(y-y/2)**2)
v = sqrt((y-y/2)**2+(z-z/2)**2)
w = sqrt((z-z/2)**2+(x-x/2)**2)
d = eval(dfunc)
x = d
y = d
z = d
if (B.Effecttype.val==3): # cilindrical
u = sqrt((x-x/2)**2+(y-y/2)**2)
v = sqrt((y-y/2)**2+(z-z/2)**2)
w = sqrt((z-z/2)**2+(x-x/2)**2)
d = eval(dfunc)
x = d
y = d
z = d
if (B.Effecttype.val==4): # z radial
u = sqrt((x-x/2)**2+(y-y/2)**2)
v = sqrt((y-y/2)**2+(z-z/2)**2)
w = sqrt((z-z/2)**2+(x-x/2)**2)
d = eval(dfunc)
x = 0
y = 0
z *= d
if (B.Effecttype.val==5): # y radial
u = sqrt((z-z/2)**2+(x-x/2)**2)
v = sqrt((y-y/2)**2+(z-z/2)**2)
w = sqrt((x-x/2)**2+(y-y/2)**2)
d = eval(dfunc)
x = 0
y *= d
z = 0
if (B.Effecttype.val==6): # x radial
u = sqrt((y-y/2)**2+(z-z/2)**2)
v = sqrt((z-z/2)**2+(x-x/2)**2)
w = sqrt((x-x/2)**2+(y-y/2)**2)
d = eval(dfunc)
x *= d
y = 0
z = 0
except:
infotext = "Warning: input error !"
return x,y,z
#-----------------------------------------------------------------------
def Get_And_Apply_fu():
global B, infotext
try:
obj=Blender.Object.GetSelected()[0]
except:
infotext = "Nothing sellected!"
return 0
if obj:
dat = obj.getData()
if type(dat) != Types.NMeshType:
infotext = "Sellect a mesh!"
return 0
else:
pass
if obj != Blender.working_object:
Blender.working_object = obj
Blender.base_data = obj.getData()
mesh=obj.getData()
normals = []
coordinates = []
for v in mesh.verts:
i = mesh.verts.index(v)
normals.append([v.no[0],v.no[1],v.no[2]])
coordinates.append([v.co[0],v.co[1],v.co[2]])
inp = form_input_fu(v.co[0],v.co[1],v.co[2])
if (B.Effecttype.val==1): # manual
v.co[0] = coordinates[i][0] + (inp[0] * normals[i][0])
v.co[1] = coordinates[i][1] + (inp[1] * normals[i][1])
v.co[2] = coordinates[i][2] + (inp[2] * normals[i][2])
if (B.Effecttype.val==2): # spherical
for z in range(3):
v.co[z] = coordinates[i][z] + (inp[2] * normals[i][z])
if (B.Effecttype.val==3): # cilindrical
for c in range(2):
v.co[c] = coordinates[i][c] + (inp[2] * normals[i][c])
else: # x,y,z radial
v.co[0] = coordinates[i][0] + (inp[0] * normals[i][0])
v.co[1] = coordinates[i][1] + (inp[1] * normals[i][1])
v.co[2] = coordinates[i][2] + (inp[2] * normals[i][2])
mesh.update()
obj.makeDisplayList()
#----------------------------
def restore(object):
m=object.getData()
m=Blender.base_data
m.update()
object.makeDisplayList()
#----------------------------
Blender.working_object=None
Blender.base_data=None
#------------------------------------------------------------------------
def GUI_Box(x, y, w, h, r, g, b):
glColor3f(r+0.075, g+0.075, b+0.075)
glRecti(x+6, y-6, w+6, h-6)
glColor3f(r+0.05, g+0.05, b+0.05)
glRecti(x+5, y-5, w+5, h-5)
glColor3f(r+0.025, g+0.025, b+0.025)
glRecti(x+4, y-4, w+4, h-4)
glColor3f(r, g, b)
glRecti(x+3, y-3, w+3, h-3)
glColor3f(r-0.025, g-0.025, b-0.025)
glRecti(x+2, y-2, w+2, h-2)
glColor3f(r-0.3, g-0.3, b-0.3)
glRecti(x, y, w, h)
glColor3f(r+0.2, g+0.2, b+0.2)
glRecti(x+1, y+1, w-1, h-1)
glColor3f(r-0.1,g-0.1,b-0.1)
glLineWidth(1)
glBegin(GL_LINES)
glVertex2d(250,20)
glVertex2d(405,20)
glEnd()
glBegin(GL_LINES)
glVertex2d(330,36)
glVertex2d(390,36)
glEnd()
glBegin(GL_LINES)
glVertex2d(180,27)
glVertex2d(335,27)
glEnd()
glColor3f(0.1, 0.1, 0.1)
glRasterPos2d(340, 24)
Text("Formula D.")
#------------------------------------------------------------------------
def gui():
global B, infotext
BGL.glClearColor(0.6, 0.6, 0.6, 1)
BGL.glClear(BGL.GL_COLOR_BUFFER_BIT)
eft="Effect%t|Manual%x1|Spherical%x2|Cilindrical%x3|Z radial%x4|Y radial%x5|X radial%x6"
B.Effecttype = Menu(eft, 3, 250,80,140,18, B.Effecttype.val)
if (B.Effecttype.val==1):
GUI_Box(10, 10, 420, 215, 0.5,0.5,0.5)
glColor3f(1.0, 0.0, 0.0)
glRasterPos2d(40, 195)
Text(infotext)
B.Fdstring=String("d: ",3,40,170,350,18,B.Fdstring.val,256,
"d (u,v,w, x,y,z)")
B.Fxstring=String("x: ",3,40,145,350,18,B.Fxstring.val,256,
"x (d, u,v,w, x,y,z)")
B.Fystring=String("y: ",3,40,125,350,18,B.Fystring.val,256,
"y (d, u,v,w, x,y,z)")
B.Fzstring=String("z: ",3,40,105,350,18,B.Fzstring.val,256,
"z (d, u,v,w, x,y,z)")
else:
GUI_Box(10, 10, 420, 150, 0.5,0.5,0.5)
glColor3f(1.0, 0.0, 0.0)
glRasterPos2d(40, 130)
Text(infotext)
B.Fdstring=String("d: ",3,40,105,350,18,B.Fdstring.val,256,
"d (u,v,w, x,y,z)")
B.SIZx=Number("x:",3,40,80,70,18,B.SIZx.val,0.001,50.0,"size X")
B.SIZy=Number("y:",3,110,80,70,18,B.SIZy.val,0.001,50.0,"size Y")
B.SIZz=Number("z:",3,180,80,70,18,B.SIZz.val,0.001,50.0,"size Z")
Button("Apply",12,40,55,70,18,"Apply deformation.")
Button("Restore",11,110,55,70,18,"Restore to original mesh.")
Button("Redraw",3,180,55,70,18," Redraw mesh.")
Button("Reset",4,250,55,70,18,"Restore to original and Reset input.")
Button("Exit",1,320,55,70,18,"Exit and Restore to original.")
lstip="Save/Load file name"
BRSAtxt=B.Record['SaveAs'].val
B.Record['SaveAs']=String("File: ",3,180,35,140,18,BRSAtxt,256,lstip)
B.Record['Save']=Button("Save", 5, 40, 35, 70, 18)
B.Record['Load']=Button("Load", 6, 110, 35, 70, 18)
#---------------------------------------
def event(evt, val):
if (evt == ESCKEY and not val):
name = "OK?%t|Exit %x1"
result = Blender.Draw.PupMenu(name)
if result == 1:
Exit()
#---------------------------------------
def bevent(evt):
global B, infotext
if evt == 1:
name = "OK?%t|Exit %x1"
result = Blender.Draw.PupMenu(name)
if result == 1:
Exit()
if evt == 5: # Save file #
infotext = ""
name = "OK?%t|Save %x1"
result = Blender.Draw.PupMenu(name)
if result == 1:
B.prf_dump()
Blender.Window.Redraw()
if evt == 6: # Load file #
infotext = ""
name = "OK?%t|Load %x1"
result = Blender.Draw.PupMenu(name)
if result == 1:
B.prf_load()
Blender.Window.Redraw()
if evt == 4: # Reset value's , and Restore mesh #
infotext = ""
name = "OK?%t|Reset %x1"
result = Blender.Draw.PupMenu(name)
if result == 1:
B.SIZx = Create(1.0)
B.SIZy = Create(1.0)
B.SIZz = Create(1.0)
B.Fdstring = Create("0")
B.Fxstring = Create("0")
B.Fystring = Create("0")
B.Fzstring = Create("0")
Draw()
if evt == 11: # Restore mesh #
infotext = ""
if Blender.working_object:
restore(Blender.working_object)
return 0
if evt == 12: # Apply deformation #
infotext = ""
name = "OK?%t|Apply deformation %x1"
result = Blender.Draw.PupMenu(name)
if result == 1:
obj=Blender.Object.GetSelected()[0]
m=obj.getData()
Blender.base_data=m
restore(obj)
infotext = "Mesh 'Deformed'."
return 0
if Blender.working_object:
restore(Blender.working_object)
if evt == 3: # Update mesh #
infotext = ""
Get_And_Apply_fu()
Draw()
Register(gui, event, bevent)