# Commits

committed 1e728a7

Tutorial 6: Hierarchy code finished.

• Participants
• Parent commits 8aeaa2e
• Branches default

# File Documents/Positioning/Tutorial 06.xml

`         <para>This is functional, but not particularly flexible; the series of transforms is baked`
`             into the shader. It is also not particularly fast, what with having to do four matrix`
`             multiplications, per vertex.</para>`
`-        <para>Matrix math gives us an opportunity, however. Matrix multiplication is not`
`-            commutative, so the order of operations cannot be changed. The usual grouping is this: <inlineequation>`
`+        <para>Matrix math gives us an optimization. Matrix math is not commutative: <inlineequation>`
`+                <mathphrase>S*R</mathphrase>`
`+            </inlineequation> is not the same as <inlineequation>`
`+                <mathphrase>R*S</mathphrase>`
`+            </inlineequation>. However, it <emphasis>is</emphasis> associative: <inlineequation>`
`+                <mathphrase>(S*R)*T</mathphrase>`
`+            </inlineequation> is the same as <inlineequation>`
`+                <mathphrase>S*(R*T)</mathphrase>`
`+            </inlineequation>. The usual grouping for vertex transformation is this: <inlineequation>`
`                 <mathphrase>Final = C*(S*(R*(T*position)))</mathphrase>`
`             </inlineequation>. But this can easily be regrouped as: <inlineequation>`
`                 <mathphrase>Final = (((C*S)*R)*T)*position</mathphrase>`
`             </inlineequation>.</para>`
`         <para>This would in fact be slower for the shader to compute, since full matrix-to-matrix`
`-            multiplication is quite slow. But the quantity <inlineequation>`
`+            multiplication is much slower than matrix-to-vector multiplication. But the combined`
`+            matrix <inlineequation>`
`                 <mathphrase>(((C*S)*R)*T)</mathphrase>`
`             </inlineequation> is <emphasis>fixed</emphasis> for all of a given object's vertices.`
`             This can be computed on the CPU, and all we have to do is upload a single matrix to`
`-            OpenGL.</para>`
`+            OpenGL. And since we're already uploading a matrix to OpenGL for each object we render,`
`+            this changes nothing about the overall performance characteristics of the`
`+            rendering.</para>`
`         <para><emphasis>This</emphasis> is one of the main reasons matrices are used. You can have a`
`             transformation sequence with dozens of component transformations, and yet all it takes`
`             for the GPU to process this is a single vector/matrix multiplication.</para>`
`         <section>`
`             <title>Order of Transforms</title>`
`             <para>As previously stated, matrix multiplication is not commutative. This means that`
`-                the combined transform S*T is not the same as T*S. Let us explore this further. This`
`-                is what these two composite transform matrices look like:</para>`
`+                the combined transform <inlineequation>`
`+                    <mathphrase>S*T</mathphrase>`
`+                </inlineequation> is not the same as <inlineequation>`
`+                    <mathphrase>T*S</mathphrase>`
`+                </inlineequation>. Let us explore this further. This is what these two composite`
`+                transform matrices look like:</para>`
`             <!--TODO: Show T, S, S*T and T*S.-->`
`-            <para>The transform S*T actually scales the translation part of the resulting matrix.`
`-                This means that the vertices will not just get farther from each other, but farther`
`+            <para>The transform <inlineequation>`
`+                    <mathphrase>S*T</mathphrase>`
`+                </inlineequation> actually scales the translation part of the resulting matrix. This`
`+                means that the vertices will not just get farther from each other, but farther`
`                     <emphasis>from the origin</emphasis> of the destination space. It is the`
`                 difference between these two transforms:</para>`
`             <!--TODO: Show what the two transforms actually look like.-->`
`             <para>If you think about the order of operations, this makes sense. Even though one can`
`-                think of the combined transform S*T as a single transform, it is ultimately a`
`-                composite operation. The transformation T happens first; the object is translated`
`-                into a new position.</para>`
`+                think of the combined transform <inlineequation>`
`+                    <mathphrase>S*T</mathphrase>`
`+                </inlineequation> as a single transform, it is ultimately a composite operation. The`
`+                transformation T happens first; the object is translated into a new position.</para>`
`             <para>What you must understand is that something special happens between S and T.`
`                 Namely, that S is now being applied to positions that are not from model space (the`
`                 space the original vertices were in), but are in <emphasis>post translation`
`                 Remember: a matrix, even a translation matrix, defines a full-fledged coordinate`
`                 system.</para>`
`             <para>So S now acts on the T-space position of the vertices. T-space has an origin,`
`-                defined by the matrix T. So the scaling matrix S will scale the points away from the`
`-                origin point in T-space. Since what you (probably) actually wanted was to scale the`
`-                points away from the origin point in <emphasis>model space</emphasis>, S needs to`
`-                come first.</para>`
`+                defined by the matrix T. A scaling transformation matrix performs scaling based on`
`+                the origin point in the space of the vertices being scaled. So the scaling matrix S`
`+                will scale the points away from the origin point in T-space. Since what you`
`+                (probably) actually wanted was to scale the points away from the origin point in`
`+                    <emphasis>model space</emphasis>, S needs to come first.</para>`
`             <para>Rotation (orientation) matrices have the same issue. The orientation is always`
`                 local to the origin in the current space of the positions. So a rotation matrix must`
`                 happen before the translation matrix. Scales generally should happen before`
`                 orientation; if they happen afterwards, then the scale will be relative to the`
`                     <emphasis>new</emphasis> axis orientation, not the model-space one. This is fine`
`                 if it is a uniform scale, but a non-uniform scale will be problematic.</para>`
`+            <para>There are reasons to put a translation matrix first. If the model-space origin is`
`+                not the point that you wish to rotate or scale around, then you will need to perform`
`+                the translation first, then apply a scale or rotation. Doing this multiple times can`
`+                allow you to scale and rotate about two completely different points. However, this`
`+                gets progressively more difficult, as each new translation needs to be based on the`
`+                space of the rotated or scaled points.</para>`
`         </section>`
`         <section>`
`             <title>Hierarchical Models</title>`
`-            <para/>`
`+            <para>Successive transforms allow us to create a hierarchy of transformations </para>`
`+        </section>`
`+    </section>`
`+    <section>`
`+        <title>In Review</title>`
`+        <para/>`
`+        <section>`
`+            <title>Further Study</title>`
`+            <para>Try doing these things with the given programs.</para>`
`+            <itemizedlist>`
`+                <listitem>`
`+                    <para>Reverse the order of rotations on the wrist in the Hierarchy tutorial.`
`+                        Note how this affects the ability to adjust the wrist.</para>`
`+                </listitem>`
`+            </itemizedlist>`
`         </section>`
`     </section>`
`     <section>`

# File Documents/Tutorial Documents.xpr

