def cam_and_swivel(cam_location=[25, 0, 0], cam_rotation_euler=[0, 0, 0], cam_name="Camera Bobject", swivel_location=[0, 0, 0], swivel_rotation_euler=[0, 0, 0], swivel_name='Cam swivel', control_sun=False): cam_bobj = bobject.Bobject(location=cam_location, rotation_euler=cam_rotation_euler, name=cam_name) cam_swivel = bobject.Bobject( cam_bobj, location=swivel_location, rotation_euler=swivel_rotation_euler, name=swivel_name, ) cam_obj = bpy.data.objects['Camera'] cam_obj.data.clip_end = 100 cam_obj.location = [0, 0, 0] cam_obj.parent = cam_bobj.ref_obj if control_sun == True: sun_obj = bpy.data.objects['Sun'] sun_obj.location = [0, 0, 0] sun_obj.parent = cam_bobj.ref_obj return cam_bobj, cam_swivel
def head_move_eyes_locked(self): cam_bobj, cam_swivel = cam_and_swivel( cam_location=[0, 0, 90], cam_rotation_euler=[0, 0, 0], cam_name="Camera Bobject", swivel_location=[0, 0, -2], swivel_rotation_euler=[math.pi / 2, 0, math.pi / 2], swivel_name='Cam swivel', #control_sun = True ) cam_swivel.add_to_blender(appear_time=-1) skull = bpy.data.objects['Skull_Top'] skull_bobj = bobject.Bobject(objects=[skull]) skull_bobj.add_to_blender(appear_time=0, animate=False) eye_l = bpy.data.objects['eye_l'] eye_l_initial_angle = list(eye_l.rotation_euler) eye_r = bpy.data.objects['eye_r'] eye_r_initial_angle = list(eye_r.rotation_euler) angles = [[0, 0, 15 * math.pi / 180], [0, 0, -15 * math.pi / 180], [0, 0, 15 * math.pi / 180], [0, 0, -15 * math.pi / 180], [0, 0, -15 * math.pi / 180], [0, 10 * math.pi / 180, 0], [0, -5 * math.pi / 180, 0], [0, 0, 15 * math.pi / 180], [0, 10 * math.pi / 180, 0], [0, 0, 0]] rot_start_time = 49.5 for i, angle in enumerate(angles): time = i / 2 skull_bobj.move_to(new_angle=angle, start_time=time + rot_start_time) #Eyes aren't set up to work well as bobjects since I currently don't #plan to reuse them a bunch. Probably poor foresight. /shrug #They are also rotated in the z-direction with xyz euler angles, so #the corrections need to accound for this. eye_l.keyframe_insert(data_path='rotation_euler', frame=(time + rot_start_time) * FRAME_RATE) eye_l.rotation_euler = [ eye_l_initial_angle[0] - angle[1], eye_l_initial_angle[1] + angle[0], eye_l_initial_angle[2] - angle[2] ] eye_l.keyframe_insert(data_path='rotation_euler', frame=(time + rot_start_time + 0.5) * FRAME_RATE) eye_r.keyframe_insert(data_path='rotation_euler', frame=(time + rot_start_time) * FRAME_RATE) eye_r.rotation_euler = [ eye_r_initial_angle[0] - angle[1], eye_r_initial_angle[1] + angle[0], eye_r_initial_angle[2] - angle[2] ] eye_r.keyframe_insert(data_path='rotation_euler', frame=(time + rot_start_time + 0.5) * FRAME_RATE)
def zoom(self): cues = self.subscenes['zoom'] cam_bobj = bobject.Bobject( location=[90, 0, 0], rotation_euler=[math.pi / 2, 0, 87 * math.pi / 180], name="Camera Bobject") cam_swivel = bobject.Bobject(cam_bobj, location=[0, 0, 0], rotation_euler=[0, 0, 0], name='Cam swivel') cam_swivel.add_to_blender(appear_time=0, animate=False) #cam_bobj.add_to_blender(appear_time = 0, animate = False) cam_obj = bpy.data.objects['Camera'] cam_obj.data.clip_end = 1000 cam_obj.location = [0, 0, 0] cam_obj.parent = cam_bobj.ref_obj #Look at brain and temporal bone cam_swivel.move_to(new_angle=[0, 0, -55 * math.pi / 180], start_time=self.brain_zoom_time, end_time=self.brain_zoom_time + 1.5) cam_bobj.move_to( new_location=[35.3, 0, 0], new_angle=[95.8 * math.pi / 180, 0, 85.6 * math.pi / 180], start_time=self.brain_zoom_time, end_time=self.brain_zoom_time + 1.5) #Look at inner ear cam_bobj.move_to( new_location=[5, 0, 0], new_angle=[92.5 * math.pi / 180, 0, 89 * math.pi / 180], start_time=self.inner_zoom_time, end_time=self.inner_zoom_time + 1.5) #Look at utricle cam_swivel.move_to( new_angle=[0, 15.5 * math.pi / 180, -190 * math.pi / 180], start_time=self.utricle_time, end_time=self.utricle_time + 1.5) cam_bobj.move_to( new_location=[0.3, 0, 0.15], new_angle=[80.9 * math.pi / 180, 0, 89 * math.pi / 180], start_time=self.utricle_time, end_time=self.utricle_time + 1.5) #Side view of canals cam_swivel.move_to(new_angle=[0, 0, -217 * math.pi / 180], start_time=self.dislodged_time, end_time=self.dislodged_time + 1.5) cam_bobj.move_to( new_location=[5, 0, 0], new_angle=[92.5 * math.pi / 180, 0, 91 * math.pi / 180], start_time=self.dislodged_time, end_time=self.dislodged_time + 1.5) #rotate and highlight rot_duration = 2 #25 deg_angle = -217 + 360 / 10 * rot_duration cam_swivel.move_to(new_angle=[0, 0, deg_angle * math.pi / 180], start_time=self.only_posterior_time, end_time=self.only_posterior_time + rot_duration) #Epley position (stationary camera after initial positioning) cam_swivel.move_to( new_angle=[0, 0, 60 * math.pi / 180], start_time=self.epley_camera_time, ) """#Dix Hallpike lean back
def end_card(self): logo = svg_bobject.SVGBobject( "UCSF_logo", #location = (-5, 3.75, 0), #Centered position #scale = 0.26, #Centered scale location=[0, 0, 0], scale=0.121, color='color2', #centered = True, ) baf = svg_bobject.SVGBobject( 'BaFC_Arial', location=[5.2257280349731445, -0.26257357001304626, 0.0], scale=2.23, color='color2', #centered = True, ) logobaf = bobject.Bobject( logo, baf, location=[-11.57, 2.5, 0], #location = [0, 1.5, Z0], scale=0.852, #centered = True ) logobaf.add_to_blender( appear_time=0, animate=False, ) url = tex_bobject.TexBobject( '\\text{ohns.ucsf.edu/otology-neurotology/balance-and-falls}', location=[0, 0.8, 0], color='color2', name='url', typeface='arial', scale=0.8, centered=True) url.add_to_blender(appear_time=0) mpb_loc = [1, -4.25, 0] mpb = tex_bobject.TexBobject('\\text{Made possible by:}', location=mpb_loc, color='color2', name='mpb', typeface='arial') mzhf = tex_bobject.TexBobject( '\\text{Mount Zion Health Fund}', color='color2', scale=1.2, location=[mpb_loc[0] + 0.5, mpb_loc[1] - 1.4, mpb_loc[2]], name='mzhf', typeface='arial') vpb_loc = [-13, -4.25, 0] vpb = tex_bobject.TexBobject('\\text{Video produced by:}', color='color2', location=vpb_loc, name='vpb', typeface='arial') jh = tex_bobject.TexBobject( '\\text{Justin Helps}', location=[vpb_loc[0] + 0.5, vpb_loc[1] - 1.4, vpb_loc[2]], scale=1.2, color='color2', name='jh', typeface='arial') jds = tex_bobject.TexBobject( '\\text{Jeffrey D. Sharon, MD}', location=[vpb_loc[0] + 0.5, vpb_loc[1] - 2.8, vpb_loc[2]], scale=1.2, color='color2', name='jds', typeface='arial') for bobj in [mpb, mzhf, vpb, jh, jds]: bobj.add_to_blender(appear_time=0, animate=False)
def add_annotation(self, targets=None, alignment='top', labels=None, angle=0, length=1, label_scale=0.67, gest_scale=1): #calc points from targets gesture_series = [] tex_bobj = self.tex_bobjects[targets[0]] #label_anchor = None for j, target in enumerate(targets[1]): bobjs = [] path = tex_bobj.paths[target[0]] for i in range(target[1], target[2] + 1): bobjs.append(tex_bobj.imported_svg_data[path]['curves'][i]) left_most = math.inf right_most = -math.inf y = 0 for bobj in bobjs: cur = bobj.objects[0] for spline in cur.data.splines: for point in spline.bezier_points: candidatex = cur.location[0] * cur.parent.scale[0] + \ cur.parent.location[0] * cur.parent.parent.scale[0] + \ point.co[0] * cur.scale[0] if right_most < candidatex: right_most = candidatex if left_most > candidatex: left_most = candidatex for point in spline.bezier_points: candidatey = cur.location[1] * cur.parent.scale[1] + \ cur.parent.location[1] * cur.parent.parent.scale[1] + \ point.co[1] * cur.scale[1] if alignment == 'top': if y < candidatey: y = candidatey elif alignment == 'bottom': if y > candidatey: y = candidatey if isinstance(angle, (float, int)): this_angle = angle elif isinstance(angle, list): this_angle = angle[j] if len(target ) > 3 and target[3] == None: #No bobjs, empty gesture. HEH. if alignment == 'top': #y += 0 * self.scale[1] * tex_bobj.scale[1] head = ((right_most + left_most) / 2 / gest_scale, y + length, 0) rot = (0, 0, 0) elif alignment == 'bottom': #y -= 0 * self.scale[1] * tex_bobj.scale[1] head = ((right_most + left_most) / 2 / gest_scale, y - length, 0) rot = (0, 0, math.pi) #if label_anchor == None: # label_anchor = list(head) gesture_series.append({ 'type': None, 'points': { 'location': head, 'rotation': rot } }) elif len(target) > 3 and target[3] == 'bracket' or \ (len(target) == 3 and len(bobjs) > 1): #Bracket if alignment == 'top': y += 0.2 * self.scale[1] * tex_bobj.scale[1] annotation_point = ((right_most + left_most) / 2 / gest_scale, y + length, 0) left_point = (left_most / gest_scale, y, 0) right_point = (right_most / gest_scale, y, 0) elif alignment == 'bottom': y -= 0.2 * self.scale[1] * tex_bobj.scale[1] annotation_point = ((right_most + left_most) / 2 / gest_scale, y - length, 0) left_point = [right_most / gest_scale, y, 0] right_point = [left_most / gest_scale, y, 0] #if label_anchor == None: # label_anchor = list(annotation_point) gesture_series.append({ 'type': 'bracket', 'points': { 'annotation_point': annotation_point, 'left_point': left_point, 'right_point': right_point } }) elif len(target) > 3 and target[3] == 'arrow' or \ (len(target) == 3 and len(bobjs) == 1): #Arrow if alignment == 'top': y += 0.3 * tex_bobj.scale[1] #* self.scale[1] head = ((right_most + left_most) / 2 / gest_scale + math.tan(this_angle) * 0.4, y / gest_scale, 0) tail = ((right_most + left_most) / 2 / gest_scale + math.tan(this_angle) * length, (y + length) / gest_scale, 0) elif alignment == 'bottom': y -= 0.3 * tex_bobj.scale[1] #* self.scale[1] head = ((right_most + left_most) / 2 / gest_scale - math.tan(this_angle) * 0.4, y / gest_scale, 0) tail = ((right_most + left_most) / 2 / gest_scale - math.tan(this_angle) * length, (y - length) / gest_scale, 0) #if label_anchor == None: # label_anchor = list(tail) gesture_series.append({ 'type': 'arrow', 'points': { 'head': head, 'tail': tail, } }) else: raise Warning('Something is wrong with the gesture targets.') container = bobject.Bobject(name='annotation') gest = gesture.Gesture(gesture_series=gesture_series, color='color2', scale=gest_scale) container.add_subbobject(gest) tex_bobj.annotations.append([container, targets[1], alignment]) self.annotations.append([container, targets[0]]) #Make TexComplex for the annotation_text t_bobj_count = 0 for label in labels: t_bobj_count = max(len(label), t_bobj_count) for label in labels: while len(label) < t_bobj_count: label.append(None) t_bobjs = [] for i in range(t_bobj_count): strings = [] for label in labels: strings.append(label[i]) #print(len(strings)) t_bobj = tex_bobject.TexBobject(*strings, centered=True, color='color2') t_bobjs.append(t_bobj) #label_scale = 0.67 #Smaller than text. Could do this in a more robust way #se;fline_height = 1.2 #Could make this a constant. It's already a default. #dy = (1 + t_bobj_count) / 2 * self.line_height #print(t_bobj_count) if alignment == 'top': dy = (t_bobj_count / 2 + 1 / 2) * self.line_height if alignment == 'bottom': dy = (t_bobj_count / 2) * self.line_height #Some t_bobjs may start with empty expressions. Initial position #shouldn't take empty lines into account, and position will be adjusted on morph if alignment == 'top': for t_bobj in t_bobjs: if t_bobj.paths[0] == None: dy -= self.line_height # * label_scale #label_anchor[1] += dy label_text = TexComplex( *t_bobjs, multiline=True, centered=True, align_y='center', scale=label_scale, name='label', location=(0, dy, 0), #label_anchor rotation_euler=[ 0, 0, -gest.subbobjects[0].ref_obj.rotation_euler[2] ]) gest.subbobjects[0].add_subbobject(label_text) self.add_subbobject(container)
def import_object(filename, *folders, **kwargs): #Needs filename and the name of the template object to be the same DIR = BLEND_DIR for folder in folders: DIR = os.path.join(DIR, folder) filepath = os.path.join(DIR, filename) + '.blend' #Unsurprisingly, but for reasons not fully understood, this doesn't work #properly when the blender's open file is the one at the filepath. with bpy.data.libraries.load(filepath) as (data_from, data_to): data_to.objects = data_from.objects num = len([x for x in data_to.objects if filename in x]) #Get most recent objects with the right kind of name #Matters when we want to import multiple objects from a .blend file #objs = [x for x in bpy.data.objects if filename == x.name] #obj_names = [x.name for x in objs] new_obj = None for object in bpy.data.objects: if object.name == filename: new_obj = object if new_obj == None: raise Warning('Did not find object with same name as file') #Make object and children names unique by adding a num in front #Blender already adds numbers to the end of names, but this allows more #than 1000 objects with the (otherwise) same name and groups metaballs #together. existing_names = [x.name for x in bpy.data.objects] count = 0 prefix = str(count).zfill(4) name = prefix + new_obj.name while name in existing_names: count += 1 prefix = str(count).zfill(4) name = prefix + new_obj.name new_obj.name = name #Give children a unique prefix to separate metaball groups #Would need to expand this if importing more complex files where children #have children for child in new_obj.children: child.name = new_obj.name + child.name if 'name' not in kwargs.keys(): name = new_obj.name kwargs['name'] = name #If this is an svg from blend, make subbobjects out of children before #making the final bobject. '''if 'svg' in kwargs and kwargs['svg'] == True: #print('bananananan') subbobjs = [] for child in new_obj.children: child_bobj = bobject.Bobject(objects = [child]) subbobjs.append(child_bobj) new_bobject = bobject.Bobject(*subbobjs, **kwargs) else:''' new_bobject = bobject.Bobject(objects=[new_obj], **kwargs) #Blinks ref_obj = new_bobject.ref_obj if filename == 'boerd_blob' or filename == 'boerd_blob_squat': leye = ref_obj.children[0].pose.bones[5] reye = ref_obj.children[0].pose.bones[6] t = 0 if 'cycle_length' not in kwargs: cycle_length = BLINK_CYCLE_LENGTH else: cycle_length = kwargs['cycle_length'] leye.keyframe_insert(data_path='scale', frame=0) leye.keyframe_insert(data_path='scale', frame=BLINK_CYCLE_LENGTH) reye.keyframe_insert(data_path='scale', frame=0) reye.keyframe_insert(data_path='scale', frame=BLINK_CYCLE_LENGTH) while t < cycle_length - BLINK_LENGTH: blink_roll = random() if blink_roll < BLINK_CHANCE: leye.keyframe_insert(data_path='scale', frame=t) leye.scale[1] = 0.2 frm = math.floor(BLINK_LENGTH / 2) - 1 leye.keyframe_insert(data_path='scale', frame=t + frm) frm = math.ceil(BLINK_LENGTH / 2) + 1 leye.keyframe_insert(data_path='scale', frame=t + frm) leye.scale[1] = 1 leye.keyframe_insert(data_path='scale', frame=t + BLINK_LENGTH) reye.keyframe_insert(data_path='scale', frame=t) reye.scale[1] = 0.2 frm = math.floor(BLINK_LENGTH / 2) - 1 reye.keyframe_insert(data_path='scale', frame=t + frm) frm = math.ceil(BLINK_LENGTH / 2) + 1 reye.keyframe_insert(data_path='scale', frame=t + frm) reye.scale[1] = 1 reye.keyframe_insert(data_path='scale', frame=t + BLINK_LENGTH) t += BLINK_LENGTH else: t += 1 #Make blinks cyclical try: leye_fcurve = ref_obj.children[ 0].animation_data.action.fcurves.find( 'pose.bones["brd_bone_eye.l"].scale', index=1) l_cycle = leye_fcurve.modifiers.new(type='CYCLES') #l_cycle.blend_out = BLINK_CYCLE_LENGTH reye_fcurve = ref_obj.children[ 0].animation_data.action.fcurves.find( 'pose.bones["brd_bone_eye.r"].scale', index=1) r_cycle = reye_fcurve.modifiers.new(type='CYCLES') #r_cycle.blend_out = BLINK_CYCLE_LENGTH except: #Sometimes a creature goes the whole cycle length without blinking, #in which case, there's no fcurve, so the above block throws an #error. In the end, it's fine if the creature never blinks. It's rare. pass #Wiggles if 'wiggle' in kwargs: wiggle = kwargs['wiggle'] else: wiggle = False if (filename == 'boerd_blob' or filename == 'boerd_blob_squat') \ and wiggle == True: if 'cycle_length' not in kwargs: wiggle_cycle_length = BLINK_CYCLE_LENGTH else: wiggle_cycle_length = int(kwargs['cycle_length']) wiggle_slow_factor = 1 wind_down_time = FRAME_RATE / wiggle_slow_factor new_bobject.head_angle = [None] * wiggle_cycle_length new_bobject.head_angle_vel = [None] * wiggle_cycle_length for t in range(wiggle_cycle_length): if t == 0: #Start in neutral position new_bobject.head_angle[t] = [ 1, uniform(0, 0), uniform(0, 0), uniform(0, 0), ] new_bobject.head_angle_vel[t] = [ 0, uniform(-0.0025, 0.0025), uniform(-0.0025, 0.0025), uniform(-0.0025, 0.0025) ] bone = ref_obj.children[0].pose.bones[3] bone.rotation_quaternion = new_bobject.head_angle[t] bone.keyframe_insert(data_path="rotation_quaternion", frame=t * wiggle_slow_factor) elif t < wiggle_cycle_length - wind_down_time: #Random movement up to a half second before end of cycle. #update position a = new_bobject.head_angle[t - 1] b = new_bobject.head_angle_vel[t - 1] new_bobject.head_angle[t] = list(map(sum, zip(a, b))) #Hard max on head angles extrema = [[1, 1], [-0.05, 0.05], [-0.05, 0.05], [-0.05, 0]] a = new_bobject.head_angle[t] for i in range(1, len(new_bobject.head_angle[t])): if a[i] < extrema[i][0]: a[i] = extrema[i][0] if a[i] > extrema[i][1]: a[i] = extrema[i][1] #update velocity to be used when updating position #in next frame a = new_bobject.head_angle_vel[t - 1] b = [ 0, uniform(-0.0005, 0.0005), uniform(-0.0005, 0.0005), uniform(-0.0005, 0.0005) ] #Shift the acceleration distribution toward neutral for i in range(1, len(b)): go_back = -new_bobject.head_angle[t][i] / 5000 b[i] += go_back new_bobject.head_angle_vel[t] = list(map(sum, zip(a, b))) bone = ref_obj.children[0].pose.bones[3] bone.rotation_quaternion = new_bobject.head_angle[t] bone.keyframe_insert(data_path="rotation_quaternion", frame=t * wiggle_slow_factor) else: #Approach neutral toward end of cycle, for continuity across #scenes #update position a = new_bobject.head_angle[t - 1] b = new_bobject.head_angle_vel[t - 1] new_bobject.head_angle[t] = list(map(sum, zip(a, b))) #Hard max on head angles extrema = [[1, 1], [-0.1, 0.1], [-0.1, 0.1], [-0.1, 0]] a = new_bobject.head_angle[t] for i in range(1, len(new_bobject.head_angle[t])): if a[i] < extrema[i][0]: a[i] = extrema[i][0] if b[i] < 0: b[i] = 0 if a[i] > extrema[i][1]: a[i] = extrema[i][1] if b[i] > 0: b[i] = 0 #update velocity to be used when updating position #in next frame #Calculate acceleration needed to get back to neutral time_left = wiggle_cycle_length - t timing_factor = (wind_down_time - time_left) * time_left \ / wind_down_time ** 2 target_v = [ #Approaches zero as distance goes to zero -a[1] * timing_factor, -a[2] * timing_factor, -a[3] * timing_factor, ] acc_x = (target_v[0] - b[1]) / 2 acc_y = (target_v[1] - b[2]) / 2 acc_z = (target_v[2] - b[3]) / 2 a = new_bobject.head_angle_vel[t - 1] b = [ 0, acc_x, acc_y, acc_z, ] new_bobject.head_angle_vel[t] = list(map(sum, zip(a, b))) bone = ref_obj.children[0].pose.bones[3] bone.rotation_quaternion = new_bobject.head_angle[t] bone.keyframe_insert(data_path="rotation_quaternion", frame=t * wiggle_slow_factor) #Make wiggle cyclical bone_x_fcurve = ref_obj.children[0].animation_data.action.fcurves.find( 'pose.bones["brd_bone_neck"].rotation_quaternion', index=0) neck_x_cycle = bone_x_fcurve.modifiers.new(type='CYCLES') neck_x_cycle.frame_start = 0 neck_x_cycle.frame_end = wiggle_cycle_length * wiggle_slow_factor bone_y_fcurve = ref_obj.children[0].animation_data.action.fcurves.find( 'pose.bones["brd_bone_neck"].rotation_quaternion', index=1) neck_y_cycle = bone_y_fcurve.modifiers.new(type='CYCLES') neck_y_cycle.frame_start = 0 neck_y_cycle.frame_end = wiggle_cycle_length * wiggle_slow_factor bone_z_fcurve = ref_obj.children[0].animation_data.action.fcurves.find( 'pose.bones["brd_bone_neck"].rotation_quaternion', index=2) neck_z_cycle = bone_z_fcurve.modifiers.new(type='CYCLES') neck_z_cycle.frame_start = 0 neck_z_cycle.frame_end = wiggle_cycle_length * wiggle_slow_factor if filename == 'stanford_bunny': eye = ref_obj.children[0].children[0] t = 0 while t < BLINK_CYCLE_LENGTH: blink_roll = random() if blink_roll < BLINK_CHANCE: eye.keyframe_insert(data_path='scale', frame=t) eye.scale[1] = 0.2 frm = math.floor(BLINK_LENGTH / 2) - 1 eye.keyframe_insert(data_path='scale', frame=t + frm) frm = math.ceil(BLINK_LENGTH / 2) + 1 eye.keyframe_insert(data_path='scale', frame=t + frm) eye.scale[1] = 1 eye.keyframe_insert(data_path='scale', frame=t + BLINK_LENGTH) t += BLINK_LENGTH else: t += 1 #Make blinks cyclical try: eye_fcurve = ref_obj.children[0].children[ 0].animation_data.action.fcurves.find('scale', index=1) cycle = eye_fcurve.modifiers.new(type='CYCLES') cycle.frame_start = 0 cycle.frame_end = BLINK_CYCLE_LENGTH except: #Sometimes a creature goes the whole cycle length without blinking, #in which case, there's no fcurve, so the above block throws an #error. In the end, it's fine if the creature never blinks. It's rare. pass return new_bobject
def add_to_blender(self, **kwargs): super().add_to_blender(**kwargs) ''' Pretty hacky due to the fact that the TexBobject class was created before the SVGBobject class, despite inheritance going the other direction ''' appear_frame = kwargs['appear_frame'] try: name = self.file_name path = os.path.join(SVG_DIR, name) + ".svg" #print(path) previous_curves = [ obj for obj in bpy.data.objects if obj.type == 'CURVE' ] bpy.ops.import_curve.svg(filepath=path) new_curves = [obj for obj in bpy.data.objects if obj.type == 'CURVE' and \ obj not in previous_curves] print(new_curves) LOCAL_SCALE_UP = 260 #Value that makes line height about 1 Blender Unit scale_up = LOCAL_SCALE_UP #* self.size for i, curve in enumerate(new_curves): for spline in curve.data.splines: for point in spline.bezier_points: point.handle_left_type = 'FREE' point.handle_right_type = 'FREE' #This needs to be in a separate loop because moving points before #they're all 'Free' type makes the shape warp. #It makes a cool "disappear in the wind" visual, though. for spline in curve.data.splines: for point in spline.bezier_points: for i in range(len(point.co)): point.co[i] *= scale_up point.handle_left[i] *= scale_up point.handle_right[i] *= scale_up curve.select = True bpy.ops.object.origin_set(type="ORIGIN_GEOMETRY") curve.select = False #for i, curve in enumerate(new_curves): # curve.parent = self.ref_obj # curve.matrix_parent_inverse = curve.parent.matrix_world.inverted() for curve in new_curves: #curve = expression['curves'][i] curve_bobj = bobject.Bobject() print('making bobject') curve_bobj.ref_obj.matrix_local = deepcopy(curve.matrix_local) curve_bobj.ref_obj.parent = self.ref_obj curve.parent = curve_bobj.ref_obj curve.location = [0, 0, 0] #curve.matrix_parent_inverse = curve.parent.matrix_world.inverted() curve_bobj.objects.append(curve) self.subbobjects.append(curve_bobj) curve_bobj.superbobject = self #if expression == self.expressions[0]: bpy.context.scene.objects.unlink(curve) curve_bobj.add_to_blender(appear_frame=appear_frame, animate=False) except: print('No SVG file')
def asymmetrical_inputs(self): cam_bobj, cam_swivel = cam_and_swivel( cam_location=[0, 0, 100], cam_rotation_euler=[0, 0, 0], cam_name="Camera Bobject", swivel_location=[0, 5.1, -2], swivel_rotation_euler=[75 * math.pi / 180, 0, 135 * math.pi / 180], swivel_name='Cam swivel', #control_sun = True ) cam_swivel.add_to_blender(appear_time=-1) cam_bobj.ref_obj.children[0].data.clip_end = 200 rot_start = 78 l_green_time = 80.5 l_back_time = 85.5 spin_time_1 = 83 spins_1 = 5 spin_duration_1 = 3 r_red_time = 90.5 r_back_time = 102.5 spin_time_2 = 100 spins_2 = 5 spin_duration_2 = 3 skin = bpy.data.objects['robertot'] r_inner_ear = bpy.data.objects['inner ear_from microCT'] l_inner_ear = bpy.data.objects['inner ear_from microCT.001'] to_keep = [skin, r_inner_ear, l_inner_ear] for obj in bpy.data.objects: if obj not in to_keep: obj.hide = True obj.hide_render = True mix = skin.material_slots[0].material.node_tree.nodes[ 'Mix Shader'].inputs[0] mix.default_value = 0.9 #Prep inner ear materials slots = r_inner_ear.material_slots v_sys_mats = [ slots[0].material, slots[1].material, slots[2].material, slots[3].material, slots[4].material ] #Set initial state for inner ear materials for mat in v_sys_mats: nodes = mat.node_tree.nodes mix = nodes['Mix Shader'] mix.inputs[0].default_value = 0 #princ = nodes['Principled BSDF'] #color = princ.inputs[0] #color.default_value = [0, 1, 0, 1] #Make separate materials for left inner ear to animate separately for slot in l_inner_ear.material_slots: mat_copy = slot.material.copy() slot.material = mat_copy #Turn left inner ear green and back for slot in l_inner_ear.material_slots: nodes = slot.material.node_tree.nodes color = nodes['Principled BSDF'].inputs[0] initial_color = list(color.default_value) color.keyframe_insert(data_path='default_value', frame=l_green_time * FRAME_RATE) color.default_value = [0, 1, 0, 1] color.keyframe_insert(data_path='default_value', frame=l_green_time * FRAME_RATE + 2 * OBJECT_APPEARANCE_TIME) color.keyframe_insert(data_path='default_value', frame=l_back_time * FRAME_RATE) color.default_value = initial_color color.keyframe_insert(data_path='default_value', frame=l_back_time * FRAME_RATE + 2 * OBJECT_APPEARANCE_TIME) #Turn right inner ear red and back for mat in v_sys_mats: nodes = mat.node_tree.nodes color = nodes['Principled BSDF'].inputs[0] initial_color = list(color.default_value) color.keyframe_insert(data_path='default_value', frame=r_red_time * FRAME_RATE) color.default_value = [1, 0, 0, 1] color.keyframe_insert(data_path='default_value', frame=r_red_time * FRAME_RATE + 2 * OBJECT_APPEARANCE_TIME) color.keyframe_insert(data_path='default_value', frame=r_back_time * FRAME_RATE) color.default_value = initial_color color.keyframe_insert(data_path='default_value', frame=r_back_time * FRAME_RATE + 2 * OBJECT_APPEARANCE_TIME) #Spins skull = bpy.data.objects['Skull_Top'] skull_bobj = bobject.Bobject(objects=[skull]) skull_bobj.add_to_blender(appear_time=0, unhide=False) skull_bobj.move_to(new_angle=[0, 0, spins_1 * 2 * math.pi], start_time=spin_time_1, end_time=spin_time_1 + spin_duration_1) skull_bobj.move_to(new_angle=[ skull_bobj.ref_obj.rotation_euler[0], skull_bobj.ref_obj.rotation_euler[1], skull_bobj.ref_obj.rotation_euler[2] + spins_2 * 2 * math.pi, ], start_time=spin_time_2, end_time=spin_time_2 + spin_duration_2) cam_swivel.move_to( new_angle=[75 * math.pi / 180, 0, 45 * math.pi / 180], start_time=rot_start, end_time=r_red_time) cam_swivel.move_to( new_angle=[75 * math.pi / 180, 0, 135 * math.pi / 180], start_time=r_red_time, end_time=spin_time_2 + spin_duration_2) '''rate = 0.025
def asymmetrical_inputs(self): cam_bobj, cam_swivel = cam_and_swivel( cam_location=[0, 0, 100], cam_rotation_euler=[0, 0, 0], cam_name="Camera Bobject", swivel_location=[0, 5.1, -2], swivel_rotation_euler=[75 * math.pi / 180, 0, 135 * math.pi / 180], swivel_name='Cam swivel', #control_sun = True ) cam_swivel.add_to_blender(appear_time=-1) cam_bobj.ref_obj.children[0].data.clip_end = 200 l_red_time = 115 spin_time = 117.5 spins = 6 spin_duration = 6 r_red_time = 122.5 skin = bpy.data.objects['robertot'] r_inner_ear = bpy.data.objects['inner ear_from microCT'] l_inner_ear = bpy.data.objects['inner ear_from microCT.001'] to_keep = [skin, r_inner_ear, l_inner_ear] for obj in bpy.data.objects: if obj not in to_keep: obj.hide = True obj.hide_render = True mix = skin.material_slots[0].material.node_tree.nodes[ 'Mix Shader'].inputs[0] mix.default_value = 0.9 slots = r_inner_ear.material_slots v_sys_mats = [ slots[0].material, slots[1].material, slots[2].material, slots[3].material, slots[4].material ] #Set initial state for inner ear materials for mat in v_sys_mats: nodes = mat.node_tree.nodes mix = nodes['Mix Shader'] mix.inputs[0].default_value = 0 princ = nodes['Principled BSDF'] color = princ.inputs[0] color.default_value = [0, 1, 0, 1] #Make separate materials for left inner ear to animate separately for slot in l_inner_ear.material_slots: mat_copy = slot.material.copy() slot.material = mat_copy for mat in v_sys_mats: nodes = mat.node_tree.nodes princ = nodes['Principled BSDF'] color = princ.inputs[0] color.keyframe_insert(data_path='default_value', frame=l_red_time * FRAME_RATE) color.default_value = [1, 0, 0, 1] color.keyframe_insert(data_path='default_value', frame=l_red_time * FRAME_RATE + 2 * OBJECT_APPEARANCE_TIME) skull = bpy.data.objects['Skull_Top'] skull_bobj = bobject.Bobject(objects=[skull]) skull_bobj.add_to_blender(appear_time=0, unhide=False) skull_bobj.move_to(new_angle=[0, 0, spins * 2 * math.pi], start_time=spin_time, end_time=spin_time + spin_duration) for slot in l_inner_ear.material_slots: nodes = slot.material.node_tree.nodes color = nodes['Principled BSDF'].inputs[0] color.keyframe_insert(data_path='default_value', frame=r_red_time * FRAME_RATE) color.default_value = [1, 0, 0, 1] color.keyframe_insert(data_path='default_value', frame=r_red_time * FRAME_RATE + 2 * OBJECT_APPEARANCE_TIME) cam_swivel.move_to( new_angle=[75 * math.pi / 180, 0, 45 * math.pi / 180], start_time=110, end_time=127) '''rate = 0.025