Can now load a glb model with textures embedded in the model. Further cleanup coming.
This commit is contained in:
parent
5b5e8a9fb0
commit
c6a7c42a4e
12 changed files with 323 additions and 194 deletions
|
|
@ -1,20 +1,14 @@
|
|||
#include "model.hpp"
|
||||
#include "dbc.hpp"
|
||||
#include <print>
|
||||
|
||||
unsigned int TextureFromFile(const std::string& path, const std::string& directory, bool gamma)
|
||||
{
|
||||
std::string filename = path + "/" + filename;
|
||||
unsigned int TextureFromFile(const std::string& path, const std::string& directory);
|
||||
unsigned int TextureFromInternal(const aiScene *scene, size_t index);
|
||||
|
||||
unsigned int to_gl_texture(unsigned char *data, int width, int height, int nrComponents) {
|
||||
unsigned int textureID;
|
||||
glGenTextures(1, &textureID);
|
||||
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
int nrComponents = 0;
|
||||
|
||||
unsigned char *data = stbi_load(filename.c_str(), &width, &height, &nrComponents, 0);
|
||||
dbc::check(data != nullptr, $F("Failed to load texture {}", filename));
|
||||
|
||||
GLenum format = GL_RGB;
|
||||
|
||||
if (nrComponents == 1) {
|
||||
|
|
@ -34,6 +28,48 @@ unsigned int TextureFromFile(const std::string& path, const std::string& directo
|
|||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
return textureID;
|
||||
}
|
||||
|
||||
unsigned int TextureFromInternal(const aiScene *scene, size_t index) {
|
||||
const aiTexture *aiTex = scene->mTextures[index];
|
||||
unsigned int textureID = 0;
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
int nrComponents = 0;
|
||||
unsigned char *data = nullptr;
|
||||
const unsigned char* dataBytes = (const unsigned char*)aiTex->pcData;
|
||||
|
||||
if(aiTex->mHeight == 0) {
|
||||
// compressed texture (PNG or JPG)
|
||||
size_t dataSize = aiTex->mWidth;
|
||||
data = stbi_load_from_memory(dataBytes, dataSize, &width, &height, &nrComponents, 0);
|
||||
textureID = to_gl_texture(data, width, height, nrComponents);
|
||||
stbi_image_free(data);
|
||||
} else {
|
||||
data = (unsigned char*)aiTex->pcData;
|
||||
width = aiTex->mWidth;
|
||||
height = aiTex->mHeight;
|
||||
nrComponents = 4; // either BGRA8888 or RGBA8888
|
||||
textureID = to_gl_texture(data, width, height, nrComponents);
|
||||
}
|
||||
|
||||
return textureID;
|
||||
}
|
||||
|
||||
unsigned int TextureFromFile(const std::string& path, const std::string& directory)
|
||||
{
|
||||
std::string filename = directory + "/" + path;
|
||||
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
int nrComponents = 0;
|
||||
|
||||
unsigned char *data = stbi_load(filename.c_str(), &width, &height, &nrComponents, 0);
|
||||
dbc::check(data != nullptr, $F("Failed to load texture {}", filename));
|
||||
|
||||
unsigned int textureID = to_gl_texture(data, width, height, nrComponents);
|
||||
|
||||
stbi_image_free(data);
|
||||
|
||||
return textureID;
|
||||
|
|
@ -45,9 +81,14 @@ void Model::Draw(Shader &shader) {
|
|||
}
|
||||
}
|
||||
|
||||
void Model::loadModel(std::string path) {
|
||||
void Model::loadModel(const std::string& path) {
|
||||
Assimp::Importer importer;
|
||||
const aiScene* scene = importer.ReadFile(path, aiProcess_Triangulate | aiProcess_GenSmoothNormals | aiProcess_FlipUVs | aiProcess_CalcTangentSpace);
|
||||
|
||||
const aiScene* scene = importer.ReadFile(path,
|
||||
aiProcess_Triangulate |
|
||||
aiProcess_GenSmoothNormals |
|
||||
aiProcess_FlipUVs |
|
||||
aiProcess_CalcTangentSpace);
|
||||
|
||||
dbc::check(scene != nullptr, "Assimp ReadFile return null");
|
||||
dbc::check(!(scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE), "Assimp says incomplete.");
|
||||
|
|
@ -118,54 +159,53 @@ Mesh Model::processMesh(aiMesh *mesh, const aiScene *scene) {
|
|||
// normal: texture_normalN
|
||||
|
||||
// 1. diffuse maps
|
||||
std::vector<Texture> diffuseMaps = loadMaterialTextures(material, aiTextureType_DIFFUSE, "texture_diffuse");
|
||||
textures.insert(textures.end(), diffuseMaps.begin(), diffuseMaps.end());
|
||||
loadMaterialTextures(textures, scene, material, aiTextureType_DIFFUSE, "texture_diffuse");
|
||||
|
||||
// 2. specular maps
|
||||
std::vector<Texture> specularMaps = loadMaterialTextures(material, aiTextureType_SPECULAR, "texture_specular");
|
||||
textures.insert(textures.end(), specularMaps.begin(), specularMaps.end());
|
||||
loadMaterialTextures(textures, scene, material, aiTextureType_SPECULAR, "texture_specular");
|
||||
|
||||
// 3. normal maps
|
||||
std::vector<Texture> normalMaps = loadMaterialTextures(material, aiTextureType_HEIGHT, "texture_normal");
|
||||
textures.insert(textures.end(), normalMaps.begin(), normalMaps.end());
|
||||
loadMaterialTextures(textures, scene, material, aiTextureType_HEIGHT, "texture_normal");
|
||||
|
||||
// 4. height maps
|
||||
std::vector<Texture> heightMaps = loadMaterialTextures(material, aiTextureType_AMBIENT, "texture_height");
|
||||
textures.insert(textures.end(), heightMaps.begin(), heightMaps.end());
|
||||
loadMaterialTextures(textures, scene, material, aiTextureType_AMBIENT, "texture_height");
|
||||
|
||||
return Mesh(vertices, indices, textures);
|
||||
}
|
||||
|
||||
std::vector<Texture> Model::loadMaterialTextures(aiMaterial *mat, aiTextureType type, std::string typeName)
|
||||
void Model::loadMaterialTextures(std::vector<Texture>& textures, const aiScene *scene, aiMaterial *mat, aiTextureType type, std::string typeName)
|
||||
{
|
||||
fmt::println("TEXTURE COUNT: {}, {}, {}", (int)type, typeName, mat->GetTextureCount(type));
|
||||
|
||||
std::vector<Texture> textures;
|
||||
for(unsigned int i = 0; i < mat->GetTextureCount(type); i++) {
|
||||
aiString str;
|
||||
|
||||
mat->GetTexture(type, i, &str);
|
||||
std::string tx_str{str.C_Str()};
|
||||
dbc::check(!tx_str.empty(), "Texture has empty path, should be impossible?");
|
||||
|
||||
bool skip = false;
|
||||
for(unsigned int j = 0; j < textures_loaded.size(); j++) {
|
||||
if(textures_loaded[j].path == tx_str) {
|
||||
textures.push_back(textures_loaded[j]);
|
||||
skip = true;
|
||||
break;
|
||||
if(textures_loaded.contains(tx_str)) {
|
||||
textures.push_back(textures_loaded.at(tx_str));
|
||||
} else {
|
||||
unsigned int tx_id = 0;
|
||||
|
||||
// if it's a *# style path then it's internal
|
||||
if(tx_str[0] == '*') {
|
||||
// get the texture from the internal version
|
||||
tx_id = TextureFromInternal(scene, std::stoi(tx_str.substr(1)));
|
||||
} else {
|
||||
// else get it from a file
|
||||
tx_id = TextureFromFile(tx_str, directory);
|
||||
}
|
||||
}
|
||||
|
||||
if(!skip) {
|
||||
Texture texture{
|
||||
.id = TextureFromFile(tx_str, directory),
|
||||
.id = tx_id,
|
||||
.type = typeName,
|
||||
.path = tx_str,
|
||||
};
|
||||
|
||||
textures.push_back(texture);
|
||||
textures_loaded.push_back(texture);
|
||||
textures_loaded.try_emplace(tx_str, texture);
|
||||
}
|
||||
}
|
||||
|
||||
return textures;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue