/* Copyright (C) 2021 hiimgoodpack This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #define FAST_OBJ_IMPLEMENTATION #include "../fast_obj/fast_obj.h" #include #include #include #include #include #include typedef struct { linalg::aliases::float3 position; } Vertex; typedef unsigned int Element; const Mesh::Attribute VERTEX_ATTRIBUTES[] = { { .index = 0, .size = 3, .type = GL_FLOAT, .stride = sizeof(Vertex), .pointer = (void*)offsetof(Vertex, position) } }; Mesh::InstancedElements processMesh(const char* const path) { fastObjMesh* mesh = fast_obj_read(path); assert(mesh && "An error occured while reading a mesh. Make sure the path is correct and points to a wavefront object file"); const unsigned int vertexCount = mesh->position_count-1; const unsigned int indexCount = mesh->face_count*3; Vertex* const vertices = new Vertex[vertexCount]; Element* const elements = new Element[indexCount]; // Index 0 is an invalid index to use in an object file, so we'll remove it for (unsigned int i = 1; i < mesh->position_count; i++) { vertices[i-1].position = {mesh->positions[i*3], mesh->positions[i*3+1], mesh->positions[i*3+2]}; } for (unsigned int i = 0; i < mesh->face_count; i += 3) { elements[i] = mesh->indices[i].p-1; elements[i+1] = mesh->indices[i].t-1; elements[i+2] = mesh->indices[i].n-1; } fast_obj_destroy(mesh); // TODO: Make a way to clean up buffers Buffer::Specialized vertexBuffer(vertices, vertexCount * sizeof(Vertex), GL_STATIC_DRAW); Buffer::Specialized elementBuffer(elements, indexCount * sizeof(Element), GL_STATIC_DRAW); delete[] vertices; delete[] elements; Mesh::Buffer buffers[2] = { { .buffer = vertexBuffer, .attributes = VERTEX_ATTRIBUTES, .attributeCount = sizeof(VERTEX_ATTRIBUTES)/sizeof(Mesh::Attribute) }, { .buffer = elementBuffer } }; return Mesh::InstancedElements(buffers, 2, indexCount, 1, GL_UNSIGNED_INT); } #include std::string readExternalFile(const char* name) { std::string contents; std::ifstream file; file.open(name, std::fstream::in); if (!file.is_open()) std::cerr << "Failed to load file " << name << ": " << strerror(errno) << "\n"; std::string line; while (getline(file, line)) { contents += line; contents += "\n"; } file.close(); return std::string(contents); } void onDebugOutput(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const char* message, const void* /* userParam */) { std::cerr << "OpenGL "; switch (severity) { case GL_DEBUG_SEVERITY_HIGH: std::cerr << "high severity"; break; case GL_DEBUG_SEVERITY_MEDIUM: std::cerr << "moderately severity"; break; case GL_DEBUG_SEVERITY_LOW: std::cerr << "low severity"; break; case GL_DEBUG_SEVERITY_NOTIFICATION: std::cerr << "notification"; break; default: std::cerr << "[unknown severity " << severity << "]"; break; } std::cerr << " "; switch (type) { case GL_DEBUG_TYPE_ERROR: std::cerr << "error"; break; case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: std::cerr << "deprecation warning"; break; case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: std::cerr << "undefined behavior warning"; break; case GL_DEBUG_TYPE_PORTABILITY: std::cerr << "portability warning"; break; case GL_DEBUG_TYPE_PERFORMANCE: std::cerr << "performance warning"; break; case GL_DEBUG_TYPE_MARKER: std::cerr << "debug marker"; break; case GL_DEBUG_TYPE_PUSH_GROUP: std::cerr << "pushed group"; break; case GL_DEBUG_TYPE_POP_GROUP: std::cerr << "popped group"; break; case GL_DEBUG_TYPE_OTHER: std::cerr << "debug message"; break; default: std::cerr << "[unknown message type " << type << "]"; break; } std::cerr << " from "; switch (source) { case GL_DEBUG_SOURCE_API: std::cerr << "API"; break; case GL_DEBUG_SOURCE_WINDOW_SYSTEM: std::cerr << "window system"; break; case GL_DEBUG_SOURCE_SHADER_COMPILER: std::cerr << "shader compiler"; break; case GL_DEBUG_SOURCE_THIRD_PARTY: std::cerr << "third party"; break; case GL_DEBUG_SOURCE_APPLICATION: std::cerr << "application"; break; case GL_DEBUG_SOURCE_OTHER: std::cerr << "unknown source"; break; default: std::cerr << "[unknown source type " << source << "]"; break; } std::cerr << ": "; if (length < 0) std::cerr << message; else std::cerr << std::string(message, length); std::cerr << " (message id: " << id << ")\n"; } void onGLFWError(int errorCode, const char* error) { std::cerr << "GLFW error: " << error << " (error code: " << errorCode << ")\n"; } int main() { glfwSetErrorCallback(onGLFWError); glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, 1); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, true); glfwWindowHint(GLFW_SAMPLES, 4); glfwWindowHint(GLFW_VISIBLE, false); GLFWwindow* window = glfwCreateWindow(1, 1, "You aren't supposed to see this", NULL, NULL); glfwMakeContextCurrent(window); Mesh::InstancedElements sphere = processMesh("../meshes/sphere.obj"); Shader::Program shader; shader.add(readExternalFile("../shaders/vertex.glsl").c_str(), -1, GL_VERTEX_SHADER); shader.add(readExternalFile("../shaders/fragment.glsl").c_str(), -1, GL_FRAGMENT_SHADER); shader.link(); shader.use(); }