From 2ade6919d1eee6a9904ca6361ece90e43186f771 Mon Sep 17 00:00:00 2001 From: Peder Bergebakken Sundt Date: Fri, 22 Mar 2019 00:01:14 +0100 Subject: [PATCH] Add texture support for models --- src/utilities/imageLoader.cpp | 20 ++++++++++++-- src/utilities/imageLoader.hpp | 5 +++- src/utilities/modelLoader.cpp | 51 +++++++++++++++++++++++------------ src/utilities/modelLoader.hpp | 3 ++- 4 files changed, 58 insertions(+), 21 deletions(-) diff --git a/src/utilities/imageLoader.cpp b/src/utilities/imageLoader.cpp index 643ad47..f593885 100644 --- a/src/utilities/imageLoader.cpp +++ b/src/utilities/imageLoader.cpp @@ -2,19 +2,24 @@ #include #include #include +#include +#include +#include using glm::vec2; +using std::string; +using std::map; using std::vector; typedef unsigned int uint; // Original source: https://raw.githubusercontent.com/lvandeve/lodepng/master/examples/example_decode.cpp -PNGImage loadPNGFile(std::string fileName, bool flip_handedness) { +PNGImage loadPNGFile(string filename, bool flip_handedness) { vector png; vector pixels; //the raw pixels uint width, height; //load and decode - uint error = lodepng::load_file(png, fileName); + uint error = lodepng::load_file(png, filename); if(!error) error = lodepng::decode(pixels, width, height, png); //if there's an error, display it @@ -57,6 +62,17 @@ PNGImage loadPNGFile(std::string fileName, bool flip_handedness) { return image; } +PNGImage* loadPNGFileDynamic(string filename, bool flip_handedness) { + static map cache{}; + if (cache.find(filename) == cache.end()) + cache[filename] = loadPNGFileDynamicNoCaching(filename, flip_handedness); + return cache[filename]; +} +PNGImage* loadPNGFileDynamicNoCaching(string filename, bool flip_handedness) { + PNGImage* out = new PNGImage; + *out = loadPNGFile(filename, flip_handedness); + return out; +} PNGImage makePerlinNoisePNG(uint w, uint h, float scale) { return makePerlinNoisePNG(w, h, vector{scale}); diff --git a/src/utilities/imageLoader.hpp b/src/utilities/imageLoader.hpp index 954ebfa..7f61175 100644 --- a/src/utilities/imageLoader.hpp +++ b/src/utilities/imageLoader.hpp @@ -12,7 +12,10 @@ struct PNGImage { std::vector pixels; // RGBA }; -PNGImage loadPNGFile(std::string fileName, bool flip_handedness=false); +PNGImage loadPNGFile(std::string filename, bool flip_handedness=false); + +PNGImage* loadPNGFileDynamic(std::string filename, bool flip_handedness=false); +PNGImage* loadPNGFileDynamicNoCaching(std::string filename, bool flip_handedness=false); PNGImage makePerlinNoisePNG(uint w, uint h, float scale=0.1); diff --git a/src/utilities/modelLoader.cpp b/src/utilities/modelLoader.cpp index 58800f2..b32cff1 100644 --- a/src/utilities/modelLoader.cpp +++ b/src/utilities/modelLoader.cpp @@ -25,15 +25,14 @@ using std::endl; SceneNode* buildSceneNodes( const aiNode* node, const vector& meshes, - const vector& textures, const vector& mat_lookup) { - if (DEBUG) cout << "Building node from " << node->mName.C_Str() << "..." << endl; + if (DEBUG) cout << "Building node from " << node->mName.data << "..." << endl; // filter semantic-only nodes if (node->mTransformation.IsIdentity() && node->mNumMeshes == 0 && node->mNumChildren == 1) - return buildSceneNodes(node->mChildren[0], meshes, textures, mat_lookup); + return buildSceneNodes(node->mChildren[0], meshes, mat_lookup); SceneNode* out = createSceneNode(); @@ -58,15 +57,15 @@ SceneNode* buildSceneNodes( } for (uint i=0; imNumChildren; i++) - out->children.push_back(buildSceneNodes(node->mChildren[i], meshes, textures, mat_lookup)); + out->children.push_back(buildSceneNodes(node->mChildren[i], meshes, mat_lookup)); return out; } -SceneNode* loadModelScene(const std::string& filename, const map& overrides) { +SceneNode* loadModelScene(const std::string& dirname, const std::string& filename, const map& overrides) { Assimp::Importer importer; - const aiScene* scene = importer.ReadFile(filename, + const aiScene* scene = importer.ReadFile(dirname + "/" + filename, aiProcess_CalcTangentSpace //| aiProcess_FlipWindingOrder | aiProcess_Triangulate @@ -82,7 +81,7 @@ SceneNode* loadModelScene(const std::string& filename, const map& // read materials uint j=0; - Material default_material = Material().diffuse({1, 1, 1}); + Material default_material; vector materials(scene->mNumMaterials); for (Material& material : materials) { const aiMaterial* aimat = scene->mMaterials[j++]; @@ -90,9 +89,9 @@ SceneNode* loadModelScene(const std::string& filename, const map& // print material aiString name; aimat->Get(AI_MATKEY_NAME, name); if (DEBUG){ - cout << "Read material #" << j-1 << " '" << name.C_Str() << "':" << endl; + cout << "Read material #" << j-1 << " '" << name.data << "':" << endl; for (uint i=0; i < aimat->mNumProperties; i++) - cout << " " << aimat->mProperties[i]->mKey.C_Str() << endl; + cout << " " << aimat->mProperties[i]->mKey.data << endl; } aiColor3D color (1,1,1); @@ -111,8 +110,32 @@ SceneNode* loadModelScene(const std::string& filename, const map& // material.specular_color = {color4.r, color4.g, color4.b}; aimat->Get(AI_MATKEY_SHININESS, material.shininess); + //todo: opacity? + + if (aimat->GetTextureCount(aiTextureType_DIFFUSE)) { + aiString path; aimat->GetTexture(aiTextureType_DIFFUSE, 0, &path); + if (DEBUG) cout << " diffuse texture path: " << dirname << "/" << path.data << endl; + material.diffuse_texture = loadPNGFileDynamic(dirname + "/" + path.data); + } + if (aimat->GetTextureCount(aiTextureType_NORMALS)) { + aiString path; aimat->GetTexture(aiTextureType_NORMALS, 0, &path); + if (DEBUG) cout << " normal texture path: " << dirname << "/" << path.data << endl; + material.normal_texture = loadPNGFileDynamic(dirname + "/" + path.data); + } + if (aimat->GetTextureCount(aiTextureType_DISPLACEMENT)) { + aiString path; aimat->GetTexture(aiTextureType_DISPLACEMENT, 0, &path); + if (DEBUG) cout << " displacement texture path: " << dirname << "/" << path.data << endl; + material.displacement_texture = loadPNGFileDynamic(dirname + "/" + path.data); + } + if (aimat->GetTextureCount(aiTextureType_REFLECTION)) { + aiString path; aimat->GetTexture(aiTextureType_REFLECTION, 0, &path); + if (DEBUG) cout << " displacement texture path: " << dirname << "/" << path.data << endl; + material.reflection_texture = loadPNGFileDynamic(dirname + "/" + path.data); + } + } + // apply material overriders to material list for (auto override : overrides) { Material& mat = (override.first>=0) ? materials[override.first] @@ -121,7 +144,6 @@ SceneNode* loadModelScene(const std::string& filename, const map& } vector meshes( scene->mNumMeshes); - vector textures(scene->mNumTextures); vector mat_lookup(scene->mNumMeshes); // to be passed to buildSceneNodes // read meshes @@ -174,13 +196,8 @@ SceneNode* loadModelScene(const std::string& filename, const map& } } - // read textures - j=0; - for (PNGImage& texture : textures) { - const aiTexture* aitex = scene->mTextures[j++]; - // todo - } - SceneNode* out = buildSceneNodes(scene->mRootNode, meshes, textures, mat_lookup); + // build scene node tree: + SceneNode* out = buildSceneNodes(scene->mRootNode, meshes, mat_lookup); out->rotation.x += M_PI/2; // account for my weird coordinates. Z is upward damnit! return out; } diff --git a/src/utilities/modelLoader.hpp b/src/utilities/modelLoader.hpp index 6dd2fa2..69566e5 100644 --- a/src/utilities/modelLoader.hpp +++ b/src/utilities/modelLoader.hpp @@ -8,5 +8,6 @@ #define DEBUG false SceneNode* loadModelScene( - const std::string& filename, + const std::string& dirname, + const std::string& filename, //basename const std::map& overrides={});