#pragma once #include #include #include #include "../glIncludes.h" #include "glm/glm.hpp" #include "textureManager.h" #define MODEL_PATH_OBJ "../res/models/obj/" #define MODEL_PATH_OFF "../res/models/off/" /** * @struct VBOData * @brief Stores all VBO related data for a model. * * @author Chase Percy * */ struct VBOData { bool vboSafe{true}; /// True if a model has 3 vertices for every face and /// a material GLsizei totalBytes{0}; /// The size of the vbo data GLuint vboID{0}; /// The vertex buffer ID GLuint iboID{0}; /// The index buffer ID GLuint nboID{0}; /// The normal buffer ID GLuint cboID{0}; /// The colour buffer ID }; /** * @struct Face * @brief Contains all the data for a given face on a model. * * @author Chase Percy * */ struct Face { std::vector vertIndices; /// Vertex indices (f with no '/') std::vector texCoordsIndices; /// Texture coordinates (f with one '/') std::vector normalIndices; /// Normal indices (f with two '/') glm::vec3 colour; /// 0 - 255 stored in .r .g .b std::size_t materialID{0}; /// Id to associate to material index bool hasMaterial{false}; /// Flag for material or not }; /** * @struct Material * @brief Contains all the material data for a single material from a mtl file. * * @author Chase Percy * */ struct Material { std::string name; /// The name of the material (newmtl) float ambient[4]; /// The ambient colour, RGB (Ka) float diffuse[4]; /// The diffuse colour, RGB (Kd) float specular[4]; /// The specular colour and weighting, RGBW (Ks, Ns) float transparency; /// The transparency values (d / Tr) std::string mapKD; /// Name of the image to map to (texture) GLuint textureID{0}; /// Texture id for this material, 0 if none. }; /** * @struct Mesh * @brief Contains all the raw mesh data for a model. * * @warning All data stored is not homogenous. * * @author Chase Percy * */ struct Mesh { // NON-HOMOGENOUS std::vector verts; /// Vertex data (v) std::vector texCoords; /// Texture Coordinates (vt) std::vector normals; /// Normal data (vn) std::vector psVerts; /// Polygonal Face element (vp) std::vector> faces; /// Face data (f) std::vector lineElements; /// Line element data (l) std::vector> material; /// Material data (newmtl) }; struct BoundingSphere { glm::vec3 centre{0}; /// The centre of the model glm::vec3 centreNoY{0}; /// The centre of the model with Y at 0 float radius{0}; /// The Max radius of the model float radiusAverage{0}; /// The average radius of the model float radiusNoY{0}; /// The max radius of the model, x & z only }; /** * @class Model * @brief A class that contains all the data for a model as well as the * functions for it to draw itself. The draw function will internally decide if * the model will be drawn in immediate or retained mode rendering. * * @author Chase Percy * */ class Model { public: std::size_t ID; /// ID of the model (location in the vector) std::string name; /// Name of the model (filename with pathing/extension) std::string subPath; /// Sub path from ..res/models/obj (used for material) Mesh mesh; /// Mesh data for the model VBOData vboData; /// VBO data for the model BoundingSphere boundingSphere; /// The bounding sphere for the model /** * Draws a model, applies its colour or texture if applicable. */ void draw() const; private: /** * The classic mode of drawing where all data is passed to the gpu each * frame. Called if a model has VBOSafe defined as false. (HEAVY PERFORMANCE * OVERHEAD) */ void immediateModeDraw() const; /** * The newer mode of drawing where all data is uploaded to the GPU before * runtime so that it can be called internally each frame without being * uploaded. Called if a model has VBOSafe defined as true. */ void retainedModeDraw() const; }; /** * @class ModelManager * @brief Managers a set of models. Loads a set of models from a txt and stores * them internally, providing them when requested. Sorts the VBO data for all * its models once they have all been loaded from the txt. * * @author Chase Percy * */ class ModelManager { public: /** * Pre loads models from the res/preload/models.txt file. All models must * load from the preload list to return true and allow the engine to start. * @param modelPreloadPath the path to the file to preload from. * @return true if all preloads are successful, false otherwise. */ bool init(const std::string& modelPreloadPath); /** * Loads a model with the filename given, file must be stored in res/models * @param fName the filename of the model to load * @return the pointer to the model, else nullptr. */ std::shared_ptr load(const std::string& fName); /** * Returns a model based on its ID * @param ID the ID of the model to retrieve * @return A pointer to the model, else nullptr. */ std::shared_ptr getModel(std::size_t ID); /** * Returns a model based on its ID * @param name the name of the model to retrieve, i.e. the filename. * @return a pointer to the model if found, else nullptr. */ std::shared_ptr getModel(const std::string& name); /** * Finds the bounding sphere for a model at its initial scale. */ void findBoundingSpheres(); private: std::vector> m_models; /// All currently loaded models /* * Creates VBO's for model who meet the requirement and stores the assigned * ID's within the models VBOData struct. */ void VBOSort(); }; /** * @namespace OBJ_LOADER * @brief A namespace that contains a function to load a model from a obj file. * * @author Chase Percy * */ namespace OBJ_LOADER { /** * Loads an obj file and stores it into a model. * @param fName the name of the obj file to open * @return the shared ptr to the model with all loaded data, else nullptr if * failed to load */ std::shared_ptr load(const std::string& fName); } // namespace OBJ_LOADER /** * @namespace OFF_LOADER * @brief A namespace that contains a function to load a model from a off file. * * @author Chase Percy * */ namespace OFF_LOADER { /** * Loads an off file and stores it into a model. * @param fName the name of the off file to open * @return the shared ptr to the model with all loaded data, else nullptr if * failed to load */ std::shared_ptr load(const std::string& fName); } // namespace OFF_LOADER /** * @namespace MTL_LOADER * @brief A namespace that contains a function to load a model from a mtl file. * * @author Chase Percy * */ namespace MTL_LOADER { /** * Loads an mtl file and stores it into a model. Takes model as a parameter * since multiple materials can be stored in one mtl file. * @param fName the name of the mtl file to open * @param model the model to load the mtl data into. */ void load(const std::string& fName, std::shared_ptr& model); } // namespace MTL_LOADER