\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 a set of data.

\begin{itemize}
    \item \textbf{Vertices} are simply 3D points;
    \item \textbf{Faces} are polygons defined from vertices (most of the time, they are triangles);
    \item \textbf{Textures} are images that can be applied to faces;
    \item \textbf{Texture coordinates} are information added to a face to describe how the texture should be applied on a face;
    \item \textbf{Normals} are 3D vectors that can give information about light behaviour on a face.
\end{itemize}

The Wavefront OBJ is probably the best format to give an example of 3D model since it describes all these elements in text format.
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, and can have photometric properties such as 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 apply the materials that it declares 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.

Another way to improve the performance of rendering is \textbf{frustum culling}.
Frustum culling is a technique that consists in avoiding drawing objects that are not in the field of view of the user's camera.
It is particularly 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 grouped together depending on their location to keep the frustum culling efficient.
\end{itemize}


