scene_functions.py 14.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
Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
9
    bcs.world.light_settings.use_environment_light = False # True ??
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'])
Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
28
    #bpy.data.objects.remove(bpy.data.objects['Lamp'])
Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
29
30
31
32

    # Basic Objects
    addCameras() # Add cameras

33
    if camera_type == "ForwardCamera":
34
        addALICE_Geometry(True,transp_par,detectors) # ALICE TPC, EMCal, ITS, TRD
35
    else:
36
        addALICE_Geometry(False,transp_par,detectors)
Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
37

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

40
41
42
43
    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
44

Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
45

46
47
    # ADD ITS
    if detectors[0]:
Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
48

49
        # ADD ITS INNER BARREL
Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
50

51
        # Material
52
        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
53

54
55
56
57
        # 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
58

59
60
61
        # Set Material
        inner_TPC.data.materials.clear()
        inner_TPC.data.materials.append(bpy.data.materials["innerITS"])
62
63


64
        # ADD ITS OUTER BARREL
65

66
        # Material
67
        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)
68

69
        # ADD ITS MIDDLE LAYERS
70

71
72
73
74
        # 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"
75

76
77
78
79
        # 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"
80

81
82
        # Subtract hole from main TPC part
        subtract(middle_ITS_hole,middle_ITS)
83

84
85
86
        # Set material
        middle_ITS.data.materials.clear()
        middle_ITS.data.materials.append(bpy.data.materials["outerITS"])
87
88


89
        # ADD ITS OUTER LAYERS
90

91
92
93
94
        # 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"
95

96
97
98
99
        # 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"
100

101
102
        # Subtract hole from main TPC part
        subtract(outer_ITS_hole,outer_ITS)
103

104
105
106
        # Set material
        outer_ITS.data.materials.clear()
        outer_ITS.data.materials.append(bpy.data.materials["outerITS"])
107

108
109
110
111
        # Make ITS middle and outer layers a single object
        joinObjects([middle_ITS,outer_ITS])
        Outer_ITS = bpy.context.object
        Outer_ITS.name = "OuterITS"
112

113
114
    # ADD TPC
    if detectors[1]:
115

116
        # Material
117
        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)
118

119
120
121
122
        # 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"
123

124
125
126
        # Set material
        TPC.data.materials.clear()
        TPC.data.materials.append(bpy.data.materials["tpc"])
127

128
    # ADD ALICE TRD
129
    if detectors[2]:
130

131
        # Material
132
        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)
133

134
135
136
137
        # 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"
138

139
140
141
142
        # 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"
143

144
145
        # Subtract hole from main TRD part
        subtract(TRD_hole,TRD)
146

147
148
149
        # Set material
        TRD.data.materials.clear()
        TRD.data.materials.append(bpy.data.materials["TRD"])
150

151
152
153
154
155
156
157
        # 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)
158

159
160
        def rad(theta): # Convert degrees to radians
            return theta * math.pi / 180
161

162
163
        xn = 2.9 * math.cos(rad(10))
        yn = 2.9 * math.sin(rad(10))
164

165
        for n in range(1,18):
166

167
168
            dx = -2 * 2.9 * math.sin(rad(10)) * math.sin(rad(n * 20))
            xn += dx
169

170
171
            dy = 2 * 2.9 * math.sin(rad(10)) * math.cos(rad(n * 20))
            yn += dy
172

173
            rotat = rad(10 + n*20)
174

175
176
177
178
179
            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
180

181
182
183
184
185
186
            subtract(slice,TRD)

    # ADD EMCal
    if detectors[3]:

        # Material
187
        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)
188
189
190
191
192
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

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

223

Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
224
225
def addCameras():
    # ForwardCamera
226
    bpy.ops.object.camera_add(location = (0,0.5,20), rotation = (0, 0, 0))
Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
227
228
229
    bpy.context.object.name = "ForwardCamera"
    camera_forward=bpy.data.objects['ForwardCamera']
    camera_forward.data.type = 'ORTHO'
230
    camera_forward.data.ortho_scale = 18
Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
231
232

    # OverviewCamera
233
    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
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
    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}

    #Create Materials
    for type in particle_types:
        bpy.data.materials.new(name=type)
        #bpy.context.object.active_material = (1, 0, 0)
        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
        print("Adding Sphere - Particle " + str(len(blender_particles))+" of "+str(n_particles-1)+" - "+this_type)
        bpy.ops.mesh.primitive_uv_sphere_add()
269
        bpy.ops.object.shade_smooth()
Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
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
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
        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:
                this_type=track.p_type #TO DO: make this not random, but according to file data
                print("Adding Curve - Track " + str(len(blender_tracks))+" of "+str(n_particles-1)+" - "+this_type)

                # 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
    for f in range(1, bcs.frame_end):
        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
    for f in range(1, bcs.frame_end):
        t = driver.delta_t*f
        bcs.frame_current = f
        print("Configuring tracks in frame: "+ str(f) +" of "+ str(bcs.frame_end))
        for point in range(f,bcs.frame_end):
            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