Attempted to follow this tutorial to add model loading.
https://learnopengl.com/Model-Loading/Model Currently getting an error from assimp claiming it's missing data from the example model.
This commit is contained in:
parent
644ac26403
commit
753ec9c857
12 changed files with 199647 additions and 3 deletions
BIN
data/models/backpack/ao.jpg
Normal file
BIN
data/models/backpack/ao.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.8 MiB |
16
data/models/backpack/backpack.mtl
Normal file
16
data/models/backpack/backpack.mtl
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
# Blender MTL File: 'None'
|
||||||
|
# Material Count: 1
|
||||||
|
|
||||||
|
newmtl Scene_-_Root
|
||||||
|
Ns 225.000000
|
||||||
|
Ka 1.000000 1.000000 1.000000
|
||||||
|
Kd 0.800000 0.800000 0.800000
|
||||||
|
Ks 0.500000 0.500000 0.500000
|
||||||
|
Ke 0.0 0.0 0.0
|
||||||
|
Ni 1.450000
|
||||||
|
d 1.000000
|
||||||
|
illum 2
|
||||||
|
map_Kd diffuse.jpg
|
||||||
|
map_Bump normal.png
|
||||||
|
map_Ks specular.jpg
|
||||||
|
|
||||||
199481
data/models/backpack/backpack.obj
Normal file
199481
data/models/backpack/backpack.obj
Normal file
File diff suppressed because it is too large
Load diff
BIN
data/models/backpack/diffuse.jpg
Normal file
BIN
data/models/backpack/diffuse.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.8 MiB |
BIN
data/models/backpack/normal.png
Normal file
BIN
data/models/backpack/normal.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 14 MiB |
BIN
data/models/backpack/roughness.jpg
Normal file
BIN
data/models/backpack/roughness.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.2 MiB |
3
data/models/backpack/source_attribution.txt
Normal file
3
data/models/backpack/source_attribution.txt
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
Model by Berk Gedik, from: https://sketchfab.com/3d-models/survival-guitar-backpack-low-poly-799f8c4511f84fab8c3f12887f7e6b36
|
||||||
|
|
||||||
|
Modified material assignment (Joey de Vries) for easier load in OpenGL model loading chapter, and renamed albedo to diffuse and metallic to specular to match non-PBR lighting setup.
|
||||||
BIN
data/models/backpack/specular.jpg
Normal file
BIN
data/models/backpack/specular.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.4 MiB |
|
|
@ -14,6 +14,7 @@ struct Vertex {
|
||||||
struct Texture {
|
struct Texture {
|
||||||
unsigned int id;
|
unsigned int id;
|
||||||
std::string type;
|
std::string type;
|
||||||
|
std::string path;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Mesh {
|
class Mesh {
|
||||||
|
|
|
||||||
131
src/Model.cpp
131
src/Model.cpp
|
|
@ -1,6 +1,6 @@
|
||||||
#include "Model.h"
|
#include "Model.h"
|
||||||
|
|
||||||
Model::Model(char *path) {}
|
Model::Model(char *path) { loadModel(path); }
|
||||||
Model::Model(Mesh mesh) { this->meshes.push_back(mesh); }
|
Model::Model(Mesh mesh) { this->meshes.push_back(mesh); }
|
||||||
Model::Model(std::vector<Mesh> meshes) { this->meshes = meshes; }
|
Model::Model(std::vector<Mesh> meshes) { this->meshes = meshes; }
|
||||||
|
|
||||||
|
|
@ -21,4 +21,131 @@ void Model::translate(glm::vec3 translation) {
|
||||||
this->model = glm::translate(glm::mat4(1.0f), glm::vec3(this->position));
|
this->model = glm::translate(glm::mat4(1.0f), glm::vec3(this->position));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Model::loadModel(char *path) {}
|
void Model::loadModel(std::string path) {
|
||||||
|
// Attempt to import model data using assimp
|
||||||
|
Assimp::Importer import;
|
||||||
|
const aiScene *scene =
|
||||||
|
import.ReadFile(path, aiProcess_Triangulate | aiProcess_FlipUVs);
|
||||||
|
|
||||||
|
// Check the model got imported correctly
|
||||||
|
if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE ||
|
||||||
|
!scene->mRootNode) {
|
||||||
|
error.crash("Assimp failed to load model data", import.GetErrorString());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
directory = path.substr(0, path.find_last_of('/'));
|
||||||
|
processNode(scene->mRootNode, scene);
|
||||||
|
}
|
||||||
|
void Model::processNode(aiNode *node, const aiScene *scene) {
|
||||||
|
// if the node has meshes process them
|
||||||
|
for (unsigned int i = 0; i < node->mNumMeshes; i++) {
|
||||||
|
aiMesh *mesh = scene->mMeshes[node->mMeshes[i]];
|
||||||
|
meshes.push_back(processMesh(mesh, scene));
|
||||||
|
}
|
||||||
|
// Now process any nodes that this node contains
|
||||||
|
for (unsigned int i = 0; i < node->mNumChildren; i++) {
|
||||||
|
processNode(node->mChildren[i], scene);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// transform assimps mesh format to our own custom one
|
||||||
|
Mesh Model::processMesh(aiMesh *mesh, const aiScene *scene) {
|
||||||
|
std::vector<Vertex> vertices;
|
||||||
|
std::vector<unsigned int> indecies;
|
||||||
|
std::vector<Texture> textures;
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < mesh->mNumVertices; i++) {
|
||||||
|
Vertex vertex;
|
||||||
|
// process vertex postions and add to our mesh
|
||||||
|
vertex.Position = glm::vec3(mesh->mVertices[i].x, mesh->mVertices[i].y,
|
||||||
|
mesh->mVertices[i].z);
|
||||||
|
vertex.Normal = glm::vec3(mesh->mNormals[i].x, mesh->mNormals[i].y,
|
||||||
|
mesh->mNormals[i].z);
|
||||||
|
// Handle texture coords
|
||||||
|
if (mesh->mTextureCoords[0]) {
|
||||||
|
vertex.TexCoords =
|
||||||
|
glm::vec2(mesh->mTextureCoords[0][i].x, mesh->mTextureCoords[0][i].y);
|
||||||
|
} else
|
||||||
|
vertex.TexCoords = glm::vec2(0.0f, 0.0f);
|
||||||
|
|
||||||
|
vertices.push_back(vertex);
|
||||||
|
}
|
||||||
|
// Handle indeces
|
||||||
|
// Loop through the meshes faces to get the correct order
|
||||||
|
for (unsigned int i = 0; mesh->mNumFaces; i++) {
|
||||||
|
aiFace face = mesh->mFaces[i];
|
||||||
|
// loop through and add each face's indecies
|
||||||
|
for (unsigned int faceIndicie = 0; faceIndicie < face.mNumIndices;
|
||||||
|
faceIndicie++) {
|
||||||
|
indecies.push_back(face.mIndices[faceIndicie]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO Handle Assimps material format
|
||||||
|
if (mesh->mMaterialIndex >= 0) {
|
||||||
|
aiMaterial *material = scene->mMaterials[mesh->mMaterialIndex];
|
||||||
|
std::vector<Texture> diffuseMaps = loadMaterialTextures(
|
||||||
|
material, aiTextureType_DIFFUSE, "texture_diffuse");
|
||||||
|
textures.insert(textures.end(), diffuseMaps.begin(), diffuseMaps.end());
|
||||||
|
std::vector<Texture> specularMaps = loadMaterialTextures(
|
||||||
|
material, aiTextureType_DIFFUSE, "texture_diffuse");
|
||||||
|
textures.insert(textures.end(), specularMaps.begin(), specularMaps.end());
|
||||||
|
}
|
||||||
|
return Mesh(vertices, indecies, textures);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<Texture> Model::loadMaterialTextures(aiMaterial *material,
|
||||||
|
aiTextureType type,
|
||||||
|
std::string typeName) {
|
||||||
|
std::vector<Texture> textures;
|
||||||
|
for (unsigned int i = 0; i < material->GetTextureCount(type); i++) {
|
||||||
|
aiString str;
|
||||||
|
material->GetTexture(type, i, &str);
|
||||||
|
bool skip = false;
|
||||||
|
// check we're not loading in a texture we already have
|
||||||
|
for (unsigned int loadedtex = 0; loadedtex < textures_loaded.size();
|
||||||
|
loadedtex++) {
|
||||||
|
if (std::strcmp(textures_loaded[loadedtex].path.data(), str.C_Str()) ==
|
||||||
|
0) {
|
||||||
|
textures.push_back(textures_loaded[loadedtex]);
|
||||||
|
skip = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If the texture isn't already loaded load it here
|
||||||
|
if (!skip) {
|
||||||
|
Texture texture;
|
||||||
|
texture.id = loadTextureFromFile(str.C_Str(), directory);
|
||||||
|
texture.type = typeName;
|
||||||
|
texture.path = str.C_Str();
|
||||||
|
textures.push_back(texture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return textures;
|
||||||
|
}
|
||||||
|
unsigned int Model::loadTextureFromFile(std::string file,
|
||||||
|
std::string directory) {
|
||||||
|
// Use sdl2_image to load the texture.
|
||||||
|
unsigned int texture;
|
||||||
|
SDL_Surface *image = IMG_Load((directory + file).c_str());
|
||||||
|
if (image == nullptr) {
|
||||||
|
error.crash("SDL2_image was unable to load a texture", IMG_GetError());
|
||||||
|
}
|
||||||
|
// Generate the texture and put its reference id in the texture variable
|
||||||
|
glGenTextures(1, &texture);
|
||||||
|
|
||||||
|
// Handle different SDL Surface data types
|
||||||
|
int mode = GL_RGB;
|
||||||
|
if (image->format->BytesPerPixel == 4) {
|
||||||
|
mode = GL_RGBA;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Put image data into texture we've just generated
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, mode, image->w, image->h, 0, mode,
|
||||||
|
GL_UNSIGNED_BYTE, image->pixels);
|
||||||
|
// Whilst we're here we might as well generate mipmaps
|
||||||
|
glGenerateMipmap(GL_TEXTURE_2D);
|
||||||
|
// remove image surface now it's no longer needed to create texture
|
||||||
|
SDL_FreeSurface(image);
|
||||||
|
image = nullptr;
|
||||||
|
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
|
|
|
||||||
15
src/Model.h
15
src/Model.h
|
|
@ -2,11 +2,13 @@
|
||||||
#include "Error.h"
|
#include "Error.h"
|
||||||
#include "Mesh.h"
|
#include "Mesh.h"
|
||||||
#include "ShaderLoader.h"
|
#include "ShaderLoader.h"
|
||||||
|
#include <SDL2/SDL_image.h>
|
||||||
#include <assimp/Importer.hpp>
|
#include <assimp/Importer.hpp>
|
||||||
#include <assimp/postprocess.h>
|
#include <assimp/postprocess.h>
|
||||||
#include <assimp/scene.h>
|
#include <assimp/scene.h>
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <glm/gtc/matrix_transform.hpp>
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
class Model {
|
class Model {
|
||||||
|
|
@ -22,7 +24,18 @@ private:
|
||||||
// Position
|
// Position
|
||||||
glm::vec4 position = glm::vec4(0.0f, 0.0f, 0.0f, 1.0f);
|
glm::vec4 position = glm::vec4(0.0f, 0.0f, 0.0f, 1.0f);
|
||||||
|
|
||||||
void loadModel(char *path);
|
// Load in models using assimp
|
||||||
|
void loadModel(std::string path);
|
||||||
|
// process assimps node structure
|
||||||
|
void processNode(aiNode *node, const aiScene *scene);
|
||||||
|
Mesh processMesh(aiMesh *mesh, const aiScene *scene);
|
||||||
|
std::vector<Texture> loadMaterialTextures(aiMaterial *material,
|
||||||
|
aiTextureType type,
|
||||||
|
std::string typeName);
|
||||||
|
|
||||||
|
std::string directory;
|
||||||
|
unsigned int loadTextureFromFile(std::string texture, std::string directory);
|
||||||
|
std::vector<Texture> textures_loaded;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Create a model from file
|
// Create a model from file
|
||||||
|
|
|
||||||
|
|
@ -186,6 +186,8 @@ int main(int argc, char **argv) {
|
||||||
|
|
||||||
model.translate(glm::vec3(1.0f, 0.0f, 0.0f));
|
model.translate(glm::vec3(1.0f, 0.0f, 0.0f));
|
||||||
|
|
||||||
|
Model backpack(ROOT_DIR "data/models/backpack/backpack.mtl");
|
||||||
|
|
||||||
// Mess with perspective
|
// Mess with perspective
|
||||||
// Projection matrix : 45° Field of View, 4:3 ratio, display range : 0.1
|
// Projection matrix : 45° Field of View, 4:3 ratio, display range : 0.1
|
||||||
// unit <-> 100 units
|
// unit <-> 100 units
|
||||||
|
|
@ -227,6 +229,7 @@ int main(int argc, char **argv) {
|
||||||
// Draw Meshes
|
// Draw Meshes
|
||||||
model2.draw(shader);
|
model2.draw(shader);
|
||||||
model.draw(shader);
|
model.draw(shader);
|
||||||
|
backpack.draw(shader);
|
||||||
|
|
||||||
// Finally render everything
|
// Finally render everything
|
||||||
shader.use();
|
shader.use();
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue