Your Assignment: Part 1 (50 pts) The first part of this assignment focuses on helping you get a better grasp of the renderer and the math that we will be using to ray trace a scene. There are two main tasks that you need to complete for this partare as follows and should be completed in assignment.cpp: 1. (20 Points) Your first task is to modify the Superquadric::IOTest() function. Its purpose is to ensure that you understand the math behind superquadrics, and to verify that you can test a point in world space using the inside-outside function of a transformed superquadric. What we want for you to do is to update the function IOTest() to return true if the corresponding coordinate passed is inside a superquadric and false otherwise. You should only need to change code where we have marked a TODO. Remember. don’t forget to apply the inverse superquadric transformations to each point you test, as the inside-outside function assumes the superquadric is centered at the origin. 2. (5 Points) Your second task is to modify the Assembly::IOTest() function. Its purpose is to ensure that you understand the math behind hierarchical scene formats. Since an assembly is essentially just a list of sub-objects, this is a straightforward recursive function. Make sure that you apply the assembly transformations. Once this (and the previous part) is completed, pressing `i` in the raytracer should render some small spheres at positions that are inside of the objects in the scene. 3. (20 Points) Your third task is to implement the Superquadric::ClosestIntersection() function. Its purpose is to ensure that you can intersect a ray with a superquadric, assuming it hits one. Given the ray equation a→t+b→ where b→ is the camera position and a→ is the direction the camera is looking, then we want to be able to find the first intersection with a superquadric (if it exists). Don’t forget to apply each superquadric’s inverse transformations to your ray. 4. (5 Points) Your fourth task is to implement the Assembly::ClosestIntersection() function. Its purpose is to ensure that you can intersect a ray with a hierarchical object, assuming it hits one. In order to intersect the above vector with an assembly, you must test if it hits each child of the assembly, and choose the intersection (if there is one) closest to the camera. Your Assignment: Part 2 (50 pts) For this part of the assignment, you must provide an implementation of the Scene::Raytrace() function, in assignment.cpp. This function should send a ray out from the camera through each pixel in a grid of arbitrary size, and compute the lighting at its first intersection with a superquadric. The point breakdown is as follows: 1. (30 points) for a correct implementation of the Phong model at each ray-superquadric intersection. 2. (20 points) for a correct implementation of shadowing at each ray-superquadric intersection. Here, we want you to output the raytraced images as a PNG. In order to make this easier, we've provided an Image class. You can set the color of pixel using the SetPixel() method, which takes two ints representing the x and y indices of the pixel, and three floats in the range [0,1] representing the red, green, and blue intensities for the pixel. The version of Scene::Raytrace() provided contains a simple example of its usage, looping through the entire grid and coloring it entirely white. Note that because the lecture note derivation of the ray equation assumes (0,0) to be in the lower left corner of the screen, so does the Image class. The size of the output image is currently set to 500x500 using a couple of constants at the top of the file, but you are free to set the resolution to whatever you desire. Just be aware that ray tracing can take a long time, so you might want to test your code with smaller images before. Using smaller images can also be a useful debugging step. Since the Raytrace() function is a member function of the Scene class, it can use all of the member variables of the Scene class defined in scene.cpp. The Scene::ClosestIntersection function will likely be very useful. Finally, because the raytracing process can take such a long time, we spawn it in a separate thread that runs in the background while the rest of the program continues executing as usual.