`                         <scenarioAssociation-array>`
`                             <scenarioAssociation>`
`                                 <field name="name">`
`-                                    <String xml:space="preserve">Tutorial to Printable PDF</String>`
`+                                    <String xml:space="preserve">Docbook HTML</String>`
`                                 </field>`
`                                 <field name="type">`
`                                     <String xml:space="preserve">XSL</String>`
`                                 </field>`
`                                 <field name="url">`
`-                                    <String xml:space="preserve">Tutorials.xml</String>`
`+                                    <String xml:space="preserve">Positioning/Tutorial%2006.xml</String>`
`                                 </field>`
`                             </scenarioAssociation>`
`                             <scenarioAssociation>`
`                                     <String xml:space="preserve">XSL</String>`
`                                 </field>`
`                                 <field name="url">`
`-                                    <String xml:space="preserve">Tutorials.html</String>`
`+                                    <String xml:space="preserve">Positioning/Tutorial%2004.xml</String>`
`+                                </field>`
`+                            </scenarioAssociation>`
`+                            <scenarioAssociation>`
`+                                <field name="name">`
`+                                    <String xml:space="preserve">Tutorial to HTML</String>`
`+                                </field>`
`+                                <field name="type">`
`+                                    <String xml:space="preserve">XSL</String>`
`+                                </field>`
`+                                <field name="url">`
`+                                    <String xml:space="preserve">Basics/Tutorial%2000.xml</String>`
`+                                </field>`
`+                            </scenarioAssociation>`
`+                            <scenarioAssociation>`
`+                                <field name="name">`
`+                                    <String xml:space="preserve">Docbook PDF Printable</String>`
`+                                </field>`
`+                                <field name="type">`
`+                                    <String xml:space="preserve">XSL</String>`
`+                                </field>`
`+                                <field name="url">`
`+                                    <String xml:space="preserve">file:/../Writing/KotoRII/Adventures%20of%20Bastila%20and%20Mira/Chapter%201.xml</String>`
`+                                </field>`
`+                            </scenarioAssociation>`
`+                            <scenarioAssociation>`
`+                                <field name="name">`
`+                                    <String xml:space="preserve">Docbook PDF Printable</String>`
`+                                </field>`
`+                                <field name="type">`
`+                                    <String xml:space="preserve">XSL</String>`
`+                                </field>`
`+                                <field name="url">`
`+                                    <String xml:space="preserve">file:/../Writing/KotoRII/Adventures%20of%20Bastila%20and%20Mira/Chapter%202.xml</String>`
`+                                </field>`
`+                            </scenarioAssociation>`
`+                            <scenarioAssociation>`
`+                                <field name="name">`
`+                                    <String xml:space="preserve">Docbook PDF Printable</String>`
`+                                </field>`
`+                                <field name="type">`
`+                                    <String xml:space="preserve">XSL</String>`
`+                                </field>`
`+                                <field name="url">`
`+                                    <String xml:space="preserve">file:/../Design/RenderToDo.xml</String>`
`+                                </field>`
`+                            </scenarioAssociation>`
`+                            <scenarioAssociation>`
`+                                <field name="name">`
`+                                    <String xml:space="preserve">Docbook PDF</String>`
`+                                </field>`
`+                                <field name="type">`
`+                                    <String xml:space="preserve">XSL</String>`
`+                                </field>`
`+                                <field name="url">`
`+                                    <String xml:space="preserve">file:/../Programming/InternalExes/FoMaker/design/FoLoadCodeGen.xml</String>`
`                                 </field>`
`                             </scenarioAssociation>`
`                             <scenarioAssociation>`
`                                     <String xml:space="preserve">XSL</String>`
`                                 </field>`
`                                 <field name="url">`
`-                                    <String xml:space="preserve">file:/G:/Program%20Files/XMLmind_XML_Editor/demo/docbook-modular-book/chapter.xml</String>`
`+                                    <String xml:space="preserve">file:/../Programming/ExternalExes/doxygen%20development/Design/ProgDocSchema.xml</String>`
`+                                </field>`
`+                            </scenarioAssociation>`
`+                            <scenarioAssociation>`
`+                                <field name="name">`
`+                                    <String xml:space="preserve">Docbook HTML</String>`
`+                                </field>`
`+                                <field name="type">`
`+                                    <String xml:space="preserve">XSL</String>`
`+                                </field>`
`+                                <field name="url">`
`+                                    <String xml:space="preserve">file:/../Writing/KotoRII/Novelization/Episode%20II/Chapter1.xml</String>`
`+                                </field>`
`+                            </scenarioAssociation>`
`+                            <scenarioAssociation>`
`+                                <field name="name">`
`+                                    <String xml:space="preserve">Docbook HTML</String>`
`+                                </field>`
`+                                <field name="type">`
`+                                    <String xml:space="preserve">XSL</String>`
`+                                </field>`
`+                                <field name="url">`
`+                                    <String xml:space="preserve">file:/../Programming/ExternalExes/doxygen%20development/Design/OldData/DoxyFormat.xml</String>`
`+                                </field>`
`+                            </scenarioAssociation>`
`+                            <scenarioAssociation>`
`+                                <field name="name">`
`+                                    <String xml:space="preserve">Docbook HTML</String>`
`+                                </field>`
`+                                <field name="type">`
`+                                    <String xml:space="preserve">XSL</String>`
`+                                </field>`
`+                                <field name="url">`
`+                                    <String xml:space="preserve">file:/../Programming/ExternalExes/doxygen%20development/Design/DoxyFormat.xml</String>`
`+                                </field>`
`+                            </scenarioAssociation>`
`+                            <scenarioAssociation>`
`+                                <field name="name">`
`+                                    <String xml:space="preserve">Docbook PDF</String>`
`+                                </field>`
`+                                <field name="type">`
`+                                    <String xml:space="preserve">XSL</String>`
`+                                </field>`
`+                                <field name="url">`
`+                                    <String xml:space="preserve">file:/../Projects/DuelingCircle/DC21.xml</String>`
`+                                </field>`
`+                            </scenarioAssociation>`
`+                            <scenarioAssociation>`
`+                                <field name="name">`
`+                                    <String xml:space="preserve">Docbook HTML</String>`
`+                                </field>`
`+                                <field name="type">`
`+                                    <String xml:space="preserve">XSL</String>`
`+                                </field>`
`+                                <field name="url">`
`+                                    <String xml:space="preserve">file:/../Critiques/Past%20Mistakes%20Prologue.xml</String>`
`+                                </field>`
`+                            </scenarioAssociation>`
`+                            <scenarioAssociation>`
`+                                <field name="name">`
`+                                    <String xml:space="preserve">Docbook HTML</String>`
`+                                </field>`
`+                                <field name="type">`
`+                                    <String xml:space="preserve">XSL</String>`
`+                                </field>`
`+                                <field name="url">`
`+                                    <String xml:space="preserve">file:/../Critiques/Past%20Mistakes%201%20Trouble.xml</String>`
`+                                </field>`
`+                            </scenarioAssociation>`
`+                            <scenarioAssociation>`
`+                                <field name="name">`
`+                                    <String xml:space="preserve">Docbook HTML</String>`
`+                                </field>`
`+                                <field name="type">`
`+                                    <String xml:space="preserve">XSL</String>`
`+                                </field>`
`+                                <field name="url">`
`+                                    <String xml:space="preserve">file:/../WritingDesign/TacticalD20/Anime_d20_SRD_v1.0_-_Chap01-12/DocBook/CharacterCreation.xml</String>`
`+                                </field>`
`+                            </scenarioAssociation>`
`+                            <scenarioAssociation>`
`+                                <field name="name">`
`+                                    <String xml:space="preserve">Docbook HTML</String>`
`+                                </field>`
`+                                <field name="type">`
`+                                    <String xml:space="preserve">XSL</String>`
`+                                </field>`
`+                                <field name="url">`
`+                                    <String xml:space="preserve">file:/H:/SM/KotoRII/BasicOutline.xml</String>`
`                                 </field>`
`                             </scenarioAssociation>`
`                             <scenarioAssociation>`
`                                     <String xml:space="preserve">XSL</String>`
`                                 </field>`
`                                 <field name="url">`
`-                                    <String xml:space="preserve">file:/H:/SM/KotoRII/FirstBook.xml</String>`
`+                                    <String xml:space="preserve">file:/H:/SM/KotoRII/Episode%20I/Chapter1.xml</String>`
`+                                </field>`
`+                            </scenarioAssociation>`
`+                            <scenarioAssociation>`
`+                                <field name="name">`
`+                                    <String xml:space="preserve">Docbook PDF</String>`
`+                                </field>`
`+                                <field name="type">`
`+                                    <String xml:space="preserve">XSL</String>`
`+                                </field>`
`+                                <field name="url">`
`+                                    <String xml:space="preserve">file:/H:/SM/KotoRII/Episode%20I/Chapter3.xml</String>`
`                                 </field>`
`                             </scenarioAssociation>`
`                             <scenarioAssociation>`
`                                     <String xml:space="preserve">XSL</String>`
`                                 </field>`
`                                 <field name="url">`
`-                                    <String xml:space="preserve">file:/H:/SM/KotoRII/Episode%20I/Chapter2.xml</String>`
`+                                    <String xml:space="preserve">file:/H:/SM/KotoRII/Episode%20I/Episode%20I.xml</String>`
`                                 </field>`
`                             </scenarioAssociation>`
`                             <scenarioAssociation>`
`                                     <String xml:space="preserve">XSL</String>`
`                                 </field>`
`                                 <field name="url">`
`-                                    <String xml:space="preserve">file:/H:/SM/KotoRII/Episode%20I/Episode%20I.xml</String>`
`-                                </field>`
`-                            </scenarioAssociation>`
`-                            <scenarioAssociation>`
`-                                <field name="name">`
`-                                    <String xml:space="preserve">Docbook PDF</String>`
`-                                </field>`
`-                                <field name="type">`
`-                                    <String xml:space="preserve">XSL</String>`
`-                                </field>`
`-                                <field name="url">`
`-                                    <String xml:space="preserve">file:/H:/SM/KotoRII/Episode%20I/Chapter3.xml</String>`
`+                                    <String xml:space="preserve">file:/H:/SM/KotoRII/Episode%20I/Chapter2.xml</String>`
`                                 </field>`
`                             </scenarioAssociation>`
`                             <scenarioAssociation>`
`                                     <String xml:space="preserve">XSL</String>`
`                                 </field>`
`                                 <field name="url">`
`-                                    <String xml:space="preserve">file:/H:/SM/KotoRII/Episode%20I/Chapter1.xml</String>`
`+                                    <String xml:space="preserve">file:/H:/SM/KotoRII/FirstBook.xml</String>`
`                                 </field>`
`                             </scenarioAssociation>`
`                             <scenarioAssociation>`
`                                     <String xml:space="preserve">XSL</String>`
`                                 </field>`
`                                 <field name="url">`
`-                                    <String xml:space="preserve">file:/H:/SM/KotoRII/BasicOutline.xml</String>`
`-                                </field>`
`-                            </scenarioAssociation>`
`-                            <scenarioAssociation>`
`-                                <field name="name">`
`-                                    <String xml:space="preserve">Docbook HTML</String>`
`-                                </field>`
`-                                <field name="type">`
`-                                    <String xml:space="preserve">XSL</String>`
`-                                </field>`
`-                                <field name="url">`
`-                                    <String xml:space="preserve">file:/../WritingDesign/TacticalD20/Anime_d20_SRD_v1.0_-_Chap01-12/DocBook/CharacterCreation.xml</String>`
`-                                </field>`
`-                            </scenarioAssociation>`
`-                            <scenarioAssociation>`
`-                                <field name="name">`
`-                                    <String xml:space="preserve">Docbook HTML</String>`
`-                                </field>`
`-                                <field name="type">`
`-                                    <String xml:space="preserve">XSL</String>`
`-                                </field>`
`-                                <field name="url">`
`-                                    <String xml:space="preserve">file:/../Critiques/Past%20Mistakes%201%20Trouble.xml</String>`
`-                                </field>`
`-                            </scenarioAssociation>`
`-                            <scenarioAssociation>`
`-                                <field name="name">`
`-                                    <String xml:space="preserve">Docbook HTML</String>`
`-                                </field>`
`-                                <field name="type">`
`-                                    <String xml:space="preserve">XSL</String>`
`-                                </field>`
`-                                <field name="url">`
`-                                    <String xml:space="preserve">file:/../Critiques/Past%20Mistakes%20Prologue.xml</String>`
`-                                </field>`
`-                            </scenarioAssociation>`
`-                            <scenarioAssociation>`
`-                                <field name="name">`
`-                                    <String xml:space="preserve">Docbook PDF</String>`
`-                                </field>`
`-                                <field name="type">`
`-                                    <String xml:space="preserve">XSL</String>`
`-                                </field>`
`-                                <field name="url">`
`-                                    <String xml:space="preserve">file:/../Projects/DuelingCircle/DC21.xml</String>`
`-                                </field>`
`-                            </scenarioAssociation>`
`-                            <scenarioAssociation>`
`-                                <field name="name">`
`-                                    <String xml:space="preserve">Docbook HTML</String>`
`-                                </field>`
`-                                <field name="type">`
`-                                    <String xml:space="preserve">XSL</String>`
`-                                </field>`
`-                                <field name="url">`
`-                                    <String xml:space="preserve">file:/../Programming/ExternalExes/doxygen%20development/Design/DoxyFormat.xml</String>`
`-                                </field>`
`-                            </scenarioAssociation>`
`-                            <scenarioAssociation>`
`-                                <field name="name">`
`-                                    <String xml:space="preserve">Docbook HTML</String>`
`-                                </field>`
`-                                <field name="type">`
`-                                    <String xml:space="preserve">XSL</String>`
`-                                </field>`
`-                                <field name="url">`
`-                                    <String xml:space="preserve">file:/../Programming/ExternalExes/doxygen%20development/Design/OldData/DoxyFormat.xml</String>`
`-                                </field>`
`-                            </scenarioAssociation>`
`-                            <scenarioAssociation>`
`-                                <field name="name">`
`-                                    <String xml:space="preserve">Docbook HTML</String>`
`-                                </field>`
`-                                <field name="type">`
`-                                    <String xml:space="preserve">XSL</String>`
`-                                </field>`
`-                                <field name="url">`
`-                                    <String xml:space="preserve">file:/../Writing/KotoRII/Novelization/Episode%20II/Chapter1.xml</String>`
`-                                </field>`
`-                            </scenarioAssociation>`
`-                            <scenarioAssociation>`
`-                                <field name="name">`
`-                                    <String xml:space="preserve">Docbook HTML</String>`
`-                                </field>`
`-                                <field name="type">`
`-                                    <String xml:space="preserve">XSL</String>`
`-                                </field>`
`-                                <field name="url">`
`-                                    <String xml:space="preserve">file:/../Programming/ExternalExes/doxygen%20development/Design/ProgDocSchema.xml</String>`
`-                                </field>`
`-                            </scenarioAssociation>`
`-                            <scenarioAssociation>`
`-                                <field name="name">`
`-                                    <String xml:space="preserve">Docbook PDF</String>`
`-                                </field>`
`-                                <field name="type">`
`-                                    <String xml:space="preserve">XSL</String>`
`-                                </field>`
`-                                <field name="url">`
`-                                    <String xml:space="preserve">file:/../Programming/InternalExes/FoMaker/design/FoLoadCodeGen.xml</String>`
`-                                </field>`
`-                            </scenarioAssociation>`
`-                            <scenarioAssociation>`
`-                                <field name="name">`
`-                                    <String xml:space="preserve">Docbook PDF Printable</String>`
`-                                </field>`
`-                                <field name="type">`
`-                                    <String xml:space="preserve">XSL</String>`
`-                                </field>`
`-                                <field name="url">`
`-                                    <String xml:space="preserve">file:/../Design/RenderToDo.xml</String>`
`-                                </field>`
`-                            </scenarioAssociation>`
`-                            <scenarioAssociation>`
`-                                <field name="name">`
`-                                    <String xml:space="preserve">Docbook PDF Printable</String>`
`-                                </field>`
`-                                <field name="type">`
`-                                    <String xml:space="preserve">XSL</String>`
`-                                </field>`
`-                                <field name="url">`
`-                                    <String xml:space="preserve">file:/../Writing/KotoRII/Adventures%20of%20Bastila%20and%20Mira/Chapter%202.xml</String>`
`-                                </field>`
`-                            </scenarioAssociation>`
`-                            <scenarioAssociation>`
`-                                <field name="name">`
`-                                    <String xml:space="preserve">Docbook PDF Printable</String>`
`-                                </field>`
`-                                <field name="type">`
`-                                    <String xml:space="preserve">XSL</String>`
`-                                </field>`
`-                                <field name="url">`
`-                                    <String xml:space="preserve">file:/../Writing/KotoRII/Adventures%20of%20Bastila%20and%20Mira/Chapter%201.xml</String>`
`+                                    <String xml:space="preserve">file:/G:/Program%20Files/XMLmind_XML_Editor/demo/docbook-modular-book/chapter.xml</String>`
`                                 </field>`
`                             </scenarioAssociation>`
`                             <scenarioAssociation>`
`                                     <String xml:space="preserve">XSL</String>`
`                                 </field>`
`                                 <field name="url">`
`-                                    <String xml:space="preserve">Basics/Tutorial%2000.xml</String>`
`+                                    <String xml:space="preserve">Tutorials.html</String>`
`                                 </field>`
`                             </scenarioAssociation>`
`                             <scenarioAssociation>`
`                                 <field name="name">`
`-                                    <String xml:space="preserve">Tutorial to HTML</String>`
`+                                    <String xml:space="preserve">Tutorial to Printable PDF</String>`
`                                 </field>`
`                                 <field name="type">`
`                                     <String xml:space="preserve">XSL</String>`
`                                 </field>`
`                                 <field name="url">`
`-                                    <String xml:space="preserve">Positioning/Tutorial%2004.xml</String>`
`+                                    <String xml:space="preserve">Tutorials.xml</String>`
`                                 </field>`
`                             </scenarioAssociation>`
`                         </scenarioAssociation-array>`

