Refactor stuff into a player class and implement jumping
This commit is contained in:
7
Makefile
7
Makefile
@@ -1,5 +1,5 @@
|
||||
ghostland: glad.o ghostland.o stb_image.o collisions.o
|
||||
g++ -o ghostland glad.o ghostland.o stb_image.o collisions.o -ldl -lglfw -std=c++17 -O3
|
||||
ghostland: glad.o ghostland.o stb_image.o collisions.o player.o
|
||||
g++ -o ghostland glad.o ghostland.o stb_image.o collisions.o player.o -ldl -lglfw -std=c++17 -O3
|
||||
|
||||
glad.o: glad.c
|
||||
g++ -c -o glad.o glad.c -O3
|
||||
@@ -13,5 +13,8 @@ stb_image.o: stb_image.c
|
||||
collisions.o: collisions.cpp
|
||||
g++ -c -o collisions.o collisions.cpp -std=c++17 -O3
|
||||
|
||||
player.o: player.cpp
|
||||
g++ -c -o player.o player.cpp -std=c++17 -O3
|
||||
|
||||
clean:
|
||||
rm -f *.o ghostland
|
||||
|
||||
@@ -14,7 +14,7 @@ int signbit(float x) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int getIntersection(glm::vec3 vec_start, glm::vec3 vec_stop, glm::vec3 P1, glm::vec3 P2, glm::vec3 P3) {
|
||||
int get_intersection(glm::vec3 vec_start, glm::vec3 vec_stop, glm::vec3 P1, glm::vec3 P2, glm::vec3 P3) {
|
||||
|
||||
glm::vec3 lba = vec_start - vec_stop;
|
||||
glm::vec3 v01 = P2 - P1;
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
int getIntersection(glm::vec3 vec_start, glm::vec3 vec_stop, glm::vec3 P1, glm::vec3 P2, glm::vec3 P3);
|
||||
int get_intersection(glm::vec3 vec_start, glm::vec3 vec_stop, glm::vec3 P1, glm::vec3 P2, glm::vec3 P3);
|
||||
|
||||
#endif
|
||||
|
||||
278
ghostland.cpp
278
ghostland.cpp
@@ -14,41 +14,31 @@
|
||||
#include <math.h>
|
||||
|
||||
#include "collisions.h"
|
||||
#include "player.h"
|
||||
|
||||
glm::vec3 getNormalFromIndex(int ix);
|
||||
glm::vec3 getVec3FromIndices(int ix, int jx);
|
||||
glm::vec3 checkIntersection(glm::vec3 movement);
|
||||
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
|
||||
void mouse_callback(GLFWwindow* window, double xpos, double ypos);
|
||||
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
|
||||
void processInput(GLFWwindow *window);
|
||||
int createShader(const char *filename, int shadertype);
|
||||
void set_light_front(int xoffset, int yoffset);
|
||||
|
||||
// player
|
||||
Player *player;
|
||||
|
||||
// settings
|
||||
const unsigned int WINDOWWIDTH = 1600;
|
||||
const unsigned int WINDOWHEIGHT = 900;
|
||||
|
||||
// camera
|
||||
glm::vec3 player_pos = glm::vec3(0.0f, 0.0f, 3.0f);
|
||||
glm::vec3 camera_front = glm::vec3(0.0f, 0.0f, -1.0f);
|
||||
glm::vec3 camera_up = glm::vec3(0.0f, 1.0f, 0.0f);
|
||||
glm::vec3 light_pos = glm::vec3(0.0f, 0.0f, 0.0f);
|
||||
glm::vec3 light_front = glm::vec3(0.0f, 0.0f, -1.0f);
|
||||
|
||||
bool mousemove = false;
|
||||
const float lightoffsetmax = 15.0f;
|
||||
float xpersist = 0.0f;
|
||||
float ypersist = 0.0f;
|
||||
float persist_factor = 0.99f;
|
||||
float offset_factor = 0.01f;
|
||||
|
||||
bool first_mouse = true;
|
||||
float yaw = 0.0f;
|
||||
float pitch = 0.0f;
|
||||
float lastX = WINDOWWIDTH / 2.0;
|
||||
float lastY = WINDOWHEIGHT / 2.0;
|
||||
float fov = 60.0f;
|
||||
|
||||
float timed = 0.0f;
|
||||
float last_frame = 0.0f;
|
||||
@@ -71,7 +61,6 @@ const char *ambientC = "light.ambient";
|
||||
const char *diffuseC = "light.diffuse";
|
||||
const char *specularC = "light.specular";
|
||||
|
||||
|
||||
int num_walls;
|
||||
float *wall_vertices;
|
||||
|
||||
@@ -81,17 +70,20 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
|
||||
int success;
|
||||
glm::vec3 position;
|
||||
|
||||
FILE *fp = fopen("maze.txt", "r");
|
||||
float fakeyaw;
|
||||
if (fscanf(fp, "%f %f %f %f\n", &player_pos.x, &player_pos.y, &player_pos.z, &fakeyaw) == EOF) {
|
||||
float yaw;
|
||||
if (fscanf(fp, "%f %f %f %f\n", &position.x, &position.y, &position.z, &yaw) == EOF) {
|
||||
printf("1st fscanf failed.\n");
|
||||
return -1;
|
||||
}
|
||||
player = new Player(position, yaw);
|
||||
if (fscanf(fp, "%d\n", &num_walls) == EOF) {
|
||||
printf("2nd fscanf failed.\n");
|
||||
return -1;
|
||||
}
|
||||
player->num_walls = num_walls;
|
||||
// num surfaces * 6 (vertices per point) * 6 (floats per point)
|
||||
int num_wall_vertices = num_walls * 6 * 6;
|
||||
wall_vertices = (float *)calloc(sizeof(float), num_wall_vertices);
|
||||
@@ -118,6 +110,27 @@ int main(int argc, char *argv[])
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
player->wall_vertices = wall_vertices;
|
||||
|
||||
// read floor
|
||||
float *floor_vertices = (float *)calloc(sizeof(float), 6*6);
|
||||
for (int j = 0; j < 6; j++) {
|
||||
int vix = j*6;
|
||||
if (fscanf(
|
||||
fp,
|
||||
"%f %f %f %f %f %f\n",
|
||||
&floor_vertices[vix],
|
||||
&floor_vertices[vix+1],
|
||||
&floor_vertices[vix+2],
|
||||
&floor_vertices[vix+3],
|
||||
&floor_vertices[vix+4],
|
||||
&floor_vertices[vix+5]
|
||||
) == EOF) {
|
||||
printf("floor fscanf failed.\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
|
||||
glfwInit();
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||
@@ -184,26 +197,6 @@ int main(int argc, char *argv[])
|
||||
glDeleteShader(vertex_shader);
|
||||
glDeleteShader(fragment_shader);
|
||||
|
||||
// read floor
|
||||
float *floor_vertices = (float *)calloc(sizeof(float), 6*6);
|
||||
for (int j = 0; j < 6; j++) {
|
||||
int vix = j*6;
|
||||
if (fscanf(
|
||||
fp,
|
||||
"%f %f %f %f %f %f\n",
|
||||
&floor_vertices[vix],
|
||||
&floor_vertices[vix+1],
|
||||
&floor_vertices[vix+2],
|
||||
&floor_vertices[vix+3],
|
||||
&floor_vertices[vix+4],
|
||||
&floor_vertices[vix+5]
|
||||
) == EOF) {
|
||||
printf("floor fscanf failed.\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
|
||||
// do stuff for walls
|
||||
unsigned int wallsVBO, wallsVAO;
|
||||
glGenVertexArrays(1, &wallsVAO);
|
||||
@@ -294,7 +287,8 @@ int main(int argc, char *argv[])
|
||||
int trail_ix = 0;
|
||||
int trail_sz = 0;
|
||||
|
||||
int time_sec = 0, num_frames = 0;
|
||||
int time_secI = 0, num_frames = 1;
|
||||
float time_sec;
|
||||
glm::vec3 wall_color = glm::vec3(0.61f, 0.6f, 0.59f);
|
||||
float wall_shininess = 6.5;
|
||||
glm::vec3 floor_color = glm::vec3(0.11f, 0.1f, 0.09f);
|
||||
@@ -310,15 +304,21 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
float current_frame = static_cast<float>(glfwGetTime());
|
||||
int current_frameI = (int)current_frame;
|
||||
if (current_frameI != time_sec) {
|
||||
if (current_frameI != time_secI) {
|
||||
glm::vec3 player_pos = player->get_position();
|
||||
float yaw, pitch;
|
||||
yaw = player->get_yaw();
|
||||
pitch = player->get_pitch();
|
||||
printf("FPS: %d\n", num_frames);
|
||||
time_sec = current_frameI;
|
||||
num_frames = 0;
|
||||
printf("Player is at: (%f, %f, %f) facing (%f, %f)\n", player_pos.x, player_pos.y, player_pos.z, yaw, pitch);
|
||||
time_sec = current_frame;
|
||||
time_secI = current_frameI;
|
||||
num_frames = 1;
|
||||
trail_positions[trail_ix].x = player_pos.x;
|
||||
trail_positions[trail_ix].y = 6.5;
|
||||
trail_positions[trail_ix].z = player_pos.z;
|
||||
trail_angles[trail_ix] = yaw;
|
||||
printf("Recorded trail %d: (%f, %f, %f) %f\n", trail_ix, trail_positions[trail_ix].x, trail_positions[trail_ix].y, trail_positions[trail_ix].z, yaw);
|
||||
//printf("Recorded trail %d: (%f, %f, %f) %f\n", trail_ix, trail_positions[trail_ix].x, trail_positions[trail_ix].y, trail_positions[trail_ix].z, yaw);
|
||||
trail_ix = (trail_ix + 1) % trailmax;
|
||||
if (trail_sz < trailmax) {
|
||||
trail_sz++;
|
||||
@@ -331,32 +331,36 @@ int main(int argc, char *argv[])
|
||||
|
||||
mousemove = false;
|
||||
|
||||
processInput(window);
|
||||
player->process_input(window);
|
||||
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
glUseProgram(wall_program);
|
||||
|
||||
float fov = player->get_fov();
|
||||
glm::mat4 projection = glm::perspective(glm::radians(fov), (float)WINDOWWIDTH / (float)WINDOWHEIGHT, 0.1f, 256.0f);
|
||||
glUniformMatrix4fv(glGetUniformLocation(wall_program, projectionC), 1, GL_FALSE, &projection[0][0]);
|
||||
|
||||
glm::mat4 view = glm::lookAt(player_pos, player_pos + camera_front, camera_up);
|
||||
glm::vec3 camera_pos, camera_front, camera_up;
|
||||
camera_pos = player->get_camera_pos();
|
||||
camera_front = player->get_camera_front();
|
||||
camera_up = player->get_camera_up();
|
||||
|
||||
glm::mat4 view = glm::lookAt(camera_pos, camera_pos + camera_front, camera_up);
|
||||
glUniformMatrix4fv(glGetUniformLocation(wall_program, viewC), 1, GL_FALSE, &view[0][0]);
|
||||
|
||||
glm::mat4 model = glm::mat4(1.0f);
|
||||
glUniformMatrix4fv(glGetUniformLocation(wall_program, modelC), 1, GL_FALSE, &model[0][0]);
|
||||
|
||||
// light position
|
||||
float armlength = 0.50f;
|
||||
float yawoffset = 90.0f;
|
||||
float pitchoffset = -30.0f;
|
||||
light_pos.x = player_pos.x + armlength * cos(glm::radians(yaw + yawoffset)) * cos(glm::radians(pitch + pitchoffset));
|
||||
light_pos.y = player_pos.y + armlength * sin(glm::radians(pitch + pitchoffset));
|
||||
light_pos.z = player_pos.z + armlength * sin(glm::radians(yaw + yawoffset)) * cos(glm::radians(pitch + pitchoffset));
|
||||
glm::vec3 light_pos = player->get_light_pos();
|
||||
//printf("light_pos: (%f, %f, %f)\n", light_pos.x, light_pos.y, light_pos.z);
|
||||
glm::vec3 light_front = player->get_light_front();
|
||||
//printf("light_pos: (%f, %f, %f)\n", light_front.x, light_front.y, light_front.z);
|
||||
|
||||
// fragment requirements
|
||||
glUniform3fv(glGetUniformLocation(wall_program, viewposC), 1, &player_pos[0]);
|
||||
glUniform3fv(glGetUniformLocation(wall_program, viewposC), 1, &camera_pos[0]);
|
||||
glUniform1f(glGetUniformLocation(wall_program, shininessC), wall_shininess);
|
||||
glUniform3fv(glGetUniformLocation(wall_program, colorC), 1, &wall_color[0]);
|
||||
glUniform3fv(glGetUniformLocation(wall_program, lightposC), 1, &light_pos[0]);
|
||||
@@ -375,10 +379,10 @@ int main(int argc, char *argv[])
|
||||
glUniformMatrix4fv(glGetUniformLocation(floor_program, projectionC), 1, GL_FALSE, &projection[0][0]);
|
||||
glUniformMatrix4fv(glGetUniformLocation(floor_program, viewC), 1, GL_FALSE, &view[0][0]);
|
||||
glUniformMatrix4fv(glGetUniformLocation(floor_program, modelC), 1, GL_FALSE, &model[0][0]);
|
||||
glUniform3fv(glGetUniformLocation(floor_program, viewposC), 1, &player_pos[0]);
|
||||
glUniform3fv(glGetUniformLocation(floor_program, viewposC), 1, &camera_pos[0]);
|
||||
|
||||
// fragment requirements
|
||||
glUniform3fv(glGetUniformLocation(floor_program, viewposC), 1, &player_pos[0]);
|
||||
glUniform3fv(glGetUniformLocation(floor_program, viewposC), 1, &camera_pos[0]);
|
||||
glUniform1f(glGetUniformLocation(floor_program, shininessC), floor_shininess);
|
||||
glUniform3fv(glGetUniformLocation(floor_program, colorC), 1, &floor_color[0]);
|
||||
glUniform3fv(glGetUniformLocation(floor_program, lightposC), 1, &light_pos[0]);
|
||||
@@ -409,13 +413,11 @@ int main(int argc, char *argv[])
|
||||
glDrawArrays(GL_TRIANGLES, 0, 3 * 3 * 3);
|
||||
}
|
||||
|
||||
player->apply_movement();
|
||||
|
||||
glfwSwapBuffers(window);
|
||||
glfwPollEvents();
|
||||
|
||||
if (!mousemove) {
|
||||
set_light_front(0.0f, 0.0f);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
glDeleteVertexArrays(1, &wallsVAO);
|
||||
@@ -428,88 +430,11 @@ int main(int argc, char *argv[])
|
||||
return 0;
|
||||
}
|
||||
|
||||
void processInput(GLFWwindow *window)
|
||||
{
|
||||
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
|
||||
glfwSetWindowShouldClose(window, true);
|
||||
|
||||
float camera_speed_adjusted = static_cast<float>(camera_speed * timed);
|
||||
glm::vec3 movement;
|
||||
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) {
|
||||
movement = glm::vec3(camera_front.x, 0.0, camera_front.z);
|
||||
} else if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) {
|
||||
movement = glm::vec3(-camera_front.x, 0.0, -camera_front.z);
|
||||
} else if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) {
|
||||
glm::vec3 right = glm::cross(camera_front, camera_up);
|
||||
movement = glm::vec3(-right.x, 0.0, -right.z);
|
||||
} else if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) {
|
||||
glm::vec3 right = glm::cross(camera_front, camera_up);
|
||||
movement = glm::vec3(right.x, 0.0, right.z);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
movement = glm::normalize(movement) * camera_speed_adjusted;
|
||||
movement = checkIntersection(movement);
|
||||
player_pos += movement;
|
||||
}
|
||||
|
||||
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
|
||||
{
|
||||
glViewport(0, 0, width, height);
|
||||
}
|
||||
|
||||
void mouse_callback(GLFWwindow* window, double xpos_in, double ypos_in)
|
||||
{
|
||||
|
||||
mousemove = true;
|
||||
|
||||
float xpos = static_cast<float>(xpos_in);
|
||||
float ypos = static_cast<float>(ypos_in);
|
||||
|
||||
if (first_mouse)
|
||||
{
|
||||
lastX = xpos;
|
||||
lastY = ypos;
|
||||
first_mouse = false;
|
||||
}
|
||||
|
||||
float xoffset = xpos - lastX;
|
||||
float yoffset = lastY - ypos;
|
||||
lastX = xpos;
|
||||
lastY = ypos;
|
||||
|
||||
float sensitivity = 0.1f;
|
||||
xoffset *= sensitivity;
|
||||
yoffset *= sensitivity;
|
||||
|
||||
float prev_yaw = yaw;
|
||||
yaw += xoffset;
|
||||
pitch += yoffset;
|
||||
|
||||
if (pitch > 89.0f)
|
||||
pitch = 89.0f;
|
||||
if (pitch < -89.0f)
|
||||
pitch = -89.0f;
|
||||
|
||||
glm::vec3 front;
|
||||
front.x = cos(glm::radians(yaw)) * cos(glm::radians(pitch));
|
||||
front.y = sin(glm::radians(pitch));
|
||||
front.z = sin(glm::radians(yaw)) * cos(glm::radians(pitch));
|
||||
camera_front = normalize(front);
|
||||
|
||||
set_light_front(xoffset, yoffset);
|
||||
|
||||
}
|
||||
|
||||
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
|
||||
{
|
||||
fov -= (float)yoffset;
|
||||
if (fov < 1.0f)
|
||||
fov = 1.0f;
|
||||
if (fov > 90.0f)
|
||||
fov = 90.0f;
|
||||
}
|
||||
|
||||
int createShader(const char *filename, int shadertype) {
|
||||
FILE* fp = fopen(filename, "r");
|
||||
if (!fp) {
|
||||
@@ -543,87 +468,10 @@ int createShader(const char *filename, int shadertype) {
|
||||
return shader;
|
||||
}
|
||||
|
||||
glm::vec3 getNormalFromIndex(int ix) {
|
||||
return glm::vec3(
|
||||
wall_vertices[ix * 6 * 6 + 3],
|
||||
wall_vertices[ix * 6 * 6 + 4],
|
||||
wall_vertices[ix * 6 * 6 + 5]
|
||||
);
|
||||
void mouse_callback(GLFWwindow* window, double xpos, double ypos) {
|
||||
player->mouse_callback(window, xpos, ypos);
|
||||
}
|
||||
|
||||
glm::vec3 getVec3FromIndices(int ix, int jx) {
|
||||
return glm::vec3(
|
||||
wall_vertices[ix * 6 * 6 + jx * 6],
|
||||
wall_vertices[ix * 6 * 6 + jx * 6 + 1],
|
||||
wall_vertices[ix * 6 * 6 + jx * 6 + 2]
|
||||
);
|
||||
}
|
||||
|
||||
glm::vec3 checkIntersection(glm::vec3 movement) {
|
||||
|
||||
glm::vec3 vec_start, vec_stop, p1, p2, p3, res;
|
||||
int gotX = 0, gotZ = 0;
|
||||
vec_start = player_pos;
|
||||
vec_stop = vec_start + movement * 20.0f;
|
||||
res.x = movement.x;
|
||||
res.y = movement.y;
|
||||
res.z = movement.z;
|
||||
|
||||
for (int ix = 0; ix < num_walls; ix++) {
|
||||
glm::vec3 norm = getNormalFromIndex(ix);
|
||||
if (gotX && gotZ) {
|
||||
break;
|
||||
}
|
||||
if (!gotX) {
|
||||
if ((movement.x > 0 && norm.x < 0) || (movement.x < 0 && norm.x > 0)) {
|
||||
p1 = getVec3FromIndices(ix, 1);
|
||||
p2 = getVec3FromIndices(ix, 0);
|
||||
p3 = getVec3FromIndices(ix, 2);
|
||||
if (getIntersection(vec_start, vec_stop, p1, p2, p3)) {
|
||||
gotX = 1;
|
||||
res.x = -movement.x;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!gotZ) {
|
||||
if ((movement.z > 0 && norm.z < 0) || (movement.z < 0 && norm.z > 0)) {
|
||||
p1 = getVec3FromIndices(ix, 1);
|
||||
p2 = getVec3FromIndices(ix, 0);
|
||||
p3 = getVec3FromIndices(ix, 2);
|
||||
if (getIntersection(vec_start, vec_stop, p1, p2, p3)) {
|
||||
gotZ = 1;
|
||||
res.z = -movement.z;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
|
||||
}
|
||||
|
||||
void set_light_front(int xoffset, int yoffset) {
|
||||
|
||||
xoffset *= 128.0f;
|
||||
yoffset *= 128.0f;
|
||||
|
||||
xpersist = xpersist * persist_factor + xoffset * offset_factor;
|
||||
if (xpersist > lightoffsetmax) {
|
||||
xpersist = lightoffsetmax;
|
||||
} else if (xpersist < -lightoffsetmax) {
|
||||
xpersist = -lightoffsetmax;
|
||||
}
|
||||
ypersist = ypersist * persist_factor + yoffset * offset_factor;
|
||||
if (ypersist > lightoffsetmax) {
|
||||
ypersist = lightoffsetmax;
|
||||
} else if (ypersist < -lightoffsetmax) {
|
||||
ypersist = -lightoffsetmax;
|
||||
}
|
||||
float yawp = yaw + xpersist;
|
||||
float pitchp = pitch + ypersist;
|
||||
glm::vec3 front;
|
||||
front.x = cos(glm::radians(yawp)) * cos(glm::radians(pitchp));
|
||||
front.y = sin(glm::radians(pitchp));
|
||||
front.z = sin(glm::radians(yawp)) * cos(glm::radians(pitchp));
|
||||
light_front = normalize(front);
|
||||
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset) {
|
||||
player->scroll_callback(window, xoffset, yoffset);
|
||||
}
|
||||
|
||||
331
player.cpp
Normal file
331
player.cpp
Normal file
@@ -0,0 +1,331 @@
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
|
||||
#include "player.h"
|
||||
|
||||
Player::Player(glm::vec3 startpos, float startyaw) {
|
||||
|
||||
position = startpos;
|
||||
yaw = startyaw;
|
||||
|
||||
pitch = 0.0f;
|
||||
first_mouse = false;
|
||||
first_frame = false;
|
||||
light_xpersist = 0.0f;
|
||||
light_ypersist = 0.0f;
|
||||
armlength = 0.5f;
|
||||
camera_offset = glm::vec3(0.0f, 2.5f, 0.0f);
|
||||
camera_up = glm::vec3(0.0f, 1.0f, 0.0f);
|
||||
fov = 60.0f;
|
||||
|
||||
velocity = glm::vec3(0.0f, 0.0f, 0.0f);
|
||||
|
||||
}
|
||||
|
||||
glm::vec3 Player::get_position() {
|
||||
return position;
|
||||
}
|
||||
|
||||
glm::vec3 Player::get_camera_front() {
|
||||
return camera_front;
|
||||
}
|
||||
|
||||
glm::vec3 Player::get_camera_up() {
|
||||
return camera_up;
|
||||
}
|
||||
|
||||
glm::vec3 Player::get_camera_pos() {
|
||||
return position + camera_offset;
|
||||
}
|
||||
|
||||
glm::vec3 Player::get_light_pos() {
|
||||
return get_camera_pos() + get_light_front() * armlength;
|
||||
}
|
||||
|
||||
glm::vec3 Player::get_light_front() {
|
||||
float yawp = yaw + light_xpersist;
|
||||
float pitchp = pitch + light_ypersist;
|
||||
glm::vec3 front;
|
||||
front.x = cos(glm::radians(yawp)) * cos(glm::radians(pitchp));
|
||||
front.y = sin(glm::radians(pitchp));
|
||||
front.z = sin(glm::radians(yawp)) * cos(glm::radians(pitchp));
|
||||
return normalize(front);
|
||||
}
|
||||
|
||||
float Player::get_yaw() {
|
||||
return yaw;
|
||||
}
|
||||
|
||||
float Player::get_pitch() {
|
||||
return pitch;
|
||||
}
|
||||
|
||||
float Player::get_fov() {
|
||||
return fov;
|
||||
}
|
||||
|
||||
void Player::mouse_callback(GLFWwindow* window, double xposI, double yposI) {
|
||||
|
||||
float xpos = static_cast<float>(xposI);
|
||||
float ypos = static_cast<float>(yposI);
|
||||
|
||||
if (first_mouse) {
|
||||
prevx = xpos;
|
||||
prevy = ypos;
|
||||
first_mouse = false;
|
||||
}
|
||||
|
||||
float xoffset = xpos - prevx;
|
||||
float yoffset = prevy - ypos;
|
||||
prevx = xpos;
|
||||
prevy = ypos;
|
||||
|
||||
float sensitivity = 0.1f;
|
||||
xoffset *= sensitivity;
|
||||
yoffset *= sensitivity;
|
||||
|
||||
float prev_yaw = yaw;
|
||||
yaw += xoffset;
|
||||
pitch += yoffset;
|
||||
|
||||
if (pitch > 89.0f) {
|
||||
pitch = 89.0f;
|
||||
}
|
||||
if (pitch < -89.0f) {
|
||||
pitch = -89.0f;
|
||||
}
|
||||
|
||||
mouse_xoffset = xoffset;
|
||||
mouse_yoffset = yoffset;
|
||||
|
||||
}
|
||||
|
||||
void Player::process_input(GLFWwindow *window)
|
||||
{
|
||||
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) {
|
||||
glfwSetWindowShouldClose(window, true);
|
||||
}
|
||||
|
||||
bool W, A, S, D, space;
|
||||
|
||||
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) {
|
||||
W = true;
|
||||
} else {
|
||||
W = false;
|
||||
}
|
||||
if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) {
|
||||
S = true;
|
||||
} else {
|
||||
S = false;
|
||||
}
|
||||
if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) {
|
||||
A = true;
|
||||
} else {
|
||||
A = false;
|
||||
}
|
||||
if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) {
|
||||
D = true;
|
||||
} else {
|
||||
D = false;
|
||||
}
|
||||
if (glfwGetKey(window, GLFW_KEY_SPACE) == GLFW_PRESS) {
|
||||
space = true;
|
||||
} else {
|
||||
space = false;
|
||||
}
|
||||
|
||||
if (!is_in_air()) {
|
||||
|
||||
glm::vec3 relvel;
|
||||
|
||||
if (space) {
|
||||
velocity.y = jumpvelocity;
|
||||
return;
|
||||
} else {
|
||||
velocity.y = 0.0;
|
||||
}
|
||||
|
||||
// intentionally don't update velocity if contradictory keys are pressed
|
||||
if (!W && !S) {
|
||||
relvel.z = 0.0;
|
||||
} else if (W) {
|
||||
relvel.z = 1.0;
|
||||
} else if (S) {
|
||||
relvel.z = -1.0;
|
||||
}
|
||||
|
||||
if (!A && !D) {
|
||||
relvel.x = 0.0;
|
||||
} else if (A) {
|
||||
relvel.x = -1.0;
|
||||
} else if (D) {
|
||||
relvel.x = 1.0;
|
||||
}
|
||||
|
||||
if (relvel.x == 0.0 && relvel.z == 0.0) {
|
||||
velocity.x = 0.0;
|
||||
velocity.z = 0.0;
|
||||
return;
|
||||
}
|
||||
|
||||
relvel = glm::normalize(relvel);
|
||||
relvel *= hvelocity;
|
||||
|
||||
float yawr = glm::radians(yaw);
|
||||
velocity.z = relvel.x * cos(yawr) + relvel.z * sin(yawr);
|
||||
velocity.x = -relvel.x * sin(yawr) + relvel.z * cos(yawr);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool Player::is_in_air() {
|
||||
return position.y > 0.0;
|
||||
}
|
||||
|
||||
void Player::set_light_offset(float xoffset, float yoffset) {
|
||||
|
||||
xoffset *= light_movement_multiplier;
|
||||
yoffset *= light_movement_multiplier;
|
||||
|
||||
light_xpersist = light_xpersist * light_persist_factor + xoffset * light_offset_factor;
|
||||
if (light_xpersist > lightoffsetmax) {
|
||||
light_xpersist = lightoffsetmax;
|
||||
} else if (light_xpersist < -lightoffsetmax) {
|
||||
light_xpersist = -lightoffsetmax;
|
||||
}
|
||||
light_ypersist = light_ypersist * light_persist_factor + yoffset * light_offset_factor;
|
||||
if (light_ypersist > lightoffsetmax) {
|
||||
light_ypersist = lightoffsetmax;
|
||||
} else if (light_ypersist < -lightoffsetmax) {
|
||||
light_ypersist = -lightoffsetmax;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Player::apply_movement() {
|
||||
|
||||
float curr_time = static_cast<float>(glfwGetTime());
|
||||
|
||||
if (!first_frame) {
|
||||
prev_move_time = curr_time;
|
||||
first_frame = true;
|
||||
return;
|
||||
}
|
||||
|
||||
float diff_time = curr_time - prev_move_time;
|
||||
prev_move_time = curr_time;
|
||||
|
||||
// mouse movement
|
||||
glm::vec3 front;
|
||||
front.x = cos(glm::radians(yaw)) * cos(glm::radians(pitch));
|
||||
front.y = sin(glm::radians(pitch));
|
||||
front.z = sin(glm::radians(yaw)) * cos(glm::radians(pitch));
|
||||
camera_front = normalize(front);
|
||||
|
||||
// light movement;
|
||||
set_light_offset(mouse_xoffset, mouse_yoffset);
|
||||
mouse_xoffset = 0.0;
|
||||
mouse_yoffset = 0.0;
|
||||
|
||||
// positional movement
|
||||
glm::vec3 movement = velocity;
|
||||
movement *= diff_time;
|
||||
glm::vec3 intersected = check_intersection(movement);
|
||||
if (is_in_air()) {
|
||||
if (intersected.x == 0.0) {
|
||||
velocity.x = 0.0;
|
||||
}
|
||||
if (intersected.z == 0.0) {
|
||||
velocity.z = 0.0;
|
||||
}
|
||||
} else { // not in air
|
||||
if (intersected.x != movement.x) {
|
||||
intersected.x = -movement.x;
|
||||
}
|
||||
if (intersected.z != movement.z) {
|
||||
intersected.z = -movement.z;
|
||||
}
|
||||
}
|
||||
|
||||
position.y += intersected.y;
|
||||
if (position.y <= 0.0f) {
|
||||
position.y = 0.0f;
|
||||
velocity.y = 0.0f;
|
||||
} else {
|
||||
velocity.y += diff_time * vacceleration;
|
||||
}
|
||||
|
||||
position.x += intersected.x;
|
||||
position.z += intersected.z;
|
||||
|
||||
}
|
||||
|
||||
glm::vec3 Player::get_normal_from_index(int ix) {
|
||||
return glm::vec3(
|
||||
wall_vertices[ix * 6 * 6 + 3],
|
||||
wall_vertices[ix * 6 * 6 + 4],
|
||||
wall_vertices[ix * 6 * 6 + 5]
|
||||
);
|
||||
}
|
||||
|
||||
glm::vec3 Player::get_vec3_from_indices(int ix, int jx) {
|
||||
return glm::vec3(
|
||||
wall_vertices[ix * 6 * 6 + jx * 6],
|
||||
wall_vertices[ix * 6 * 6 + jx * 6 + 1],
|
||||
wall_vertices[ix * 6 * 6 + jx * 6 + 2]
|
||||
);
|
||||
}
|
||||
|
||||
glm::vec3 Player::check_intersection(glm::vec3 movement) {
|
||||
|
||||
glm::vec3 vec_start, vec_stop, p1, p2, p3, res;
|
||||
bool gotX = false, gotZ = false;
|
||||
vec_start = get_camera_pos();
|
||||
vec_stop = vec_start + movement * 20.0f;
|
||||
res.x = movement.x;
|
||||
res.y = movement.y;
|
||||
res.z = movement.z;
|
||||
|
||||
for (int ix = 0; ix < num_walls; ix++) {
|
||||
if (gotX && gotZ) {
|
||||
break;
|
||||
}
|
||||
glm::vec3 norm = get_normal_from_index(ix);
|
||||
if (!gotX) {
|
||||
if ((movement.x > 0 && norm.x < 0) || (movement.x < 0 && norm.x > 0)) {
|
||||
p1 = get_vec3_from_indices(ix, 1);
|
||||
p2 = get_vec3_from_indices(ix, 0);
|
||||
p3 = get_vec3_from_indices(ix, 2);
|
||||
if (get_intersection(vec_start, vec_stop, p1, p2, p3)) {
|
||||
gotX = true;
|
||||
res.x = 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!gotZ) {
|
||||
if ((movement.z > 0 && norm.z < 0) || (movement.z < 0 && norm.z > 0)) {
|
||||
p1 = get_vec3_from_indices(ix, 1);
|
||||
p2 = get_vec3_from_indices(ix, 0);
|
||||
p3 = get_vec3_from_indices(ix, 2);
|
||||
if (get_intersection(vec_start, vec_stop, p1, p2, p3)) {
|
||||
gotZ = true;
|
||||
res.z = 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
|
||||
}
|
||||
|
||||
void Player::scroll_callback(GLFWwindow* window, double xoffset, double yoffset) {
|
||||
fov -= (float)yoffset;
|
||||
if (fov < 1.0f) {
|
||||
fov = 1.0f;
|
||||
}
|
||||
if (fov > 90.0f) {
|
||||
fov = 90.0f;
|
||||
}
|
||||
}
|
||||
75
player.h
Normal file
75
player.h
Normal file
@@ -0,0 +1,75 @@
|
||||
#ifndef PLAYER_H
|
||||
#define PLAYER_H
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <string>
|
||||
|
||||
#include "collisions.h"
|
||||
|
||||
const float lightoffsetmax = 15.0;
|
||||
const float light_persist_factor = 0.99;
|
||||
const float light_offset_factor = 0.01;
|
||||
const float light_movement_multiplier = 128.0;
|
||||
const float jumpvelocity = 8.104849;
|
||||
const float vacceleration = -13.4058;
|
||||
const float hvelocity = 10.0;
|
||||
|
||||
class Player {
|
||||
|
||||
|
||||
public:
|
||||
|
||||
Player(glm::vec3 startpos, float startyaw);
|
||||
|
||||
int num_walls;
|
||||
float *wall_vertices;
|
||||
|
||||
glm::vec3 get_position();
|
||||
glm::vec3 get_camera_front();
|
||||
glm::vec3 get_camera_up();
|
||||
glm::vec3 get_camera_pos();
|
||||
glm::vec3 get_light_pos();
|
||||
glm::vec3 get_light_front();
|
||||
float get_yaw();
|
||||
float get_pitch();
|
||||
float get_fov();
|
||||
|
||||
void mouse_callback(GLFWwindow *window, double xposI, double yposI);
|
||||
void process_input(GLFWwindow *window);
|
||||
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
|
||||
bool is_in_air();
|
||||
void apply_movement();
|
||||
|
||||
private:
|
||||
float yaw;
|
||||
float pitch;
|
||||
float fov;
|
||||
float prevx;
|
||||
float prevy;
|
||||
bool first_mouse;
|
||||
bool first_frame;
|
||||
float light_xpersist;
|
||||
float light_ypersist;
|
||||
float armlength;
|
||||
float prev_move_time;
|
||||
float mouse_xoffset;
|
||||
float mouse_yoffset;
|
||||
|
||||
glm::vec3 position;
|
||||
glm::vec3 camera_front;
|
||||
glm::vec3 camera_up;
|
||||
glm::vec3 light_pos;
|
||||
glm::vec3 light_front;
|
||||
glm::vec3 velocity;
|
||||
glm::vec3 camera_offset;
|
||||
|
||||
void set_light_offset(float xoffset, float yoffset);
|
||||
|
||||
glm::vec3 get_normal_from_index(int ix);
|
||||
glm::vec3 get_vec3_from_indices(int ix, int jx);
|
||||
glm::vec3 check_intersection(glm::vec3 movement);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user