#define APPNAMEVERSION "EnginPasTangible (alpha 0.4.2)" #include "./Libraries/glad/glad.h" #include #include #include #include "./Libraries/GLFW/glfw3.h" #define STB_IMAGE_IMPLEMENTATION #include "./Libraries/stb/stb_image.h" #include "headers/shader.h" /* SCENE LIST shaders/default.fs shaders/immeublesparisiens.fs */ #define SCENE "shaders/default.fs" //#define SCENE "shaders/immeublesparisiens.fs" #define FULLSCREEN 0 #define EXPERIMENTAL_FEATURES 0 /* ## DEBUG MODE ## * 0 for all * 1 for nothing * 2 for FPS * 3 for cursor position * 5 for scroll level and precision * * For instance if you want fps and position set the value to 2*3=6 */ #define DEBUG_MODE 2 GLuint screenWidth = 720, screenHeight = 480; const GLFWvidmode* mode; GLFWwindow* window; bool pause; void setupVAO(); //GLuint getTextureHandle(char* path); unsigned int VAO; float currentTime, deltaTime, lastFrame,startTime; float mousePosX,mousePosY; float speedlevel=4.; float camPosX=2.5; float camPosY=0.5; float camPosZ=2.5; float speed=.04; float pan=0.; float multiplicatorFov=1.; float tilt=0.; float ez[3] = {0}; float ex[3] = {0}; float ey[3] = {0}; bool upar = false; bool downar = false; bool leftar = false; bool rightar = false; bool forwardar = false; bool backwardar = false; float fovValue=1.0; //281=3.13/2 * 180 const int maxYmouse = 281; // more precision means less speed float camPrecision = 2.; /*float[3] crossProduct(float vect_A[3], float vect_B[3]) { float cross_P[3]; cross_P[0] = vect_A[1] * vect_B[2] - vect_A[2] * vect_B[1]; cross_P[1] = vect_A[2] * vect_B[0] - vect_A[0] * vect_B[2]; cross_P[2] = vect_A[0] * vect_B[1] - vect_A[1] * vect_B[0]; return cross_P; }*/ static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) { int stateShift = glfwGetKey(window, GLFW_KEY_LEFT_SHIFT); int stateControl = glfwGetKey(window, GLFW_KEY_LEFT_CONTROL); if (stateShift == GLFW_PRESS) { speed=.08*speedlevel; multiplicatorFov=0.8; } else { speed=.02*speedlevel; multiplicatorFov=1.; } if (action == GLFW_PRESS) { if (key == GLFW_KEY_ESCAPE) { //glfwSetWindowShouldClose(window, GLFW_TRUE); pause=!pause; printf(pause ? "En pause\n" : "En fonctionnement\n"); if (pause) { glfwSetWindowTitle(window, "EnginPasTangible (En pause)"); glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL); } else { glfwSetWindowTitle(window, APPNAMEVERSION); glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); } } if (key == GLFW_KEY_BACKSPACE) glfwSetWindowShouldClose(window, GLFW_TRUE); if (key == GLFW_KEY_SPACE) upar = true; if (key == GLFW_KEY_LEFT_CONTROL) downar = true; if (key == GLFW_KEY_UP || key == GLFW_KEY_W) { forwardar = true; } if (key == GLFW_KEY_DOWN || key == GLFW_KEY_S ) { backwardar = true; } if (key == GLFW_KEY_RIGHT || key == GLFW_KEY_D) { rightar = true; } if (key == GLFW_KEY_LEFT || key == GLFW_KEY_A ) { leftar = true; } } else if (action == GLFW_RELEASE) { if (key == GLFW_KEY_SPACE) upar = false; if (key == GLFW_KEY_LEFT_CONTROL) downar = false; if (key == GLFW_KEY_UP || key == GLFW_KEY_W) { forwardar = false; } if (key == GLFW_KEY_DOWN || key == GLFW_KEY_S ) { backwardar = false; } if (key == GLFW_KEY_RIGHT || key == GLFW_KEY_D) { rightar = false; } if (key == GLFW_KEY_LEFT || key == GLFW_KEY_A ) { leftar = false; } } } void scroll_callback(GLFWwindow* window, double xoffset, double yoffset) { int stateControl = glfwGetKey(window, GLFW_KEY_LEFT_CONTROL); // we only use yoffset as it is present on normal mice if (DEBUG_MODE % 5 == 0) { printf("scroll value : %f | precision : %f | ",yoffset, camPrecision); printf((stateControl == GLFW_PRESS) ? "ctrl -> speed" : "Zooming"); printf("\n"); } if (stateControl == GLFW_PRESS) { camPrecision += yoffset/2; if (camPrecision <= 1) camPrecision=1; } else { fovValue += yoffset/5; if (fovValue <= 0.2 && EXPERIMENTAL_FEATURES == 0) fovValue=0.2; } } static void cursor_position_callback(GLFWwindow* window, double xpos, double ypos) { /* //if (xpos>283){ //////283=3.14/2 * 180 // //xpos=283 //} //if (xpos<-283){ // //xpos=-283 //}*/ int maxYcorrected = maxYmouse*camPrecision; if (ypos>maxYcorrected){ glfwSetCursorPos(window, xpos, maxYcorrected); } if (ypos<-maxYcorrected){ glfwSetCursorPos(window, xpos, -maxYcorrected); } if (DEBUG_MODE % 3 == 0) printf("x:%f | y:%f\n",xpos, ypos); mousePosX = xpos/camPrecision; mousePosY = ypos/camPrecision; } int main (){ // Window setup GLint glfwStatus = glfwInit(); //glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); //glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); //glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); //glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); //// glfwWindowHint(GLFW_SAMPLES, 4); glfwWindowHint(GLFW_RESIZABLE,GL_FALSE);//##### //glfwWindowHint(GLFW_DECORATED,GL_FALSE); //glfwWindowHint(GLFW_CONTEXT_NO_ERROR,GL_FALSE); pause = false; window = glfwCreateWindow(screenWidth, screenHeight, APPNAMEVERSION, NULL, NULL); if (window == NULL) { printf("Window failed to create"); glfwTerminate(); } glfwMakeContextCurrent(window); //glfwSwapInterval(1); // To my knowledge, this turns on vsync on macOS // If Windows or Linux: load all OpenGL function pointers with GLAD if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) { printf("Failed to initialize GLAD"); return -1; } // END Window setup // set up Vertex Array Object that contains our vertices and bind it setupVAO(); glBindVertexArray(VAO); // seeing as we only have a single VAO there's no need to unbind in the setupVertexArray function and then bind here, but we'll do so for clarity, organization, and avoiding possible bugs in future GLuint quad_shader = glCreateProgram(); int compilerInfo=buildShaders(quad_shader, "shaders/generic.vs", SCENE); if(compilerInfo>0){ return compilerInfo; } glUseProgram(quad_shader); //GLuint channel_logo = getTextureHandle("assets/logo.png"); //glBindTexture(GL_TEXTURE_2D, channel_logo); // for alpha (opacity) //glEnable (GL_BLEND); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glfwSetKeyCallback(window, key_callback); glfwSetCursorPosCallback(window, cursor_position_callback); glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); glfwSetScrollCallback(window, scroll_callback); GLFWimage images[1]; images[0].pixels = stbi_load("./assets/icon.png", &images[0].width, &images[0].height, 0, 4); //rgba channels glfwSetWindowIcon(window, 1, images); stbi_image_free(images[0].pixels); int window_width, window_height; char FPS[20]; startTime = glfwGetTime(); while (!glfwWindowShouldClose(window)) { // glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.) // ------------------------------------------------------------------------------- glfwSwapBuffers(window); glfwPollEvents(); if (pause) { glClearColor(.1f, .2f, 0.3f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); continue; } pan=-mousePosX/180.; tilt=-mousePosY/180.; //ez ez[0] = cos(tilt)*sin(pan); ez[1] = sin(tilt); ez[2] = cos(tilt)*cos(pan);//normalize(lookingAt-posCam);////base orthonormée //ex ex[0] = -ez[2];//crossProduct(ez,{0.,1.,0.}); ex[2] = ez[0]; // ey ey[0] = ex[1] * ez[2] - ex[2] * ez[1]; ey[1] = ex[2] * ez[0] - ex[0] * ez[2]; ey[2] = ex[0] * ez[1] - ex[1] * ez[0]; //crossProduct(ex,ez); if (upar) camPosY += speed; if (downar) camPosY -= speed; if (forwardar) { camPosX += speed*ez[0]; camPosY += speed*ez[1]; camPosZ += speed*ez[2]; } if (backwardar) { camPosX -= speed*ez[0]; camPosY -= speed*ez[1]; camPosZ -= speed*ez[2]; } if (rightar) { camPosX += speed*ex[0]; camPosY += speed*ex[1]; camPosZ += speed*ex[2]; } if (leftar) { camPosX -= speed*ex[0]; camPosY -= speed*ex[1]; camPosZ -= speed*ex[2]; } currentTime = glfwGetTime(); deltaTime = currentTime - lastFrame; lastFrame = currentTime; gcvt(1/deltaTime,4,FPS); if (DEBUG_MODE % 2 == 0) printf("FPS : %s\n",FPS); glfwGetWindowSize(window, &window_width, &window_height); glViewport(0, 0, window_width, window_height); // printf("%d\n", window_width); glClearColor(0.9f, 0.9f, 0.2f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); //glDrawArrays(GL_TRIANGLES, 0, 6); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); glUniform1f(glGetUniformLocation(quad_shader, "iTime"), currentTime-startTime); glUniform3f(glGetUniformLocation(quad_shader, "iEx"), ex[0],ex[1],ex[2]); glUniform3f(glGetUniformLocation(quad_shader, "iEy"), ey[0],ey[1],ey[2]); glUniform3f(glGetUniformLocation(quad_shader, "iEz"), ez[0],ez[1],ez[2]); glUniform3f(glGetUniformLocation(quad_shader, "iCamPos"), camPosX,camPosY,camPosZ); glUniform1f(glGetUniformLocation(quad_shader, "iFovValue"), fovValue*fovValue*multiplicatorFov); // glBindVertexArray(0); // no need to unbind it every time } // Optional cleaning up bc OS will likely do it for us, but is a good practice. Note that shaders are deleted in shader.h glDeleteProgram(quad_shader); // glfw: terminate, clearing all previously allocated GLFW resources. glfwTerminate(); return 0; } void setupVAO(){ // set up vertex data (and buffer(s)) and configure vertex attributes // ------------------------------------------------------------------ float vertices[] = { // positions // textures 1.f, 1.0f, 0.0f, 1.5f, 1.0f, // top right 1.f, -1.f, 0.0f, 1.5f, -1.0f, // bottom right/////-1 => 0. -1.f, -1.f, 0.0f, -1.5f, -1.0f, // bottom left -1.f, 1.f, 0.0f, -1.5f, 1.0f // top left }; unsigned int indices[] = { 0, 1, 3, // first Triangle 1, 2, 3 // second Triangle }; unsigned int VBO, EBO; glGenVertexArrays(1, &VAO); glGenBuffers(1, &VBO); glGenBuffers(1, &EBO); // bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s). glBindVertexArray(VAO); glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); // Position attribute glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)0); glEnableVertexAttribArray(0); // TexCoord attribute glVertexAttribPointer(2, 2, GL_FLOAT, GL_TRUE, 5 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat))); glEnableVertexAttribArray(2); // note that this is allowed, the call to glVertexAttribPointer registered VBO as the vertex attribute's bound vertex buffer object so afterwards we can safely unbind glBindBuffer(GL_ARRAY_BUFFER, 0); // remember: do NOT unbind the EBO while a VAO is active as the bound element buffer object IS stored in the VAO; keep the EBO bound. //glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); // You can unbind the VAO afterwards so other VAO calls won't accidentally modify this VAO, but this rarely happens. Modifying other // VAOs requires a call to glBindVertexArray anyways so we generally don't unbind VAOs (nor VBOs) when it's not directly necessary. glBindVertexArray(0); }