CSE 682 Classwork
Role
In this project, I was primarily responsible for procedurally generating the shaking of objects and the flipping of pages. After some preliminary work it was decided that we could keyframe the guts of the page flipping and I would focus on the shaking of our main book.To achieve this goal I produced a script that when loaded into the maya environment, that would allow you to select objects that you would like to shake and then click a shelf button to apply the attributes necessary to gain control of the shaking process.
In addition to the procedural task, I was responsible for some technical support to the group. I compressed the renders of our movie to be shown in class. I also helped with the initial creation of our group website and configured this forumn.
Journal
Week 1
- Formation of group
- Brain Storming of Animation Ideas
- Decided to use web forumn as a central place for ideas
Week 2
- Set up the forumn
- Narrowed down brainstorm ideas
- Read about the principles of animation
Week 3
- Started playing with maya
- Continued research of animation techniques
Week 4
- Played with animating a page turn
Week 5
- Page flipping animation enhanced with Sucheta's help
- Started making attempts at using mel to create effects
Week 6
- Primitive book shaking in place
- Started work on enhancing with a spring system
Week 7
- Completed advance shaking code manipulating the power of randomness
Week 8
- Discarded advance shaking code manipulating the power of randomness
- Re-engineered algorithm to use sin waves to generate the shaking motiion
Week 9
- Added function to control the flapping of the book binding
- Merged randomness back into shaking code for added realism
Week 10
- Assisted in adding final touches to scenes
Source Code
Final Source
/*
* New "Better" Version of createShaker()
*/
global proc createShaker() {
string $nodes[] = selectedNodes("-do");
string $node;
for($node in $nodes) {
string $type[] = {"rotate", "translate"};
string $param[] = {"Weight", "Origin", "Amplitude", "Frequency"};
string $axis[] = {"X", "Y", "Z"};
string $t, $p, $a;
/*
* Add Attributes that allow for the modification of a node's rotations and
* translations.
*/
for($t in $type) {
for($p in $param) {
for($a in $axis) {
string $attr = $t + $p + $a;
/*
* Only add attribute if necessary.
*/
if(!attributeExists($attr, $node)) addAttr -ln $attr -dv 0 $node;
/*
* Make origin attributes equal to the current transformation
* attributes.
*/
if($p == "Origin") {
setAttr($node + "." + $attr, getAttr($node + "." + $t + $a));
}
/*
* Make frequency default to something reasonable.
*/
else if($p == "Frequency") {
setAttr($node + "." + $attr, 1);
}
}
}
}
/*
* Add expression to control object.
*
* Note: There needs to be a check to make sure an object isn't "shaked"
* twice.
*/
expression("-s", "updateShaker(\"" + $node + "\", frame);", "-ae", 1);
}
}
/*
* New "Even Better" Version of updateShaker(string, int)
*/
global proc int updateShaker(string $node, int $frame) {
string $type[] = {"rotate", "translate"};
string $axis[] = {"X", "Y", "Z"};
string $t, $p, $a;
float $factor = deg_to_rad(360) / 24;
for($t in $type) {
for($a in $axis) {
string $val_str = $node + "." + $t + $a;
string $org_str = $node + "." + $t + "Origin" + $a;
string $amp_str = $node + "." + $t + "Amplitude" + $a;
string $frq_str = $node + "." + $t + "Frequency" + $a;
string $weight_str = $node + "." + $t + "Weight" + $a;
float $val = getAttr($val_str);
float $org = getAttr($org_str);
float $amp = getAttr($amp_str);
float $frq = getAttr($frq_str);
float $off = $amp * sin($frame * $factor * $frq);
float $weight = getAttr($weight_str);
if($amp != 0) {
// Add Jitter to break oscillations
$off = (1 - $weight) * $off + $weight * rand(-$amp, $amp);
}
setAttr($val_str, $org + $off);
}
}
return 1;
}
global proc extraShake(int $frame) {
if($frame > 1684 && $frame < 1804) {
float $intensity = 1 - abs($frame - 1744)/60;
float $rotate1 = $intensity * rand(0, 5);
float $rotate2 = $intensity * rand(0, 5) + $rotate1;
setAttr("joint2.rotateZ", $rotate2);
setAttr("joint1.rotateZ", -$rotate1);
setAttr("joint1.translateY", 1.65 * sin(deg_to_rad($rotate1)) + 6.231);
}
else if($frame = 1804) {
setAttr("joint1.translateY", 6.231);
setAttr("joint1.rotateZ", 0);
}
}
Early Attempt [Randomness]
/*
* New "Better" Version of createShaker()
*/
global proc createShaker() {
string $nodes[] = selectedNodes("-do");
string $node;
for($node in $nodes) {
string $type[] = {"rotate", "translate"};
string $param[] = {"Origin", "Offset", "Intensity", "Frequency"};
string $axis[] = {"X", "Y", "Z"};
string $t, $p, $a;
/*
* Add Attributes that allow for the modification of a node's rotations and
* translations.
*/
for($t in $type) {
for($p in $param) {
for($a in $axis) {
string $attr = $t + $p + $a;
/*
* Only add attribute if necessary.
*/
if(!attributeExists($attr, $node)) addAttr -ln $attr -dv 0 $node;
/*
* Make origin attributes equal to the current transformation
* attributes.
*/
if($p == "Origin") {
setAttr($node + "." + $attr, getAttr($node + "." + $t + $a));
}
}
}
}
/*
* Add expression to control object.
*
* Note: There needs to be a check to make sure an object isn't "shaked"
* twice.
*/
expression("-s", "updateShaker(\"" + $node + "\");", "-ae", 1);
}
}
/*
* New "Better" Version of updateShaker(string)
*/
global proc int updateShaker(string $node) {
string $type[] = {"rotate", "translate"};
string $axis[] = {"X", "Y", "Z"};
string $t, $p, $a;
for($t in $type) {
for($a in $axis) {
string $val_str = $node + "." + $t + $a;
string $off_str = $node + "." + $t + "Offset" + $a;
string $org_str = $node + "." + $t + "Origin" + $a;
string $int_str = $node + "." + $t + "Intensity" + $a;
string $frq_str = $node + "." + $t + "Frequency" + $a;
float $val = getAttr($val_str);
float $off = getAttr($off_str);
float $org = getAttr($org_str);
float $int = getAttr($int_str);
float $frq = getAttr($frq_str);
float $delta = $org + $off - $val;
if($int != 0) {
// Shaker is active since intensity != 0
if(abs($delta) < .01) {
setAttr($off_str, rand(-$int, $int));
}
else {
// More than .01 from destination. Go halfway there.
$val += ($delta)/2;
}
setAttr($val_str, $val);
}
}
}
return 1;
}