Write Up 12
Press Escape to quit the application.
Press the right arrow key to move the pumpkin towards the right.
Press the left arrow key to move the pumpkin towards the left.
Press the up arrow key to move the pumpkin up.
Press the down arrow key to move the pumpkin down.
Press the ‘A’ key to move the camera towards the left.
Press the ‘D’ key to move the camera towards the right.
Press the ‘W’ key to move the camera up.
Press the ‘S’ key to move the camera down.
Press the ‘Q’ key to move the camera backwards.
Press the ‘E’ key to move the camera forwards.
Press the ‘T’ key to rotate the camera counterclockwise along its local Y axis.
Press the ‘G’ key to rotate the camera clockwise along its local Y axis.
Press the ‘Y’ key to rotate the camera counterclockwise along its local X axis.
Press the ‘H’ key to rotate the camera clockwise along its local X axis.
The main objective of Assignment12 was to create binary files from the data of the meshes exported previously from Maya 2018. To do this, four pieces of data where written to a binary. The data included the vertex count, the array of vertices, the index count and the array of indices in that order.
The following is a screenshot of a binary mesh file with the data mentioned previously:
Yellow is the vertex count data which takes 2 bytes.
Red is the vertex array which has 4 elements in this case. The first set of four bytes are for the position’s x component. The second set of four bytes are for the position’s y component. The third set of four bytes are for the position’s z component. The fourth set of four bytes are for the u component. The fifth set of four bytes are for the v component. The sixth set of four bytes are for color where the r, g, b and a components are each represented by one byte.
Green is the index count data which takes 2 bytes.
Purple is the index array which has 6 elements in this case. Each element is and index of 2 bytes.
I chose to put the data in this order to first be able to get the vertex count and then be able to know how much to offset the pointer that points to the block of memory containing the whole chunk of data. Knowing this, the offset would be sizeof(VertexFormats::sMesh) * vertexCount. After this, I chose to read the index count and then offset the pointer by this amount. The index data did not need ant offsetting because this was the last element in the memory chunk.
The advantages of using binary file formats are:
They are smaller which means they take up less space in memory.
They are fast to read from memory which means they are quicker to parse at runtime.
In comparison to human readable files, binary files are harder to understand when seen in a text editor. However, we use them at run-time because the data that they store is quickly readable when loaded. This is possible with a human readable file but reading it would mean that an array of characters is read for each data type and the size of each piece of data varies. This leads to slower data parsing when loading the mesh file. It is not the case with binary files because data types such as uint16_t use the same amount of memory and therefore are quicker to parse at runtime. Human readable files are preferred to store the data because they are easier to understand and debug. These will also not affect runtime since the MeshBuilder project creates a binary version of them.
The built binary mesh files are different for each platform because Direct3D platforms use a left handed winding order and use and inverted v component. The indices for Direct3D will have the second and third indices swapped for every three indices and the v components of every vertex will become 1 – vertexVComponent. As such, the binary mesh files will be different for both platforms.
The following is the code to extract the four pieces of data from binary data at run-time:
auto currentOffset = reinterpret_cast<uintptr_t>(dataFromFile.data);
const auto finalOffset = currentOffset + dataFromFile.size;
const auto vertexCount = *reinterpret_cast<uint16_t*>(currentOffset);
currentOffset += sizeof(vertexCount);
const auto* const vertexArray = reinterpret_cast<VertexFormats::sMesh*>(currentOffset);
currentOffset += sizeof(VertexFormats::sMesh) * vertexCount;
const auto indexCount = *reinterpret_cast<uint16_t*>(currentOffset);
currentOffset += sizeof(indexCount);
const auto* const indexArray = reinterpret_cast<uint16_t*>(currentOffset);
While creating mesh files for a pumpkin mesh downloaded from with 1292 vertices, I noticed the human readable file is 1.3 MB and the generated binary file is 138 KB.
The time it took to load the .lua file and extract the data from the pumpkin mesh file was 0.049752 seconds on an x64 Release build.
The time it took to load and extract the data from the binary pumpkin mesh file was 0.000124 seconds on an x64 Release build.
The time it took me to complete this assignment was 10 hours.