Skip to content
106 changes: 105 additions & 1 deletion includes/learnopengl/model.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ unsigned int TextureFromFile(const char *path, const string &directory, bool gam
class Model
{
public:
static unsigned int defaultDiffuse, defaultSpecular, defaultNormal, defaultOther;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can function in the private section. Unless you have external texture you want to use.
There's a way for that too!

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The issue with this is the textureFromFile() function is outside of the model class so when it tries to return Model::defaultDiffuse it can't because that is a private member.


// model data
vector<Texture> textures_loaded; // stores all the textures loaded so far, optimization to make sure textures aren't loaded more than once.
vector<Mesh> meshes;
Expand All @@ -35,6 +37,55 @@ class Model
// constructor, expects a filepath to a 3D model.
Model(string const &path, bool gamma = false) : gammaCorrection(gamma)
{
defaultDiffuse = 0;
defaultSpecular = 0;
defaultNormal = 0;
defaultOther = 0;
Comment thread
CMDR-JohnAlex marked this conversation as resolved.
Outdated
if (defaultDiffuse == 0)
{
uint8_t data[4] = { 255,255,255 };
glGenTextures(1, &defaultDiffuse);
glBindTexture(GL_TEXTURE_2D, defaultDiffuse);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
}
if (defaultSpecular == 0)
{
uint8_t data[3] = { 255,255,255 };
glGenTextures(1, &defaultSpecular);
glBindTexture(GL_TEXTURE_2D, defaultSpecular);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
}
if (defaultNormal == 0)
{
uint8_t data[3] = { 128,128,255 };
glGenTextures(1, &defaultNormal);
glBindTexture(GL_TEXTURE_2D, defaultNormal);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
}
if (defaultOther == 0)
{
uint8_t data[4] = { 0,0,0,0 };
glGenTextures(1, &defaultOther);
glBindTexture(GL_TEXTURE_2D, defaultOther);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
}

loadModel(path);
}

Expand Down Expand Up @@ -173,6 +224,42 @@ class Model
vector<Texture> loadMaterialTextures(aiMaterial *mat, aiTextureType type, string typeName)
{
vector<Texture> textures;

// First check if there isn't a texture, if so create an empty image
if (mat->GetTextureCount(type) == 0)
{
bool skip = false;
for (unsigned int j = 0; j < textures_loaded.size(); j++)
{
std::string name = "DEFAULT_" + typeName;
if (std::strcmp(textures_loaded[j].path.data(), name.c_str()) == 0)
Comment thread
CMDR-JohnAlex marked this conversation as resolved.
Outdated
{
textures.push_back(textures_loaded[j]);
skip = true; // A texture with the same filepath has already been loaded, continue to next one. (optimization)
break;
}
}
if (!skip)
{ // If texture hasn't been loaded already, load it
Texture texture;

if (typeName == "texture_diffuse")
texture.id = defaultDiffuse; // Use the default diffuse texture
else if (typeName == "texture_specular")
texture.id = defaultSpecular; // Use the default specular map
else if (typeName == "texture_normal")
texture.id = defaultNormal; // Use the default normal map
else
texture.id = defaultOther; // Otherwise use the default other because it is just empty

texture.type = typeName;
texture.path = "DEFAULT_" + typeName;
textures.push_back(texture);
textures_loaded.push_back(texture); // Store it as texture loaded for entire model, to ensure we won't unnecessary load duplicate textures.
}
std::cout << "Lack " << typeName << "\n";
}

for(unsigned int i = 0; i < mat->GetTextureCount(type); i++)
{
aiString str;
Expand All @@ -192,6 +279,17 @@ class Model
{ // if texture hasn't been loaded already, load it
Texture texture;
texture.id = TextureFromFile(str.C_Str(), this->directory);
if (texture.id == defaultDiffuse)
{
if (typeName == "texture_diffuse")
texture.id = defaultDiffuse;
if (typeName == "texture_specular")
Comment thread
CMDR-JohnAlex marked this conversation as resolved.
Outdated
texture.id = defaultSpecular;
else if (typeName == "texture_normal")
texture.id = defaultNormal;
else
texture.id = defaultOther;
}
texture.type = typeName;
texture.path = str.C_Str();
textures.push_back(texture);
Expand All @@ -202,6 +300,8 @@ class Model
}
};

unsigned int Model::defaultDiffuse = 0, Model::defaultSpecular = 0, Model::defaultNormal = 0, Model::defaultOther = 0;


unsigned int TextureFromFile(const char *path, const string &directory, bool gamma)
{
Expand Down Expand Up @@ -233,13 +333,17 @@ unsigned int TextureFromFile(const char *path, const string &directory, bool gam
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

stbi_image_free(data);

return textureID;
}
else
{
std::cout << "Texture failed to load at path: " << path << std::endl;
stbi_image_free(data);

return Model::defaultDiffuse;
}

return textureID;
return Model::defaultDiffuse;
}
#endif