scene_functions.py 14.6 KB
Newer Older
1
2
3
# Import Blender functions
filename = os.path.join(os.path.basename(bpy.data.filepath), "blender_functions.py")
exec(compile(open(filename).read(), filename, 'exec'))
Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
4

5
def init(unique_id,camera_type,transp_par,detectors):
Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
6
7
8
    bcs = bpy.context.scene

    # Configure Environment
9
    bcs.world.light_settings.use_environment_light = False
Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
10
11
12
    bcs.world.light_settings.environment_energy = 0.1

    # Configure Stamp
Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
13
14
15
16
17
18
19
20
21
22
23
    bcsr = bpy.context.scene.render
    bcsr.use_stamp = True
    bcsr.use_stamp_time = False
    bcsr.use_stamp_date = False
    bcsr.use_stamp_render_time = False
    bcsr.use_stamp_frame = False
    bcsr.use_stamp_scene = False
    bcsr.use_stamp_camera = False
    bcsr.use_stamp_filename = False
    bcsr.stamp_note_text = unique_id
    bcsr.use_stamp_note = True
Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
24
25
26
27

    # Cleanup
    bpy.data.objects.remove(bpy.data.objects['Cube'])
    bpy.data.objects.remove(bpy.data.objects['Camera'])
28
    bpy.data.objects.remove(bpy.data.objects['Lamp'])
Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
29
30
31

    # Basic Objects
    addCameras() # Add cameras
32
33
34
35
36

    if camera_type == "OverviewCamera":
        addOverviewLamps()
    else:
        addLamps() # Add Lamps
Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
37

38
    if camera_type == "ForwardCamera":
39
        addALICE_Geometry(True,transp_par,detectors) # ALICE TPC, EMCal, ITS, TRD
40
    else:
41
        addALICE_Geometry(False,transp_par,detectors)
Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
42

43
def addALICE_Geometry(bright_colors=True, transp_par=1.0, detectors=[1,1,1,1]):
Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
44

45
46
47
48
    if bright_colors: # Defining sequence of RGB values to fill 'createMaterial' functions below
        rgb_v = [13,13,25,10] # Colors for "ForwardCamera"
    else:
        rgb_v = [0.5,0.9,1,0.2] # Colors for "OverviewCamera" and "BarrelCamera"
Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
49

Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
50

51
52
    # ADD ITS
    if detectors[0]:
Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
53

54
        # ADD ITS INNER BARREL
Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
55

56
        # Material
57
        createMaterial("innerITS",R=rgb_v[2],G=0,B=rgb_v[2],shadows=False,cast_shadows=False,transparency=True,alpha=transp_par*0.7,emit=0,specular_alpha=0,fresnel_factor=5,fresnel=0.3)
Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
58

59
60
61
62
        # Add Inner ITS
        bpy.ops.mesh.primitive_cylinder_add(radius=0.0421, depth=0.271, view_align=False, enter_editmode=False, location=(0, 0, 0))
        inner_TPC = bpy.context.object
        inner_TPC.name = "innerITS"
Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
63

64
65
66
        # Set Material
        inner_TPC.data.materials.clear()
        inner_TPC.data.materials.append(bpy.data.materials["innerITS"])
67
68


69
        # ADD ITS OUTER BARREL
70

71
        # Material
72
        createMaterial("outerITS",R=rgb_v[3],G=0,B=rgb_v[3],shadows=False,cast_shadows=False,transparency=True,alpha=transp_par*0.4,emit=0.8,specular_alpha=0,fresnel_factor=5,fresnel=0.3)
73

74
        # ADD ITS MIDDLE LAYERS
75

76
77
78
79
        # Add "hole" to subtract from the middle
        bpy.ops.mesh.primitive_cylinder_add(radius=0.1944, depth=0.9, view_align=False, enter_editmode=False, location=(0, 0, 0)) #smaller cylinder
        middle_ITS_hole = bpy.context.object
        middle_ITS_hole.name = "Hole"
80

81
82
83
84
        # Add actual middle layer ITS part
        bpy.ops.mesh.primitive_cylinder_add(radius=0.247, depth=0.843, view_align=False, enter_editmode=False, location=(0, 0, 0)) #bigger cylinder
        middle_ITS = bpy.context.object
        middle_ITS.name = "middleITS"
85

86
87
        # Subtract hole from main TPC part
        subtract(middle_ITS_hole,middle_ITS)
88

89
90
91
        # Set material
        middle_ITS.data.materials.clear()
        middle_ITS.data.materials.append(bpy.data.materials["outerITS"])
92
93


94
        # ADD ITS OUTER LAYERS