# File Documents/cssDoc.txt

`     code.varname: Used for variable names.`
`     code.filename: Used for filenames.`
`     code.literal: Used for various kinds of literals in code.`
`+    code.classname: Used for classes.`
`     span.type: Used for the types of things.`
`+    span.mathphrase: Used for math phrases.`
`     `
`     div.example: Stores the entire example.`
`         p.title: The title of the example.`

# File Tut 06 Objects in Motion/Hierarchy.cpp

` #include <string>`
` #include <vector>`
`+#include <stack>`
` #include <math.h>`
` #include <glloader/gl_3_2_comp.h>`
` #include <GL/freeglut.h>`
` 	modelToCameraMatrixUnif = glGetUniformLocation(theProgram, "modelToCameraMatrix");`
` 	cameraToClipMatrixUnif = glGetUniformLocation(theProgram, "cameraToClipMatrix");`
` `
`-	float fzNear = 1.0f; float fzFar = 61.0f;`
`+	float fzNear = 1.0f; float fzFar = 100.0f;`
` `
` 	cameraToClipMatrix[0].x = fFrustumScale;`
` 	cameraToClipMatrix[1].y = fFrustumScale;`
` 	glUseProgram(0);`
` }`
` `
`-const int numberOfVertices = 8;`
`+const int numberOfVertices = 24;`
` `
`+#define RED_COLOR 1.0f, 0.0f, 0.0f, 1.0f`
` #define GREEN_COLOR 0.0f, 1.0f, 0.0f, 1.0f`
` #define BLUE_COLOR 	0.0f, 0.0f, 1.0f, 1.0f`
`-#define RED_COLOR 1.0f, 0.0f, 0.0f, 1.0f`
`-#define GREY_COLOR 0.8f, 0.8f, 0.8f, 1.0f`
`-#define BROWN_COLOR 0.5f, 0.5f, 0.0f, 1.0f`
`+`
`+#define YELLOW_COLOR 1.0f, 1.0f, 0.0f, 1.0f`
`+#define CYAN_COLOR 0.0f, 1.0f, 1.0f, 1.0f`
`+#define MAGENTA_COLOR 	1.0f, 0.0f, 1.0f, 1.0f`
` `
` const float vertexData[] =`
` {`
`+	//Front`
` 	+1.0f, +1.0f, +1.0f,`
`+	+1.0f, -1.0f, +1.0f,`
` 	-1.0f, -1.0f, +1.0f,`
`+	-1.0f, +1.0f, +1.0f,`
`+`
`+	//Top`
`+	+1.0f, +1.0f, +1.0f,`
`+	-1.0f, +1.0f, +1.0f,`
` 	-1.0f, +1.0f, -1.0f,`
`+	+1.0f, +1.0f, -1.0f,`
`+`
`+	//Left`
`+	+1.0f, +1.0f, +1.0f,`
`+	+1.0f, +1.0f, -1.0f,`
`+	+1.0f, -1.0f, -1.0f,`
`+	+1.0f, -1.0f, +1.0f,`
`+`
`+	//Back`
`+	+1.0f, +1.0f, -1.0f,`
`+	-1.0f, +1.0f, -1.0f,`
`+	-1.0f, -1.0f, -1.0f,`
` 	+1.0f, -1.0f, -1.0f,`
` `
`+	//Bottom`
`+	+1.0f, -1.0f, +1.0f,`
`+	+1.0f, -1.0f, -1.0f,`
` 	-1.0f, -1.0f, -1.0f,`
`-	+1.0f, +1.0f, -1.0f,`
`-	+1.0f, -1.0f, +1.0f,`
`+	-1.0f, -1.0f, +1.0f,`
`+`
`+	//Right`
` 	-1.0f, +1.0f, +1.0f,`
`+	-1.0f, -1.0f, +1.0f,`
`+	-1.0f, -1.0f, -1.0f,`
`+	-1.0f, +1.0f, -1.0f,`
`+`
` `
` 	GREEN_COLOR,`
`+	GREEN_COLOR,`
`+	GREEN_COLOR,`
`+	GREEN_COLOR,`
`+`
` 	BLUE_COLOR,`
`+	BLUE_COLOR,`
`+	BLUE_COLOR,`
`+	BLUE_COLOR,`
`+`
` 	RED_COLOR,`
`-	BROWN_COLOR,`
`+	RED_COLOR,`
`+	RED_COLOR,`
`+	RED_COLOR,`
` `
`-	GREEN_COLOR,`
`-	BLUE_COLOR,`
`-	RED_COLOR,`
`-	BROWN_COLOR,`
`+	YELLOW_COLOR,`
`+	YELLOW_COLOR,`
`+	YELLOW_COLOR,`
`+	YELLOW_COLOR,`
`+`
`+	CYAN_COLOR,`
`+	CYAN_COLOR,`
`+	CYAN_COLOR,`
`+	CYAN_COLOR,`
`+`
`+	MAGENTA_COLOR,`
`+	MAGENTA_COLOR,`
`+	MAGENTA_COLOR,`
`+	MAGENTA_COLOR,`
` };`
` `
` const GLshort indexData[] =`
` {`
` 	0, 1, 2,`
`-	1, 0, 3,`
` 	2, 3, 0,`
`-	3, 2, 1,`
` `
`-	5, 4, 6,`
`-	4, 5, 7,`
`-	7, 6, 4,`
`-	6, 7, 5,`
`+	4, 5, 6,`
`+	6, 7, 4,`
`+`
`+	8, 9, 10,`
`+	10, 11, 8,`
`+`
`+	12, 13, 14,`
`+	14, 15, 12,`
`+`
`+	16, 17, 18,`
`+	18, 19, 16,`
`+`
`+	20, 21, 22,`
`+	22, 23, 20,`
` };`
` `
` GLuint vertexBufferObject;`
` GLuint indexBufferObject;`
` GLuint vao;`
` `
`-`
`-void InitializeVertexBuffer()`
`+void InitializeVAO()`
` {`
` 	glGenBuffers(1, &vertexBufferObject);`
` `
` 	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferObject);`
` 	glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indexData), indexData, GL_STATIC_DRAW);`
` 	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);`
`-}`
`-`
`-float CalcLerpFactor(float fElapsedTime, float fLoopDuration)`
`-{`
`-	float fValue = fmodf(fElapsedTime, fLoopDuration) / fLoopDuration;`
`-	if(fValue > 0.5f)`
`-		fValue = 1.0f - fValue;`
`-`
`-	return fValue * 2.0f;`
`-}`
`-`
`-glm::mat3 NullRotation(float fElapsedTime)`
`-{`
`-	return glm::mat3(1.0f);`
`-}`
`-`
`-float ComputeAngleRad(float fElapsedTime, float fLoopDuration)`
`-{`
`-	const float fScale = 3.14159f * 2.0f / fLoopDuration;`
`-	float fCurrTimeThroughLoop = fmodf(fElapsedTime, fLoopDuration);`
`-	return fCurrTimeThroughLoop * fScale;`
`-}`
`-`
`-glm::mat3 RotateX(float fElapsedTime)`
`-{`
`-	float fAngRad = ComputeAngleRad(fElapsedTime, 3.0);`
`-	float fCos = cosf(fAngRad);`
`-	float fSin = sinf(fAngRad);`
`-`
`-	glm::mat3 theMat(1.0f);`
`-	theMat[1].y = fCos; theMat[2].y = -fSin;`
`-	theMat[1].z = fSin; theMat[2].z = fCos;`
`-	return theMat;`
`-}`
`-`
`-glm::mat3 RotateY(float fElapsedTime)`
`-{`
`-	float fAngRad = ComputeAngleRad(fElapsedTime, 2.0);`
`-	float fCos = cosf(fAngRad);`
`-	float fSin = sinf(fAngRad);`
`-`
`-	glm::mat3 theMat(1.0f);`
`-	theMat[0].x = fCos; theMat[2].x = fSin;`
`-	theMat[0].z = -fSin; theMat[2].z = fCos;`
`-	return theMat;`
`-}`
`-`
`-glm::mat3 RotateZ(float fElapsedTime)`
`-{`
`-	float fAngRad = ComputeAngleRad(fElapsedTime, 2.0);`
`-	float fCos = cosf(fAngRad);`
`-	float fSin = sinf(fAngRad);`
`-`
`-	glm::mat3 theMat(1.0f);`
`-	theMat[0].x = fCos; theMat[1].x = -fSin;`
`-	theMat[0].y = fSin; theMat[1].y = fCos;`
`-	return theMat;`
`-}`
`-`
`-glm::mat3 RotateAxis(float fElapsedTime)`
`-{`
`-	float fAngRad = ComputeAngleRad(fElapsedTime, 2.0);`
`-	float fCos = cosf(fAngRad);`
`-	float fInvCos = 1.0f - fCos;`
`-	float fSin = sinf(fAngRad);`
`-	float fInvSin = 1.0f - fSin;`
`-`
`-	glm::vec3 axis(1.0f, 1.0f, 1.0f);`
`-	axis = glm::normalize(axis);`
`-`
`-	glm::mat3 theMat(1.0f);`
`-	theMat[0].x = (axis.x * axis.x) + ((1 - axis.x * axis.x) * fCos);`
`-	theMat[1].x = axis.x * axis.y * (fInvCos) - (axis.z * fSin);`
`-	theMat[2].x = axis.x * axis.z * (fInvCos) + (axis.y * fSin);`
`-`
`-	theMat[0].y = axis.x * axis.y * (fInvCos) + (axis.z * fSin);`
`-	theMat[1].y = (axis.y * axis.y) + ((1 - axis.y * axis.y) * fCos);`
`-	theMat[2].y = axis.y * axis.z * (fInvCos) - (axis.x * fSin);`
`-`
`-	theMat[0].z = axis.x * axis.z * (fInvCos) - (axis.y * fSin);`
`-	theMat[1].z = axis.y * axis.z * (fInvCos) + (axis.x * fSin);`
`-	theMat[2].z = (axis.z * axis.z) + ((1 - axis.z * axis.z) * fCos);`
`-	return theMat;`
`-}`
`-`
`-glm::vec3 DynamicNonUniformScale(float fElapsedTime)`
`-{`
`-	const float fXLoopDuration = 3.0f;`
`-	const float fZLoopDuration = 5.0f;`
`-`
`-	return glm::vec3(glm::mix(1.0f, 0.5f, CalcLerpFactor(fElapsedTime, fXLoopDuration)),`
`-		1.0f,`
`-		glm::mix(1.0f, 10.0f, CalcLerpFactor(fElapsedTime, fZLoopDuration)));`
`-}`
`-`
`-struct Instance`
`-{`
`-	typedef glm::mat3(*RotationFunc)(float);`
`-`
`-	RotationFunc CalcRotation;`
`-	glm::vec3 offset;`
`-`
`-	glm::mat4 ConstructMatrix(float fElapsedTime)`
`-	{`
`-		const glm::mat3 &rotMatrix = CalcRotation(fElapsedTime);`
`-		glm::mat4 theMat(rotMatrix);`
`-		theMat[3] = glm::vec4(offset, 1.0f);`
`-`
`-		return theMat;`
`-	}`
`-};`
`-`
`-Instance g_instanceList[] =`
`-{`
`-	{NullRotation,				glm::vec3(0.0f, 0.0f, -25.0f)},`
`-	{RotateX,					glm::vec3(-5.0f, -5.0f, -25.0f)},`
`-	{RotateY,					glm::vec3(-5.0f, 5.0f, -25.0f)},`
`-	{RotateZ,					glm::vec3(5.0f, 5.0f, -25.0f)},`
`-	{RotateAxis,				glm::vec3(5.0f, -5.0f, -25.0f)},`
`-};`
`-`
`-//Called after the window and OpenGL are initialized. Called exactly once, before the main loop.`
`-void init()`
`-{`
`-	InitializeProgram();`
`-	InitializeVertexBuffer();`
` `
` 	glGenVertexArrays(1, &vao);`
` 	glBindVertexArray(vao);`
` 	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferObject);`
` `
` 	glBindVertexArray(0);`
`+}`
`+`
`+inline float DegToRad(float fAngDeg)`
`+{`
`+	const float fDegToRad = 3.14159f * 2.0f / 360.0f;`
`+	return fAngDeg * fDegToRad;`
`+}`
`+`
`+inline float Clamp(float fValue, float fMinValue, float fMaxValue)`
`+{`
`+	if(fValue < fMinValue)`
`+		return fMinValue;`
`+`
`+	if(fValue > fMaxValue)`
`+		return fMaxValue;`
`+`
`+	return fValue;`
`+}`
`+`
`+glm::mat3 RotateX(float fAngDeg)`
`+{`
`+	float fAngRad = DegToRad(fAngDeg);`
`+	float fCos = cosf(fAngRad);`
`+	float fSin = sinf(fAngRad);`
`+`
`+	glm::mat3 theMat(1.0f);`
`+	theMat[1].y = fCos; theMat[2].y = -fSin;`
`+	theMat[1].z = fSin; theMat[2].z = fCos;`
`+	return theMat;`
`+}`
`+`
`+glm::mat3 RotateY(float fAngDeg)`
`+{`
`+	float fAngRad = DegToRad(fAngDeg);`
`+	float fCos = cosf(fAngRad);`
`+	float fSin = sinf(fAngRad);`
`+`
`+	glm::mat3 theMat(1.0f);`
`+	theMat[0].x = fCos; theMat[2].x = fSin;`
`+	theMat[0].z = -fSin; theMat[2].z = fCos;`
`+	return theMat;`
`+}`
`+`
`+glm::mat3 RotateZ(float fAngDeg)`
`+{`
`+	float fAngRad = DegToRad(fAngDeg);`
`+	float fCos = cosf(fAngRad);`
`+	float fSin = sinf(fAngRad);`
`+`
`+	glm::mat3 theMat(1.0f);`
`+	theMat[0].x = fCos; theMat[1].x = -fSin;`
`+	theMat[0].y = fSin; theMat[1].y = fCos;`
`+	return theMat;`
`+}`
`+`
`+class MatrixStack`
`+{`
`+public:`
`+	glm::mat4 Top()`
`+	{`
`+		if(m_matrices.empty())`
`+		{`
`+			m_matrices.push(glm::mat4(1.0f));`
`+		}`
`+`
`+		return m_matrices.top();`
`+	}`
`+`
`+	void RotateX(float fAngDeg)`
`+	{`
`+		const glm::mat4 &top = Top();`
`+		m_matrices.pop();`
`+		m_matrices.push(top * glm::mat4(::RotateX(fAngDeg)));`
`+	}`
`+`
`+	void RotateY(float fAngDeg)`
`+	{`
`+		const glm::mat4 &top = Top();`
`+		m_matrices.pop();`
`+		m_matrices.push(top * glm::mat4(::RotateY(fAngDeg)));`
`+	}`
`+`
`+	void RotateZ(float fAngDeg)`
`+	{`
`+		const glm::mat4 &top = Top();`
`+		m_matrices.pop();`
`+		m_matrices.push(top * glm::mat4(::RotateZ(fAngDeg)));`
`+	}`
`+`
`+	void Scale(const glm::vec3 &scaleVec)`
`+	{`
`+		glm::mat4 scaleMat(1.0f);`
`+		scaleMat[0].x = scaleVec.x;`
`+		scaleMat[1].y = scaleVec.y;`
`+		scaleMat[2].z = scaleVec.z;`
`+`
`+		const glm::mat4 &top = Top();`
`+		m_matrices.pop();`
`+		m_matrices.push(top * scaleMat);`
`+	}`
`+`
`+	void Translate(const glm::vec3 &offsetVec)`
`+	{`
`+		glm::mat4 translateMat(1.0f);`
`+		translateMat[3] = glm::vec4(offsetVec, 1.0f);`
`+`
`+		const glm::mat4 &top = Top();`
`+		m_matrices.pop();`
`+		m_matrices.push(top * translateMat);`
`+	}`
`+`
`+	void Push()`
`+	{`
`+		m_matrices.push(Top());`
`+	}`
`+`
`+	void Pop()`
`+	{`
`+		m_matrices.pop();`
`+	}`
`+`
`+private:`
`+	std::stack<glm::mat4> m_matrices;`
`+};`
`+`
`+class Hierarchy`
`+{`
`+public:`
`+	Hierarchy()`
`+		: posBase(glm::vec3(3.0f, -5.0f, -40.0f))`
`+		, angBase(-45.0f)`
`+		, posBaseLeft(glm::vec3(2.0f, 0.0f, 0.0f))`
`+		, posBaseRight(glm::vec3(-2.0f, 0.0f, 0.0f))`
`+		, scaleBaseZ(3.0f)`
`+		, angUpperArm(-33.75f)`
`+		, sizeUpperArm(9.0f)`
`+		, posLowerArm(glm::vec3(0.0f, 0.0f, 8.0f))`
`+		, angLowerArm(146.25f)`
`+		, lenLowerArm(5.0f)`
`+		, widthLowerArm(1.5f)`
`+		, posWrist(glm::vec3(0.0f, 0.0f, 5.0f))`
`+		, angWristRoll(0.0f)`
`+		, angWristPitch(67.5f)`
`+		, lenWrist(2.0f)`
`+		, widthWrist(2.0f)`
`+		, posLeftFinger(glm::vec3(1.0f, 0.0f, 1.0f))`
`+		, posRightFinger(glm::vec3(-1.0f, 0.0f, 1.0f))`
`+		, angFingerOpen(180.0f)`
`+		, lenFinger(2.0f)`
`+		, widthFinger(0.5f)`
`+		, angLowerFinger(45.0f)`
`+	{}`
`+`
`+	void Draw()`
`+	{`
`+		MatrixStack modelToCameraStack;`
`+`
`+		glUseProgram(theProgram);`
`+		glBindVertexArray(vao);`
`+`
`+		modelToCameraStack.Translate(posBase);`
`+		modelToCameraStack.RotateY(angBase);`
`+`
`+		//Draw left base.`
`+		{`
`+			modelToCameraStack.Push();`
`+			modelToCameraStack.Translate(posBaseLeft);`
`+			modelToCameraStack.Scale(glm::vec3(1.0f, 1.0f, scaleBaseZ));`
`+			glUniformMatrix4fv(modelToCameraMatrixUnif, 1, GL_FALSE, glm::value_ptr(modelToCameraStack.Top()));`
`+			glDrawElements(GL_TRIANGLES, ARRAY_COUNT(indexData), GL_UNSIGNED_SHORT, 0);`
`+			modelToCameraStack.Pop();`
`+		}`
`+`
`+		//Draw right base.`
`+		{`
`+			modelToCameraStack.Push();`
`+			modelToCameraStack.Translate(posBaseRight);`
`+			modelToCameraStack.Scale(glm::vec3(1.0f, 1.0f, scaleBaseZ));`
`+			glUniformMatrix4fv(modelToCameraMatrixUnif, 1, GL_FALSE, glm::value_ptr(modelToCameraStack.Top()));`
`+			glDrawElements(GL_TRIANGLES, ARRAY_COUNT(indexData), GL_UNSIGNED_SHORT, 0);`
`+			modelToCameraStack.Pop();`
`+		}`
`+`
`+		//Draw main arm.`
`+		DrawUpperArm(modelToCameraStack);`
`+`
`+		glBindVertexArray(0);`
`+		glUseProgram(0);`
`+	}`
`+`
`+#define STANDARD_ANGLE_INCREMENT 11.25f`
`+#define SMALL_ANGLE_INCREMENT 9.0f`
`+`
`+	void AdjBase(bool bIncrement)`
`+	{`
`+		angBase += bIncrement ? STANDARD_ANGLE_INCREMENT : -STANDARD_ANGLE_INCREMENT;`
`+		angBase = fmodf(angBase, 360.0f);`
`+	}`
`+`
`+	void AdjUpperArm(bool bIncrement)`
`+	{`
`+		angUpperArm += bIncrement ? STANDARD_ANGLE_INCREMENT : -STANDARD_ANGLE_INCREMENT;`
`+		angUpperArm = Clamp(angUpperArm, -90.0f, 0.0f);`
`+	}`
`+`
`+	void AdjLowerArm(bool bIncrement)`
`+	{`
`+		angLowerArm += bIncrement ? STANDARD_ANGLE_INCREMENT : -STANDARD_ANGLE_INCREMENT;`
`+		angLowerArm = Clamp(angLowerArm, 0.0f, 146.25f);`
`+	}`
`+`
`+	void AdjWristPitch(bool bIncrement)`
`+	{`
`+		angWristPitch += bIncrement ? STANDARD_ANGLE_INCREMENT : -STANDARD_ANGLE_INCREMENT;`
`+		angWristPitch = Clamp(angWristPitch, 0.0f, 90.0f);`
`+	}`
`+`
`+	void AdjWristRoll(bool bIncrement)`
`+	{`
`+		angWristRoll += bIncrement ? STANDARD_ANGLE_INCREMENT : -STANDARD_ANGLE_INCREMENT;`
`+		angWristRoll = fmodf(angWristRoll, 360.0f);`
`+	}`
`+`
`+	void AdjFingerOpen(bool bIncrement)`
`+	{`
`+		angFingerOpen += bIncrement ? SMALL_ANGLE_INCREMENT : -SMALL_ANGLE_INCREMENT;`
`+		angFingerOpen = Clamp(angFingerOpen, 9.0f, 180.0f);`
`+	}`
`+`
`+	void WritePose()`
`+	{`
`+		printf("angBase:\t%f\n", angBase);`
`+		printf("angUpperArm:\t%f\n", angUpperArm);`
`+		printf("angLowerArm:\t%f\n", angLowerArm);`
`+		printf("angWristPitch:\t%f\n", angWristPitch);`
`+		printf("angWristRoll:\t%f\n", angWristRoll);`
`+		printf("angFingerOpen:\t%f\n", angFingerOpen);`
`+		printf("\n");`
`+	}`
`+`
`+private:`
`+	void DrawFingers(MatrixStack &modelToCameraStack)`
`+	{`
`+		//Draw left finger`
`+		modelToCameraStack.Push();`
`+		modelToCameraStack.Translate(posLeftFinger);`
`+		modelToCameraStack.RotateY(angFingerOpen);`
`+`
`+		modelToCameraStack.Push();`
`+		modelToCameraStack.Translate(glm::vec3(0.0f, 0.0f, lenFinger / 2.0f));`
`+		modelToCameraStack.Scale(glm::vec3(widthFinger / 2.0f, widthFinger/ 2.0f, lenFinger / 2.0f));`
`+		glUniformMatrix4fv(modelToCameraMatrixUnif, 1, GL_FALSE, glm::value_ptr(modelToCameraStack.Top()));`
`+		glDrawElements(GL_TRIANGLES, ARRAY_COUNT(indexData), GL_UNSIGNED_SHORT, 0);`
`+		modelToCameraStack.Pop();`
`+`
`+		{`
`+			//Draw left lower finger`
`+			modelToCameraStack.Push();`
`+			modelToCameraStack.Translate(glm::vec3(0.0f, 0.0f, lenFinger));`
`+			modelToCameraStack.RotateY(-angLowerFinger);`
`+`
`+			modelToCameraStack.Push();`
`+			modelToCameraStack.Translate(glm::vec3(0.0f, 0.0f, lenFinger / 2.0f));`
`+			modelToCameraStack.Scale(glm::vec3(widthFinger / 2.0f, widthFinger/ 2.0f, lenFinger / 2.0f));`
`+			glUniformMatrix4fv(modelToCameraMatrixUnif, 1, GL_FALSE, glm::value_ptr(modelToCameraStack.Top()));`
`+			glDrawElements(GL_TRIANGLES, ARRAY_COUNT(indexData), GL_UNSIGNED_SHORT, 0);`
`+			modelToCameraStack.Pop();`
`+`
`+			modelToCameraStack.Pop();`
`+		}`
`+`
`+		modelToCameraStack.Pop();`
`+`
`+		//Draw right finger`
`+		modelToCameraStack.Push();`
`+		modelToCameraStack.Translate(posRightFinger);`
`+		modelToCameraStack.RotateY(-angFingerOpen);`
`+`
`+		modelToCameraStack.Push();`
`+		modelToCameraStack.Translate(glm::vec3(0.0f, 0.0f, lenFinger / 2.0f));`
`+		modelToCameraStack.Scale(glm::vec3(widthFinger / 2.0f, widthFinger/ 2.0f, lenFinger / 2.0f));`
`+		glUniformMatrix4fv(modelToCameraMatrixUnif, 1, GL_FALSE, glm::value_ptr(modelToCameraStack.Top()));`
`+		glDrawElements(GL_TRIANGLES, ARRAY_COUNT(indexData), GL_UNSIGNED_SHORT, 0);`
`+		modelToCameraStack.Pop();`
`+`
`+		{`
`+			//Draw right lower finger`
`+			modelToCameraStack.Push();`
`+			modelToCameraStack.Translate(glm::vec3(0.0f, 0.0f, lenFinger));`
`+			modelToCameraStack.RotateY(angLowerFinger);`
`+`
`+			modelToCameraStack.Push();`
`+			modelToCameraStack.Translate(glm::vec3(0.0f, 0.0f, lenFinger / 2.0f));`
`+			modelToCameraStack.Scale(glm::vec3(widthFinger / 2.0f, widthFinger/ 2.0f, lenFinger / 2.0f));`
`+			glUniformMatrix4fv(modelToCameraMatrixUnif, 1, GL_FALSE, glm::value_ptr(modelToCameraStack.Top()));`
`+			glDrawElements(GL_TRIANGLES, ARRAY_COUNT(indexData), GL_UNSIGNED_SHORT, 0);`
`+			modelToCameraStack.Pop();`
`+`
`+			modelToCameraStack.Pop();`
`+		}`
`+`
`+		modelToCameraStack.Pop();`
`+	}`
`+`
`+	void DrawWrist(MatrixStack &modelToCameraStack)`
`+	{`
`+		modelToCameraStack.Push();`
`+		modelToCameraStack.Translate(posWrist);`
`+		modelToCameraStack.RotateZ(angWristRoll);`
`+		modelToCameraStack.RotateX(angWristPitch);`
`+`
`+		modelToCameraStack.Push();`
`+		modelToCameraStack.Scale(glm::vec3(widthWrist / 2.0f, widthWrist/ 2.0f, lenWrist / 2.0f));`
`+		glUniformMatrix4fv(modelToCameraMatrixUnif, 1, GL_FALSE, glm::value_ptr(modelToCameraStack.Top()));`
`+		glDrawElements(GL_TRIANGLES, ARRAY_COUNT(indexData), GL_UNSIGNED_SHORT, 0);`
`+		modelToCameraStack.Pop();`
`+`
`+		DrawFingers(modelToCameraStack);`
`+`
`+		modelToCameraStack.Pop();`
`+	}`
`+`
`+	void DrawLowerArm(MatrixStack &modelToCameraStack)`
`+	{`
`+		modelToCameraStack.Push();`
`+		modelToCameraStack.Translate(posLowerArm);`
`+		modelToCameraStack.RotateX(angLowerArm);`
`+`
`+		modelToCameraStack.Push();`
`+		modelToCameraStack.Translate(glm::vec3(0.0f, 0.0f, lenLowerArm / 2.0f));`
`+		modelToCameraStack.Scale(glm::vec3(widthLowerArm / 2.0f, widthLowerArm / 2.0f, lenLowerArm / 2.0f));`
`+		glUniformMatrix4fv(modelToCameraMatrixUnif, 1, GL_FALSE, glm::value_ptr(modelToCameraStack.Top()));`
`+		glDrawElements(GL_TRIANGLES, ARRAY_COUNT(indexData), GL_UNSIGNED_SHORT, 0);`
`+		modelToCameraStack.Pop();`
`+`
`+		DrawWrist(modelToCameraStack);`
`+`
`+		modelToCameraStack.Pop();`
`+	}`
`+`
`+	void DrawUpperArm(MatrixStack &modelToCameraStack)`
`+	{`
`+		modelToCameraStack.Push();`
`+		modelToCameraStack.RotateX(angUpperArm);`
`+`
`+		{`
`+			modelToCameraStack.Push();`
`+			modelToCameraStack.Translate(glm::vec3(0.0f, 0.0f, (sizeUpperArm / 2.0f) - 1.0f));`
`+			modelToCameraStack.Scale(glm::vec3(1.0f, 1.0f, sizeUpperArm / 2.0f));`
`+			glUniformMatrix4fv(modelToCameraMatrixUnif, 1, GL_FALSE, glm::value_ptr(modelToCameraStack.Top()));`
`+			glDrawElements(GL_TRIANGLES, ARRAY_COUNT(indexData), GL_UNSIGNED_SHORT, 0);`
`+			modelToCameraStack.Pop();`
`+		}`
`+`
`+		DrawLowerArm(modelToCameraStack);`
`+`
`+		modelToCameraStack.Pop();`
`+	}`
`+`
`+	glm::vec3		posBase;`
`+	float			angBase;`
`+`
`+	glm::vec3		posBaseLeft, posBaseRight;`
`+	float			scaleBaseZ;`
`+`
`+	float			angUpperArm;`
`+	float			sizeUpperArm;`
`+`
`+	glm::vec3		posLowerArm;`
`+	float			angLowerArm;`
`+	float			lenLowerArm;`
`+	float			widthLowerArm;`
`+`
`+	glm::vec3		posWrist;`
`+	float			angWristRoll;`
`+	float			angWristPitch;`
`+	float			lenWrist;`
`+	float			widthWrist;`
`+`
`+	glm::vec3		posLeftFinger, posRightFinger;`
`+	float			angFingerOpen;`
`+	float			lenFinger;`
`+	float			widthFinger;`
`+	float			angLowerFinger;`
`+};`
`+`
`+`
`+Hierarchy g_armature;`
`+`
`+//Called after the window and OpenGL are initialized. Called exactly once, before the main loop.`
`+void init()`
`+{`
`+	InitializeProgram();`
`+	InitializeVAO();`
`+`
` `
` 	glEnable(GL_CULL_FACE);`
` 	glCullFace(GL_BACK);`
` 	glClearDepth(1.0f);`
` 	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);`
` `
`-	glUseProgram(theProgram);`
`-`
`-	glBindVertexArray(vao);`
`-`
`-	float fElapsedTime = glutGet(GLUT_ELAPSED_TIME) / 1000.0f;`
`-	for(int iLoop = 0; iLoop < ARRAY_COUNT(g_instanceList); iLoop++)`
`-	{`
`-		Instance &currInst = g_instanceList[iLoop];`
`-		const glm::mat4 &transformMatrix = currInst.ConstructMatrix(fElapsedTime);`
`-`
`-		glUniformMatrix4fv(modelToCameraMatrixUnif, 1, GL_FALSE, glm::value_ptr(transformMatrix));`
`-		glDrawElements(GL_TRIANGLES, ARRAY_COUNT(indexData), GL_UNSIGNED_SHORT, 0);`
`-	}`
`-`
`-	glBindVertexArray(0);`
`-	glUseProgram(0);`
`+	g_armature.Draw();`
` `
` 	glutSwapBuffers();`
` 	glutPostRedisplay();`
` 	case 27:`
` 		glutLeaveMainLoop();`
` 		break;`
`+	case ',': g_armature.AdjBase(true); break;`
`+	case '/': g_armature.AdjBase(false); break;`
`+	case 'l': g_armature.AdjUpperArm(false); break;`
`+	case '.': g_armature.AdjUpperArm(true); break;`
`+	case 't': g_armature.AdjLowerArm(false); break;`
`+	case 'g': g_armature.AdjLowerArm(true); break;`
`+	case 'w': g_armature.AdjWristPitch(false); break;`
`+	case 's': g_armature.AdjWristPitch(true); break;`
`+	case 'a': g_armature.AdjWristRoll(true); break;`
`+	case 'd': g_armature.AdjWristRoll(false); break;`
`+`
`+	case 'q': g_armature.AdjFingerOpen(true); break;`
`+	case 'e': g_armature.AdjFingerOpen(false); break;`
`+	case 32: g_armature.WritePose(); break;`
` 	}`
` }`
` `

