scene_functions.py 15.1 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

    if camera_type == "OverviewCamera":
        addOverviewLamps()
    else:
Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
36
37
38
39
        if camera_type == "AntiOverviewCamera":
            addAntiOverviewLamps()
        else:
            addLamps() # Add Lamps
Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
40

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

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

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

Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
53

54
55
    # ADD ITS
    if detectors[0]:
Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
56

57
        # ADD ITS INNER BARREL
Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
58

59
        # Material
60
        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
61

62
63
64
65
        # 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
66

67
68
69
        # Set Material
        inner_TPC.data.materials.clear()
        inner_TPC.data.materials.append(bpy.data.materials["innerITS"])
70
71


72
        # ADD ITS OUTER BARREL
73

74
        # Material
75
        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)
76

77
        # ADD ITS MIDDLE LAYERS
78

79
80
81
82
        # 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"
83

84
85
86
87
        # 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"
88

89
90
        # Subtract hole from main TPC part
        subtract(middle_ITS_hole,middle_ITS)
91

92
93
94
        # Set material
        middle_ITS.data.materials.clear()
        middle_ITS.data.materials.append(bpy.data.materials["outerITS"])
95
96


97
        # ADD ITS OUTER LAYERS
98

99
100
101
102
        # 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"
103

104
105
106
107
        # 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"
108

109
110
        # Subtract hole from main TPC part
        subtract(outer_ITS_hole,outer_ITS)
111

112
113
114
        # Set material
        outer_ITS.data.materials.clear()
        outer_ITS.data.materials.append(bpy.data.materials["outerITS"])
115

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

121
122
    # ADD TPC
    if detectors[1]:
123

124
        # Material
125
        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)
126

127
128
129
130
        # 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"
131

132
133
134
        # Set material
        TPC.data.materials.clear()
        TPC.data.materials.append(bpy.data.materials["tpc"])
135

136
    # ADD ALICE TRD
137
    if detectors[2]:
138

139
        # Material
140
        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)
141

142
143
144
145
        # 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"
146

147
148
149
150
        # 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"
151

152
153
        # Subtract hole from main TRD part
        subtract(TRD_hole,TRD)
154

155
156
157
        # Set material
        TRD.data.materials.clear()
        TRD.data.materials.append(bpy.data.materials["TRD"])
158

159
160
161
162
163
164
165
        # 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)
166

167
168
        def rad(theta): # Convert degrees to radians
            return theta * math.pi / 180
169

170
171
        xn = 2.9 * math.cos(rad(10))
        yn = 2.9 * math.sin(rad(10))
172

173
        for n in range(1,18):
174

175
176
            dx = -2 * 2.9 * math.sin(rad(10)) * math.sin(rad(n * 20))
            xn += dx
177

178
179
            dy = 2 * 2.9 * math.sin(rad(10)) * math.cos(rad(n * 20))
            yn += dy
180

181
            rotat = rad(10 + n*20)
182

183
184
185
186
187
            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
188

189
190
191
192
193
194
            subtract(slice,TRD)

    # ADD EMCal
    if detectors[3]:

        # Material
195
        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)
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
227
228
229

        # 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"])
230

231

232
def addLamps():
233
234
    bpy.ops.object.lamp_add(type='POINT', location=(4,1,6))
    bpy.ops.object.lamp_add(type='POINT', location=(-4,-1,-6))
235

236
237
def addOverviewLamps():
    bpy.ops.object.lamp_add(type='POINT', location=(0,0,6))
238

Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
239
240
241
def addAntiOverviewLamps():
    bpy.ops.object.lamp_add(type='POINT', location=(0,0,-6))

Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
242
243
def addCameras():
    # ForwardCamera
244
    bpy.ops.object.camera_add(location = (0,0.5,20), rotation = (0, 0, 0))
Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
245
246
247
    bpy.context.object.name = "ForwardCamera"
    camera_forward=bpy.data.objects['ForwardCamera']
    camera_forward.data.type = 'ORTHO'
248
    camera_forward.data.ortho_scale = 18
Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
249
250

    # OverviewCamera
251
    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
252
253
254
    bpy.context.object.name = "OverviewCamera"
    bpy.context.object.data.lens = 66.78

Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
255
256
257
258
259
    # AntiOverviewCamera
    bpy.ops.object.camera_add(location = (-24.1218, -10.7468, -22.754), rotation = (-0.10123, 2.27591, 3.44703))
    bpy.context.object.name = "AntiOverviewCamera"
    bpy.context.object.data.lens = 66.78

Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
    # 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}

277
    # Create Materials
Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
278
279
280
    for type in particle_types:
        bpy.data.materials.new(name=type)
        #bpy.context.object.active_material = (1, 0, 0)
281
        bpy.data.materials[type].emit = 0.05
Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
282
283
284
285
286
287
288
289
290
        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
291
        print("Adding Sphere - Particle " + str(len(blender_particles)+1)+" of "+str(n_particles)+" - "+this_type)
Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
292
        bpy.ops.mesh.primitive_uv_sphere_add()
293
        bpy.ops.object.shade_smooth()
Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
294
295
296
297
298
299
300
301
302
303
304
305
        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:
306
307
                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
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341

                # 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
342
    for f in range(1, bcs.frame_end+1):
Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
343
344
345
346
347
348
349
350
351
352
353
354
355
        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
356
    for f in range(1, bcs.frame_end+1):
Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
357
358
359
        t = driver.delta_t*f
        bcs.frame_current = f
        print("Configuring tracks in frame: "+ str(f) +" of "+ str(bcs.frame_end))
360
        for point in range(f,bcs.frame_end+1):
Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
            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
381
382
383
384
385
386
387
388

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")