glitch3d 0.2.2.3 → 0.2.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/fixtures/dude.jpg +0 -0
- data/lib/glitch3d/bpy/canvas/dreamatorium.py +73 -0
- data/lib/glitch3d/bpy/helpers.py +121 -78
- data/lib/glitch3d/bpy/lighting.py +32 -0
- data/lib/glitch3d/bpy/main.py +135 -0
- data/lib/glitch3d/bpy/render_settings.py +26 -0
- data/lib/glitch3d/version.rb +1 -1
- data/lib/glitch3d.rb +24 -5
- metadata +7 -4
- data/fixtures/demo.png +0 -0
- data/lib/glitch3d/bpy/rendering.py +0 -236
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a15b6ba339b081828a44dfb59587d73745cecfbc
|
4
|
+
data.tar.gz: 4b7d71946ca52bf70a562a9ec457b9a72cbdded8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c5c5fd02a892349daf3b9fa218d9782a79804e1b8feb26d92a56903bb4a821d2aaef940d5c304ed35df34adcca3fde11708898c37f99b71b8a277cc5b77402a5
|
7
|
+
data.tar.gz: 6fa00d4f1fd9ada772c01a6a145e42348ca23717c4497c74539d3d9766895284240acc52bdb6768316d743a9e445ea40e40c51eb48fd3471a30bfcf5ebec3aa7
|
data/fixtures/dude.jpg
ADDED
Binary file
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# Load props
|
2
|
+
bpy.ops.import_scene.obj(filepath = os.path.join(FIXTURES_FOLDER_PATH + 'm4a1.obj'), use_edges=True)
|
3
|
+
m4a1 = bpy.data.objects['m4a1']
|
4
|
+
m4a1.location = rand_location()
|
5
|
+
m4a1.scale = (0.5, 0.5, 0.5)
|
6
|
+
props.append(m4a1)
|
7
|
+
|
8
|
+
# Add props
|
9
|
+
rand_primitive = random.choice(PRIMITIVES)
|
10
|
+
build_composite_object(rand_primitive, 4, 1)
|
11
|
+
|
12
|
+
# Set up virtual displays
|
13
|
+
bpy.ops.mesh.primitive_grid_add(x_subdivisions=100, y_subdivisions=100, location=(0, 6, 2))
|
14
|
+
display1 = bpy.data.objects['Grid']
|
15
|
+
bpy.ops.mesh.primitive_grid_add(x_subdivisions=100, y_subdivisions=100, location=(6, 0, 2))
|
16
|
+
display2 = bpy.data.objects['Grid.001']
|
17
|
+
|
18
|
+
bpy.data.groups.new('Displays')
|
19
|
+
bpy.data.groups['Displays'].objects.link(display1)
|
20
|
+
bpy.data.groups['Displays'].objects.link(display2)
|
21
|
+
|
22
|
+
display1.rotation_euler.x += math.radians(90)
|
23
|
+
display1.rotation_euler.z -= math.radians(90)
|
24
|
+
display2.rotation_euler.x += math.radians(90)
|
25
|
+
display2.rotation_euler.y += math.radians(90)
|
26
|
+
display2.rotation_euler.z += math.radians(120)
|
27
|
+
|
28
|
+
for display in bpy.data.groups['Displays'].objects:
|
29
|
+
display.rotation_euler.x += math.radians(90)
|
30
|
+
display.scale = DISPLAY_SCALE
|
31
|
+
texture_object(display)
|
32
|
+
make_texture_object_transparent(display)
|
33
|
+
unwrap_model(display)
|
34
|
+
glitch(display)
|
35
|
+
|
36
|
+
glitch(m4a1)
|
37
|
+
make_object_gradient_fabulous(m4a1, rand_color(), rand_color())
|
38
|
+
|
39
|
+
# Make floor
|
40
|
+
bpy.ops.mesh.primitive_plane_add(location=(0, 0, -2))
|
41
|
+
floor = last_added_object('PLANE')
|
42
|
+
bpy.data.groups['Plane'].objects.link(floor)
|
43
|
+
floor.scale = (20,20,20)
|
44
|
+
subdivide(floor, 8)
|
45
|
+
displace(floor)
|
46
|
+
texture_object(floor)
|
47
|
+
|
48
|
+
OCEAN = add_ocean(10, 20)
|
49
|
+
|
50
|
+
# Create lines as backdrop
|
51
|
+
bpy.data.groups.new('Lines')
|
52
|
+
for j in range(0,20):
|
53
|
+
for i in range(0, 20):
|
54
|
+
new_line = create_line('line' + str(uuid.uuid1()), series(30), 0.003, (j, -10, 2))
|
55
|
+
new_line.location.z += i / 3
|
56
|
+
|
57
|
+
# Add flying letters, lmao
|
58
|
+
for index in range(1, len(WORDS)):
|
59
|
+
new_object = spawn_text()
|
60
|
+
props.append(new_object)
|
61
|
+
text_scale = random.uniform(0.75, 3)
|
62
|
+
make_object_glossy(new_object, rand_color(), 0.0)
|
63
|
+
new_object.scale = (text_scale, text_scale, text_scale)
|
64
|
+
new_object.location = rand_location()
|
65
|
+
# pivot text to make it readable by camera
|
66
|
+
new_object.rotation_euler.x += math.radians(90)
|
67
|
+
new_object.rotation_euler.z += math.radians(90)
|
68
|
+
|
69
|
+
for plane in bpy.data.groups['Plane'].objects:
|
70
|
+
unwrap_model(plane)
|
71
|
+
|
72
|
+
for obj in WIREFRAMES:
|
73
|
+
wireframize(obj)
|
data/lib/glitch3d/bpy/helpers.py
CHANGED
@@ -1,29 +1,18 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
import datetime
|
4
|
-
import bmesh
|
5
|
-
import random
|
6
|
-
import code
|
7
|
-
import math
|
8
|
-
import mathutils
|
9
|
-
import random
|
10
|
-
import uuid
|
11
|
-
import sys
|
12
|
-
import logging
|
13
|
-
import string
|
14
|
-
import colorsys
|
15
|
-
import numpy
|
16
|
-
|
17
|
-
REFLECTOR_SCALE = random.uniform(4, 6)
|
18
|
-
REFLECTOR_STRENGTH = random.uniform(8, 12)
|
19
|
-
REFLECTOR_LOCATION_PADDING = random.uniform(10, 12)
|
20
|
-
WIREFRAME_THICKNESS = random.uniform(0.008, 0.01)
|
21
|
-
DISPLACEMENT_AMPLITUDE = random.uniform(0.06, 0.08)
|
22
|
-
REPLACE_TARGET = '6'
|
23
|
-
REPLACEMENT = '2'
|
24
|
-
ORIGIN = (0,0,0)
|
25
|
-
NUMBER_OF_FRAMES = 100
|
1
|
+
# DISCLAIMER: all of this could be done in a much more intelligent way (with more Python knowledge)
|
2
|
+
# This is just what works for now for the needs of my current project
|
26
3
|
|
4
|
+
REFLECTOR_SCALE = random.uniform(5, 8)
|
5
|
+
REFLECTOR_STRENGTH = random.uniform(10, 15)
|
6
|
+
REFLECTOR_LOCATION_PADDING = random.uniform(10, 12)
|
7
|
+
WIREFRAME_THICKNESS = random.uniform(0.006, 0.02)
|
8
|
+
DISPLACEMENT_AMPLITUDE = random.uniform(0.02, 0.1)
|
9
|
+
REPLACE_TARGET = str(random.uniform(0, 9))
|
10
|
+
REPLACEMENT = str(random.uniform(0, 9))
|
11
|
+
ORIGIN = (0,0,2)
|
12
|
+
NUMBER_OF_FRAMES = 400
|
13
|
+
SCATTER_INTENSITY = 0.015
|
14
|
+
ABSORPTION_INTENSITY = 0.25
|
15
|
+
DISPLAY_SCALE = (2, 2, 2)
|
27
16
|
PRIMITIVES = ['PYRAMID', 'CUBE']
|
28
17
|
props = []
|
29
18
|
YELLOW = (1, 0.7, 0.1, 1)
|
@@ -32,39 +21,40 @@ BLUE = (0.1, 0.1, 0.8, 1)
|
|
32
21
|
PINK = (0.8, 0.2, 0.7, 1.0)
|
33
22
|
WORDS = string.ascii_lowercase
|
34
23
|
WIREFRAMES = []
|
35
|
-
|
36
|
-
context = bpy.context
|
24
|
+
VORONOIED = []
|
37
25
|
|
38
26
|
def debug():
|
39
27
|
code.interact(local=dict(globals(), **locals()))
|
40
28
|
sys.exit("Aborting execution")
|
41
29
|
|
42
30
|
# Helper methods
|
43
|
-
def look_at(
|
44
|
-
location_camera =
|
45
|
-
|
46
|
-
direction =
|
31
|
+
def look_at(object):
|
32
|
+
location_camera = CAMERA.matrix_world.to_translation()
|
33
|
+
location_object = object.matrix_world.to_translation()
|
34
|
+
direction = location_object - location_camera
|
47
35
|
rot_quat = direction.to_track_quat('-Z', 'Y')
|
48
|
-
|
36
|
+
CAMERA.rotation_euler = rot_quat.to_euler()
|
49
37
|
|
50
38
|
def empty_materials():
|
51
39
|
for material in bpy.data.materials.keys():
|
52
40
|
bpy.data.materials.remove(object.data.materials[material])
|
53
41
|
|
54
|
-
def shoot(
|
42
|
+
def shoot(model_object, filepath):
|
55
43
|
directory = os.path.dirname('./renders')
|
56
44
|
if not os.path.exists(directory):
|
57
45
|
os.makedirs(directory)
|
58
|
-
look_at(
|
59
|
-
print('Camera now at location: ' + camera_location_string(
|
46
|
+
look_at(model_object)
|
47
|
+
print('Camera now at location: ' + camera_location_string(CAMERA) + ' / rotation: ' + camera_rotation_string(CAMERA))
|
60
48
|
bpy.context.scene.render.filepath = filepath
|
61
49
|
if animate:
|
62
|
-
bpy.context.scene.render.filepath = './renders/animation-' + str(uuid.uuid1()) + '/'
|
63
50
|
return bpy.ops.render.render(animation=animate)
|
64
51
|
bpy.ops.render.render(write_still=True)
|
65
52
|
|
66
53
|
def output_name(index, model_path):
|
67
|
-
|
54
|
+
if animate == True:
|
55
|
+
return './renders/' + os.path.splitext(model_path)[0].split('/')[-1] + '_' + str(index) + '_' + str(datetime.date.today()) + '_' + str(mode) + '.avi'
|
56
|
+
else:
|
57
|
+
return './renders/' + os.path.splitext(model_path)[0].split('/')[-1] + '_' + str(index) + '_' + str(datetime.date.today()) + '_' + str(mode) + '.png'
|
68
58
|
|
69
59
|
def rotate(model_object, index):
|
70
60
|
model_object.rotation_euler[2] = math.radians(index * (360.0 / shots_number))
|
@@ -80,7 +70,7 @@ def rand_rotation():
|
|
80
70
|
return (rand_rotation_value(), rand_rotation_value(), rand_rotation_value())
|
81
71
|
|
82
72
|
def rand_rotation_value():
|
83
|
-
return round(random.uniform(0,
|
73
|
+
return round(math.radians(random.uniform(0, 60), 10))
|
84
74
|
|
85
75
|
def rand_rotation():
|
86
76
|
return (random.uniform(0, 20), random.uniform(0, 20), random.uniform(0, 20))
|
@@ -106,20 +96,6 @@ def unwrap_model(obj):
|
|
106
96
|
bpy.ops.uv.unwrap()
|
107
97
|
bpy.ops.object.mode_set(mode='OBJECT')
|
108
98
|
|
109
|
-
def get_args():
|
110
|
-
parser = argparse.ArgumentParser()
|
111
|
-
# get all script args
|
112
|
-
_, all_arguments = parser.parse_known_args()
|
113
|
-
double_dash_index = all_arguments.index('--')
|
114
|
-
script_args = all_arguments[double_dash_index + 1: ]
|
115
|
-
# add parser rules
|
116
|
-
parser.add_argument('-f', '--file', help="obj file to render")
|
117
|
-
parser.add_argument('-n', '--shots-number', help="number of shots desired")
|
118
|
-
parser.add_argument('-m', '--mode', help="quality mode: low | high")
|
119
|
-
parser.add_argument('-p', '--path', help="root path of assets")
|
120
|
-
parsed_script_args, _ = parser.parse_known_args(script_args)
|
121
|
-
return parsed_script_args
|
122
|
-
|
123
99
|
def camera_rotation_string(camera):
|
124
100
|
return str(int(camera.rotation_euler.x)) + ' ' + str(int(camera.rotation_euler.y)) + ' ' + str(int(camera.rotation_euler.z))
|
125
101
|
|
@@ -161,13 +137,12 @@ def mix_nodes(material, node1, node2):
|
|
161
137
|
material.node_tree.links.new(mix.inputs[2], node2.outputs[0])
|
162
138
|
assign_node_to_output(material, mix)
|
163
139
|
|
164
|
-
def make_object_glossy(obj, color):
|
140
|
+
def make_object_glossy(obj, color = (PINK), roughness = 0.2):
|
165
141
|
material = bpy.data.materials.new('Glossy Material - ' + str(uuid.uuid1()))
|
166
142
|
material.use_nodes = True
|
167
143
|
glossy_node = material.node_tree.nodes.new('ShaderNodeBsdfGlossy')
|
168
144
|
glossy_node.inputs[0].default_value = color
|
169
|
-
|
170
|
-
glossy_node.inputs[1].default_value = 0.2
|
145
|
+
glossy_node.inputs[1].default_value = roughness
|
171
146
|
assign_node_to_output(material, glossy_node)
|
172
147
|
assign_material(obj, material)
|
173
148
|
|
@@ -175,13 +150,16 @@ def make_object_reflector(obj):
|
|
175
150
|
obj.scale = (REFLECTOR_SCALE, REFLECTOR_SCALE, REFLECTOR_SCALE)
|
176
151
|
make_object_emitter(obj, REFLECTOR_STRENGTH)
|
177
152
|
|
178
|
-
def
|
179
|
-
material =
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
153
|
+
def make_texture_object_transparent(obj, color = (1,1,1,0.5), intensity = 0.25):
|
154
|
+
material = obj.data.materials[-1]
|
155
|
+
emission_node = material.node_tree.nodes['Emission']
|
156
|
+
trans = material.node_tree.nodes.new('ShaderNodeBsdfTransparent')
|
157
|
+
add = material.node_tree.nodes.new('ShaderNodeMixShader')
|
158
|
+
material.node_tree.links.new(emission_node.outputs[0], add.inputs[0])
|
159
|
+
material.node_tree.links.new(trans.outputs[0], add.inputs[1])
|
160
|
+
material.node_tree.links.new(emission_node.outputs[0], add.inputs[0])
|
161
|
+
add.inputs[0].default_value = intensity
|
162
|
+
trans.inputs[0].default_value = color
|
185
163
|
|
186
164
|
def make_object_emitter(obj, emission_strength):
|
187
165
|
emissive_material = bpy.data.materials.new('Emissive Material #' + str(uuid.uuid1()))
|
@@ -209,6 +187,14 @@ def make_object_gradient_fabulous(obj, color1, color2):
|
|
209
187
|
mixer_node.inputs['Color1'].default_value = color1
|
210
188
|
mixer_node.inputs['Color2'].default_value = color2
|
211
189
|
|
190
|
+
def voronoize(obj, scale = 5.0):
|
191
|
+
material = obj.data.materials[-1]
|
192
|
+
texture_node = material.node_tree.nodes.new('ShaderNodeTexVoronoi')
|
193
|
+
material.node_tree.links.new(texture_node.outputs['Color'], material.node_tree.nodes['Glossy BSDF'].inputs['Color'])
|
194
|
+
texture_node.coloring = 'CELLS'
|
195
|
+
texture_node.inputs[1].default_value = scale
|
196
|
+
VORONOIED.append(obj)
|
197
|
+
|
212
198
|
def texture_object(obj):
|
213
199
|
new_material = create_cycles_material()
|
214
200
|
assign_texture_to_material(new_material, random_texture())
|
@@ -258,8 +244,8 @@ def series(length):
|
|
258
244
|
return list(map(lambda x: (0, x, math.cos(x)), numpy.arange(0.0, length, 0.1)))
|
259
245
|
|
260
246
|
def randomize_reflectors_colors():
|
261
|
-
|
262
|
-
|
247
|
+
for r in bpy.data.groups['Plane'].objects:
|
248
|
+
r.data.materials[-1].node_tree.nodes['Emission'].inputs[0].default_value = rand_color()
|
263
249
|
|
264
250
|
def add_object(obj, x, y, z, radius):
|
265
251
|
infer_primitive(obj, location=(x, y, z), radius=radius)
|
@@ -314,8 +300,8 @@ def displace_vector(vector):
|
|
314
300
|
return mathutils.Vector((vector.x + random.uniform(-DISPLACEMENT_AMPLITUDE, DISPLACEMENT_AMPLITUDE), vector.y + random.uniform(-DISPLACEMENT_AMPLITUDE, DISPLACEMENT_AMPLITUDE), vector.z + random.uniform(-DISPLACEMENT_AMPLITUDE, DISPLACEMENT_AMPLITUDE)))
|
315
301
|
|
316
302
|
# Replace vertex coordinate everywhere
|
317
|
-
def find_and_replace(vector):
|
318
|
-
return mathutils.Vector((float(str(vector.x).replace(
|
303
|
+
def find_and_replace(vector, target = random.uniform(0,9), replacement = random.uniform(0,9)):
|
304
|
+
return mathutils.Vector((float(str(vector.x).replace(target, replacement)), float(str(vector.y).replace(target, replacement)), float(str(vector.z).replace(target, replacement))))
|
319
305
|
|
320
306
|
def glitch(object):
|
321
307
|
bpy.ops.object.mode_set(mode='OBJECT')
|
@@ -360,7 +346,7 @@ def add_ocean(spatial_size, resolution):
|
|
360
346
|
wireframize(shadow)
|
361
347
|
shadow.name = 'ocean'
|
362
348
|
ocean.name = 'ocean'
|
363
|
-
return ocean
|
349
|
+
return [ocean, shadow]
|
364
350
|
|
365
351
|
# Delete current objects
|
366
352
|
def flush_all_objects():
|
@@ -400,14 +386,31 @@ def build_pyramid(width=random.uniform(1,3), length=random.uniform(1,3), height=
|
|
400
386
|
faces.append([3,0,4])
|
401
387
|
return create_mesh('Pyramid ' + str(uuid.uuid1()), verts, faces, location)
|
402
388
|
|
403
|
-
def
|
404
|
-
|
405
|
-
|
389
|
+
def move_ocean(ocean):
|
390
|
+
ocean.modifiers['Ocean'].time += 1.5
|
391
|
+
ocean.modifiers['Ocean'].random_seed = round(random.uniform(0, 100))
|
392
|
+
ocean.modifers['Ocean'].choppiness += 0.3
|
393
|
+
|
394
|
+
def camera_path(pitch):
|
395
|
+
res = []
|
396
|
+
initial_z = INITIAL_CAMERA_LOCATION[2]
|
397
|
+
initial_x = INITIAL_CAMERA_LOCATION[0]
|
398
|
+
for y in numpy.arange(initial_x, -initial_x, pitch):
|
399
|
+
res.append((initial_x, y, initial_z))
|
400
|
+
for x in numpy.arange(initial_x, -initial_x, pitch):
|
401
|
+
res.append((x,-initial_x, initial_z))
|
402
|
+
for y in numpy.arange(-initial_x, initial_x, pitch):
|
403
|
+
res.append((-initial_x, y, initial_z))
|
404
|
+
for x in numpy.arange(-initial_x, initial_x, pitch):
|
405
|
+
res.append((x, initial_x, initial_z))
|
406
|
+
return res
|
407
|
+
|
408
|
+
def still_routine():
|
409
|
+
CAMERA.location.x = INITIAL_CAMERA_LOCATION[0] + round(random.uniform(-2, 2), 10)
|
410
|
+
CAMERA.location.y = INITIAL_CAMERA_LOCATION[1] + round(random.uniform(-2, 2), 10)
|
406
411
|
randomize_reflectors_colors()
|
407
|
-
OCEAN
|
408
|
-
|
409
|
-
make_object_glossy(OCEAN, rand_color())
|
410
|
-
OCEAN.modifiers['Ocean'].choppiness += 0.3
|
412
|
+
map(move_ocean, OCEAN)
|
413
|
+
map(make_object_glossy, OCEAN)
|
411
414
|
rotate(model_object, index)
|
412
415
|
for l in bpy.data.groups['Lines'].objects:
|
413
416
|
rotation = rand_rotation()
|
@@ -416,13 +419,31 @@ def dance_routine():
|
|
416
419
|
prop.location = rand_location()
|
417
420
|
prop.rotation_euler = rand_rotation()
|
418
421
|
for obj in WIREFRAMES:
|
419
|
-
|
420
|
-
obj.
|
421
|
-
obj.rotation_euler.z += math.radians(round(random.uniform(0, 90)))
|
422
|
+
obj.location = rand_location()
|
423
|
+
obj.rotation_euler = rand_rotation()
|
422
424
|
for display in bpy.data.groups['Displays'].objects:
|
423
425
|
display.location = rand_location()
|
424
426
|
rotate(display, index)
|
425
427
|
|
428
|
+
def animation_routine(frame):
|
429
|
+
assert len(camera_path) >= NUMBER_OF_FRAMES
|
430
|
+
CAMERA.location = camera_path[frame]
|
431
|
+
randomize_reflectors_colors()
|
432
|
+
map(move_ocean, OCEAN)
|
433
|
+
map(make_object_glossy, OCEAN)
|
434
|
+
glitch(model_object)
|
435
|
+
model_object.rotation_euler.z += math.radians(4)
|
436
|
+
for l in bpy.data.groups['Lines'].objects:
|
437
|
+
l.rotation_euler.x += math.radians(5)
|
438
|
+
l.rotation_euler.z += math.radians(5)
|
439
|
+
for prop in props:
|
440
|
+
prop.rotation_euler.x += math.radians(5)
|
441
|
+
for obj in WIREFRAMES:
|
442
|
+
obj.location.z += 0.1
|
443
|
+
obj.rotation_euler.z += math.radians(5)
|
444
|
+
for display in bpy.data.groups['Displays'].objects:
|
445
|
+
display.rotation_euler.x += math.radians(3)
|
446
|
+
|
426
447
|
def create_line(name, point_list, thickness = 0.002, location = (0, -10, 0)):
|
427
448
|
# setup basic line data
|
428
449
|
line_data = bpy.data.curves.new(name=name,type='CURVE')
|
@@ -435,8 +456,30 @@ def create_line(name, point_list, thickness = 0.002, location = (0, -10, 0)):
|
|
435
456
|
for idx in range(len(point_list)):
|
436
457
|
polyline.points[idx].co = (point_list[idx])+(1.0,)
|
437
458
|
# create an object that uses the linedata
|
438
|
-
line = bpy.data.objects.new('
|
459
|
+
line = bpy.data.objects.new('line' + str(uuid.uuid1()), line_data)
|
439
460
|
bpy.context.scene.objects.link(line)
|
440
461
|
line.location = location
|
441
462
|
make_object_emitter(line, 0.8)
|
442
463
|
return line
|
464
|
+
|
465
|
+
def add_spotlight(location, intensity, radians):
|
466
|
+
bpy.ops.object.lamp_add(type='SPOT', radius=1.0, view_align=False, location=location)
|
467
|
+
spot = last_added_object('Spot')
|
468
|
+
spot.data.node_tree.nodes['Emission'].inputs[1].default_value = intensity
|
469
|
+
spot.data.spot_size = radians
|
470
|
+
return spot
|
471
|
+
|
472
|
+
def make_world_volumetric(world, scatter_intensity = SCATTER_INTENSITY, absorption_intensity = ABSORPTION_INTENSITY):
|
473
|
+
assert world.use_nodes == True
|
474
|
+
output = world.node_tree.nodes['World Output']
|
475
|
+
bg_node = world.node_tree.nodes.new('ShaderNodeBackground')
|
476
|
+
absorption_node = world.node_tree.nodes.new('ShaderNodeVolumeAbsorption')
|
477
|
+
scatter_node = world.node_tree.nodes.new('ShaderNodeVolumeScatter')
|
478
|
+
add_shader = world.node_tree.nodes.new('ShaderNodeAddShader')
|
479
|
+
world.node_tree.links.new(add_shader.outputs[0], output.inputs['Volume'])
|
480
|
+
world.node_tree.links.new(bg_node.outputs['Background'], output.inputs['Surface'])
|
481
|
+
world.node_tree.links.new(scatter_node.outputs[0], add_shader.inputs[0])
|
482
|
+
world.node_tree.links.new(absorption_node.outputs[0], add_shader.inputs[1])
|
483
|
+
scatter_node.inputs['Density'].default_value = SCATTER_INTENSITY
|
484
|
+
absorption_node.inputs['Density'].default_value = ABSORPTION_INTENSITY
|
485
|
+
bg_node.inputs[0].default_value = rand_color()
|
@@ -0,0 +1,32 @@
|
|
1
|
+
def let_there_be_light(scene):
|
2
|
+
add_spotlight((0, 0, 12), 14000, math.radians(60))
|
3
|
+
spot1 = add_spotlight((0, 8, 4), 8000, math.radians(60))
|
4
|
+
spot2 = add_spotlight((0, -8, 4), 8000, math.radians(60))
|
5
|
+
spot1.rotation_euler.x -= math.radians(90)
|
6
|
+
spot2.rotation_euler.x += math.radians(90)
|
7
|
+
|
8
|
+
bpy.ops.mesh.primitive_plane_add(location=(0,8 + REFLECTOR_LOCATION_PADDING, 0))
|
9
|
+
bpy.ops.mesh.primitive_plane_add(location=(8 + REFLECTOR_LOCATION_PADDING,0,0))
|
10
|
+
bpy.ops.mesh.primitive_plane_add(location=(0, 0, 30))
|
11
|
+
|
12
|
+
reflector1 = bpy.data.objects['Plane']
|
13
|
+
reflector2 = bpy.data.objects['Plane.001']
|
14
|
+
reflector3 = bpy.data.objects['Plane.002']
|
15
|
+
|
16
|
+
bpy.data.groups.new('Plane')
|
17
|
+
bpy.data.groups['Plane'].objects.link(reflector1)
|
18
|
+
bpy.data.groups['Plane'].objects.link(reflector2)
|
19
|
+
bpy.data.groups['Plane'].objects.link(reflector3)
|
20
|
+
|
21
|
+
reflector2.rotation_euler.x += math.radians(90)
|
22
|
+
reflector1.rotation_euler.x += math.radians(90)
|
23
|
+
reflector2.rotation_euler.z += math.radians(90)
|
24
|
+
|
25
|
+
make_object_reflector(reflector1)
|
26
|
+
make_object_reflector(reflector2)
|
27
|
+
make_object_reflector(reflector3)
|
28
|
+
|
29
|
+
world = bpy.data.worlds.new('A Brave New World')
|
30
|
+
world.use_nodes = True
|
31
|
+
make_world_volumetric(world)
|
32
|
+
scene.world = world
|
@@ -0,0 +1,135 @@
|
|
1
|
+
# Rendering script
|
2
|
+
# Run by calling the blender executable with -b -P <script_name>
|
3
|
+
# Use `debug()` to pry into the script
|
4
|
+
|
5
|
+
import argparse
|
6
|
+
|
7
|
+
DEBUG=False
|
8
|
+
|
9
|
+
def get_args():
|
10
|
+
parser = argparse.ArgumentParser()
|
11
|
+
# get all script args
|
12
|
+
_, all_arguments = parser.parse_known_args()
|
13
|
+
double_dash_index = all_arguments.index('--')
|
14
|
+
script_args = all_arguments[double_dash_index + 1: ]
|
15
|
+
# add parser rules
|
16
|
+
parser.add_argument('-f', '--file', help="obj file to render")
|
17
|
+
parser.add_argument('-n', '--shots-number', help="number of shots desired")
|
18
|
+
parser.add_argument('-m', '--mode', help="quality mode: low | high")
|
19
|
+
parser.add_argument('-p', '--path', help="root path of assets")
|
20
|
+
parser.add_argument('-a', '--animate', help="render animation") # bool
|
21
|
+
parsed_script_args, _ = parser.parse_known_args(script_args)
|
22
|
+
return parsed_script_args
|
23
|
+
|
24
|
+
args = get_args()
|
25
|
+
file = args.file
|
26
|
+
mode = args.mode
|
27
|
+
path = str(args.path)
|
28
|
+
animate = (args.animate == 'True')
|
29
|
+
shots_number = int(args.shots_number)
|
30
|
+
|
31
|
+
import os
|
32
|
+
import bpy
|
33
|
+
import datetime
|
34
|
+
import bmesh
|
35
|
+
import random
|
36
|
+
import math
|
37
|
+
import mathutils
|
38
|
+
import random
|
39
|
+
import uuid
|
40
|
+
import sys
|
41
|
+
import logging
|
42
|
+
import string
|
43
|
+
import colorsys
|
44
|
+
import numpy
|
45
|
+
import code
|
46
|
+
|
47
|
+
# DEBUG = True
|
48
|
+
if DEBUG:
|
49
|
+
shots_number = 2
|
50
|
+
import os
|
51
|
+
mode = 'low'
|
52
|
+
animate = False
|
53
|
+
file = "/Users/pascal/dev/glitch3d/fixtures/skull.obj"
|
54
|
+
path = "/Users/pascal/dev/glitch3d/lib/"
|
55
|
+
|
56
|
+
exec(open(os.path.join(path + '/glitch3d/bpy', 'helpers.py')).read())
|
57
|
+
exec(open(os.path.join(path + '/glitch3d/bpy', 'render_settings.py')).read())
|
58
|
+
exec(open(os.path.join(path + '/glitch3d/bpy', 'lighting.py')).read())
|
59
|
+
|
60
|
+
DEBUG = False
|
61
|
+
FISHEYE = True
|
62
|
+
COLORS = rand_color_palette(5)
|
63
|
+
INITIAL_CAMERA_LOCATION = (4, 4, 1)
|
64
|
+
FIXTURES_FOLDER_PATH = path + '/../fixtures/'
|
65
|
+
TEXTURE_FOLDER_PATH = FIXTURES_FOLDER_PATH + 'textures/'
|
66
|
+
|
67
|
+
# Scene
|
68
|
+
context = bpy.context
|
69
|
+
new_scene = bpy.data.scenes.new("Automated Render Scene")
|
70
|
+
bpy.ops.scene.delete() # Delete old scene
|
71
|
+
context.screen.scene = new_scene # selects the new scene as the current one
|
72
|
+
|
73
|
+
flush_all_objects()
|
74
|
+
|
75
|
+
camera_data = bpy.data.cameras['Camera']
|
76
|
+
bpy.data.objects.new('Camera', object_data=camera_data)
|
77
|
+
CAMERA = bpy.data.objects['Camera']
|
78
|
+
new_scene.objects.link(CAMERA)
|
79
|
+
context.scene.camera = CAMERA
|
80
|
+
CAMERA.location = INITIAL_CAMERA_LOCATION
|
81
|
+
|
82
|
+
if FISHEYE:
|
83
|
+
CAMERA.data.type = 'PANO'
|
84
|
+
CAMERA.data.cycles.panorama_type = 'FISHEYE_EQUISOLID'
|
85
|
+
CAMERA.data.cycles.fisheye_lens = 12
|
86
|
+
CAMERA.data.cycles.fisheye_fov = 2.5
|
87
|
+
CAMERA.data.sensor_width = 20
|
88
|
+
CAMERA.data.sensor_height = 20
|
89
|
+
|
90
|
+
render_settings(context.scene, animate, mode)
|
91
|
+
|
92
|
+
# Initialize groups
|
93
|
+
for primitive in PRIMITIVES:
|
94
|
+
bpy.data.groups.new(primitive.lower().title())
|
95
|
+
|
96
|
+
# Load model
|
97
|
+
model_path = os.path.join(file)
|
98
|
+
bpy.ops.import_scene.obj(filepath = model_path, use_edges=True)
|
99
|
+
model_object = bpy.data.objects[1]
|
100
|
+
model_object.select = True
|
101
|
+
bpy.ops.object.origin_set(type="ORIGIN_CENTER_OF_MASS")
|
102
|
+
model_object.location = ORIGIN
|
103
|
+
make_object_glossy(model_object, YELLOW, 0.1)
|
104
|
+
voronoize(model_object)
|
105
|
+
|
106
|
+
let_there_be_light(context.scene)
|
107
|
+
|
108
|
+
exec(open(os.path.join(path + '/glitch3d/bpy/canvas', 'dreamatorium.py')).read())
|
109
|
+
|
110
|
+
print('Rendering images with resolution: ' + str(context.scene.render.resolution_x) + ' x ' + str(context.scene.render.resolution_y))
|
111
|
+
|
112
|
+
if animate:
|
113
|
+
print('ANIMATION RENDERING BEGIN')
|
114
|
+
context.scene.frame_start = 0
|
115
|
+
context.scene.frame_end = NUMBER_OF_FRAMES
|
116
|
+
bpy.ops.screen.frame_jump(end=False)
|
117
|
+
camera_path = camera_path(0.08)
|
118
|
+
|
119
|
+
for frame in range(0, NUMBER_OF_FRAMES):
|
120
|
+
bpy.context.scene.frame_set(frame)
|
121
|
+
animation_routine(frame - 1)
|
122
|
+
for ob in context.scene.objects:
|
123
|
+
ob.keyframe_insert(data_path="location", index=-1)
|
124
|
+
bpy.ops.screen.frame_jump(end=False)
|
125
|
+
shoot(model_object, output_name(index, model_path))
|
126
|
+
|
127
|
+
else:
|
128
|
+
print('STILL RENDERING BEGIN')
|
129
|
+
for index in range(0, int(shots_number)):
|
130
|
+
print("-------------------------- " + str(index) + " --------------------------")
|
131
|
+
still_routine()
|
132
|
+
shoot(model_object, output_name(index, model_path))
|
133
|
+
|
134
|
+
|
135
|
+
print('FINISHED ¯\_(ツ)_/¯')
|
@@ -0,0 +1,26 @@
|
|
1
|
+
def render_settings(scene, animate, mode):
|
2
|
+
scene.render.resolution_x = 2000
|
3
|
+
scene.render.resolution_y = 2000
|
4
|
+
scene.render.engine = 'CYCLES'
|
5
|
+
scene.render.resolution_percentage = 25
|
6
|
+
|
7
|
+
# bpy.scene.cycles.device = 'GPU'
|
8
|
+
scene.render.image_settings.compression = 0
|
9
|
+
scene.cycles.samples = 25
|
10
|
+
scene.cycles.max_bounces = 1
|
11
|
+
scene.cycles.min_bounces = 1
|
12
|
+
scene.cycles.caustics_reflective = False
|
13
|
+
scene.cycles.caustics_refractive = False
|
14
|
+
scene.render.tile_x = 32
|
15
|
+
scene.render.tile_y = 32
|
16
|
+
scene.render.image_settings.color_mode ='RGBA'
|
17
|
+
|
18
|
+
if animate:
|
19
|
+
scene.render.image_settings.file_format='H264'
|
20
|
+
else:
|
21
|
+
scene.render.image_settings.file_format='PNG'
|
22
|
+
|
23
|
+
if mode == 'high':
|
24
|
+
scene.render.image_settings.compression = 90
|
25
|
+
scene.cycles.samples = 400
|
26
|
+
scene.render.resolution_percentage = 100
|
data/lib/glitch3d/version.rb
CHANGED
data/lib/glitch3d.rb
CHANGED
@@ -15,7 +15,7 @@ module Glitch3d
|
|
15
15
|
CHUNK_SIZE=20
|
16
16
|
|
17
17
|
BLENDER_EXECUTABLE_PATH = ENV['BLENDER_EXECUTABLE_PATH'].freeze
|
18
|
-
RENDERING_SCRIPT_PATH = File.dirname(__FILE__) + '/glitch3d/bpy/
|
18
|
+
RENDERING_SCRIPT_PATH = File.dirname(__FILE__) + '/glitch3d/bpy/main.py'
|
19
19
|
|
20
20
|
def clean_model(source_file)
|
21
21
|
self.class.include Glitch3d::None
|
@@ -28,7 +28,7 @@ module Glitch3d
|
|
28
28
|
# @param String source_file, 3d model file to take as input
|
29
29
|
# @param Hash args, parameters { 'stuff' => 'shit' }
|
30
30
|
def process_model(source_file, args = nil)
|
31
|
-
source_file =
|
31
|
+
source_file = random_fixture if source_file.nil?
|
32
32
|
args = Hash[ARGV.join(' ').scan(/--?([^=\s]+)(?:=(\S+))?/)] if args.nil?
|
33
33
|
return clean_model(source_file) if args['clean']
|
34
34
|
|
@@ -37,6 +37,12 @@ module Glitch3d
|
|
37
37
|
return nil
|
38
38
|
end
|
39
39
|
|
40
|
+
if args.has_key?('animate')
|
41
|
+
args['animate'] = 'true'
|
42
|
+
else
|
43
|
+
args['animate'] = 'false'
|
44
|
+
end
|
45
|
+
|
40
46
|
raise 'Set Blender executable path in your env variables before using glitch3d' if BLENDER_EXECUTABLE_PATH.nil?
|
41
47
|
self.class.include infer_strategy(args['mode'] || 'default')
|
42
48
|
@quality = args['quality'] || 'low'
|
@@ -45,7 +51,17 @@ module Glitch3d
|
|
45
51
|
model_name = File.basename(source_file, '.obj')
|
46
52
|
target_file = base_file_name + '_glitched.obj'
|
47
53
|
create_glitched_file(glitch(read_source(source_file)), target_file, model_name)
|
48
|
-
render(target_file, args['shots-number'] || 6) unless args['no-render']
|
54
|
+
render(args, target_file, args['shots-number'] || 6) unless args['no-render']
|
55
|
+
end
|
56
|
+
|
57
|
+
def random_fixture
|
58
|
+
@fixtures_path = File.dirname(__FILE__) + '/../fixtures'
|
59
|
+
fixtures = []
|
60
|
+
Dir.foreach(@fixtures_path) do |item|
|
61
|
+
next if item == '.' or item == '..' or item.end_with?('_glitched.obj') or !item.end_with?('.obj')
|
62
|
+
fixtures << @fixtures_path + '/' + item
|
63
|
+
end
|
64
|
+
fixtures.sample
|
49
65
|
end
|
50
66
|
|
51
67
|
def infer_strategy(mode)
|
@@ -135,7 +151,8 @@ module Glitch3d
|
|
135
151
|
boundaries.flatten.map(&:abs).max.abs > BOUNDARY_LIMIT
|
136
152
|
end
|
137
153
|
|
138
|
-
def render(file_path, shots_number)
|
154
|
+
def render(initial_args, file_path, shots_number)
|
155
|
+
raise 'Animation arg not boolean' unless eval(initial_args['animate']).is_a?(FalseClass) || eval(initial_args['animate']).is_a?(TrueClass)
|
139
156
|
args = [
|
140
157
|
BLENDER_EXECUTABLE_PATH,
|
141
158
|
'-b',
|
@@ -149,7 +166,9 @@ module Glitch3d
|
|
149
166
|
'-m',
|
150
167
|
@quality,
|
151
168
|
'-p',
|
152
|
-
File.dirname(__FILE__).to_s
|
169
|
+
File.dirname(__FILE__).to_s,
|
170
|
+
'-a',
|
171
|
+
initial_args['animate'].capitalize
|
153
172
|
]
|
154
173
|
raise 'Make sure Blender is correctly installed' unless system(*args)
|
155
174
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: glitch3d
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.2.
|
4
|
+
version: 0.2.2.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- pskl
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-09
|
11
|
+
date: 2017-10-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -88,7 +88,7 @@ files:
|
|
88
88
|
- bin/setup
|
89
89
|
- fixtures/brain.obj
|
90
90
|
- fixtures/cube.obj
|
91
|
-
- fixtures/
|
91
|
+
- fixtures/dude.jpg
|
92
92
|
- fixtures/face.obj
|
93
93
|
- fixtures/m4a1.obj
|
94
94
|
- fixtures/male_head.obj
|
@@ -106,8 +106,11 @@ files:
|
|
106
106
|
- fixtures/textures/vapor.jpg
|
107
107
|
- glitch3d.gemspec
|
108
108
|
- lib/glitch3d.rb
|
109
|
+
- lib/glitch3d/bpy/canvas/dreamatorium.py
|
109
110
|
- lib/glitch3d/bpy/helpers.py
|
110
|
-
- lib/glitch3d/bpy/
|
111
|
+
- lib/glitch3d/bpy/lighting.py
|
112
|
+
- lib/glitch3d/bpy/main.py
|
113
|
+
- lib/glitch3d/bpy/render_settings.py
|
111
114
|
- lib/glitch3d/objects/face.rb
|
112
115
|
- lib/glitch3d/objects/vertex.rb
|
113
116
|
- lib/glitch3d/strategies/default.rb
|
data/fixtures/demo.png
DELETED
Binary file
|
@@ -1,236 +0,0 @@
|
|
1
|
-
# Rendering script
|
2
|
-
# Run by calling the blender executable with -b -P <script_name>
|
3
|
-
# Disclaimer: I never did Python before so this is mostly hacks
|
4
|
-
#
|
5
|
-
# process:
|
6
|
-
# 1) Load model given as a parameter
|
7
|
-
# 2) Create emitting surfaces to act as lamps
|
8
|
-
# 3) Create camera
|
9
|
-
# 4) Rotate model and shoot image at each step
|
10
|
-
#
|
11
|
-
# Use `debug()` to pry into the script
|
12
|
-
import os
|
13
|
-
exec(open(os.path.join(os.path.dirname(__file__), 'helpers.py')).read())
|
14
|
-
|
15
|
-
# Arguments parsing
|
16
|
-
args = get_args()
|
17
|
-
file = args.file
|
18
|
-
mode = args.mode
|
19
|
-
path = str(args.path)
|
20
|
-
shots_number = int(args.shots_number)
|
21
|
-
|
22
|
-
FIXTURES_FOLDER_PATH = path + '/../fixtures/'
|
23
|
-
|
24
|
-
DEBUG = False
|
25
|
-
FISHEYE = True
|
26
|
-
COLORS = rand_color_palette(5)
|
27
|
-
INITIAL_CAMERA_LOCATION = (4, 4, 1)
|
28
|
-
ANIMATE = False
|
29
|
-
|
30
|
-
# DEBUG = True
|
31
|
-
if DEBUG:
|
32
|
-
shots_number = 2
|
33
|
-
import os
|
34
|
-
mode = 'low'
|
35
|
-
file = "/Users/pascal/dev/glitch3d/fixtures/skull.obj"
|
36
|
-
FIXTURES_FOLDER_PATH = "/Users/pascal/dev/glitch3d/fixtures/"
|
37
|
-
|
38
|
-
TEXTURE_FOLDER_PATH = FIXTURES_FOLDER_PATH + 'textures/'
|
39
|
-
|
40
|
-
# Scene
|
41
|
-
new_scene = bpy.data.scenes.new("Automated Render Scene")
|
42
|
-
bpy.ops.scene.delete() # Delete old scene
|
43
|
-
context.screen.scene = new_scene # selects the new scene as the current one
|
44
|
-
|
45
|
-
# Initialize groups
|
46
|
-
for primitive in PRIMITIVES:
|
47
|
-
bpy.data.groups.new(primitive.lower().title())
|
48
|
-
|
49
|
-
# Render settings
|
50
|
-
context.scene.render.resolution_x = 2000
|
51
|
-
context.scene.render.resolution_y = 2000
|
52
|
-
context.scene.render.engine = 'CYCLES'
|
53
|
-
context.scene.render.resolution_percentage = 25
|
54
|
-
# uncomment if GPU
|
55
|
-
# bpy.context.scene.cycles.device = 'GPU'
|
56
|
-
context.scene.render.image_settings.compression = 0
|
57
|
-
context.scene.cycles.samples = 25
|
58
|
-
context.scene.render.image_settings.color_mode ='RGBA'
|
59
|
-
context.scene.render.image_settings.file_format='PNG'
|
60
|
-
|
61
|
-
if mode == 'high':
|
62
|
-
context.scene.render.image_settings.compression = 90
|
63
|
-
context.scene.cycles.samples = 400
|
64
|
-
context.scene.render.resolution_percentage = 100
|
65
|
-
|
66
|
-
# Add background to world
|
67
|
-
|
68
|
-
# This shit doesnt work in v 2.76
|
69
|
-
# bpy.data.worlds.remove(bpy.data.worlds[0])
|
70
|
-
world = bpy.data.worlds.new('A Brave New World')
|
71
|
-
world.use_nodes = True
|
72
|
-
world_node_tree = world.node_tree
|
73
|
-
context.scene.world = world
|
74
|
-
|
75
|
-
# Clean slate
|
76
|
-
flush_all_objects()
|
77
|
-
|
78
|
-
# Load model
|
79
|
-
model_path = os.path.join(file)
|
80
|
-
|
81
|
-
bpy.ops.import_scene.obj(filepath = model_path, use_edges=True)
|
82
|
-
model_object = bpy.data.objects[0]
|
83
|
-
|
84
|
-
# Load props
|
85
|
-
bpy.ops.import_scene.obj(filepath = os.path.join(FIXTURES_FOLDER_PATH + 'm4a1.obj'), use_edges=True)
|
86
|
-
m4a1 = bpy.data.objects['m4a1']
|
87
|
-
m4a1.location = rand_location()
|
88
|
-
m4a1.scale = (0.5, 0.5, 0.5)
|
89
|
-
props.append(m4a1)
|
90
|
-
|
91
|
-
# Use center of mass to center object
|
92
|
-
model_object.select = True
|
93
|
-
bpy.ops.object.origin_set(type="ORIGIN_CENTER_OF_MASS")
|
94
|
-
model_object.location = ORIGIN
|
95
|
-
make_object_glossy(model_object, YELLOW)
|
96
|
-
|
97
|
-
# Add props
|
98
|
-
rand_primitive = random.choice(PRIMITIVES)
|
99
|
-
build_composite_object(rand_primitive, 4, 1)
|
100
|
-
|
101
|
-
# --------------
|
102
|
-
# Create camera
|
103
|
-
# --------------
|
104
|
-
camera_data = bpy.data.cameras.new('Camera')
|
105
|
-
bpy.data.objects.new('Camera', object_data=camera_data)
|
106
|
-
camera_object = bpy.data.objects['Camera']
|
107
|
-
new_scene.objects.link(camera_object)
|
108
|
-
camera_object.location = INITIAL_CAMERA_LOCATION
|
109
|
-
|
110
|
-
if FISHEYE:
|
111
|
-
camera_object.data.type = 'PANO'
|
112
|
-
camera_object.data.cycles.panorama_type = 'FISHEYE_EQUISOLID'
|
113
|
-
camera_object.data.cycles.fisheye_lens = 12
|
114
|
-
camera_object.data.cycles.fisheye_fov = 2.5
|
115
|
-
camera_object.data.sensor_width = 20
|
116
|
-
camera_object.data.sensor_height = 20
|
117
|
-
|
118
|
-
# Add reflectors
|
119
|
-
bpy.ops.mesh.primitive_plane_add(location=(0,8 + REFLECTOR_LOCATION_PADDING, 0))
|
120
|
-
bpy.ops.mesh.primitive_plane_add(location=(8 + REFLECTOR_LOCATION_PADDING,0,0))
|
121
|
-
bpy.ops.mesh.primitive_plane_add(location=(0, 0, 20))
|
122
|
-
bpy.ops.mesh.primitive_plane_add(location=(0, 0, -2))
|
123
|
-
|
124
|
-
reflector1 = bpy.data.objects['Plane']
|
125
|
-
reflector2 = bpy.data.objects['Plane.001']
|
126
|
-
reflector3 = bpy.data.objects['Plane.002']
|
127
|
-
|
128
|
-
bpy.data.groups.new('Plane')
|
129
|
-
bpy.data.groups['Plane'].objects.link(reflector1)
|
130
|
-
bpy.data.groups['Plane'].objects.link(reflector2)
|
131
|
-
bpy.data.groups['Plane'].objects.link(reflector3)
|
132
|
-
|
133
|
-
reflector2.rotation_euler.x += math.radians(90)
|
134
|
-
reflector1.rotation_euler.x += math.radians(90)
|
135
|
-
reflector2.rotation_euler.z += math.radians(90)
|
136
|
-
|
137
|
-
make_object_reflector(reflector1)
|
138
|
-
make_object_reflector(reflector2)
|
139
|
-
make_object_reflector(reflector3)
|
140
|
-
|
141
|
-
# Set up virtual displays
|
142
|
-
bpy.ops.mesh.primitive_grid_add(x_subdivisions=100, y_subdivisions=100, location=(0, 6, 2))
|
143
|
-
display1 = bpy.data.objects['Grid']
|
144
|
-
bpy.ops.mesh.primitive_grid_add(x_subdivisions=100, y_subdivisions=100, location=(6, 0, 2))
|
145
|
-
display2 = bpy.data.objects['Grid.001']
|
146
|
-
|
147
|
-
bpy.data.groups.new('Displays')
|
148
|
-
bpy.data.groups['Displays'].objects.link(display1)
|
149
|
-
bpy.data.groups['Displays'].objects.link(display2)
|
150
|
-
|
151
|
-
display1.rotation_euler.x += math.radians(90)
|
152
|
-
display1.rotation_euler.z -= math.radians(90)
|
153
|
-
display2.rotation_euler.x += math.radians(90)
|
154
|
-
display2.rotation_euler.y += math.radians(90)
|
155
|
-
display2.rotation_euler.z += math.radians(120)
|
156
|
-
|
157
|
-
for display in bpy.data.groups['Displays'].objects:
|
158
|
-
display.rotation_euler.x += math.radians(90)
|
159
|
-
display.scale = (3,3,3)
|
160
|
-
texture_object(display)
|
161
|
-
unwrap_model(display)
|
162
|
-
glitch(display)
|
163
|
-
|
164
|
-
glitch(m4a1)
|
165
|
-
make_object_gradient_fabulous(m4a1, rand_color(), rand_color())
|
166
|
-
|
167
|
-
# Adjust camera
|
168
|
-
context.scene.camera = camera_object
|
169
|
-
look_at(camera_object, model_object)
|
170
|
-
|
171
|
-
# Make floor
|
172
|
-
floor = bpy.data.objects['Plane.003']
|
173
|
-
bpy.data.groups['Plane'].objects.link(floor)
|
174
|
-
floor.scale = (20,20,20)
|
175
|
-
subdivide(floor, 8)
|
176
|
-
displace(floor)
|
177
|
-
texture_object(floor)
|
178
|
-
|
179
|
-
OCEAN = add_ocean(10, 20)
|
180
|
-
|
181
|
-
# Create lines
|
182
|
-
bpy.data.groups.new('Lines')
|
183
|
-
for i in range(0, 20):
|
184
|
-
new_line = create_line('line' + str(uuid.uuid1()), series(30))
|
185
|
-
new_line.location.z += i / 6
|
186
|
-
|
187
|
-
for index in range(1, len(WORDS)):
|
188
|
-
new_object = spawn_text()
|
189
|
-
props.append(new_object)
|
190
|
-
text_scale = random.uniform(0.75, 2)
|
191
|
-
make_object_glossy(new_object, GREY)
|
192
|
-
new_object.scale = (text_scale, text_scale, text_scale)
|
193
|
-
new_object.location = rand_location()
|
194
|
-
# pivot text to make it readable by camera
|
195
|
-
new_object.rotation_euler.x += math.radians(90)
|
196
|
-
new_object.rotation_euler.z += math.radians(90)
|
197
|
-
|
198
|
-
for plane in bpy.data.groups['Plane'].objects:
|
199
|
-
unwrap_model(plane)
|
200
|
-
|
201
|
-
for obj in WIREFRAMES:
|
202
|
-
wireframize(obj)
|
203
|
-
|
204
|
-
look_at(camera_object, model_object)
|
205
|
-
model_object.location.z += 2
|
206
|
-
|
207
|
-
# ------
|
208
|
-
# Shoot
|
209
|
-
# ------
|
210
|
-
print('Rendering images with resolution: ' + str(context.scene.render.resolution_x) + ' x ' + str(context.scene.render.resolution_y))
|
211
|
-
|
212
|
-
if ANIMATE:
|
213
|
-
print('ANIMATION RENDERING BEGIN')
|
214
|
-
context.scene.frame_start = 0
|
215
|
-
context.scene.frame_end = NUMBER_OF_FRAMES
|
216
|
-
bpy.ops.screen.frame_jump(end=False)
|
217
|
-
|
218
|
-
for frame in range(1, NUMBER_OF_FRAMES):
|
219
|
-
bpy.context.scene.frame_set(frame)
|
220
|
-
|
221
|
-
dance_routine()
|
222
|
-
|
223
|
-
for ob in context.scene.objects:
|
224
|
-
ob.keyframe_insert(data_path="location", index=-1)
|
225
|
-
|
226
|
-
bpy.ops.screen.frame_jump(end=False)
|
227
|
-
shoot(True, camera_object, model_object, output_name(index, model_path))
|
228
|
-
else:
|
229
|
-
print('STILL RENDERING BEGIN')
|
230
|
-
for index in range(0, int(shots_number)):
|
231
|
-
print("-------------------------- " + str(index) + " --------------------------")
|
232
|
-
shoot(False, camera_object, model_object, output_name(index, model_path))
|
233
|
-
dance_routine()
|
234
|
-
|
235
|
-
|
236
|
-
print('FINISHED ¯\_(ツ)_/¯')
|