# Use noise to animate some objects in sphere pattern import sys, code, random, os, math, bpy, canvas, colorsys from math import pi, sin, cos, ceil from mathutils import Vector, Quaternion from random import TWOPI
sys.path.append(os.path.dirname(os.path.dirname(__file__))) import helpers
class Sphere(canvas.Canvas):
def render(self): diameter = 4.0 sz = 2.125 / diameter base_object = helpers.infer_primitive(random.choice(self.PRIMITIVES), location = (100, 100, 100), radius=sz) latitude = 16 longitude = latitude * 2 invlatitude = 1.0 / (latitude - 1) invlongitude = 1.0 / (longitude - 1) iprc = 0.0 jprc = 0.0 phi = 0.0 theta = 0.0 invfcount = 1.0 / (self.NUMBER_OF_FRAMES - 1) # Animate center of the sphere. center = Vector((0.0, 0.0, 0.0)) startcenter = Vector((0.0, -4.0, 0.0)) stopcenter = Vector((0.0, 4.0, 0.0)) # Rotate cubes around the surface of the sphere. pt = Vector((0.0, 0.0, 0.0)) rotpt = Vector((0.0, 0.0, 0.0)) # Change the axis of rotation for the point. baseaxis = Vector((0.0, 1.0, 0.0)) axis = Vector((0.0, 0.0, 0.0)) # Slerp between two rotations for each cube. startrot = Quaternion((0.0, 1.0, 0.0), pi) stoprot = Quaternion((1.0, 0.0, 0.0), pi * 1.5) currot = Quaternion() for i in range(0, latitude, 1): iprc = i * invlatitude phi = pi * (i + 1) * invlatitude rad = 0.01 + sz * abs(sin(phi)) * 0.99 pt.z = cos(phi) * diameter for j in range(0, longitude, 1): jprc = j * invlongitude theta = TWOPI * j / longitude pt.y = center.y + sin(phi) * sin(theta) * diameter pt.x = center.x + sin(phi) * cos(theta) * diameter current = helpers.duplicate_object(base_object) current.location = pt current.name = 'Object ({0:0>2d}, {1:0>2d})'.format(i, j) current.data.name = 'Mesh ({0:0>2d}, {1:0>2d})'.format(i, j) current.rotation_euler = (0.0, phi, theta) helpers.assign_material(current, helpers.random_material(self.MATERIALS_NAMES)) axis = self.vecrotatex(theta, baseaxis) currot = startrot center = startcenter for f in range(0, self.NUMBER_OF_FRAMES, 1): fprc = f / (self.NUMBER_OF_FRAMES - 1) osc = abs(sin(TWOPI * fprc)) bpy.context.scene.frame_set(f) center = startcenter.lerp(stopcenter, osc) current.location = helpers.rotate_vector(TWOPI * fprc, axis, pt) current.keyframe_insert(data_path='location') currot = startrot.slerp(stoprot, jprc * fprc) current.rotation_euler = currot.to_euler() current.keyframe_insert(data_path='rotation_euler') # Rotate vector by a given angle from a starting vector and return a new vector # Trigonometry: # x' = x cos θ − y sin θ # y' = x sin θ + y cos θ def vecrotatex(self, angle, vin): vout = Vector((0.0, 0.0, 0.0)) vout.x = vin.x vout.y = cos(angle) * vin.y - sin(angle) * vin.z vout.z = cos(angle) * vin.z + sin(angle) * vin.y return vout