95

96
97
98
99
        # Add "hole" to subtract from the middle
        bpy.ops.mesh.primitive_cylinder_add(radius=0.3423, depth=1.5, view_align=False, enter_editmode=False, location=(0, 0, 0)) #smaller cylinder
        outer_ITS_hole = bpy.context.object
        outer_ITS_hole.name = "Hole"
100

101
102
103
104
        # Add actual outer layer ITS part
        bpy.ops.mesh.primitive_cylinder_add(radius=0.3949, depth=1.475, view_align=False, enter_editmode=False, location=(0, 0, 0)) #bigger cylinder
        outer_ITS = bpy.context.object
        outer_ITS.name = "outerITS"
105

106
107
        # Subtract hole from main TPC part
        subtract(outer_ITS_hole,outer_ITS)
108

109
110
111
        # Set material
        outer_ITS.data.materials.clear()
        outer_ITS.data.materials.append(bpy.data.materials["outerITS"])
112

113
114
115
116
        # Make ITS middle and outer layers a single object
        joinObjects([middle_ITS,outer_ITS])
        Outer_ITS = bpy.context.object
        Outer_ITS.name = "OuterITS"
117

118
119
    # ADD TPC
    if detectors[1]:
120

121
        # Material
122
        createMaterial("tpc",R=0,G=rgb_v[0],B=0,shadows=False,cast_shadows=False,transparency=True,alpha=transp_par*0.2,emit=0.3,specular_alpha=0,fresnel_factor=5,fresnel=0.3)
123

124
125
126
127
        # Add TPC
        bpy.ops.mesh.primitive_cylinder_add(radius=2.461, depth=5.1, view_align=False, enter_editmode=False, location=(0, 0, 0)) #bigger cylinder
        TPC = bpy.context.object
        TPC.name = "TPC"
128

129
130
131
        # Set material
        TPC.data.materials.clear()
        TPC.data.materials.append(bpy.data.materials["tpc"])
132

133
    # ADD ALICE TRD
134
    if detectors[2]:
135

136
        # Material
137
        createMaterial("TRD",R=rgb_v[3],G=0,B=rgb_v[3],shadows=False,cast_shadows=False,transparency=True,alpha=transp_par*0.15,emit=0.8,specular_alpha=0,fresnel_factor=5,fresnel=0.3)
138

139
140
141
142
        # Add "hole" to subtract from the middle
        bpy.ops.mesh.primitive_cylinder_add(radius=2.9, depth=6, vertices=18, view_align=False, enter_editmode=False, location=(0, 0, 0)) #smaller cylinder
        TRD_hole = bpy.context.object
        TRD_hole.name = "Hole"
143

144
145
146
147
        # Add actual TRD part
        bpy.ops.mesh.primitive_cylinder_add(radius=3.7, depth=5.1, vertices=18, view_align=False, enter_editmode=False, location=(0, 0, 0)) #bigger cylinder
        TRD = bpy.context.object
        TRD.name = "TRD"
148

149
150
        # Subtract hole from main TRD part
        subtract(TRD_hole,TRD)
151

152
153
154
        # Set material
        TRD.data.materials.clear()
        TRD.data.materials.append(bpy.data.materials["TRD"])
155

156
157
158
159
160
161
162
        # Add 'slices' to subtract from TRD structure
        bpy.ops.mesh.primitive_cube_add(radius=1, location=(2.855942,0.50358,0))
        slice = bpy.context.object
        slice.name = "slice"
        bpy.ops.transform.resize(value=(1,0.03,4))
        bpy.context.object.rotation_euler[2] = 0.174533
        subtract(slice,TRD)
163

164
165
        def rad(theta): # Convert degrees to radians
            return theta * math.pi / 180
166

167
168
        xn = 2.9 * math.cos(rad(10))
        yn = 2.9 * math.sin(rad(10))
169

170
        for n in range(1,18):
171

172
173
            dx = -2 * 2.9 * math.sin(rad(10)) * math.sin(rad(n * 20))
            xn += dx
174

175
176
            dy = 2 * 2.9 * math.sin(rad(10)) * math.cos(rad(n * 20))
            yn += dy
177

178
            rotat = rad(10 + n*20)
179

180
181
182
183
184
            bpy.ops.mesh.primitive_cube_add(radius=1, location=(xn,yn,0))
            slice = bpy.context.object
            slice.name = "slice"
            bpy.ops.transform.resize(value=(1,0.03,4))
            bpy.context.object.rotation_euler[2] = rotat
185

