Posted on 2010-09-23 17:47:01

Rigging a Book Part 1

So I started rigging a book for Maya. A book, that plays a big role in our short. I found out the geometry has li'l issues so while our modeler is fixing it, I'll write about what I plan to do.

You see, we'll have the book do fast and slow page turns. A character will also peruse parts of the page which would require a lot of fine detail controls that animator's would need. I scoured the net but couldn't find much info, aside from these, that are worth mentioning:

  1. Page Turn Animation
  2. Cinema 4D book page rigging video tutorial

So I set out to develop my own book rig system. One of the things I wanted to have was an attribute that animators could scrub to make each page flip either forwards or backwards. The problem was how to make the page flipping flip with a drag or have it lead. I knew this would have to be accomplished by something that works like blendshapes but on the attribute level instead of components. My plan is to have a bunch of joints' rotation and translation values blend between three different joint hierarchies. One hierarchy would be the pose of the page when it's lying on the back side. Another would be when it's flipping in the air. Lastly, there'll be one to serve as it's pose for it lying on the front side.

The blending between multiply hierarchies can easily be done using constraints. But I was thinking of having a book with a number of pages, around 10-25, and on each there'll be another number of joints. Putting constraints on that would be crazy and too laggy for animators.

I wrote a script that would not only set up the blend, it'll also do so without using any constraints. It'll use a terribly more process efficient node, the blendWeighted node.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
/*

// =============
// Example Usage
// =============

$controller = "nurbsCircle1";

select -r "skin";
select -hi;
$skin = `ls -sl`;

select -r "left";
select -hi;
$left = `ls -sl`;

select -r "middle";
select -hi;
$middle = `ls -sl`;

select -r "right";
select -hi;
$right = `ls -sl`;

// ==== actual command ==== //
pagesetup $controller $left $middle $right $skin;

*/

