Read diffuse textures from 3d models
This commit is contained in:
parent
5a7e5cd10f
commit
08bcb56a5f
|
@ -24,6 +24,7 @@
|
|||
|
||||
#include <glm/ext/matrix_clip_space.hpp>
|
||||
#include <glm/fwd.hpp>
|
||||
#include <assimp/material.h>
|
||||
|
||||
#include <memory>
|
||||
#include <chrono>
|
||||
|
@ -80,7 +81,7 @@ int main(int argc, char *argv[]) {
|
|||
auto light = std::make_shared<se::gfx::Light>(core_shader, glm::vec3(0.f, 1.f, -10.f), glm::vec3(1.f, 1.f, 1.f));
|
||||
game.add_event(light);
|
||||
|
||||
se::gfx::Texture white_texture("examples/dev_testing/resources/white_texture.png");
|
||||
auto white_texture = se::gfx::Texture::white_texture();
|
||||
// white_texture.shine_damper = 10;
|
||||
//white_texture.reflectivity = 1;
|
||||
/* auto dragon = std::make_shared<se::objects_3d::Mesh>(game.get_window(), core_shader, white_texture, "examples/dev_testing/resources/dragon.obj");
|
||||
|
@ -165,11 +166,13 @@ int main(int argc, char *argv[]) {
|
|||
5, 6, 12, 12, 6, 13
|
||||
};
|
||||
|
||||
se::gfx::Material material(white_texture, 1.f, 0.f, 0.f, 0.f, 0.f);
|
||||
std::unordered_map<aiTextureType, std::vector<se::gfx::Texture>> textures;
|
||||
textures.emplace(white_texture.type, std::vector<se::gfx::Texture>{ white_texture });
|
||||
se::gfx::Material white_material(textures, 1.f, 0.f, 0.f, 0.f, 0.f);
|
||||
|
||||
// Create the entity and add the model component to it.
|
||||
/* auto entity = std::make_shared<simpleengine::Entity>();
|
||||
entity->add_component<se::MeshComponent>(cube_vertices, cube_indicies, material, true);
|
||||
entity->add_component<se::MeshComponent>(cube_vertices, cube_indicies, white_material, true);
|
||||
entity->translate(3.5f, 0.f, 0.f); */
|
||||
|
||||
auto entity = std::make_shared<simpleengine::Entity>();
|
||||
|
|
|
@ -2,12 +2,13 @@
|
|||
|
||||
#include "texture.h"
|
||||
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <assimp/material.h>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace simpleengine::gfx {
|
||||
class Material {
|
||||
public:
|
||||
Texture texture;
|
||||
std::unordered_map<aiTextureType, std::vector<Texture>> textures;
|
||||
|
||||
float ambient_scalar;
|
||||
float diffuse_scalar;
|
||||
|
@ -15,8 +16,8 @@ namespace simpleengine::gfx {
|
|||
float shine;
|
||||
float reflectivity;
|
||||
|
||||
Material(Texture texture, float shine = 1.f, float reflectivity = 0.f, float specular_scalar = 0.f, float ambient_scalar = 0.f, float diffuse_scalar = 0.f) :
|
||||
texture(texture), ambient_scalar(ambient_scalar), diffuse_scalar(diffuse_scalar), specular_scalar(specular_scalar),
|
||||
Material(std::unordered_map<aiTextureType, std::vector<Texture>> textures, float shine = 1.f, float reflectivity = 0.f, float specular_scalar = 0.f, float ambient_scalar = 0.f, float diffuse_scalar = 0.f) :
|
||||
textures(textures), ambient_scalar(ambient_scalar), diffuse_scalar(diffuse_scalar), specular_scalar(specular_scalar),
|
||||
shine(shine), reflectivity(reflectivity) {
|
||||
|
||||
}
|
||||
|
|
|
@ -30,8 +30,6 @@ namespace simpleengine::gfx {
|
|||
Mesh(std::vector<LitVertex> vertices, std::vector<GLuint> indicies, Material material);
|
||||
Mesh(std::vector<LitVertex> vertices, std::vector<GLuint> indicies = std::vector<GLuint>(), std::optional<Material> material = std::nullopt);
|
||||
Mesh(std::vector<LitVertex> vertices, std::vector<GLuint> indicies, Material material, gfx::VBO ebo, gfx::VBO vbo, gfx::VAO vao);
|
||||
Mesh(Material material, std::string filename);
|
||||
Mesh(Material material, std::ifstream file_stream);
|
||||
|
||||
virtual void destroy() override;
|
||||
|
||||
|
@ -46,10 +44,5 @@ namespace simpleengine::gfx {
|
|||
*
|
||||
*/
|
||||
void calculate_normals();
|
||||
|
||||
private:
|
||||
void process_vertex(const std::vector<std::string>& vertex_data, const std::vector<glm::vec2>& in_textures,
|
||||
const std::vector<glm::vec3>& in_normals, std::vector<GLuint>& out_indicies,
|
||||
std::vector<glm::vec2>& out_textures, std::vector<glm::vec3>& out_normals);
|
||||
};
|
||||
}
|
|
@ -28,6 +28,6 @@ namespace simpleengine::gfx {
|
|||
void load_model(std::string path);
|
||||
void process_node(aiNode* node, const aiScene* scene);
|
||||
gfx::Mesh process_mesh(aiMesh* mesh, const aiScene* scene);
|
||||
std::vector<Texture> load_material_textures(aiMaterial* material, aiTextureType* type, std::string type_name);
|
||||
std::vector<Texture> load_material_textures(aiMaterial* material, aiTextureType type);
|
||||
};
|
||||
}
|
|
@ -8,7 +8,7 @@
|
|||
#include <gl/gl.h>
|
||||
#endif
|
||||
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <assimp/material.h>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
|
@ -26,19 +26,10 @@ namespace simpleengine::gfx {
|
|||
|
||||
Texture() = default;
|
||||
public:
|
||||
/**
|
||||
* @brief The type of the texture
|
||||
*
|
||||
*/
|
||||
enum Type {
|
||||
TexT_DIFFUSE,
|
||||
TexT_SPECULAR
|
||||
};
|
||||
|
||||
int height;
|
||||
int width;
|
||||
int channels;
|
||||
Type type;
|
||||
aiTextureType type;
|
||||
|
||||
/**
|
||||
* @brief Construct a new Texture object from a path.
|
||||
|
@ -47,7 +38,7 @@ namespace simpleengine::gfx {
|
|||
* @param img_2d Whether or not the texture is 2D.
|
||||
* @param mipmap Whether or not to generate mipmaps for this texture.
|
||||
*/
|
||||
Texture(const char* path, Type type = Type::TexT_DIFFUSE, bool img_2d = true, bool mipmap = true);
|
||||
Texture(const char* path, aiTextureType type = aiTextureType::aiTextureType_DIFFUSE, bool img_2d = true, bool mipmap = true);
|
||||
|
||||
/**
|
||||
* @brief Construct a new Texture object from the loaded file buffer.
|
||||
|
@ -57,7 +48,7 @@ namespace simpleengine::gfx {
|
|||
* @param img_2d Whether or not the texture is 2D.
|
||||
* @param mipmap Whether or not to generate mipmaps for this texture.
|
||||
*/
|
||||
Texture(const unsigned char *const buffer, int buffer_length, Type type = Type::TexT_DIFFUSE, bool img_2d = true, bool mipmap = true);
|
||||
Texture(const unsigned char *const buffer, int buffer_length, aiTextureType type = aiTextureType::aiTextureType_DIFFUSE, bool img_2d = true, bool mipmap = true);
|
||||
|
||||
/**
|
||||
* @brief Construct a new Texture object from the loaded file buffer.
|
||||
|
@ -66,7 +57,7 @@ namespace simpleengine::gfx {
|
|||
* @param img_2d Whether or not the texture is 2D.
|
||||
* @param mipmap Whether or not to generate mipmaps for this texture.
|
||||
*/
|
||||
Texture(std::vector<unsigned char> buffer, Type type = Type::TexT_DIFFUSE, bool img_2d = true, bool mipmap = true);
|
||||
Texture(std::vector<unsigned char> buffer, aiTextureType type = aiTextureType::aiTextureType_DIFFUSE, bool img_2d = true, bool mipmap = true);
|
||||
|
||||
static Texture white_texture();
|
||||
|
||||
|
|
|
@ -21,10 +21,6 @@ namespace simpleengine::gfx {
|
|||
|
||||
}
|
||||
|
||||
Mesh::Mesh(Material material, std::string filename) :
|
||||
Mesh(material, std::ifstream(filename, std::ios::in | std::ios::binary)) {
|
||||
}
|
||||
|
||||
std::vector<std::string> split_string(std::string str, const char delim) {
|
||||
std::istringstream ss(str);
|
||||
|
||||
|
@ -41,90 +37,6 @@ namespace simpleengine::gfx {
|
|||
return tokens;
|
||||
}
|
||||
|
||||
Mesh::Mesh(Material material, std::ifstream file_stream) :
|
||||
vbo(gfx::VBO::init(GL_ARRAY_BUFFER, false)), ebo(gfx::VBO::init(GL_ELEMENT_ARRAY_BUFFER, false)),
|
||||
vao(gfx::VAO::init()), material(material) {
|
||||
|
||||
if (!file_stream.is_open()) {
|
||||
std::cerr << "File stream that was given to ObjModel::ObjModel is not open!" << std::endl;
|
||||
throw std::runtime_error("Failed to open ObjModel model file");
|
||||
}
|
||||
|
||||
// The vertices, texture coords, and normals that were read from the obj file
|
||||
// these are not in a particular order.
|
||||
std::vector<glm::vec3> obj_vertices;
|
||||
std::vector<glm::vec2> obj_textures;
|
||||
std::vector<glm::vec3> obj_normals;
|
||||
|
||||
// The texture coords and normals that have been sorted.
|
||||
std::vector<glm::vec2> textures;
|
||||
std::vector<glm::vec3> normals;
|
||||
|
||||
// Read the vertices, texture coords, and normals. Break when run into indices
|
||||
std::string line;
|
||||
while (std::getline(file_stream, line)) {
|
||||
std::vector<std::string> line_tokens = split_string(line, ' ');
|
||||
|
||||
if (line_tokens.front() == "v") {
|
||||
//glm::vec3 vertex(stof(line_tokens[1]), stof(line_tokens[2]), stof(line_tokens[3]));
|
||||
obj_vertices.emplace_back(stof(line_tokens[1]), stof(line_tokens[2]), stof(line_tokens[3]));
|
||||
} else if (line_tokens.front() == "vt") {
|
||||
obj_textures.emplace_back(stof(line_tokens[1]), stof(line_tokens[2]));
|
||||
} else if (line_tokens.front() == "vn") {
|
||||
obj_normals.emplace_back(stof(line_tokens[1]), stof(line_tokens[2]), stof(line_tokens[3]));
|
||||
} else if (line_tokens.front() == "f") {
|
||||
auto size = obj_vertices.size();
|
||||
textures.resize(size);
|
||||
normals.resize(size);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Process the indicies. This will sort everything for storing inside of the Vertex list.
|
||||
do {
|
||||
if (!line.starts_with("f")) {
|
||||
continue;
|
||||
}
|
||||
std::vector<std::string> line_tokens = split_string(line, ' ');
|
||||
std::vector<std::string> vertex1 = split_string(line_tokens[1], '/');
|
||||
std::vector<std::string> vertex2 = split_string(line_tokens[2], '/');
|
||||
std::vector<std::string> vertex3 = split_string(line_tokens[3], '/');
|
||||
|
||||
process_vertex(vertex1, obj_textures, obj_normals, indicies, textures, normals);
|
||||
process_vertex(vertex2, obj_textures, obj_normals, indicies, textures, normals);
|
||||
process_vertex(vertex3, obj_textures, obj_normals, indicies, textures, normals);
|
||||
} while (std::getline(file_stream, line));
|
||||
|
||||
file_stream.close();
|
||||
|
||||
const int texture_id = 0;
|
||||
|
||||
std::cout << "Texture ID: " << texture_id << std::endl;
|
||||
|
||||
// Insert everything into lit_vertices.
|
||||
for (int i = 0; i < obj_vertices.size(); i++) {
|
||||
vertices.emplace_back(simpleengine::Vectorf(obj_vertices.at(i)), glm::vec3(1.f), textures.at(i), normals.at(i), texture_id);
|
||||
}
|
||||
}
|
||||
|
||||
void Mesh::process_vertex(const std::vector<std::string>& vertex_data, const std::vector<glm::vec2>& in_textures,
|
||||
const std::vector<glm::vec3>& in_normals, std::vector<GLuint>& out_indicies,
|
||||
std::vector<glm::vec2>& out_textures, std::vector<glm::vec3>& out_normals) {
|
||||
|
||||
// Get the index the current vertex and put it in indicies
|
||||
int currentVertexIndex = stoi(vertex_data[0]) - 1;
|
||||
out_indicies.push_back(currentVertexIndex);
|
||||
|
||||
// Read texture coords
|
||||
glm::vec2 current_tex = in_textures.at(stoi(vertex_data[1]) - 1);
|
||||
current_tex.y = 1 - current_tex.y;
|
||||
out_textures.at(currentVertexIndex) = current_tex;
|
||||
|
||||
// Read normals
|
||||
glm::vec3 current_norm = in_normals.at(stoi(vertex_data[2]) - 1);
|
||||
out_normals.at(currentVertexIndex) = current_norm;
|
||||
}
|
||||
|
||||
void Mesh::destroy() {
|
||||
this->ebo.destroy();
|
||||
this->vbo.destroy();
|
||||
|
|
|
@ -7,7 +7,11 @@
|
|||
#include <assimp/material.h>
|
||||
#include <assimp/scene.h>
|
||||
#include <assimp/postprocess.h>
|
||||
|
||||
#include <optional>
|
||||
#include <sstream>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
namespace simpleengine::gfx {
|
||||
Model::Model(std::string file_path) {
|
||||
|
@ -77,38 +81,48 @@ namespace simpleengine::gfx {
|
|||
}
|
||||
}
|
||||
|
||||
std::optional<gfx::Material> op_mat;
|
||||
// Create a default material and white texture.
|
||||
auto white_texture = gfx::Texture::white_texture();
|
||||
std::unordered_map<aiTextureType, std::vector<Texture>> default_textures;
|
||||
default_textures.emplace(white_texture.type, std::vector<Texture>{ white_texture });
|
||||
gfx::Material mat(default_textures, 1.f, 0.f, 0.f, 0.f, 0.f);
|
||||
|
||||
// TODO: Process material
|
||||
if(mesh->mMaterialIndex >= 0) {
|
||||
std::cout << "TODO: Process model materials!" << std::endl;
|
||||
|
||||
/* aiMaterial *material = scene->mMaterials[mesh->mMaterialIndex];
|
||||
std::vector<Texture> diffuseMaps = load_material_textures(material,
|
||||
aiTextureType_DIFFUSE, "texture_diffuse");
|
||||
std::unordered_map<aiTextureType, std::vector<Texture>> textures;
|
||||
aiMaterial *material = scene->mMaterials[mesh->mMaterialIndex];
|
||||
|
||||
textures.insert(textures.end(), diffuseMaps.begin(), diffuseMaps.end());
|
||||
|
||||
std::vector<Texture> specularMaps = load_material_textures(material,
|
||||
aiTextureType_SPECULAR, "texture_specular");
|
||||
textures.insert(textures.end(), specularMaps.begin(), specularMaps.end()); */
|
||||
// Load Diffuse texture maps
|
||||
std::vector<Texture> diffuse_maps = load_material_textures(material, aiTextureType_DIFFUSE);
|
||||
if (!diffuse_maps.empty()) textures.emplace(aiTextureType_DIFFUSE, diffuse_maps);
|
||||
|
||||
// TODO Handle other types of texture maps
|
||||
|
||||
if (!textures.empty()) {
|
||||
// TODO: Find a way to let the user set the scalars.
|
||||
mat = Material(textures, 1.f, 0.f, 0.f, 0.f, 0.f);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: After we start processing materials, this can be put in the else statement as a fallback.
|
||||
|
||||
auto white_texture = gfx::Texture::white_texture();
|
||||
//gfx::Material mat(white_texture);
|
||||
|
||||
//gfx::Texture white_texture("examples/dev_testing/resources/white_texture.png");
|
||||
gfx::Material mat(white_texture, 1.f, 0.f, 0.f, 0.f, 0.f);
|
||||
|
||||
op_mat = std::optional<gfx::Material>(mat);
|
||||
|
||||
//return Mesh(vertices, indices, textures);
|
||||
return Mesh(vertices, indices, op_mat);
|
||||
return Mesh(vertices, indices, mat);
|
||||
}
|
||||
|
||||
std::vector<Texture> Model::load_material_textures(aiMaterial* material, aiTextureType* type, std::string type_name) {
|
||||
std::vector<Texture> Model::load_material_textures(aiMaterial* material, aiTextureType type) {
|
||||
std::vector<Texture> textures;
|
||||
|
||||
for(int i = 0; i < material->GetTextureCount(type); i++) {
|
||||
aiString texture_path;
|
||||
material->GetTexture(type, i, &texture_path);
|
||||
|
||||
std::stringstream ss;
|
||||
ss << model_directory << "/" << texture_path.C_Str();
|
||||
std::string full_path = ss.str();
|
||||
|
||||
Texture texture(full_path.c_str(), type);
|
||||
textures.emplace_back(texture);
|
||||
}
|
||||
|
||||
return textures;
|
||||
}
|
||||
} // namespace simpleengine::gfx
|
|
@ -9,6 +9,7 @@
|
|||
#include "ecs/component/model_component.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <assimp/material.h>
|
||||
|
||||
namespace simpleengine::gfx {
|
||||
void create_mesh_buffers(std::shared_ptr<simpleengine::Component> comp, simpleengine::gfx::Mesh& mesh);
|
||||
|
@ -99,9 +100,17 @@ namespace simpleengine::gfx {
|
|||
shader.set_uniform_float("u_texture_shine", material->shine, false);
|
||||
shader.set_uniform_float("u_texture_reflectivity", material->reflectivity, false);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTextureUnit(0, material->texture.get_texture_id());
|
||||
material->texture.bind();
|
||||
int texture_count = 0;
|
||||
auto diffuse_maps = material->textures.find(aiTextureType_DIFFUSE);
|
||||
for (const auto& texture : diffuse_maps->second) {
|
||||
// We can only bind to 16 textures at a time (indexes are 0-15)
|
||||
if (texture_count >= 16) break;
|
||||
|
||||
glActiveTexture(GL_TEXTURE0 + texture_count);
|
||||
glBindTextureUnit(texture_count, texture.get_texture_id());
|
||||
|
||||
texture_count++;
|
||||
}
|
||||
}
|
||||
|
||||
model.vao.bind();
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#include <stb_image.h>
|
||||
|
||||
namespace simpleengine::gfx {
|
||||
Texture::Texture(const char* path, Type type, bool img_2d, bool mipmap): type(type) {
|
||||
Texture::Texture(const char* path, aiTextureType type, bool img_2d, bool mipmap): type(type) {
|
||||
image_type_gl = img_2d ? GL_TEXTURE_2D : GL_TEXTURE_3D;
|
||||
|
||||
glGenTextures(1, &texture_id);
|
||||
|
@ -12,7 +12,7 @@ namespace simpleengine::gfx {
|
|||
|
||||
int linear_param = mipmap ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
|
||||
|
||||
glTexParameteri(image_type_gl, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(image_type_gl, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(image_type_gl, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
glTexParameteri(image_type_gl, GL_TEXTURE_MIN_FILTER, linear_param);
|
||||
glTexParameteri(image_type_gl, GL_TEXTURE_MAG_FILTER, linear_param);
|
||||
|
@ -35,7 +35,7 @@ namespace simpleengine::gfx {
|
|||
unbind();
|
||||
}
|
||||
|
||||
Texture::Texture(const unsigned char *const buffer, int buffer_length, Type type, bool img_2d, bool mipmap): type(type) {
|
||||
Texture::Texture(const unsigned char *const buffer, int buffer_length, aiTextureType type, bool img_2d, bool mipmap): type(type) {
|
||||
image_type_gl = img_2d ? GL_TEXTURE_2D : GL_TEXTURE_3D;
|
||||
|
||||
glGenTextures(1, &texture_id);
|
||||
|
@ -66,7 +66,7 @@ namespace simpleengine::gfx {
|
|||
unbind();
|
||||
}
|
||||
|
||||
Texture::Texture(std::vector<unsigned char> buffer, Type type, bool img_2d, bool mipmap) :
|
||||
Texture::Texture(std::vector<unsigned char> buffer, aiTextureType type, bool img_2d, bool mipmap) :
|
||||
Texture(buffer.data(), buffer.size(), type, img_2d, mipmap) {
|
||||
|
||||
}
|
||||
|
@ -86,7 +86,7 @@ namespace simpleengine::gfx {
|
|||
texture.width = width;
|
||||
texture.height = height;
|
||||
texture.channels = 4;
|
||||
texture.type = Texture::Type::TexT_DIFFUSE;
|
||||
texture.type = aiTextureType::aiTextureType_DIFFUSE;
|
||||
texture.img_data = data;
|
||||
|
||||
glGenTextures(1, &texture.texture_id);
|
||||
|
|
Loading…
Reference in New Issue