186
187
188
189
190
191
            subtract(slice,TRD)

    # ADD EMCal
    if detectors[3]:

        # Material
192
        createMaterial("emcal",R=rgb_v[1],G=rgb_v[1],B=0,shadows=False,cast_shadows=False,transparency=True,alpha=transp_par*0.05,emit=1.5,specular_alpha=0,fresnel_factor=5,fresnel=0.3)
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226

        # Add cylinder for EMCal
        bpy.ops.mesh.primitive_cylinder_add(radius=4.7, depth=5.1, vertices=19, view_align=False, enter_editmode=False, location=(0, 0, 0))
        EMCal = bpy.context.object
        EMCal.name = "EMCal"

        # Add cylinder to be removed from center
        bpy.ops.mesh.primitive_cylinder_add(radius=4.35, depth=5.2, vertices=19, view_align=False, enter_editmode=False, location=(0, 0, 0))
        emcal_hole = bpy.context.object
        emcal_hole.name = "Hole"

        subtract(emcal_hole,EMCal);

        # Adds rotated cube to be removed from EMCal so that there's a 7.3° angle with top y axis, clockwise
        bpy.ops.mesh.primitive_cube_add(location=(2.85,2.2,0), rotation=(0,0,-0.1274), radius=2.55)
        bpy.ops.transform.resize(value=(1.5,1.5,1.5), constraint_axis=(False,False,True))
        cube1 = bpy.context.object # first quadrant
        subtract(cube1,EMCal)

        # Adds rotated cube to be removed from EMCal so that there's a 9.7° angle with left x axis, anticlockwise
        bpy.ops.mesh.primitive_cube_add(location=(-2.08,-2.95,0), rotation=(0,0,0.1693), radius=2.55)
        bpy.ops.transform.resize(value=(1.5,1.5,1.5), constraint_axis=(False,False,True))
        cube3 = bpy.context.object # third quadrant
        subtract(cube3,EMCal)

        #Adds cube with right angle in fourth quadrant to be removed from EMCal
        bpy.ops.mesh.primitive_cube_add(location=(2.55,-2.55,0), radius=2.55)
        bpy.ops.transform.resize(value=(1.5,1.5,1.5), constraint_axis=(False,False,True))
        cube4 = bpy.context.object # fourth quadrant
        subtract(cube4,EMCal)

        # Set Material
        EMCal.data.materials.clear()
        EMCal.data.materials.append(bpy.data.materials["emcal"])
227

228

229
def addLamps():
230
231
    bpy.ops.object.lamp_add(type='POINT', location=(4,1,6))
    bpy.ops.object.lamp_add(type='POINT', location=(-4,-1,-6))
232

233
234
def addOverviewLamps():
    bpy.ops.object.lamp_add(type='POINT', location=(0,0,6))
235

Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
236
237
def addCameras():
    # ForwardCamera
238
    bpy.ops.object.camera_add(location = (0,0.5,20), rotation = (0, 0, 0))
Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
239
240
241
    bpy.context.object.name = "ForwardCamera"
    camera_forward=bpy.data.objects['ForwardCamera']
    camera_forward.data.type = 'ORTHO'
242
    camera_forward.data.ortho_scale = 18
Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
243
244

    # OverviewCamera
245
    bpy.ops.object.camera_add(location = (23.27182, 10.3968, 22.754), rotation = (-0.071558, 0.879645, 0.305433))
Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
    bpy.context.object.name = "OverviewCamera"
    bpy.context.object.data.lens = 66.78

    # Barrel Camera
    bpy.ops.object.camera_add(location = (6, 0, 0), rotation = (0, 1.5708, 0))
    bpy.context.object.name = "BarrelCamera"

# Function that creates Blender Objects from input list of particles.
## Returns a list of blender objects
def createSceneParticles(particles, createTracks = False):
    # Associate particles and colors
    particle_types = ["Electron","Pion","Muon","Proton","Kaon","Unknown"]
    clRed = (1, 0, 0)
    clGreen = (0, 1, 0)
    clBlue = (0, 0, 1)
    clMagenta = (0.75, 0, 1)
    clYellow = (1, 1, 0)
    clWhite = (255, 255, 255)
    particle_colors = {"Electron":clRed, "Pion":clGreen, "Muon":clBlue, "Proton":clMagenta, "Kaon": clYellow, "Unknown": clWhite}

266
    # Create Materials
Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
267
268
269
    for type in particle_types:
        bpy.data.materials.new(name=type)
        #bpy.context.object.active_material = (1, 0, 0)
