scene_functions.py 15.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,transp_par,detectors,blender_path,bgshade):
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
    bcs.world.light_settings.environment_energy = 0.1
11
    bpy.context.scene.world.horizon_color = (bgshade,bgshade,bgshade)
Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
12
13

    # Configure Stamp
Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
14
15
16
17
18
19
20
21
22
23
24
    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
25
26
27
28

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

    # Basic Objects
    addCameras() # Add cameras
33
    addLamps() # Add Lamps
34

35
    addALICE_Geometry(False,transp_par,detectors,blender_path)
Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
36

37
def addALICE_Geometry(bright_colors=False, transp_par=1.0, detectors=[1,1,1,1,0], blender_path="/home/"):
Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
38

39
    if bright_colors: # Defining sequence of RGB values to fill 'createMaterial' functions below
40
        rgb_v = [13,13,25,10] # Colors for brighter detector
41
    else:
42
        rgb_v = [0.5,0.9,1,0.2] # Colors for standard geometry
Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
43

Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
44

45
    if detectors[0]:
46
47
48
49
50
51
52
53
54
55
        addALICE_ITS(transp_par,rgb_v)
    if detectors[4]:
        importALICE_detailed_TPC(transp_par,blender_path)
    else:
        if detectors[1]:
            addALICE_TPC(transp_par,rgb_v)
    if detectors[2]:
        addALICE_TRD(transp_par,rgb_v)
    if detectors[3]:
        addALICE_EMCal(transp_par,rgb_v)
Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
56

57
def addALICE_ITS(transp_par,rgb_v):
Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
58

59
    # ADD ITS INNER BARREL
Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
60

61
62
    # Material
    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
63

64
65
66
67
    # 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"
68

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


74
    # ADD ITS OUTER BARREL
75

76
77
    # Material
    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)
78

79
    # ADD ITS MIDDLE LAYERS
80

81
82
83
84
    # 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"
85

86
87
88
89
    # 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"
90

91
92
    # Subtract hole from main TPC part
    subtract(middle_ITS_hole,middle_ITS)
93

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


99
    # ADD ITS OUTER LAYERS
100

101
102
103
104
    # 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"
105

106
107
108
109
    # 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"
110

111
112
113
114
115
116
    # Subtract hole from main ITS part
    subtract(outer_ITS_hole,outer_ITS)

    # Set material
    outer_ITS.data.materials.clear()
    outer_ITS.data.materials.append(bpy.data.materials["outerITS"])
117

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

123
def addALICE_TPC(transp_par,rgb_v):
124

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

128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
    # 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"

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

def importALICE_detailed_TPC(transp_par,blender_path):

    # Materials
    createMaterial("tpc_part_1",R=0,G=1,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)
    createMaterial("tpc_part_2",R=1,G=1,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)
    createMaterial("tpc_part_3",R=1,G=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)
    createMaterial("tpc_part_4",R=0,G=1,B=1,shadows=False,cast_shadows=False,transparency=True,alpha=transp_par*0.2,emit=0.3,specular_alpha=0,fresnel_factor=5,fresnel=0.3)

    # Import detailed TPC
146
147
148
149
    #
    # File was provided by CERN's researcher Stefan Rossegger
    # Email: stefan.rossegger@gmail.com
    #
150
151
152
153
154
    for i in range(1,5):
        bpy.ops.wm.append(filename="tpc_part"+str(i), directory=blender_path+"/Detailed_TPC.blend/Object/")
        bpy.context.scene.objects.active = bpy.data.objects["tpc_part"+str(i)]
        TPC_part = bpy.context.object
        TPC_part.name = "TPC_part_"+str(i)
155

156
        # Set material
157
158
        TPC_part.data.materials.clear()
        TPC_part.data.materials.append(bpy.data.materials["tpc_part_"+str(i)])
159

160
def addALICE_TRD(transp_par,rgb_v):
161

162
163
    # Material
    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)
164

165
166
167
168
    # 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"
169

170
171
172
173
    # 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"
174

175
176
    # Subtract hole from main TRD part
    subtract(TRD_hole,TRD)
177

178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
    # Set material
    TRD.data.materials.clear()
    TRD.data.materials.append(bpy.data.materials["TRD"])

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

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

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

    for n in range(1,18):

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

201
202
203
204
205
206
        dy = 2 * 2.9 * math.sin(rad(10)) * math.cos(rad(n * 20))
        yn += dy

        rotat = rad(10 + n*20)

        bpy.ops.mesh.primitive_cube_add(radius=1, location=(xn,yn,0))
207
208
209
        slice = bpy.context.object
        slice.name = "slice"
        bpy.ops.transform.resize(value=(1,0.03,4))
210
        bpy.context.object.rotation_euler[2] = rotat
211

212
        subtract(slice,TRD)
213

214
def addALICE_EMCal(transp_par,rgb_v):
215

216
217
    # Material
    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)
218

219
220
221
222
    # 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"
223

224
225
226
227
    # 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"
228

229
    subtract(emcal_hole,EMCal);
230

231
232
233
234
235
    # 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)
236

237
238
239
240
241
    # 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)
242

243
244
245
246
247
    #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)
248

249
250
251
    # Set Material
    EMCal.data.materials.clear()
    EMCal.data.materials.append(bpy.data.materials["emcal"])
252

253

254
def addLamps():
255
    bpy.ops.object.lamp_add(type='POINT', location=(4,1,6))
256
    bpy.ops.object.lamp_add(type='POINT', location=(0,0,-8))
Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
257

Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
258
259
def addCameras():
    # ForwardCamera
260
    bpy.ops.object.camera_add(location = (0,0.5,20), rotation = (0, 0, 0))
Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
261
262
263
    bpy.context.object.name = "ForwardCamera"
    camera_forward=bpy.data.objects['ForwardCamera']
    camera_forward.data.type = 'ORTHO'
264
    camera_forward.data.ortho_scale = 18
Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
265
266

    # OverviewCamera
267
    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
268
269
270
271
272
273
274
    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"

275
276
277
278
279
    # Side Camera
    bpy.ops.object.camera_add(location = (6, 0, 0), rotation = (0, 1.5708, 0))
    bpy.context.object.name = "SideCamera"
    bpy.context.object.data.lens = 9

Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
280
281
282
283
284
285
286
287
288
289
290
291
292
# 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}

293
    # Create Materials
Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
294
295
296
    for type in particle_types:
        bpy.data.materials.new(name=type)
        #bpy.context.object.active_material = (1, 0, 0)
297
        bpy.data.materials[type].emit = 0.05
Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
298
299
300
301
302
303
304
305
306
        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
307
        print("Adding Sphere - Particle " + str(len(blender_particles)+1)+" of "+str(n_particles)+" - "+this_type)
Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
308
        bpy.ops.mesh.primitive_uv_sphere_add()
309
        bpy.ops.object.shade_smooth()
Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
310
311
312
313
314
315
316
317
318
319
320
321
        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:
322
323
                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
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
357

                # 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
358
    for f in range(bcs.frame_end):
Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
359
360
361
362
363
364
365
366
367
368
369
370
371
        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
372
373
    for f in range(bcs.frame_end):
        t = driver.delta_t*(f+1) # choosing (f+1) instead of (f) removes gap between track and particle
Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
374
375
        bcs.frame_current = f
        print("Configuring tracks in frame: "+ str(f) +" of "+ str(bcs.frame_end))
376
        for point in range(f,bcs.frame_end+1):
Breno Rilho Lemos's avatar
Breno Rilho Lemos committed
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
            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