-
Notifications
You must be signed in to change notification settings - Fork 4
/
lightfield_cylinder.py
128 lines (102 loc) · 4.16 KB
/
lightfield_cylinder.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
import random
import math
import bpy
import bmesh
from .camera_position import CameraPosition
from mathutils import Color
from .lightfield import LightfieldPropertyGroup
class LightfieldCylinder(LightfieldPropertyGroup):
def construct(self):
visuals = self.default_construct()
self.lf_type = 'CYLINDER'
self.obj_empty.empty_display_type = 'CIRCLE'
# Update lightfield references
self.obj_visuals.add().obj_visual = visuals[0]
self.obj_visuals.add().obj_visual = visuals[1]
self.obj_visuals.add().obj_visual = visuals[2]
self.obj_visuals.add().obj_visual = visuals[3]
self.obj_grid = visuals[1]
self.set_camera_to_first_view()
def construct_visuals(self, collection):
grid = self.create_grid()
space, edges = self.create_space()
front = self.create_front()
# Add to lightfield collection
collection.objects.link(grid)
collection.objects.link(space)
collection.objects.link(front)
collection.objects.link(edges)
return [space, grid, front, edges]
def create_space(self):
"""
Create visual that represents the space the lightfield is occupying.
:return: Object.
"""
# Used to clean up after making a mess with meshes.
dumped_meshes = []
# Top and bottom circle colored
bpy.ops.mesh.primitive_circle_add(location=(0.0, 0.0, 1.0), fill_type='NGON')
c2 = bpy.context.object
bpy.ops.mesh.primitive_circle_add(location=(0.0, 0.0, -1.0), fill_type='NGON')
c1 = bpy.context.object
dumped_meshes.append(c2.data)
dumped_meshes.append(c1.data)
# Cylinder
name = self.construct_names()['space']
bpy.ops.mesh.primitive_cylinder_add(location=(0.0, 0.0, 0.0), end_fill_type='NGON')
bpy.ops.object.shade_smooth()
space = bpy.context.object
space.name = name
c1.select_set(True)
c2.select_set(True)
bpy.ops.object.join()
space.scale = [0.5] * 3
space.data.name = name
# Unlink the object from its current collection
space.users_collection[0].objects.unlink(space)
space_mat = bpy.data.materials.new(name)
col = Color()
col.hsv = (random.random(), 1.0, 0.8)
space_mat.diffuse_color = col[:] + (0.1,)
space.data.materials.append(space_mat)
space.hide_render = True
# Top and bottom circle
bpy.ops.mesh.primitive_circle_add(location=(0.0, 0.0, 1.0))
c2 = bpy.context.object
bpy.ops.mesh.primitive_circle_add(location=(0.0, 0.0, -1.0))
c1 = bpy.context.object
c1.name = self.construct_names()['edges']
c1.data.name = c1.name
c2.select_set(True)
dumped_meshes.append(c2.data)
bpy.ops.object.join()
bpy.ops.object.origin_set(type='ORIGIN_GEOMETRY')
c1.scale = [0.5] * 3
c1.users_collection[0].objects.unlink(c1)
# Delete all unused mesh data.
for mesh in dumped_meshes:
bpy.data.meshes.remove(mesh)
return space, c1
@staticmethod
def construct_names():
base = "LFCylinder"
return {'lightfield': base,
'camera': "{}_Camera".format(base),
'grid': "{}_Grid".format(base),
'space': "{}_Space".format(base),
'front': "{}_Front".format(base),
'edges': "{}_Edges".format(base)}
def position_generator(self):
# TODO: implement cube-map render
for y in range(self.num_cams_y):
for r in range(self.num_cams_radius):
yield self.get_camera_pos(y, r)
def get_camera_pos(self, y, r):
base_y = 1 / (self.num_cams_y - 1)
angle = r * 2 * math.pi / self.num_cams_radius
return CameraPosition("view_{:04d}f".format(y * self.num_cams_radius + r),
0.5 * math.sin(angle),
0.5 * math.cos(angle),
0.5 - y * base_y,
alpha=0.5*math.pi,
phi=-angle + (math.pi if self.face_inside else 0))