270
        bpy.data.materials[type].emit = 0.05
Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
271
272
273
274
275
276
277
278
279
        bpy.data.materials[type].diffuse_color = particle_colors[type]
        bpy.data.materials[type].use_shadows = False
        bpy.data.materials[type].use_cast_shadows = False

    # Create blender spheres (particles)
    blender_particles=[]
    n_particles=len(particles)
    for particle in particles:
        this_type=particle.p_type
280
        print("Adding Sphere - Particle " + str(len(blender_particles)+1)+" of "+str(n_particles)+" - "+this_type)
Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
281
        bpy.ops.mesh.primitive_uv_sphere_add()
282
        bpy.ops.object.shade_smooth()
Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
283
284
285
286
287
288
289
290
291
292
293
294
        this_particle = bpy.context.object
        this_particle.name = "part"+str(particle.iDx)
        this_particle.location = ((particle.x,particle.y,particle.z))
        this_particle.delta_scale = (r_part,r_part,r_part)
        this_particle.data.materials.clear()
        this_particle.data.materials.append(bpy.data.materials[this_type])
        blender_particles.append(this_particle)

    # Create blender curves (tracks)
    blender_tracks=[]
    if createTracks:
            for track in particles:
295
296
                this_type=track.p_type
                print("Adding Curve - Track " + str(len(blender_tracks)+1)+" of "+str(n_particles)+" - "+this_type)
Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330

                # create the Curve Datablock
                curveTrack = bpy.data.curves.new('CurveTrack', type='CURVE')
                curveTrack.dimensions = '3D'
                curveTrack.resolution_u = 2

                curveTrack.fill_mode = 'FULL'
                curveTrack.bevel_depth = 0.02
                curveTrack.bevel_resolution = 3


                # map coords to spline
                bcs = bpy.context.scene
                polyline = curveTrack.splines.new('NURBS')
                polyline.points.add(bcs.frame_end) # Add one point per frame
                for i in range(bcs.frame_end):
                    polyline.points[i].co = (particle.x,particle.y,particle.z, 1)

                # create Object
                trackOB = bpy.data.objects.new('Track', curveTrack)
                trackOB.data.materials.clear()
                trackOB.data.materials.append(bpy.data.materials[this_type])
                scn = bpy.context.scene
                scn.objects.link(trackOB)
                blender_tracks.append(trackOB)


    return blender_particles, blender_tracks

# Function that animates the scene using the particle propagator class
def animate(objects, particles, driver):
    bcs = bpy.context.scene

    #Animate particles
331
    for f in range(1, bcs.frame_end+1):
Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
332
333
334
335
336
337
338
339
340
341
342
343
344
        t = driver.delta_t*f
        bcs.frame_current = f
        print("Configuring particles in frame: "+str(f)+" of "+str(bcs.frame_end))
        for i in range(0, len(objects)):
            bcs.objects.active=objects[i]
            objects[i].location=(particles[i].Propagate(t))
            objects[i].keyframe_insert(data_path='location')

# Function that animates particle tracks using the particle propagator class
def animate_tracks(tracks, particles, driver):
    bcs = bpy.context.scene

    #Animate tracks
345
    for f in range(1, bcs.frame_end+1):
Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
346
347
348
        t = driver.delta_t*f
        bcs.frame_current = f
        print("Configuring tracks in frame: "+ str(f) +" of "+ str(bcs.frame_end))
349
        for point in range(f,bcs.frame_end+1):
Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
            for i in range(0, len(particles)):
                #bcs.objects.active=tracks[i]
                tracks[i].data.splines[0].points[point].keyframe_insert(data_path="co", frame = f)
                x, y, z = particles[i].Propagate(t)
                tracks[i].data.splines[0].points[point].co = (x, y, z, 1)



                ##polyline = curveTrack.splines.new('NURBS')
                ##polyline.points.add(len(coords))
                ##for i, coord in enumerate(coords):
                ##    x,y,z = coord
                ##    polyline.points[i].co = (x, y, z, 1)

                #curve = bpy.data.objects["Track"]
                #curve.data.splines[0].points[1].co


                #point.keyframe_insert(data_path="co", frame = i)
                # https://blender.stackexchange.com/questions/73630/animate-curves-by-changing-spline-data-using-a-python-script
370
371
372
373
374
375
376
377

def take_picture(pic_pct,driver):
    bcs = bpy.context.scene

    bcs.frame_current = int(bcs.frame_end * pic_pct/100)
    bcs.camera = bpy.data.objects[driver.renderCamera]
    bpy.ops.render.render()
    bpy.data.images['Render Result'].save_render(filepath=bcs.render.filepath+".png")