\section{What is a 3D model?}

Before talking about 3D streaming, we need to define what is a 3D model and how it is rendered.

\subsection{Content of a 3D model}

A 3D model consists in 3D points (that are called \emph{vertices}), texture coordinates, nomals, faces, materials and textures.
The Wavefront OBJ is probably the best to give an introduction to 3D models since it describes all these elements.
A 3D model encoded in the OBJ format typically consists in two files: the materials file (\texttt{.mtl}) and the object file (\texttt{.obj}).

\paragraph{}
The materials file declare all the materials that the object file will reference.
Each material has a name, ambient, diffuse and specular colors, as well as texture maps.
A simple material file is visible on Listing~\ref{i:mtl}.

\paragraph{}
The object file declare the 3D content of the objects.
It declares vertices, texture coordinates and normals from coordinates (e.g.\ \texttt{v 1.0 2.0 3.0} for a vertex, \texttt{vt 1.0 2.0} for a texture coordinate, \texttt{vn 1.0 2.0 3.0} for a normal).
These elements are numbered starting from 1.
Faces are declared by using the indices of these elements. A face is a polygon with any number of vertices and can be declared in multiple manners:

\begin{itemize}
    \item \texttt{f 1 2 3} defines a triangle face that joins the first, the second and the third vertex declared;
    \item \texttt{f 1/1 2/3 3/4} defines a triangle similar but with texture coordinates, the first texture coordinate is associated to the first vertex, the third texture coordinate is associated to the second vertex, and the fourth texture coordinate is associated with the third vertex;
    \item \texttt{f 1//1 2//3 3//4} defines a triangle similar but using normal instead of texture coordinates;
    \item \texttt{f 1/1/1 2/3/3 3/4/4} defines a triangle with both texture coordinates and normals.
\end{itemize}

It can include materials from a material file (\texttt{mtllib path.mtl}) and use apply it to faces.
A material is applied by using the \texttt{usemtl} keyword, followed by the name of the material to use.
The faces declared after a \texttt{usemtl} are painted using the material in question.
An example of object file is visible on Listing~\ref{i:obj}.

\begin{figure}[th]
    \centering
    \begin{subfigure}[b]{0.4\textwidth}
        \lstinputlisting[
            language=XML,
            caption={An object file describing a cube},
            label=i:obj,
        ]{assets/introduction/cube.obj}
    \end{subfigure}\quad%
    \begin{subfigure}[b]{0.4\textwidth}
        \lstinputlisting[
            language=XML,
            caption={A material file describing a material},
            label=i:mtl,
        ]{assets/introduction/materials.mtl}
        \vspace{0.2cm}
        \includegraphics[width=\textwidth]{assets/introduction/cube.png}
        \caption*{A rendering of the cube}
    \end{subfigure}
    \caption{The OBJ representation of a cube and its render\label{i:cube}}
\end{figure}

\subsection{Rendering a 3D model\label{i:rendering}}

To be able to render a model, it is first required to send the data (vertices, textures coordinates, normals, faces and textures) to the GPU, and then only the rendering can be done.
Then, to render a 3D model, the objects from the model are traversed, the materials and textures are bound to the target on which the rendering will be done, and then, \texttt{glDrawArray} or \texttt{glDrawElements} function is called.
To understand how performance is impacted by the structure of the model, we need to realize two things:

\begin{itemize}
    \item calling many times \texttt{glDrawArray} on small arrays is considerably slower than calling it once on a big array;
    \item calling \texttt{glDrawArray} on a small array is faster than calling it on a big array.
\end{itemize}

However, due to the way the materials and textures work, we are forced to call \texttt{glDrawArray} at least as many times as there are materials in the model.
Minimizing the numbers of materials used in a 3D model is thus critical for rendering performances.

However, frustum culling can be used to improve the performance of rendering.
Frustum culling is a technique that consists in avoiding drawing objects that are not in the field of view of the user's camera.
Frustum culling is efficient when they are many objects in a scene since it gives potential for skips.

These two aspects are somehow contradictory, and to have greatest performance for 3D rendering, one must ensure that:
\begin{itemize}
    \item the least amount of materials are used, and most objects that share materials are drawn together in a single \texttt{glDrawArray} call;
    \item objects are not all drawn together and regrouped by location to keep the frustum culling efficient.
\end{itemize}


