\documentclass[letterpaper,10pt]{article} %\topmargin -1in %\textheight 10in %\oddsidemargin -0.25in %\evensidemargin 0in %\textwidth 6.5in \setlength{\parindent}{0pt} \setlength{\parskip}{1em} \pagestyle{empty} \usepackage{geometry} \geometry{papersize={216mm,279mm},total={176mm,239mm}} \usepackage{listings} \lstloadlanguages{C++} \title{CSC418 Assignment \#2} \author{Aly Merchant [991579083]} \begin{document} \maketitle \section{Rendering} The dog is rendered using a method similar to that of assignment one. The difference is that if an object appears only once it will join its parent. For example limbs are rendered four times so they are separated but the tail is rendered only once and is quite simple so it is rendered with the torso. The general method used for rendering: \begin{enumerate} \item translate to the joint location on the current object \item for sliding joints translate by the specified amount \item rotate the joint to its standard position (e.g. neck points up at 30$^o$) \item rotate the joint about its degrees of freedom (yaw = $\hat{y}$, pitch = $\hat{z}$, elbow/knee = $\hat{z}$) \item push a new matrix stack \item scale the object to be rendered \item translate to the middle of the object \item render using a cube, prism or pyramid \item pop the matrix stack \end{enumerate} Most of the dog is rendered using the {\tt drawCube()} function; however, I added a {\tt drawExtrudedTri()} and {\tt drawPyramid()} which render an extruded triangle and a square-based pyramid respectively. In writing these function I encountered some problems with the ordering of verticies: since back-face removal was enabled the order of the verticies determine which side is facing the camera. The different rendering styles were implemented by supplying different arguments to {\tt glPolygonMode()}. Wireframe rendering was done by setting {\tt (GL\_FRONT, GL\_LINE)} and {\tt (GL\_BACK, GL\_LINE)}. Solid rendering was handled by {\tt (GL\_FRONT, GL\_FILL)}. The outline rendering was a combination of the previous methods, where the dog was rendered as solid first, then in wireframe. For this to work correctly {\tt glPolygonOffset(-0.1, 0.0)} was used to ensure the lines would be drawn over the filled areas. This does produce some artifacts where small portions of lines can be seen through filled faces which should be in front of them. \section{Animation} Most of the work for keyframe capture was done in the starter code. The only code added was to copy the data in {\tt joint\_ui\_data} and to keep track of the end frame. The interpolation routine required some special cases. For a single keyframe, or at the end of a sequence the last keyframe is displayed. If the time is between the first and second keyframes then the tangent vector should go from the first to the second points. If the time is between the second last and last keyframes the tangent vector should go from the second last to the last point. In all other cases the following formula was used: $$p(t) = p_j + t(q_j) + t^2(-3p_j + 3p_{j+1} - 2q_j - q_{j+1}) + t^3(2p_j - 2p_{j+1} + q_j + q_{j+1})$$ where $$ j \leq t \leq j+1 $$ $$ q_j = p_{j+1}-p_{j-1} $$ $$ q_{j+1} = p_{j+2}-p_{j} $$ . The implementation was greatly simplified by the vector class provided with the starter code and closely resemble the formula above where each of $p_{j-1},p_j,p_{j+1},p_{j+2}$ are the {\tt jointDOFS} vectors from elements in the {\tt keyframes} array. \section{Code Listing} \lstset{numbers=left,stepnumber=5,numberstyle=\tiny,numbersep=5pt,breaklines=true} \lstinputlisting[language=c++,tabsize=2]{dog.cpp} \end{document}