diff --git a/AimGL/resources/Models/tree/tree.png b/AimGL/resources/Models/tree/tree.png new file mode 100644 index 0000000..50cc97e Binary files /dev/null and b/AimGL/resources/Models/tree/tree.png differ diff --git a/AimGL/resources/Models/tree/tree_bark.png b/AimGL/resources/Models/tree/tree_bark.png new file mode 100644 index 0000000..3ed2756 Binary files /dev/null and b/AimGL/resources/Models/tree/tree_bark.png differ diff --git a/AimGL/resources/Models/tree/tree_combined.png b/AimGL/resources/Models/tree/tree_combined.png new file mode 100644 index 0000000..d9aaa34 Binary files /dev/null and b/AimGL/resources/Models/tree/tree_combined.png differ diff --git a/AimGL/resources/Shaders/Graphics/InfiniteGridFloor.fs b/AimGL/resources/Shaders/Graphics/InfiniteGridFloor.fs index ddee668..3bb096e 100644 --- a/AimGL/resources/Shaders/Graphics/InfiniteGridFloor.fs +++ b/AimGL/resources/Shaders/Graphics/InfiniteGridFloor.fs @@ -4,7 +4,7 @@ out vec4 FragColor; float near = 0.01f; -float far = 20.f; +uniform float far = 5.f; in vec3 nearPoint; in vec3 farPoint; diff --git a/AimGL/resources/Shaders/Graphics/Model/ModelTextured.fs b/AimGL/resources/Shaders/Graphics/Model/ModelTextured.fs new file mode 100644 index 0000000..3d7cea7 --- /dev/null +++ b/AimGL/resources/Shaders/Graphics/Model/ModelTextured.fs @@ -0,0 +1,50 @@ +#version 330 core + +out vec4 FragColor; + +in vec3 FragmentNormal; +in vec3 FragPos; +in vec2 TexCoords; + +uniform vec3 lightPos = vec3(3, 3, 3); +uniform vec3 cameraPosition; +uniform vec3 lightColor = vec3(1,1,1); + +struct Material { + bool isDiffusePresent; + bool isSpecularPresent; + sampler2D diffuse; + sampler2D specular; // not used yet +}; + +uniform Material material; + +void main() +{ + // ambient + float ambientStrength = 0.1; + vec3 ambientColor = vec3(1.0, 1.0, 1.0); + vec3 ambient = ambientStrength * ambientColor; + + // diffuse + vec3 norm = normalize(FragmentNormal); + vec3 lightDir = normalize(lightPos - FragPos); + float diff = max(dot(norm, lightDir), 0.0); + vec3 diffuseLight = diff * lightColor; + + // specular + float specularStrength = 0.5; + vec3 viewDir = normalize(cameraPosition - FragPos); + vec3 reflectDir = reflect(-lightDir, norm); + float spec = pow(max(dot(viewDir, reflectDir), 0.0), 16); + vec3 specular = specularStrength * spec * lightColor; + + // Combine texture color with lighting + vec3 textureColor = vec3(1,1,1); + if(material.isDiffusePresent) + { + textureColor = vec3(texture(material.diffuse, TexCoords)); + } + vec3 result = textureColor * (ambient + diffuseLight) + specular; + FragColor = vec4(result, 1.0); +} \ No newline at end of file diff --git a/AimGL/resources/Shaders/Graphics/Model/ModelTextured.vs b/AimGL/resources/Shaders/Graphics/Model/ModelTextured.vs new file mode 100644 index 0000000..b836658 --- /dev/null +++ b/AimGL/resources/Shaders/Graphics/Model/ModelTextured.vs @@ -0,0 +1,23 @@ +#version 330 core + +layout(location = 0) in vec3 position; // Vertex position +layout(location = 1) in vec3 normal; // Norm +layout(location = 2) in vec2 texCoords; // Texture coordinates + +out vec3 FragmentNormal; +out vec3 FragPos; +out vec2 TexCoords; + +uniform mat4 model = mat4(1.0); +uniform mat4 view; +uniform mat4 projection; + +void main() +{ + TexCoords = texCoords; + mat4 mvp = projection * view * model; + FragPos = vec3(model * vec4(normal, 1.0)); + FragmentNormal = mat3(transpose(inverse(model))) * normal; + + gl_Position = mvp * vec4(position, 1.0); +} \ No newline at end of file diff --git a/AimGL/resources/Shaders/basic.fs b/AimGL/resources/Shaders/basic.fs deleted file mode 100644 index a081fad..0000000 --- a/AimGL/resources/Shaders/basic.fs +++ /dev/null @@ -1,12 +0,0 @@ -#version 330 core -out vec4 FragColor; - -in vec3 ourColor; -in vec2 TexCoord; - -uniform sampler2D ourTexture; - -void main() -{ - FragColor = texture(ourTexture, TexCoord); -} \ No newline at end of file diff --git a/AimGL/resources/Shaders/basic.vs b/AimGL/resources/Shaders/basic.vs deleted file mode 100644 index 311ec24..0000000 --- a/AimGL/resources/Shaders/basic.vs +++ /dev/null @@ -1,14 +0,0 @@ -#version 330 core -layout (location = 0) in vec3 aPos; -layout (location = 1) in vec3 aColor; -layout (location = 2) in vec2 aTexCoord; - -out vec3 ourColor; -out vec2 TexCoord; - -void main() -{ - gl_Position = vec4(aPos, 1.0); - ourColor = aColor; - TexCoord = aTexCoord; -} \ No newline at end of file diff --git a/AimGL/src/CMakeLists_Sources.txt b/AimGL/src/CMakeLists_Sources.txt index 80d47cc..722cd5a 100644 --- a/AimGL/src/CMakeLists_Sources.txt +++ b/AimGL/src/CMakeLists_Sources.txt @@ -11,9 +11,12 @@ set(PROJECT_SOURCES Renderer/Core/OpenglUtils.cpp Renderer/Graphics/Texture.cpp Renderer/Graphics/2D/Sprite2D.cpp - Renderer/Graphics/3D/Sprite3D.cpp Renderer/Graphics/2D/Rectangle2D.cpp + Renderer/Graphics/3D/Sprite3D.cpp + Renderer/Graphics/3D/Core/Mesh.cpp + Renderer/Graphics/3D/Model.cpp Renderer/Renderer.cpp + Resources/ObjLoader.cpp States/State.cpp States/StateStack.cpp States/CustomStates/LogoState.cpp diff --git a/AimGL/src/Game.cpp b/AimGL/src/Game.cpp index b5dd81c..9edd9e4 100644 --- a/AimGL/src/Game.cpp +++ b/AimGL/src/Game.cpp @@ -72,7 +72,7 @@ Game::Game() mAppStack.saveState(State_ID::GameState, *mGameWindow); // Initial state of the statestack is TitleState - mAppStack.push(State_ID::LogoState); + mAppStack.push(State_ID::GameState); } void Game::run() diff --git a/AimGL/src/Renderer/Core/Buffers/IndexBuffer.h b/AimGL/src/Renderer/Core/Buffers/IndexBuffer.h index 3191e55..f90609f 100644 --- a/AimGL/src/Renderer/Core/Buffers/IndexBuffer.h +++ b/AimGL/src/Renderer/Core/Buffers/IndexBuffer.h @@ -36,6 +36,15 @@ class IndexBuffer : public Buffer */ void setBuffer(const unsigned int* data, unsigned count); + + /** + * \brief Sets the data from vector and binds the buffer + * \tparam T Type of vector + * \param vector Vector having linearly arranged data of type T in memory + */ + template + void setBuffer(const std::vector& vector); + /** * Returns the number of elements in the index buffer * @return Size of the index buffer @@ -45,3 +54,9 @@ class IndexBuffer : public Buffer private: unsigned int mCount; }; + +template +void IndexBuffer::setBuffer(const std::vector& vector) +{ + setBuffer(vector.data(), vector.size()); +} diff --git a/AimGL/src/Renderer/Core/Buffers/VertexBuffer.h b/AimGL/src/Renderer/Core/Buffers/VertexBuffer.h index 7ce3f55..fcf4f74 100644 --- a/AimGL/src/Renderer/Core/Buffers/VertexBuffer.h +++ b/AimGL/src/Renderer/Core/Buffers/VertexBuffer.h @@ -59,7 +59,5 @@ VertexBuffer::VertexBuffer(const std::vector& vector) template void VertexBuffer::setBuffer(const std::vector& vector) { - bind(); - GLCall(glBindBuffer(GL_ARRAY_BUFFER, mBufferId)); - GLCall(glBufferData(GL_ARRAY_BUFFER, vector.size(), vector.data(), GL_STATIC_DRAW)); + setBuffer(vector.data(), vector.size() * sizeof(vector[0])); } diff --git a/AimGL/src/Renderer/Core/Shader.cpp b/AimGL/src/Renderer/Core/Shader.cpp index b1b4d73..5caf613 100644 --- a/AimGL/src/Renderer/Core/Shader.cpp +++ b/AimGL/src/Renderer/Core/Shader.cpp @@ -38,6 +38,11 @@ void Shader::setUniform(const std::string& name, glm::vec4 vec) const GLCall(glUniform4fv(getUniformLocation(name), 1, glm::value_ptr(vec))); } +void Shader::setUniform(const std::string& name, glm::vec3 vec) const +{ + GLCall(glUniform3fv(getUniformLocation(name), 1, glm::value_ptr(vec))); +} + void Shader::setUniform(const std::string& name, float f1, float f2, float f3, float f4) const { GLCall(glUniform4f(getUniformLocation(name), f1, f2, f3, f4)); diff --git a/AimGL/src/Renderer/Core/Shader.h b/AimGL/src/Renderer/Core/Shader.h index 74fe13c..dbe6834 100644 --- a/AimGL/src/Renderer/Core/Shader.h +++ b/AimGL/src/Renderer/Core/Shader.h @@ -65,6 +65,7 @@ class Shader void setUniform(const std::string& name, glm::mat4 mat) const; void setUniform(const std::string& name, glm::vec4 vec) const; + void setUniform(const std::string& name, glm::vec3 vec) const; void setUniform(const std::string& name, float f1, float f2, float f3, float f4) const; void setUniform(const std::string& name, float f1, float f2, float f3) const; void setUniform(const std::string& name, float f1, float f2) const; diff --git a/AimGL/src/Renderer/Graphics/3D/Core/Mesh.cpp b/AimGL/src/Renderer/Graphics/3D/Core/Mesh.cpp new file mode 100644 index 0000000..f5211ba --- /dev/null +++ b/AimGL/src/Renderer/Graphics/3D/Core/Mesh.cpp @@ -0,0 +1,57 @@ +#include "Mesh.h" +#include "pch.h" + +Mesh::Mesh(std::vector&& vertices, std::vector&& indices, + std::vector&& textures) + : vertices(std::move(vertices)), + indices(std::move(indices)), + textures(std::move(textures)) +{ + mVBO.setBuffer(this->vertices); + mEBO.setBuffer(this->indices); + + mVAO.bind(); + mVBO.bind(); + mBufferLayout.push(3); + mBufferLayout.push(3); + mBufferLayout.push(2); + mVAO.setBuffer(mVBO, mBufferLayout); + mVAO.unbind(); +} + +void Mesh::setTextureToShaderUniform(const Shader& shader, const Texture& texture) const +{ + switch (texture.type()) + { + case Texture::Type::Diffuse: // + shader.setUniform("material.diffuse", 0); + shader.setUniform("material.isDiffusePresent", true); + break; + case Texture::Type::Specular: // + shader.setUniform("material.specular", 1); + shader.setUniform("material.isSpecularPresent", true); + break; + default: spdlog::warn( + "Trying to draw texture of unsupported type inside Mesh. TextureType used: {}", + toString(texture.type())); + } +} + +void Mesh::setDefaultValuesToMaterialUniforms(const Shader& shader) const +{ + shader.setUniform("material.isDiffusePresent", false); + shader.setUniform("material.isSpecularPresent", false); +} + +void Mesh::draw(const Renderer& target, const Camera& camera, const Shader& shader) const +{ + shader.bind(); + setDefaultValuesToMaterialUniforms(shader); + for (auto i = 0; i < textures.size(); ++i) + { + auto& texture = textures[i]; + setTextureToShaderUniform(shader, texture); + texture.bind(i); + } + target.draw3D(mVAO, mEBO, shader, camera); +} diff --git a/AimGL/src/Renderer/Graphics/3D/Core/Mesh.h b/AimGL/src/Renderer/Graphics/3D/Core/Mesh.h new file mode 100644 index 0000000..40cc8fa --- /dev/null +++ b/AimGL/src/Renderer/Graphics/3D/Core/Mesh.h @@ -0,0 +1,58 @@ +#pragma once + +#include "Renderer/Graphics/3D/Core/Vertex.h" + +#include +#include +#include +#include +#include +#include + +/** + * \brief Basic representation of shape of 3d object + */ +class Mesh +{ +public: + /** + * \brief Constructor of Mesh class + * \param vertices The vertices of which the shape consists + * \param indices Indexes describing the order in which the vertices are drawn + * \param textures Textures with which the mesh should be drawn + */ + Mesh(std::vector&& vertices, std::vector&& indices, + std::vector&& textures); + + /** + * \brief Draws a mesh for a given target + * \param target The target to which the mesh is drawn + * \param camera A camera in 3D space that looks at this object + * \param shader Shader that should be used to draw the mesh + */ + void draw(const Renderer& target, const Camera& camera, const Shader& shader) const; + +private: + /** + * \brief Sets the specified texture to the shader + * \param shader Shader to which the texture should be bind + * \param texture Texture that should be bind to shader + */ + void setTextureToShaderUniform(const Shader& shader, const Texture& texture) const; + + /** + * \brief Sets default values to object material in shader + * \param shader Shader to which default values should be set + */ + void setDefaultValuesToMaterialUniforms(const Shader& shader) const; + +private: + std::vector vertices; + std::vector indices; + std::vector textures; // TODO: resource manager should be used there + + VertexArray mVAO; + VertexBuffer mVBO; + IndexBuffer mEBO; + BufferLayout mBufferLayout; +}; diff --git a/AimGL/src/Renderer/Graphics/3D/Core/Vertex.h b/AimGL/src/Renderer/Graphics/3D/Core/Vertex.h new file mode 100644 index 0000000..08d411b --- /dev/null +++ b/AimGL/src/Renderer/Graphics/3D/Core/Vertex.h @@ -0,0 +1,8 @@ +#pragma once + +struct Vertex +{ + glm::vec3 position; + glm::vec3 normal; + glm::vec2 textureCoordinates; +}; \ No newline at end of file diff --git a/AimGL/src/Renderer/Graphics/3D/Model.cpp b/AimGL/src/Renderer/Graphics/3D/Model.cpp new file mode 100644 index 0000000..ff456c0 --- /dev/null +++ b/AimGL/src/Renderer/Graphics/3D/Model.cpp @@ -0,0 +1,52 @@ +#include "Model.h" +#include "pch.h" + +Model::Model(const std::string& objFilePath, const std::vector& texturesToLoad) + : mShader{{ShaderType::VertexShader, "resources/Shaders/Graphics/Model/ModelTextured.vs"}, + {ShaderType::FragmentShader, "resources/Shaders/Graphics/Model/ModelTextured.fs"}} + , mObjLoader(objFilePath, {ObjLoader::Flags::ForceCenterAtOrigin}) +{ + // TODO: Storing texture this way is not the best idea as the texture + // TODO: may be duplicated as many times as this object is loaded! :<< + std::vector textures; + textures.reserve(textures.size()); + for (const auto& textureToLoad: texturesToLoad) + { + const auto& [texturePath, textureType] = textureToLoad; + textures.emplace_back(texturePath, textureType); + } + mMesh = std::make_unique(std::move(mObjLoader.vertices()), + std::move(mObjLoader.indices()), std::move(textures)); + setPosition({0, 0, 0}); +} + +void Model::draw(const Renderer& target, const Camera& camera) const +{ + mMesh->draw(target, camera, mShader); +} + +void Model::setPosition(const glm::vec3& newPosition, Origin origin) +{ + mPosition = newPosition; + switch (origin) + { + case Origin::Center: break; + case Origin::LeftBottom: mPosition += mObjLoader.dimensions() / 2.f; + break; + case Origin::CenterBottom: mPosition.y += mObjLoader.dimensions().y / 2.f; + break; + } + updateModel(); +} + +void Model::updateModel() +{ + glm::mat4 model = glm::mat4(1.0f); + model = glm::translate(model, glm::vec3(mPosition)); + // TODO: Add rotation and scale to the model + //model = glm::rotate(model, glm::radians(mRotation.first), mRotation.second); + //model = glm::scale(model, glm::vec3(mDimensionsNormalized * mScale / 2.f, 1.0f)); + mShader.bind(); + mShader.setUniform("model", model); + mShader.unbind(); +} diff --git a/AimGL/src/Renderer/Graphics/3D/Model.h b/AimGL/src/Renderer/Graphics/3D/Model.h new file mode 100644 index 0000000..1924cf7 --- /dev/null +++ b/AimGL/src/Renderer/Graphics/3D/Model.h @@ -0,0 +1,65 @@ +#pragma once +#include "Core/Mesh.h" + +#include +#include + +/** + * \brief Texture along with the type of texture it represents + */ +struct TextureType +{ + std::string texturePath; + Texture::Type textureType; +}; + +/** + * \brief A class representing a 3D model in the game's 3D space + */ +class Model +{ +public: + /** + * \brief Model class constructor + * \param objFilePath Path to a file with the extension .obj, which is a + * representation of a 3d model + * \param textures Path to the texture files and types that should be applied to the object. + */ + Model(const std::string& objFilePath, const std::vector& textures = {}); + + /** + * \brief Determines the point at which the model has its position (0,0,0) + */ + enum class Origin + { + LeftBottom, + Center, + CenterBottom + }; + + /** + * \brief Draws a model for a given target + * \param target The target to which the model is drawn + * \param camera A camera in 3D space that looks at this object + */ + void draw(const Renderer& target, const Camera& camera) const; + + /** + * \brief Sets new 3d model position in space + * \param newPosition New 3d model position in space + * \param origin Point at which the model has its position (0,0,0) + */ + void setPosition(const glm::vec3& newPosition, Origin origin = Origin::CenterBottom); + +private: + /** + * \brief Updates the model in the shader + */ + void updateModel(); + +private: + Shader mShader; + ObjLoader mObjLoader; + std::unique_ptr mMesh; + glm::vec3 mPosition{0,0,0}; +}; diff --git a/AimGL/src/Renderer/Graphics/Texture.cpp b/AimGL/src/Renderer/Graphics/Texture.cpp index 1da1863..fd1b7bd 100644 --- a/AimGL/src/Renderer/Graphics/Texture.cpp +++ b/AimGL/src/Renderer/Graphics/Texture.cpp @@ -6,14 +6,15 @@ #define STB_IMAGE_IMPLEMENTATION #include "stb_image.h" -Texture::Texture(const std::string& filePath) +Texture::Texture(const std::string& filePath, Type type) : mTextureId(0) , mFilePath(filePath) - , mData(nullptr) , mWidth(0) , mHeight(0) , mNrChannels(0) + , mTextureType(type) { + unsigned char* mData = nullptr; stbi_set_flip_vertically_on_load(true); mData = stbi_load(filePath.c_str(), &mWidth, &mHeight, &mNrChannels, 0); GLCall(glGenTextures(1, &mTextureId)); @@ -44,6 +45,23 @@ Texture::~Texture() GLCall(glDeleteTextures(1, &mTextureId)); } +Texture::Texture(const Texture& rhs) + : Texture(rhs.mFilePath) +{ + // TODO: Please improve me later! +} + +Texture::Texture(Texture&& rhs) noexcept +{ + mTextureId = rhs.mTextureId; + rhs.mTextureId = 0; + mFilePath = std::move(rhs.mFilePath); + mAspectRatio = rhs.mAspectRatio; + mWidth = rhs.mWidth; + mHeight = rhs.mHeight; + mNrChannels = rhs.mNrChannels; +} + void Texture::bind(unsigned int slot) const { GLCall(glActiveTexture(GL_TEXTURE0 + slot)); @@ -69,3 +87,8 @@ float Texture::aspectRatio() const { return mAspectRatio; } + +Texture::Type Texture::type() const +{ + return mTextureType; +} diff --git a/AimGL/src/Renderer/Graphics/Texture.h b/AimGL/src/Renderer/Graphics/Texture.h index 51b8920..90e84c5 100644 --- a/AimGL/src/Renderer/Graphics/Texture.h +++ b/AimGL/src/Renderer/Graphics/Texture.h @@ -6,17 +6,40 @@ class Texture { public: + /** + * \brief Type indicates whether it is used for + * diffuse reflection or sepcular highlight etc. + */ + enum class Type + { + NoSpecified, + Diffuse, + Specular + }; /** * \brief Creates a texture based on the file path to image * \param filePath Path to the image + * \param type Texture type */ - Texture(const std::string& filePath); + Texture(const std::string& filePath, Type type = Type::NoSpecified); /** * \brief Removes texture */ ~Texture(); + /** + * \brief Copy contructor of texture class + * \param rhs Other texture to copy + */ + Texture(const Texture& rhs); + + /** + * \brief Move constructor of texture class + * \param rhs Other r-value texture object + */ + Texture(Texture&& rhs) noexcept; + /** * \brief Binds a texture for rendering * \param slot Slot to which the texture will be binded (can be obtained from the shader level) @@ -32,24 +55,41 @@ class Texture * \brief Returns the width of the texture * \return Width of the texture */ - int width() const; + [[nodiscard]] int width() const; /** * \brief Returns the height of the texture * \return Height of the texture */ - int height() const; + [[nodiscard]] int height() const; /** * \brief Returns the aspect ratio of the image * \return Aspect ratio of the image */ - float aspectRatio() const; + [[nodiscard]] float aspectRatio() const; + + /** + * \brief TODO: THIS + */ + Type type() const; private: unsigned int mTextureId; std::string mFilePath; - unsigned char* mData; float mAspectRatio; int mWidth, mHeight, mNrChannels; -}; \ No newline at end of file + Type mTextureType; +}; + + +inline std::string toString(const Texture::Type& textureType) +{ + switch(textureType) + { + case Texture::Type::NoSpecified: return "NoSpecified"; + case Texture::Type::Diffuse: return "Diffuse"; + case Texture::Type::Specular: return "Specular"; + default: return "Unknown"; + } +} \ No newline at end of file diff --git a/AimGL/src/Renderer/Renderer.cpp b/AimGL/src/Renderer/Renderer.cpp index a395204..1ec58c4 100644 --- a/AimGL/src/Renderer/Renderer.cpp +++ b/AimGL/src/Renderer/Renderer.cpp @@ -40,6 +40,7 @@ void Renderer::draw3D(const VertexArray& va, const IndexBuffer& ib, const Shader const auto projection = camera.projection(); shader.setUniform("view", view); shader.setUniform("projection", projection); + shader.setUniform("cameraPosition", camera.cameraPosition()); GLCall(glDrawElements(toOpenGl(drawMode), ib.size(), GL_UNSIGNED_INT, nullptr)); #ifdef _DEBUG diff --git a/AimGL/src/Resources/ObjLoader.cpp b/AimGL/src/Resources/ObjLoader.cpp new file mode 100644 index 0000000..40af454 --- /dev/null +++ b/AimGL/src/Resources/ObjLoader.cpp @@ -0,0 +1,166 @@ +#include "ObjLoader.h" +#include "pch.h" + +ObjLoader::ObjLoader(const std::string& objFilePath, std::vector flags) + : mFlags(flags) +{ + loadObject(objFilePath); +} + +std::vector ObjLoader::vertices() const +{ + return mVertices; +} + +std::vector ObjLoader::indices() const +{ + return mIndices; +} + +glm::vec3 ObjLoader::dimensions() const +{ + return mDimensions; +} + +glm::vec3 ObjLoader::midPoint() const +{ + return mMidPoint; +} + +void ObjLoader::loadObject(const std::string& objFilePath) +{ + std::ifstream file(objFilePath); + std::string line; + while (std::getline(file, line)) + { + parseLine(line); + } + + mDimensions = {mBiggestDimensions.x - mLowestDimensions.x, + mBiggestDimensions.y - mLowestDimensions.y, + mBiggestDimensions.z - mLowestDimensions.z}; + + mMidPoint = {((mBiggestDimensions.x + mLowestDimensions.x) / 2.f), + ((mBiggestDimensions.y + mLowestDimensions.y) / 2.f), + ((mBiggestDimensions.z + mLowestDimensions.z) / 2.f)}; + + if (std::find(mFlags.begin(), mFlags.end(), Flags::ForceCenterAtOrigin) != mFlags.end()) + { + for (auto& vertex: mVertices) + { + vertex.position.x -= mMidPoint.x; + vertex.position.y -= mMidPoint.y; + vertex.position.z -= mMidPoint.z; + } + } + + mPositions.clear(); + mNormals.clear(); + mTextureCoordinates.clear(); +} + +void ObjLoader::collectDimensionsInformations(const glm::vec3& vec) +{ + if (vec.x > mBiggestDimensions.x) + { + mBiggestDimensions.x = vec.x; + } + if (vec.y > mBiggestDimensions.y) + { + mBiggestDimensions.y = vec.y; + } + if (vec.z > mBiggestDimensions.z) + { + mBiggestDimensions.z = vec.z; + } + + if (vec.x < mLowestDimensions.x) + { + mLowestDimensions.x = vec.x; + } + if (vec.y < mLowestDimensions.y) + { + mLowestDimensions.y = vec.y; + } + if (vec.z < mLowestDimensions.z) + { + mLowestDimensions.z = vec.z; + } +} + +void ObjLoader::parseVertex(std::istringstream& ss) +{ + glm::vec3 position; + ss >> position.x >> position.y >> position.z; + collectDimensionsInformations(position); + mPositions.push_back(position); +} + +void ObjLoader::parseNormal(std::istringstream& ss) +{ + glm::vec3 normal; + ss >> normal.x >> normal.y >> normal.z; + mNormals.push_back(normal); +} + +void ObjLoader::parseTextureCoordinate(std::istringstream& ss) +{ + glm::vec2 textureCoordinate; + ss >> textureCoordinate.x >> textureCoordinate.y; + mTextureCoordinates.push_back(textureCoordinate); +} + +std::tuple ObjLoader::parseIndices(const std::string& vertex) +{ + std::istringstream vertexStream(vertex); + std::string index; + std::vector indices; + + while (std::getline(vertexStream, index, '/')) + { + if (!index.empty()) + { + indices.push_back(std::stoi(index) - 1); + } + } + + return {indices[0], indices[1], indices[2]}; +} + +void ObjLoader::parseFace(std::istringstream& ss) +{ + std::string vertex; + while (ss >> vertex) + { + // TODO: Index buffer is useless and vertices are duplicated this way. Should be fixed later + auto [positionIndex, textureIndex, normalIndex] = parseIndices(vertex); + Vertex v{mPositions[positionIndex], + mNormals[normalIndex], mTextureCoordinates[textureIndex]}; + mVertices.push_back(v); + mIndices.push_back(mIndices.size()); + } +} + +void ObjLoader::parseLine(const std::string& line) +{ + std::istringstream ss(line); + std::string prefix; + ss >> prefix; + + if (prefix == "v") + { + parseVertex(ss); + } + else if (prefix == "vn") + { + parseNormal(ss); + } + else if (prefix == "vt") + { + parseTextureCoordinate(ss); + } + else if (prefix == "f") + { + parseFace(ss); + } +} diff --git a/AimGL/src/Resources/ObjLoader.h b/AimGL/src/Resources/ObjLoader.h new file mode 100644 index 0000000..3f08d2c --- /dev/null +++ b/AimGL/src/Resources/ObjLoader.h @@ -0,0 +1,48 @@ +#pragma once +#include +#include +#include + + +class ObjLoader +{ +public: + enum class Flags + { + ForceCenterAtOrigin + }; + + + ObjLoader(const std::string& objFilePath, std::vector flags = {}); + [[nodiscard]] std::vector vertices() const; + [[nodiscard]] std::vector indices() const; + [[nodiscard]] glm::vec3 dimensions() const; + [[nodiscard]] glm::vec3 midPoint() const; + +private: + std::vector mVertices; + std::vector mPositions; + std::vector mNormals; + std::vector mTextureCoordinates; + std::vector mIndices; + + std::vector mFlags; + glm::vec3 mDimensions; + glm::vec3 mMidPoint; + glm::vec3 mLowestDimensions{std::numeric_limits::max(), + std::numeric_limits::max(), + std::numeric_limits::max()}; + glm::vec3 mBiggestDimensions{std::numeric_limits::lowest(), + std::numeric_limits::lowest(), + std::numeric_limits::lowest()}; + + + void loadObject(const std::string& objFilePath); + void collectDimensionsInformations(const glm::vec3& vec); + void parseVertex(std::istringstream& ss); + void parseNormal(std::istringstream& ss); + void parseTextureCoordinate(std::istringstream& ss); + std::tuple parseIndices(const std::string& vertex); + void parseFace(std::istringstream& ss); + void parseLine(const std::string& line); +}; diff --git a/AimGL/src/States/CustomStates/GameState.cpp b/AimGL/src/States/CustomStates/GameState.cpp index 15609e5..30144df 100644 --- a/AimGL/src/States/CustomStates/GameState.cpp +++ b/AimGL/src/States/CustomStates/GameState.cpp @@ -6,13 +6,14 @@ GameState::GameState(StateStack& stack, WindowToRender& window) : State(stack) - , mWindow(window) - , mRenderer(mWindow) - , mLogoTexture("resources/Textures/logo_background.png") - , mLogo(mLogoTexture) - , mCamera(window) - , mGameBackground(glm::vec2(1280, 720.f), glm::vec4(0.85f, 0.85f, 0.85f, 1.f)) - , mPhaseInLogoColor({window.getSize().x, window.getSize().y}, {0.067f, 0.11f, 0.18f, 1.1f}) + , mWindow(window) + , mRenderer(mWindow) + , mLogoTexture("resources/Textures/logo_background.png") + , mLogo(mLogoTexture) + , mCamera(window) + , mGameBackground(glm::vec2(1280, 720.f), glm::vec4(0.85f, 0.85f, 0.85f, 1.f)) + , mPhaseInLogoColor({window.getSize().x, window.getSize().y}, {0.067f, 0.11f, 0.18f, 1.1f}) + , tree("resources/Models/tree/tree.obj", {{"resources/Models/tree/tree_combined.png", Texture::Type::Diffuse}}) { Mouse::lockMouseAtCenter(mWindow); mLogo.setHeight(2.f); @@ -29,7 +30,8 @@ void GameState::draw(sf::Window& target) const MTR_SCOPE("GameState", "GameState::draw"); mGameBackground.draw(mRenderer); mInfiniteGridFloor.draw(target, mCamera); - mLogo.draw(mRenderer, mCamera); + tree.draw(mRenderer, mCamera); + // mLogo.draw(mRenderer, mCamera); mPhaseInLogoColor.draw(mRenderer); } @@ -61,7 +63,8 @@ bool GameState::handleEvent(const sf::Event& event) { switch (event.key.code) { - case sf::Keyboard::Escape: Mouse::unlockMouse(mWindow); break; + case sf::Keyboard::Escape: Mouse::unlockMouse(mWindow); + break; } } return true; @@ -71,6 +74,7 @@ bool GameState::updateImGui(const float& deltaTime) { MTR_SCOPE("GameState", "GameState::updateImGui"); mCamera.updateImGui(); + mInfiniteGridFloor.showDebugImGui(); ImGui::ShowDemoWindow(); return true; } diff --git a/AimGL/src/States/CustomStates/GameState.h b/AimGL/src/States/CustomStates/GameState.h index e4d6cd4..a09ec8b 100644 --- a/AimGL/src/States/CustomStates/GameState.h +++ b/AimGL/src/States/CustomStates/GameState.h @@ -7,6 +7,8 @@ #include "World/Camera.h" #include "World/InfiniteGridFloor.h" +#include + class StateStack; /** @@ -58,4 +60,5 @@ class GameState : public State sf::Clock mPhaseInClock; Rectangle2D mPhaseInLogoColor; InfiniteGridFloor mInfiniteGridFloor; + Model tree; }; diff --git a/AimGL/src/World/InfiniteGridFloor.cpp b/AimGL/src/World/InfiniteGridFloor.cpp index 31f74d7..c5e1cff 100644 --- a/AimGL/src/World/InfiniteGridFloor.cpp +++ b/AimGL/src/World/InfiniteGridFloor.cpp @@ -21,3 +21,14 @@ void InfiniteGridFloor::draw(sf::Window& target, const Camera& camera) const glDrawArrays(GL_TRIANGLES, 0, 6); mInfiniteGridShader.unbind(); } + +void InfiniteGridFloor::showDebugImGui(std::string name) +{ + name = "[InfiniteGridFloor] " + name; + ImGui::Begin(name.c_str()); + ImGui::SliderFloat("Far", &mFar, 0.0f, 5.f); + ImGui::End(); + mInfiniteGridShader.bind(); + mInfiniteGridShader.setUniform("far", mFar); + mInfiniteGridShader.unbind(); +} diff --git a/AimGL/src/World/InfiniteGridFloor.h b/AimGL/src/World/InfiniteGridFloor.h index 8b19134..dafb24a 100644 --- a/AimGL/src/World/InfiniteGridFloor.h +++ b/AimGL/src/World/InfiniteGridFloor.h @@ -25,6 +25,14 @@ class InfiniteGridFloor */ void draw(sf::Window& target, const Camera& camera) const; + /** + * \brief Displays a debug ImGui window that allows to change the internal + * variables of the Infinite Grid. + * \param name Optional name of the Infinite grid (it can be seen in the window name). + */ + void showDebugImGui(std::string name = ""); + private: Shader mInfiniteGridShader; + float mFar = 5.f; }; \ No newline at end of file