{{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: ![](defaultscene.png) 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.