#define GL_GLEXT_PROTOTYPES
#define _USE_MATH_DEFINES
#include <uthash.h>
#if defined(_WIN32)
#if defined(__GNUC__)
#include <cpuid.h>
#elif defined(_MSC_VER)
#include <intrin.h>
#endif
//#define APIENTRY __stdcall
#include <windows.h>
#include <errno.h>
#define GLEW_STATIC
#include <GL/glew.h>
//#include "glew/glew.h"
//#include <GL/gl.h>
//#include <GLES2/gl2.h>
//#include <GLES2/gl2ext.h>
//#define GLFW_INCLUDE_ES3
#define GLFW_EXPOSE_NATIVE_WGL
#define GLFW_EXPOSE_NATIVE_WIN
#else
#include <GL/gl.h>
//#include <GL/glext.h>
#define GLFW_EXPOSE_NATIVE_X11
#define GLFW_EXPOSE_NATIVE_GLX
#endif
#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
#include <GLFW/glfw3native.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include "linmathv2.h"
#include <math.h>
#ifndef M_PI
#define M_PI 3.14159265358979323846264338327950288
#endif
#define degToRad(angleInDegrees) ((angleInDegrees) * M_PI / 180.0)
#define radToDeg(angleInRadians) ((angleInRadians) * 180.0 / M_PI)
#define MIN(a,b) (((a)<(b))?(a):(b))
#define MAX(a,b) (((a)>(b))?(a):(b))
#define CLAMP(x, upper, lower) (MIN(upper, MAX(x, lower)))
#include "custom.h"
#include "input.h"
#include "shaders.h"
#include "text.h"
#include "player.h"
#include "sky.h"
vec3 up={0,1,0};
int invertControl=1;
//int should_render=1;
// moved to camera->theta
//float theta = 0.0f; // theta phi may be swapped
//float phi = 0.0f; // theta is horizontal angle
float x_input = 0.0f;
float y_input = 0.0f;
int is_moving = 0; // forward backward
int is_turning = 0; // include strife if drag --
int is_elevating = 0;
// process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly
// ---------------------------------------------------------------------------------------------------------
float zoomDist = 3.0f; // set in custom.c InistializePlayer
float lastZoomDist = 0.0f;
bool readyZoomTog = false;
bool readyBlinkTog = false;
bool readyBlink = false;
bool readyManualSave = false;
bool readyResetPlayer = false;
bool readyPrintDetail = false;
bool shiftDown = false;
bool controlDown = false;
bool vDown = false;
float cubeScale = 0.25f;
bool readyCubeScale = false;
bool boundsTog = false; // start off
bool readyBoundsTog = false;
bool wireframeOn = false; // start off
bool readyWireframe = false;
bool gridOn = true; // start on
bool readyGrid = false;
int vsync = 1; // 1 = on, 2 = adaptive, 0 = off
bool readyVsync = false;
bool reloadShaders = false;
bool readyReloadShaders = false;
int fontIdx = 0; //
bool reloadFont = false;
bool readyReloadFont = false;
bool enableTracking = false;
bool readyTrackingTog = false;
bool readyPlayerTog = false;
bool hiddenTerrain = false;
int hiddenWater = 0;
int hiddenSky = 1; // default 1
int hiddenCloud = 1; // default 1
int readyHideTerrain = 0;
int readyHideWater = 0;
int readyHideSky = 0;
int readyHideCloud = 0;
int readyRendMode = 0;
bool readyWaterHeight = false;
bool waterHeightShow = false;
int keystrlen=30; // change below and in header as well
int printKeys() {
for(int i=0;i<keystrlen;i++) {
printf("> %s\n",keystr[i]);
}
printf("\n\n");
return 0;
}
const char *keystr[30] = { // remember change in header too
"W | ARROW_UP",
"S | ARROW_DOWN",
"A | ARROW_LEFT",
"D | ARROW_RIGHT",
"E Speed/Blink forward",
"",
"Esc | Q Quit the program",
"Space Ascend/Jump",
"LControl Descend",
"LShift Speed increase",
"V Change FOV with scroll",
"Z Toggle vsync 1-2-0",
"X Toggle first person/3rd person (same as scroll but remembers zoomDist)",
"G Toggle grid",
"B Toggle bounding boxes",
"I Toggle wireframe all",
"T Toggle tracking player",
"H Toggle player mode/free mode (fly)", // moveMode = 0 to start flying, modeMode = 1 start falling
"P Show water height map",
"L Cycle depth views",
"F Toggle fullscreen/window",
"R Reload shaders live",
"O Manual save game",
"0 Reset player position/view",
"1 Cycle cube(player) scales",
"2 Cycle fonts",
"3 Toggle Sky",
"4 Toggle Clouds",
"5 Toggle Terrain",
"6 Toggle Water"
};
void processInput(GLFWwindow *window)
{
struct Vec3 *pos = malloc(sizeof(struct Vec3));
struct Vec3 *rot = malloc(sizeof(struct Vec3));
bool updateTexts=false;
// quit
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
if (glfwGetKey(window, GLFW_KEY_Q) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
// move up down
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS ||
glfwGetKey(window, GLFW_KEY_UP) == GLFW_PRESS) {
updateTexts=true;
is_moving=1;
} else if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS ||
glfwGetKey(window, GLFW_KEY_DOWN) == GLFW_PRESS) {
updateTexts=true;
is_moving=-1;
} else if(is_moving != 0) {
is_moving = 0; // forward/backward only
}
// move left right
if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS ||
glfwGetKey(window, GLFW_KEY_LEFT) == GLFW_PRESS) {
updateTexts=true;
is_turning = 1;
}
if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS ||
glfwGetKey(window, GLFW_KEY_RIGHT) == GLFW_PRESS) {
updateTexts=true;
is_turning = -1;
}
if (glfwGetKey(window, GLFW_KEY_SPACE) == GLFW_PRESS) {
updateTexts=true;
is_elevating = 1;
} else if (glfwGetKey(window, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS) {
updateTexts=true;
is_elevating = -1;
controlDown=true;
} else if(is_elevating != 0) {
is_elevating = 0; // forward/backward only
controlDown=false;
}
if (glfwGetKey(window, GLFW_KEY_V) == GLFW_PRESS) {
vDown=true;
} else {
vDown=false;
}
// live reload shaders
if (glfwGetKey(window, GLFW_KEY_R) == GLFW_PRESS) {
if(!readyReloadShaders) {
readyReloadShaders=true;
reloadShaders=true;
}
} else {
readyReloadShaders=false;
}
if (glfwGetKey(window, GLFW_KEY_C) == GLFW_PRESS) {
if(!readyPrintDetail) {
printf("Print details;\n");
printf("Player position: {%f,%f,%f}, scale: %f, phi: %f\n",player->transform->position->x,player->transform->position->y,player->transform->position->z,cubeScale,player->phi);
printf("Camera position: {%f,%f,%f}, zoomDist: %f, theta: %f, phi: %f, xOffset: %f\n",camera->dir->forward->x,camera->dir->forward->y,camera->dir->forward->z,zoomDist,camera->theta,camera->phi,camera->xOffset);
printf("\n");
readyPrintDetail=true;
}
} else {
readyPrintDetail=false;
}
if (glfwGetKey(window, GLFW_KEY_T) == GLFW_PRESS) {
if(!readyTrackingTog) {
readyTrackingTog=true;
enableTracking=!enableTracking;
}
} else {
readyTrackingTog=false;
}
// zoom in out
if (glfwGetKey(window, GLFW_KEY_Z) == GLFW_PRESS) {
if(readyVsync) {
if(vsync == 1) { // adaptive
vsync=2;
glfwSwapInterval(-1);
} else if(vsync == 0) { // on
vsync=1;
glfwSwapInterval(1);
} else { // off
vsync=0;
glfwSwapInterval(0);
}
readyVsync=false;
}
} else {
readyVsync=true;
}
if (glfwGetKey(window, GLFW_KEY_X) == GLFW_PRESS) {
if(readyZoomTog) {
if(zoomDist<1.0f) {
zoomDist = lastZoomDist;
} else {
zoomDist = 0.01f;
}
readyZoomTog = false;
}
} else if(!readyZoomTog) {
readyZoomTog=true;
}
if (glfwGetKey(window, GLFW_KEY_H) == GLFW_PRESS) {
if(readyPlayerTog) {
if(moveMode==0) { // moveMode in player.c
moveMode=1;
} else {
moveMode=0;
}
readyPlayerTog=false;
}
} else if(!readyPlayerTog) {
readyPlayerTog=true;
}
if (glfwGetKey(window, GLFW_KEY_B) == GLFW_PRESS) {
if(readyBoundsTog) {
boundsTog = !boundsTog;
readyBoundsTog = false;
}
} else if(!readyBoundsTog) {
readyBoundsTog=true;
}
if (glfwGetKey(window, GLFW_KEY_I) == GLFW_PRESS) {
if(readyWireframe) {
wireframeOn = !wireframeOn;
readyWireframe = false;
}
} else if(!readyWireframe) {
readyWireframe=true;
}
if (glfwGetKey(window, GLFW_KEY_O) == GLFW_PRESS) {
if(readyManualSave) {
saveGame();
//saveCount=saveTime;
float hhT = totalTime / 60 / 60;
hh = floor(hhT);
hhT -= hh;
float mmT = hhT * 60;
mm = floor(mmT);
mmT -= mm;
ss = mmT * 60;
printf("[Manual] Game saved. (Game local time=%d:%02d:%02d\n",hh,mm,ss);
readyManualSave = false;
}
} else if(!readyManualSave) {
readyManualSave=true;
}
if (glfwGetKey(window, GLFW_KEY_E) == GLFW_PRESS) {
if(readyBlinkTog) {
readyBlink = true;
readyBlinkTog = false;
}
} else if(!readyBlinkTog) {
readyBlinkTog=true;
}
if (glfwGetKey(window, GLFW_KEY_L) == GLFW_PRESS) {
if(readyRendMode) {
rendMode++;
if(rendMode>4) rendMode = 0;
readyRendMode = false;
}
} else if(!readyRendMode) {
readyRendMode=true;
}
if (glfwGetKey(window, GLFW_KEY_P) == GLFW_PRESS) {
if(readyWaterHeight) {
waterHeightShow = !waterHeightShow;
readyWaterHeight = false;
}
} else if(!readyWaterHeight) {
readyWaterHeight=true;
}
if (glfwGetKey(window, GLFW_KEY_G) == GLFW_PRESS) {
if(readyGrid) {
gridOn = !gridOn;
readyGrid = false;
}
} else if(!readyGrid) {
readyGrid=true;
}
if (glfwGetKey(window, GLFW_KEY_0) == GLFW_PRESS) {
if(!readyResetPlayer) {
readyResetPlayer=true;
moveMode = 0; // free
gridOn = 1;
cubeScale = 0.25f;
fontIdx = 0;
wireframeOn = false;
boundsTog = false;
enableTracking = false;
vsync = 1;
rendMode = 0;
waterHeightShow = false;
FOV = 120;
fovrad=degToRad(FOV);
InitializePlayer();
}
} else if(readyResetPlayer) {
readyResetPlayer=false;
}
if (glfwGetKey(window, GLFW_KEY_1) == GLFW_PRESS) {
if(readyCubeScale) {
if(cubeScale==5.0f) {
cubeScale = 0.0f;
} else if(cubeScale==0.0f) {
cubeScale = 0.25f;
} else if(cubeScale==3.0f) {
cubeScale = 5.0f;
} else if(cubeScale==2.0f) {
cubeScale = 3.0f;
} else if(cubeScale==1.0f) {
cubeScale = 2.0f;
} else if(cubeScale==0.5f) {
cubeScale = 1.0f;
} else if(cubeScale==0.25f) {
cubeScale = 0.5f;
}
readyCubeScale = false;
}
} else if(!readyCubeScale) {
readyCubeScale=true;
}
// live font reload
if (glfwGetKey(window, GLFW_KEY_2) == GLFW_PRESS) {
if(!readyReloadFont) {
readyReloadFont=true;
if(fontIdx==0) {
fontIdx=1;
} else if(fontIdx==1) {
fontIdx=2;
} else if(fontIdx==2) {
fontIdx=3;
} else if(fontIdx==3) {
fontIdx=4;
} else if(fontIdx==4) {
fontIdx=0;
}
reloadFont = true;
}
} else {
readyReloadFont=false;
}
if (glfwGetKey(window, GLFW_KEY_3) == GLFW_PRESS) {
if(readyHideSky==0) {
readyHideSky=1;
if(hiddenSky==0) {
hiddenSky=1;
} else if(hiddenSky==1) {
hiddenSky=2;
} else {
hiddenSky=0;
}
}
} else if(readyHideSky==1) {
readyHideSky=0;
}
if (glfwGetKey(window, GLFW_KEY_4) == GLFW_PRESS) {
if(readyHideCloud==0) {
readyHideCloud=1;
if(hiddenCloud==0) {
hiddenCloud=1;
} else if(hiddenCloud==1) {
hiddenCloud=0;
}
}
} else if(readyHideCloud==1) {
readyHideCloud=0;
}
if (glfwGetKey(window, GLFW_KEY_5) == GLFW_PRESS) {
if(readyHideTerrain==0) {
readyHideTerrain=1;
hiddenTerrain=!hiddenTerrain;
}
} else if(readyHideTerrain==1) {
readyHideTerrain=0;
}
if (glfwGetKey(window, GLFW_KEY_6) == GLFW_PRESS) {
if(readyHideWater==0) {
readyHideWater=1;
if(hiddenWater==1) { // for also passing int to shader underwater
hiddenWater=0;
} else {
hiddenWater=1;
}
}
} else if(readyHideWater==1) {
readyHideWater=0;
}
if (glfwGetKey(window, GLFW_KEY_F) == GLFW_PRESS) {
if(readyFullScreen==0) {
readyFullScreen=1;
}
} else if(readyFullScreen==2) {
readyFullScreen=0;
}
// speed
if (glfwGetKey(window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS ||
glfwGetKey(window, GLFW_KEY_RIGHT_SHIFT) == GLFW_PRESS) {
speedMulti=2.0f;
shiftDown = true;
} else if(shiftDown) {
speedMulti=1.0f;
shiftDown = false;
}
if(updateTexts) {
//// get direction temporary value normalized 0-1
//sprintf(campostext,"campos x=%f, y=%f, z=%f\n", camera->eye->position->x, camera->eye->position->y, camera->eye->position->z);
//sprintf(camrottext,"playerpos x=%f, y=%f, z=%f\n", player->transform->position->x, player->transform->position->y, player->transform->position->z);
//sprintf(camdirtext,"input X theta=%f, phi=%f, ?=%f\n", theta, phi, 0.0f);
//rot->x=0.0f; rot->y=0.0f; rot->z=0.0f; pos->z=0.0f;
//pos->x=0.0f; pos->y=50.0f;
//UpdateText(7, pos, rot, 1.0f, Align.topleft);
//pos->x=0.0f; pos->y=60.0f;
//UpdateText(8, pos, rot, 1.0f, Align.topleft);
//pos->x=0.0f; pos->y=70.0f;
//UpdateText(9, pos, rot, 1.0f, Align.topleft);
}
free(pos);
free(rot);
}
// glfw: whenever the window size changed (by OS or user resize) this callback function executes
// ---------------------------------------------------------------------------------------------
//void framebuffer_size_callback(__attribute__((unused)) GLFWwindow* window, __attribute__((unused)) int width, __attribute__((unused)) int height)
//{
// make sure the viewport matches the new window dimensions; note that width and
// height will be significantly larger than specified on retina displays.
//SCR_WIDTH = width;
//SCR_HEIGHT = height;
//ratio = SCR_WIDTH / (float) SCR_HEIGHT;
//glViewport(0, 0, width, height);
//CreateFrameMsaa(1);
//glUseProgram(0);
//glUseProgram(programPost);
//setUniform1i(&programPost, "viewport_width", SCR_WIDTH);
//setUniform1i(&programPost, "viewport_height", SCR_HEIGHT);
//rerenderText=1;
//should_render = 1;
//}
int is_pressed = 0;
bool mouse_drag = false;
bool mouse_drag_started=false;
float lastMouseX, lastMouseY;
float lockMouseX, lockMouseY;
// glfw: whenever the mouse moves, this callback is called
// -------------------------------------------------------
//void mouse_mov_callback(GLFWwindow*, double xposIn, double yposIn)
void mouse_mov_callback(GLFWwindow* window, double xposIn, double yposIn)
{
float xpos = (float)(xposIn);
float ypos = (float)(yposIn);
if(is_pressed>0) {
if(!mouse_drag) {
lockMouseX = xpos;
lockMouseY = ypos;
mouse_drag=true;
}
} else {
if(mouse_drag) {
mouse_drag=false;
mouse_drag_started=false;
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
}
}
float diffLockX = xpos - lockMouseX;
float diffLockY = ypos - lockMouseY;
//float diffLastX = xpos - lastMouseX;
//float diffLastY = ypos - lastMouseY;
struct Vec3 *pos = malloc(sizeof(struct Vec3));
struct Vec3 *rot = malloc(sizeof(struct Vec3));
bool updateTexts=false;
if(mouse_drag) {
if(!mouse_drag_started) {
//sprintf(mousextext, "MX=%f, MY=%f", xpos, ypos);
updateTexts=true;
if(diffLockX > 2.0f || diffLockX< -2.0f ||
diffLockY > 2.0f || diffLockY < -2.0f) {
mouse_drag_started=true;
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
//glfwSetCursorPos(window, lockMouseX, lockMouseY);
}
} else {
//sprintf(mousextext, "MX=%f [DX=%f], MY=%f [DY=%f]", xpos, diffLockX, ypos, diffLockY);
updateTexts=true;
glfwSetCursorPos(window, lockMouseX, lockMouseY);
x_input = diffLockX;
y_input = diffLockY;
camera->eye->rotation->x = x_input; // for sprintf
camera->eye->rotation->y = y_input;
lastMouseX = xpos;
lastMouseY = ypos;
}
} else {
//sprintf(mousextext, "MX=%f, MY=%f", xpos, ypos);
updateTexts=true;
}
if(updateTexts) {
//// mousextext
//rot->x=0.0f; rot->y=0.0f; rot->z=0.0f; pos->z=0.0f;
//pos->x=0.0f; pos->y=20.0f;
//UpdateText(4, pos, rot, 1.0f, Align.topleft);
//sprintf(campostext,"campos x=%f, y=%f, z=%f\n", camera->eye->position->x, camera->eye->position->y, camera->eye->position->z);
//sprintf(camrottext,"playerpos x=%f, y=%f, z=%f\n", player->transform->position->x, player->transform->position->y, player->transform->position->z);
//sprintf(camdirtext,"input M theta=%f, phi=%f, ?=%f\n", theta, phi, 0.0f);
//rot->x=0.0f; rot->y=0.0f; rot->z=0.0f; pos->z=0.0f;
//pos->x=0.0f; pos->y=50.0f;
//UpdateText(7, pos, rot, 1.0f, Align.topleft);
//pos->x=0.0f; pos->y=60.0f;
//UpdateText(8, pos, rot, 1.0f, Align.topleft);
//pos->x=0.0f; pos->y=70.0f;
//UpdateText(9, pos, rot, 1.0f, Align.topleft);
}
free(pos);
free(rot);
}
bool click_ready = false;
bool LMB_press = false;
bool RMB_press = false;
int click_trace = 0;
//void mouse_btn_callback(GLFWwindow *window, int button, int action, int mods)
void mouse_btn_callback(GLFWwindow *window, int button, int action, __attribute__((unused)) int mods)
{
struct Vec3 *pos = malloc(sizeof(struct Vec3));
struct Vec3 *rot = malloc(sizeof(struct Vec3));
bool updateTexts=false;
if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS)
{
if(!LMB_press) {
LMB_press = true;
if(!RMB_press) {
click_ready = true;
}
}
} else if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_REPEAT) {
// holding
if(!LMB_press)
LMB_press = true;
} else if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_RELEASE) {
if(LMB_press) {
LMB_press = false;
if(!RMB_press && click_ready) {
//sprintf(mouseetext, "MouseAction=LMB (Click)");
updateTexts=true;
click_trace = 1;
double xposition, yposition;
glfwGetCursorPos(window, &xposition, &yposition);
lockMouseX = (float)xposition;
lockMouseY = (float)yposition;
is_pressed = false;
//mouse_drag=true;
mouse_drag=false;
mouse_drag_started=false;
}
click_ready = false;
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
}
}
if (button == GLFW_MOUSE_BUTTON_RIGHT && action == GLFW_PRESS)
{
if(!RMB_press) {
RMB_press = true;
if(!LMB_press) {
click_ready = true;
}
}
}
else if (button == GLFW_MOUSE_BUTTON_RIGHT && action == GLFW_REPEAT)
{
// holding
if(!RMB_press)
RMB_press = true;
}
else if (button == GLFW_MOUSE_BUTTON_RIGHT && action == GLFW_RELEASE)
{
if(RMB_press) {
RMB_press = false;
if(!LMB_press && click_ready) {
//sprintf(mouseetext, "MouseAction=RMB (Click)");
updateTexts=true;
click_trace = 2;
double xposition, yposition;
glfwGetCursorPos(window, &xposition, &yposition);
lockMouseX = (float)xposition;
lockMouseY = (float)yposition;
is_pressed = false;
//mouse_drag=true;
mouse_drag=false;
mouse_drag_started=false;
}
click_ready = false;
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
}
}
if(LMB_press && RMB_press)
{
if(is_pressed!=3) {
is_pressed = 3;
//sprintf(mouseetext, "MouseAction=LMB+RMB");
updateTexts=true;
}
}
else if(RMB_press)
{
if(is_pressed!=2) {
is_pressed = 2;
//sprintf(mouseetext, "MouseAction=RMB");
updateTexts=true;
}
}
else if(LMB_press)
{
if(is_pressed!=1) {
is_pressed = 1;
//sprintf(mouseetext, "MouseAction=LMB");
updateTexts=true;
}
}
else
{
if(is_pressed!=0) {
is_pressed = 0;
if(!click_ready) {
//sprintf(mouseetext, "MouseAction=none");
updateTexts=true;
}
if(mouse_drag) {
mouse_drag=false;
mouse_drag_started=false;
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
}
}
}
if(updateTexts) {
//// mouseetext
//rot->x=0.0f; rot->y=0.0f; rot->z=0.0f; pos->z=0.0f;
//pos->x=0.0f; pos->y=40.0f;
//UpdateText(6, pos, rot, 1.0f, Align.topleft);
//sprintf(campostext,"position M x=%f, y=%f, z=%f\n", camera->eye->position->x, camera->eye->position->y, camera->eye->position->z);
//sprintf(camrottext,"playerpos x=%f, y=%f, z=%f\n", player->transform->position->x, player->transform->position->y, player->transform->position->z);
////sprintf(camdirtext,"direction M x=%f, y=%f, z=%f\n", camera->center->position->x, camera->center->position->y, camera->center->position->z);
//sprintf(camdirtext,"direction MD x=%f, y=%f, z=%f\n", camera->center->rotation->x, camera->center->rotation->y, camera->center->rotation->z);
//rot->x=0.0f; rot->y=0.0f; rot->z=0.0f; pos->z=0.0f;
//pos->x=0.0f; pos->y=50.0f;
//UpdateText(7, pos, rot, 1.0f, Align.topleft);
//pos->x=0.0f; pos->y=60.0f;
//UpdateText(8, pos, rot, 1.0f, Align.topleft);
//pos->x=0.0f; pos->y=70.0f;
//UpdateText(9, pos, rot, 1.0f, Align.topleft);
}
free(pos);
free(rot);
}
//float scrollStep = 10.0f;
// glfw: whenever the mouse scroll wheel scrolls, this callback is called
// ----------------------------------------------------------------------
void scroll_callback(__attribute__((unused)) GLFWwindow* window, __attribute__((unused)) double xoffset, double yoffset)
{
if(vDown) { // fov change
if(yoffset<0) {
FOV+=1.0f;
} else if(yoffset>0) {
FOV-=1.0f;
}
fovrad=degToRad(FOV);
printf("new FOV set to %d degree (%f) [default 120]\n",FOV,fovrad);
} else { // distance camera zoom
if(yoffset<0) {
zoomDist+=1.0f;
} else if(yoffset>0) {
zoomDist-=1.0f;
}
zoomDist=CLAMP(zoomDist,200.0f,0.01f);
if(zoomDist<3.0f && zoomDist>2.0f) zoomDist = 2.0f; // reset 2.01
lastZoomDist = zoomDist;
}
}
Top