EnginPasTangible/main.c
2023-03-21 20:42:47 +01:00

393 lines
12 KiB
C

#define APPNAMEVERSION "EnginPasTangible (alpha 0.4.2)"
#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"
/* 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);
}