Fix #105067: Node Wrangler: cannot preview multi-user material group
[blender-addons.git] / add_mesh_extra_objects / add_mesh_rocks / rockgen.py
blobf9ca2051f9aa556db5de94e9dcd0c45c583ceb5c
1 # SPDX-FileCopyrightText: 2019-2023 Blender Foundation
3 # SPDX-License-Identifier: GPL-2.0-or-later
5 # Blender rock creation tool
7 # Based on BlenderGuru's asteroid tutorial and personal experimentation.
8 # Tutorial: http://www.blenderguru.com/how-to-make-a-realistic-asteroid/
9 # Update with another tutorial shared by "rusted" of BlenderArtists:
10 # Tutorial: http://saschahenrichs.blogspot.com/2010/03/3dsmax-environment-modeling-1.html
12 # Uses the NumPy Gaussian random number generator to generate a
13 # a rock within a given range and give some randomness to the displacement
14 # texture values. NumPy's gaussian generator was chosen as, based on
15 # profiling I performed, it runs in about half the time as the built in
16 # Python gaussian equivalent. I would like to shift the script to use the
17 # NumPy beta distribution as it ran in about half the time as the NumPy
18 # gaussian once the skew calculations are added.
20 # Set lower and upper bounds to the same for no randomness.
22 # Tasks:
23 # Generate meshes with random scaling between given values.
24 # - Allow for a skewed distribution
25 # *** Completed on 4/17/2011 ***
26 # - Create a set of meshes that can be used
27 # Give the user the ability to set the subsurf level (detail level)
28 # *** Completed on 4/29/2011 ***
29 # - Set subsurf modifiers to default at view:3, render:3.
30 # *** Completed on 4/17/2011 ***
31 # - Set crease values to allow for hard edges on first subsurf.
32 # *** Completed on 4/29/2011 ***
33 # Be able to generate and add a texture to the displacement modifiers.
34 # *** Completed 5/17/2011 ***
35 # - Generate three displacement modifiers.
36 # - The first only uses a Musgrave for initial intentations.
37 # *** Now generating four displacement modifiers ***
38 # *** Completed on 5/17/2011 ***
39 # - Set a randomness for the type and values of the displacement texture.
40 # *** Completed 5/9/2011 ***
41 # - Allow the user to set a value for the range of displacement.
42 # -> Modification: have user set "roughness" and "roughness range".
43 # *** Compleded on 4/23/2011 ***
44 # Set material settings and assign material textures
45 # *** Completed 6/9/2011 ***
46 # - Mossiness of the rocks.
47 # *** Completed 6/9/2011 ***
48 # - Color of the rocks.
49 # *** Completed 5/16/2011 ***
50 # - Wetness/shinyness of the rock.
51 # *** Completed 5/6/2011 ***
52 # - For all the user provides a mean value for a skewed distribution.
53 # *** Removed to lessen usage complexity ***
54 # Add some presets (mesh) to make it easier to use
55 # - Examples: river rock, asteroid, quaried rock, etc
56 # *** Completed 7/12/2011 ***
58 # Code Optimization:
59 # Remove all "bpy.ops" operations with "bpy.data" base operations.
60 # Remove material/texture cataloging with building a list of
61 # returned values from bpy.data.*.new() operations.
62 # *** Completed on 9/6/2011 ***
63 # Search for places where list comprehensions can be used.
64 # Look for alternate methods
65 # - Possible alternate and more efficient data structures
66 # - Possible alternate algorithms may realize greater performance
67 # - Look again at multi-processing. Without bpy.ops is might
68 # be viable.
70 # Future tasks:
71 # Multi-thread the script
72 # *** Will not be implemented. Multi-processing is adding to much
73 # overhead to realize a performance increase ***
74 # - Learn basic multi-threading in Python (multiprocessing)
75 # - Break material generation into separate threads (processes)
76 # - Break mesh generation into separate threads (processes)
77 # - Move name generation, texture ID generation, etc to process first
78 # - Roll version to 2.0 on completion
80 # Paul "BrikBot" Marshall
81 # Created: April 17, 2011
82 # Last Modified: November 17, 2011
83 # Homepage (blog): http://post.darkarsenic.com/
84 # //blog.darkarsenic.com/
85 # Thanks to Meta-Androco, RickyBlender, Ace Dragon, and PKHG for ideas
86 # and testing.
88 # Coded in IDLE, tested in Blender 2.59. NumPy Recommended.
89 # Search for "@todo" to quickly find sections that need work.
91 # Remember -
92 # Functional code comes before fast code. Once it works, then worry about
93 # making it faster/more efficient.
95 import bpy
96 import time
97 from . import (
98 settings,
99 utils
101 from .utils import skewedGauss
102 from .randomize_texture import randomizeTexture
103 from bpy_extras import object_utils
104 from mathutils import (
105 Vector
107 from bpy.props import (
108 BoolProperty,
109 IntProperty,
110 FloatProperty,
111 FloatVectorProperty,
112 EnumProperty
115 # This try block allows for the script to psudo-intelligently select the
116 # appropriate random to use. If Numpy's random is present it will use that.
117 # If Numpy's random is not present, it will through a "module not found"
118 # exception and instead use the slower built-in random that Python has.
119 try:
120 from numpy.random import random_integers as randint
121 from numpy.random import normal as gauss
122 from numpy.random import (
123 seed,
124 weibull)
125 # print("Rock Generator: Numpy found.")
126 numpy = True
127 except:
128 from random import (
129 randint,
130 gauss,
131 seed)
132 from random import weibullvariate as weibull
133 print("Rock Generator: Numpy not found. Using Python's random.")
134 numpy = False
136 # Global variables:
137 LASTROCK = 0
140 # Creates a new mesh:
142 # param: verts - Vector of vertices for the mesh.
143 # edges - Edges for the mesh. Can be "[]".
144 # faces - Face tuples corresponding to vertices.
145 # name - Name of the mesh.
146 def createMeshObject(context, verts, edges, faces, name):
147 # Create new mesh
148 mesh = bpy.data.meshes.new(name)
150 # Make a mesh from a list of verts/edges/faces.
151 mesh.from_pydata(verts, edges, faces)
153 # Update mesh geometry after adding stuff.
154 mesh.update()
156 if bpy.context.mode == "EDIT_MESH":
157 bpy.ops.object.mode_set(mode='OBJECT')
159 return object_utils.object_data_add(context, mesh, operator=None)
162 # Generates an object based on one of several different mesh types.
163 # All meshes have exactly eight vertices, and may be built from either
164 # tri's or quads.
166 # param: muX - mean X offset value
167 # sigmaX - X offset standard deviation
168 # scaleX - X upper and lower bounds
169 # upperSkewX - Is the distribution upperskewed?
170 # muY - mean Y offset value
171 # sigmaY - Y offset standard deviation
172 # scaleY - Y upper and lower bounds
173 # upperSkewY - Is the distribution upperskewed?
174 # muZ - mean Z offset value
175 # sigmaZ - Z offset standard deviation
176 # scaleZ - Z upper and lower bounds
177 # upperSkewY - Is the distribution upperskewed?
178 # base - base number on the end of the object name
179 # shift - Addition to the base number for multiple runs.
180 # scaleDisplace - Scale the displacement maps
182 # return: name - the built name of the object
183 def generateObject(context, muX, sigmaX, scaleX, upperSkewX, muY, sigmaY,
184 scaleY, upperSkewY, muZ, sigmaZ, scaleZ, upperSkewZ, base,
185 shift, scaleDisplace, scale_fac):
186 x = []
187 y = []
188 z = []
189 shape = randint(0, 11)
191 # Cube
192 # Use parameters to re-scale cube:
193 # Reversed if/for nesting. Should be a little faster.
194 if shape == 0:
195 for j in range(8):
196 if sigmaX == 0:
197 x.append(scaleX[0] / 2)
198 else:
199 x.append(skewedGauss(muX, sigmaX, scaleX, upperSkewX) / 2)
200 if sigmaY == 0:
201 y.append(scaleY[0] / 2)
202 else:
203 y.append(skewedGauss(muY, sigmaY, scaleY, upperSkewY) / 2)
204 if sigmaZ == 0:
205 z.append(scaleZ[0] / 2)
206 else:
207 z.append(skewedGauss(muZ, sigmaZ, scaleZ, upperSkewZ) / 2)
208 elif shape == 1:
209 for j in range(8):
210 if j in [0, 1, 3, 4]:
211 if sigmaX == 0:
212 x.append(scaleX[0] / 2)
213 else:
214 x.append(skewedGauss(muX, sigmaX, scaleX, upperSkewX) / 2)
215 if sigmaY == 0:
216 y.append(scaleY[0] / 2)
217 else:
218 y.append(skewedGauss(muY, sigmaY, scaleY, upperSkewY) / 2)
219 if sigmaZ == 0:
220 z.append(scaleZ[0] / 2)
221 else:
222 z.append(skewedGauss(muZ, sigmaZ, scaleZ, upperSkewZ) / 2)
223 elif j in [2, 5]:
224 if sigmaX == 0:
225 x.append(0)
226 else:
227 x.append(skewedGauss(muX, sigmaX, scaleX, upperSkewX) / 4)
228 if sigmaY == 0:
229 y.append(scaleY[0] / 2)
230 else:
231 y.append(skewedGauss(muY, sigmaY, scaleY, upperSkewY) / 2)
232 if sigmaZ == 0:
233 z.append(scaleZ[0] / 2)
234 else:
235 z.append(skewedGauss(muZ, sigmaZ, scaleZ, upperSkewZ) / 2)
236 elif j in [6, 7]:
237 if sigmaX == 0:
238 x.append(0)
239 else:
240 x.append(skewedGauss(0, sigmaX, scaleX, upperSkewX) / 4)
241 if sigmaY == 0:
242 y.append(0)
243 else:
244 y.append(skewedGauss(0, sigmaY, scaleY, upperSkewY) / 4)
245 if sigmaZ == 0:
246 z.append(scaleZ[0] / 2)
247 else:
248 z.append(skewedGauss(muZ, sigmaZ, scaleZ, upperSkewZ) / 2)
249 elif shape == 2:
250 for j in range(8):
251 if j in [0, 2, 5, 7]:
252 if sigmaX == 0:
253 x.append(scaleX[0] / 4)
254 else:
255 x.append(skewedGauss(muX, sigmaX, scaleX, upperSkewX) / 4)
256 if sigmaY == 0:
257 y.append(0)
258 else:
259 y.append(skewedGauss(0, sigmaY, scaleY, upperSkewY) / 4)
260 if sigmaZ == 0:
261 z.append(scaleZ[0] / 2)
262 else:
263 z.append(skewedGauss(muZ, sigmaZ, scaleZ, upperSkewZ) / 4)
264 elif j in [1, 3, 4, 6]:
265 if sigmaX == 0:
266 x.append(scaleX[0] / 2)
267 else:
268 x.append(skewedGauss(muX, sigmaX, scaleX, upperSkewX) / 2)
269 if sigmaY == 0:
270 y.append(scaleY[0] / 2)
271 else:
272 y.append(skewedGauss(muY, sigmaY, scaleY, upperSkewY) / 2)
273 if sigmaZ == 0:
274 z.append(scaleZ[0] / 2)
275 else:
276 z.append(skewedGauss(muZ, sigmaZ, scaleZ, upperSkewZ) / 2)
277 elif shape == 3:
278 for j in range(8):
279 if j > 0:
280 if sigmaX == 0:
281 x.append(scaleX[0] / 2)
282 else:
283 x.append(skewedGauss(muX, sigmaX, scaleX, upperSkewX) / 2)
284 if sigmaY == 0:
285 y.append(scaleY[0] / 2)
286 else:
287 y.append(skewedGauss(muY, sigmaY, scaleY, upperSkewY) / 2)
288 if sigmaZ == 0:
289 z.append(scaleZ[0] / 2)
290 else:
291 z.append(skewedGauss(muZ, sigmaZ, scaleZ, upperSkewZ) / 2)
292 else:
293 if sigmaX == 0:
294 x.append(0)
295 else:
296 x.append(skewedGauss(0, sigmaX, scaleX, upperSkewX) / 8)
297 if sigmaY == 0:
298 y.append(0)
299 else:
300 y.append(skewedGauss(0, sigmaY, scaleY, upperSkewY) / 8)
301 if sigmaZ == 0:
302 z.append(0)
303 else:
304 z.append(skewedGauss(0, sigmaZ, scaleZ, upperSkewZ) / 8)
305 elif shape == 4:
306 for j in range(10):
307 if j in [0, 9]:
308 if sigmaX == 0:
309 x.append(0)
310 else:
311 x.append(skewedGauss(0, sigmaX, scaleX, upperSkewX) / 2)
312 if sigmaY == 0:
313 y.append(0)
314 else:
315 y.append(skewedGauss(0, sigmaY, scaleY, upperSkewY) / 2)
316 if sigmaZ == 0:
317 z.append(scaleZ[0] / 2)
318 else:
319 z.append(skewedGauss(muZ, sigmaZ, scaleZ, upperSkewZ) / 2)
320 elif j in [1, 2, 3, 4]:
321 if sigmaX == 0:
322 x.append(scaleX[0] / 2)
323 else:
324 x.append(skewedGauss(muX, sigmaX, scaleX, upperSkewX) / 2)
325 if sigmaY == 0:
326 y.append(scaleY[0] / 2)
327 else:
328 y.append(skewedGauss(muY, sigmaY, scaleY, upperSkewY) / 2)
329 if sigmaZ == 0:
330 z.append(scaleZ[0] / 2)
331 else:
332 z.append(skewedGauss(muZ, sigmaZ, scaleZ, upperSkewZ) / 2)
333 elif j in [5, 7]:
334 if sigmaX == 0:
335 x.append(0)
336 else:
337 x.append(skewedGauss(0, sigmaX, scaleX, upperSkewX) / 3)
338 if sigmaY == 0:
339 y.append(scaleY[0] / 3)
340 else:
341 y.append(skewedGauss(muY, sigmaY, scaleY, upperSkewY) / 3)
342 if sigmaZ == 0:
343 z.append(0)
344 else:
345 z.append(skewedGauss(0, sigmaZ, scaleZ, upperSkewZ) / 6)
346 elif j in [6, 8]:
347 if sigmaX == 0:
348 x.append(scaleX[0] / 3)
349 else:
350 x.append(skewedGauss(muX, sigmaX, scaleX, upperSkewX) / 3)
351 if sigmaY == 0:
352 y.append(0)
353 else:
354 y.append(skewedGauss(0, sigmaY, scaleY, upperSkewY) / 3)
355 if sigmaZ == 0:
356 z.append(0)
357 else:
358 z.append(skewedGauss(0, sigmaZ, scaleZ, upperSkewZ) / 6)
359 elif shape == 5:
360 for j in range(10):
361 if j == 0:
362 if sigmaX == 0:
363 x.append(0)
364 else:
365 x.append(skewedGauss(0, sigmaX, scaleX, upperSkewX) / 8)
366 if sigmaY == 0:
367 y.append(0)
368 else:
369 y.append(skewedGauss(0, sigmaY, scaleY, upperSkewY) / 8)
370 if sigmaZ == 0:
371 z.append(scaleZ[0] / 2)
372 else:
373 z.append(skewedGauss(muZ, sigmaZ, scaleZ, upperSkewZ) / 2)
374 elif j in [1, 2]:
375 if sigmaX == 0:
376 x.append(scaleZ[0] * .125)
377 else:
378 x.append(skewedGauss(muX, sigmaX, scaleX, upperSkewX) * 0.125)
379 if sigmaY == 0:
380 y.append(scaleZ[0] * 0.2165)
381 else:
382 y.append(skewedGauss(muY, sigmaY, scaleY, upperSkewY) * 0.2165)
383 if sigmaZ == 0:
384 z.append(0)
385 else:
386 z.append(skewedGauss(0, sigmaZ, scaleZ, upperSkewZ) / 4)
387 elif j == 3:
388 if sigmaX == 0:
389 x.append(scaleX[0] / 4)
390 else:
391 x.append(skewedGauss(muX, sigmaX, scaleX, upperSkewX) / 4)
392 if sigmaY == 0:
393 y.append(0)
394 else:
395 y.append(skewedGauss(0, sigmaY, scaleY, upperSkewY) / 4)
396 if sigmaZ == 0:
397 z.append(0)
398 else:
399 z.append(skewedGauss(0, sigmaZ, scaleZ, upperSkewZ) / 4)
400 elif j in [4, 6]:
401 if sigmaX == 0:
402 x.append(scaleX[0] * 0.25)
403 else:
404 x.append(skewedGauss(muX, sigmaX, scaleX, upperSkewX) * 0.25)
405 if sigmaY == 0:
406 y.append(scaleY[0] * 0.433)
407 else:
408 y.append(skewedGauss(muY, sigmaY, scaleY, upperSkewY) * 0.433)
409 if sigmaZ == 0:
410 z.append(scaleZ[0] / 2)
411 else:
412 z.append(skewedGauss(muZ, sigmaZ, scaleZ, upperSkewZ) / 2)
413 elif j == 5:
414 if sigmaX == 0:
415 x.append(scaleX[0] / 4)
416 else:
417 x.append(skewedGauss(muX, sigmaX, scaleX, upperSkewX) / 4)
418 if sigmaY == 0:
419 y.append(0)
420 else:
421 y.append(skewedGauss(0, sigmaY, scaleY, upperSkewY) / 2)
422 if sigmaZ == 0:
423 z.append(scaleZ[0] / 2)
424 else:
425 z.append(skewedGauss(muZ, sigmaZ, scaleZ, upperSkewZ) / 2)
426 elif j in [7, 9]:
427 if sigmaX == 0:
428 x.append(scaleX[0] * 0.10825)
429 else:
430 x.append(skewedGauss(muX, sigmaX, scaleX, upperSkewX) * 0.10825)
431 if sigmaY == 0:
432 y.append(scaleY[0] * 0.2165)
433 else:
434 y.append(skewedGauss(muY, sigmaY, scaleY, upperSkewY) * 0.2165)
435 if sigmaZ == 0:
436 z.append(scaleZ[0] / 2)
437 else:
438 z.append(skewedGauss(muZ, sigmaZ, scaleZ, upperSkewZ) / 2)
439 elif j == 8:
440 if sigmaX == 0:
441 x.append(scaleX[0] / 2)
442 else:
443 x.append(skewedGauss(muX, sigmaX, scaleX, upperSkewX) / 2)
444 if sigmaY == 0:
445 y.append(0)
446 else:
447 y.append(skewedGauss(0, sigmaY, scaleY, upperSkewY) / 4)
448 if sigmaZ == 0:
449 z.append(scaleZ[0] / 2)
450 else:
451 z.append(skewedGauss(muZ, sigmaZ, scaleZ, upperSkewZ) / 2)
452 elif shape == 6:
453 for j in range(7):
454 if j > 0:
455 if sigmaX == 0:
456 x.append(scaleX[0] / 2)
457 else:
458 x.append(skewedGauss(muX, sigmaX, scaleX, upperSkewX) / 2)
459 if sigmaY == 0:
460 y.append(scaleY[0] / 2)
461 else:
462 y.append(skewedGauss(muY, sigmaY, scaleY, upperSkewY) / 2)
463 if sigmaZ == 0:
464 z.append(scaleZ[0] / 2)
465 else:
466 z.append(skewedGauss(muZ, sigmaZ, scaleZ, upperSkewZ) / 2)
467 else:
468 if sigmaX == 0:
469 x.append(scaleX[0] / 2)
470 else:
471 x.append(skewedGauss(muX, sigmaX, scaleX, upperSkewX) / 2)
472 if sigmaY == 0:
473 y.append(0)
474 else:
475 y.append(skewedGauss(0, sigmaY, scaleY, upperSkewY) / 2)
476 if sigmaZ == 0:
477 z.append(scaleZ[0] / 2)
478 else:
479 z.append(skewedGauss(muZ, sigmaZ, scaleZ, upperSkewZ) / 2)
480 elif shape == 7:
481 for j in range(10):
482 if j in [1, 3, 4, 5, 8, 9]:
483 if sigmaX == 0:
484 x.append(scaleX[0] / 2)
485 else:
486 x.append(skewedGauss(muX, sigmaX, scaleX, upperSkewX) / 2)
487 if sigmaY == 0:
488 y.append(scaleY[0] / 2)
489 else:
490 y.append(skewedGauss(muY, sigmaY, scaleY, upperSkewY) / 2)
491 if sigmaZ == 0:
492 z.append(scaleZ[0] / 2)
493 else:
494 z.append(skewedGauss(muZ, sigmaZ, scaleZ, upperSkewZ) / 2)
495 else:
496 if sigmaX == 0:
497 x.append(scaleX[0] / 2)
498 else:
499 x.append(skewedGauss(muX, sigmaX, scaleX, upperSkewX) / 2)
500 if sigmaY == 0:
501 y.append(0)
502 else:
503 y.append(skewedGauss(0, sigmaY, scaleY, upperSkewY) / 2)
504 if sigmaZ == 0:
505 z.append(scaleZ[0] / 2)
506 else:
507 z.append(skewedGauss(muZ, sigmaZ, scaleZ, upperSkewZ) / 2)
508 elif shape == 8:
509 for j in range(7):
510 if sigmaX == 0:
511 x.append(scaleX[0] / 2)
512 else:
513 x.append(skewedGauss(muX, sigmaX, scaleX, upperSkewX) / 2)
514 if sigmaY == 0:
515 y.append(scaleY[0] / 2)
516 else:
517 y.append(skewedGauss(muY, sigmaY, scaleY, upperSkewY) / 2)
518 if sigmaZ == 0:
519 z.append(scaleZ[0] / 2)
520 else:
521 z.append(skewedGauss(muZ, sigmaZ, scaleZ, upperSkewZ) / 2)
522 elif shape == 9:
523 for j in range(8):
524 if sigmaX == 0:
525 x.append(scaleX[0] / 2)
526 else:
527 x.append(skewedGauss(muX, sigmaX, scaleX, upperSkewX) / 2)
528 if sigmaY == 0:
529 y.append(scaleY[0] / 2)
530 else:
531 y.append(skewedGauss(muY, sigmaY, scaleY, upperSkewY) / 2)
532 if sigmaZ == 0:
533 z.append(scaleZ[0] / 2)
534 else:
535 z.append(skewedGauss(muZ, sigmaZ, scaleZ, upperSkewZ) / 2)
536 elif shape == 10:
537 for j in range(7):
538 if sigmaX == 0:
539 x.append(scaleX[0] / 2)
540 else:
541 x.append(skewedGauss(muX, sigmaX, scaleX, upperSkewX) / 2)
542 if sigmaY == 0:
543 y.append(scaleY[0] / 2)
544 else:
545 y.append(skewedGauss(muY, sigmaY, scaleY, upperSkewY) / 2)
546 if sigmaZ == 0:
547 z.append(scaleZ[0] / 2)
548 else:
549 z.append(skewedGauss(muZ, sigmaZ, scaleZ, upperSkewZ) / 2)
550 elif shape == 11:
551 for j in range(7):
552 if sigmaX == 0:
553 x.append(scaleX[0] / 2)
554 else:
555 x.append(skewedGauss(muX, sigmaX, scaleX, upperSkewX) / 2)
556 if sigmaY == 0:
557 y.append(scaleY[0] / 2)
558 else:
559 y.append(skewedGauss(muY, sigmaY, scaleY, upperSkewY) / 2)
560 if sigmaZ == 0:
561 z.append(scaleZ[0] / 2)
562 else:
563 z.append(skewedGauss(muZ, sigmaZ, scaleZ, upperSkewZ) / 2)
565 # This is for scaling the displacement textures.
566 # Scale the vertices so that their average is equal to 1 * scale factor.
567 if scaleDisplace:
568 averageX = (sum(x) / len(x)) * scale_fac[0]
569 for i in range(len(x)):
570 x[i] /= averageX
571 averageY = (sum(y) / len(y)) * scale_fac[1]
572 for i in range(len(y)):
573 y[i] /= averageY
574 averageZ = (sum(z) / len(z)) * scale_fac[2]
575 for i in range(len(z)):
576 z[i] /= averageZ
578 # Build vertex and face arrays:
579 if shape == 1:
580 verts = [(-x[0], -y[0], -z[0]), (x[1], -y[1], -z[1]), (x[2], -y[2], z[2]),
581 (-x[3], y[3], -z[3]), (x[4], y[4], -z[4]), (x[5], y[5], z[5]),
582 (x[6], y[6], z[6]), (x[7], y[7], -z[7])]
583 faces = [[0, 1, 2], [0, 1, 7], [3, 0, 7], [3, 4, 7], [1, 4, 7], [3, 4, 5], [1, 2, 6],
584 [1, 4, 6], [4, 5, 6], [0, 2, 6], [0, 3, 6], [3, 5, 6]]
585 elif shape == 2:
586 verts = [(-x[0], y[0], -z[0]), (x[1], -y[1], -z[1]), (x[2], y[2], -z[2]),
587 (-x[3], y[3], -z[3]), (-x[4], -y[4], z[4]), (x[5], y[5], z[5]),
588 (x[6], y[6], z[6]), (-x[7], y[7], z[7])]
589 faces = [[0, 1, 2], [0, 2, 3], [0, 3, 7], [0, 7, 4], [1, 4, 5], [0, 1, 4], [5, 1, 2],
590 [5, 2, 6], [3, 2, 6], [3, 6, 7], [5, 4, 7], [5, 6, 7]]
591 elif shape == 3:
592 verts = [(x[0], y[0], z[0]), (x[1], -y[1], -z[1]), (x[2], y[2], -z[2]),
593 (-x[3], y[3], -z[3]), (x[4], -y[4], z[4]), (x[5], y[5], z[5]),
594 (-x[6], y[6], z[6]), (-x[7], -y[7], z[7])]
595 faces = [[0, 1, 2], [0, 2, 3], [0, 3, 6], [0, 6, 7], [0, 7, 4], [0, 4, 1], [5, 4, 1, 2],
596 [5, 6, 3, 2], [5, 4, 7, 6]]
597 elif shape == 4:
598 verts = [(x[0], y[0], z[0]), (x[1], -y[1], -z[1]), (x[2], y[2], -z[2]),
599 (-x[3], y[3], -z[3]), (-x[4], -y[4], -z[4]), (x[5], -y[5], -z[5]),
600 (x[6], y[6], -z[6]), (x[7], y[7], -z[7]), (-x[8], y[8], -z[8]),
601 (x[9], y[9], -z[9])]
602 faces = [[0, 1, 6], [0, 6, 2], [0, 2, 7], [0, 7, 3], [0, 3, 8], [0, 8, 4], [0, 4, 5],
603 [0, 5, 1], [1, 9, 2], [2, 9, 3], [3, 9, 4], [4, 9, 1], [1, 6, 2], [2, 7, 3],
604 [3, 8, 4], [4, 5, 1]]
605 elif shape == 5:
606 verts = [(x[0], y[0], z[0]), (x[1], -y[1], z[1]), (x[2], y[2], z[2]),
607 (-x[3], y[3], z[3]), (x[4], -y[4], -z[4]), (x[5], y[5], -z[5]),
608 (x[6], y[6], -z[6]), (-x[7], y[7], -z[7]), (-x[8], y[8], -z[8]),
609 (-x[9], -y[9], -z[9])]
610 faces = [[0, 1, 2], [0, 2, 3], [0, 3, 1], [1, 4, 5], [1, 5, 2], [2, 5, 6], [2, 6, 7],
611 [2, 7, 3], [3, 7, 8], [3, 8, 9], [3, 9, 1], [1, 9, 4], [4, 5, 9], [5, 6, 7],
612 [7, 8, 9], [9, 5, 7]]
613 elif shape == 6:
614 verts = [(x[0], y[0], z[0]), (x[1], -y[1], -z[1]), (x[2], y[2], -z[2]),
615 (-x[3], y[3], -z[3]), (-x[4], y[4], z[4]), (-x[5], -y[5], z[5]),
616 (-x[6], -y[6], -z[6])]
617 faces = [[0, 1, 2], [0, 2, 3, 4], [0, 1, 6, 5], [0, 4, 5], [1, 2, 3, 6], [3, 4, 5, 6]]
618 elif shape == 7:
619 verts = [(x[0], y[0], z[0]), (x[1], -y[1], -z[1]), (x[2], y[2], -z[2]),
620 (x[3], y[3], -z[3]), (-x[4], y[4], -z[4]), (-x[5], y[5], z[5]),
621 (-x[6], y[6], z[6]), (-x[7], y[7], -z[7]), (-x[8], -y[8], -z[8]),
622 (-x[9], -y[9], z[9])]
623 faces = [[0, 1, 2], [0, 2, 3], [0, 5, 6], [0, 6, 9], [0, 1, 8, 9], [0, 3, 4, 5],
624 [1, 2, 7, 8], [2, 3, 4, 7], [4, 5, 6, 7], [6, 7, 8, 9]]
625 elif shape == 8:
626 verts = [(x[0], y[0], z[0]), (x[1], -y[1], -z[1]), (x[2], y[2], -z[2]),
627 (-x[3], y[3], -z[3]), (-x[4], -y[4], -z[4]), (-x[5], -y[5], z[5]),
628 (-x[6], y[6], z[6])]
629 faces = [[0, 2, 1], [0, 1, 4], [0, 4, 5], [0, 5, 6], [0, 6, 3, 2], [2, 1, 4, 3],
630 [3, 6, 5, 4]]
631 elif shape == 9:
632 verts = [(-x[0], -y[0], -z[0]), (-x[1], y[1], -z[1]), (-x[2], y[2], z[2]),
633 (-x[3], -y[3], z[3]), (x[4], -y[4], -z[4]), (x[5], y[5], -z[5]),
634 (x[6], y[6], z[6]), (x[7], -y[7], z[7])]
635 faces = [[0, 1, 6, 2], [1, 5, 7, 6], [5, 4, 3, 7], [4, 0, 2, 3], [0, 1, 5, 4], [3, 2, 6, 7]]
636 elif shape == 10:
637 verts = [(-x[0], -y[0], -z[0]), (-x[1], y[1], -z[1]), (-x[2], y[2], z[2]),
638 (x[3], -y[3], z[3]), (x[4], y[4], z[4]), (x[5], y[5], -z[5]),
639 (x[6], -y[6], -z[6])]
640 faces = [[0, 2, 3], [0, 3, 6], [0, 1, 5, 6], [2, 3, 4], [0, 1, 2], [1, 2, 4, 5], [3, 4, 5, 6]]
641 elif shape == 11:
642 verts = [(-x[0], -y[0], -z[0]), (-x[1], y[1], -z[1]), (-x[2], y[2], z[2]),
643 (x[3], -y[3], z[3]), (x[4], y[4], z[4]), (x[5], y[5], -z[5]),
644 (x[6], -y[6], -z[6])]
645 faces = [[0, 2, 3], [0, 3, 6], [0, 1, 5, 6], [2, 3, 4], [5, 6, 3], [1, 5, 3, 4], [0, 1, 4, 2]]
646 else:
647 verts = [(-x[0], -y[0], -z[0]), (-x[1], y[1], -z[1]), (-x[2], -y[2], z[2]),
648 (-x[3], y[3], z[3]), (x[4], -y[4], -z[4]), (x[5], y[5], -z[5]),
649 (x[6], -y[6], z[6]), (x[7], y[7], z[7])]
650 faces = [[0, 1, 3, 2], [0, 1, 5, 4], [0, 4, 6, 2], [7, 5, 4, 6], [7, 3, 2, 6], [7, 5, 1, 3]]
652 # name = "Rock." + str(base + shift).zfill(3)
653 name = "rock"
655 # Make object:
656 obj = createMeshObject(context, verts, [], faces, name)
658 if scaleDisplace:
659 # bpy.data.objects[name].scale = Vector((averageX, averageY, averageZ))
660 obj.scale = Vector((averageX, averageY, averageZ))
662 # For a slight speed bump / Readability:
663 # mesh = bpy.data.meshes[name]
664 mesh = obj.data
666 creases = mesh.edge_creases_ensure().data
668 # Apply creasing:
669 if shape == 0:
670 for i in range(12):
671 # todo: "0.375 / 3"? WTF? That = 0.125. . . .
672 # *** Completed 7/15/2011: Changed second one ***
673 creases[i].value = gauss(0.125, 0.125)
674 elif shape == 1:
675 for i in [0, 2]:
676 creases[i].value = gauss(0.5, 0.125)
677 for i in [6, 9, 11, 12]:
678 creases[i].value = gauss(0.25, 0.05)
679 for i in [5, 7, 15, 16]:
680 creases[i].value = gauss(0.125, 0.025)
681 elif shape == 2:
682 for i in range(18):
683 creases[i].value = gauss(0.125, 0.025)
684 elif shape == 3:
685 for i in [0, 1, 6, 10, 13]:
686 creases[i].value = gauss(0.25, 0.05)
687 creases[8].value = gauss(0.5, 0.125)
688 elif shape == 4:
689 for i in [5, 6, 7, 10, 14, 16, 19, 21]:
690 creases[i].value = gauss(0.5, 0.125)
691 elif shape == 7:
692 for i in range(18):
693 if i in [0, 1, 2, 3, 6, 7, 8, 9, 13, 16]:
694 creases[i].value = gauss(0.5, 0.125)
695 elif i in [11, 17]:
696 creases[i].value = gauss(0.25, 0.05)
697 else:
698 creases[i].value = gauss(0.125, 0.025)
699 elif shape == 8:
700 for i in range(12):
701 if i in [0, 3, 8, 9, 10]:
702 creases[i].value = gauss(0.5, 0.125)
703 elif i == 11:
704 creases[i].value = gauss(0.25, 0.05)
705 else:
706 creases[i].value = gauss(0.125, 0.025)
707 elif shape == 9:
708 for i in range(12):
709 if i in [0, 3, 4, 11]:
710 creases[i].value = gauss(0.5, 0.125)
711 else:
712 creases[i].value = gauss(0.25, 0.05)
713 elif shape == 10:
714 for i in range(12):
715 if i in [0, 2, 3, 4, 8, 11]:
716 creases[i].value = gauss(0.5, 0.125)
717 elif i in [1, 5, 7]:
718 creases[i].value = gauss(0.25, 0.05)
719 else:
720 creases[i].value = gauss(0.125, 0.025)
721 elif shape == 11:
722 for i in range(11):
723 if i in [1, 2, 3, 4, 8, 11]:
724 creases[i].value = gauss(0.25, 0.05)
725 else:
726 creases[i].value = gauss(0.125, 0.025)
728 return obj
731 # Creates rock objects:
732 def generateRocks(context, scaleX, skewX, scaleY, skewY, scaleZ, skewZ,
733 scale_fac, detail, display_detail, deform, rough,
734 smooth_fac, smooth_it,
735 numOfRocks=1, userSeed=1.0,
736 scaleDisplace=False, randomSeed=True, use_enter_edit_mode=False):
737 global LASTROCK
738 sigmaX = 0
739 sigmaY = 0
740 sigmaZ = 0
741 upperSkewX = False
742 upperSkewY = False
743 upperSkewZ = False
744 shift = 0
745 # vertexScaling = []
747 # Seed the random Gaussian value generator:
748 if randomSeed:
749 seed(int(time.time()))
750 else:
751 seed(userSeed)
753 # These values need to be really small to look good.
754 # So the user does not have to use such ridiculously small values:
755 deform /= 10
756 rough /= 100
758 # Verify that the min really is the min:
759 if scaleX[1] < scaleX[0]:
760 scaleX[0], scaleX[1] = scaleX[1], scaleX[0]
761 if scaleY[1] < scaleY[0]:
762 scaleY[0], scaleY[1] = scaleY[1], scaleY[0]
763 if scaleZ[1] < scaleZ[0]:
764 scaleZ[0], scaleZ[1] = scaleZ[1], scaleZ[0]
766 # todo: edit below to allow for skewing the distribution
767 # *** todo completed 4/22/2011 ***
768 # *** Code now generating "int not scriptable error" in Blender ***
770 # Calculate mu and sigma for a Gaussian distributed random number
771 # generation:
772 # If the lower and upper bounds are the same, skip the math.
774 # sigma is the standard deviation of the values. The 95% interval is three
775 # standard deviations, which is what we want most generated values to fall
776 # in. Since it might be skewed we are going to use half the difference
777 # between the mean and the furthest bound and scale the other side down
778 # post-number generation.
779 if scaleX[0] != scaleX[1]:
780 skewX = (skewX + 1) / 2
781 muX = scaleX[0] + ((scaleX[1] - scaleX[0]) * skewX)
782 if skewX < 0.5:
783 sigmaX = (scaleX[1] - muX) / 3
784 else:
785 sigmaX = (muX - scaleX[0]) / 3
786 upperSkewX = True
787 else:
788 muX = scaleX[0]
789 if scaleY[0] != scaleY[1]:
790 skewY = (skewY + 1) / 2
791 muY = scaleY[0] + ((scaleY[1] - scaleY[0]) * skewY)
792 if skewY < 0.5:
793 sigmaY = (scaleY[1] - muY) / 3
794 else:
795 sigmaY = (muY - scaleY[0]) / 3
796 upperSkewY = True
797 else:
798 muY = scaleY[0]
799 if scaleZ[0] != scaleZ[1]:
800 skewZ = (skewZ + 1) / 2
801 muZ = scaleZ[0] + ((scaleZ[1] - scaleZ[0]) * skewZ)
802 if skewZ < 0.5:
803 sigmaZ = (scaleZ[1] - muZ) / 3
804 else:
805 sigmaZ = (muZ - scaleZ[0]) / 3
806 upperSkewZ = True
807 else:
808 muZ = scaleZ
810 rocks = []
812 for i in range(numOfRocks):
813 # todo: enable different random values for each (x,y,z) coordinate for
814 # each vertex. This will add additional randomness to the shape of the
815 # generated rocks.
816 # *** todo completed 4/19/2011 ***
817 # *** Code is notably slower at high rock counts ***
819 # name = generateObject(context, muX, sigmaX, scaleX, upperSkewX, muY,
820 rock = generateObject(
821 context, muX, sigmaX, scaleX, upperSkewX, muY,
822 sigmaY, scaleY, upperSkewY, muZ, sigmaZ, scaleZ,
823 upperSkewZ, i, LASTROCK, scaleDisplace, scale_fac)
825 # rock = bpy.data.objects[name]
827 # todo Map what the two new textures will be:
828 # This is not working. It works on paper so . . . ???
829 # *** todo completed on 4/23/2011 ***
830 # *** todo re-added as the first rock is getting
831 # 'Texture.001' twice. ***
832 # *** todo completed on 4/25/2011 ***
833 # *** Script no longer needs to map new texture names 9/6/2011 ***
835 # Create the four new textures:
836 # todo Set displacement texture parameters:
837 # *** todo completed on 5/31/2011 ***
838 # Voronoi has been removed from being an option for the fine detail
839 # texture.
840 texTypes = ['CLOUDS', 'MUSGRAVE', 'DISTORTED_NOISE', 'STUCCI', 'VORONOI']
841 newTex = []
842 # The first texture is to give a more ranodm base shape appearance:
843 newTex.append(bpy.data.textures.new(
844 name='rock_displacement',
845 type=texTypes[1]))
846 randomizeTexture(newTex[0], 0)
847 newTex.append(bpy.data.textures.new(
848 name='rock_displacement',
849 type=texTypes[4]))
850 randomizeTexture(newTex[1], 0)
851 if numpy:
852 newTex.append(bpy.data.textures.new(
853 name='rock_displacement',
854 type=texTypes[int(round(weibull(1, 1)[0] / 2.125))]))
855 randomizeTexture(newTex[2], 1)
856 newTex.append(bpy.data.textures.new(
857 name='rock_displacement',
858 type=texTypes[int(round(weibull(1, 1)[0] / 2.125))]))
859 randomizeTexture(newTex[3], 2)
860 else:
861 newTex.append(bpy.data.textures.new(
862 name='rock_displacement',
863 type=texTypes[int(round(weibull(1, 1) / 2.125))]))
864 randomizeTexture(newTex[2], 1)
865 newTex.append(bpy.data.textures.new(
866 name='rock_displacement',
867 type=texTypes[int(round(weibull(1, 1) / 2.125))]))
868 randomizeTexture(newTex[3], 2)
870 # Add modifiers:
871 rock.modifiers.new(name="Subsurf", type='SUBSURF')
872 rock.modifiers.new(name="Subsurf", type='SUBSURF')
873 rock.modifiers.new(name="Displace", type='DISPLACE')
874 rock.modifiers.new(name="Displace", type='DISPLACE')
875 rock.modifiers.new(name="Displace", type='DISPLACE')
876 rock.modifiers.new(name="Displace", type='DISPLACE')
878 # If smoothing is enabled, allow a little randomness into the
879 # smoothing factor. Then add the smoothing modifier.
880 if smooth_fac > 0.0 and smooth_it > 0:
881 rock.modifiers.new(name="Smooth", type='SMOOTH')
882 rock.modifiers[6].factor = gauss(smooth_fac, (smooth_fac ** 0.5) / 12)
883 rock.modifiers[6].iterations = smooth_it
884 # Make a call to random to keep things consistent:
885 else:
886 gauss(0, 1)
888 # Set subsurf modifier parameters:
889 rock.modifiers[0].levels = display_detail
890 rock.modifiers[0].render_levels = detail
891 rock.modifiers[1].levels = display_detail
892 rock.modifiers[1].render_levels = detail
894 # todo Set displacement modifier parameters:
895 # *** todo completed on 4/23/2011 ***
896 # *** toned down the variance on 4/26/2011 ***
897 # *** added third modifier on 4/28/2011 ***
898 # *** texture access changed on 9/6/2011 ***
899 rock.modifiers[2].texture = newTex[0]
900 rock.modifiers[2].strength = gauss(deform / 100, (1 / 300) * deform)
901 rock.modifiers[2].mid_level = 0
902 rock.modifiers[3].texture = newTex[1]
903 rock.modifiers[3].strength = gauss(deform, (1 / 3) * deform)
904 rock.modifiers[3].mid_level = 0
905 rock.modifiers[4].texture = newTex[2]
906 rock.modifiers[4].strength = gauss(rough * 2, (1 / 3) * rough)
907 rock.modifiers[5].texture = newTex[3]
908 rock.modifiers[5].strength = gauss(rough, (1 / 3) * rough)
910 # Set mesh to be smooth and fix the normals:
911 utils.smooth(rock.data)
912 # utils.smooth(bpy.data.meshes[name])
913 bpy.ops.object.editmode_toggle()
914 bpy.ops.mesh.normals_make_consistent()
915 bpy.ops.object.editmode_toggle()
917 if use_enter_edit_mode:
918 for m in rock.modifiers:
919 m.show_in_editmode = True
920 m.show_on_cage = True
922 # Store the last value of i:
923 shift = i
925 rocks.append(rock)
927 # Add the shift to LASTROCK:
928 LASTROCK += shift + 1
930 return rocks
933 # Much of the code below is more-or-less imitation of other addons and as such
934 # I have left it undocumented.
936 class OBJECT_OT_add_mesh_rock(bpy.types.Operator):
937 """Add rock objects"""
938 bl_idname = "mesh.add_mesh_rock"
939 bl_label = "Add Rocks"
940 bl_options = {'REGISTER', 'UNDO'}
941 bl_description = "Add rocks"
943 # Get the preset values from the XML file.
944 # -> The script was morphed into a Python module
945 # to support this.
946 # Tell settings.py to parse the XML file with the settings.
947 # Then get the default values resulting from the parsing.
948 # Make a list containing the default values and append to that
949 # the presets specified in the same XML file. This list will
950 # be used to load preset values.
951 settings.parse()
952 defaults = settings.getDefault()
953 presetsList = [defaults]
954 presetsList += settings.getPresetLists()
955 presets = []
956 lastPreset = 0
958 # Build the presets list for the enum property.
959 # This needs to be a for loop as the user might add presets to
960 # the XML file and those should show here:
961 for i, preset in enumerate(presetsList):
962 presets.append((str(i), preset[0], preset[0] + " preset values"))
964 preset_values: EnumProperty(
965 name="Presets",
966 items=presets,
967 description="Preset values for some rock types")
969 num_of_rocks: IntProperty(
970 name="Number of rocks",
971 description="Number of rocks to generate. WARNING: Slow at high values!",
972 min=1, max=1048576,
973 soft_max=20,
974 default=1)
976 scale_X: FloatVectorProperty(
977 name="X scale",
978 description="X axis scaling range",
979 min=0.0, max=256.0, step=1,
980 default=defaults[1], size=2)
981 skew_X: FloatProperty(
982 name="X skew",
983 description="X Skew ratio. 0.5 is no skew",
984 min=-1.0, max=1.0, default=defaults[4])
985 scale_Y: FloatVectorProperty(
986 name="Y scale",
987 description="Y axis scaling range",
988 min=.0, max=256.0, step=1,
989 default=defaults[2], size=2)
990 skew_Y: FloatProperty(
991 name="Y skew",
992 description="Y Skew ratio. 0.5 is no skew",
993 min=-1.0, max=1.0, default=defaults[5])
994 scale_Z: FloatVectorProperty(
995 name="Z scale",
996 description="Z axis scaling range",
997 min=0.0, max=256.0, step=1,
998 default=defaults[3], size=2)
999 skew_Z: FloatProperty(
1000 name="Z skew",
1001 description="Z Skew ratio. 0.5 is no skew",
1002 min=-1.0, max=1.0, default=defaults[6])
1003 use_scale_dis: BoolProperty(
1004 name="Scale displace textures",
1005 description="Scale displacement textures with dimensions. May cause stretched textures",
1006 default=defaults[7])
1007 scale_fac: FloatVectorProperty(
1008 name="Scaling Factor",
1009 description="XYZ scaling factor. 1: no scaling",
1010 min=0.0001, max=256.0, step=0.1,
1011 default=defaults[8], size=3)
1013 # @todo Possible to title this section "Physical Properties:"?
1014 deform: FloatProperty(
1015 name="Deformation",
1016 description="Rock deformation",
1017 min=0.0, soft_max=50, max=1024.0, default=defaults[9])
1018 rough: FloatProperty(
1019 name="Roughness",
1020 description="Rock roughness",
1021 min=0.0, soft_max=50, max=1024.0, default=defaults[10])
1022 detail: IntProperty(
1023 name="Detail level",
1024 description="Detail level. WARNING: Slow at high values!",
1025 min=1, soft_max=4, max=10, default=defaults[11])
1026 display_detail: IntProperty(
1027 name="Display Detail",
1028 description="Display detail. Use a lower value for high numbers of rocks",
1029 min=1, soft_max=4, max=10, default=defaults[12])
1030 smooth_fac: FloatProperty(
1031 name="Smooth Factor",
1032 description="Smoothing factor. A value of 0 disables",
1033 min=0.0, max=128.0, default=defaults[13])
1034 smooth_it: IntProperty(
1035 name="Smooth Iterations",
1036 description="Smoothing iterations. A value of 0 disables",
1037 min=0, max=50, default=defaults[14])
1039 use_generate: BoolProperty(
1040 name="Generate Rocks",
1041 description="Enable actual generation",
1042 default=defaults[15])
1043 use_random_seed: BoolProperty(
1044 name="Use a random seed",
1045 description="Create a seed based on time. Causes user seed to be ignored",
1046 default=defaults[16])
1047 user_seed: IntProperty(
1048 name="User seed",
1049 description="Use a specific seed for the generator",
1050 min=0, max=1048576, default=defaults[17])
1052 def draw(self, context):
1053 layout = self.layout
1054 box = layout.box()
1055 box.prop(self, 'num_of_rocks')
1056 box = layout.box()
1057 box.prop(self, 'scale_X')
1058 box.prop(self, 'skew_X')
1059 box.prop(self, 'scale_Y')
1060 box.prop(self, 'skew_Y')
1061 box.prop(self, 'scale_Z')
1062 box.prop(self, 'skew_Z')
1063 box.prop(self, 'use_scale_dis')
1064 if self.use_scale_dis:
1065 box.prop(self, 'scale_fac')
1066 else:
1067 self.scale_fac = utils.toFloats(self.defaults[8])
1068 box = layout.box()
1069 box.prop(self, 'deform')
1070 box.prop(self, 'rough')
1071 box.prop(self, 'detail')
1072 box.prop(self, 'display_detail')
1073 box.prop(self, 'smooth_fac')
1074 box.prop(self, 'smooth_it')
1076 box = layout.box()
1077 box.prop(self, 'use_generate')
1078 box.prop(self, 'use_random_seed')
1079 if not self.use_random_seed:
1080 box.prop(self, 'user_seed')
1081 box.prop(self, 'preset_values')
1083 def execute(self, context):
1084 # turn off 'Enter Edit Mode'
1085 use_enter_edit_mode = bpy.context.preferences.edit.use_enter_edit_mode
1086 bpy.context.preferences.edit.use_enter_edit_mode = False
1088 # The following "if" block loads preset values:
1089 if self.lastPreset != int(self.preset_values):
1090 self.scale_X = utils.toFloats(self.presetsList[int(self.preset_values)][1])
1091 self.scale_Y = utils.toFloats(self.presetsList[int(self.preset_values)][2])
1092 self.scale_Z = utils.toFloats(self.presetsList[int(self.preset_values)][3])
1093 self.skew_X = float(self.presetsList[int(self.preset_values)][4])
1094 self.skew_Y = float(self.presetsList[int(self.preset_values)][5])
1095 self.skew_Z = float(self.presetsList[int(self.preset_values)][6])
1096 self.use_scale_dis = bool(self.presetsList[int(self.preset_values)][7])
1097 self.scale_fac = utils.toFloats(self.presetsList[int(self.preset_values)][8])
1098 self.deform = float(self.presetsList[int(self.preset_values)][9])
1099 self.rough = float(self.presetsList[int(self.preset_values)][10])
1100 self.detail = int(self.presetsList[int(self.preset_values)][11])
1101 self.display_detail = int(self.presetsList[int(self.preset_values)][12])
1102 self.smooth_fac = float(self.presetsList[int(self.preset_values)][13])
1103 self.smooth_it = int(self.presetsList[int(self.preset_values)][14])
1104 self.use_generate = bool(self.presetsList[int(self.preset_values)][15])
1105 self.use_random_seed = bool(self.presetsList[int(self.preset_values)][16])
1106 self.user_seed = int(self.presetsList[int(self.preset_values)][17])
1107 self.lastPreset = int(self.preset_values)
1109 # todo Add deform, deform_Var, rough, and rough_Var:
1110 # *** todo completed 4/23/2011 ***
1111 # *** Eliminated "deform_Var" and "rough_Var" so the script is not
1112 # as complex to use. May add in again as advanced features. ***
1113 if self.use_generate:
1114 rocks = generateRocks(context,
1115 self.scale_X,
1116 self.skew_X,
1117 self.scale_Y,
1118 self.skew_Y,
1119 self.scale_Z,
1120 self.skew_Z,
1121 self.scale_fac,
1122 self.detail,
1123 self.display_detail,
1124 self.deform,
1125 self.rough,
1126 self.smooth_fac,
1127 self.smooth_it,
1128 self.num_of_rocks,
1129 self.user_seed,
1130 self.use_scale_dis,
1131 self.use_random_seed,
1132 use_enter_edit_mode)
1134 for rock in rocks:
1135 rock.select_set(True)
1137 if use_enter_edit_mode:
1138 bpy.ops.object.mode_set(mode = 'EDIT')
1140 # restore pre operator state
1141 bpy.context.preferences.edit.use_enter_edit_mode = use_enter_edit_mode
1143 return {'FINISHED'}
1145 # Register:
1146 def menu_func_rocks(self, context):
1147 layout = self.layout
1148 layout.separator()
1149 layout.operator(
1150 OBJECT_OT_add_mesh_rock.bl_idname,
1151 text="Rock Generator",
1152 icon="MESH_ICOSPHERE")
1155 classes = (
1156 OBJECT_OT_add_mesh_rock,
1160 def register():
1161 from bpy.utils import register_class
1162 for cls in classes:
1163 register_class(cls)
1164 bpy.types.VIEW3D_MT_mesh_add.append(menu_func_rocks)
1167 def unregister():
1168 from bpy.utils import unregister_class
1169 for cls in reversed(classes):
1170 unregister_class(cls)
1171 bpy.types.VIEW3D_MT_mesh_add.remove(menu_func_rocks)
1174 if __name__ == "__main__":
1175 register()