diff --git a/3DViewer/Header/callback.h b/3DViewer/Header/callback.h new file mode 100644 index 0000000..aa6993c --- /dev/null +++ b/3DViewer/Header/callback.h @@ -0,0 +1,102 @@ +#pragma once +#include +#include +#include +#include "setup.h" + +#define GLFW_KEY_PLUS_GER GLFW_KEY_RIGHT_BRACKET +#define GLFW_KEY_MINUS_GER GLFW_KEY_SLASH + +struct { + double posX; + double posY; + bool leftHold; + bool middleHold; + bool rightHold; + double speed = 1; +} mouse; + + +void windowResize(GLFWwindow * window, int width, int height) +{ + monitor.witdh = width; + monitor.heigh = height; + + glViewport(0, 0, width, height); +} + +void mouseButton(GLFWwindow *window, int button, int action, int mod) +{ + if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS) + { + mouse.leftHold = true; + glfwGetCursorPos(window, &mouse.posX, &mouse.posY); + } + else if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_RELEASE) + { + mouse.leftHold = false; + } + + if (button == GLFW_MOUSE_BUTTON_RIGHT && action == GLFW_PRESS) + { + mouse.rightHold = true; + glfwGetCursorPos(window, &mouse.posX, &mouse.posY); + } + else if (button == GLFW_MOUSE_BUTTON_RIGHT && action == GLFW_RELEASE) + { + mouse.rightHold = false; + } +} + +void mouseMove(GLFWwindow *window, double xpos, double ypos) +{ + if (mouse.leftHold) + { + monitor.rotX += static_cast((ypos - mouse.posY) * 0.01 * mouse.speed); + monitor.rotY += static_cast((xpos - mouse.posX) * 0.01 * mouse.speed); + + mouse.posX = xpos; + mouse.posY = ypos; + } + + if (mouse.rightHold) + { + monitor.transX -= (xpos - mouse.posX) * 0.01 * mouse.speed; + monitor.transY += (ypos - mouse.posY) * 0.01 * mouse.speed; + + mouse.posX = xpos; + mouse.posY = ypos; + } +} + +void mouseWheel(GLFWwindow *window, double xoffset, double yoffset) +{ + monitor.transZ -= yoffset * 0.5 * mouse.speed; +} + +void keyPress(GLFWwindow *window, int key, int scancode, int action, int mods) +{ + if (action == GLFW_PRESS || action == GLFW_REPEAT) + { + switch (key) + { + case GLFW_KEY_ESCAPE: + glfwSetWindowShouldClose(window, GLFW_TRUE); + break; + case GLFW_KEY_MINUS_GER: case GLFW_KEY_KP_SUBTRACT: + mouse.speed -= 0.1; + if (mouse.speed < 0.1) + mouse.speed = 0; + break; + case GLFW_KEY_PLUS_GER: case GLFW_KEY_KP_ADD: + mouse.speed += 0.1; + break; + case GLFW_KEY_A: + std::cout << mouse.speed << std::endl; + break; + default: + std::cout << key << " " << scancode << std::endl; + break; + } + } +} diff --git a/3DViewer/Header/import.h b/3DViewer/Header/import.h new file mode 100644 index 0000000..470b7e6 --- /dev/null +++ b/3DViewer/Header/import.h @@ -0,0 +1,137 @@ +#pragma once +#include +#include +#include +#include + +std::vector loadData() +{ + return std::vector( + { + -1.0f, -1.0f, -1.0f, + -1.0f, -1.0f, 1.0f, + -1.0f, 1.0f, 1.0f, + 1.0f, 1.0f, -1.0f, + -1.0f, -1.0f, -1.0f, + -1.0f, 1.0f, -1.0f, + 1.0f, -1.0f, 1.0f, + -1.0f, -1.0f, -1.0f, + 1.0f, -1.0f, -1.0f, + 1.0f, 1.0f, -1.0f, + 1.0f, -1.0f, -1.0f, + -1.0f, -1.0f, -1.0f, + -1.0f, -1.0f, -1.0f, + -1.0f, 1.0f, 1.0f, + -1.0f, 1.0f, -1.0f, + 1.0f, -1.0f, 1.0f, + -1.0f, -1.0f, 1.0f, + -1.0f, -1.0f, -1.0f, + -1.0f, 1.0f, 1.0f, + -1.0f, -1.0f, 1.0f, + 1.0f, -1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, + 1.0f, -1.0f, -1.0f, + 1.0f, 1.0f, -1.0f, + 1.0f, -1.0f, -1.0f, + 1.0f, 1.0f, 1.0f, + 1.0f, -1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, + 1.0f, 1.0f, -1.0f, + -1.0f, 1.0f, -1.0f, + 1.0f, 1.0f, 1.0f, + -1.0f, 1.0f, -1.0f, + -1.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, + -1.0f, 1.0f, 1.0f, + 1.0f, -1.0f, 1.0f + } + ); +} + +std::vector loadColor() +{ + return std::vector( + { + 0.583f, 0.771f, 0.014f, + 0.609f, 0.115f, 0.436f, + 0.327f, 0.483f, 0.844f, + 0.822f, 0.569f, 0.201f, + 0.435f, 0.602f, 0.223f, + 0.310f, 0.747f, 0.185f, + 0.597f, 0.770f, 0.761f, + 0.559f, 0.436f, 0.730f, + 0.359f, 0.583f, 0.152f, + 0.483f, 0.596f, 0.789f, + 0.559f, 0.861f, 0.639f, + 0.195f, 0.548f, 0.859f, + 0.014f, 0.184f, 0.576f, + 0.771f, 0.328f, 0.970f, + 0.406f, 0.615f, 0.116f, + 0.676f, 0.977f, 0.133f, + 0.971f, 0.572f, 0.833f, + 0.140f, 0.616f, 0.489f, + 0.997f, 0.513f, 0.064f, + 0.945f, 0.719f, 0.592f, + 0.543f, 0.021f, 0.978f, + 0.279f, 0.317f, 0.505f, + 0.167f, 0.620f, 0.077f, + 0.347f, 0.857f, 0.137f, + 0.055f, 0.953f, 0.042f, + 0.714f, 0.505f, 0.345f, + 0.783f, 0.290f, 0.734f, + 0.722f, 0.645f, 0.174f, + 0.302f, 0.455f, 0.848f, + 0.225f, 0.587f, 0.040f, + 0.517f, 0.713f, 0.338f, + 0.053f, 0.959f, 0.120f, + 0.393f, 0.621f, 0.362f, + 0.673f, 0.211f, 0.457f, + 0.820f, 0.883f, 0.371f, + 0.982f, 0.099f, 0.879f + } + ); +} + +std::vector loadUV() +{ + return std::vector( + { + 0.000059f, 1.0f - 0.000004f, + 0.000103f, 1.0f - 0.336048f, + 0.335973f, 1.0f - 0.335903f, + 1.000023f, 1.0f - 0.000013f, + 0.667979f, 1.0f - 0.335851f, + 0.999958f, 1.0f - 0.336064f, + 0.667979f, 1.0f - 0.335851f, + 0.336024f, 1.0f - 0.671877f, + 0.667969f, 1.0f - 0.671889f, + 1.000023f, 1.0f - 0.000013f, + 0.668104f, 1.0f - 0.000013f, + 0.667979f, 1.0f - 0.335851f, + 0.000059f, 1.0f - 0.000004f, + 0.335973f, 1.0f - 0.335903f, + 0.336098f, 1.0f - 0.000071f, + 0.667979f, 1.0f - 0.335851f, + 0.335973f, 1.0f - 0.335903f, + 0.336024f, 1.0f - 0.671877f, + 1.000004f, 1.0f - 0.671847f, + 0.999958f, 1.0f - 0.336064f, + 0.667979f, 1.0f - 0.335851f, + 0.668104f, 1.0f - 0.000013f, + 0.335973f, 1.0f - 0.335903f, + 0.667979f, 1.0f - 0.335851f, + 0.335973f, 1.0f - 0.335903f, + 0.668104f, 1.0f - 0.000013f, + 0.336098f, 1.0f - 0.000071f, + 0.000103f, 1.0f - 0.336048f, + 0.000004f, 1.0f - 0.671870f, + 0.336024f, 1.0f - 0.671877f, + 0.000103f, 1.0f - 0.336048f, + 0.336024f, 1.0f - 0.671877f, + 0.335973f, 1.0f - 0.335903f, + 0.667969f, 1.0f - 0.671889f, + 1.000004f, 1.0f - 0.671847f, + 0.667979f, 1.0f - 0.335851f + } + ); +} diff --git a/3DViewer/Header/setup.h b/3DViewer/Header/setup.h new file mode 100644 index 0000000..b706ea7 --- /dev/null +++ b/3DViewer/Header/setup.h @@ -0,0 +1,162 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include "shader.h" +#include "import.h" +#include "texture.h" + +#define OGL_MAJOR_VERSION 4 +#define OGL_MINOR_VERSION 5 +#define AA_VALUE 4 +#define MAINWINDOW_NAME "MeshViewer 2.0 pre-alpha" +#define VERTEX_SHADER "Shader/VertexTextureShader.mv2shdr" +#define FRAGMENT_SHADER "Shader/FragmentTextureShader.mv2shdr" +#define TEXTURE_NAME "Textures/dice.tga" + + +struct oglVariables { + GLFWwindow* window; // window + GLuint vertexArrayID; // vertex array + GLuint vertexBufferID; // vertex buffer + GLuint colorBufferID; // color buffer + GLuint samplerID; // sampler handler + GLuint uvBufferID; // uv buffer + GLuint shaderPrgmID; // shader + struct { + GLuint id; // matrix ID + glm::mat4 projection; // projection + glm::mat4 view; // view + glm::mat4 model; // model + glm::mat4 mvp; // mvp + } matrix; + struct { + std::vector data; // obj data + std::vector color; // obj color + std::vector uv; // obj uv + GLuint textureID; // texture data + } object; +}; + +struct { + float fov = 45.f; + float minView = 0.1f; + float maxView = 100.0f; + int witdh = 640; + int heigh = 480; + float rotX = 0; + float rotY = 0; + float rotZ = 0; + double transX = 0.0; + double transY = 0.0; + double transZ = 5.0; +} monitor; + +void setupGLFW() +{ + if (!glfwInit()) + { + MessageBox(NULL, "Failed to initialize GLFW", "MeshViewer 2.0 Error", MB_OK | MB_ICONERROR); + exit(0); + } + + glfwWindowHint(GLFW_SAMPLES, AA_VALUE); // antialiasing level + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, OGL_MAJOR_VERSION); // OpenGL major version number + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, OGL_MINOR_VERSION); // OpenGL minor verison number + glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // something we need for new OGL +} + +GLFWwindow* createWindow() +{ + GLFWwindow* window = glfwCreateWindow(monitor.witdh, monitor.heigh, MAINWINDOW_NAME, NULL, NULL); + + if (window == NULL) + { + char tempMajor[10], tempMinor[10]; + _itoa_s(OGL_MAJOR_VERSION, tempMajor, 10, 10); + _itoa_s(OGL_MINOR_VERSION, tempMinor, 10, 10); + + MessageBox(NULL, + (std::string("Your GPU does not support OpenGL ") += std::string(tempMajor) += std::string(".") += std::string(tempMinor)).c_str(), + "MeshViewer 2.0 Error", MB_OK | MB_ICONERROR); + + glfwTerminate(); + exit(0); + } + + glfwMakeContextCurrent(window); + + return window; +} + +void setupGLEW() +{ + glewExperimental = true; + + if (glewInit() != GLEW_OK) + { + MessageBox(NULL, "Failed to initialize GLEW!", "MeshViewer 2.0 Error", MB_OK | MB_ICONERROR); + glfwTerminate(); + exit(0); + } +} + +void calcMatrices(oglVariables &scene) +{ + scene.matrix.projection = glm::perspective(monitor.fov, float(monitor.witdh) / float(monitor.heigh), monitor.minView, monitor.maxView); + scene.matrix.view = glm::lookAt( + glm::vec3(monitor.transX, monitor.transY, monitor.transZ), + glm::vec3(monitor.transX, monitor.transY, monitor.transZ - 1), + glm::vec3(0, 1, 0) + ); + scene.matrix.model = glm::mat4(1.0f); + scene.matrix.model = glm::rotate(scene.matrix.model, monitor.rotX, glm::vec3(1, 0, 0)); + scene.matrix.model = glm::rotate(scene.matrix.model, monitor.rotY, glm::vec3(0, 1, 0)); + scene.matrix.model = glm::rotate(scene.matrix.model, monitor.rotZ, glm::vec3(0, 0, 1)); + + scene.matrix.mvp = scene.matrix.projection * scene.matrix.view * scene.matrix.model; +} + +void initVariables(oglVariables &temp) +{ + glGenVertexArrays(1, &(temp.vertexArrayID)); + glGenBuffers(1, &temp.vertexBufferID); + glGenBuffers(1, &temp.colorBufferID); + glGenBuffers(1, &temp.uvBufferID); + temp.shaderPrgmID = LoadShaders(VERTEX_SHADER, FRAGMENT_SHADER); + + temp.matrix.id = glGetUniformLocation(temp.shaderPrgmID, "MVP"); + calcMatrices(temp); + + temp.samplerID = glGetUniformLocation(temp.shaderPrgmID, "textureSampler"); + + temp.object.data = loadData(); + temp.object.color = loadColor(); + temp.object.uv = loadUV(); + + glGenTextures(1, &temp.object.textureID); + glBindTexture(GL_TEXTURE_2D, temp.object.textureID); + TextureTGA tempTex(TEXTURE_NAME); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tempTex.getWidth(), tempTex.getHeight(), 0, GL_BGR, GL_UNSIGNED_BYTE, tempTex.getData().data()); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glGenerateMipmap(GL_TEXTURE_2D); + +} + +void cleanUp(oglVariables &scene) +{ + glDeleteBuffers(1, &scene.uvBufferID); + glDeleteBuffers(1, &scene.colorBufferID); + glDeleteBuffers(1, &scene.vertexBufferID); + glDeleteVertexArrays(1, &scene.vertexArrayID); + glDeleteProgram(scene.shaderPrgmID); + glDeleteTextures(1, &scene.samplerID); + glfwTerminate(); +} diff --git a/3DViewer/Header/shader.h b/3DViewer/Header/shader.h new file mode 100644 index 0000000..cebdac9 --- /dev/null +++ b/3DViewer/Header/shader.h @@ -0,0 +1,4 @@ +#pragma once +#include + +GLuint LoadShaders(const char * vertex_file_path, const char * fragment_file_path); \ No newline at end of file diff --git a/3DViewer/Header/texture.h b/3DViewer/Header/texture.h new file mode 100644 index 0000000..ad193d1 --- /dev/null +++ b/3DViewer/Header/texture.h @@ -0,0 +1,31 @@ +#pragma once +#include + + +class TextureTGA +{ +public: + TextureTGA(const char* filePath); + ~TextureTGA(); + +private: + std::vector vui8Pixels; + bool bCompressed; + std::uint32_t ui32IDLength; + bool bColorTabel; + std::uint32_t ui32PicType; + std::uint32_t ui32PaletteBegin; + std::uint32_t ui32PaletteLength; + std::uint32_t ui32PaletteBpP; + std::uint32_t ui32Width; + std::uint32_t ui32Height; + std::uint32_t ui32Size; + std::uint32_t ui32BpP; + std::uint32_t ui32Attribut; + +public: + std::vector getData() const; + bool hasAlpha() const; + std::uint32_t getWidth() const; + std::uint32_t getHeight() const; +}; diff --git a/3DViewer/Header/tga.h b/3DViewer/Header/tga.h new file mode 100644 index 0000000..becc82e --- /dev/null +++ b/3DViewer/Header/tga.h @@ -0,0 +1,135 @@ +#pragma once +#include +#include +#include +#include + +typedef union PixelInfo +{ + std::uint32_t Colour; + struct + { + std::uint8_t B, G, R, A; + }; +} *PPixelInfo; + +class Tga +{ +private: + std::vector Pixels; + bool ImageCompressed; + std::uint32_t width, height, size, BitsPerPixel; + +public: + Tga(const char* FilePath); + std::vector GetPixels() { return this->Pixels; } + std::uint32_t GetWidth() const { return this->width; } + std::uint32_t GetHeight() const { return this->height; } + bool HasAlphaChannel() { return BitsPerPixel == 32; } +}; + +Tga::Tga(const char* FilePath) +{ + std::fstream hFile(FilePath, std::ios::in | std::ios::binary); + if (!hFile.is_open()) { throw std::invalid_argument("File Not Found."); } + + std::uint8_t Header[18] = { 0 }; + std::vector ImageData; + static std::uint8_t DeCompressed[12] = { 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }; + static std::uint8_t IsCompressed[12] = { 0x0, 0x0, 0xA, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }; + + hFile.read(reinterpret_cast(&Header), sizeof(Header)); + + if (!std::memcmp(DeCompressed, &Header, sizeof(DeCompressed))) + { + BitsPerPixel = Header[16]; + width = Header[13] * 0xFF + Header[12]; + height = Header[15] * 0xFF + Header[14]; + size = ((width * BitsPerPixel + 31) / 32) * 4 * height; + + if ((BitsPerPixel != 24) && (BitsPerPixel != 32)) + { + hFile.close(); + throw std::invalid_argument("Invalid File Format. Required: 24 or 32 Bit Image."); + } + + ImageData.resize(size); + ImageCompressed = false; + hFile.read(reinterpret_cast(ImageData.data()), size); + } + else if (!std::memcmp(IsCompressed, &Header, sizeof(IsCompressed))) + { + BitsPerPixel = Header[16]; + width = Header[13] * 0xFF + Header[12]; + height = Header[15] * 0xFF + Header[14]; + size = ((width * BitsPerPixel + 31) / 32) * 4 * height; + + if ((BitsPerPixel != 24) && (BitsPerPixel != 32)) + { + hFile.close(); + throw std::invalid_argument("Invalid File Format. Required: 24 or 32 Bit Image."); + } + + PixelInfo Pixel = { 0 }; + int CurrentByte = 0; + std::size_t CurrentPixel = 0; + ImageCompressed = true; + std::uint8_t ChunkHeader = { 0 }; + int BytesPerPixel = (BitsPerPixel / 8); + ImageData.resize(width * height * sizeof(PixelInfo)); + + do + { + hFile.read(reinterpret_cast(&ChunkHeader), sizeof(ChunkHeader)); + + if (ChunkHeader < 128) + { + ++ChunkHeader; + for (int I = 0; I < ChunkHeader; ++I, ++CurrentPixel) + { + hFile.read(reinterpret_cast(&Pixel), BytesPerPixel); + + ImageData[CurrentByte++] = Pixel.B; + ImageData[CurrentByte++] = Pixel.G; + ImageData[CurrentByte++] = Pixel.R; + if (BitsPerPixel > 24) ImageData[CurrentByte++] = Pixel.A; + } + } + else + { + ChunkHeader -= 127; + hFile.read(reinterpret_cast(&Pixel), BytesPerPixel); + + for (int I = 0; I < ChunkHeader; ++I, ++CurrentPixel) + { + ImageData[CurrentByte++] = Pixel.B; + ImageData[CurrentByte++] = Pixel.G; + ImageData[CurrentByte++] = Pixel.R; + if (BitsPerPixel > 24) ImageData[CurrentByte++] = Pixel.A; + } + } + } while (CurrentPixel < (width * height)); + } + else + { + hFile.close(); + throw std::invalid_argument("Invalid File Format. Required: 24 or 32 Bit TGA File."); + } + + //fix color mix + std::uint8_t temp; + unsigned int it = 0; + while (1) + { + temp = ImageData[it]; + ImageData[it] = ImageData[it + 2]; + ImageData[it + 2] = temp; + BitsPerPixel == 32 ? it += 2 : it += 3; + + if (it + 2 >= size) + break; + } + + hFile.close(); + this->Pixels = ImageData; +} diff --git a/3DViewer/Shader/FragmentColorShader.mv2shdr b/3DViewer/Shader/FragmentColorShader.mv2shdr new file mode 100644 index 0000000..5f13d27 --- /dev/null +++ b/3DViewer/Shader/FragmentColorShader.mv2shdr @@ -0,0 +1,12 @@ +#version 450 core + +// Input +in vec3 fragmentColor; + +// Ouput data +out vec3 color; + +void main() +{ + color = fragmentColor; +} \ No newline at end of file diff --git a/3DViewer/Shader/FragmentTextureShader.mv2shdr b/3DViewer/Shader/FragmentTextureShader.mv2shdr new file mode 100644 index 0000000..2ed0112 --- /dev/null +++ b/3DViewer/Shader/FragmentTextureShader.mv2shdr @@ -0,0 +1,14 @@ +#version 450 core + +// Input +in vec2 UV; + +// Ouput data +out vec3 color; + +uniform sampler2D textureSampler; + +void main() +{ + color = texture(textureSampler, UV).rgb; +} \ No newline at end of file diff --git a/3DViewer/Shader/VertexColorShader.mv2shdr b/3DViewer/Shader/VertexColorShader.mv2shdr new file mode 100644 index 0000000..e07d841 --- /dev/null +++ b/3DViewer/Shader/VertexColorShader.mv2shdr @@ -0,0 +1,20 @@ +#version 450 core + +// Input vertex data, different for all executions of this shader. +layout(location = 0) in vec3 vertexPosition_modelspace; +layout(location = 1) in vec3 vertexColor; + +// Output +out vec3 fragmentColor; + +// Values that stay constant for the whole mesh. +uniform mat4 MVP; + +void main(){ + + // Output position of the vertex, in clip space : MVP * position + gl_Position = MVP * vec4(vertexPosition_modelspace,1); + + fragmentColor = vertexColor; + +} diff --git a/3DViewer/Shader/VertexTextureShader.mv2shdr b/3DViewer/Shader/VertexTextureShader.mv2shdr new file mode 100644 index 0000000..5776ae8 --- /dev/null +++ b/3DViewer/Shader/VertexTextureShader.mv2shdr @@ -0,0 +1,20 @@ +#version 450 core + +// Input vertex data, different for all executions of this shader. +layout(location = 0) in vec3 vertexPosition_modelspace; +layout(location = 1) in vec2 vertexUV; + +// Output +out vec2 UV; + +// Values that stay constant for the whole mesh. +uniform mat4 MVP; + +void main(){ + + // Output position of the vertex, in clip space : MVP * position + gl_Position = MVP * vec4(vertexPosition_modelspace,1); + + UV = vertexUV; + +} diff --git a/3DViewer/Source/shader.cpp b/3DViewer/Source/shader.cpp new file mode 100644 index 0000000..37df2f5 --- /dev/null +++ b/3DViewer/Source/shader.cpp @@ -0,0 +1,111 @@ +#include +#include +#include +#include +#include +#include +using namespace std; + +#include +#include + +#include + +#include "shader.h" + +GLuint LoadShaders(const char * vertex_file_path, const char * fragment_file_path) { + + // Create the shaders + GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER); + GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER); + + // Read the Vertex Shader code from the file + std::string VertexShaderCode; + std::ifstream VertexShaderStream(vertex_file_path, std::ios::in); + if (VertexShaderStream.is_open()) { + std::string Line = ""; + while (getline(VertexShaderStream, Line)) + VertexShaderCode += "\n" + Line; + VertexShaderStream.close(); + } + else { + printf("Impossible to open %s. Are you in the right directory ? Don't forget to read the FAQ !\n", vertex_file_path); + getchar(); + return 0; + } + + // Read the Fragment Shader code from the file + std::string FragmentShaderCode; + std::ifstream FragmentShaderStream(fragment_file_path, std::ios::in); + if (FragmentShaderStream.is_open()) { + std::string Line = ""; + while (getline(FragmentShaderStream, Line)) + FragmentShaderCode += "\n" + Line; + FragmentShaderStream.close(); + } + + GLint Result = GL_FALSE; + int InfoLogLength; + + + // Compile Vertex Shader + printf("Compiling shader : %s\n", vertex_file_path); + char const * VertexSourcePointer = VertexShaderCode.c_str(); + glShaderSource(VertexShaderID, 1, &VertexSourcePointer, NULL); + glCompileShader(VertexShaderID); + + // Check Vertex Shader + glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result); + glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength); + if (InfoLogLength > 0) { + std::vector VertexShaderErrorMessage(InfoLogLength + 1); + glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]); + printf("%s\n", &VertexShaderErrorMessage[0]); + } + + + + // Compile Fragment Shader + printf("Compiling shader : %s\n", fragment_file_path); + char const * FragmentSourcePointer = FragmentShaderCode.c_str(); + glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer, NULL); + glCompileShader(FragmentShaderID); + + // Check Fragment Shader + glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result); + glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength); + if (InfoLogLength > 0) { + std::vector FragmentShaderErrorMessage(InfoLogLength + 1); + glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]); + printf("%s\n", &FragmentShaderErrorMessage[0]); + } + + + + // Link the program + printf("Linking program\n"); + GLuint ProgramID = glCreateProgram(); + glAttachShader(ProgramID, VertexShaderID); + glAttachShader(ProgramID, FragmentShaderID); + glLinkProgram(ProgramID); + + // Check the program + glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result); + glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength); + if (InfoLogLength > 0) { + std::vector ProgramErrorMessage(InfoLogLength + 1); + glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]); + printf("%s\n", &ProgramErrorMessage[0]); + } + + + glDetachShader(ProgramID, VertexShaderID); + glDetachShader(ProgramID, FragmentShaderID); + + glDeleteShader(VertexShaderID); + glDeleteShader(FragmentShaderID); + + return ProgramID; +} + + diff --git a/3DViewer/Source/texture.cpp b/3DViewer/Source/texture.cpp new file mode 100644 index 0000000..6d9a491 --- /dev/null +++ b/3DViewer/Source/texture.cpp @@ -0,0 +1,106 @@ +#include "texture.h" +#include +#include +#include + +TextureTGA::TextureTGA(const char * filePath) +{ + // open the file + std::fstream fsPicture(filePath, std::ios::in | std::ios::binary); + + if (!fsPicture.is_open()) + throw std::invalid_argument(std::string("file not found: ") += filePath); + + // read in the header + std::uint8_t ui8x18Header[18] = { 0 }; + fsPicture.read(reinterpret_cast(&ui8x18Header), sizeof(ui8x18Header)); + + // extract all information from header + ui32IDLength = ui8x18Header[0]; + bColorTabel = ui8x18Header[1] == 1; + ui32PicType = ui8x18Header[2]; + ui32PaletteBegin = ui8x18Header[4] * 0x100 + ui8x18Header[3]; + ui32PaletteLength = ui8x18Header[6] * 0x100 + ui8x18Header[5]; + ui32PaletteBpP = ui8x18Header[7]; + ui32Width = ui8x18Header[13] * 0x100 + ui8x18Header[12]; + ui32Height = ui8x18Header[15] * 0x100 + ui8x18Header[14]; + ui32BpP = ui8x18Header[16]; + ui32Attribut = ui8x18Header[17]; + + // calculate some more information + ui32Size = ui32Width * ui32Height * ui32BpP/8; + bCompressed = ui32PicType == 9 || ui32PicType == 10; + vui8Pixels.resize(ui32Size); + + /* consol output of the header + std::cout << "Header\n" + << "ID länge: " << ui32IDLength << std::endl + << "Farbtabelle: " << (int)bColorTabel << std::endl + << "Bildtype: " << ui32PicType << std::endl + << "Palletenbegin: " << ui32PaletteBegin << std::endl + << "Palletenlängen: " << ui32PaletteLength << std::endl + << "Bits pro Palleteneintrag: " << ui32PaletteBpP << std::endl + << "Breite: " << ui32Width << std::endl + << "Höhe: " << ui32Height << std::endl + << "Bit pro Pixel: " << ui32BpP << std::endl + << "Bild Attribute: " << ui32Attribut << std::endl;*/ + + // jump to the data block + fsPicture.seekg(ui32IDLength + ui32PaletteLength, std::ios_base::cur); + + // If not compressed 24 or 32 bit + if (ui32PicType == 2 && (ui32BpP == 24 || ui32BpP == 32)) + { + fsPicture.read(reinterpret_cast(vui8Pixels.data()), ui32Size); + } + // else if compressed 24 or 32 bit + else if (ui32PicType == 10 && (ui32BpP == 24 || ui32BpP == 32)) // compressed + { + throw std::invalid_argument("Invaild File Format! Don't compress the image."); + } + // not useable format + else + { + fsPicture.close(); + throw std::invalid_argument("Invaild File Format! Required 24 or 31 Bit Image."); + } + + + //fix color mix + /*std::uint8_t temp; + std::uint32_t it = 0; + + while (it + 2 < ui32Size) + { + temp = vui8Pixels[it]; + vui8Pixels[it] = vui8Pixels[it + 2]; + vui8Pixels[it + 2] = temp; + ui32BpP == 32 ? it += 4 : it += 3; + }*/ + + fsPicture.close(); +} + +TextureTGA::~TextureTGA() +{ +} + +std::vector TextureTGA::getData() const +{ + return vui8Pixels; +} + +bool TextureTGA::hasAlpha() const +{ + return ui32BpP == 32; +} + +std::uint32_t TextureTGA::getWidth() const +{ + return ui32Width; +} + +std::uint32_t TextureTGA::getHeight() const +{ + return ui32Height; +} diff --git a/3DViewer/Textures/10x10H.tga b/3DViewer/Textures/10x10H.tga new file mode 100644 index 0000000..6b897ce Binary files /dev/null and b/3DViewer/Textures/10x10H.tga differ diff --git a/3DViewer/Textures/10x10V.tga b/3DViewer/Textures/10x10V.tga new file mode 100644 index 0000000..05561ac Binary files /dev/null and b/3DViewer/Textures/10x10V.tga differ diff --git a/3DViewer/Textures/256x256H.tga b/3DViewer/Textures/256x256H.tga new file mode 100644 index 0000000..49beceb Binary files /dev/null and b/3DViewer/Textures/256x256H.tga differ diff --git a/3DViewer/Textures/4x4H16.tga b/3DViewer/Textures/4x4H16.tga new file mode 100644 index 0000000..981a422 Binary files /dev/null and b/3DViewer/Textures/4x4H16.tga differ diff --git a/3DViewer/Textures/dice.tga b/3DViewer/Textures/dice.tga new file mode 100644 index 0000000..722da4f Binary files /dev/null and b/3DViewer/Textures/dice.tga differ diff --git a/3DViewer/Textures/texture16.tga b/3DViewer/Textures/texture16.tga new file mode 100644 index 0000000..0320a47 Binary files /dev/null and b/3DViewer/Textures/texture16.tga differ diff --git a/3DViewer/Textures/texture24.tga b/3DViewer/Textures/texture24.tga new file mode 100644 index 0000000..ebdef93 Binary files /dev/null and b/3DViewer/Textures/texture24.tga differ diff --git a/3DViewer/Textures/texture24R.tga b/3DViewer/Textures/texture24R.tga new file mode 100644 index 0000000..c5d5391 Binary files /dev/null and b/3DViewer/Textures/texture24R.tga differ diff --git a/3DViewer/Textures/texture32.tga b/3DViewer/Textures/texture32.tga new file mode 100644 index 0000000..b54937f Binary files /dev/null and b/3DViewer/Textures/texture32.tga differ diff --git a/3DViewer/Textures/texture32R.tga b/3DViewer/Textures/texture32R.tga new file mode 100644 index 0000000..6b996ed Binary files /dev/null and b/3DViewer/Textures/texture32R.tga differ diff --git a/3DViewer/Textures/uvtemplate.DDS b/3DViewer/Textures/uvtemplate.DDS new file mode 100644 index 0000000..3e9afee Binary files /dev/null and b/3DViewer/Textures/uvtemplate.DDS differ diff --git a/3DViewer/Textures/uvtemplate.tga b/3DViewer/Textures/uvtemplate.tga new file mode 100644 index 0000000..4b0fac0 Binary files /dev/null and b/3DViewer/Textures/uvtemplate.tga differ diff --git a/3DViewer/main.cpp b/3DViewer/main.cpp new file mode 100644 index 0000000..412a20f --- /dev/null +++ b/3DViewer/main.cpp @@ -0,0 +1,115 @@ +#define _CRT_SECURE_NO_WARNINGS +#ifndef _DEBUG + #pragma comment( linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"" ) +#endif // DEBUG + +#include +#include + +#include "setup.h" +#include "callback.h" + +int main(int argc, char** argv) +{ + oglVariables scene; + + // init everything + setupGLFW(); + scene.window = createWindow(); + setupGLEW(); + initVariables(scene); + glBindVertexArray(scene.vertexArrayID); + + // Set callback functions + glfwSetMouseButtonCallback(scene.window, mouseButton); + glfwSetCursorPosCallback(scene.window, mouseMove); + glfwSetWindowSizeCallback(scene.window, windowResize); + glfwSetScrollCallback(scene.window, mouseWheel); + glfwSetKeyCallback(scene.window, keyPress); + + // set background color 0,5 0,8 1,0 + glClearColor(0.0000f, 0.0000f, 0.4000f, 0.0000f); + + // enable z-order + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LESS); + glEnable(GL_CULL_FACE); + + // load object to OGL + glBindBuffer(GL_ARRAY_BUFFER, scene.vertexBufferID); + glBufferData( + GL_ARRAY_BUFFER, + sizeof(scene.object.data) * scene.object.data.size(), + scene.object.data.data(), + GL_STATIC_DRAW + ); + + /*/ load color to OGL + glBindBuffer(GL_ARRAY_BUFFER, scene.colorBufferID); + glBufferData( + GL_ARRAY_BUFFER, + sizeof(scene.object.color) * scene.object.color.size(), + scene.object.color.data(), + GL_STATIC_DRAW + );*/ + + // load UV to OGL + glBindBuffer(GL_ARRAY_BUFFER, scene.uvBufferID); + glBufferData( + GL_ARRAY_BUFFER, + sizeof(scene.object.uv) * scene.object.uv.size(), + scene.object.uv.data(), + GL_STATIC_DRAW + ); + + // Main loop + do { + //processInteraction(scene.window); + calcMatrices(scene); + + // clear the scene + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + // use shader prgram + glUseProgram(scene.shaderPrgmID); + + // tell shader transformation + glUniformMatrix4fv(scene.matrix.id, 1, GL_FALSE, &scene.matrix.mvp[0][0]); + + // bind texture in texture unit 0 + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, scene.object.textureID); + // tell sampler to use texture unit 0 + glUniform1i(scene.samplerID, 0); + + // open attribute position + glEnableVertexAttribArray(0); + glBindBuffer(GL_ARRAY_BUFFER, scene.vertexBufferID); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0); + + /*/ open attribute color + glEnableVertexAttribArray(1); + glBindBuffer(GL_ARRAY_BUFFER, scene.colorBufferID); + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);*/ + + // open attribute uv + glEnableVertexAttribArray(1); + glBindBuffer(GL_ARRAY_BUFFER, scene.uvBufferID); + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0); + + // draw object + glDrawArrays(GL_TRIANGLES, 0, 3*12); + + // close attributes + glDisableVertexAttribArray(0); + glDisableVertexAttribArray(1); + + glfwSwapBuffers(scene.window); + glfwPollEvents(); + } + while (!glfwWindowShouldClose(scene.window)); + + cleanUp(scene); + + return 0; +} diff --git a/MshViewer/Source/OpenGlController.cpp b/MshViewer/Source/OpenGlController.cpp index 041a118..3371414 100644 --- a/MshViewer/Source/OpenGlController.cpp +++ b/MshViewer/Source/OpenGlController.cpp @@ -179,10 +179,6 @@ void OpenGLController::setCallbackFunctions() glfwSetKeyCallback(pWindow, keyPress); } - -///////////////////////////////////////////////////////////////////////// -// public getter - glm::mat4 OpenGLController::getMVPMatrix() { m4x4Projection = glm::perspective(fFOV, float(iWidth) / float(iHeight), fMinView, fMaxView); @@ -199,6 +195,10 @@ glm::mat4 OpenGLController::getMVPMatrix() return m4x4Projection * m4x4View * m4x4Model; } + +///////////////////////////////////////////////////////////////////////// +// public getter + GLFWwindow * OpenGLController::getWindow() const { return pWindow;