{{FULL_COURSE}} Homework 2 - Scene Graph
Overview
-----
You will create a tree data structure wherein each node contains a
transformation matrix, and child nodes inherit the transformations of their
parent nodes. During this process you will reinforce your knowledge of C++
pointers and polymorphism as well as linear algebra transformation sequences.
Supplied Code
---------
Click here to access
the homework's Github repository.
We will provide you with a basic Qt GUI that consists of only a window with a
widget to render 2D scenes using OpenGL. You are free to organize your code and
classes however you like as long as they adhere to the requirements outlined
below. Additionally, we have provided a robust library of linear algebra functions
called GLM (OpenGL Mathematics) to use for your transformation needs. The
library you wrote for homework 1 was designed to be very similar in format to
the classes and functions provided by GLM, but there are some differences in
inputs to the transformation matrix functions GLM provides.
You can find the
(admittedly difficult to navigate) documentation for GLM here.
When your project runs successfully, you should see the following scene:

You can toggle the grid off and on by pressing the `G` key on your keyboard.
Conceptual Questions (10 points, Due Friday, September 15 at 11:59 PM)
-------------
Before you begin the programming portion of this homework assignment, read
and answer the following conceptual questions. Your answers should be submitted
as a plaintext (`.txt`) file.
* (3 pts) In C++, what is a virtual function and how does it relate to object
polymorphism? Say I have a class `Base` and a class `Derived` that inherits from
`Base`. Both classes implement a __non__-virtual function called `func()`. If `func()` is
invoked by dereferencing a `Base*` that actually points to an
instance of `Derived`, which implementation of `func()` will be called, and why?
* (2 pts) In `polygon.cpp` there is a constructor for the `Polygon` class that
takes in a number of sides to construct a regular, convex polygon. There is a
section of this constructor's body that sets up "indices" to construct triangles
out of the polygon's perimeter vertices. Please draw how these triangles would
be formed for a regular convex pentagon (five-sided polygon), and label each
vertex with its index number. You may draw your image on a piece of paper and
take a photograph, or create it in some sort of image editing software. Your
drawing need not be perfect, just make sure it's understandable. In the
end, please submit your drawing as a `.png` image.
* (5 pts) If I want to write a function that builds my entire scene graph and
returns its root node, what should the return type of the function be?
Additionally, where in memory should I instantiate the nodes of my scene graph?
Why should I instantiate my nodes in this portion of memory?
Help Log (5 points)
-------
Maintain a log of all help you receive and resources you use. Make sure the date and time, the names of everyone you work with or get help from, and every URL you use, except as noted in the collaboration policy. Also briefly log your question, bug or the topic you were looking up/discussing. Ideally, you should also the answer to your question or solution to your bug. This will help you learn and provide a useful reference for future assignments and exams. This also helps us know if there is a topic that people are finding difficult.
If you did not use external resources or otherwise receive help, please submit a help log that states you did not receive external help.
You may submit your help log as an ASCII (plain) text file or as a PDF. Refer to the Policies section of the course web site for more specifications.
Code Requirements (85 points, Due Wednesday, September 20 at 11:59 PM)
-------
### Node classes (25 points) ###
A scene graph is a node-based tree data structure used to organize geometry in
computer graphics. You will create a basic `Node` class which should support the
following features:
* A set of pointers to the node's children. We recommend using `std::vector`s to
store the pointers, since they act as dynamically resizeable arrays.
* A pointer to one instance of geometry.
* The color with which to draw the geometry pointed to by the node, if
applicable. This should be stored as a `vec3` with elements in the range [0,1].
You will use this to temporarily override the color attribute of the geometry
pointed to by this node. This enables you to draw the same basic geometry with
differing transformations and colors without having to create a duplicate, as
demonstrated in the example scene drawing code in `MyGL::paintGL`.
* A __purely virtual__ function that computes and returns a 3x3 homogeneous
matrix representing the transformation in the node.
* A QString to represent a name for the node. This will be used later on when
you create a GUI to display your scene graph nodes.
* A function that adds a given `Node*` as a child to this node.
* A function that allows the user to modify the color stored in this node.
Additionally, you will create the following classes that inherit from the basic
`Node` class:
* `TranslateNode`, which stores two floating point numbers: one that represents
its translation in the X direction, and one that represents its translation in
the Y direction.
* `RotateNode`, which stores one floating point number which represents the
magnitude of its rotation in degrees.
* `ScaleNode`, which stores two floating point numbers: one that represents
its scale in the X direction, and one that represents its scale in
the Y direction.
All three subclasses should implement the purely virtual function you declared
in your `Node` class that computes and returns a 3x3 transformation matrix.
Additionally, make sure you remember to use initializer lists in your
constructors and to make your destructors `virtual`.
### Scene graph construction (35 points) ###
Add a member variable to `MyGL` that represents the root node of your scene
graph. Then, write a function that you invoke from within `MyGL::initializeGL`
that constructs your entire scene graph and returns its root node, which you
will store in `MyGL`'s member variable.
Within your scene graph construction function, you will build a scene graph
that forms a humanoid puppet. This puppet must have the following features:
* At least two limbs that each have two segments, e.g. upper arm and forearm.
Each arm segment must pivot about one of its ends, such that if both segments
are rotated the limb curls as an arm or leg would.
* A head or head-analogue that pivots about its base. You may choose to include
a neck if you wish.
* A torso that serves as the "root" of all body transformations. In other words,
any transformations you apply to the torso should apply to the rest of the
character's body.
### Qt GUI (25 points) ###
Add the following elements to your GUI in order to enable interactive alteration
of your nodes' transformation values. You can edit the GUI that appears when
you run your program by opening `Forms/forms/mainwindow.ui` in Qt Creator:
* A Tree Widget (NOT a Tree View) off to the side of the OpenGL rendering window.
This widget will be used to display your scene graph nodes. See the explanation
in the next paragraph for more information.
* A set of five Spin Boxes that enable the user to edit the translation,
rotation, and scale of a given node.
* A button that, when clicked, sets the geometry pointer of the currently
selected node to be `MyGL`'s `m_geomSquare` if that node does not already have
geometry.
* Three buttons that each allow the user to add a new node as a child of the
currently selected node, with one button for each type of node (translate,
rotate, and scale).
In order for your Tree Widget to display your nodes, you will have to add the
following functionality to your node class:
* Have your node class inherit from the `QTreeWidgetItem` class
* In the function you wrote to add a node as a child to another node,
invoke `QTreeWidgetItem::addChild`, with the child node as the input.
* In your node's constructor(s), invoke `setText` on your node's name. This
will allow the name to show up in the tree widget.
* Just after you invoke your scene graph building function, have `MyGL` emit
a signal to `MainWindow` that contains your root node. `MainWindow`'s receiving
slot will invoke `ui->treeWidget.addTopLevelItem` on this root node in order
to add your entire scene graph to the tree widget at once. Note that if you
renamed your tree widget in the GUI editor then it will be called whatever you
named it, not `treeWidget`.
Coding Style (10 points)
----------
We will provide you with feedback on the organization and clarity of the code
you have written for this assignment. Please refer to our course style guide as
you implement your scene graph.
Extra Credit (20 points maximum)
-------------------------------
Include a readme.txt file in your repository that lists which extra credit
features you implemented and how to display them.
### Artistically interesting scene (5 pts) ###
Go beyond the basic requirements for your puppet and add detail to your scene.
Give your character a face, props, clothing, etc. Have fun with it!
### Polished GUI (5 - 10 pts) ###
Connect signals and slots in your GUI such that when a particular type of
node is selected in your tree widget, only the transformation adjustment widgets
that are compatible with that node are "active". For additional points, alter
the visual style of your GUI with Qt style sheets so it looks more professional
and less "default Windows/OSX user interface".
### Support concave polygons (15 pts) ###
Modify the constructor of `Polygon2D` that takes in a list of vertices such that
its triangulation process works on both concave and convex polygons. You
may have to add additional vertices to the polygon to make this work.
Submission
--------
We will grade the code you have pushed to your GitHub repository, so make sure
that you have correctly committed all of your files! Once you have pushed your
finished project to GitHub, submit a link to your commit through the course
dashboard. If you click on the Commits tab of your repository on Github, you
will be brought to a list of commits you've made. Simply click on the one you
wish for us to grade, then copy and paste the URL of the page into your text
file.