# File Tut 06 Objects in Motion/Rotations.cpp

` #define ARRAY_COUNT( array ) (sizeof( array ) / (sizeof( array[0] ) * (sizeof( array ) != sizeof(void*) || sizeof( array[0] ) <= sizeof(void*))))`
` `
` GLuint theProgram;`
`-GLuint positionAttrib;`
`-GLuint colorAttrib;`
` `
` GLuint modelToCameraMatrixUnif;`
` GLuint cameraToClipMatrixUnif;`
` `
` 	theProgram = Framework::CreateProgram(shaderList);`
` `
`-	positionAttrib = glGetAttribLocation(theProgram, "position");`
`-	colorAttrib = glGetAttribLocation(theProgram, "color");`
`-`
` 	modelToCameraMatrixUnif = glGetUniformLocation(theProgram, "modelToCameraMatrix");`
` 	cameraToClipMatrixUnif = glGetUniformLocation(theProgram, "cameraToClipMatrix");`
` `
` `
` 	size_t colorDataOffset = sizeof(float) * 3 * numberOfVertices;`
` 	glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject);`
`-	glEnableVertexAttribArray(positionAttrib);`
`-	glEnableVertexAttribArray(colorAttrib);`
`-	glVertexAttribPointer(positionAttrib, 3, GL_FLOAT, GL_FALSE, 0, 0);`
`-	glVertexAttribPointer(colorAttrib, 4, GL_FLOAT, GL_FALSE, 0, (void*)colorDataOffset);`
`+	glEnableVertexAttribArray(0);`
`+	glEnableVertexAttribArray(1);`
`+	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);`
`+	glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, (void*)colorDataOffset);`
` 	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferObject);`
` `
` 	glBindVertexArray(0);`

