diff --git a/src/GLObjects.cpp b/src/GLObjects.cpp index 12f5129..a16b241 100644 --- a/src/GLObjects.cpp +++ b/src/GLObjects.cpp @@ -1,439 +1,316 @@ #include -#include -#include +#include +#include #include #include "GLObjects.hpp" using namespace OpenGL; IGLObject::~IGLObject() { - destroy(); + destroy(); } void IGLBinding::bind() const { - bind0(id); + bind0(id); } void IGLBinding::unbind() const { - bind0(0); + bind0(0); } void IGLTargetBinding::bind(GLenum unit) const { - bind0(unit, id); + bind0(unit, id); } void IGLTargetBinding::unbind(GLenum target) const { - bind0(target, 0); + bind0(target, 0); } -BufferObject::BufferObject(): size(0) { - glCreateBuffers(1, &id); +BufferObject::BufferObject() : size(0) { + glCreateBuffers(1, &id); } void BufferObject::destroy() const { - glDeleteBuffers(1, &id); + glDeleteBuffers(1, &id); } void BufferObject::bind0(GLenum target, GLuint id) const { - glBindBuffer(target, id); + glBindBuffer(target, id); } void BufferObject::allocate(GLsizeiptr size, unsigned int flags) { - this->size = size; + this->size = size; } void BufferObject::allocate(const void* data, GLsizeiptr size, unsigned int flags) { - this->size = size; + this->size = size; } void BufferObject::invalidate() const { - glInvalidateBufferData(IGLObject::id); + glInvalidateBufferData(IGLObject::id); } void BufferObject::Mutable::allocate(GLsizeiptr size, unsigned int flags) { - BufferObject::allocate(size, flags); - glNamedBufferData(id, size, NULL, flags); + BufferObject::allocate(size, flags); + glNamedBufferData(id, size, NULL, flags); } void BufferObject::Mutable::allocate(const void* data, GLsizeiptr size, unsigned int flags) { - BufferObject::allocate(data, size, flags); - glNamedBufferData(id, size, data, flags); + BufferObject::allocate(data, size, flags); + glNamedBufferData(id, size, data, flags); } void BufferObject::Immutable::allocate(GLsizeiptr size, unsigned int flags) { - BufferObject::allocate(size, flags); - glNamedBufferStorage(id, size, NULL, flags); + BufferObject::allocate(size, flags); + glNamedBufferStorage(id, size, NULL, flags); } void BufferObject::Immutable::allocate(const void* data, GLsizeiptr size, unsigned int flags) { - BufferObject::allocate(data, size, flags); - glNamedBufferStorage(id, size, data, flags); + BufferObject::allocate(data, size, flags); + glNamedBufferStorage(id, size, data, flags); }; -VertexArrayObject::VertexArrayObject(): elementBuffer(NULL) { - glCreateVertexArrays(1, &id); +VertexArrayObject::VertexArrayObject() : elementBuffer(NULL) { + glCreateVertexArrays(1, &id); } VertexArrayObject::~VertexArrayObject() { - destroyAll(); + destroyAll(); } void VertexArrayObject::destroy() const { - glDeleteVertexArrays(1, &id); + glDeleteVertexArrays(1, &id); } void VertexArrayObject::bind0(GLuint id) const { - glBindVertexArray(id); + glBindVertexArray(id); } void VertexArrayObject::attachElementBuffer(BufferObject& buffer) { - glVertexArrayElementBuffer(id, buffer.id); - elementBuffer = &buffer; + glVertexArrayElementBuffer(id, buffer.id); + elementBuffer = &buffer; } void VertexArrayObject::attachVertexBuffer(BufferObject& buffer, GLuint offset, VertexAttribute& vertexAttribute) { - GLuint binding = (GLuint) vertexBuffers.size(); - glVertexArrayVertexBuffer(id, binding, buffer.id, offset, vertexAttribute.stride); - vertexBuffers.push_back(&buffer); - vertexAttribute.apply(*this, binding); + GLuint binding = (GLuint) vertexBuffers.size(); + glVertexArrayVertexBuffer(id, binding, buffer.id, offset, vertexAttribute.stride); + vertexBuffers.push_back(&buffer); + vertexAttribute.apply(*this, binding); } void VertexArrayObject::attachVertexBuffer(BufferObject& buffer, VertexAttribute& vertexAttribute) { - attachVertexBuffer(buffer, 0, vertexAttribute); + attachVertexBuffer(buffer, 0, vertexAttribute); } void VertexArrayObject::clearAttachments() { - if (elementBuffer != NULL) { - glVertexArrayElementBuffer(id, 0); - elementBuffer = NULL; - } - GLuint length = (GLuint) vertexBuffers.size(); - for (GLuint i = 0; i < length; i++) { - glVertexArrayVertexBuffer(id, i, 0, 0, 0); - } - vertexBuffers.clear(); + if (elementBuffer != NULL) { + glVertexArrayElementBuffer(id, 0); + elementBuffer = NULL; + } + GLuint length = (GLuint) vertexBuffers.size(); + for (GLuint i = 0; i < length; i++) { + glVertexArrayVertexBuffer(id, i, 0, 0, 0); + } + vertexBuffers.clear(); } void VertexArrayObject::destroyAll() { - destroy(); - if (elementBuffer != NULL) { - elementBuffer->destroy(); - } - size_t length = vertexBuffers.size(); - for (size_t i = 0; i < length; i++) { - vertexBuffers[i]->destroy(); - } - vertexBuffers.clear(); + destroy(); + if (elementBuffer != NULL) { + elementBuffer->destroy(); + } + size_t length = vertexBuffers.size(); + for (size_t i = 0; i < length; i++) { + vertexBuffers[i]->destroy(); + } + vertexBuffers.clear(); } -VertexAttribute::VertexAttribute(std::vector entries, GLsizei stride, GLuint divisor): entries(entries), stride(stride), divisor(divisor) {}; +VertexAttribute::VertexAttribute(std::vector entries, GLsizei stride, GLuint divisor) : entries(entries), stride(stride), divisor(divisor) {}; VertexAttribute::~VertexAttribute() { - size_t length = entries.size(); - for (size_t i = 0; i < length; i++) { - delete entries[i]; - } - entries.clear(); + size_t length = entries.size(); + for (size_t i = 0; i < length; i++) { + delete entries[i]; + } + entries.clear(); } void VertexAttribute::apply(VertexArrayObject& vao, int binding) { - size_t length = entries.size(); - for (size_t i = 0; i < length; i++) { - entries[i]->apply(vao, binding); - } - glVertexArrayBindingDivisor(vao.id, binding, divisor); + size_t length = entries.size(); + for (size_t i = 0; i < length; i++) { + entries[i]->apply(vao, binding); + } + glVertexArrayBindingDivisor(vao.id, binding, divisor); } class VertexAttribute::Entry::Float final : VertexAttribute::Entry { private: - GLboolean normalized; + GLboolean normalized; public: - Float(GLuint index, GLint size, GLenum type, GLuint offset, GLboolean normalized): normalized(normalized) { - VertexAttribute::Entry::index = index; - VertexAttribute::Entry::size = size; - VertexAttribute::Entry::type = type; - VertexAttribute::Entry::offset = offset; - } - - void apply(VertexArrayObject& vao, GLuint binding) const override { - glEnableVertexArrayAttrib(vao.id, index); - glVertexArrayAttribFormat(vao.id, index, size, type, normalized, offset); - glVertexArrayAttribBinding(vao.id, index, binding); - }; + Float(GLuint index, GLint size, GLenum type, GLuint offset, GLboolean normalized) : normalized(normalized) { + VertexAttribute::Entry::index = index; + VertexAttribute::Entry::size = size; + VertexAttribute::Entry::type = type; + VertexAttribute::Entry::offset = offset; + } + + void apply(VertexArrayObject& vao, GLuint binding) const override { + glEnableVertexArrayAttrib(vao.id, index); + glVertexArrayAttribFormat(vao.id, index, size, type, normalized, offset); + glVertexArrayAttribBinding(vao.id, index, binding); + }; }; class VertexAttribute::Entry::Int final : VertexAttribute::Entry { public: - Int(GLuint index, GLint size, GLenum type, GLuint offset) { - VertexAttribute::Entry::index = index; - VertexAttribute::Entry::size = size; - VertexAttribute::Entry::type = type; - VertexAttribute::Entry::offset = offset; - } - - void apply(VertexArrayObject& vao, GLuint binding) const override { - glEnableVertexArrayAttrib(vao.id, index); - glVertexArrayAttribIFormat(vao.id, index, size, type, offset); - glVertexArrayAttribBinding(vao.id, index, binding); - }; + Int(GLuint index, GLint size, GLenum type, GLuint offset) { + VertexAttribute::Entry::index = index; + VertexAttribute::Entry::size = size; + VertexAttribute::Entry::type = type; + VertexAttribute::Entry::offset = offset; + } + + void apply(VertexArrayObject& vao, GLuint binding) const override { + glEnableVertexArrayAttrib(vao.id, index); + glVertexArrayAttribIFormat(vao.id, index, size, type, offset); + glVertexArrayAttribBinding(vao.id, index, binding); + }; }; -VertexAttribute::Builder::Builder(GLsizei stride, GLuint divisor): stride(stride), divisor(divisor), offset(0) {} +VertexAttribute::Builder::Builder(GLsizei stride, GLuint divisor) : stride(stride), divisor(divisor), offset(0) {} unsigned int getSize(GLenum type) { - int result = 0; - switch (type) { - case GL_BYTE: - case GL_UNSIGNED_BYTE: - result = 1; - break; - case GL_SHORT: - case GL_UNSIGNED_SHORT: - result = 2; - break; - case GL_INT: - case GL_UNSIGNED_INT: - case GL_FLOAT: - result = 4; - break; - default: - throw 0; - break; - } - return result; + int result = 0; + switch (type) { + case GL_BYTE: + case GL_UNSIGNED_BYTE: + result = 1; + break; + case GL_SHORT: + case GL_UNSIGNED_SHORT: + result = 2; + break; + case GL_INT: + case GL_UNSIGNED_INT: + case GL_FLOAT: + result = 4; + break; + default: + throw 0; + break; + } + return result; } VertexAttribute::Builder& VertexAttribute::Builder::addInt(GLuint index, GLint size, GLenum type) { - entries.push_back((VertexAttribute::Entry*) new VertexAttribute::Entry::Int(index, size, type, this->offset)); - offset += size * getSize(type); - return *this; + entries.push_back((VertexAttribute::Entry*) new VertexAttribute::Entry::Int(index, size, type, this->offset)); + offset += size * getSize(type); + return *this; } VertexAttribute::Builder& VertexAttribute::Builder::addFloat(GLuint index, GLint size, GLenum type, GLboolean normalized) { - entries.push_back((VertexAttribute::Entry*) new VertexAttribute::Entry::Float(index, size, type, this->offset, normalized)); - offset += size * getSize(type); - return *this; + entries.push_back((VertexAttribute::Entry*) new VertexAttribute::Entry::Float(index, size, type, this->offset, normalized)); + offset += size * getSize(type); + return *this; } VertexAttribute::Builder& VertexAttribute::Builder::addPadding(GLuint size) { - offset += size; - return *this; + offset += size; + return *this; } VertexAttribute& VertexAttribute::Builder::build() { - return *new VertexAttribute(entries, stride, divisor); -} - -TextureObject::TextureObject(GLenum target): target(target) { - glCreateTextures(target, 1, &id); -} - -TextureObject::~TextureObject() { - destroy(); -} - -void TextureObject::destroy() const { - glDeleteTextures(1, &id); -} - -void TextureObject::bind0(GLenum target, GLuint id) const { - glBindTextureUnit(target, id); -} - -TextureObject::Texture2D::Texture2D(): TextureObject(GL_TEXTURE_2D) {} - -void TextureObject::Texture2D::allocate(const GLsizei levels, const GLenum internalformat, const glm::i32vec2 size) { - this->size = size; - glTextureStorage2D(id, levels, internalformat, size.x, size.y); -} - -void TextureObject::Texture2D::upload(const GLint level, const glm::i32vec2 offset, const glm::i32vec2 size, GLenum format, GLenum type, const void* pixels) { - glTextureSubImage2D(id, level, offset.x, offset.y, size.x, size.y, format, type, pixels); -} - -RenderBuffer::RenderBuffer() { - glCreateRenderbuffers(1, &id); -} - -RenderBuffer::~RenderBuffer() { - destroy(); -} - -void RenderBuffer::destroy() const { - glDeleteRenderbuffers(1, &id); -} - -void RenderBuffer::bind0(GLuint id) const { - glBindRenderbuffer(GL_RENDERBUFFER, id); -} - -void RenderBuffer::allocate(const GLenum internalformat, const glm::i32vec2 size) { - this->size = size; - glNamedRenderbufferStorage(id, internalformat, size.x, size.y); -} - -Framebuffer::Framebuffer() { - glCreateFramebuffers(1, &id); -} - -Framebuffer::~Framebuffer() { - destroyAll(); -} - -void Framebuffer::destroy() const { - glDeleteFramebuffers(1, &id); -} - -void Framebuffer::bind0(GLenum target, GLuint id) const { - glBindFramebuffer(target, id); -} - -void Framebuffer::attach(const TextureObject& texture, const GLenum attachment, const GLint level) { - switch (attachment) { - case GL_DEPTH_ATTACHMENT: - depthAttachment = &texture; - break; - case GL_STENCIL_ATTACHMENT: - stencilAttachment = &texture; - case GL_DEPTH_STENCIL_ATTACHMENT: - depthAttachment = &texture; - stencilAttachment = &texture; - default: - colorAttachments.push_back(&texture); - break; - } - - glNamedFramebufferTexture(id, attachment, texture.id, level); -} - -void Framebuffer::attach(const RenderBuffer& buffer, const GLenum attachment, const GLint level) { - switch (attachment) { - case GL_DEPTH_ATTACHMENT: - depthAttachment = &buffer; - break; - case GL_STENCIL_ATTACHMENT: - stencilAttachment = &buffer; - case GL_DEPTH_STENCIL_ATTACHMENT: - depthAttachment = &buffer; - stencilAttachment = &buffer; - default: - colorAttachments.push_back(&buffer); - break; - } - - glNamedFramebufferRenderbuffer(id, attachment, buffer.id, level); -} - -void Framebuffer::check() const { - GLenum result = glCheckNamedFramebufferStatus(id, GL_FRAMEBUFFER); - if (result != GL_FRAMEBUFFER_COMPLETE) { - throw result; - } -} - -void Framebuffer::destroyAll() { - destroy(); - size_t length = colorAttachments.size(); - for (size_t i = 0; i < length; i++) { - delete colorAttachments[i]; - } - colorAttachments.clear(); - if (stencilAttachment != NULL) { - delete stencilAttachment; - } - if (depthAttachment != NULL && depthAttachment != stencilAttachment) { - delete depthAttachment; - } - stencilAttachment = NULL; - depthAttachment = NULL; + return *new VertexAttribute(entries, stride, divisor); } GLint createShader(const std::string path, GLenum shaderType) { - std::ifstream t(path); - std::stringstream buffer; - buffer << t.rdbuf(); - - std::string codeSrc = buffer.str(); - const GLchar* codeSrcCStr = codeSrc.c_str(); - - GLint id = glCreateShader(shaderType); - glShaderSource(id, 1, &codeSrcCStr, NULL); - glCompileShader(id); - - GLint compiled = 0; - glGetShaderiv(id, GL_COMPILE_STATUS, &compiled); - if (compiled == GL_FALSE) { - GLint logLength; - glGetShaderiv(id, GL_INFO_LOG_LENGTH, &logLength); - - if (logLength > 0) { - std::vector infoLog(logLength); - glGetShaderInfoLog(id, logLength, &logLength, &infoLog[0]); - std::cout << &infoLog[0] << std::endl; - } - } + std::ifstream t(path); + std::stringstream buffer; + buffer << t.rdbuf(); + + std::string codeSrc = buffer.str(); + const GLchar* codeSrcCStr = codeSrc.c_str(); + + GLint id = glCreateShader(shaderType); + glShaderSource(id, 1, &codeSrcCStr, NULL); + glCompileShader(id); + + GLint compiled = 0; + glGetShaderiv(id, GL_COMPILE_STATUS, &compiled); + if (compiled == GL_FALSE) { + GLint logLength; + glGetShaderiv(id, GL_INFO_LOG_LENGTH, &logLength); + + if (logLength > 0) { + std::vector infoLog(logLength); + glGetShaderInfoLog(id, logLength, &logLength, &infoLog[0]); + std::cout << &infoLog[0] << std::endl; + } + } - return id; + return id; } OpenGL::ShaderProgram::ShaderProgram(const std::string vertex, const std::string fragment) { - this->id = glCreateProgram(); - int vert = createShader(vertex, GL_VERTEX_SHADER); - int frag = createShader(fragment, GL_FRAGMENT_SHADER); - - glAttachShader(this->id, vert); - glAttachShader(this->id, frag); - - glLinkProgram(this->id); - - GLint linked = 0; - glGetProgramiv(this->id, GL_LINK_STATUS, &linked); - if (linked == GL_FALSE) { - GLint logLength; - glGetProgramiv(this->id, GL_INFO_LOG_LENGTH, &logLength); - - if (logLength > 0) { - std::vector infoLog(logLength); - glGetProgramInfoLog(this->id, logLength, &logLength, &infoLog[0]); - std::cout << &infoLog[0] << std::endl; - } - } + this->id = glCreateProgram(); + int vert = createShader(vertex, GL_VERTEX_SHADER); + int frag = createShader(fragment, GL_FRAGMENT_SHADER); + + glAttachShader(this->id, vert); + glAttachShader(this->id, frag); + + glLinkProgram(this->id); + + GLint linked = 0; + glGetProgramiv(this->id, GL_LINK_STATUS, &linked); + if (linked == GL_FALSE) { + GLint logLength; + glGetProgramiv(this->id, GL_INFO_LOG_LENGTH, &logLength); + + if (logLength > 0) { + std::vector infoLog(logLength); + glGetProgramInfoLog(this->id, logLength, &logLength, &infoLog[0]); + std::cout << &infoLog[0] << std::endl; + } + } - glDetachShader(this->id, vert); - glDetachShader(this->id, frag); + glDetachShader(this->id, vert); + glDetachShader(this->id, frag); - glDeleteShader(vert); - glDeleteShader(frag); + glDeleteShader(vert); + glDeleteShader(frag); } void OpenGL::ShaderProgram::destroy() const { - glDeleteProgram(this->id); + glDeleteProgram(this->id); } OpenGL::ShaderProgram::~ShaderProgram() { - destroy(); + destroy(); } void OpenGL::ShaderProgram::bind0(const GLuint id) const { - glUseProgram(id); + glUseProgram(id); } void OpenGL::ShaderProgram::bindBuffer(const GLuint target, const BufferObject buffer, const std::string& blockName, const GLintptr offset, const GLsizeiptr size) { if (this->bindings.find(blockName) == this->bindings.end()) { - this->bindings[blockName] = this->bindings.size(); + this->bindings[blockName] = this->bindings.size(); } GLuint bindingIndex = this->bindings[blockName]; - if (offset == -1 || size == -1) { - glBindBufferBase(target, bindingIndex, buffer.id); - } else { + if (offset == -1 || size == -1) { + glBindBufferBase(target, bindingIndex, buffer.id); + } + else { glBindBufferRange(target, bindingIndex, buffer.id, offset, size); - } + } } diff --git a/src/GLObjects.hpp b/src/GLObjects.hpp index 06f97c7..a17ab93 100644 --- a/src/GLObjects.hpp +++ b/src/GLObjects.hpp @@ -7,192 +7,137 @@ #include namespace OpenGL { - class IGLObject { - public: - ~IGLObject(); - GLuint id; - - virtual void destroy() const {}; - }; - - class IGLBinding : public IGLObject { - protected: - virtual void bind0(GLuint id) const {}; - - public: - void bind() const; - void unbind() const; - }; - - class IGLTargetBinding : public IGLObject { - protected: - virtual void bind0(GLenum target, GLuint id) const {}; - - public: - void bind(GLenum target) const; - void unbind(GLenum target) const; - }; - - class BufferObject : public IGLTargetBinding { - public: - BufferObject(); - - GLsizeiptr size; - - void destroy() const override; - void bind0(GLenum target, GLuint id) const override; - - virtual void allocate(GLsizeiptr size, unsigned int flags); - virtual void allocate(const void* data, GLsizeiptr size, unsigned int flags); - void invalidate() const; - - class Mutable; - class Immutable; - }; - - class BufferObject::Mutable final : public BufferObject { - public: - void allocate(GLsizeiptr size, unsigned int flags) override; - void allocate(const void* data, GLsizeiptr size, unsigned int flags) override; - }; - - class BufferObject::Immutable final : public BufferObject { - public: - void allocate(GLsizeiptr size, unsigned int flags) override; - void allocate(const void* data, GLsizeiptr size, unsigned int flags) override; - }; - - class VertexArrayObject; - - class VertexAttribute { - private: - class Entry; - std::vector entries; - GLuint divisor; - - public: - VertexAttribute(std::vector entries, GLsizei stride, GLuint divisor); - ~VertexAttribute(); - - GLsizei stride; - - void apply(VertexArrayObject& vao, int binding); - - class Builder { - private: - GLsizei stride; - GLuint divisor; - GLuint offset; - std::vector entries; - public: + class IGLObject { + public: + ~IGLObject(); + GLuint id; + + virtual void destroy() const {}; + }; + + class IGLBinding : public IGLObject { + protected: + virtual void bind0(GLuint id) const {}; + + public: + void bind() const; + void unbind() const; + }; + + class IGLTargetBinding : public IGLObject { + protected: + virtual void bind0(GLenum target, GLuint id) const {}; + + public: + void bind(GLenum target) const; + void unbind(GLenum target) const; + }; + + class BufferObject : public IGLTargetBinding { + public: + BufferObject(); + + GLsizeiptr size; + + void destroy() const override; + void bind0(GLenum target, GLuint id) const override; + + virtual void allocate(GLsizeiptr size, unsigned int flags); + virtual void allocate(const void* data, GLsizeiptr size, unsigned int flags); + void invalidate() const; + + class Mutable; + class Immutable; + }; + + class BufferObject::Mutable final : public BufferObject { + public: + void allocate(GLsizeiptr size, unsigned int flags) override; + void allocate(const void* data, GLsizeiptr size, unsigned int flags) override; + }; + + class BufferObject::Immutable final : public BufferObject { + public: + void allocate(GLsizeiptr size, unsigned int flags) override; + void allocate(const void* data, GLsizeiptr size, unsigned int flags) override; + }; + + class VertexArrayObject; + + class VertexAttribute { + private: + class Entry; + std::vector entries; + GLuint divisor; + + public: + VertexAttribute(std::vector entries, GLsizei stride, GLuint divisor); + ~VertexAttribute(); + + GLsizei stride; + + void apply(VertexArrayObject& vao, int binding); + + class Builder { + private: + GLsizei stride; + GLuint divisor; + GLuint offset; + std::vector entries; + public: Builder(GLsizei stride, GLuint divisor = 0); - VertexAttribute::Builder& addInt(GLuint index, GLint size, GLenum type); - VertexAttribute::Builder& addFloat(GLuint index, GLint size, GLenum type, GLboolean normalized); - VertexAttribute::Builder& addPadding(GLuint size); - VertexAttribute& build(); - }; - }; - - class VertexArrayObject final : public IGLBinding { - private: - BufferObject* elementBuffer; - std::vector vertexBuffers; - - public: - VertexArrayObject(); - ~VertexArrayObject(); - - void destroy() const override; - void bind0(GLuint id) const override; - - void attachElementBuffer(BufferObject& buffer); - void attachVertexBuffer(BufferObject& buffer, GLuint offset, VertexAttribute& vertexAttribute); - void attachVertexBuffer(BufferObject& buffer, VertexAttribute& vertexAttribute); - - void clearAttachments(); - - void destroyAll(); - }; - - class VertexAttribute::Entry { - protected: - GLuint index; - GLint size; - GLenum type; - GLuint offset; - public: - virtual void apply(VertexArrayObject& vao, GLuint binding) const {}; - - class Float; - class Int; - }; - - class TextureObject : public IGLTargetBinding { - public: - GLenum target; - - TextureObject(GLenum target); - ~TextureObject(); - - void destroy() const override; - void bind0(GLenum unit, GLuint id) const override; - - class Texture2D; - }; - - class TextureObject::Texture2D final : public TextureObject { - public: - glm::i32vec2 size; - - Texture2D(); - - void allocate(const GLsizei levels, const GLenum internalformat, const glm::i32vec2 size); - void upload(const GLint level, const glm::i32vec2 offset, const glm::i32vec2 size, GLenum format, GLenum type, const void* pixels); - }; - - class RenderBuffer final : public IGLBinding { - public: - glm::i32vec2 size; - - RenderBuffer(); - ~RenderBuffer(); - - void destroy() const override; - void bind0(GLuint id) const override; - - void allocate(const GLenum internalformat, const glm::i32vec2 size); - }; - - class Framebuffer final : public IGLTargetBinding { - private: - std::vector colorAttachments; - const IGLObject* depthAttachment; - const IGLObject* stencilAttachment; - - public: - Framebuffer(); - ~Framebuffer(); - - void destroy() const override; - void bind0(const GLenum target, const GLuint id) const override; - - void attach(const TextureObject& texture, const GLenum attachment, const GLint level = 0); - void attach(const RenderBuffer& buffer, const GLenum attachment, const GLint level = 0); - void check() const; - void destroyAll(); - }; - - class ShaderProgram : public IGLBinding { - private: - std::unordered_map bindings; - public: - ShaderProgram(const std::string vertex, const std::string fragment); - ~ShaderProgram(); - - void destroy() const override; - void bind0(const GLuint id) const override; + VertexAttribute::Builder& addInt(GLuint index, GLint size, GLenum type); + VertexAttribute::Builder& addFloat(GLuint index, GLint size, GLenum type, GLboolean normalized); + VertexAttribute::Builder& addPadding(GLuint size); + VertexAttribute& build(); + }; + }; + + class VertexArrayObject final : public IGLBinding { + private: + BufferObject* elementBuffer; + std::vector vertexBuffers; + + public: + VertexArrayObject(); + ~VertexArrayObject(); + + void destroy() const override; + void bind0(GLuint id) const override; + + void attachElementBuffer(BufferObject& buffer); + void attachVertexBuffer(BufferObject& buffer, GLuint offset, VertexAttribute& vertexAttribute); + void attachVertexBuffer(BufferObject& buffer, VertexAttribute& vertexAttribute); + + void clearAttachments(); + + void destroyAll(); + }; + + class VertexAttribute::Entry { + protected: + GLuint index; + GLint size; + GLenum type; + GLuint offset; + public: + virtual void apply(VertexArrayObject& vao, GLuint binding) const {}; + + class Float; + class Int; + }; + + class ShaderProgram : public IGLBinding { + private: + std::unordered_map bindings; + public: + ShaderProgram(const std::string vertex, const std::string fragment); + ~ShaderProgram(); + + void destroy() const override; + void bind0(const GLuint id) const override; void bindBuffer(const GLuint target, const BufferObject buffer, const std::string& blockName, const GLintptr offset = -1, const GLsizeiptr size = -1); - }; + }; } \ No newline at end of file diff --git a/src/Game.cpp b/src/Game.cpp new file mode 100644 index 0000000..b4ec382 --- /dev/null +++ b/src/Game.cpp @@ -0,0 +1,37 @@ +#include "Game.hpp" + +Game::Game() : player(), world(), timeElapsed(0.0), state(State::Waiting) {} + +void Game::placeFood(int n) { + for (int i = 0; i < n; ++i) { + this->world.placeFood(this->player); + } +} + +void Game::tick(double dt) { + switch (this->state) { + case State::Waiting: + // give 1 second so stuff has a chance to load + this->timeElapsed += dt; + if (this->timeElapsed >= 1.0) { + this->state = State::Playing; + this->timeElapsed = 0.0f; + } + break; + case State::Playing: + this->timeElapsed += dt; + // if they didn't lose + if (this->player.tick(dt, this->world) != LoseCode::None) + this->state = State::Overing; + break; + case State::Overing: + // game over :( + break; + default: + break; + } +} + +int Game::getScore() { + return (int) timeElapsed + player.foodsEaten; +} \ No newline at end of file diff --git a/src/Game.hpp b/src/Game.hpp new file mode 100644 index 0000000..24ed335 --- /dev/null +++ b/src/Game.hpp @@ -0,0 +1,24 @@ +#pragma once + +#include "World.hpp" +#include "Snake.hpp" + +enum class State { + Waiting, + Playing, + Overing, +}; + +class Game { +public: + Snake player; + World world; + long double timeElapsed; + State state; + + + Game(); + void placeFood(int n = 1); + void tick(double dt); + int getScore(); +}; \ No newline at end of file diff --git a/src/Main.cpp b/src/Main.cpp index fa40f73..9e2611b 100644 --- a/src/Main.cpp +++ b/src/Main.cpp @@ -1,23 +1,22 @@ #include -#include "Main.h" +#include "Main.hpp" #include #include #include -#include "RenderEngine.h" - -#include "game/Game.hpp" +#include "RenderEngine.hpp" +#include "Game.hpp" // Debug message handler void GLAPIENTRY messageCallback(GLenum source, - GLenum type, - GLuint id, - GLenum severity, - GLsizei length, - const GLchar* message, - const void* userParam) { - fprintf(stderr, "GL CALLBACK: %s type = 0x%x, severity = 0x%x, message = %s\n", - (type == GL_DEBUG_TYPE_ERROR ? "** GL ERROR **" : ""), - type, severity, message); + GLenum type, + GLuint id, + GLenum severity, + GLsizei length, + const GLchar* message, + const void* userParam) { + fprintf(stderr, "GL CALLBACK: %s type = 0x%x, severity = 0x%x, message = %s\n", + (type == GL_DEBUG_TYPE_ERROR ? "** GL ERROR **" : ""), + type, severity, message); } // game instance @@ -29,174 +28,175 @@ bool controlled = false; bool wireframe = false; void keyCallback(GLFWwindow* window, int key, int scancode, int action, int mods) { - if (key == GLFW_KEY_LEFT_CONTROL) { - if (action == GLFW_PRESS) { - controlled = true; - } - else if (action == GLFW_RELEASE) { - controlled = false; - } - } else if (action == GLFW_PRESS || action == GLFW_REPEAT) { - glm::vec2 cameraRotation = renderEnginePtr->camera.rotation; - cameraRotation.x += 180.0f; - cameraRotation.y = 0.0f; - cameraRotation = glm::round(cameraRotation / 90.0f) * 90.0f; - switch (key) { - case GLFW_KEY_W: - game.player.setRotation(cameraRotation + glm::vec2(0.0f, 0.0f)); - break; - case GLFW_KEY_A: - game.player.setRotation(cameraRotation + glm::vec2(-90.0f, 0.0f)); - break; - case GLFW_KEY_S: - game.player.setRotation(cameraRotation + glm::vec2(180.0f, 0.0f)); - break; - case GLFW_KEY_D: - game.player.setRotation(cameraRotation + glm::vec2(90.0f, 0.0f)); - break; - - case GLFW_KEY_SPACE: - game.player.setRotation(glm::vec2(0.0f, 90.0f)); - break; - case GLFW_KEY_LEFT_SHIFT: - game.player.setRotation(glm::vec2(0.0f, -90.0f)); - break; - - case GLFW_KEY_ESCAPE: - glfwSetWindowShouldClose(window, GL_TRUE); - break; - - - // debug controls - case GLFW_KEY_T: // wireframe toggle - if (controlled) { - wireframe = !wireframe; - if (wireframe) { - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - } - else { - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - } - } - break; - case GLFW_KEY_R: // restart - if (controlled) { - game.player = Snake(); - game.state = State::Waiting; - game.timeElapsed = 0.0; - game.world.objects = {}; - game.placeFood(INITIAL_FOODS); - } - break; - case GLFW_KEY_F: // force end - if (controlled) { - game.state = State::Overing; - } - break; - case GLFW_KEY_C: // force continue - if (controlled) { - game.state = State::Playing; - } - break; - default: - break; - } - } + if (key == GLFW_KEY_LEFT_CONTROL) { + if (action == GLFW_PRESS) { + controlled = true; + } + else if (action == GLFW_RELEASE) { + controlled = false; + } + } + else if (action == GLFW_PRESS || action == GLFW_REPEAT) { + glm::vec2 cameraRotation = renderEnginePtr->camera.rotation; + cameraRotation.x += 180.0f; + cameraRotation.y = 0.0f; + cameraRotation = glm::round(cameraRotation / 90.0f) * 90.0f; + switch (key) { + case GLFW_KEY_W: + game.player.setRotation(cameraRotation + glm::vec2(0.0f, 0.0f)); + break; + case GLFW_KEY_A: + game.player.setRotation(cameraRotation + glm::vec2(-90.0f, 0.0f)); + break; + case GLFW_KEY_S: + game.player.setRotation(cameraRotation + glm::vec2(180.0f, 0.0f)); + break; + case GLFW_KEY_D: + game.player.setRotation(cameraRotation + glm::vec2(90.0f, 0.0f)); + break; + + case GLFW_KEY_SPACE: + game.player.setRotation(glm::vec2(0.0f, 90.0f)); + break; + case GLFW_KEY_LEFT_SHIFT: + game.player.setRotation(glm::vec2(0.0f, -90.0f)); + break; + + case GLFW_KEY_ESCAPE: + glfwSetWindowShouldClose(window, GL_TRUE); + break; + + + // debug controls + case GLFW_KEY_T: // wireframe toggle + if (controlled) { + wireframe = !wireframe; + if (wireframe) { + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + } + else { + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + } + } + break; + case GLFW_KEY_R: // restart + if (controlled) { + game.player = Snake(); + game.state = State::Waiting; + game.timeElapsed = 0.0; + game.world.objects = {}; + game.placeFood(INITIAL_FOODS); + } + break; + case GLFW_KEY_F: // force end + if (controlled) { + game.state = State::Overing; + } + break; + case GLFW_KEY_C: // force continue + if (controlled) { + game.state = State::Playing; + } + break; + default: + break; + } + } } int main() { - std::string title = "Wacky Snake"; + std::string title = "Wacky Snake"; - glfwInit(); + glfwInit(); - glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); - glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6); + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6); GameWindow gameWindow{ {-1, -1}, {1280, 720}, nullptr }; - gameWindow.window = glfwCreateWindow(gameWindow.windowSize.x, gameWindow.windowSize.y, title.c_str(), NULL, NULL); - glfwMakeContextCurrent(gameWindow.window); + gameWindow.window = glfwCreateWindow(gameWindow.windowSize.x, gameWindow.windowSize.y, title.c_str(), NULL, NULL); + glfwMakeContextCurrent(gameWindow.window); - glewInit(); + glewInit(); - // Double buffered V-Sync - glfwSwapInterval(1); - glfwWindowHint(GLFW_DOUBLEBUFFER, true); - glfwSetInputMode(gameWindow.window, GLFW_RAW_MOUSE_MOTION, GLFW_TRUE); + // Double buffered V-Sync + glfwSwapInterval(1); + glfwWindowHint(GLFW_DOUBLEBUFFER, GLFW_TRUE); + glfwSetInputMode(gameWindow.window, GLFW_RAW_MOUSE_MOTION, GLFW_TRUE); glfwSetInputMode(gameWindow.window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN); - glfwPollEvents(); + glfwPollEvents(); - // Mouse/Keyboard callbacks - //glfwSetMouseButtonCallback(window, mouseButtonCallback); + // Mouse/Keyboard callbacks + //glfwSetMouseButtonCallback(window, mouseButtonCallback); - glfwSetKeyCallback(gameWindow.window, keyCallback); - glm::f64vec2 prevMousePos; + glfwSetKeyCallback(gameWindow.window, keyCallback); + glm::f64vec2 prevMousePos; glfwGetCursorPos(gameWindow.window, &prevMousePos.x, &prevMousePos.y); - glm::f64vec2 mousePos; + glm::f64vec2 mousePos; - #ifdef _DEBUG - glEnable(GL_DEBUG_OUTPUT); - glDebugMessageCallback(messageCallback, 0); - #endif +#ifdef _DEBUG + glEnable(GL_DEBUG_OUTPUT); + glDebugMessageCallback(messageCallback, 0); +#endif - // Setup here + // Setup here RenderEngine renderEngine; - renderEnginePtr = &renderEngine; + renderEnginePtr = &renderEngine; - GLenum err; - while ((err = glGetError()) != GL_NO_ERROR) { - std::cerr << "Pre render OpenGL error: " << err << std::endl; - } + GLenum err; + while ((err = glGetError()) != GL_NO_ERROR) { + std::cerr << "Pre render OpenGL error: " << err << std::endl; + } - double curTime = glfwGetTime(); - double lastTickTime = curTime; + double curTime = glfwGetTime(); + double lastTickTime = curTime; - // game initialization - game.placeFood(INITIAL_FOODS); + // game initialization + game.placeFood(INITIAL_FOODS); - while (!glfwWindowShouldClose(gameWindow.window)) { - glfwPollEvents(); - // Process inputs here - glm::f64vec2 center = (glm::f64vec2) gameWindow.windowSize / 2.0; + while (!glfwWindowShouldClose(gameWindow.window)) { + glfwPollEvents(); + // Process inputs here + glm::f64vec2 center = (glm::f64vec2) gameWindow.windowSize / 2.0; glfwGetCursorPos(gameWindow.window, &mousePos.x, &mousePos.y); glm::f32vec2 mouseDelta = mousePos - prevMousePos; - glfwSetCursorPos(gameWindow.window, center.x, center.y); - glfwGetCursorPos(gameWindow.window, &prevMousePos.x, &prevMousePos.y); - - double time = glfwGetTime(); - double dt = time - curTime; - curTime = time; - game.tick(dt); - - glfwGetWindowSize(gameWindow.window, &gameWindow.windowSize.x, &gameWindow.windowSize.y); - - if (gameWindow.prevWindowSize != gameWindow.windowSize - && gameWindow.windowSize.x != 0 && gameWindow.windowSize.y != 0) { - gameWindow.prevWindowSize = gameWindow.windowSize; - } - - glBindFramebuffer(GL_FRAMEBUFFER, 0); - glClearColor(0.0f, 0.0f, 0.0f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glViewport(0, 0, gameWindow.windowSize.x, gameWindow.windowSize.y); - glEnable(GL_CULL_FACE); - glCullFace(GL_BACK); - - // Render goes here - renderEngine.camera.updateProjection(gameWindow); - renderEngine.camera.updateModelView(game, mouseDelta); + glfwSetCursorPos(gameWindow.window, center.x, center.y); + glfwGetCursorPos(gameWindow.window, &prevMousePos.x, &prevMousePos.y); + + double time = glfwGetTime(); + double dt = time - curTime; + curTime = time; + game.tick(dt); + + glfwGetWindowSize(gameWindow.window, &gameWindow.windowSize.x, &gameWindow.windowSize.y); + + if (gameWindow.prevWindowSize != gameWindow.windowSize + && gameWindow.windowSize.x != 0 && gameWindow.windowSize.y != 0) { + gameWindow.prevWindowSize = gameWindow.windowSize; + } + + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glViewport(0, 0, gameWindow.windowSize.x, gameWindow.windowSize.y); + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + + // Render goes here + renderEngine.camera.updateProjection(gameWindow); + renderEngine.camera.updateModelView(game, mouseDelta); renderEngine.setup(gameWindow, game, dt); renderEngine.render(gameWindow, dt); - glBindFramebuffer(GL_FRAMEBUFFER, 0); + glBindFramebuffer(GL_FRAMEBUFFER, 0); - GLenum err; - while ((err = glGetError()) != GL_NO_ERROR) { - std::cerr << "OpenGL error: " << err << std::endl; - } + GLenum err; + while ((err = glGetError()) != GL_NO_ERROR) { + std::cerr << "OpenGL error: " << err << std::endl; + } - glfwSwapBuffers(gameWindow.window); - } + glfwSwapBuffers(gameWindow.window); + } - glfwDestroyWindow(gameWindow.window); + glfwDestroyWindow(gameWindow.window); } \ No newline at end of file diff --git a/src/Main.h b/src/Main.hpp similarity index 100% rename from src/Main.h rename to src/Main.hpp diff --git a/src/MathUtils.cpp b/src/MathUtils.cpp index 429807b..0a4aa63 100644 --- a/src/MathUtils.cpp +++ b/src/MathUtils.cpp @@ -1,4 +1,4 @@ -#include "MathUtils.h" +#include "MathUtils.hpp" #include float normalizeAngle(float x) { diff --git a/src/MathUtils.h b/src/MathUtils.hpp similarity index 100% rename from src/MathUtils.h rename to src/MathUtils.hpp diff --git a/src/game/Object.hpp b/src/Object.hpp similarity index 100% rename from src/game/Object.hpp rename to src/Object.hpp diff --git a/src/RenderEngine.cpp b/src/RenderEngine.cpp index 76ecb15..bc00003 100644 --- a/src/RenderEngine.cpp +++ b/src/RenderEngine.cpp @@ -1,10 +1,10 @@ -#include "RenderEngine.h" +#include "RenderEngine.hpp" #include "Mesh.hpp" #include #include #include #include -#include "Main.h" +#include "Main.hpp" #include Camera::Camera() : matrix(), rotation(160.0f, 30.0f), fov(60.0f) {} diff --git a/src/RenderEngine.h b/src/RenderEngine.hpp similarity index 92% rename from src/RenderEngine.h rename to src/RenderEngine.hpp index 35d1ff7..f4c3f3d 100644 --- a/src/RenderEngine.h +++ b/src/RenderEngine.hpp @@ -1,9 +1,9 @@ #pragma once -#include "game/Game.hpp" +#include "Game.hpp" #include #include "GLObjects.hpp" -#include "Main.h" +#include "Main.hpp" class RenderEngine; diff --git a/src/Snake.cpp b/src/Snake.cpp new file mode 100644 index 0000000..ce27efe --- /dev/null +++ b/src/Snake.cpp @@ -0,0 +1,6 @@ +#include "Snake.hpp" + +Snake::Snake() : + segments({ glm::vec3(0.0), glm::vec3(0.0, 0.0, -20.0) }), + rotation(), + length(20.0f) {} \ No newline at end of file diff --git a/src/game/Snake.hpp b/src/Snake.hpp similarity index 93% rename from src/game/Snake.hpp rename to src/Snake.hpp index c19fe4b..ae2bda8 100644 --- a/src/game/Snake.hpp +++ b/src/Snake.hpp @@ -3,8 +3,7 @@ #include #include #include - -#include "../MathUtils.h" +#include "MathUtils.hpp" #include "Object.hpp" #include "World.hpp" @@ -34,10 +33,7 @@ class Snake { static constexpr float speed = 2.0f; // speed in m/s float shrinkage = glm::pow(0.5f, 1.0f / 30.0f); - Snake() : - segments({ glm::vec3(0.0), glm::vec3(0.0, 0.0, -20.0) }), - rotation(), - length(20.0f) {} + Snake(); void setRotation(glm::vec2 rotation) { rotation.x = normalizeAngle(rotation.x); diff --git a/src/World.cpp b/src/World.cpp new file mode 100644 index 0000000..0b13079 --- /dev/null +++ b/src/World.cpp @@ -0,0 +1,5 @@ + +#include "World.hpp" +#include "Object.hpp" + +World::World() : objects(), rd(), re(rd()) {} \ No newline at end of file diff --git a/src/game/World.hpp b/src/World.hpp similarity index 92% rename from src/game/World.hpp rename to src/World.hpp index f499252..257f700 100644 --- a/src/game/World.hpp +++ b/src/World.hpp @@ -2,30 +2,25 @@ #include #include - #include "Object.hpp" struct World { std::vector objects; - std::random_device rd; std::default_random_engine re; - World() : - objects(), rd(), re(rd()) {} - - + World(); // returns nullptr on failure, ignores None items // type T must have distance function that takes an Object as input - template [[nodiscard]] + template + [[nodiscard]] ItemObj* checkCollision(const T& obj, Object* filter = nullptr) { for (auto& object : objects) { if (object.item == Item::None || &object == filter) continue; if (obj.dist(object) <= 0.0) return &object; } - return nullptr; } @@ -35,9 +30,7 @@ struct World { std::uniform_int_distribution dist(-63, 63); do { - obj.pos = glm::vec3(dist(re), dist(re), dist(re)); - } while (checkCollision(obj, &obj) != nullptr || collider.collides(obj)); } diff --git a/src/game/Game.hpp b/src/game/Game.hpp deleted file mode 100644 index 7e714c4..0000000 --- a/src/game/Game.hpp +++ /dev/null @@ -1,63 +0,0 @@ -#pragma once - -#include "World.hpp" -#include "Snake.hpp" - -enum class State { - Waiting, - Playing, - Overing, -}; - -class Game { -public: - Snake player; - World world; - long double timeElapsed = 0.0; - - State state = State::Waiting; - - - Game() : - player(), world() {} - - void placeFood(int n = 1) { - for (int i = 0; i < n; ++i) { - world.placeFood(player); - } - } - - void tick(double dt) { - - switch (state) - { - case State::Waiting: - // give 1 second so stuff has a chance to load - timeElapsed += dt; - - if (timeElapsed >= 1.0) { - state = State::Playing; - timeElapsed = 0.0f; - } - - break; - - case State::Playing: - timeElapsed += dt; - // if they didn't lose - if (player.tick(dt, world) != LoseCode::None) - state = State::Overing; - break; - - case State::Overing: - // game over :( - break; - default: - break; - } - } - - double getScore() { - return timeElapsed + player.foodsEaten; - } -}; \ No newline at end of file diff --git a/src/mesh.hpp b/src/mesh.hpp index 4b0b960..c6e52ef 100644 --- a/src/mesh.hpp +++ b/src/mesh.hpp @@ -2,21 +2,18 @@ #include #include - #include -#include "RenderEngine.h" - -using namespace glm; +#include "RenderEngine.hpp" template [[nodiscard]] -std::array createNormals(const std::array& mesh) { +std::array createNormals(const std::array& mesh) { - std::array out{}; + std::array out{}; for (int i = 0; i < N / 3; ++i) { - vec3 a = mesh[i * 3]; - vec3 b = mesh[i * 3 + 1]; - vec3 c = mesh[i * 3 + 2]; + glm::vec3 a = mesh[i * 3]; + glm::vec3 b = mesh[i * 3 + 1]; + glm::vec3 c = mesh[i * 3 + 2]; out[i] = glm::normalize(glm::cross(b - a, c - a)); } @@ -25,15 +22,15 @@ std::array createNormals(const std::array& mesh) { } template [[nodiscard]] -std::vector createNormals(const T& mesh) { +std::vector createNormals(const T& mesh) { - std::vector out; + std::vector out; out.reserve(mesh.size() / 3); for (int i = 0; i < mesh.size() / 3; ++i) { - vec3 A = mesh[i * 3]; - vec3 B = mesh[i * 3 + 1]; - vec3 C = mesh[i * 3 + 2]; + glm::vec3 A = mesh[i * 3]; + glm::vec3 B = mesh[i * 3 + 1]; + glm::vec3 C = mesh[i * 3 + 2]; out.emplace_back(glm::normalize(glm::cross(B - A, C - A))); } @@ -43,26 +40,26 @@ std::vector createNormals(const T& mesh) { //creates an axis-aligned rectangular prism given two points [[nodiscard]] -constexpr std::array createRectMesh(const vec3& p1, const vec3& p2, float sidelen) { +constexpr std::array createRectMesh(const glm::vec3& p1, const glm::vec3& p2, float sidelen) { float halflen = sidelen * 0.5f; - float minX = min(p1.x, p2.x) - halflen; - float minY = min(p1.y, p2.y) - halflen; - float minZ = min(p1.z, p2.z) - halflen; + float minX = glm::min(p1.x, p2.x) - halflen; + float minY = glm::min(p1.y, p2.y) - halflen; + float minZ = glm::min(p1.z, p2.z) - halflen; - float maxX = max(p1.x, p2.x) + halflen; - float maxY = max(p1.y, p2.y) + halflen; - float maxZ = max(p1.z, p2.z) + halflen; + float maxX = glm::max(p1.x, p2.x) + halflen; + float maxY = glm::max(p1.y, p2.y) + halflen; + float maxZ = glm::max(p1.z, p2.z) + halflen; - vec3 vertA(minX, minY, minZ); - vec3 vertB(maxX, minY, minZ); - vec3 vertC(minX, maxY, minZ); - vec3 vertD(maxX, maxY, minZ); + glm::vec3 vertA(minX, minY, minZ); + glm::vec3 vertB(maxX, minY, minZ); + glm::vec3 vertC(minX, maxY, minZ); + glm::vec3 vertD(maxX, maxY, minZ); - vec3 vertG(minX, minY, maxZ); - vec3 vertH(maxX, minY, maxZ); - vec3 vertE(minX, maxY, maxZ); - vec3 vertF(maxX, maxY, maxZ); + glm::vec3 vertG(minX, minY, maxZ); + glm::vec3 vertH(maxX, minY, maxZ); + glm::vec3 vertE(minX, maxY, maxZ); + glm::vec3 vertF(maxX, maxY, maxZ); return { vertA, vertD, vertB, @@ -86,20 +83,18 @@ constexpr std::array createRectMesh(const vec3& p1, const vec3& p2, fl } [[nodiscard]] -std::vector createSnakeMesh(const std::vector& points, float sidelen) { +std::vector createSnakeMesh(const std::vector& points, float sidelen) { if (points.size() < 2) return {}; - std::vector out; + std::vector out; out.reserve(points.size() * 36); for (int i = 1; i < points.size(); ++i) { auto p1 = points[i - 1]; auto p2 = points[i]; - vec3 dir = normalize(p2 - p1); - - //vec3 endp = p2 - dir * sidelen; - vec3 endp = p2; + glm::vec3 dir = normalize(p2 - p1); + glm::vec3 endp = p2; auto verts = createRectMesh(p1, endp, sidelen); for (auto&& vert : verts) { @@ -110,7 +105,7 @@ std::vector createSnakeMesh(const std::vector& points, float sidelen return out; } -void fillSnakeMeshInterleaved(const std::vector& points, PersistentMappedBuffer& buffer, float sidelen, vec4 color) { +void fillSnakeMeshInterleaved(const std::vector& points, PersistentMappedBuffer& buffer, float sidelen, glm::vec4 color) { auto snakeMesh = createSnakeMesh(points, sidelen); auto normals = createNormals(snakeMesh); @@ -118,45 +113,45 @@ void fillSnakeMeshInterleaved(const std::vector& points, PersistentMappedB int nIndex = i / 3; auto& curA = snakeMesh[i]; - memcpy(buffer.pointer + buffer.size, &curA, sizeof(vec3)); - buffer.size += sizeof(vec3); - memcpy(buffer.pointer + buffer.size, &normals[nIndex], sizeof(vec3)); - buffer.size += sizeof(vec3); - memcpy(buffer.pointer + buffer.size, &color, sizeof(vec4)); - buffer.size += sizeof(vec4); + memcpy(buffer.pointer + buffer.size, &curA, sizeof(glm::vec3)); + buffer.size += sizeof(glm::vec3); + memcpy(buffer.pointer + buffer.size, &normals[nIndex], sizeof(glm::vec3)); + buffer.size += sizeof(glm::vec3); + memcpy(buffer.pointer + buffer.size, &color, sizeof(glm::vec4)); + buffer.size += sizeof(glm::vec4); auto& curB = snakeMesh[i + 1]; - memcpy(buffer.pointer + buffer.size, &curB, sizeof(vec3)); - buffer.size += sizeof(vec3); - memcpy(buffer.pointer + buffer.size, &normals[nIndex], sizeof(vec3)); - buffer.size += sizeof(vec3); - memcpy(buffer.pointer + buffer.size, &color, sizeof(vec4)); - buffer.size += sizeof(vec4); + memcpy(buffer.pointer + buffer.size, &curB, sizeof(glm::vec3)); + buffer.size += sizeof(glm::vec3); + memcpy(buffer.pointer + buffer.size, &normals[nIndex], sizeof(glm::vec3)); + buffer.size += sizeof(glm::vec3); + memcpy(buffer.pointer + buffer.size, &color, sizeof(glm::vec4)); + buffer.size += sizeof(glm::vec4); auto& curC = snakeMesh[i + 2]; - memcpy(buffer.pointer + buffer.size, &curC, sizeof(vec3)); - buffer.size += sizeof(vec3); - memcpy(buffer.pointer + buffer.size, &normals[nIndex], sizeof(vec3)); - buffer.size += sizeof(vec3); - memcpy(buffer.pointer + buffer.size, &color, sizeof(vec4)); - buffer.size += sizeof(vec4); + memcpy(buffer.pointer + buffer.size, &curC, sizeof(glm::vec3)); + buffer.size += sizeof(glm::vec3); + memcpy(buffer.pointer + buffer.size, &normals[nIndex], sizeof(glm::vec3)); + buffer.size += sizeof(glm::vec3); + memcpy(buffer.pointer + buffer.size, &color, sizeof(glm::vec4)); + buffer.size += sizeof(glm::vec4); } } [[nodiscard]] -consteval std::array createFoodMesh() { - constexpr float a = 0.52573; - constexpr float b = 0.85065; +consteval std::array createFoodMesh() { + constexpr float a = 0.52573f; + constexpr float b = 0.85065f; // adapted from https://github.com/anishagartia/Icosahedron_OpenGL - constexpr std::array < vec3, 12> verts = { - vec3(-a, 0.0, b), vec3(a, 0.0, b), vec3(-a, 0.0, -b), vec3(a, 0.0, -b), - vec3(0.0, b, a), vec3(0.0, b, -a), vec3(0.0, -b, a), vec3(0.0, -b, -a), - vec3(b, a, 0.0), vec3(-b, a, 0.0), vec3(b, -a, 0.0), vec3(-b, -a, 0.0) + constexpr std::array verts = { + glm::vec3{ -a, 0.0f, b }, { a, 0.0, b }, { -a, 0.0, -b }, { a, 0.0, -b }, + { 0.0, b, a }, { 0.0, b, -a }, { 0.0, -b, a }, { 0.0, -b, -a }, + { b, a, 0.0 }, { -b, a, 0.0 }, { b, -a, 0.0 }, { -b, -a, 0.0 } }; //unit isocahedron - constexpr std::array isocahedronMesh = { + constexpr std::array isocahedronMesh = { verts[0], verts[4], verts[1], verts[0], verts[9], verts[4], verts[9], verts[5], verts[4], @@ -183,10 +178,10 @@ consteval std::array createFoodMesh() { } [[nodiscard]] -constexpr std::array createFoodMesh(vec3 pos, float r) { - constexpr std::array isocahedronMesh = createFoodMesh(); +constexpr std::array createFoodMesh(glm::vec3 pos, float r) { + constexpr std::array isocahedronMesh = createFoodMesh(); - std::array out{}; + std::array out{}; for (int i = 0; i < out.size(); ++i) { out[i] = isocahedronMesh[i] * r + pos; } @@ -194,35 +189,35 @@ constexpr std::array createFoodMesh(vec3 pos, float r) { return out; } -void fillFoodMeshInterleaved(PersistentMappedBuffer& buffer, vec3 pos, float radius, vec4 color) { +void fillFoodMeshInterleaved(PersistentMappedBuffer& buffer, const glm::vec3& pos, float radius, const glm::vec4& color) { static constexpr auto isocahedronMesh = createFoodMesh(); static auto normals = createNormals(isocahedronMesh); for (int i = 0; i < 20; i++) { - vec3 transformed = isocahedronMesh[i * 3] * radius + pos; - memcpy(buffer.pointer + buffer.size, &transformed, sizeof(vec3)); - buffer.size += sizeof(vec3); - memcpy(buffer.pointer + buffer.size, &normals[i], sizeof(vec3)); - buffer.size += sizeof(vec3); - memcpy(buffer.pointer + buffer.size, &color, sizeof(vec4)); - buffer.size += sizeof(vec4); + glm::vec3 transformed = isocahedronMesh[i * 3] * radius + pos; + memcpy(buffer.pointer + buffer.size, &transformed, sizeof(glm::vec3)); + buffer.size += sizeof(glm::vec3); + memcpy(buffer.pointer + buffer.size, &normals[i], sizeof(glm::vec3)); + buffer.size += sizeof(glm::vec3); + memcpy(buffer.pointer + buffer.size, &color, sizeof(glm::vec4)); + buffer.size += sizeof(glm::vec4); transformed = isocahedronMesh[i * 3 + 1] * radius + pos; - memcpy(buffer.pointer + buffer.size, &transformed, sizeof(vec3)); - buffer.size += sizeof(vec3); - memcpy(buffer.pointer + buffer.size, &normals[i], sizeof(vec3)); - buffer.size += sizeof(vec3); - memcpy(buffer.pointer + buffer.size, &color, sizeof(vec4)); - buffer.size += sizeof(vec4); + memcpy(buffer.pointer + buffer.size, &transformed, sizeof(glm::vec3)); + buffer.size += sizeof(glm::vec3); + memcpy(buffer.pointer + buffer.size, &normals[i], sizeof(glm::vec3)); + buffer.size += sizeof(glm::vec3); + memcpy(buffer.pointer + buffer.size, &color, sizeof(glm::vec4)); + buffer.size += sizeof(glm::vec4); transformed = isocahedronMesh[i * 3 + 2] * radius + pos; - memcpy(buffer.pointer + buffer.size, &transformed, sizeof(vec3)); - buffer.size += sizeof(vec3); - memcpy(buffer.pointer + buffer.size, &normals[i], sizeof(vec3)); - buffer.size += sizeof(vec3); - memcpy(buffer.pointer + buffer.size, &color, sizeof(vec4)); - buffer.size += sizeof(vec4); + memcpy(buffer.pointer + buffer.size, &transformed, sizeof(glm::vec3)); + buffer.size += sizeof(glm::vec3); + memcpy(buffer.pointer + buffer.size, &normals[i], sizeof(glm::vec3)); + buffer.size += sizeof(glm::vec3); + memcpy(buffer.pointer + buffer.size, &color, sizeof(glm::vec4)); + buffer.size += sizeof(glm::vec4); } } diff --git a/wacky-snake.vcxproj b/wacky-snake.vcxproj index b07440c..1dc2e1e 100644 --- a/wacky-snake.vcxproj +++ b/wacky-snake.vcxproj @@ -122,6 +122,7 @@ stdcpp20 + MultiThreadedDebug @@ -131,24 +132,34 @@ Speed true true + MultiThreaded + MaxSpeed + true + true + + UseLinkTimeCodeGeneration + + + + - - - - + + + + + - + - - + diff --git a/wacky-snake.vcxproj.filters b/wacky-snake.vcxproj.filters index 92f6abb..e601b54 100644 --- a/wacky-snake.vcxproj.filters +++ b/wacky-snake.vcxproj.filters @@ -27,6 +27,15 @@ Source Files + + Source Files + + + Source Files + + + Source Files + @@ -35,25 +44,25 @@ Header Files - + Header Files - + Header Files - + Header Files - + Header Files - + Header Files - + Header Files - + Header Files