350 lines
9.7 KiB
C
350 lines
9.7 KiB
C
#include "../include/app.h"
|
|
#include <GL/gl.h>
|
|
|
|
void init_app(App *app, uint w, uint h)
|
|
{
|
|
int err;
|
|
|
|
err = SDL_Init(SDL_INIT_EVERYTHING);
|
|
if (err != 0) {
|
|
printf("Failed to initialize SDL. Error: %s\n",
|
|
SDL_GetError());
|
|
exit(1);
|
|
}
|
|
|
|
app->window = SDL_CreateWindow(
|
|
"test",
|
|
SDL_WINDOWPOS_CENTERED,
|
|
SDL_WINDOWPOS_CENTERED,
|
|
w, h, SDL_WINDOW_OPENGL);
|
|
|
|
if (app->window == NULL) {
|
|
printf("Failed to create window.\n");
|
|
exit(1);
|
|
}
|
|
|
|
app->context = SDL_GL_CreateContext(app->window);
|
|
if (app->context == NULL) {
|
|
printf("Failed to create OpenGL context.\n");
|
|
exit(1);
|
|
}
|
|
app->is_running = true;
|
|
|
|
//SDL_ShowCursor(SDL_DISABLE);
|
|
init_camera(&app->camera);
|
|
init_opengl();
|
|
reshape(w, h);
|
|
|
|
init_camera(&(app->camera));
|
|
|
|
app->surface = IMG_Load("assets/block.png");
|
|
app->tid = 0;
|
|
|
|
if(app->surface==NULL) {
|
|
printf("error\n");
|
|
exit(1);
|
|
}
|
|
glGenTextures(1, &app->tid);
|
|
glBindTexture(GL_TEXTURE_2D, app->tid);
|
|
|
|
int Mode = GL_RGB;
|
|
|
|
if(app->surface->format->BytesPerPixel == 4) {
|
|
Mode = GL_RGBA;
|
|
}
|
|
|
|
glTexImage2D(GL_TEXTURE_2D, 0, Mode, app->surface->w, app->surface->h, 0, Mode, GL_UNSIGNED_BYTE, app->surface->pixels);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
|
|
glBindTexture(GL_TEXTURE_2D, app->tid);
|
|
}
|
|
|
|
void update_app(App* app)
|
|
{
|
|
app->camera.speed.z -= GRAVITY * (app->frame_time/1000);
|
|
|
|
if(app_check_collision(app))
|
|
camera_set_vertical_speed(&app->camera, 0.0);
|
|
update_camera(&(app->camera), app->frame_time/1000);
|
|
}
|
|
|
|
void init_opengl()
|
|
{
|
|
// https://gitlab.com/imre-piller/me-courses/ alapjan.
|
|
glShadeModel(GL_SMOOTH);
|
|
|
|
glEnable(GL_NORMALIZE);
|
|
glEnable(GL_AUTO_NORMAL);
|
|
|
|
glClearColor(0.1, 0.1, 0.1, 1.0);
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
glLoadIdentity();
|
|
|
|
glEnable(GL_DEPTH_TEST);
|
|
glClearDepth(1.0);
|
|
glEnable(GL_TEXTURE_2D);
|
|
}
|
|
|
|
void reshape(GLsizei width, GLsizei height)
|
|
{
|
|
int x, y, w, h;
|
|
double ratio;
|
|
|
|
ratio = (double)width / height;
|
|
if (ratio > VIEWPORT_RATIO) {
|
|
w = (int)((double)height * VIEWPORT_RATIO);
|
|
h = height;
|
|
x = (width - w) / 2;
|
|
y = 0;
|
|
}
|
|
else {
|
|
w = width;
|
|
h = (int)((double)width / VIEWPORT_RATIO);
|
|
x = 0;
|
|
y = (height - h) / 2;
|
|
}
|
|
|
|
glViewport(x, y, w, h);
|
|
glMatrixMode(GL_PROJECTION);
|
|
glLoadIdentity();
|
|
glFrustum(
|
|
-.08, .08,
|
|
-.06, .06,
|
|
.1, 1000
|
|
);
|
|
}
|
|
|
|
void handle_events(App* app)
|
|
{
|
|
SDL_Event event;
|
|
static bool is_mouse_down = false;
|
|
static int mouse_x = 0;
|
|
static int mouse_y = 0;
|
|
int x;
|
|
int y;
|
|
|
|
while (SDL_PollEvent(&event)) {
|
|
switch (event.type) {
|
|
case SDL_KEYDOWN:
|
|
switch (event.key.keysym.scancode) {
|
|
case SDL_SCANCODE_ESCAPE:
|
|
app->is_running = false;
|
|
break;
|
|
case SDL_SCANCODE_W:
|
|
set_camera_speed(&(app->camera), SPEED);
|
|
break;
|
|
case SDL_SCANCODE_S:
|
|
set_camera_speed(&(app->camera), -SPEED);
|
|
break;
|
|
case SDL_SCANCODE_A:
|
|
set_camera_side_speed(&(app->camera), SPEED);
|
|
break;
|
|
case SDL_SCANCODE_D:
|
|
set_camera_side_speed(&(app->camera), -SPEED);
|
|
break;
|
|
case SDL_SCANCODE_SPACE:
|
|
if (app_check_collision(app))
|
|
app->camera.position.z+=0.3;
|
|
camera_set_vertical_speed(&app->camera, SPEED);
|
|
break;
|
|
case SDL_SCANCODE_LSHIFT:
|
|
camera_set_vertical_speed(&app->camera, -SPEED);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
case SDL_KEYUP:
|
|
switch (event.key.keysym.scancode) {
|
|
case SDL_SCANCODE_W:
|
|
case SDL_SCANCODE_S:
|
|
set_camera_speed(&(app->camera), 0);
|
|
break;
|
|
case SDL_SCANCODE_A:
|
|
case SDL_SCANCODE_D:
|
|
set_camera_side_speed(&(app->camera), 0);
|
|
break;
|
|
case SDL_SCANCODE_SPACE:
|
|
case SDL_SCANCODE_LSHIFT:
|
|
camera_set_vertical_speed(&app->camera, -0);
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
case SDL_MOUSEBUTTONDOWN:
|
|
is_mouse_down = true;
|
|
break;
|
|
case SDL_MOUSEMOTION:
|
|
SDL_GetMouseState(&x, &y);
|
|
if (is_mouse_down) {
|
|
rotate_camera(&(app->camera), mouse_x - x, mouse_y - y);
|
|
}
|
|
mouse_x = x;
|
|
mouse_y = y;
|
|
break;
|
|
case SDL_MOUSEBUTTONUP:
|
|
is_mouse_down = false;
|
|
break;
|
|
case SDL_QUIT:
|
|
app->is_running = false;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
void app_raycast(App *app)
|
|
{
|
|
vec4f v = {0, 0, -1, 1};
|
|
vec4f retv;
|
|
float projection[16];
|
|
glGetFloatv(GL_PROJECTION_MATRIX, projection);
|
|
mult_matrix(projection, v, &retv);
|
|
retv.z = -1.0;
|
|
retv.w = 0.0;
|
|
|
|
}
|
|
|
|
void draw_cube(App *app, float x, float y, float z)
|
|
{
|
|
/*x*=2;
|
|
y*=2;
|
|
z*=2;
|
|
*/
|
|
glBegin( GL_QUADS );
|
|
|
|
glColor3f(1, 1, 1);
|
|
glTexCoord2f(0, 0); glVertex3f(x+1.0, y, z-1.0 );
|
|
glTexCoord2f(0, 1); glVertex3f(x, y, z-1.0);
|
|
glTexCoord2f(1, 1); glVertex3f(x, y, z);
|
|
glTexCoord2f(1, 0); glVertex3f(x+1.0, y, z);
|
|
|
|
glColor3f(1, 1, 1);
|
|
glTexCoord2f(0, 0); glVertex3f(x+1.0, y-1.0, z-1.0);
|
|
glTexCoord2f(0, 1); glVertex3f(x, y-1.0, z-1.0);
|
|
glTexCoord2f(1, 1); glVertex3f(x, y-1.0, z);
|
|
glTexCoord2f(1, 0); glVertex3f(x+1.0, y-1.0, z);
|
|
|
|
glColor3f(1, 1, 1);
|
|
glTexCoord2f(0, 0); glVertex3f(x+1.0, y, z);
|
|
glTexCoord2f(0, 1); glVertex3f(x, y, z);
|
|
glTexCoord2f(1, 1); glVertex3f(x, y-1.0, z);
|
|
glTexCoord2f(1, 0); glVertex3f(x+1.0, y-1.0, z);
|
|
|
|
glColor3f(1, 1, 1);
|
|
glTexCoord2f(0, 0); glVertex3f(x, y, z-1.0); // Top-Right of back face
|
|
glTexCoord2f(0, 1); glVertex3f(x+1.0, y, z-1.0); // Top-Left of back face
|
|
glTexCoord2f(1, 1); glVertex3f(x+1.0, y-1.0, z-1.0); // Bottom-Left of back face
|
|
glTexCoord2f(1, 0); glVertex3f(x, y-1.0, z-1.0); // Bottom-Right of back face
|
|
|
|
glColor3f(1, 1, 1);
|
|
glTexCoord2f(0, 0); glVertex3f(x, y, z); // Top-Right of left face
|
|
glTexCoord2f(0, 1); glVertex3f(x, y, z-1.0); // Top-Left of left face
|
|
glTexCoord2f(1, 1); glVertex3f(x, y-1.0, z-1.0); // Bottom-Left of left face
|
|
glTexCoord2f(1, 0); glVertex3f(x, y-1.0, z); // Bottom-Right of left face
|
|
|
|
glColor3f(1, 1, 1);
|
|
glTexCoord2f(0, 0); glVertex3f(x+1.0, y, z); // Top-Right of left face
|
|
glTexCoord2f(0, 1); glVertex3f(x+1.0, y, z-1.0); // Top-Left of left face
|
|
glTexCoord2f(1, 1); glVertex3f(x+1.0, y-1.0, z-1.0); // Bottom-Left of left face
|
|
glTexCoord2f(1, 0); glVertex3f(x+1.0, y-1.0, z); // Bottom-Right of left face
|
|
glEnd();
|
|
glFlush();
|
|
}
|
|
|
|
float calc_frame_time(struct timespec *start, struct timespec *end)
|
|
{
|
|
float elapsed_time = (end->tv_sec - start->tv_sec)*1000;
|
|
|
|
elapsed_time += (float)(end->tv_nsec - start->tv_nsec)/1000000;
|
|
|
|
return elapsed_time;
|
|
}
|
|
|
|
int app_get_current_chunk_index(App *app)
|
|
{
|
|
for (int i = 0; i < app->chunk_count; i++) {
|
|
for (int x = 0; x < CHUNK_MAX_X; x++) {
|
|
for (int y = 0; y < CHUNK_MAX_Y; y++) {
|
|
for (int z = 0; z < CHUNK_MAX_Z; z++) {
|
|
if (app->camera.position.x < app->chunks[i].start_pos.x + CHUNK_MAX_X &&
|
|
app->camera.position.x > app->chunks[i].start_pos.x &&
|
|
app->camera.position.y < app->chunks[i].start_pos.y + CHUNK_MAX_Y &&
|
|
app->camera.position.y > app->chunks[i].start_pos.y) {
|
|
return i;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
bool is_block(Block b)
|
|
{
|
|
if(b.type != BLOCKTYPE_AIR)
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
bool app_check_collision(App *app)
|
|
{
|
|
int i = app_get_current_chunk_index(app);
|
|
|
|
if (i < 0)
|
|
return false;
|
|
|
|
for (int x = 0; x < CHUNK_MAX_X; x++) {
|
|
for (int y = 0; y < CHUNK_MAX_Y; y++) {
|
|
for (int z = 0; z < CHUNK_MAX_Z; z++) {
|
|
if (!is_block(app->chunks[i].blocks[x][y][z]))
|
|
continue;
|
|
if (app->camera.position.z <= z+5)
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void check_intersection_block(App *app, vec3i *retv)
|
|
{
|
|
int i = app_get_current_chunk_index(app);
|
|
|
|
vec3f c_pos = app->camera.position;
|
|
vec3f c_dir = get_camera_dir_vec3f(&app->camera);
|
|
|
|
retv->x = 0;
|
|
retv->y = 0;
|
|
retv->z = 0;
|
|
|
|
if (i < 0)
|
|
return;
|
|
|
|
for (int x = 0; x < CHUNK_MAX_X; x++) {
|
|
for (int y = 0; y < CHUNK_MAX_Y; y++) {
|
|
for (int z = 0; z < CHUNK_MAX_Z; z++) {
|
|
for (int i = 0; i < 8; i+=0.1) {
|
|
vec3f ray = {c_pos.x + c_dir.x * i,
|
|
c_pos.y + c_dir.y * i,
|
|
c_pos.z + c_dir.z * i};
|
|
|
|
vec3i rayi = {floor(ray.x/1), floor(ray.y/1), floor(ray.z/1)};
|
|
|
|
if (is_block(app->chunks[i].blocks[rayi.x][rayi.y][rayi.z])) {
|
|
retv->x = ray.x;
|
|
retv->y = ray.y;
|
|
retv->z = ray.z;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|