# File Tut 06 Objects in Motion/Scale.cpp

` #define ARRAY_COUNT( array ) (sizeof( array ) / (sizeof( array[0] ) * (sizeof( array ) != sizeof(void*) || sizeof( array[0] ) <= sizeof(void*))))`
` `
` GLuint theProgram;`
`-GLuint positionAttrib;`
`-GLuint colorAttrib;`
` `
` GLuint modelToCameraMatrixUnif;`
` GLuint cameraToClipMatrixUnif;`
` `
` 	theProgram = Framework::CreateProgram(shaderList);`
` `
`-	positionAttrib = glGetAttribLocation(theProgram, "position");`
`-	colorAttrib = glGetAttribLocation(theProgram, "color");`
`-`
` 	modelToCameraMatrixUnif = glGetUniformLocation(theProgram, "modelToCameraMatrix");`
` 	cameraToClipMatrixUnif = glGetUniformLocation(theProgram, "cameraToClipMatrix");`
` `
` `
` 	size_t colorDataOffset = sizeof(float) * 3 * numberOfVertices;`
` 	glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject);`
`-	glEnableVertexAttribArray(positionAttrib);`
`-	glEnableVertexAttribArray(colorAttrib);`
`-	glVertexAttribPointer(positionAttrib, 3, GL_FLOAT, GL_FALSE, 0, 0);`
`-	glVertexAttribPointer(colorAttrib, 4, GL_FLOAT, GL_FALSE, 0, (void*)colorDataOffset);`
`+	glEnableVertexAttribArray(0);`
`+	glEnableVertexAttribArray(1);`
`+	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);`
`+	glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, (void*)colorDataOffset);`
` 	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferObject);`
` `
` 	glBindVertexArray(0);`

# File Tut 06 Objects in Motion/Translation.cpp

` #define ARRAY_COUNT( array ) (sizeof( array ) / (sizeof( array[0] ) * (sizeof( array ) != sizeof(void*) || sizeof( array[0] ) <= sizeof(void*))))`
` `
` GLuint theProgram;`
`-GLuint positionAttrib;`
`-GLuint colorAttrib;`
` `
` GLuint modelToCameraMatrixUnif;`
` GLuint cameraToClipMatrixUnif;`
` `
` 	theProgram = Framework::CreateProgram(shaderList);`
` `
`-	positionAttrib = glGetAttribLocation(theProgram, "position");`
`-	colorAttrib = glGetAttribLocation(theProgram, "color");`
`-`
` 	modelToCameraMatrixUnif = glGetUniformLocation(theProgram, "modelToCameraMatrix");`
` 	cameraToClipMatrixUnif = glGetUniformLocation(theProgram, "cameraToClipMatrix");`
` `
` `
` 	size_t colorDataOffset = sizeof(float) * 3 * numberOfVertices;`
` 	glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject);`
`-	glEnableVertexAttribArray(positionAttrib);`
`-	glEnableVertexAttribArray(colorAttrib);`
`-	glVertexAttribPointer(positionAttrib, 3, GL_FLOAT, GL_FALSE, 0, 0);`
`-	glVertexAttribPointer(colorAttrib, 4, GL_FLOAT, GL_FALSE, 0, (void*)colorDataOffset);`
`+	glEnableVertexAttribArray(0);`
`+	glEnableVertexAttribArray(1);`
`+	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);`
`+	glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, (void*)colorDataOffset);`
` 	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferObject);`
` `
` 	glBindVertexArray(0);`