EnginPasTangible/main.c
2023-03-16 09:32:30 +01:00

326 lines
11 KiB
C

#define APPNAMEVERSION "EnginPasTangible (alpha 0.2.5)"
#include "./Libraries/glad/glad.h"
#include <stdio.h>
#include <math.h>
#include <stdbool.h>
#include "./Libraries/GLFW/glfw3.h"
#define STB_IMAGE_IMPLEMENTATION
#include "./Libraries/stb/stb_image.h"
#include "headers/shader.h"
#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 5
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,camPosX,camPosY,camPosZ;
float fovValue=1.0;
//283=3.14/2 * 180
const int maxYmouse = 283;
// 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)
{
if (!action == GLFW_PRESS)
return;
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);
}
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", "shaders/quad.fs");
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;
}
float pan=-mousePosX/180.;
float tilt=-mousePosY/180.;
float ez[3] = {cos(tilt)*sin(pan),sin(tilt),cos(tilt)*cos(pan)};//normalize(lookingAt-posCam);////base orthonormée
float ex[3] = {-ez[2],0,ez[0]};//crossProduct(ez,{0.,1.,0.});
float ey[3] = {
ex[1] * ez[2] - ex[2] * ez[1],
ex[2] * ez[0] - ex[0] * ez[2],
ex[0] * ez[1] - ex[1] * ez[0]
};//crossProduct(ex,ez);
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);
// 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);
}
/*
GLuint getTextureHandle(char* path)
{
GLuint textureHandle;
glGenTextures(1, &textureHandle);
glBindTexture(GL_TEXTURE_2D, textureHandle); // All upcoming GL_TEXTURE_2D operations now have effect on our texture object
// Set our texture parameters
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // Set texture wrapping to GL_REPEAT
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); // Set texture wrapping to GL_CLAMP_TO_BORDER
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
// Set texture filtering
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
// Load, create texture and generate mipmaps;
//
// Note: image loaders usually think of top left as being (0,0) while in OpenGL I would rather think of bottom left as being (0,0) as OpenGL does that already, so that is why I set the stb library to flip image vertically. There are other workarounds like flipping our texCoords upside down or flipping things in the vs or fs, but that would mean that we are choosing in OpenGL to work with two different coordinate systems, one upside-down from the other. I would rather choose not to do that and simply flip images when loading in. It is a matter of personal choice.
//
int width, height, nrChannels;
stbi_set_flip_vertically_on_load(1);
unsigned char *image = stbi_load(path, &width, &height, &nrChannels, 0);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);
glGenerateMipmap(GL_TEXTURE_2D);
// free memory
stbi_image_free(image);
glBindTexture(GL_TEXTURE_2D, 0); // unbind so that we can deal with other textures
return textureHandle;
}
*/