Commit 21dbf452 authored by Rafael Peretti Pezzi's avatar Rafael Peretti Pezzi

New class to drive animation (animationDriver)

 - genDrive: Derived class for particle generator driver.
parent eae4afb3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# particulas.py - Protótipo de animação de partículas # animate_particles.py - Animate HEP events
# Para utilizar este script chame o blender com a opção -P e o nome do arquivo
# #
# For console only rendering: # For console only rendering:
# $ blender -noaudio --background -P animate_particles.py # $ blender -noaudio --background -P animate_particles.py
...@@ -8,54 +7,47 @@ ...@@ -8,54 +7,47 @@
# TODO: - Implement command line arguments # TODO: - Implement command line arguments
# - https://blender.stackexchange.com/questions/6817/how-to-pass-command-line-arguments-to-a-blender-python-script # - https://blender.stackexchange.com/questions/6817/how-to-pass-command-line-arguments-to-a-blender-python-script
import os
import bpy import bpy
bpy.context.user_preferences.view.show_splash = False bpy.context.user_preferences.view.show_splash = False
bcs = bpy.context.scene # Import Drivers, partiles and scence functions:
bcsr = bcs.render filename = os.path.join(os.path.basename(bpy.data.filepath), "drivers.py")
import math
import os
import random
# Import Particle class
filename = os.path.join(os.path.basename(bpy.data.filepath), "particle.py")
exec(compile(open(filename).read(), filename, 'exec'))
# Import scene functions
filename = os.path.join(os.path.basename(bpy.data.filepath), "scene_functions.py")
exec(compile(open(filename).read(), filename, 'exec')) exec(compile(open(filename).read(), filename, 'exec'))
# Set animation parameters # Set animation parameters
renderCamera = "ForwardCamera" # Set rendering Camera: "ForwardCamera" "OverviewCamera" "BarrelCamera"
n_particles = 500 # Event Multiplicity
r_part = 0.05 # Particle radius r_part = 0.05 # Particle radius
t_video=15 # total video duration in seconds simulated_t = 0.015
t_simulado=0.015 # tempo simulado em microssegundos. 0.01 é o tempo para percorrer 3m na velocidade da luz duration = 15
fps = 24 # frames per second fps = 24
N_frames=t_video*fps # Total number of frames resolution_percent = 100
delta_t=t_simulado/N_frames # time elapsed per frame
bcs.frame_start = 0
bcs.frame_end = N_frames
init()
#configure output #configure output
fileIdentifier="_GaussianMomentum-PhysicalTrajectories_" outputPath = "/tmp/blender/"
configureOutput(fileIdentifier,resolution_percent=100) fileIdentifier = "PhysicalTrajectories_"
renderAnimation=False ## RenderCameras: ["ForwardCamera", "OverviewCamera", "BarrelCamera"]
renderCamera="ForwardCamera"
addCameras() # Add cameras
addALICE_TPC() # ALICE TPC
particles = createNparticlesPropGaussian(n_particles) # Create particles
blender_particles = create(particles) # Create blender objects - one sphere per particle
animate(blender_particles,particles) #Animate Scene using particle propagator
bpy.context.scene.frame_current = 24
## Todo: renderAnimation = True # True
## - Add option to keep particle trails saveBlenderFile = False # False
# Create and configure animation driver
n_particles = 500 # Event Multiplicity
driver = genDriver("GaussianGenerator_N"+str(n_particles)+"_")
driver.configure(renderCamera, duration, fps, simulated_t, outputPath, fileIdentifier, resolution_percent)
### Build scene
init() # Cleanup, addCameras, addALICE_TPC
particles = driver.createParticles(n_particles,3.0) # Simple genDriver takes two parameters: number of particles and Gaussian width
blender_particles = createSceneParticles(particles) # Create blender objects - one sphere per particle
#Animate scene using driver
animate(blender_particles,particles,driver)
bpy.context.scene.frame_current = 24
## Save blender file ## Save blender file
#bpy.ops.wm.save_as_mainfile(filepath="/home/pezzi/particles_"+str(n_particles)+".blend") if saveBlenderFile: bpy.ops.wm.save_as_mainfile(filepath=outputPath+fileIdentifier+".blend")
# Render animation # Render animation
bpy.context.scene.camera = bpy.data.objects[renderCamera] if renderAnimation: driver.render()
bpy.ops.render.render(animation=renderAnimation)
#exit() #exit()
# -*- coding: utf-8 -*-
# Import Particle class
filename = os.path.join(os.path.basename(bpy.data.filepath), "particle.py")
exec(compile(open(filename).read(), filename, 'exec'))
# Import scene functions
filename = os.path.join(os.path.basename(bpy.data.filepath), "scene_functions.py")
exec(compile(open(filename).read(), filename, 'exec'))
class animationDriver:
def __init__(self,name):
self.name=name
def configure(self, renderCamera, duration, fps, simulated_t, outputPath, fileIdentifier, resolution_percent=100):
self.renderCamera=renderCamera
self.duration=duration # total video duration in seconds
self.fps=fps
self.simulated_t=simulated_t # total simulated time in microseconds. (0.01 -> light travels ~ 3 m)
self.N_frames=duration*fps
self.delta_t=self.simulated_t/self.N_frames # time elapsed per frame
self.outputPath = outputPath
self.fileIdentifier = fileIdentifier
self.resolution_percent = resolution_percent
self.configureOutput()
bcs = bpy.context.scene
bcs.frame_start = 0
bcs.frame_end = self.N_frames
def render(self):
bpy.context.scene.camera = bpy.data.objects[self.renderCamera]
bpy.ops.render.render(animation=True)
def configureOutput(self):
# Configure Output
bcsr = bpy.context.scene.render
bcsr.fps=self.fps
bcsr.resolution_percentage = self.resolution_percent
bcsr.image_settings.file_format = 'FFMPEG'
bcsr.ffmpeg.format = "MPEG4"
bcsr.ffmpeg.codec = "H264"
bcsr.ffmpeg.use_max_b_frames = False
bcsr.ffmpeg.video_bitrate = 6000
bcsr.ffmpeg.maxrate = 9000
bcsr.ffmpeg.minrate = 0
bcsr.ffmpeg.buffersize = 224 * 8
bcsr.ffmpeg.packetsize = 2048
bcsr.ffmpeg.muxrate = 10080000
xpixels = int(bcsr.resolution_percentage * bcsr.resolution_x / 100)
output_prefix=fileIdentifier+str(xpixels)+"px_"+self.name
bcsr.filepath = "/tmp/blender/"+output_prefix
class genDriver(animationDriver): # A driver for particle generators
def createParticles(self, N_particles, par1, x = 0, y = 0, z = 0): # Create particles at given position and return them in a list
particles=[]
#loop over particles
for i in range(0, N_particles):
charge = random.choice([+1,-1])
part = ParticlePropagator(i,x,y,z)
part.SetMagneticField()
part.SetProperties(random.gauss(0,par1),random.gauss(0,par1),random.gauss(0,par1),charge)
particles.append(part)
return particles;
class dataDriver(animationDriver): # A driver for data from files. Under construction
def createParticles(self, filename): # Create particles acording to parameters from file
# TODO: load data into vectors
particles=[]
x = y = z = 0;
#loop over particles
for i in range(0, N_particles):
charge = random.choice([+1,-1])
part = ParticlePropagator(i,x,y,z)
part.SetMagneticField()
part.SetProperties(random.gauss(0,par1),random.gauss(0,par1),random.gauss(0,par1),charge)
particles.append(part)
return particles;
...@@ -17,14 +17,6 @@ class Particle: ...@@ -17,14 +17,6 @@ class Particle:
def GetPosition(self): def GetPosition(self):
return self.x, self.y, self.z return self.x, self.y, self.z
#Function that creates N particles and return them in a list
def createNparticles(N_particles, x = 0, y = 0, z = 0): # Create particles at given position and return them in a list
particles=[]
#loop over particles
for i in range(0, N_particles):
part = Particle(i,x,y,z)
particles.append(part)
return particles;
# Derived class to computes the time evolution particle positions # Derived class to computes the time evolution particle positions
class ParticlePropagator(Particle): class ParticlePropagator(Particle):
...@@ -46,16 +38,3 @@ class ParticlePropagator(Particle): ...@@ -46,16 +38,3 @@ class ParticlePropagator(Particle):
Yprop = self.y + Ry * math.sin(omega*time) + Rx * ( math.cos(omega*time) - 1 ) Yprop = self.y + Ry * math.sin(omega*time) + Rx * ( math.cos(omega*time) - 1 )
Zprop = self.z + self.Vz * time Zprop = self.z + self.Vz * time
return Xprop, Yprop, Zprop return Xprop, Yprop, Zprop
# Function that creates N particle propagators
# Momentum values to be obtained from real data
def createNparticlesPropGaussian(N_particles, x = 0, y = 0, z = 0): # Create particles at given position and return them in a list
particles=[]
#loop over particles
for i in range(0, N_particles):
charge = random.choice([+1,-1])
part = ParticlePropagator(i,x,y,z)
part.SetMagneticField()
part.SetProperties(random.gauss(0,3),random.gauss(0,3),random.gauss(0,3),charge)
particles.append(part)
return particles;
# -*- coding: utf-8 -*-
from particle import *
# Creates one particle propagator with default values
a = ParticlePropagator(0)
a.PrintPosition()
# Configure kinematics
a.SetMagneticField(0.5)
a.SetMomentum(-1.0, 2.0, 3.0)
#Print propagation
print(a.Propagate(1))
print(a.Propagate(2))
print(a.Propagate(3))
print(a.Propagate(3)[0]*2) #Acessing a single element of the result
# -*- coding: utf-8 -*-
def init(): def init():
bcs = bpy.context.scene
# Configure Environment # Configure Environment
bcs.world.light_settings.use_environment_light = False bcs.world.light_settings.use_environment_light = False
...@@ -10,25 +10,9 @@ def init(): ...@@ -10,25 +10,9 @@ def init():
bpy.data.objects.remove(bpy.data.objects['Cube']) bpy.data.objects.remove(bpy.data.objects['Cube'])
bpy.data.objects.remove(bpy.data.objects['Camera']) bpy.data.objects.remove(bpy.data.objects['Camera'])
# Basic Objects
def configureOutput(fileIdentifier,resolution_percent=100): addCameras() # Add cameras
# Configure Output addALICE_TPC() # ALICE TPC
bcsr.fps=fps
bcsr.resolution_percentage = resolution_percent
bcsr.image_settings.file_format = 'FFMPEG'
bcsr.ffmpeg.format = "MPEG4"
bcsr.ffmpeg.codec = "H264"
bcsr.ffmpeg.use_max_b_frames = False
bcsr.ffmpeg.video_bitrate = 6000
bcsr.ffmpeg.maxrate = 9000
bcsr.ffmpeg.minrate = 0
bcsr.ffmpeg.buffersize = 224 * 8
bcsr.ffmpeg.packetsize = 2048
bcsr.ffmpeg.muxrate = 10080000
xpixels = int(bcsr.resolution_percentage * bcsr.resolution_x / 100)
output_prefix="N"+str(n_particles)+fileIdentifier+str(xpixels)+"px_"
bcsr.filepath = "/tmp/blender/"+output_prefix
def addALICE_TPC(): def addALICE_TPC():
print("Adding ALICE TPC") print("Adding ALICE TPC")
...@@ -50,26 +34,26 @@ def addALICE_TPC(): ...@@ -50,26 +34,26 @@ def addALICE_TPC():
def addCameras(): def addCameras():
# ForwardCamera # ForwardCamera
bpy.ops.object.camera_add(location=(0,0,20), rotation=(0, 0, 0)) bpy.ops.object.camera_add(location = (0,0,20), rotation = (0, 0, 0))
bpy.context.object.name = "ForwardCamera" bpy.context.object.name = "ForwardCamera"
camera_forward=bpy.data.objects['ForwardCamera'] camera_forward=bpy.data.objects['ForwardCamera']
camera_forward.data.type = 'ORTHO' camera_forward.data.type = 'ORTHO'
camera_forward.data.ortho_scale = 10 camera_forward.data.ortho_scale = 10
# OverviewCamera # OverviewCamera
bpy.ops.object.camera_add(location=(6.98591, -19.7115, 23.9696), rotation=(-0.281366, 0.683857, -1.65684)) bpy.ops.object.camera_add(location = (6.98591, -19.7115, 23.9696), rotation = (-0.281366, 0.683857, -1.65684))
bpy.context.object.name = "OverviewCamera" bpy.context.object.name = "OverviewCamera"
bpy.context.object.data.lens = 66.78 bpy.context.object.data.lens = 66.78
# Barrel Camera # Barrel Camera
bpy.ops.object.camera_add(location=(6, 0, 0), rotation=(0, 1.5708, 0)) bpy.ops.object.camera_add(location = (6, 0, 0), rotation = (0, 1.5708, 0))
#bpy.context.object.rotation_euler[1] = 1.5708 #bpy.context.object.rotation_euler[1] = 1.5708
bpy.context.object.name = "BarrelCamera" bpy.context.object.name = "BarrelCamera"
# Function that creates Blender Objects from input list of particles. # Function that creates Blender Objects from input list of particles.
## Returns a list of blender objects ## Returns a list of blender objects
def create(particles): def createSceneParticles(particles):
# Associate particles and colors
particle_types = ["Electron","Pion","Muon","Proton","Kaon"] particle_types = ["Electron","Pion","Muon","Proton","Kaon"]
clRed = (1, 0, 0) clRed = (1, 0, 0)
clGreen = (0, 1, 0) clGreen = (0, 1, 0)
...@@ -78,8 +62,6 @@ def create(particles): ...@@ -78,8 +62,6 @@ def create(particles):
clYellow = (1, 1, 0) clYellow = (1, 1, 0)
particle_colors = {"Electron":clRed, "Pion":clGreen, "Muon":clBlue, "Proton":clMagenta, "Kaon": clYellow} particle_colors = {"Electron":clRed, "Pion":clGreen, "Muon":clBlue, "Proton":clMagenta, "Kaon": clYellow}
blender_particles=[]
#Create Materials #Create Materials
for type in particle_types: for type in particle_types:
bpy.data.materials.new(name=type) bpy.data.materials.new(name=type)
...@@ -89,24 +71,27 @@ def create(particles): ...@@ -89,24 +71,27 @@ def create(particles):
bpy.data.materials[type].use_cast_shadows = False bpy.data.materials[type].use_cast_shadows = False
# Create blender spheres (particles) # Create blender spheres (particles)
blender_particles=[]
for particle in particles: for particle in particles:
this_type=random.choice(particle_types) this_type=random.choice(particle_types)
print("Adding Sphere - Particle " + str(len(blender_particles))+" of "+str(n_particles-1)+" - "+this_type) print("Adding Sphere - Particle " + str(len(blender_particles))+" of "+str(n_particles-1)+" - "+this_type)
bpy.ops.mesh.primitive_uv_sphere_add() bpy.ops.mesh.primitive_uv_sphere_add()
this_particle = bpy.context.object this_particle = bpy.context.object
this_particle.name = "part"+str(particle.iDx) this_particle.name = "part"+str(particle.iDx)
this_particle.location=((particle.x,particle.y,particle.z)) this_particle.location = ((particle.x,particle.y,particle.z))
this_particle.delta_scale=(r_part,r_part,r_part) this_particle.delta_scale = (r_part,r_part,r_part)
this_particle.data.materials.clear() this_particle.data.materials.clear()
this_particle.data.materials.append(bpy.data.materials[this_type]) this_particle.data.materials.append(bpy.data.materials[this_type])
blender_particles.append(this_particle) blender_particles.append(this_particle)
return blender_particles return blender_particles
# Function that animates the scene using the particle propagator class # Function that animates the scene using the particle propagator class
def animate(objects, particles): def animate(objects, particles, driver):
bcs = bpy.context.scene
#Animate particles #Animate particles
for f in range(1, bcs.frame_end): for f in range(1, bcs.frame_end):
t=delta_t*f t = driver.delta_t*f
bcs.frame_current = f bcs.frame_current = f
print("Configuring Frame: "+str(f)+" of "+str(bcs.frame_end)) print("Configuring Frame: "+str(f)+" of "+str(bcs.frame_end))
for i in range(0, len(objects)): for i in range(0, len(objects)):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment