Last active
August 29, 2015 14:15
-
-
Save HansNewbie/0fc560d134fa9181f2b7 to your computer and use it in GitHub Desktop.
CS3242
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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