deep_computer.py 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. import bpy
  2. import mathutils
  3. import math
  4. import random
  5. # first, clean the slate
  6. # for o in bpy.data.objects:
  7. # bpy.data.objects.remove(o)
  8. # # add a camera
  9. # cam = bpy.data.cameras.new("EndlessCamera")
  10. # cam.type = 'ORTHO'
  11. # cam.angle = 0.85756
  12. # cam.clip_start = 0.100
  13. # cam.clip_end = 100.0
  14. # cam.lens = 35
  15. # cam.ortho_scale = 6.0
  16. # cam.sensor_height = 18
  17. # cam.sensor_width = 32
  18. # cam_obj = bpy.data.objects.new("EndlessCameraObj", cam)
  19. # cam_obj.location = mathutils.Vector((-10, -10, 8.2))
  20. # cam_obj.rotation_euler = mathutils.Vector((1.047, 0.0, -0.7854))
  21. # bpy.context.collection.objects.link(cam_obj)
  22. # bpy.context.scene.camera = cam_obj
  23. # # light sources
  24. # # lamp
  25. # bpy.ops.object.add(type='LIGHT', location=(1.568, -3.856, 1.311))
  26. # lamp = bpy.context.object
  27. # lamp.data.type = 'POINT'
  28. # lamp.data.cutoff_distance = 30.0
  29. # lamp.data.energy = 2
  30. # lamp.data.shadow_buffer_clip_start = 1.00
  31. # lamp.data.shadow_soft_size = 1.0
  32. # lamp.data.use_shadow = True
  33. # lamp.rotation_euler = mathutils.Vector((0.6503271, 0.05521698, 1.866455))
  34. # # sun
  35. # bpy.ops.object.add(type='LIGHT', location=(0.7973, 7.599, 4.7))
  36. # sun = bpy.context.object
  37. # sun.data.type='SUN'
  38. # sun.data.cutoff_distance = 30.0
  39. # sun.data.energy = 2
  40. # sun.data.shadow_buffer_clip_start = 1.00
  41. # sun.data.shadow_soft_size = 1.0
  42. # sun.data.use_shadow = True
  43. # sun.rotation_euler = mathutils.Vector((-0.418879, -0.1396263, 0.2094395))
  44. # we need five materials
  45. # - the monitor (image texture)
  46. # - the metal for the case
  47. # - three colors for the buttons
  48. # - green (pressed down)
  49. # - grey/clear (most unpressed)
  50. # - red (unpressed but alert)
  51. monitor_mat = bpy.data.materials.new("ComputerMonitor")
  52. monitor_mat.diffuse_color = [0, 0.02, 0, 1]
  53. monitor_mat.specular_color = [0.9, 1, 0.9]
  54. monitor_mat.roughness = 0.05
  55. monitor_mat.use_nodes = True
  56. mon_nodes = monitor_mat.node_tree.nodes
  57. mon_links = monitor_mat.node_tree.links
  58. mon_mat_output = mon_nodes.get('Material Output')
  59. mon_bsdf = mon_nodes.get('Principled BSDF')
  60. mon_bsdf.inputs['Roughness'].default_value = 0.1
  61. mon_bsdf.inputs['Emission Strength'].default_value = 3
  62. mon_img = bpy.data.images.load(filepath = '/home/jmelesky/Pictures/game images/oscilloscreen 5.png')
  63. mon_imgtx = mon_nodes.new('ShaderNodeTexImage')
  64. mon_imgtx.image = mon_img
  65. mon_links.new(mon_imgtx.outputs['Color'], mon_bsdf.inputs['Base Color'])
  66. mon_ramp = mon_nodes.new('ShaderNodeValToRGB')
  67. mon_ramp.color_ramp.interpolation = 'B_SPLINE'
  68. mon_ramp.color_ramp.elements[0].position = 0.1
  69. mon_ramp.color_ramp.elements[1].color = [0.05, 1.0, 0.0, 1.0]
  70. mon_links.new(mon_imgtx.outputs['Color'], mon_ramp.inputs['Fac'])
  71. mon_links.new(mon_ramp.outputs['Color'], mon_bsdf.inputs['Emission Color'])
  72. metal_mat = bpy.data.materials.new("ComputerMetal")
  73. metal_mat.use_nodes = True
  74. metal_nodes = metal_mat.node_tree.nodes
  75. metal_links = metal_mat.node_tree.links
  76. metal_mat_output = metal_nodes.get('Material Output')
  77. metal_bsdf = metal_nodes.get('Principled BSDF')
  78. metal_bsdf.inputs['Metallic'].default_value = 1.0
  79. metal_noise = metal_nodes.new('ShaderNodeTexNoise')
  80. metal_noise.inputs['Scale'].default_value = 70.0
  81. metal_noise.inputs['Detail'].default_value = 15.0
  82. metal_noise.inputs['Roughness'].default_value = 0.6
  83. metal_ramp = metal_nodes.new('ShaderNodeValToRGB')
  84. metal_ramp.color_ramp.elements[0].color = [0.012, 0.006, 0.001, 1.0]
  85. metal_ramp.color_ramp.elements[1].color = [0.0204, 0.0204, 0.0204, 1.0]
  86. metal_links.new(metal_noise.outputs['Fac'], metal_ramp.inputs['Fac'])
  87. metal_links.new(metal_ramp.outputs['Color'], metal_bsdf.inputs['Base Color'])
  88. metal_bump = metal_nodes.new('ShaderNodeBump')
  89. metal_bump.invert = True
  90. metal_bump.inputs['Strength'].default_value = 0.3
  91. metal_links.new(metal_noise.outputs['Fac'], metal_bump.inputs['Height'])
  92. metal_links.new(metal_bump.outputs['Normal'], metal_bsdf.inputs['Normal'])
  93. metal_links.new(metal_bump.outputs['Normal'], metal_bsdf.inputs['Roughness'])
  94. down_button_mat = bpy.data.materials.new("DownButton")
  95. down_button_mat.use_nodes = True
  96. down_button_mat.blend_method = 'BLEND'
  97. down_bsdf = down_button_mat.node_tree.nodes.get('Principled BSDF')
  98. down_bsdf.inputs['Base Color'].default_value = [0.5, 0.5, 0.5, 0.95]
  99. down_bsdf.inputs['Roughness'].default_value = 0.4
  100. down_bsdf.inputs['Emission Color'].default_value = [0.2, 0.85, 0.2, 0.3]
  101. down_bsdf.inputs['Emission Strength'].default_value = 0.8
  102. up_button_mat = bpy.data.materials.new("UpButton")
  103. up_button_mat.diffuse_color = [0.5, 0.5, 0.5, 0.4]
  104. up_button_mat.roughness = 0.8
  105. up_button_mat.blend_method = 'BLEND'
  106. attn_button_mat = bpy.data.materials.new("AttnButton")
  107. attn_button_mat.use_nodes = True
  108. attn_button_mat.blend_method = 'BLEND'
  109. attn_bsdf = attn_button_mat.node_tree.nodes.get('Principled BSDF')
  110. attn_bsdf.inputs['Base Color'].default_value = [0.5, 0.5, 0.5, 0.95]
  111. attn_bsdf.inputs['Roughness'].default_value = 0.4
  112. attn_bsdf.inputs['Emission Color'].default_value = [0.7, 0.1, 0.1, 0.3]
  113. attn_bsdf.inputs['Emission Strength'].default_value = 0.7
  114. # now the big box
  115. back_bottom_left = (0,0,0)
  116. back_top_left = (0,0,8)
  117. front_top_left = (2,0,8)
  118. front_mid_left = (4,0,3)
  119. front_bottom_left = (4,0,0)
  120. back_bottom_right = (0,10,0)
  121. back_top_right = (0,10,8)
  122. front_top_right = (2,10,8)
  123. front_mid_right = (4,10,3)
  124. front_bottom_right = (4,10,0)
  125. box_vertices = [back_bottom_left, back_top_left, back_bottom_right, back_top_right,
  126. front_top_left, front_top_right, front_mid_left, front_mid_right,
  127. front_bottom_left, front_bottom_right]
  128. box_faces = [
  129. (0,1,3,2), # the back of the box: back_bottom_left, back_top_left, back_top_right, back_bottom_right
  130. (0,2,9,8), # the bottom: back_bottom_left, back_bottom_right, front_bottom_right, front_bottom_left
  131. (8,9,7,6), # lower front plate: front_bottom_left, front_bottom_right, front_mid_right, front_mid_left
  132. (9,2,3,5,7), # right side panel (5 edges): front_bottom_right, back_bottom_right, back_top_right, front_top_right, front_mid_right
  133. (0,8,6,4,1), # left side panel: back_bottom_left, front_bottom_left, front_mid_left, front_top_left, back_top_left
  134. (6,7,5,4), # upper front plate: front_mid_left, front_mid_right, front_top_right, front_top_left
  135. (4,5,3,1), # top: front_top_left, front_top_right, back_top_right, back_top_left
  136. ]
  137. # box_mat = bpy.data.materials.new('MyBoxMaterial')
  138. # box_mat.use_nodes = True
  139. # if box_mat.node_tree:
  140. # box_mat.node_tree.links.clear()
  141. # box_mat.node_tree.nodes.clear()
  142. # box_output = box_mat.node_tree.nodes.new(type='ShaderNodeOutputMaterial')
  143. # box_shader = box_mat.node_tree.nodes.new(type='ShaderNodeBsdfDiffuse')
  144. # box_mat.node_tree.nodes['Diffuse BSDF'].inputs[0].default_value = (.125, .179, .263, 1)
  145. # box_mat.node_tree.links.new(box_shader.outputs[0], box_output.inputs[0])
  146. box_mesh = bpy.data.meshes.new('MyComputerBoxMesh')
  147. box_mesh.from_pydata(box_vertices, [], box_faces)
  148. box_obj = bpy.data.objects.new('MyComputerBox', box_mesh)
  149. box_obj.data.materials.append(metal_mat)
  150. bpy.context.scene.collection.objects.link(box_obj)
  151. # the oscilloscope-style monitor
  152. monitor_location = mathutils.Vector((3, 2.5, 5.5))
  153. monitor_scale = mathutils.Vector((.4, 1, 1))
  154. monitor_rotation = mathutils.Euler((0, math.radians(203), math.radians(180)))
  155. bpy.ops.mesh.primitive_uv_sphere_add(
  156. segments=32,
  157. ring_count=16,
  158. radius=2,
  159. location=monitor_location,
  160. scale=monitor_scale, # this is relative to the size
  161. rotation=monitor_rotation)
  162. # smooth the monitor, add a texture
  163. monitor_obj = bpy.context.active_object
  164. for f in monitor_obj.data.polygons:
  165. f.use_smooth = True
  166. monitor_obj.data.update()
  167. monitor_obj.data.materials.append(monitor_mat)
  168. # three rows of buttons, randomly depressed
  169. #
  170. # a better way to do this would be to set the buttons in a group,
  171. # then rotate that entire group. i'm not there yet, so we're
  172. # using some magic numbers for positional offsets.
  173. buttons = []
  174. for i in [7, 5.5, 4]:
  175. for j in [6.8, 7.2, 7.6, 8, 8.4, 8.8, 9.2]:
  176. if random.random() > .6:
  177. button_location = mathutils.Vector((5.0 - (i/2.5), j, i-.1))
  178. button_material = down_button_mat
  179. else:
  180. button_location = mathutils.Vector((5.2 - (i/2.5), j, i))
  181. if random.random() > .8:
  182. button_material = attn_button_mat
  183. else:
  184. button_material = up_button_mat
  185. bpy.ops.mesh.primitive_cube_add(
  186. size=1,
  187. location=button_location,
  188. rotation=monitor_rotation,
  189. scale=mathutils.Vector((.8, .2, .6)))
  190. button = bpy.context.active_object
  191. buttons.append(button)
  192. button.data.materials.append(button_material)
  193. box_obj.select_set(True)
  194. monitor_obj.select_set(True)
  195. for b in buttons:
  196. b.select_set(True)
  197. bpy.ops.transform.resize(
  198. value=(0.25, 0.25, 0.25)
  199. )
  200. bpy.ops.transform.rotate(
  201. value=math.radians(90)
  202. )
  203. bpy.ops.transform.translate(
  204. value=(-2,-5,-3.3)
  205. )