global proc pagesetup(string $controller, string $left[], string $middle[],
string $right[], string $skin[]) {
    // check if the attribtue is correct
    if (!`attributeExists "page" $controller`) {
        addAttr -ln "page"  -at double  -min -10 -max 10 -dv 0 $controller;
        setAttr -e-keyable true ($controller+".page");
    }
    for ($i = 0; $i<`size $skin`; $i++) {
        // create blendweights
        $rx = `createNode blendWeighted -n ($skin[$i]+"rx")`;
        $ry = `createNode blendWeighted -n ($skin[$i]+"ry")`;
        $rz = `createNode blendWeighted -n ($skin[$i]+"rz")`;
        $tx = `createNode blendWeighted -n ($skin[$i]+"tx")`;
        $ty = `createNode blendWeighted -n ($skin[$i]+"ty")`;
        $tz = `createNode blendWeighted -n ($skin[$i]+"tz")`;

        // setup blendweights (must do this to work)
        setAttr ($rx+".w[0]") 0;
        setAttr ($ry+".w[0]") 0;
        setAttr ($rz+".w[0]") 0;
        setAttr ($tx+".w[0]") 0;
        setAttr ($ty+".w[0]") 0;
        setAttr ($tz+".w[0]") 0;
        setAttr ($rx+".w[1]") 0;
        setAttr ($ry+".w[1]") 0;
        setAttr ($rz+".w[1]") 0;
        setAttr ($tx+".w[1]") 0;
        setAttr ($ty+".w[1]") 0;
        setAttr ($tz+".w[1]") 0;
        setAttr ($rx+".w[2]") 0;
        setAttr ($ry+".w[2]") 0;
        setAttr ($rz+".w[2]") 0;
        setAttr ($tx+".w[2]") 0;
        setAttr ($ty+".w[2]") 0;
        setAttr ($tz+".w[2]") 0;

        setAttr ($rx+".i[0]") 0;
        setAttr ($ry+".i[0]") 0;
        setAttr ($rz+".i[0]") 0;
        setAttr ($tx+".i[0]") 0;
        setAttr ($ty+".i[0]") 0;
        setAttr ($tz+".i[0]") 0;
        setAttr ($rx+".i[1]") 0;
        setAttr ($ry+".i[1]") 0;
        setAttr ($rz+".i[1]") 0;
        setAttr ($tx+".i[1]") 0;
        setAttr ($ty+".i[1]") 0;
        setAttr ($tz+".i[1]") 0;
        setAttr ($rx+".i[2]") 0;
        setAttr ($ry+".i[2]") 0;
        setAttr ($rz+".i[2]") 0;
        setAttr ($tx+".i[2]") 0;
        setAttr ($ty+".i[2]") 0;
        setAttr ($tz+".i[2]") 0;

        // connect target joints to blendweights
        connectAttr ($left[$i]+".rx") ($rx+".i[0]");
        connectAttr ($left[$i]+".ry") ($ry+".i[0]");
        connectAttr ($left[$i]+".rz") ($rz+".i[0]");
        connectAttr ($middle[$i]+".rx") ($rx+".i[1]");
        connectAttr ($middle[$i]+".ry") ($ry+".i[1]");
        connectAttr ($middle[$i]+".rz") ($rz+".i[1]");
        connectAttr ($right[$i]+".rx") ($rx+".i[2]");
        connectAttr ($right[$i]+".ry") ($ry+".i[2]");
        connectAttr ($right[$i]+".rz") ($rz+".i[2]");

        connectAttr ($left[$i]+".tx") ($tx+".i[0]");
        connectAttr ($left[$i]+".ty") ($ty+".i[0]");
        connectAttr ($left[$i]+".tz") ($tz+".i[0]");
        connectAttr ($middle[$i]+".tx") ($tx+".i[1]");
        connectAttr ($middle[$i]+".ty") ($ty+".i[1]");
        connectAttr ($middle[$i]+".tz") ($tz+".i[1]");
        connectAttr ($right[$i]+".tx") ($tx+".i[2]");
        connectAttr ($right[$i]+".ty") ($ty+".i[2]");
        connectAttr ($right[$i]+".tz") ($tz+".i[2]");

        // connect blendweights to their respective connections
        connectAttr ($rx+".o") ($skin[$i]+".rx");
        connectAttr ($ry+".o") ($skin[$i]+".ry");
        connectAttr ($rz+".o") ($skin[$i]+".rz");
        connectAttr ($tx+".o") ($skin[$i]+".tx");
        connectAttr ($ty+".o") ($skin[$i]+".ty");
        connectAttr ($tz+".o") ($skin[$i]+".tz");

        // set driven keys on blendweights

        setDrivenKeyframe -itt "flat" -ott "flat" -cd ($controller+".page") -dv -10 -v 1 ($rx+".w[0]");
        setDrivenKeyframe -itt "flat" -ott "flat" -cd ($controller+".page") -dv -10 -v 1 ($ry+".w[0]");
        setDrivenKeyframe -itt "flat" -ott "flat" -cd ($controller+".page") -dv -10 -v 1 ($rz+".w[0]");
        setDrivenKeyframe -itt "flat" -ott "flat" -cd ($controller+".page") -dv -10 -v 0 ($rx+".w[1]");
        setDrivenKeyframe -itt "flat" -ott "flat" -cd ($controller+".page") -dv -10 -v 0 ($ry+".w[1]");
        setDrivenKeyframe -itt "flat" -ott "flat" -cd ($controller+".page") -dv -10 -v 0 ($rz+".w[1]");
        setDrivenKeyframe -itt "flat" -ott "flat" -cd ($controller+".page") -dv -10 -v 0 ($rx+".w[2]");
        setDrivenKeyframe -itt "flat" -ott "flat" -cd ($controller+".page") -dv -10 -v 0 ($ry+".w[2]");
        setDrivenKeyframe -itt "flat" -ott "flat" -cd ($controller+".page") -dv -10 -v 0 ($rz+".w[2]");

        setDrivenKeyframe -itt "flat" -ott "flat" -cd ($controller+".page") -dv 0 -v 0 ($rx+".w[0]");
        setDrivenKeyframe -itt "flat" -ott "flat" -cd ($controller+".page") -dv 0 -v 0 ($ry+".w[0]");
        setDrivenKeyframe -itt "flat" -ott "flat" -cd ($controller+".page") -dv 0 -v 0 ($rz+".w[0]");
        setDrivenKeyframe -itt "flat" -ott "flat" -cd ($controller+".page") -dv 0 -v 1 ($rx+".w[1]");
        setDrivenKeyframe -itt "flat" -ott "flat" -cd ($controller+".page") -dv 0 -v 1 ($ry+".w[1]");
        setDrivenKeyframe -itt "flat" -ott "flat" -cd ($controller+".page") -dv 0 -v 1 ($rz+".w[1]");
        setDrivenKeyframe -itt "flat" -ott "flat" -cd ($controller+".page") -dv 0 -v 0 ($rx+".w[2]");
        setDrivenKeyframe -itt "flat" -ott "flat" -cd ($controller+".page") -dv 0 -v 0 ($ry+".w[2]");
        setDrivenKeyframe -itt "flat" -ott "flat" -cd ($controller+".page") -dv 0 -v 0 ($rz+".w[2]");

        setDrivenKeyframe -itt "flat" -ott "flat" -cd ($controller+".page") -dv 10 -v 0 ($rx+".w[0]");
        setDrivenKeyframe -itt "flat" -ott "flat" -cd ($controller+".page") -dv 10 -v 0 ($ry+".w[0]");
        setDrivenKeyframe -itt "flat" -ott "flat" -cd ($controller+".page") -dv 10 -v 0 ($rz+".w[0]");
        setDrivenKeyframe -itt "flat" -ott "flat" -cd ($controller+".page") -dv 10 -v 0 ($rx+".w[1]");
        setDrivenKeyframe -itt "flat" -ott "flat" -cd ($controller+".page") -dv 10 -v 0 ($ry+".w[1]");
        setDrivenKeyframe -itt "flat" -ott "flat" -cd ($controller+".page") -dv 10 -v 0 ($rz+".w[1]");
        setDrivenKeyframe -itt "flat" -ott "flat" -cd ($controller+".page") -dv 10 -v 1 ($rx+".w[2]");
        setDrivenKeyframe -itt "flat" -ott "flat" -cd ($controller+".page") -dv 10 -v 1 ($ry+".w[2]");
        setDrivenKeyframe -itt "flat" -ott "flat" -cd ($controller+".page") -dv 10 -v 1 ($rz+".w[2]");

        setDrivenKeyframe -itt "flat" -ott "flat" -cd ($controller+".page") -dv -10 -v 1 ($tx+".w[0]");
        setDrivenKeyframe -itt "flat" -ott "flat" -cd ($controller+".page") -dv -10 -v 1 ($ty+".w[0]");
        setDrivenKeyframe -itt "flat" -ott "flat" -cd ($controller+".page") -dv -10 -v 1 ($tz+".w[0]");
        setDrivenKeyframe -itt "flat" -ott "flat" -cd ($controller+".page") -dv -10 -v 0 ($tx+".w[1]");
        setDrivenKeyframe -itt "flat" -ott "flat" -cd ($controller+".page") -dv -10 -v 0 ($ty+".w[1]");
        setDrivenKeyframe -itt "flat" -ott "flat" -cd ($controller+".page") -dv -10 -v 0 ($tz+".w[1]");
        setDrivenKeyframe -itt "flat" -ott "flat" -cd ($controller+".page") -dv -10 -v 0 ($tx+".w[2]");
        setDrivenKeyframe -itt "flat" -ott "flat" -cd ($controller+".page") -dv -10 -v 0 ($ty+".w[2]");
        setDrivenKeyframe -itt "flat" -ott "flat" -cd ($controller+".page") -dv -10 -v 0 ($tz+".w[2]");

        setDrivenKeyframe -itt "flat" -ott "flat" -cd ($controller+".page") -dv 0 -v 0 ($tx+".w[0]");
        setDrivenKeyframe -itt "flat" -ott "flat" -cd ($controller+".page") -dv 0 -v 0 ($ty+".w[0]");
        setDrivenKeyframe -itt "flat" -ott "flat" -cd ($controller+".page") -dv 0 -v 0 ($tz+".w[0]");
        setDrivenKeyframe -itt "flat" -ott "flat" -cd ($controller+".page") -dv 0 -v 1 ($tx+".w[1]");
        setDrivenKeyframe -itt "flat" -ott "flat" -cd ($controller+".page") -dv 0 -v 1 ($ty+".w[1]");
        setDrivenKeyframe -itt "flat" -ott "flat" -cd ($controller+".page") -dv 0 -v 1 ($tz+".w[1]");
        setDrivenKeyframe -itt "flat" -ott "flat" -cd ($controller+".page") -dv 0 -v 0 ($tx+".w[2]");
        setDrivenKeyframe -itt "flat" -ott "flat" -cd ($controller+".page") -dv 0 -v 0 ($ty+".w[2]");
        setDrivenKeyframe -itt "flat" -ott "flat" -cd ($controller+".page") -dv 0 -v 0 ($tz+".w[2]");

        setDrivenKeyframe -itt "flat" -ott "flat" -cd ($controller+".page") -dv 10 -v 0 ($tx+".w[0]");
        setDrivenKeyframe -itt "flat" -ott "flat" -cd ($controller+".page") -dv 10 -v 0 ($ty+".w[0]");
        setDrivenKeyframe -itt "flat" -ott "flat" -cd ($controller+".page") -dv 10 -v 0 ($tz+".w[0]");
        setDrivenKeyframe -itt "flat" -ott "flat" -cd ($controller+".page") -dv 10 -v 0 ($tx+".w[1]");
        setDrivenKeyframe -itt "flat" -ott "flat" -cd ($controller+".page") -dv 10 -v 0 ($ty+".w[1]");
        setDrivenKeyframe -itt "flat" -ott "flat" -cd ($controller+".page") -dv 10 -v 0 ($tz+".w[1]");
        setDrivenKeyframe -itt "flat" -ott "flat" -cd ($controller+".page") -dv 10 -v 1 ($tx+".w[2]");
        setDrivenKeyframe -itt "flat" -ott "flat" -cd ($controller+".page") -dv 10 -v 1 ($ty+".w[2]");
        setDrivenKeyframe -itt "flat" -ott "flat" -cd ($controller+".page") -dv 10 -v 1 ($tz+".w[2]");
    }
}

When you use this, you'll end up with the $skinjoints following the three other sets of joints. But since, we weren't using any constraints, it's so much faster than you'd expect. Tomorrow, I'll write about the next step. The goal is to have the $skinjoints control a page looking mesh. But this mesh won't be the actual page. It'll only serve as the "house" where we'll put clusters that'll control the actual mesh.

doddy
2012-02-03 17:18:48

It's good tutorial.

gopimahanthi
2012-06-12 13:24:43

thanks for tutorial... its really nice...

[nickname]
2013-03-31 05:57:49.571590

awesome rig man Thanks

ho
2013-11-02 00:27:45.392810

wheres da download?

zyenne
2014-10-15 13:53:39.681130

Pls pls pls do a tutorial? Love your work, but don't quite get your instructions here.

custom
2018-09-17 13:46:53.064160

Indian http://metropoliscomix.com/ tablets for women .