I have been coding in a certain style for some time now, where I try to avoid classes and stick to pure data structures whenever possible. Basically every module of my program has its own namespace in which all the data structures and functions are declared.
I started doing this because I wanted to focus on the actual data that gets processed and wanted to abstract data as little as possible. Performance is very important to me and I would like to develop a minimal, cache- and compiler-friendly style and I need someone to help me understand what I actually do by structuring my code like this.
So this is how I would structure the functionality of loading 3D meshes into my program for example. The actual code is very abbreviated because right now I would like to only focus on the structure with the namespace and the external declarations.
The header Mesh.h
#include "OpenGL.h" //a higher level namespace containing context information
namespace OpenGL{
namespace Mesh{
struct Vertex{
vec3 pos;
vec3 normal;
vec2 uv;
};
struct Material{
vec3 amb;
vec3 diff;
vec3 spec;
float shininess;
};
struct Mesh{
unsigned int indexOffset;
unsigned int indexCount;
unsigned int materialIndex;
};
extern vector<Vertex> allVertices;
extern vector<unsigned int> allIndices;
extern vector<Material> allMaterials;
extern vector<Mesh> allMeshes;
extern string MESH_DIR;
extern vector<string> meshNames; //find mesh index by name
void setMeshDirectory(string pDirectory);
void loadAllMeshes();
Mesh loadMesh(string pFilename);
void addMesh(string pFileName);
}
}
The code file
#include "Mesh.h"
#define DEFAULT_MESH_DIR "..//assets//meshes//"
//define all external variables
vector<Vertex> allVertices = {};
vector<unsigned int> allIndices = {};
vector<Material> allMaterials = {};
vector<Mesh> allMeshes = {};
string MESH_DIR = DEFAULT_MESH_DIR;
vector<string> meshNames = {};
void OpenGL::Mesh::setMeshDirectory(string pDirectory){
MESH_DIR = pDirectory;
}
void OpenGL::Mesh::addMesh(string pFileName){
auto it = find(meshNames.begin(), meshNames.end(), pFileName);
if(it == meshNames.end()){
meshNames.push_back(pFileName);
}else{
//error
}
}
void OpenGL::Mesh::loadAllMeshes(){
allMeshes.resize(meshNames.size()); //resize allMeshes array in advance
for(unsigned int m = 0; 0 < meshNames.size(); ++m){
allMeshes[m] = loadMesh(meshNames[m]);
}
}
OpenGL::Mesh::Mesh OpenGL::Mesh::loadMesh(string pFilename){
Mesh mesh;
mesh.indexOffset = allIndices.size();
unsigned int indexCount;
unsigned int materialIndex;
//use assimp to actually load the mesh from an .obj, .3DS, .fbx (etc) file
//fill allMaterials, allVertices and allIndices with the data from this mesh
mesh.indexCount = indexCount;
mesh.materialIndex = materialIndex;
return mesh;
}