3
""" Registration info for Blender menus: <- these words are ignored
7
Tip: 'use vertex paint color value to modify shape displacing vertices along normal'
10
__author__ = "Jean-Michel Soler (jms)"
11
__url__ = ("blender", "elysiun",
12
"Script's homepage, http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_displacementpainting.htm",
13
"Communicate problems and errors, http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender")
17
This script displaces mesh vertices according to vertex color values.
21
Select the mesh, enter Edit Mode and run this script to open its GUI. Options
22
include setting mode, orientation, size and number of repetitions of the
23
displacement. You can enter Vertex Paint mode and alternate applying
24
displacements and painting parts of the mesh.
26
Orientation includes vertex normals, local coordinates and noise (you may need
27
to resize the scripts window to view the noise menu below the "Last Error:"
28
line. This menu lets you define noise type from the many options available in
32
The "Create" button will make at any time a copy of the active mesh in its
33
current state, so you can keep it and continue working on the copy;<br>
34
One of the great possible uses of this script is to "raise" terrain from a
35
subdivided plane, for example, with good control of the process by setting
36
options, defining orientation and alternating vertex painting with
40
#----------------------------------------------
41
# jm soler, displacement paint 03/2002 - > 05/2004: disp_paintf
42
# Terrain Noise added suugered by Jimmy Haze
43
#----------------------------------------------
45
# http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_displacementpainting.htm
46
# Communiquer les problemes et erreurs sur:
47
# http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender
48
#---------------------------------------------
49
# ce script est propos� sous licence GPL pour etre associe
50
# a la distribution de Blender 2.33
51
#----------------------------------------------
52
# this script is released under GPL licence
53
# for the Blender 2.33 scripts package
54
#----------------------------------------------
55
# ***** BEGIN GPL LICENSE BLOCK *****
57
# Copyright (C) 2003, 2004: Jean-Michel Soler
59
# This program is free software; you can redistribute it and/or
60
# modify it under the terms of the GNU General Public License
61
# as published by the Free Software Foundation; either version 2
62
# of the License, or (at your option) any later version.
64
# This program is distributed in the hope that it will be useful,
65
# but WITHOUT ANY WARRANTY; without even the implied warranty of
66
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
67
# GNU General Public License for more details.
69
# You should have received a copy of the GNU General Public License
70
# along with this program; if not, write to the Free Software Foundation,
71
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
73
# ***** END GPL LICENCE BLOCK *****
74
# --------------------------------------------------------------------------
75
# 09/07/04 : Noise functions based on a piece of script by Jimmy Haze.
76
# --------------------------------------------------------------------------
80
from Blender.Draw import *
81
from Blender.BGL import *
82
from Blender.Noise import *
83
from Blender.Scene import *
86
# niveau du deplacement
92
# profondeur des couleurs primaires rgb
95
# limitation de la zone de travail sur le
96
# le materiau numer mat du tableau d'indices
97
# des materiaux. Par defaut mat =-1 ce qui signifie
98
# que toute la surface est traitee
114
E_MATVAL = [32,33,34,35,36,37,38,39,40,41,42,43,44]
126
E_NOISEVAL=[E_NOISEH,E_NOISELAC,E_NOISEOCT,E_NOISEOFF,E_NOISEBAS]
129
ExitTIP="Exit from this script session "
130
CreateTIP="Create a new copy of the selected shape"
131
ActionTIP="Do the current selected actions"
134
def copy_transform(ozero,Obis):
135
Obis.setSize(ozero.getSize());
136
Obis.setEuler(ozero.getEuler());
137
Obis.setLocation(ozero.getLocation())
141
global vindexm, ng, NOISE, NOISEDIM
142
global H,lacunarity,octaves,offset,basis
144
if ORIENTMenu.val==1:
145
for z in range(len(f.v)):
147
if vindex[f.v[z].index]!=0:
148
c=float(f.col[z].r+f.col[z].b+f.col[z].g)/maxcol*ng/vindex[f.v[z].index]
152
f.v[z].co[0]=f.v[z].co[0]+f.v[z].no[0]*c
153
f.v[z].co[1]=f.v[z].co[1]+f.v[z].no[1]*c
154
f.v[z].co[2]=f.v[z].co[2]+f.v[z].no[2]*c
156
elif ORIENTMenu.val==2:
157
for z in range(len(f.v)):
159
if vindex[f.v[z].index]!=0:
160
c=float(f.col[z].r+f.col[z].b+f.col[z].g)/maxcol*ng/vindex[f.v[z].index]
164
if TAXEList[1][t].val==1:
165
f.v[z].co[t]=f.v[z].co[t]+c
167
elif ORIENTMenu.val==3 and NOISE<9:
168
for z in range(len(f.v)):
170
if vindex[f.v[z].index]!=0:
171
nx=f.v[z].co[0]/NOISEDIM
172
ny=f.v[z].co[1]/NOISEDIM
173
nz=f.v[z].co[2]/NOISEDIM
174
nn = ng * noise((nx,ny,nz),NOISE)
175
c=float(f.col[z].r+f.col[z].b+f.col[z].g)/maxcol*nn/vindex[f.v[z].index]
178
f.v[z].co[0]=f.v[z].co[0]+f.v[z].no[0]*c
179
f.v[z].co[1]=f.v[z].co[1]+f.v[z].no[1]*c
180
f.v[z].co[2]=f.v[z].co[2]+f.v[z].no[2]*c
182
elif ORIENTMenu.val==3 and NOISE==9:
183
for z in range(len(f.v)):
185
if vindex[f.v[z].index]!=0:
186
nx=f.v[z].co[0]/NOISEDIM
187
ny=f.v[z].co[1]/NOISEDIM
188
nz=f.v[z].co[2]/NOISEDIM
189
nn = ng * cellNoise((nx,ny,nz))
190
c=float(f.col[z].r+f.col[z].b+f.col[z].g)/maxcol*nn/vindex[f.v[z].index]
193
f.v[z].co[0]=f.v[z].co[0]+f.v[z].no[0]*c
194
f.v[z].co[1]=f.v[z].co[1]+f.v[z].no[1]*c
195
f.v[z].co[2]=f.v[z].co[2]+f.v[z].no[2]*c
197
elif ORIENTMenu.val==3 and NOISE==10:
198
for z in range(len(f.v)):
200
if vindex[f.v[z].index]!=0:
201
nx=f.v[z].co[0]/NOISEDIM
202
ny=f.v[z].co[1]/NOISEDIM
203
nz=f.v[z].co[2]/NOISEDIM
204
nn = ng * heteroTerrain((nx,ny,nz),H,lacunarity,octaves,offset,basis)
205
c=float(f.col[z].r+f.col[z].b+f.col[z].g)/maxcol*nn/vindex[f.v[z].index]
208
f.v[z].co[0]=f.v[z].co[0]+f.v[z].no[0]*c
209
f.v[z].co[1]=f.v[z].co[1]+f.v[z].no[1]*c
210
f.v[z].co[2]=f.v[z].co[2]+f.v[z].no[2]*c
214
global MODEMenu, vindex,ng, mat, ORIName, NEWName
215
global ERROR, TextERROR
217
Me=Object.GetSelected()
219
if Me[0].getType()=='Mesh':
222
ORIName=Me[0].getData().name
223
me=NMesh.GetRaw(Me[0].getData().name)
249
Me[0].makeDisplayList()
252
TextERROR='No color on this Object.'
254
def NEWMEcreation(obj):
256
if obj.getType()=='Mesh':
258
objnumber=-1; namelist=[]
262
if ozero.getType()=='Mesh':
263
namelist.append(ozero.getData().name)
266
nomdelobjet=ozero.getName()
267
Mesh=Blender.NMesh.GetRawFromObject(nomdelobjet)
268
name=obj.getData().name
269
n=0; name2=name[:];ok=0
273
if n0.find(name2)==0:
274
ok=0;name2=name[0:name.find('.')+1]+'%s'%(n+1)
279
Obis = Blender.NMesh.PutRaw(Mesh,name2)
280
copy_transform(ozero,Obis)
281
Obis.makeDisplayList()
283
def DOCMat_list(TMATList):
285
Me=Object.GetSelected()
287
if Me[0].getType()=='Mesh':
288
me=NMesh.GetRaw(Me[0].getData().name)
289
if len(me.materials)!=0:
291
for mat in me.materials:
292
TMATList[1][n][0]=mat.R
293
TMATList[1][n][1]=mat.G
294
TMATList[1][n][2]=mat.B
301
MOname = "MODE MENU %t|Normal %x1|Material %x2|Selected %x3"
302
ORname = "ORIENT MENU %t|From Normal %x1|Local Axes %x2| Noise %x3"
303
NOname = "NOISE MENU %t|BLENDER %x1|STDPERLIN %x2|NEWPERLIN %x3|VORONOI_F1%x4|VORONOI_F2%x5|VORONOI_F3%x6|VORONOI_F4%x7|VORONOI_F2F1%x8|VORONOI_CRACKLE%x9|CELLNOISE%x10|HETEROTENOISE%x11"
306
ORIENTMenu = Create(1)
307
NOISEMenu = Create(1)
320
NOISEDIMbout=Create(NOISEDIM)
322
lacunarityBout=Create(lacunarity)
323
octavesBout=Create(octaves)
324
offsetBout=Create(offset)
325
basisBout=Create(basis)
328
noiseTYPE={0:'BLENDER',
342
TMATList[1].append([0.0,0.0,0.0])
343
TMATList[2].append(Create(0))
345
TAXEList=[['X','Y','Z'],[]]
347
TAXEList[1].append(Create(0))
357
global MODEMenu, NSIZE, TDOCMat,TMATList, TAXEList
358
global mat, ORIName, NEWName, ORIENTMenu
359
global NRepeat, ERROR, TextERROR , NOISE, NOISEMenu, NOISEDIMbout,NOISEDIM
360
global HBout,lacunarityBout,octavesBout,offsetBout,basisBout
361
global noiseTYPE, ExitTIP, CreateTIP, ActionTIP
363
size=Buffer(GL_FLOAT, 4)
364
glGetFloatv(GL_SCISSOR_BOX, size)
367
for s in [0,1,2,3]: size[s]=int(size[s])
369
glClear(GL_COLOR_BUFFER_BIT)
371
glColor3f(0.0,0.0,0.0)
372
glRectf(4,size[3],534,size[3]-32 )
374
glColor3f(1.0,1.0,1.0)
375
glRasterPos2f(20, size[3]-15)
376
Text("Script Python de displacement paintingt")
378
glRasterPos2f(20, size[3]-28)
379
Text("Jean-michel Soler, juillet 2004")
385
Button("Create" ,E_CREATE ,5 ,size[3]-n0+16 ,60 ,20,CreateTIP)
386
Button("Action" ,E_ACTION ,5 ,size[3]-n0-4 ,60 ,20,ActionTIP)
387
Button("Exit" ,E_EXIT ,5 ,size[3]-n0-24 ,60 ,20,ExitTIP)
389
NRepeat=Number("repeat" ,E_REPEAT ,5 ,size[3]-n0-50 ,75 ,20, NRepeat.val,1,10)
391
glColor3f(0.0,0.0,0.0)
392
glRasterPos2f(80 ,size[3]-n0+24)
395
MODEMenu= Menu(MOname, E_MODE ,80 ,size[3]-n0 ,100,20, MODEMenu.val, "MODE menu.")
398
TDOCMat=Toggle("Doc Mat" ,E_DOCMAT ,180 ,size[3]-n0 ,60 ,20,TDOCMat.val)
401
for t in range(TMATList[0]):
402
glCl3(TMATList[1][t][0],
409
TMATList[2][t]=Toggle("%s"%t , 32+t ,80+t*40+5 ,size[3]-n0-50 ,30 , 20,TMATList[2][t].val)
411
glColor3f(1.0,0.3,0.0)
412
glRasterPos2f(80+40+5 ,size[3]-n0-80)
414
Text('Last error : '+TextERROR)
416
Text('Last error : ')
418
glColor3f(0.0,0.0,0.0)
419
glRasterPos2f(240 ,size[3]-n0+24)
421
ORIENTMenu= Menu(ORname, E_ORIENT ,240 ,size[3]-n0 ,100,20, ORIENTMenu.val, "ORIENT menu.")
423
if ORIENTMenu.val==2 :
425
TAXEList[1][t]=Toggle("%s"%TAXEList[0][t],
427
240+100+t*30 , size[3]-n0 ,30 , 20,
431
if ORIENTMenu.val==3 :
432
glRasterPos2f(240 ,size[3]-n0-90-4)
434
NOISEMenu= Menu(NOname, E_NOISEME , 240 ,size[3]-n0-118 ,110,20, NOISEMenu.val, "NOISE menu.")
435
NOISEDIMbout=Number(" Dim: " ,E_NOISEDIM , 240 ,size[3]-n0-138 ,110,20, NOISEDIMbout.val, 1,100)
437
if NOISEMenu.val==11:
438
basisBout=Slider(noiseTYPE[basisBout.val],
439
E_NOISEBAS ,40 ,size[3]-n0-118 ,175,20, basisBout.val, 0,9,)
440
HBout= Slider("H", E_NOISEH ,40 ,size[3]-n0-138 ,175,20, HBout.val, -2.0,+2.0,0,)
441
lacunarityBout=Slider("lacunarity", E_NOISELAC ,40 ,size[3]-n0-158 ,175,20, lacunarityBout.val, -4.0,+4.0,0,)
442
octavesBout=Slider("octave", E_NOISEOCT ,40 ,size[3]-n0-178 ,175,20, octavesBout.val, -10.0,+10.0,0,)
443
offsetBout=Slider("offset", E_NOISEOFF ,40 ,size[3]-n0-198 ,175,20, offsetBout.val, -5.0,+5.0,0,)
445
NSIZE= Slider("Disp Size", E_NSIZE ,80 ,size[3]-n0-20 ,260,20, NSIZE.val, -4.0,+4.0,0,"SIZE.")
451
if (evt== QKEY and not val): Exit()
454
global MODEMenu, NSIZE, ng, TMATList
455
global mat, ORIENTMenu, NRepeat, TAXEList
456
global ERROR,TextERROR, NOISE, NOISEMenu, NOISEDIMbout,NOISEDIM
457
global HBout,lacunarityBout,octavesBout,offsetBout,basisBout
458
global H,lacunarity,octaves,offset,basis
464
elif (evt== E_ACTION):
465
for n in range(NRepeat.val):
468
elif (evt== E_NSIZE):
471
elif (evt== E_DOCMAT) or (evt in E_MATVAL):
472
Me=Object.GetSelected()
474
if Me[0].getType()=='Mesh':
475
TMATList=DOCMat_list(TMATList)
477
for TMat in TMATList[2]:
479
mat.append(TMATList[2].index(TMat))
483
TextERROR='Selected Object is not a mesh.'
486
TextERROR='No Selected Object.'
489
elif (evt== E_CREATE):
491
NEWMEcreation(Blender.Object.GetSelected()[0])
492
Blender.Draw.Redraw()
495
TextERROR='No Selected Object.'
497
elif (evt== E_NOISEME):
498
NOISE=NOISEMenu.val-1
500
elif (evt in E_NOISEVAL):
502
lacunarity=lacunarityBout.val
503
octaves=octavesBout.val
504
offset=offsetBout.val
507
elif (evt== E_NOISEDIM):
508
NOISEDIM=NOISEDIMbout.val
510
Blender.Draw.Redraw()
512
Register(draw, event, bevent)