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