Advertisement
49xur

natures_donut_002

Jun 12th, 2022 (edited)
98
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 15.15 KB | None | 0 0
  1. import bpy
  2. import bmesh
  3. import math
  4.  
  5. '''
  6. - Version 1: First release
  7. - Version 2: Changed from Lattice deform to Mesh Deform due to some strange non linear characteristics
  8. '''
  9.  
  10.  
  11. clear_first = True # clearing all existing torus objects first
  12. smoothing = 0 # set to 0 for default torus geometry, set to > 0 for subdivision multiple
  13. # progressive radii of torus, radius_1 is the minor radius and radius_2 is major radius of first torus
  14. radius_1 = 0.5
  15. radius_2 = 2.0
  16. radius_3 = 8.0
  17. radius_4 = 32.0
  18. radius_5 = 128.0
  19. # pregressive number of sections on each torus (smallest to largest)
  20. sections_1 = 32
  21. sections_2 = 32
  22. sections_3 = 32
  23. # whether or not to stretch the outer edge of the torus to attempt to fill the parent torus volume (smallest to largest)
  24. # be awre that using stretch on more than one level will result in non symetric torus on the lower levels.
  25. stretch_1 = True
  26. stretch_2 = True
  27. stretch_3 = True
  28. level = 4 # level of torus to render up to
  29.  
  30.  
  31. from bpy import context
  32.  
  33. import builtins as __builtin__
  34.  
  35. def console_print(*args, **kwargs):
  36. for a in context.screen.areas:
  37. if a.type == 'CONSOLE':
  38. c = {}
  39. c['area'] = a
  40. c['space_data'] = a.spaces.active
  41. c['region'] = a.regions[-1]
  42. c['window'] = context.window
  43. c['screen'] = context.screen
  44. s = " ".join([str(arg) for arg in args])
  45. for line in s.split("\n"):
  46. bpy.ops.console.scrollback_append(c, text=line)
  47.  
  48. def print(*args, **kwargs):
  49. """Console print() function."""
  50.  
  51. console_print(*args, **kwargs) # to py consoles
  52. __builtin__.print(*args, **kwargs) # to system console
  53.  
  54.  
  55. #bpy.ops.object.mode_set(mode='OBJECT')
  56. bpy.ops.object.select_all(action='DESELECT')
  57. if clear_first:
  58. for obj in bpy.context.scene.objects:
  59. if obj.name.startswith('Torus'):
  60. bpy.data.objects.remove(obj, do_unlink = True)
  61. #bpy.ops.object.select_all(action='SELECT')
  62. #bpy.ops.object.delete(use_global=False, confirm=False)
  63.  
  64. #bpy.ops.mesh.primitive_uv_sphere_add(radius=radius_4, enter_editmode=False, align='WORLD', location=(0, 0, 0), scale=(1, 1, 1))
  65.  
  66. if level > 0:
  67. # first torus level
  68.  
  69. bpy.ops.mesh.primitive_torus_add(align='WORLD', location=(0, 0, 0), rotation=(0, 0, 0), major_radius=radius_2-radius_1, minor_radius=radius_1, abso_major_rad=radius_2, abso_minor_rad=radius_1)
  70. torus_1 = bpy.context.selected_objects[0]
  71.  
  72. if level > 1:
  73. # second torus level
  74.  
  75. bpy.ops.transform.translate(value=(radius_3-radius_2, 0, 0), orient_axis_ortho='X', orient_type='GLOBAL', orient_matrix=((1, 0, 0), (0, 1, 0), (0, 0, 1)), orient_matrix_type='GLOBAL', constraint_axis=(True, False, False), mirror=False, use_proportional_edit=False, proportional_edit_falloff='SMOOTH', proportional_size=1, use_proportional_connected=False, use_proportional_projected=False)
  76. bpy.ops.object.origin_set(type='ORIGIN_CURSOR', center='MEDIAN')
  77.  
  78. bpy.ops.mesh.primitive_uv_sphere_add(radius=1, enter_editmode=False, align='WORLD', location=(0, 0, 0), scale=(1, 1, 1))
  79. origin_1 = bpy.context.selected_objects[0]
  80.  
  81. bpy.ops.mesh.primitive_cube_add(enter_editmode=False, align='WORLD', location=(radius_3/2, 0, 0), scale=(1,1,1))
  82. bpy.ops.transform.resize(value=(radius_3/2, radius_2, radius_1), orient_type='GLOBAL', orient_matrix=((1, 0, 0), (0, 1, 0), (0, 0, 1)), orient_matrix_type='GLOBAL', constraint_axis=(True, False, False), mirror=False, use_proportional_edit=False, proportional_edit_falloff='SMOOTH', proportional_size=1, use_proportional_connected=False, use_proportional_projected=False)
  83. lattice_1 = bpy.context.selected_objects[0]
  84.  
  85. # https://blender.stackexchange.com/questions/163855/how-to-subdivide-mesh-with-python-and-blender-2-8
  86. bm = bmesh.new()
  87. bm.from_mesh(lattice_1.data)
  88. #bm = bmesh.from_edit_mesh(lattice_1.data)
  89. edges_to_split = [edge for edge in bm.edges if edge.verts[0].co.z == -1 * edge.verts[1].co.z]
  90. bmesh.ops.subdivide_edges(bm, edges=edges_to_split, cuts=1, use_grid_fill=True)
  91. bm.to_mesh(lattice_1.data)
  92. bm.free()
  93. lattice_1.data.update()
  94. #bmesh.update_edit_mesh(lattice_1.data)
  95.  
  96. if smoothing > 0:
  97. modifier_subd = torus_1.modifiers.new("Subdivision", 'SUBSURF')
  98. modifier_subd.levels = smoothing
  99.  
  100. modifier_latt = torus_1.modifiers.new("MeshDeform", 'MESH_DEFORM')
  101. modifier_latt.object = lattice_1
  102. modifier_latt.precision = 3
  103.  
  104. bpy.ops.object.select_all(action='DESELECT')
  105. bpy.context.view_layer.objects.active = torus_1
  106. torus_1.select_set(True)
  107. bpy.ops.object.meshdeform_bind(modifier="MeshDeform")
  108.  
  109. bm = bmesh.new()
  110. bm.from_mesh(lattice_1.data)
  111. for p in bm.verts:
  112. #print(p.co)
  113. if p.co.x == -1.0:
  114. p.co.z = 0.0
  115. if stretch_1 and p.co.x == 1.0 and p.co.z != 0.0:
  116. #print(math.cos((2*math.pi)/(sections_1*2)))
  117. #print(radius_3*math.sin((2*math.pi)/(sections_1*2))/radius_1)
  118. p.co.x = math.cos((2*math.pi)/(sections_1*2))
  119. if p.co.z == 1.0:
  120. p.co.z = radius_3*math.sin((2*math.pi)/(sections_1*2))/radius_1
  121. if p.co.z == -1.0:
  122. p.co.z = -radius_3*math.sin((2*math.pi)/(sections_1*2))/radius_1
  123.  
  124. bm.to_mesh(lattice_1.data)
  125. bm.free()
  126. lattice_1.data.update()
  127.  
  128. modifier_arr = torus_1.modifiers.new("Array", 'ARRAY')
  129. modifier_arr.count = sections_1
  130. modifier_arr.use_relative_offset = False
  131. modifier_arr.use_constant_offset = True
  132. modifier_arr.constant_offset_displace[0] = 0
  133. modifier_arr.use_object_offset = True
  134. modifier_arr.offset_object = origin_1
  135.  
  136. bpy.ops.object.select_all(action='DESELECT')
  137. bpy.context.view_layer.objects.active = origin_1
  138. origin_1.select_set(True)
  139.  
  140. bpy.ops.transform.rotate(value=(2*math.pi)/sections_1, orient_axis='Y', orient_type='GLOBAL', orient_matrix=((1, 0, 0), (0, 1, 0), (0, 0, 1)), orient_matrix_type='GLOBAL', constraint_axis=(False, True, False), mirror=False, use_proportional_edit=False, proportional_edit_falloff='SMOOTH', proportional_size=1, use_proportional_connected=False, use_proportional_projected=False)
  141.  
  142. bpy.ops.object.select_all(action='DESELECT')
  143. context.view_layer.objects.active = torus_1
  144. torus_1.select_set(True)
  145. if smoothing > 0:
  146. bpy.ops.object.modifier_apply(modifier="Subdivision")
  147. bpy.ops.object.modifier_apply(modifier="MeshDeform")
  148. bpy.ops.object.modifier_apply(modifier="Array")
  149.  
  150. bpy.ops.object.select_all(action='DESELECT')
  151. context.view_layer.objects.active = lattice_1
  152. lattice_1.select_set(True)
  153. origin_1.select_set(True)
  154. bpy.ops.object.delete(use_global=False, confirm=False)
  155.  
  156. if level > 2:
  157. # third level torus
  158.  
  159. bpy.ops.mesh.primitive_uv_sphere_add(radius=1, enter_editmode=False, align='WORLD', location=(0, 0, 0), scale=(1, 1, 1))
  160. origin_1 = bpy.context.selected_objects[0]
  161.  
  162. bpy.ops.object.select_all(action='DESELECT')
  163. context.view_layer.objects.active = torus_1
  164. torus_1.select_set(True)
  165.  
  166. bpy.ops.transform.translate(value=(radius_4-radius_3, 0, 0), orient_axis_ortho='X', orient_type='GLOBAL', orient_matrix=((1, 0, 0), (0, 1, 0), (0, 0, 1)), orient_matrix_type='GLOBAL', constraint_axis=(True, False, False), mirror=False, use_proportional_edit=False, proportional_edit_falloff='SMOOTH', proportional_size=1, use_proportional_connected=False, use_proportional_projected=False)
  167. bpy.ops.object.origin_set(type='ORIGIN_CURSOR', center='MEDIAN')
  168.  
  169. bpy.ops.mesh.primitive_cube_add(enter_editmode=False, align='WORLD', location=(radius_4/2, 0, 0), scale=(1,1,1))
  170. bpy.ops.transform.resize(value=(radius_4/2, radius_2, radius_3), orient_type='GLOBAL', orient_matrix=((1, 0, 0), (0, 1, 0), (0, 0, 1)), orient_matrix_type='GLOBAL', constraint_axis=(True, False, False), mirror=False, use_proportional_edit=False, proportional_edit_falloff='SMOOTH', proportional_size=1, use_proportional_connected=False, use_proportional_projected=False)
  171. lattice_1 = bpy.context.selected_objects[0]
  172.  
  173. # https://blender.stackexchange.com/questions/163855/how-to-subdivide-mesh-with-python-and-blender-2-8
  174. bm = bmesh.new()
  175. bm.from_mesh(lattice_1.data)
  176. #bm = bmesh.from_edit_mesh(lattice_1.data)
  177. edges_to_split = [edge for edge in bm.edges if edge.verts[0].co.y == -1 * edge.verts[1].co.y]
  178. bmesh.ops.subdivide_edges(bm, edges=edges_to_split, cuts=1, use_grid_fill=True)
  179. bm.to_mesh(lattice_1.data)
  180. bm.free()
  181. lattice_1.data.update()
  182. #bmesh.update_edit_mesh(lattice_1.data)
  183.  
  184. modifier_latt = torus_1.modifiers.new("MeshDeform", 'MESH_DEFORM')
  185. modifier_latt.object = lattice_1
  186. modifier_latt.precision = 3
  187.  
  188. bpy.ops.object.select_all(action='DESELECT')
  189. bpy.context.view_layer.objects.active = torus_1
  190. torus_1.select_set(True)
  191. bpy.ops.object.meshdeform_bind(modifier="MeshDeform")
  192.  
  193. bm = bmesh.new()
  194. bm.from_mesh(lattice_1.data)
  195. for p in bm.verts:
  196. print(p.co)
  197. if p.co.x == -1.0:
  198. p.co.y = 0.0
  199. if stretch_2 and p.co.x == 1.0 and p.co.y != 0.0:
  200. #print(math.cos((2*math.pi)/(sections_2*2)))
  201. #print(radius_4*math.sin((2*math.pi)/(sections_2*2))/radius_2)
  202. p.co.x = math.cos((2*math.pi)/(sections_2*2))
  203. if p.co.y == 1.0:
  204. p.co.y = radius_4*math.sin((2*math.pi)/(sections_2*2))/radius_2
  205. if p.co.y == -1.0:
  206. p.co.y = -radius_4*math.sin((2*math.pi)/(sections_2*2))/radius_2
  207.  
  208. bm.to_mesh(lattice_1.data)
  209. bm.free()
  210. lattice_1.data.update()
  211.  
  212. modifier_arr = torus_1.modifiers.new("Array", 'ARRAY')
  213. modifier_arr.count = sections_2
  214. modifier_arr.use_relative_offset = False
  215. modifier_arr.use_constant_offset = True
  216. modifier_arr.constant_offset_displace[0] = 0
  217. modifier_arr.use_object_offset = True
  218. modifier_arr.offset_object = origin_1
  219.  
  220. bpy.ops.object.select_all(action='DESELECT')
  221. bpy.context.view_layer.objects.active = origin_1
  222. origin_1.select_set(True)
  223.  
  224. bpy.ops.transform.rotate(value=(2*math.pi)/sections_2, orient_axis='Y', orient_type='GLOBAL', orient_matrix=((1, 0, 0), (0, 1, 0), (0, 0, 1)), orient_matrix_type='GLOBAL', constraint_axis=(False, False, True), mirror=False, use_proportional_edit=False, proportional_edit_falloff='SMOOTH', proportional_size=1, use_proportional_connected=False, use_proportional_projected=False)
  225.  
  226. bpy.ops.object.select_all(action='DESELECT')
  227. context.view_layer.objects.active = torus_1
  228. torus_1.select_set(True)
  229. bpy.ops.object.modifier_apply(modifier="MeshDeform")
  230. bpy.ops.object.modifier_apply(modifier="Array")
  231.  
  232. bpy.ops.object.select_all(action='DESELECT')
  233. context.view_layer.objects.active = lattice_1
  234. lattice_1.select_set(True)
  235. origin_1.select_set(True)
  236. bpy.ops.object.delete(use_global=False, confirm=False)
  237.  
  238.  
  239. if level > 3:
  240. # fourth level torus
  241.  
  242. bpy.ops.mesh.primitive_uv_sphere_add(radius=1, enter_editmode=False, align='WORLD', location=(0, 0, 0), scale=(1, 1, 1))
  243. origin_1 = bpy.context.selected_objects[0]
  244.  
  245. bpy.ops.object.select_all(action='DESELECT')
  246. context.view_layer.objects.active = torus_1
  247. torus_1.select_set(True)
  248.  
  249. bpy.ops.transform.translate(value=(radius_5-radius_4, 0, 0), orient_axis_ortho='X', orient_type='GLOBAL', orient_matrix=((1, 0, 0), (0, 1, 0), (0, 0, 1)), orient_matrix_type='GLOBAL', constraint_axis=(True, False, False), mirror=False, use_proportional_edit=False, proportional_edit_falloff='SMOOTH', proportional_size=1, use_proportional_connected=False, use_proportional_projected=False)
  250. bpy.ops.object.origin_set(type='ORIGIN_CURSOR', center='MEDIAN')
  251.  
  252. bpy.ops.mesh.primitive_cube_add(enter_editmode=False, align='WORLD', location=(radius_5/2, 0, 0), scale=(1,1,1))
  253. bpy.ops.transform.resize(value=(radius_5/2, radius_4, radius_3), orient_type='GLOBAL', orient_matrix=((1, 0, 0), (0, 1, 0), (0, 0, 1)), orient_matrix_type='GLOBAL', constraint_axis=(True, False, False), mirror=False, use_proportional_edit=False, proportional_edit_falloff='SMOOTH', proportional_size=1, use_proportional_connected=False, use_proportional_projected=False)
  254. lattice_1 = bpy.context.selected_objects[0]
  255.  
  256. # https://blender.stackexchange.com/questions/163855/how-to-subdivide-mesh-with-python-and-blender-2-8
  257. bm = bmesh.new()
  258. bm.from_mesh(lattice_1.data)
  259. #bm = bmesh.from_edit_mesh(lattice_1.data)
  260. edges_to_split = [edge for edge in bm.edges if edge.verts[0].co.z == -1 * edge.verts[1].co.z]
  261. bmesh.ops.subdivide_edges(bm, edges=edges_to_split, cuts=1, use_grid_fill=True)
  262. bm.to_mesh(lattice_1.data)
  263. bm.free()
  264. lattice_1.data.update()
  265. #bmesh.update_edit_mesh(lattice_1.data)
  266.  
  267. modifier_latt = torus_1.modifiers.new("MeshDeform", 'MESH_DEFORM')
  268. modifier_latt.object = lattice_1
  269. modifier_latt.precision = 3
  270.  
  271. bpy.ops.object.select_all(action='DESELECT')
  272. bpy.context.view_layer.objects.active = torus_1
  273. torus_1.select_set(True)
  274. bpy.ops.object.meshdeform_bind(modifier="MeshDeform")
  275.  
  276. bm = bmesh.new()
  277. bm.from_mesh(lattice_1.data)
  278. for p in bm.verts:
  279. #print(p.co)
  280. if p.co.x == -1.0:
  281. p.co.z = 0.0
  282. if stretch_3 and p.co.x == 1.0 and p.co.z != 0.0:
  283. #print(math.cos((2*math.pi)/(sections_3*2)))
  284. #print(radius_5*math.sin((2*math.pi)/(sections_3*2))/radius_3)
  285. p.co.x = math.cos((2*math.pi)/(sections_3*2))
  286. if p.co.z == 1.0:
  287. p.co.z = radius_5*math.sin((2*math.pi)/(sections_3*2))/radius_3
  288. if p.co.z == -1.0:
  289. p.co.z = -radius_5*math.sin((2*math.pi)/(sections_3*2))/radius_3
  290.  
  291. bm.to_mesh(lattice_1.data)
  292. bm.free()
  293. lattice_1.data.update()
  294.  
  295. modifier_arr = torus_1.modifiers.new("Array", 'ARRAY')
  296. modifier_arr.count = sections_3
  297. modifier_arr.use_relative_offset = False
  298. modifier_arr.use_constant_offset = True
  299. modifier_arr.constant_offset_displace[0] = 0
  300. modifier_arr.use_object_offset = True
  301. modifier_arr.offset_object = origin_1
  302.  
  303. bpy.ops.object.select_all(action='DESELECT')
  304. bpy.context.view_layer.objects.active = origin_1
  305. origin_1.select_set(True)
  306.  
  307. bpy.ops.transform.rotate(value=(2*math.pi)/sections_3, orient_axis='Y', orient_type='GLOBAL', orient_matrix=((1, 0, 0), (0, 1, 0), (0, 0, 1)), orient_matrix_type='GLOBAL', constraint_axis=(False, True, False), mirror=False, use_proportional_edit=False, proportional_edit_falloff='SMOOTH', proportional_size=1, use_proportional_connected=False, use_proportional_projected=False)
  308.  
  309. bpy.ops.object.select_all(action='DESELECT')
  310. context.view_layer.objects.active = torus_1
  311. torus_1.select_set(True)
  312. bpy.ops.object.modifier_apply(modifier="MeshDeform")
  313. bpy.ops.object.modifier_apply(modifier="Array")
  314.  
  315. bpy.ops.object.select_all(action='DESELECT')
  316. context.view_layer.objects.active = lattice_1
  317. lattice_1.select_set(True)
  318. origin_1.select_set(True)
  319. bpy.ops.object.delete(use_global=False, confirm=False)
  320.  
  321.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement