Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
CS3242
from maya import cmds
from math import *
def euler(x, dt, dxdt):
x_new = [0, 0, 0]
# TODO: implement the Euler method here
for i in range(0,3):
x_new[i] = x[i] + dt*dxdt[i]
return x_new
def make_state(x):
return [x]
def get_location(state):
return state[0]
def compute_circle_derivatives(state, angular_velocity):
x = get_location(state)
dxdt = [0, 0, 0]
# TODO: compute the derivative dxdt from the current location and the angular velocity
###### Cheating way by getting next position
radius = sqrt(pow(x[0], 2) + pow(x[1], 2))
angle = atan2(x[1], x[0])
dxdt[0] = radius * cos(angle+angular_velocity) - x[0]
dxdt[1] = radius * sin(angle+angular_velocity) - x[1]
######
###### Proper method by derivation
# This will not be perfect circle but rather spiral because lim (t -> 0) is not fulfilled
# Set parameter time step to be smaller to achieve this
dxdt[0] = -1 * x[1] * angular_velocity
dxdt[1] = x[0] * angular_velocity
######
return dxdt
def simulate_circle(state, angular_velocity, dt):
x = get_location(state)
dxdt = compute_circle_derivatives(state, angular_velocity)
x = euler(x, dt, dxdt)
return make_state(x)
def maya_move(angular_velocity, time_step):
objects = cmds.ls(sl=True)
if objects == []:
print('* Please select at least an object.')
return
trajectory = cmds.ls('trajectory')
for i, o in enumerate(objects):
x = cmds.getAttr(o + '.translateX')
y = cmds.getAttr(o + '.translateY')
z = cmds.getAttr(o + '.translateZ')
loc = [x, y, z]
state = make_state(loc)
state = simulate_circle(state, angular_velocity, time_step)
old_loc = loc
loc = get_location(state)
cmds.select(o)
cmds.move(loc[0], loc[1], loc[2])
# draw trajectory for the first object
if i == 0:
if trajectory == []:
cv = cmds.curve(point=[old_loc, loc], degree=1)
cmds.rename(cv, 'trajectory')
else:
cmds.curve('trajectory', point=[loc], degree=1, append=True)
# keep all objects selected
cmds.select(objects)
maya_move(0.1 * pi, 1.0)
from maya import cmds
from math import *
def euler(x, dt, dxdt):
x_new = [0, 0, 0]
# TODO: implement euler method here
for i in range(0, 3):
x_new[i] = x[i] + dt*dxdt[i]
return x_new
def compute_force_derivatives(force, mass, velocity):
dxdt = [0, 0, 0]
dvdt = [0, 0, 0]
# TODO: compute location derivative dxdt
for i in range(0,3):
dxdt[i] = velocity[i]
# TODO: compute velocity derivative dvdt
for i in range(0,3):
dvdt[i] = force[i]/mass
return [dxdt, dvdt]
def compute_force(const, mass, velocity):
gravity = const['gravity']
viscous_drag = const['viscous_drag']
force = [0, 0, 0]
# TODO: compute total force
# You can ignore the viscous drag
force[1] = -1 * mass * gravity
return force
def make_state(x, v):
return [x, v]
def get_location(state):
return state[0]
def get_velocity(state):
return state[1]
def simulate_force(state, const, mass, dt):
x = get_location(state)
v = get_velocity(state)
# TODO: compute force, derivatives, and make an Euler step on the state
force = compute_force(const, mass, v)
state = compute_force_derivatives(force, mass, v)
# TODO: make one step Euler
x = euler(x, dt, state[0])
v = euler(v, dt, state[1])
return make_state(x, v)
def maya_reset(params):
initial_location = params['initial_location']
initial_velocity = params['initial_velocity']
objects = cmds.ls(sl=True)
if objects == []:
print('* Please select at least an object.')
return
for i, o in enumerate(objects):
cmds.select(o)
if not cmds.attributeQuery('velocityX', n=o, exists=True):
cmds.addAttr(longName='velocityX', defaultValue=initial_velocity[0])
cmds.addAttr(longName='velocityY', defaultValue=initial_velocity[1])
cmds.addAttr(longName='velocityZ', defaultValue=initial_velocity[2])
else:
cmds.setAttr(o + '.velocityX', initial_velocity[0])
cmds.setAttr(o + '.velocityY', initial_velocity[1])
cmds.setAttr(o + '.velocityZ', initial_velocity[2])
cmds.move(initial_location[0], initial_location[1], initial_location[2])
cmds.select(objects)
print 'Attributes reset.'
def maya_create_destination(const, params):
# destination is when the object touches the ground again
# assume no viscous drag
gravity = const['gravity']
v = params['initial_velocity']
# TODO: compute the time the particle touches the ground
t = 0
x = v[0] * t
z = v[2] * t
cube = cmds.polyCube(h=2, w=2, d=2)
cmds.select(cube)
cmds.move(x, 0.0, z)
def maya_move(const, params, time_step):
mass = params['mass']
initial_velocity = params['initial_velocity']
objects = cmds.ls(sl=True)
if objects == []:
print('* Please select at least an object.')
return
trajectory = cmds.ls('trajectory')
for i, o in enumerate(objects):
cmds.select(o)
x = cmds.getAttr(o + '.translateX')
y = cmds.getAttr(o + '.translateY')
z = cmds.getAttr(o + '.translateZ')
if not cmds.attributeQuery('velocityX', n=o, exists=True):
cmds.addAttr(longName='velocityX', defaultValue=initial_velocity[0])
cmds.addAttr(longName='velocityY', defaultValue=initial_velocity[1])
cmds.addAttr(longName='velocityZ', defaultValue=initial_velocity[2])
vx = cmds.getAttr(o + '.velocityX')
vy = cmds.getAttr(o + '.velocityY')
vz = cmds.getAttr(o + '.velocityZ')
loc = [x, y, z]
vel = [vx, vy, vz]
state = make_state(loc, vel)
state = simulate_force(state, const, mass, time_step)
old_loc = loc
loc = get_location(state)
cmds.move(loc[0], loc[1], loc[2])
vel = get_velocity(state)
cmds.setAttr(o + '.velocityX', vel[0])
cmds.setAttr(o + '.velocityY', vel[1])
cmds.setAttr(o + '.velocityZ', vel[2])
# draw trajectory for the first object
if i == 0:
if trajectory == []:
cv = cmds.curve(point=[old_loc, loc], degree=1)
cmds.rename(cv, 'trajectory')
else:
cmds.curve('trajectory', point=[loc], degree=1, append=True)
# keep all objects selected
cmds.select(objects)
# NOTE: remember to call reset every time initial velocity is changed.
const = {'gravity' : 0.98, 'viscous_drag' : 0.0}
params = {'mass' : 1, 'initial_location' : [0, 0, 0], 'initial_velocity' : [5, 5, 0.0]}
maya_create_destination(const, params)
maya_reset(params)
maya_move(const, params, 1.0)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment