Advertisement
Guest User

Untitled

a guest
Jul 23rd, 2017
79
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.53 KB | None | 0 0
  1. import bpy
  2. import mathutils
  3. import math
  4. from math import radians
  5. from mathutils import Matrix
  6.  
  7. # When DEBUG = True, this sets up a change-frame callback
  8. # that modifies the scene to be the current state of the animation,
  9. # deleting every object that doesn't have the 'pres' attribute set.
  10.  
  11. # When DEBUG = False, it actually renders the animation to a bunch of frames.
  12. # I seem to be unable to use blender's own animation rendering pipeline since
  13. # it doesn't have the context around for me to create primitive objects in??
  14.  
  15. DEBUG = False
  16.  
  17. SF = 5 # scale factor; ratio of how wide torus is to how thick it is
  18. MAXF = 24 # number of frames of animation
  19. C = bpy.context
  20. D = bpy.data
  21. scene = C.scene
  22. scene.frame_end = MAXF
  23.  
  24. # Uniform vector
  25. def uni(x):
  26. return ((x, x, x))
  27.  
  28. # Make a circle bezier curve with a name
  29. def circ(name, **kwargs):
  30. bpy.ops.curve.primitive_bezier_circle_add(**kwargs)
  31. C.active_object.name = name
  32.  
  33. # kinda surprised this is so hard. I would expect a 'make this bezier
  34. # not cyclic but make sure it has the same shape' operation to exist
  35. # as a UI-exposed option, but I haven't found it
  36. def decycle(sp):
  37. save_left = sp.bezier_points[0].handle_left.copy()
  38. save_right = sp.bezier_points[0].handle_right.copy()
  39. sp.use_cyclic_u = False
  40.  
  41. sp.bezier_points.add()
  42. sp.bezier_points[len(sp.bezier_points)-1].co = sp.bezier_points[0].co.copy()
  43. sp.bezier_points[len(sp.bezier_points)-1].handle_left = save_left
  44. sp.bezier_points[len(sp.bezier_points)-1].handle_right = save_right
  45. sp.bezier_points[0].handle_left_type = 'FREE'
  46. sp.bezier_points[0].handle_right_type = 'FREE'
  47. sp.bezier_points[0].handle_left = save_left
  48. sp.bezier_points[0].handle_right = save_right
  49.  
  50. def build_scene(scene, time):
  51. # time ∈ [0, 1]
  52.  
  53. # Delete everything. Not 100% sure I'm deleting enough everything to
  54. # avoid leaks, but I'm doing my best to cover the stuff I know about.
  55. for ob in scene.objects:
  56. ob.select = True
  57. if 'pres' in ob:
  58. ob.select = False
  59. bpy.ops.object.delete()
  60. for block in D.curves:
  61. if block.users == 0:
  62. D.curves.remove(block)
  63. for block in D.cameras:
  64. if block.users == 0:
  65. D.cameras.remove(block)
  66. for block in D.meshes:
  67. if block.users == 0:
  68. D.meshes.remove(block)
  69.  
  70. # Set cursor to origin
  71. scene.cursor_location = uni(0)
  72.  
  73. # parent
  74. bpy.ops.object.empty_add(type='PLAIN_AXES')
  75. C.scene.objects.active.name = 'Parent'
  76.  
  77. # Ring
  78. bpy.ops.curve.primitive_bezier_circle_add(radius=1 - 1./SF, location=uni(0))
  79. C.scene.objects.active.name = 'c1'
  80. bpy.ops.curve.primitive_bezier_circle_add(radius=1 + 1./SF, location=uni(0))
  81. C.scene.objects.active.name = 'c2'
  82. bpy.data.objects['c1'].rotation_euler = mathutils.Euler((radians(180),0,0), 'XYZ')
  83. D.objects['c1'].select = True
  84. D.objects['c2'].select = True
  85. bpy.ops.object.join()
  86. C.scene.objects.active.name = 'Ring'
  87.  
  88. # Outer
  89. circ('Outer', radius=SF)
  90. D.objects['Outer'].data.bevel_object = D.objects['Ring']
  91. decycle(D.objects['Outer'].data.splines[0])
  92.  
  93. D.objects['Outer'].data.bevel_factor_end = time
  94. D.objects['Outer'].data.bevel_factor_start = 0
  95. D.objects['Outer'].data.use_fill_caps = True
  96.  
  97. # end caps
  98. bpy.ops.mesh.primitive_torus_add(major_radius=1, minor_radius=1./SF, location=((-SF, 0, 0)),
  99. rotation=mathutils.Euler((radians(90), 0, 0), 'XYZ'))
  100. C.scene.objects.active.name = 'Cap1'
  101. for p in bpy.data.objects['Cap1'].data.polygons:
  102. p.use_smooth = True
  103.  
  104. bpy.ops.mesh.primitive_torus_add(major_radius=1, minor_radius=1./SF, location=((-SF, 0, 0)),
  105. rotation=mathutils.Euler((radians(90), 0, 0), 'XYZ'))
  106. C.scene.objects.active.name = 'Cap2'
  107. for p in bpy.data.objects['Cap2'].data.polygons:
  108. p.use_smooth = True
  109.  
  110. obj = bpy.data.objects['Cap2']
  111. mat = Matrix.Rotation(-time * radians(360), 4, 'Z')
  112. obj.matrix_world = mat * obj.matrix_world
  113.  
  114. # Parenting
  115. D.objects['Outer'].parent = D.objects['Parent']
  116. D.objects['Cap1'].parent = D.objects['Parent']
  117. D.objects['Cap2'].parent = D.objects['Parent']
  118.  
  119. # Materials
  120. bpy.data.objects['Outer'].active_material = bpy.data.materials['Red']
  121. bpy.data.objects['Cap1'].active_material = bpy.data.materials['Red']
  122. bpy.data.objects['Cap2'].active_material = bpy.data.materials['Red']
  123.  
  124. obj = bpy.data.objects['Parent']
  125. mat = Matrix.Translation(((1. - time) * SF, 0, 0))
  126. obj.matrix_world = mat * obj.matrix_world
  127.  
  128. mat = Matrix.Rotation(-time * radians(90), 4, 'X')
  129. obj.matrix_world = mat * obj.matrix_world
  130.  
  131. mat = Matrix.Scale(math.pow(1. / SF, time), 4)
  132. obj.matrix_world = mat * obj.matrix_world
  133.  
  134. # for area in bpy.context.screen.areas:
  135. # if area.type == 'VIEW_3D':
  136. # override = bpy.context.copy()
  137. # override['area'] = area
  138. # bpy.ops.view3d.viewnumpad(override, type = 'CAMERA')
  139. # break
  140.  
  141. # scene.camera = D.objects['Camera']
  142. # for area in bpy.context.screen.areas:
  143. # if area.type == 'VIEW_3D':
  144. # area.spaces[0].region_3d.view_perspective = 'CAMERA'
  145.  
  146. def handler(scene):
  147. build_scene(scene, (scene.frame_current - 1) / MAXF)
  148.  
  149. bpy.app.handlers.frame_change_pre.clear()
  150.  
  151. def ease(t):
  152. return 3 * t * t - 2 * t * t * t
  153.  
  154. if DEBUG:
  155. bpy.app.handlers.frame_change_pre.append(handler)
  156. else:
  157. bpy.context.scene.render.filepath = '/tmp/frames/'
  158. for n in range(MAXF):
  159. scene.frame_start = n
  160. scene.frame_end = n
  161. build_scene(scene, ease (n * 1.0 / MAXF))
  162. bpy.context.scene.render.resolution_x = 640
  163. bpy.context.scene.render.resolution_y = 480
  164. C.scene.render.image_settings.file_format = 'PNG'
  165. C.scene.cycles.samples = 128
  166. bpy.ops.render.render(animation=True)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement