Initial commit, building and working!
19
Makefile
Normal file
@ -0,0 +1,19 @@
|
||||
# Makefile for Cubious - (C) Chris Dorman, 2021
|
||||
|
||||
CC = gcc
|
||||
|
||||
CFLAGS = -O2
|
||||
LDFLAGS = -lGLEW -lGLU -lGL -lm -lc -lSDL2 -lSDL2_mixer
|
||||
|
||||
BIN = bin/cubious
|
||||
OBJECTS = src/engine_assets.o src/engine_camera.o src/engine_chunk.o src/engine_clock.o src/engine_console.o src/engine_cube.o src/engine_generation.o src/engine_main.o src/engine_physics.o src/engine_player.o src/engine_renderer.o src/engine_sdl.o src/engine_shader.o src/engine_text.o src/engine_ui.o src/engine_world.o
|
||||
|
||||
all: main
|
||||
|
||||
fresh: clean all
|
||||
|
||||
main: $(OBJECTS)
|
||||
$(CC) $(OBJECTS) -o $(BIN) $(LDFLAGS) $(CFLAGS)
|
||||
|
||||
clean:
|
||||
rm -f $(OBJECTS) $(BIN)
|
9
README.md
Normal file
@ -0,0 +1,9 @@
|
||||
### Cubious
|
||||
Voxel based game engine in C using SDL2 and GLEW.
|
||||
|
||||
### Compiling
|
||||
* Install SDL2, and GLEW
|
||||
* make
|
||||
* cd bin/ & ./cubious
|
||||
|
||||
Not much to do in the game yet, but is a work in progress!
|
BIN
bin/cubious
Executable file
8
data/assets/cubetypes.vxe
Normal file
@ -0,0 +1,8 @@
|
||||
000 0.3,0.09,0.113
|
||||
001 0.3,0.3,0.3
|
||||
002 0.365,0.769,0.031
|
||||
003 1.0,1.0,1.0
|
||||
004 0.2,0.09,0.113
|
||||
005 0.5,0.5,0.5
|
||||
006 0.365,0.84,0.031
|
||||
007 0.9,0.9,0.9
|
BIN
data/assets/music/fall.ogg
Normal file
BIN
data/assets/music/jump.ogg
Normal file
BIN
data/assets/textures/back.png
Normal file
After Width: | Height: | Size: 236 B |
BIN
data/assets/textures/bottom.png
Normal file
After Width: | Height: | Size: 190 B |
BIN
data/assets/textures/front.png
Normal file
After Width: | Height: | Size: 236 B |
BIN
data/assets/textures/left.png
Normal file
After Width: | Height: | Size: 236 B |
BIN
data/assets/textures/right.png
Normal file
After Width: | Height: | Size: 236 B |
BIN
data/assets/textures/top.png
Normal file
After Width: | Height: | Size: 231 B |
102
data/font/font.fnt
Normal file
@ -0,0 +1,102 @@
|
||||
info face="Droid Sans Mono" size=60 bold=0 italic=0 charset="" unicode=0 stretchH=100 smooth=1 aa=1 padding=1,1,1,1 spacing=-2,-2
|
||||
common lineHeight=71 base=56 scaleW=512 scaleH=512 pages=1 packed=0
|
||||
page id=0 file="font.png"
|
||||
chars count=97
|
||||
char id=0 x=182 y=157 width=28 height=45 xoffset=4 yoffset=12 xadvance=36 page=0 chnl=0
|
||||
char id=10 x=182 y=157 width=28 height=45 xoffset=4 yoffset=12 xadvance=36 page=0 chnl=0
|
||||
char id=32 x=0 y=0 width=0 height=0 xoffset=-1 yoffset=55 xadvance=36 page=0 chnl=0
|
||||
char id=33 x=492 y=63 width=9 height=46 xoffset=13 yoffset=12 xadvance=36 page=0 chnl=0
|
||||
char id=34 x=0 y=238 width=22 height=18 xoffset=7 yoffset=12 xadvance=36 page=0 chnl=0
|
||||
char id=35 x=344 y=157 width=35 height=45 xoffset=0 yoffset=12 xadvance=36 page=0 chnl=0
|
||||
char id=36 x=193 y=0 width=28 height=52 xoffset=4 yoffset=9 xadvance=36 page=0 chnl=0
|
||||
char id=37 x=390 y=63 width=38 height=47 xoffset=-1 yoffset=11 xadvance=36 page=0 chnl=0
|
||||
char id=38 x=428 y=63 width=37 height=47 xoffset=1 yoffset=11 xadvance=36 page=0 chnl=0
|
||||
char id=39 x=490 y=202 width=10 height=18 xoffset=13 yoffset=12 xadvance=36 page=0 chnl=0
|
||||
char id=40 x=63 y=0 width=21 height=55 xoffset=8 yoffset=12 xadvance=36 page=0 chnl=0
|
||||
char id=41 x=84 y=0 width=22 height=55 xoffset=7 yoffset=12 xadvance=36 page=0 chnl=0
|
||||
char id=42 x=400 y=202 width=32 height=30 xoffset=2 yoffset=9 xadvance=36 page=0 chnl=0
|
||||
char id=43 x=432 y=202 width=29 height=29 xoffset=3 yoffset=20 xadvance=36 page=0 chnl=0
|
||||
char id=44 x=22 y=238 width=14 height=18 xoffset=11 yoffset=48 xadvance=36 page=0 chnl=0
|
||||
char id=45 x=79 y=238 width=21 height=7 xoffset=7 yoffset=36 xadvance=36 page=0 chnl=0
|
||||
char id=46 x=500 y=202 width=11 height=13 xoffset=13 yoffset=45 xadvance=36 page=0 chnl=0
|
||||
char id=47 x=292 y=157 width=26 height=45 xoffset=5 yoffset=12 xadvance=36 page=0 chnl=0
|
||||
char id=48 x=331 y=63 width=30 height=47 xoffset=3 yoffset=11 xadvance=36 page=0 chnl=0
|
||||
char id=49 x=210 y=157 width=19 height=45 xoffset=5 yoffset=12 xadvance=36 page=0 chnl=0
|
||||
char id=50 x=31 y=111 width=29 height=46 xoffset=4 yoffset=11 xadvance=36 page=0 chnl=0
|
||||
char id=51 x=214 y=63 width=30 height=47 xoffset=2 yoffset=11 xadvance=36 page=0 chnl=0
|
||||
char id=52 x=229 y=157 width=33 height=45 xoffset=1 yoffset=12 xadvance=36 page=0 chnl=0
|
||||
char id=53 x=60 y=111 width=29 height=46 xoffset=4 yoffset=12 xadvance=36 page=0 chnl=0
|
||||
char id=54 x=244 y=63 width=29 height=47 xoffset=4 yoffset=11 xadvance=36 page=0 chnl=0
|
||||
char id=55 x=262 y=157 width=30 height=45 xoffset=3 yoffset=12 xadvance=36 page=0 chnl=0
|
||||
char id=56 x=273 y=63 width=29 height=47 xoffset=4 yoffset=11 xadvance=36 page=0 chnl=0
|
||||
char id=57 x=302 y=63 width=29 height=47 xoffset=4 yoffset=11 xadvance=36 page=0 chnl=0
|
||||
char id=58 x=501 y=63 width=9 height=36 xoffset=13 yoffset=22 xadvance=36 page=0 chnl=0
|
||||
char id=59 x=407 y=157 width=12 height=43 xoffset=10 yoffset=22 xadvance=36 page=0 chnl=0
|
||||
char id=60 x=310 y=202 width=29 height=33 xoffset=3 yoffset=18 xadvance=36 page=0 chnl=0
|
||||
char id=61 x=461 y=202 width=29 height=19 xoffset=3 yoffset=25 xadvance=36 page=0 chnl=0
|
||||
char id=62 x=339 y=202 width=29 height=33 xoffset=3 yoffset=18 xadvance=36 page=0 chnl=0
|
||||
char id=63 x=361 y=63 width=29 height=47 xoffset=3 yoffset=11 xadvance=36 page=0 chnl=0
|
||||
char id=64 x=221 y=0 width=36 height=51 xoffset=0 yoffset=12 xadvance=36 page=0 chnl=0
|
||||
char id=65 x=89 y=111 width=38 height=45 xoffset=-1 yoffset=12 xadvance=36 page=0 chnl=0
|
||||
char id=66 x=127 y=111 width=31 height=45 xoffset=3 yoffset=12 xadvance=36 page=0 chnl=0
|
||||
char id=67 x=87 y=63 width=33 height=47 xoffset=3 yoffset=11 xadvance=36 page=0 chnl=0
|
||||
char id=68 x=158 y=111 width=32 height=45 xoffset=3 yoffset=12 xadvance=36 page=0 chnl=0
|
||||
char id=69 x=190 y=111 width=27 height=45 xoffset=5 yoffset=12 xadvance=36 page=0 chnl=0
|
||||
char id=70 x=217 y=111 width=27 height=45 xoffset=6 yoffset=12 xadvance=36 page=0 chnl=0
|
||||
char id=71 x=120 y=63 width=31 height=47 xoffset=2 yoffset=11 xadvance=36 page=0 chnl=0
|
||||
char id=72 x=244 y=111 width=30 height=45 xoffset=3 yoffset=12 xadvance=36 page=0 chnl=0
|
||||
char id=73 x=274 y=111 width=25 height=45 xoffset=6 yoffset=12 xadvance=36 page=0 chnl=0
|
||||
char id=74 x=465 y=63 width=27 height=46 xoffset=3 yoffset=12 xadvance=36 page=0 chnl=0
|
||||
char id=75 x=299 y=111 width=31 height=45 xoffset=5 yoffset=12 xadvance=36 page=0 chnl=0
|
||||
char id=76 x=330 y=111 width=26 height=45 xoffset=6 yoffset=12 xadvance=36 page=0 chnl=0
|
||||
char id=77 x=356 y=111 width=31 height=45 xoffset=2 yoffset=12 xadvance=36 page=0 chnl=0
|
||||
char id=78 x=387 y=111 width=31 height=45 xoffset=3 yoffset=12 xadvance=36 page=0 chnl=0
|
||||
char id=79 x=151 y=63 width=33 height=47 xoffset=1 yoffset=11 xadvance=36 page=0 chnl=0
|
||||
char id=80 x=418 y=111 width=29 height=45 xoffset=4 yoffset=12 xadvance=36 page=0 chnl=0
|
||||
char id=81 x=30 y=0 width=33 height=59 xoffset=1 yoffset=11 xadvance=36 page=0 chnl=0
|
||||
char id=82 x=447 y=111 width=31 height=45 xoffset=4 yoffset=12 xadvance=36 page=0 chnl=0
|
||||
char id=83 x=184 y=63 width=30 height=47 xoffset=3 yoffset=11 xadvance=36 page=0 chnl=0
|
||||
char id=84 x=478 y=111 width=32 height=45 xoffset=2 yoffset=12 xadvance=36 page=0 chnl=0
|
||||
char id=85 x=0 y=111 width=31 height=46 xoffset=3 yoffset=12 xadvance=36 page=0 chnl=0
|
||||
char id=86 x=0 y=157 width=38 height=45 xoffset=-1 yoffset=12 xadvance=36 page=0 chnl=0
|
||||
char id=87 x=38 y=157 width=39 height=45 xoffset=-2 yoffset=12 xadvance=36 page=0 chnl=0
|
||||
char id=88 x=77 y=157 width=36 height=45 xoffset=0 yoffset=12 xadvance=36 page=0 chnl=0
|
||||
char id=89 x=113 y=157 width=37 height=45 xoffset=-1 yoffset=12 xadvance=36 page=0 chnl=0
|
||||
char id=90 x=150 y=157 width=32 height=45 xoffset=2 yoffset=12 xadvance=36 page=0 chnl=0
|
||||
char id=91 x=106 y=0 width=18 height=55 xoffset=11 yoffset=12 xadvance=36 page=0 chnl=0
|
||||
char id=92 x=318 y=157 width=26 height=45 xoffset=5 yoffset=12 xadvance=36 page=0 chnl=0
|
||||
char id=93 x=124 y=0 width=18 height=55 xoffset=7 yoffset=12 xadvance=36 page=0 chnl=0
|
||||
char id=94 x=368 y=202 width=32 height=30 xoffset=2 yoffset=11 xadvance=36 page=0 chnl=0
|
||||
char id=95 x=100 y=238 width=39 height=7 xoffset=-1 yoffset=60 xadvance=36 page=0 chnl=0
|
||||
char id=96 x=36 y=238 width=14 height=12 xoffset=11 yoffset=8 xadvance=36 page=0 chnl=0
|
||||
char id=97 x=419 y=157 width=29 height=36 xoffset=3 yoffset=22 xadvance=36 page=0 chnl=0
|
||||
char id=98 x=349 y=0 width=30 height=49 xoffset=4 yoffset=9 xadvance=36 page=0 chnl=0
|
||||
char id=99 x=448 y=157 width=29 height=36 xoffset=4 yoffset=22 xadvance=36 page=0 chnl=0
|
||||
char id=100 x=379 y=0 width=30 height=49 xoffset=3 yoffset=9 xadvance=36 page=0 chnl=0
|
||||
char id=101 x=477 y=157 width=30 height=36 xoffset=3 yoffset=22 xadvance=36 page=0 chnl=0
|
||||
char id=102 x=443 y=0 width=31 height=48 xoffset=4 yoffset=9 xadvance=36 page=0 chnl=0
|
||||
char id=103 x=257 y=0 width=32 height=50 xoffset=2 yoffset=22 xadvance=36 page=0 chnl=0
|
||||
char id=104 x=474 y=0 width=29 height=48 xoffset=4 yoffset=9 xadvance=36 page=0 chnl=0
|
||||
char id=105 x=0 y=63 width=28 height=48 xoffset=5 yoffset=9 xadvance=36 page=0 chnl=0
|
||||
char id=106 x=0 y=0 width=24 height=63 xoffset=2 yoffset=9 xadvance=36 page=0 chnl=0
|
||||
char id=107 x=28 y=63 width=31 height=48 xoffset=5 yoffset=9 xadvance=36 page=0 chnl=0
|
||||
char id=108 x=59 y=63 width=28 height=48 xoffset=5 yoffset=9 xadvance=36 page=0 chnl=0
|
||||
char id=109 x=58 y=202 width=33 height=35 xoffset=2 yoffset=22 xadvance=36 page=0 chnl=0
|
||||
char id=110 x=91 y=202 width=29 height=35 xoffset=4 yoffset=22 xadvance=36 page=0 chnl=0
|
||||
char id=111 x=0 y=202 width=31 height=36 xoffset=2 yoffset=22 xadvance=36 page=0 chnl=0
|
||||
char id=112 x=289 y=0 width=30 height=50 xoffset=4 yoffset=22 xadvance=36 page=0 chnl=0
|
||||
char id=113 x=319 y=0 width=30 height=50 xoffset=3 yoffset=22 xadvance=36 page=0 chnl=0
|
||||
char id=114 x=120 y=202 width=26 height=35 xoffset=7 yoffset=22 xadvance=36 page=0 chnl=0
|
||||
char id=115 x=31 y=202 width=27 height=36 xoffset=4 yoffset=22 xadvance=36 page=0 chnl=0
|
||||
char id=116 x=379 y=157 width=28 height=44 xoffset=3 yoffset=14 xadvance=36 page=0 chnl=0
|
||||
char id=117 x=146 y=202 width=29 height=35 xoffset=4 yoffset=23 xadvance=36 page=0 chnl=0
|
||||
char id=118 x=175 y=202 width=34 height=34 xoffset=1 yoffset=23 xadvance=36 page=0 chnl=0
|
||||
char id=119 x=209 y=202 width=40 height=34 xoffset=-2 yoffset=23 xadvance=36 page=0 chnl=0
|
||||
char id=120 x=249 y=202 width=34 height=34 xoffset=1 yoffset=23 xadvance=36 page=0 chnl=0
|
||||
char id=121 x=409 y=0 width=34 height=49 xoffset=1 yoffset=23 xadvance=36 page=0 chnl=0
|
||||
char id=122 x=283 y=202 width=27 height=34 xoffset=4 yoffset=23 xadvance=36 page=0 chnl=0
|
||||
char id=123 x=142 y=0 width=25 height=55 xoffset=6 yoffset=12 xadvance=36 page=0 chnl=0
|
||||
char id=124 x=24 y=0 width=6 height=63 xoffset=15 yoffset=9 xadvance=36 page=0 chnl=0
|
||||
char id=125 x=167 y=0 width=26 height=55 xoffset=5 yoffset=12 xadvance=36 page=0 chnl=0
|
||||
char id=126 x=50 y=238 width=29 height=12 xoffset=3 yoffset=29 xadvance=36 page=0 chnl=0
|
||||
kernings count=0
|
BIN
data/font/font.png
Normal file
After Width: | Height: | Size: 41 KiB |
28
data/shaders/fragment.frag
Normal file
@ -0,0 +1,28 @@
|
||||
#version 330 core
|
||||
|
||||
in vec3 objectColor;
|
||||
in vec3 vertexNormal;
|
||||
in vec3 worldPosition;
|
||||
|
||||
out vec4 color;
|
||||
|
||||
uniform vec3 ambientLight;
|
||||
|
||||
uniform vec3 lightColor0;
|
||||
uniform vec3 lightDirection0;
|
||||
|
||||
uniform vec3 lightColor1;
|
||||
uniform vec3 lightDirection1;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec3 fragNormal = normalize(vertexNormal);
|
||||
|
||||
vec3 fragLight0Dir = normalize(-(lightDirection0));
|
||||
vec3 fragLight1Dir = normalize(-(lightDirection1));
|
||||
|
||||
vec3 diffuseLight0 = max(dot(fragNormal, fragLight0Dir), 0.0) * lightColor0;
|
||||
vec3 diffuseLight1 = max(dot(fragNormal, fragLight1Dir), 0.0) * lightColor1;
|
||||
|
||||
color = vec4((diffuseLight0 + diffuseLight1 + ambientLight) * objectColor, 1.0f);
|
||||
}
|
12
data/shaders/skybox_fragment.frag
Normal file
@ -0,0 +1,12 @@
|
||||
#version 330 core
|
||||
|
||||
in vec3 textureCoordinates;
|
||||
|
||||
out vec4 color;
|
||||
|
||||
uniform samplerCube skyBoxTexture;
|
||||
|
||||
void main()
|
||||
{
|
||||
color = texture(skyBoxTexture, textureCoordinates);
|
||||
}
|
14
data/shaders/skybox_vertex.vert
Normal file
@ -0,0 +1,14 @@
|
||||
#version 330 core
|
||||
|
||||
layout (location = 0) in vec3 position;
|
||||
|
||||
out vec3 textureCoordinates;
|
||||
|
||||
uniform mat4 view;
|
||||
uniform mat4 projection;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = projection * view * vec4(position, 1.0f);
|
||||
textureCoordinates = position;
|
||||
}
|
17
data/shaders/text_fragment.frag
Normal file
@ -0,0 +1,17 @@
|
||||
#version 330 core
|
||||
|
||||
in vec2 texCoord;
|
||||
|
||||
out vec4 color;
|
||||
|
||||
uniform sampler2D fontTexture;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 TexColor = texture(fontTexture, texCoord);
|
||||
|
||||
if (TexColor.a < 0.1)
|
||||
discard;
|
||||
|
||||
color = TexColor;
|
||||
}
|
11
data/shaders/text_vertex.vert
Normal file
@ -0,0 +1,11 @@
|
||||
#version 330 core
|
||||
layout (location = 0) in vec3 position;
|
||||
layout (location = 1) in vec2 tex;
|
||||
|
||||
out vec2 texCoord;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(position, 1.0f);
|
||||
texCoord = tex;
|
||||
}
|
31
data/shaders/vertex.vert
Normal file
@ -0,0 +1,31 @@
|
||||
#version 330 core
|
||||
|
||||
layout (location = 0) in vec3 position;
|
||||
layout (location = 1) in vec3 normal;
|
||||
layout (location = 2) in vec3 color;
|
||||
|
||||
out vec3 objectColor;
|
||||
out vec3 vertexNormal;
|
||||
out vec3 worldPosition;
|
||||
|
||||
uniform mat4 model;
|
||||
uniform mat4 view;
|
||||
uniform mat4 projection;
|
||||
|
||||
uniform float time;
|
||||
uniform bool apocalypse;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = projection * view * model * vec4(position, 1.0f);
|
||||
|
||||
if (apocalypse)
|
||||
{
|
||||
gl_Position.x += sin(time);
|
||||
gl_Position.y += cos(time);
|
||||
}
|
||||
|
||||
objectColor = color;
|
||||
worldPosition = vec3(model * vec4(position, 1.0f));
|
||||
vertexNormal = normal;
|
||||
}
|
59
src/engine_assets.c
Normal file
@ -0,0 +1,59 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "engine_assets.h"
|
||||
|
||||
void
|
||||
LoadCubeTypeDefinitions(char* Path, CubeType* Types)
|
||||
{
|
||||
FILE *CubeTypeFile;
|
||||
|
||||
CubeTypeFile = fopen(Path, "rb");
|
||||
|
||||
if (!CubeTypeFile)
|
||||
{
|
||||
puts ("Cube Type file does not exist");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
char Buffer[1000];
|
||||
char Line[1000];
|
||||
|
||||
int ID;
|
||||
float rgb[3];
|
||||
|
||||
while (fgets(Buffer, 1000, CubeTypeFile) != 0)
|
||||
{
|
||||
int index = 0;
|
||||
int i = 0;
|
||||
|
||||
// Get the ID
|
||||
|
||||
for (; Buffer[index] != ' '; index++, i++)
|
||||
{
|
||||
Line[i] = Buffer[index];
|
||||
}
|
||||
|
||||
Line[i] = ' ';
|
||||
ID = atoi(Line);
|
||||
|
||||
// Get the color vector
|
||||
for (int k = 0; k < 3; k++)
|
||||
{
|
||||
for (index++, i = 0;
|
||||
Buffer[index] != ',' && Buffer[index] != '\n'
|
||||
&& Buffer[index] != ' ' && Buffer[index] != '\0';
|
||||
i++, index++)
|
||||
{
|
||||
Line[i] = Buffer[index];
|
||||
}
|
||||
|
||||
Line[i] = ' ';
|
||||
|
||||
rgb[k] = atof(Line);
|
||||
}
|
||||
|
||||
Types[ID].Color = Vec3f(rgb[0], rgb[1], rgb[2]);
|
||||
}
|
||||
|
||||
}
|
9
src/engine_assets.h
Normal file
@ -0,0 +1,9 @@
|
||||
#ifndef H_ENGINE_ASSETS
|
||||
#define H_ENGINE_ASSETS
|
||||
|
||||
#include "engine_cube.h"
|
||||
|
||||
void
|
||||
LoadCubeTypeDefinitions(char* Path, CubeType* Types);
|
||||
|
||||
#endif
|
BIN
src/engine_assets.o
Normal file
121
src/engine_camera.c
Normal file
@ -0,0 +1,121 @@
|
||||
#include "engine_camera.h"
|
||||
#include "engine_math.h"
|
||||
|
||||
mat4f_t GetPerspectiveProjection(PerspectiveProjection* Perspective)
|
||||
{
|
||||
mat4f_t ProjectionMatrix;
|
||||
|
||||
float AspectRatio = Perspective->Width / Perspective->Height;
|
||||
float TanFactor = tanf((DEG2RAD*Perspective->VerticalFov) / 2.0);
|
||||
|
||||
ProjectionMatrix.mat[0] = 1.0 / (AspectRatio * TanFactor);
|
||||
ProjectionMatrix.mat[1] = 0.0f;
|
||||
ProjectionMatrix.mat[2] = 0.0f;
|
||||
ProjectionMatrix.mat[3] = 0.0f;
|
||||
|
||||
ProjectionMatrix.mat[4] = 0.0f;
|
||||
ProjectionMatrix.mat[5] = (1.0 / TanFactor);
|
||||
ProjectionMatrix.mat[6] = 0.0f;
|
||||
ProjectionMatrix.mat[7] = 0.0f;
|
||||
|
||||
ProjectionMatrix.mat[8] = 0.0f;
|
||||
ProjectionMatrix.mat[9] = 0.0f;
|
||||
ProjectionMatrix.mat[10] = (Perspective->Near + Perspective->Far) /
|
||||
(Perspective->Near - Perspective->Far);
|
||||
ProjectionMatrix.mat[11] = -1.0f;
|
||||
|
||||
ProjectionMatrix.mat[12] = 0.0f;
|
||||
ProjectionMatrix.mat[13] = 0.0f;
|
||||
ProjectionMatrix.mat[14] = (2*Perspective->Far*Perspective->Near) /
|
||||
(Perspective->Near - Perspective->Far);
|
||||
ProjectionMatrix.mat[15] = 0.0f;
|
||||
|
||||
return ProjectionMatrix;
|
||||
}
|
||||
|
||||
mat4f_t GetGeneralView(GeneralCamera* Cam)
|
||||
{
|
||||
mat4f_t ViewMat;
|
||||
|
||||
vec3f_t w = NormalizeVec3f(SubtractVec3f(Cam->LookAt, Cam->Origin));
|
||||
vec3f_t u = NormalizeVec3f(CrossProductVec3f(Cam->Up, w));
|
||||
vec3f_t v = CrossProductVec3f(w, u);
|
||||
|
||||
ViewMat.mat[0] = u.x;
|
||||
ViewMat.mat[1] = v.x;
|
||||
ViewMat.mat[2] = w.x;
|
||||
ViewMat.mat[3] = 0.0f;
|
||||
|
||||
ViewMat.mat[4] = u.y;
|
||||
ViewMat.mat[5] = v.y;
|
||||
ViewMat.mat[6] = w.y;
|
||||
ViewMat.mat[7] = 0.0f;
|
||||
|
||||
ViewMat.mat[8] = u.z;
|
||||
ViewMat.mat[9] = v.z;
|
||||
ViewMat.mat[10] = w.z;
|
||||
ViewMat.mat[11] = 0.0f;
|
||||
|
||||
ViewMat.mat[12] = -DotProductVec3f(u, Cam->Origin);
|
||||
ViewMat.mat[13] = -DotProductVec3f(v, Cam->Origin);
|
||||
ViewMat.mat[14] = -DotProductVec3f(w, Cam->Origin);
|
||||
ViewMat.mat[15] = 1.0f;
|
||||
|
||||
return ViewMat;
|
||||
|
||||
}
|
||||
|
||||
mat4f_t GetFirstPersonView(FirstPersonCamera* Cam)
|
||||
{
|
||||
mat4f_t ViewMat;
|
||||
|
||||
float PitchCos = cos(DEG2RAD * Cam->Pitch);
|
||||
float PitchSin = sin(DEG2RAD * Cam->Pitch);
|
||||
float YawCos = cos(DEG2RAD * Cam->Yaw);
|
||||
float YawSin = sin(DEG2RAD * Cam->Yaw);
|
||||
|
||||
vec3f_t u = Vec3f(YawCos, 0.0f, YawSin);
|
||||
vec3f_t v = Vec3f(PitchSin * YawSin, PitchCos, -(PitchSin * YawCos));
|
||||
vec3f_t w = Vec3f(-(PitchCos * YawSin), PitchSin, PitchCos * YawCos);
|
||||
|
||||
ViewMat.mat[0] = u.x;
|
||||
ViewMat.mat[1] = v.x;
|
||||
ViewMat.mat[2] = w.x;
|
||||
ViewMat.mat[3] = 0.0f;
|
||||
|
||||
ViewMat.mat[4] = u.y;
|
||||
ViewMat.mat[5] = v.y;
|
||||
ViewMat.mat[6] = w.y;
|
||||
ViewMat.mat[7] = 0.0f;
|
||||
|
||||
ViewMat.mat[8] = u.z;
|
||||
ViewMat.mat[9] = v.z;
|
||||
ViewMat.mat[10] = w.z;
|
||||
ViewMat.mat[11] = 0.0f;
|
||||
|
||||
ViewMat.mat[12] = -DotProductVec3f(u, Cam->Position);
|
||||
ViewMat.mat[13] = -DotProductVec3f(v, Cam->Position);
|
||||
ViewMat.mat[14] = -DotProductVec3f(w, Cam->Position);
|
||||
ViewMat.mat[15] = 1.0f;
|
||||
|
||||
return ViewMat;
|
||||
}
|
||||
|
||||
vec3f_t FPCamFront(FirstPersonCamera* Cam)
|
||||
{
|
||||
vec3f_t Front;
|
||||
|
||||
Front.x = (cos(DEG2RAD * Cam->Pitch)*sin(DEG2RAD * Cam->Yaw));
|
||||
Front.y = -sin(DEG2RAD * Cam->Pitch);
|
||||
Front.z = -(cos(DEG2RAD * Cam->Pitch) * cos(DEG2RAD * Cam->Yaw));
|
||||
|
||||
return NormalizeVec3f(Front);
|
||||
|
||||
}
|
||||
|
||||
vec3f_t FPCamRight(vec3f_t Front)
|
||||
{
|
||||
vec3f_t Up = Vec3f(0.0f, 1.0f, 0.0f);
|
||||
|
||||
return CrossProductVec3f(NormalizeVec3f(Front), Up);
|
||||
}
|
50
src/engine_camera.h
Normal file
@ -0,0 +1,50 @@
|
||||
#ifndef H_ENGINE_CAMERA
|
||||
#define H_ENGINE_CAMERA
|
||||
|
||||
#include "engine_math.h"
|
||||
|
||||
typedef struct
|
||||
GeneralCamera
|
||||
{
|
||||
|
||||
vec3f_t Origin;
|
||||
vec3f_t LookAt;
|
||||
vec3f_t Up;
|
||||
|
||||
} GeneralCamera;
|
||||
|
||||
typedef struct
|
||||
FirstPersonCamera
|
||||
{
|
||||
|
||||
vec3f_t Position;
|
||||
float Yaw;
|
||||
float Pitch;
|
||||
|
||||
} FirstPersonCamera;
|
||||
|
||||
typedef struct
|
||||
PerspectiveProjection
|
||||
{
|
||||
|
||||
float Width;
|
||||
float Height;
|
||||
|
||||
float VerticalFov;
|
||||
|
||||
float Near;
|
||||
float Far;
|
||||
|
||||
} PerspectiveProjection;
|
||||
|
||||
mat4f_t GetPerspectiveProjection(PerspectiveProjection* Perspective);
|
||||
|
||||
mat4f_t GetGeneralView(GeneralCamera* Cam);
|
||||
|
||||
mat4f_t GetFirstPersonView(FirstPersonCamera* Cam);
|
||||
|
||||
vec3f_t FPCamFront(FirstPersonCamera* Cam);
|
||||
|
||||
vec3f_t FPCamRight(vec3f_t Front);
|
||||
|
||||
#endif
|
BIN
src/engine_camera.o
Normal file
359
src/engine_chunk.c
Normal file
@ -0,0 +1,359 @@
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "engine_chunk.h"
|
||||
#include "engine_renderer.h"
|
||||
|
||||
void
|
||||
InitializeChunk(Chunk* Chk, int size, vec3f_t Transform)
|
||||
{
|
||||
Chk->Transform.x = Transform.x;
|
||||
Chk->Transform.y = Transform.y;
|
||||
Chk->Transform.z = Transform.z;
|
||||
|
||||
Chk->ChunkDimension = size;
|
||||
|
||||
Chk->Grid = (Cube***)malloc(size * sizeof(Cube**));
|
||||
Chk->ActiveCubes = 0;
|
||||
|
||||
Cube** YData = (Cube**)malloc(size * size * sizeof(Cube*));
|
||||
Cube* ZData = (Cube*)malloc(size * size * size * sizeof(Cube));
|
||||
|
||||
int CubeID = rand() % 3;
|
||||
|
||||
for (int x = 0; x < size; x++)
|
||||
{
|
||||
Chk->Grid[x] = YData + (x * size);
|
||||
|
||||
for (int y = 0; y < size; y++)
|
||||
{
|
||||
Chk->Grid[x][y] = ZData + (x*size*size) + (y*size);
|
||||
|
||||
for (int z = 0; z < size; z++)
|
||||
{
|
||||
//SetActive(&Chk->Grid[x][y][z], (rand() <= 1500));
|
||||
SetActive(&Chk->Grid[x][y][z], 1);
|
||||
SetType(&Chk->Grid[x][y][z], CubeID);
|
||||
|
||||
if (GetActive(&Chk->Grid[x][y][z]))
|
||||
{
|
||||
Chk->ActiveCubes++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
FreeChunk(Chunk* Chk)
|
||||
{
|
||||
free(**Chk->Grid);
|
||||
free(*Chk->Grid);
|
||||
free(Chk->Grid);
|
||||
}
|
||||
|
||||
void
|
||||
GreedyMesh(Chunk* Chk, CubeType* CubeTypes,
|
||||
float* RenderBuffer, int* VertexCount)
|
||||
{
|
||||
*VertexCount = 0;
|
||||
Chk->MeshVertexCount = 0;
|
||||
|
||||
int CubeFace;
|
||||
|
||||
int FrontFace, BackFace,
|
||||
Front, Back;
|
||||
|
||||
int u, v;
|
||||
|
||||
int index[] = {0, 0, 0};
|
||||
int disp[] = {0, 0, 0};
|
||||
|
||||
int MaskSize = (Chk->ChunkDimension * Chk->ChunkDimension);
|
||||
int* Mask = malloc(sizeof(int)*MaskSize);
|
||||
|
||||
int MaskIndex = 0;
|
||||
|
||||
int QWidth, QHeight;
|
||||
|
||||
for (FrontFace = 1, BackFace = 0; !(FrontFace && BackFace); )
|
||||
{
|
||||
for (int dim = 0; dim < 3; dim++)
|
||||
{
|
||||
|
||||
// Determine CubeFace
|
||||
if (BackFace)
|
||||
{
|
||||
switch (dim)
|
||||
{
|
||||
case 0:
|
||||
CubeFace = LEFT;
|
||||
break;
|
||||
case 1:
|
||||
CubeFace = BOTTOM;
|
||||
break;
|
||||
case 2:
|
||||
CubeFace = BACK;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (FrontFace)
|
||||
{
|
||||
switch (dim)
|
||||
{
|
||||
case 0:
|
||||
CubeFace = RIGHT;
|
||||
break;
|
||||
case 1:
|
||||
CubeFace = TOP;
|
||||
break;
|
||||
case 2:
|
||||
CubeFace = FORWARD;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
u = (dim+1) % 3;
|
||||
v = (dim+2) % 3;
|
||||
|
||||
index[0] = 0;
|
||||
index[1] = 0;
|
||||
index[2] = 0;
|
||||
|
||||
disp[0] = 0;
|
||||
disp[1] = 0;
|
||||
disp[2] = 0;
|
||||
disp[dim] = 1;
|
||||
|
||||
for (index[dim] = -1; index[dim] < Chk->ChunkDimension; )
|
||||
{
|
||||
// Reset the mask
|
||||
MaskIndex = 0;
|
||||
|
||||
// Create a mask for each two dimensional plane
|
||||
for (index[u] = 0; index[u] < Chk->ChunkDimension; index[u]++)
|
||||
{
|
||||
for (index[v] = 0; index[v] < Chk->ChunkDimension; index[v]++)
|
||||
{
|
||||
Front = (index[dim] >= 0) ?
|
||||
GetActive(&Chk->Grid[index[0]][index[1]][index[2]]) : 0;
|
||||
|
||||
Back = (index[dim] < Chk->ChunkDimension - 1) ?
|
||||
GetActive(&Chk->Grid[index[0]+disp[0]]
|
||||
[index[1]+disp[1]]
|
||||
[index[2]+disp[2]]) : 0;
|
||||
|
||||
int FrontType = -1;
|
||||
int BackType = -1;
|
||||
|
||||
if (Front && index[dim] >= 0)
|
||||
{
|
||||
FrontType = GetType(&Chk->Grid[index[0]][index[1]][index[2]]);
|
||||
}
|
||||
if (Back && index[dim] < Chk->ChunkDimension - 1)
|
||||
{
|
||||
BackType = GetType(&Chk->Grid[index[0]+disp[0]][index[1]+disp[1]][index[2]+disp[2]]);
|
||||
}
|
||||
|
||||
Mask[MaskIndex++] = (Front != 0 && Back != 0 && FrontType == BackType) ? -1 :
|
||||
BackFace ? BackType : FrontType;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
index[dim]++;
|
||||
|
||||
// Generate mesh
|
||||
MaskIndex = 0;
|
||||
|
||||
for (int i = 0; i < Chk->ChunkDimension; i++)
|
||||
{
|
||||
for (int j = 0; j < Chk->ChunkDimension; )
|
||||
{
|
||||
if (Mask[MaskIndex] != -1)
|
||||
{
|
||||
|
||||
// Width of Quad
|
||||
for (QWidth = 1;
|
||||
(Mask[MaskIndex + QWidth] != -1 && Mask[MaskIndex + QWidth] == Mask[MaskIndex] && j + QWidth < Chk->ChunkDimension);
|
||||
++QWidth) {}
|
||||
|
||||
// Height of Quad
|
||||
int Done = 0;
|
||||
|
||||
for (QHeight = 1; i + QHeight < Chk->ChunkDimension; QHeight++)
|
||||
{
|
||||
for (int k = 0; k < QWidth; k++)
|
||||
{
|
||||
if (Mask[MaskIndex + k + QHeight*Chk->ChunkDimension] == -1 || Mask[MaskIndex + k + QHeight*Chk->ChunkDimension] != Mask[MaskIndex])
|
||||
{
|
||||
Done = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (Done)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
index[u] = i;
|
||||
index[v] = j;
|
||||
|
||||
int index_Du[] = {0, 0, 0};
|
||||
int index_Dv[] = {0, 0, 0};
|
||||
|
||||
index_Du[u] = QHeight;
|
||||
index_Dv[v] = QWidth;
|
||||
|
||||
AddQuad(Chk, CubeFace,
|
||||
Vec3f(index[0], index[1], index[2]),
|
||||
Vec3f(index[0] + index_Dv[0],
|
||||
index[1] + index_Dv[1],
|
||||
index[2] + index_Dv[2]),
|
||||
Vec3f(index[0] + index_Du[0] + index_Dv[0],
|
||||
index[1] + index_Du[1] + index_Dv[1],
|
||||
index[2] + index_Du[2] + index_Dv[2]),
|
||||
Vec3f(index[0] + index_Du[0],
|
||||
index[1] + index_Du[1],
|
||||
index[2] + index_Du[2]),
|
||||
Mask[MaskIndex], CubeTypes,
|
||||
RenderBuffer, VertexCount);
|
||||
|
||||
// Munch away at the part of the mask that we just consumed
|
||||
for (int t = 0; t < QHeight; t++)
|
||||
{
|
||||
for (int s = 0; s < QWidth; s++)
|
||||
{
|
||||
Mask[MaskIndex + s + t*Chk->ChunkDimension] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
MaskIndex += QWidth;
|
||||
j += QWidth;
|
||||
}
|
||||
else
|
||||
{
|
||||
MaskIndex++;
|
||||
j++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (FrontFace)
|
||||
{
|
||||
BackFace = 1;
|
||||
FrontFace = 0;
|
||||
}
|
||||
else if (BackFace)
|
||||
{
|
||||
FrontFace = 1;
|
||||
}
|
||||
}
|
||||
|
||||
free(Mask);
|
||||
}
|
||||
|
||||
void
|
||||
ChunkHeightFill(int x, int z, int height, Chunk* Chk)
|
||||
{
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
if (!GetActive(&Chk->Grid[x][y][z]))
|
||||
{
|
||||
(Chk->ActiveCubes)++;
|
||||
SetActive(&Chk->Grid[x][y][z], 1);
|
||||
}
|
||||
}
|
||||
for (int y = height; y < Chk->ChunkDimension; y++)
|
||||
{
|
||||
if (GetActive(&Chk->Grid[x][y][z]))
|
||||
{
|
||||
(Chk->ActiveCubes)--;
|
||||
SetActive(&Chk->Grid[x][y][z], 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AddQuad(Chunk* Chk, int Side,
|
||||
vec3f_t P1, vec3f_t P2,
|
||||
vec3f_t P3, vec3f_t P4,
|
||||
int CubeID, CubeType* Types,
|
||||
float* RenderBuffer, int* VertexCount)
|
||||
{
|
||||
|
||||
vec3f_t Normal;
|
||||
|
||||
switch(Side)
|
||||
{
|
||||
case LEFT:
|
||||
Normal = Vec3f(-1.0f, 0.0f, 0.0f);
|
||||
break;
|
||||
case RIGHT:
|
||||
Normal = Vec3f(1.0f, 0.0f, 0.0f);
|
||||
break;
|
||||
case BACK:
|
||||
Normal = Vec3f(0.0f, 0.0f, -1.0f);
|
||||
break;
|
||||
case FORWARD:
|
||||
Normal = Vec3f(0.0f, 0.0f, 1.0f);
|
||||
break;
|
||||
case TOP:
|
||||
Normal = Vec3f(0.0f, 1.0f, 0.0f);
|
||||
break;
|
||||
case BOTTOM:
|
||||
Normal = Vec3f(0.0f, -1.0f, 0.0f);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
GenerateQuadFace(RenderBuffer+(RENDER_FLOATS_PER_CUBE_VERTEX*
|
||||
*VertexCount),
|
||||
P1, P2, P3, P4,
|
||||
Normal,
|
||||
Types[CubeID].Color);
|
||||
|
||||
*VertexCount += 6;
|
||||
Chk->MeshVertexCount += 6;
|
||||
|
||||
}
|
||||
|
||||
Cube*
|
||||
GetCubeFromPosition(Chunk* Chk, vec3f_t Position)
|
||||
{
|
||||
|
||||
vec3f_t Max = Vec3f(Chk->Transform.x + Chk->ChunkDimension,
|
||||
Chk->Transform.y + Chk->ChunkDimension,
|
||||
Chk->Transform.z + Chk->ChunkDimension);
|
||||
|
||||
if (Position.x < Chk->Transform.x || Position.x >= Max.x) return(0);
|
||||
if (Position.y < Chk->Transform.y || Position.y >= Max.y) return(0);
|
||||
if (Position.z < Chk->Transform.z || Position.z >= Max.z) return(0);
|
||||
|
||||
return (&Chk->Grid[(int)floor(Position.x)][(int)floor(Position.y)][(int)floor(Position.z)]);
|
||||
}
|
||||
|
||||
|
||||
// TODO: Get the height of the chunk at a certain X, Z position
|
||||
int
|
||||
GetChunkHeight(Chunk* Chk, int X, int Z)
|
||||
{
|
||||
int Height;
|
||||
for (Height = 0; Height < Chk->ChunkDimension; Height++)
|
||||
{
|
||||
if (!GetActive(&Chk->Grid[X][Height][Z]))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (Height);
|
||||
}
|
71
src/engine_chunk.h
Normal file
@ -0,0 +1,71 @@
|
||||
#ifndef H_ENGINE_CHUNK
|
||||
#define H_ENGINE_CHUNK
|
||||
|
||||
#include <GL/glew.h>
|
||||
|
||||
#include "engine_main.h"
|
||||
#include "engine_cube.h"
|
||||
|
||||
global int DEFAULT_CHUNK_SIZE = 32;
|
||||
|
||||
global int RENDER_FLOATS_PER_CUBE_VERTEX = 9;
|
||||
|
||||
typedef struct
|
||||
Chunk
|
||||
{
|
||||
|
||||
Cube*** Grid;
|
||||
int ChunkDimension;
|
||||
int ActiveCubes;
|
||||
|
||||
vec3f_t Transform;
|
||||
|
||||
int MeshVertexCount;
|
||||
|
||||
GLuint VAO;
|
||||
GLuint VBO;
|
||||
|
||||
float PerlinXSeed;
|
||||
float PerlinZSeed;
|
||||
|
||||
int YLevel;
|
||||
|
||||
} Chunk;
|
||||
|
||||
enum CubeFaces
|
||||
{
|
||||
LEFT,
|
||||
RIGHT,
|
||||
FORWARD,
|
||||
BACK,
|
||||
TOP,
|
||||
BOTTOM
|
||||
};
|
||||
|
||||
void
|
||||
InitializeChunk(Chunk* Chk, int size, vec3f_t Transform);
|
||||
|
||||
void
|
||||
FreeChunk(Chunk* Chk);
|
||||
|
||||
void
|
||||
GreedyMesh(Chunk* Chk, CubeType* CubeTypes,
|
||||
float* RenderBuffer, int* VertexCount);
|
||||
|
||||
void
|
||||
ChunkHeightFill(int x, int z, int height, Chunk* Chk);
|
||||
|
||||
void
|
||||
AddQuad(Chunk* Chk, int Side,
|
||||
vec3f_t P1, vec3f_t P2,
|
||||
vec3f_t P3, vec3f_t P4,
|
||||
int CubeID, CubeType* Types,
|
||||
float* RenderBuffer, int* VertexCount);
|
||||
|
||||
Cube*
|
||||
GetCubeFromPosition(Chunk* Chk, vec3f_t Position);
|
||||
|
||||
int
|
||||
GetChunkHeight(Chunk* Chk, int X, int Z);
|
||||
|
||||
#endif
|
BIN
src/engine_chunk.o
Normal file
43
src/engine_clock.c
Normal file
@ -0,0 +1,43 @@
|
||||
#include <string.h>
|
||||
#include <SDL2/SDL_timer.h>
|
||||
|
||||
#include "engine_clock.h"
|
||||
|
||||
void
|
||||
StartClock(GameClock* C)
|
||||
{
|
||||
C->LastTime = SDL_GetTicks();
|
||||
memset(C->FrameTimes, 0, FRAME_COUNT);
|
||||
C->FrameCount = 0;
|
||||
C->FrameIndex = 0;
|
||||
}
|
||||
|
||||
void
|
||||
UpdateClock(GameClock* C)
|
||||
{
|
||||
float CurrentTime = SDL_GetTicks();
|
||||
|
||||
C->Time = CurrentTime;
|
||||
|
||||
C->DeltaTime = CurrentTime - C->LastTime;
|
||||
C->LastTime = CurrentTime;
|
||||
|
||||
C->FrameTimes[C->FrameIndex] = C->DeltaTime;
|
||||
if (C->FrameCount < FRAME_COUNT)
|
||||
{
|
||||
C->FrameCount++;
|
||||
}
|
||||
|
||||
C->FrameIndex = (C->FrameIndex + 1) % FRAME_COUNT;
|
||||
|
||||
float Sum = 0;
|
||||
|
||||
for (int i = 0; i < C->FrameCount; i++)
|
||||
{
|
||||
Sum += C->FrameTimes[i];
|
||||
}
|
||||
|
||||
Sum /= C->FrameCount;
|
||||
C->FPS = 1000.0 / Sum;
|
||||
|
||||
}
|
25
src/engine_clock.h
Normal file
@ -0,0 +1,25 @@
|
||||
#ifndef H_ENGINE_CLOCK
|
||||
#define H_ENGINE_CLOCK
|
||||
|
||||
#define FRAME_COUNT 10
|
||||
|
||||
typedef struct
|
||||
GameClock
|
||||
{
|
||||
|
||||
float Time;
|
||||
float LastTime;
|
||||
float DeltaTime;
|
||||
unsigned int FrameTimes[FRAME_COUNT];
|
||||
int FrameCount;
|
||||
int FrameIndex;
|
||||
float FPS;
|
||||
} GameClock;
|
||||
|
||||
void
|
||||
StartClock(GameClock* C);
|
||||
|
||||
void
|
||||
UpdateClock(GameClock* C);
|
||||
|
||||
#endif
|
BIN
src/engine_clock.o
Normal file
239
src/engine_console.c
Normal file
@ -0,0 +1,239 @@
|
||||
#include "engine_console.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
void
|
||||
InitializeVEConsole(VEConsole* Console,
|
||||
CubeWorld* World, CubeType* CubeTypes)
|
||||
{
|
||||
Console->Enabled = 0;
|
||||
Console->WorldRef = World;
|
||||
Console->CubeTypeRef = CubeTypes;
|
||||
memset(Console->CmdBuffer, 0, sizeof(Console->CmdBuffer));
|
||||
StopCapturingTextInput();
|
||||
}
|
||||
|
||||
void
|
||||
UpdateVEConsole(VEConsole* Console, InputSDL* Input)
|
||||
{
|
||||
if (WasKeyPressed(Input, K_TILDE))
|
||||
{
|
||||
Console->Enabled = (!Console->Enabled);
|
||||
if (Console->Enabled)
|
||||
{
|
||||
StartCapturingTextInput();
|
||||
}
|
||||
else
|
||||
{
|
||||
CloseVEConsole(Console, Input);
|
||||
}
|
||||
}
|
||||
if (Console->Enabled)
|
||||
{
|
||||
if (WasKeyPressed(Input, K_ENTER))
|
||||
{
|
||||
int Result = ParseVEConsoleCommand(Console);
|
||||
memset(Console->CmdBuffer, '\0', sizeof(Console->CmdBuffer));
|
||||
if (!Result)
|
||||
{
|
||||
sprintf(Console->CmdBuffer, "Error with command");
|
||||
}
|
||||
if (Result)
|
||||
{
|
||||
CloseVEConsole(Console, Input);
|
||||
}
|
||||
}
|
||||
else if (WasKeyPressed(Input, K_BACKSPACE))
|
||||
{
|
||||
int BIndex = 0;
|
||||
while (BIndex < MAX_COMMAND_BUFFER && Console->CmdBuffer[BIndex] != '\0')
|
||||
{
|
||||
BIndex++;
|
||||
}
|
||||
if (BIndex != 0)
|
||||
{
|
||||
Console->CmdBuffer[BIndex-1] = '\0';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
char Text[50];
|
||||
memset(Text, '\0', sizeof(Text));
|
||||
PullTextInput(Input, Text);
|
||||
sprintf(Console->CmdBuffer, "%s%s", Console->CmdBuffer, Text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CloseVEConsole(VEConsole* Console, InputSDL* Input)
|
||||
{
|
||||
Console->Enabled = 0;
|
||||
StopCapturingTextInput();
|
||||
PullTextInput(Input, 0);
|
||||
memset(Console->CmdBuffer, '\0', sizeof(Console->CmdBuffer));
|
||||
}
|
||||
|
||||
int
|
||||
ParseVEConsoleCommand(VEConsole* Console)
|
||||
{
|
||||
int Success = 0;
|
||||
int Index = 0;
|
||||
int BufIndex = 0;
|
||||
|
||||
int CmdMode = 0;
|
||||
int ArgIndex = 0;
|
||||
float Args[4];
|
||||
|
||||
int RebuildArgs[3];
|
||||
|
||||
char Buf[100];
|
||||
memset(Buf, '\0', sizeof(Buf));
|
||||
|
||||
while (Index < MAX_COMMAND_BUFFER && Console->CmdBuffer[Index] != '\0')
|
||||
{
|
||||
if (Console->CmdBuffer[Index] != '\0')
|
||||
{
|
||||
if (CmdMode == 1)
|
||||
{
|
||||
if (Console->CmdBuffer[Index] != ',')
|
||||
{
|
||||
Buf[BufIndex] = Console->CmdBuffer[Index];
|
||||
BufIndex++;
|
||||
}
|
||||
if (Console->CmdBuffer[Index] == ',' || Console->CmdBuffer[Index] == ';')
|
||||
{
|
||||
Args[ArgIndex] = atof(Buf);
|
||||
ArgIndex++;
|
||||
BufIndex = 0;
|
||||
memset(Buf, '\0', sizeof(Buf));
|
||||
}
|
||||
if (ArgIndex == 4)
|
||||
{
|
||||
Success = 1;
|
||||
ReseedWorld(Console->WorldRef, Console->CubeTypeRef,
|
||||
Args[0], Args[1], 0.01f, Args[2], Args[3]);
|
||||
}
|
||||
}
|
||||
else if (CmdMode == 2)
|
||||
{
|
||||
VEResumeMusic();
|
||||
Success = 1;
|
||||
}
|
||||
else if (CmdMode == 3)
|
||||
{
|
||||
VEPauseMusic();
|
||||
Success = 1;
|
||||
}
|
||||
else if (CmdMode == 4)
|
||||
{
|
||||
Console->WorldRef->DayNightCycle = 1;
|
||||
Success = 1;
|
||||
}
|
||||
else if (CmdMode == 5)
|
||||
{
|
||||
Console->WorldRef->DayNightCycle = 0;
|
||||
Success = 1;
|
||||
}
|
||||
else if (CmdMode == 6)
|
||||
{
|
||||
Console->WorldRef->Apocalypse = 1;
|
||||
Success = 1;
|
||||
}
|
||||
else if (CmdMode == 7)
|
||||
{
|
||||
Console->WorldRef->Apocalypse = 0;
|
||||
Success = 1;
|
||||
}
|
||||
else if (CmdMode == 8)
|
||||
{
|
||||
Console->WorldRef->Spheres = 1;
|
||||
Success = 1;
|
||||
}
|
||||
else if (CmdMode == 9)
|
||||
{
|
||||
Console->WorldRef->Spheres = 0;
|
||||
Success = 1;
|
||||
}
|
||||
else if (CmdMode == 10)
|
||||
{
|
||||
if (Console->CmdBuffer[Index] != ',')
|
||||
{
|
||||
Buf[BufIndex] = Console->CmdBuffer[Index];
|
||||
BufIndex++;
|
||||
}
|
||||
if (Console->CmdBuffer[Index] == ',' || Console->CmdBuffer[Index] == ';')
|
||||
{
|
||||
RebuildArgs[ArgIndex] = atoi(Buf);
|
||||
ArgIndex++;
|
||||
BufIndex = 0;
|
||||
memset(Buf, '\0', sizeof(Buf));
|
||||
}
|
||||
if (ArgIndex == 3)
|
||||
{
|
||||
Success = 1;
|
||||
RedoWorld(Console->WorldRef,
|
||||
RebuildArgs[0],
|
||||
RebuildArgs[1],
|
||||
RebuildArgs[2],
|
||||
32,
|
||||
1.0, 1.0, 0.01, 6, 0.5f);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Console->CmdBuffer[Index] != ':')
|
||||
{
|
||||
Buf[Index] = Console->CmdBuffer[Index];
|
||||
}
|
||||
if (Console->CmdBuffer[Index] == ':')
|
||||
{
|
||||
if (!strcmp(Buf, "hatch"))
|
||||
{
|
||||
CmdMode = 1;
|
||||
}
|
||||
if (!strcmp(Buf, "voxel_dj"))
|
||||
{
|
||||
CmdMode = 2;
|
||||
}
|
||||
if (!strcmp(Buf, "sound_of_silence"))
|
||||
{
|
||||
CmdMode = 3;
|
||||
}
|
||||
if (!strcmp(Buf, "sands_of_time"))
|
||||
{
|
||||
CmdMode = 4;
|
||||
}
|
||||
if (!strcmp(Buf, "time_goes_so_fast"))
|
||||
{
|
||||
CmdMode = 5;
|
||||
}
|
||||
if (!strcmp(Buf, "start_the_apocalypse"))
|
||||
{
|
||||
CmdMode = 6;
|
||||
}
|
||||
if (!strcmp(Buf, "have_mercy"))
|
||||
{
|
||||
CmdMode = 7;
|
||||
}
|
||||
if (!strcmp(Buf, "show_sphere"))
|
||||
{
|
||||
CmdMode = 8;
|
||||
}
|
||||
if (!strcmp(Buf, "unshow_sphere"))
|
||||
{
|
||||
CmdMode = 9;
|
||||
}
|
||||
if (!strcmp(Buf, "we_can_rebuild_it"))
|
||||
{
|
||||
CmdMode = 10;
|
||||
}
|
||||
memset(Buf, '\0', sizeof(Buf));
|
||||
}
|
||||
}
|
||||
}
|
||||
Index++;
|
||||
}
|
||||
|
||||
return (Success);
|
||||
}
|
31
src/engine_console.h
Normal file
@ -0,0 +1,31 @@
|
||||
#ifndef H_ENGINE_CONSOLE
|
||||
#define H_ENGINE_CONSOLE
|
||||
|
||||
#include "engine_world.h"
|
||||
#include "engine_sdl.h"
|
||||
|
||||
#define MAX_COMMAND_BUFFER 500
|
||||
|
||||
typedef struct
|
||||
VEConsole
|
||||
{
|
||||
int Enabled;
|
||||
char CmdBuffer[MAX_COMMAND_BUFFER];
|
||||
CubeWorld* WorldRef;
|
||||
CubeType* CubeTypeRef;
|
||||
} VEConsole;
|
||||
|
||||
void
|
||||
InitializeVEConsole(VEConsole* Console,
|
||||
CubeWorld* World, CubeType* CubeTypes);
|
||||
|
||||
void
|
||||
UpdateVEConsole(VEConsole* Console, InputSDL* Input);
|
||||
|
||||
void
|
||||
CloseVEConsole(VEConsole* Console, InputSDL* Input);
|
||||
|
||||
int
|
||||
ParseVEConsoleCommand(VEConsole* Console);
|
||||
|
||||
#endif
|
BIN
src/engine_console.o
Normal file
117
src/engine_cube.c
Normal file
@ -0,0 +1,117 @@
|
||||
#include "engine_cube.h"
|
||||
#include "engine_renderer.h"
|
||||
|
||||
void
|
||||
SetActive(Cube* Cube, unsigned int ActiveFlag)
|
||||
{
|
||||
uint8_t InfoFill;
|
||||
|
||||
InfoFill = (Cube->Info >> 1);
|
||||
InfoFill = (Cube->Info << 1);
|
||||
InfoFill = (InfoFill | ActiveFlag);
|
||||
|
||||
Cube->Info = InfoFill;
|
||||
}
|
||||
|
||||
void
|
||||
SetType(Cube* Cube, unsigned int TypeFlag)
|
||||
{
|
||||
unsigned int ActiveFlag;
|
||||
|
||||
ActiveFlag = (Cube->Info & 1);
|
||||
Cube->Info = TypeFlag;
|
||||
Cube->Info = ((Cube->Info << 1) | ActiveFlag);
|
||||
}
|
||||
|
||||
int
|
||||
GetActive(Cube *Cube)
|
||||
{
|
||||
return (Cube->Info & 1);
|
||||
}
|
||||
|
||||
int
|
||||
GetType(Cube *Cube)
|
||||
{
|
||||
return (Cube->Info >> 1);
|
||||
}
|
||||
|
||||
void
|
||||
GenerateCube(float* vertices,
|
||||
vec3f_t* position,
|
||||
float dimension)
|
||||
{
|
||||
|
||||
vec3f_t P1 = Vec3f(dimension*position->x,
|
||||
dimension*position->y,
|
||||
dimension*position->z);
|
||||
|
||||
vec3f_t P2 = Vec3f(dimension*position->x,
|
||||
dimension*position->y + dimension,
|
||||
dimension*position->z);
|
||||
|
||||
vec3f_t P3 = Vec3f(dimension*position->x + dimension,
|
||||
dimension*position->y + dimension,
|
||||
dimension*position->z);
|
||||
vec3f_t P4 = Vec3f(dimension*position->x + dimension,
|
||||
dimension*position->y,
|
||||
dimension*position->z);
|
||||
|
||||
vec3f_t P5 = Vec3f(dimension*position->x,
|
||||
dimension*position->y,
|
||||
dimension*position->z + dimension);
|
||||
|
||||
vec3f_t P6 = Vec3f(dimension*position->x,
|
||||
dimension*position->y + dimension,
|
||||
dimension*position->z + dimension);
|
||||
|
||||
vec3f_t P7 = Vec3f(dimension*position->x + dimension,
|
||||
dimension*position->y + dimension,
|
||||
dimension*position->z + dimension);
|
||||
|
||||
vec3f_t P8 = Vec3f(dimension*position->x + dimension,
|
||||
dimension*position->y,
|
||||
dimension*position->z + dimension);
|
||||
|
||||
vec3f_t Normal = Vec3f(0.0f, 0.0f, -1.0f);
|
||||
|
||||
GenerateQuadFace(vertices,
|
||||
P1, P2, P3, P4,
|
||||
Normal,
|
||||
Vec3f(1.0, 0.0, 0.0));
|
||||
|
||||
Normal = Vec3f(1.0f, 0.0f, 0.0f);
|
||||
|
||||
GenerateQuadFace(vertices + 36,
|
||||
P4, P3, P7, P8,
|
||||
Normal,
|
||||
Vec3f(1.0, 0.0, 0.0));
|
||||
|
||||
Normal = Vec3f(0.0f, -1.0f, 0.0f);
|
||||
|
||||
GenerateQuadFace(vertices + 72,
|
||||
P1, P5, P8, P4,
|
||||
Normal,
|
||||
Vec3f(1.0, 0.0, 0.0));
|
||||
|
||||
Normal = Vec3f(0.0f, 1.0f, 0.0f);
|
||||
|
||||
GenerateQuadFace(vertices + 108,
|
||||
P2, P6, P7, P3,
|
||||
Normal,
|
||||
Vec3f(1.0, 0.0, 0.0));
|
||||
|
||||
Normal = Vec3f(-1.0f, 0.0f, 0.0f);
|
||||
|
||||
GenerateQuadFace(vertices + 144,
|
||||
P5, P6, P2, P1,
|
||||
Normal,
|
||||
Vec3f(1.0, 0.0, 0.0));
|
||||
|
||||
Normal = Vec3f(0.0f, 0.0f, 1.0f);
|
||||
|
||||
GenerateQuadFace(vertices + 180,
|
||||
P8, P7, P6, P5,
|
||||
Normal,
|
||||
Vec3f(1.0, 0.0, 0.0));
|
||||
|
||||
}
|
50
src/engine_cube.h
Normal file
@ -0,0 +1,50 @@
|
||||
#ifndef H_ENGINE_CUBE
|
||||
#define H_ENGINE_CUBE
|
||||
|
||||
#include "engine_main.h"
|
||||
#include "engine_math.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
global float DEFAULT_CUBE_SIZE = 1.0f;
|
||||
global int CUBE_BUFFER_INDICES = 216;
|
||||
|
||||
#define CT_DEEP_EARTH 0
|
||||
#define CT_STONE 1
|
||||
#define CT_GRASS 2
|
||||
#define CT_SNOW 3
|
||||
#define CT_DEEP_EARTH_SEC 4
|
||||
#define CT_STONE_SEC 5
|
||||
#define CT_GRASS_SEC 6
|
||||
#define CT_SNOW_SEC 7
|
||||
|
||||
typedef struct
|
||||
Cube
|
||||
{
|
||||
uint8_t Info;
|
||||
} Cube;
|
||||
|
||||
typedef struct
|
||||
CubeType
|
||||
{
|
||||
vec3f_t Color;
|
||||
} CubeType;
|
||||
|
||||
void
|
||||
SetActive(Cube *Cube, unsigned int ActiveFlag);
|
||||
|
||||
void
|
||||
SetType(Cube *Cube, unsigned int TypeFlag);
|
||||
|
||||
int
|
||||
GetActive(Cube *Cube);
|
||||
|
||||
int
|
||||
GetType(Cube *Cube);
|
||||
|
||||
void
|
||||
GenerateCube(float* vertices,
|
||||
vec3f_t* position,
|
||||
float dimension);
|
||||
|
||||
#endif
|
BIN
src/engine_cube.o
Normal file
285
src/engine_generation.c
Normal file
@ -0,0 +1,285 @@
|
||||
#include "engine_generation.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <time.h>
|
||||
|
||||
void
|
||||
GenerateSphereChunk(Chunk* Chunk)
|
||||
{
|
||||
|
||||
Chunk->ActiveCubes = 0;
|
||||
|
||||
int radius = Chunk->ChunkDimension / 2;
|
||||
|
||||
for (int x = 0; x < Chunk->ChunkDimension; x++)
|
||||
{
|
||||
for (int y = 0; y < Chunk->ChunkDimension; y++)
|
||||
{
|
||||
for (int z = 0; z < Chunk->ChunkDimension; z++)
|
||||
{
|
||||
|
||||
SetType(&Chunk->Grid[x][y][z], CT_SNOW);
|
||||
|
||||
if (((x - radius)*(x - radius) + (y - radius)*(y - radius)
|
||||
+ (z - radius)*(z - radius)) < (radius*radius))
|
||||
{
|
||||
SetActive(&Chunk->Grid[x][y][z], 1);
|
||||
Chunk->ActiveCubes++;
|
||||
}
|
||||
else
|
||||
{
|
||||
SetActive(&Chunk->Grid[x][y][z], 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
GenerateRandomHeightMap(Chunk* Chunk)
|
||||
{
|
||||
|
||||
time_t t;
|
||||
srand((unsigned) time(&t));
|
||||
|
||||
for (int x = 0; x < Chunk->ChunkDimension; x++)
|
||||
{
|
||||
for (int z = 0; z < Chunk->ChunkDimension; z++)
|
||||
{
|
||||
int Height = (rand() % (Chunk->ChunkDimension)) + 1;
|
||||
|
||||
ChunkHeightFill(x, z, Height, Chunk);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
float
|
||||
PerlinNoise(float X, float Y)
|
||||
{
|
||||
|
||||
vec2f_t Gradients[] = {
|
||||
Vec2f(1, 0), Vec2f(1, 1),
|
||||
Vec2f(0, 1), Vec2f(-1, 0),
|
||||
Vec2f(-1, -1), Vec2f(0, -1),
|
||||
Vec2f(1, -1), Vec2f(-1, 1)
|
||||
};
|
||||
|
||||
int Permutations[] = {
|
||||
151,160,137,91,90,15,
|
||||
131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,
|
||||
190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,
|
||||
88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166,
|
||||
77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,
|
||||
102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196,
|
||||
135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123,
|
||||
5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,
|
||||
223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9,
|
||||
129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228,
|
||||
251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107,
|
||||
49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,
|
||||
138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180,
|
||||
151,160,137,91,90,15,
|
||||
131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,
|
||||
190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,
|
||||
88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166,
|
||||
77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,
|
||||
102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196,
|
||||
135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123,
|
||||
5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,
|
||||
223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9,
|
||||
129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228,
|
||||
251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107,
|
||||
49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,
|
||||
138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180
|
||||
};
|
||||
|
||||
int XUnit = floor(X);
|
||||
int YUnit = floor(Y);
|
||||
|
||||
X = X - XUnit;
|
||||
Y = Y - YUnit;
|
||||
|
||||
XUnit = XUnit & 255;
|
||||
YUnit = YUnit & 255;
|
||||
|
||||
int GIndex_00 = Permutations[XUnit + Permutations[YUnit]] % 8;
|
||||
int GIndex_01 = Permutations[XUnit + Permutations[YUnit+1]] % 8;
|
||||
int GIndex_10 = Permutations[XUnit+1 + Permutations[YUnit]] % 8;
|
||||
int GIndex_11 = Permutations[XUnit+1 + Permutations[YUnit+1]] % 8;
|
||||
|
||||
vec2f_t G00 = Gradients[GIndex_00];
|
||||
vec2f_t G01 = Gradients[GIndex_01];
|
||||
vec2f_t G10 = Gradients[GIndex_10];
|
||||
vec2f_t G11 = Gradients[GIndex_11];
|
||||
|
||||
float Weight00 = DotProductVec2f(G00, Vec2f(X, Y));
|
||||
float Weight10 = DotProductVec2f(G10, Vec2f((X-1), Y));
|
||||
float Weight01 = DotProductVec2f(G01, Vec2f(X, (Y-1)));
|
||||
float Weight11 = DotProductVec2f(G11, Vec2f((X-1), (Y-1)));
|
||||
|
||||
float XContribution = PerlinInterpolate(X);
|
||||
float YContribution = PerlinInterpolate(Y);
|
||||
|
||||
// Blend Horizontally
|
||||
float MixY0 = Blend(Weight00, Weight10, XContribution);
|
||||
float MixY1 = Blend(Weight01, Weight11, XContribution);
|
||||
|
||||
// Blend Vertically
|
||||
float TotalMix = Blend(MixY0, MixY1, YContribution);
|
||||
|
||||
// Normalize the result to the range [0, 1] from the theoretical
|
||||
// possible range of [-1, 1]
|
||||
|
||||
return ((TotalMix+1)/2.0);
|
||||
}
|
||||
|
||||
float
|
||||
PerlinInterpolate(float Val)
|
||||
{
|
||||
return ((6*Val*Val*Val*Val*Val) - (15*Val*Val*Val*Val) + (10*Val*Val*Val));
|
||||
}
|
||||
|
||||
float
|
||||
Blend(float a, float b, float t)
|
||||
{
|
||||
return ((1-t)*a + t*b);
|
||||
}
|
||||
|
||||
float
|
||||
OctavePerlinNoise(float X, float Y, int Octaves, float Persistence)
|
||||
{
|
||||
float NoiseVal = 0;
|
||||
|
||||
float Frequency = 1;
|
||||
float Amplitude = 1;
|
||||
|
||||
float MaxNoiseVal = 0;
|
||||
|
||||
for (int o = 0; o < Octaves; o++)
|
||||
{
|
||||
|
||||
NoiseVal += PerlinNoise(X*Frequency, Y*Frequency) * Amplitude;
|
||||
|
||||
MaxNoiseVal += Amplitude;
|
||||
|
||||
Frequency *= 2;
|
||||
Amplitude *= Persistence;
|
||||
}
|
||||
|
||||
return (NoiseVal/MaxNoiseVal);
|
||||
}
|
||||
|
||||
void
|
||||
GeneratePerlinChunk(float XSeed, float ZSeed, float Inc, Chunk* Chunk)
|
||||
{
|
||||
|
||||
float Noise, Height;
|
||||
|
||||
for (int x = 0; x < Chunk->ChunkDimension; x++)
|
||||
{
|
||||
for (int z = 0; z < Chunk->ChunkDimension; z++)
|
||||
{
|
||||
Noise = PerlinNoise(XSeed, ZSeed);
|
||||
|
||||
ZSeed += Inc;
|
||||
|
||||
Height = (int)(Noise * Chunk->ChunkDimension);
|
||||
ChunkHeightFill(x, z, Height, Chunk);
|
||||
}
|
||||
|
||||
ZSeed -= (Inc * Chunk->ChunkDimension);
|
||||
XSeed += Inc;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
GenerateOctavedPerlinChunk(float XSeed, float ZSeed, float Inc,
|
||||
Chunk* Chunk, int YLevel, int MaxHeight,
|
||||
int Octaves, float Persistence)
|
||||
{
|
||||
|
||||
float StackAdjustment = 1.0/MaxHeight;
|
||||
float PerlinLowerBound = YLevel*StackAdjustment;
|
||||
float PerlinUpperBound = PerlinLowerBound + StackAdjustment;
|
||||
|
||||
float Noise, Height;
|
||||
|
||||
for (int x = 0; x < Chunk->ChunkDimension; x++)
|
||||
{
|
||||
for (int z = 0; z < Chunk->ChunkDimension; z++)
|
||||
{
|
||||
Noise = OctavePerlinNoise(XSeed, ZSeed, Octaves, Persistence);
|
||||
|
||||
if (Noise < PerlinLowerBound)
|
||||
{
|
||||
ChunkHeightFill(x, z, 0, Chunk);
|
||||
}
|
||||
if (Noise >= PerlinLowerBound && Noise < PerlinUpperBound)
|
||||
{
|
||||
float AdjustedNoiseVal = (Noise - (StackAdjustment*YLevel)) / StackAdjustment;
|
||||
|
||||
Height = (int)(AdjustedNoiseVal * Chunk->ChunkDimension);
|
||||
ChunkHeightFill(x, z, Height, Chunk);
|
||||
}
|
||||
if (Noise >= PerlinUpperBound)
|
||||
{
|
||||
ChunkHeightFill(x, z, Chunk->ChunkDimension, Chunk);
|
||||
}
|
||||
|
||||
ZSeed += Inc;
|
||||
}
|
||||
|
||||
ZSeed -= (Inc * Chunk->ChunkDimension);
|
||||
XSeed += Inc;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//TODO: implement heights
|
||||
void
|
||||
ChunkEarthBiomeWash(Chunk* Chunk)
|
||||
{
|
||||
int StoneThresh, SnowThresh;
|
||||
|
||||
StoneThresh = (int)(Chunk->ChunkDimension*0.2);
|
||||
SnowThresh = (int)(Chunk->ChunkDimension*0.6);
|
||||
|
||||
for (int X = 0; X < Chunk->ChunkDimension; X++)
|
||||
{
|
||||
for (int Z = 0; Z < Chunk->ChunkDimension; Z++)
|
||||
{
|
||||
int ChkHeight = GetChunkHeight(Chunk, X, Z);
|
||||
|
||||
int Y = 0;
|
||||
while (Y < StoneThresh)
|
||||
{
|
||||
SetType(&Chunk->Grid[X][Y][Z], CT_STONE);
|
||||
Y++;
|
||||
}
|
||||
|
||||
while (Y < ChkHeight - 1)
|
||||
{
|
||||
SetType(&Chunk->Grid[X][Y][Z], CT_DEEP_EARTH);
|
||||
Y++;
|
||||
}
|
||||
|
||||
if (Y < Chunk->ChunkDimension)
|
||||
{
|
||||
SetType(&Chunk->Grid[X][Y][Z], CT_GRASS);
|
||||
Y++;
|
||||
}
|
||||
|
||||
Y = SnowThresh;
|
||||
|
||||
while (Y >= SnowThresh && Y < Chunk->ChunkDimension)
|
||||
{
|
||||
SetType(&Chunk->Grid[X][Y][Z], CT_SNOW);
|
||||
Y++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
38
src/engine_generation.h
Normal file
@ -0,0 +1,38 @@
|
||||
#ifndef H_ENGINE_GENERATION
|
||||
#define H_ENGINE_GENERATION
|
||||
|
||||
#include "engine_chunk.h"
|
||||
#include "engine_cube.h"
|
||||
|
||||
void
|
||||
GenerateSphereChunk(Chunk* Chunk);
|
||||
|
||||
void
|
||||
GenerateRandomHeightMap(Chunk* Chunk);
|
||||
|
||||
float
|
||||
PerlinNoise(float X, float Y);
|
||||
|
||||
float
|
||||
PerlinInterpolate(float Val);
|
||||
|
||||
float
|
||||
Blend(float a, float b, float t);
|
||||
|
||||
float
|
||||
OctavePerlinNoise(float X, float Y, int Octaves, float Persistence);
|
||||
|
||||
void
|
||||
GeneratePerlinChunk(float XSeed, float ZSeed, float Inc, Chunk* Chunk);
|
||||
|
||||
void
|
||||
GenerateOctavedPerlinChunk(float XSeed, float ZSeed, float Inc,
|
||||
Chunk* Chunk, int YLevel, int MaxHeight,
|
||||
int Octaves, float Persistence);
|
||||
|
||||
void
|
||||
LandscapeEarthBiomeWash(Chunk* Chunk);
|
||||
|
||||
void
|
||||
ChunkEarthBiomeWash(Chunk* Chunk);
|
||||
#endif
|
BIN
src/engine_generation.o
Normal file
230
src/engine_main.c
Normal file
@ -0,0 +1,230 @@
|
||||
#include "engine_main.h"
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
#include <GL/glew.h>
|
||||
|
||||
#include "engine_sdl.h"
|
||||
#include "engine_shader.h"
|
||||
#include "engine_camera.h"
|
||||
#include "engine_math.h"
|
||||
#include "engine_cube.h"
|
||||
#include "engine_chunk.h"
|
||||
#include "engine_renderer.h"
|
||||
#include "engine_clock.h"
|
||||
#include "engine_generation.h"
|
||||
#include "engine_world.h"
|
||||
#include "engine_assets.h"
|
||||
#include "engine_text.h"
|
||||
#include "engine_ui.h"
|
||||
#include "engine_physics.h"
|
||||
#include "engine_console.h"
|
||||
|
||||
global GLuint program;
|
||||
|
||||
global PerspectiveProjection Projection;
|
||||
global mat4f_t ProjectionMatrix;
|
||||
global CubeWorld World;
|
||||
global DirectionLight Light0;
|
||||
global DirectionLight Light1;
|
||||
global GameClock UClock;
|
||||
global CubeType CubeTypes[128];
|
||||
|
||||
global RenderConfig RConfig;
|
||||
global SkyBox WorldSkyBox;
|
||||
|
||||
global VEPlayer Player;
|
||||
global PhysicsStaticGeometry* VoxelGeo;
|
||||
|
||||
global VEConsole Console;
|
||||
|
||||
internal void
|
||||
draw_basic(SDL_Window* window, float DeltaTime)
|
||||
{
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
UpdateVEPlayer(&Player, VoxelGeo, DeltaTime);
|
||||
|
||||
RenderSkyBox(&WorldSkyBox, &RConfig);
|
||||
RenderChunks(&RConfig, World.WorldChunks, World.ChunkCount,
|
||||
UClock.Time, World.Apocalypse);
|
||||
if (World.Spheres)
|
||||
{
|
||||
RenderChunks(&RConfig, World.Sphere, SPHERE_DEMO_COUNT,
|
||||
UClock.Time, World.Apocalypse);
|
||||
}
|
||||
UpdateTextElements(&UClock, &Player, &Console, GetActiveCubeCount(&World));
|
||||
RenderUI();
|
||||
|
||||
SDL_GL_SwapWindow(window);
|
||||
|
||||
}
|
||||
|
||||
internal void
|
||||
SetupCameraAndProjection()
|
||||
{
|
||||
Projection.Width = 800.0f;
|
||||
Projection.Height = 600.0f;
|
||||
Projection.VerticalFov = 45.0f;
|
||||
Projection.Near = 0.3f;
|
||||
Projection.Far = 10000.0f;
|
||||
|
||||
ProjectionMatrix = GetPerspectiveProjection(&Projection);
|
||||
|
||||
AttachFirstPersonCamera(&Player, 0.0f, 0.0f,
|
||||
Vec3f(0.0f, 0.8f, 0.0f));
|
||||
}
|
||||
|
||||
internal void
|
||||
createScene()
|
||||
{
|
||||
|
||||
GLuint SkyBoxShaderProgram;
|
||||
CreateShaderProgram(&SkyBoxShaderProgram, "../data/shaders/skybox_vertex.vert",
|
||||
"../data/shaders/skybox_fragment.frag");
|
||||
WorldSkyBox.SkyBoxShader = SkyBoxShaderProgram;
|
||||
|
||||
char* SkyBoxTextures[] = {
|
||||
"../data/assets/textures/right.png",
|
||||
"../data/assets/textures/left.png",
|
||||
"../data/assets/textures/top.png",
|
||||
"../data/assets/textures/bottom.png",
|
||||
"../data/assets/textures/front.png",
|
||||
"../data/assets/textures/back.png"
|
||||
};
|
||||
|
||||
LoadSkyBox(&WorldSkyBox, SkyBoxTextures);
|
||||
|
||||
CreateShaderProgram(&program, "../data/shaders/vertex.vert", "../data/shaders/fragment.frag");
|
||||
|
||||
LoadCubeTypeDefinitions("../data/assets/cubetypes.vxe", CubeTypes);
|
||||
|
||||
StartClock(&UClock);
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
|
||||
Light0.AmbientStrength = 0.1f;
|
||||
Light0.LightColor = Vec3f(1.0f, 1.0f, 1.0f);
|
||||
Light0.LightDirection = Vec3f(0.5f, -0.3f, 0.0f);
|
||||
Light1.AmbientStrength = 0.1f;
|
||||
Light1.LightColor = Vec3f(0.2f, 0.2f, 0.4f);
|
||||
Light1.LightDirection = Vec3f(-0.5f, 0.6f, 1.0f);
|
||||
|
||||
WindowSDL Window;
|
||||
InputSDL Inputs;
|
||||
GameState g_state;
|
||||
|
||||
g_state.mode = RUNNING;
|
||||
|
||||
CreateWindowAndGLContext(&Window, "Cubious", 800, 600);
|
||||
|
||||
createScene();
|
||||
|
||||
CreatePlayer(&Player,
|
||||
200.0f, 150.0f, 200.0f,
|
||||
0.8f, 0.8f);
|
||||
|
||||
SetupCameraAndProjection();
|
||||
|
||||
InitializeWorld(&World, CubeTypes, 16, 16, 4, DEFAULT_CHUNK_SIZE, 1.5, 1.5, 0.01,
|
||||
6, 0.3f);
|
||||
|
||||
LayoutTextElements(&Window, GetActiveCubeCount(&World));
|
||||
|
||||
RConfig.FPSCamera = &Player.Camera;
|
||||
RConfig.ProjectionMatrix = ProjectionMatrix;
|
||||
RConfig.ChunkShaderProgram = program;
|
||||
RConfig.DirLight0 = &Light0;
|
||||
RConfig.DirLight1 = &Light1;
|
||||
|
||||
VoxelGeo = GetStaticChunkGeometryInformation(&World);
|
||||
|
||||
InitializeInputs(&Inputs);
|
||||
InitializeVEConsole(&Console, &World, CubeTypes);
|
||||
|
||||
#ifdef NOTDEF
|
||||
VESong Sita;
|
||||
VELoadSong(&Sita, "../data/assets/music/SitaMixTape.wav");
|
||||
VEPlayMusic(&Sita, 1);
|
||||
VEPauseMusic();
|
||||
#endif
|
||||
|
||||
while (!g_state.mode == SHOULD_EXIT)
|
||||
{
|
||||
UpdateClock(&UClock);
|
||||
float DeltaTime = UClock.DeltaTime;
|
||||
PollForInput(&Inputs);
|
||||
|
||||
if (Inputs.Quit)
|
||||
{
|
||||
g_state.mode = SHOULD_EXIT;
|
||||
}
|
||||
UpdateWorld(&World);
|
||||
|
||||
if (World.PhysicsModelDirty)
|
||||
{
|
||||
RebuildStaticChunkGeometryInformation(&World, VoxelGeo);
|
||||
World.PhysicsModelDirty = 0;
|
||||
}
|
||||
|
||||
UpdateVEConsole(&Console, &Inputs);
|
||||
|
||||
if (!Console.Enabled)
|
||||
{
|
||||
if (WasKeyPressed(&Inputs, K_U))
|
||||
{
|
||||
ReseedWorld(&World, CubeTypes, 1.5, 1.5, 0.01, 6, 0.8f);
|
||||
}
|
||||
HandlePlayerInput(&Player, &Inputs, DeltaTime);
|
||||
}
|
||||
|
||||
if (World.DayNightCycle)
|
||||
{
|
||||
mat4f_t Light0Rot = RotationMat4f(0.1*DeltaTime, 0, 0, 1);
|
||||
vec4f_t VResult = MultiplyVec4fByMat4f(Vec4f(Light0.LightDirection.x,
|
||||
Light0.LightDirection.y,
|
||||
Light0.LightDirection.z,
|
||||
1),
|
||||
Light0Rot);
|
||||
Light0.LightDirection.x = VResult.x;
|
||||
Light0.LightDirection.y = VResult.y;
|
||||
Light0.LightDirection.z = VResult.z;
|
||||
}
|
||||
|
||||
if (World.Apocalypse &&
|
||||
(Light0.LightColor.y > 0.0f ||
|
||||
Light0.LightColor.z > 0.0f))
|
||||
{
|
||||
Light0.LightColor.y -= 0.005f;
|
||||
Light0.LightColor.z -= 0.005f;
|
||||
|
||||
if (Light0.LightColor.y < 0.0f ||
|
||||
Light0.LightColor.z < 0.0f)
|
||||
{
|
||||
Light0.LightColor.y = 0.0f;
|
||||
Light0.LightColor.z = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
if (!World.Apocalypse &&
|
||||
(Light0.LightColor.y < 1.0f ||
|
||||
Light0.LightColor.z < 1.0f))
|
||||
{
|
||||
Light0.LightColor.y += 0.005f;
|
||||
Light0.LightColor.z += 0.005f;
|
||||
|
||||
if (Light0.LightColor.y > 1.0f ||
|
||||
Light0.LightColor.z > 1.0f)
|
||||
{
|
||||
Light0.LightColor.y = 1.0f;
|
||||
Light0.LightColor.z = 1.0f;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
draw_basic(Window.Window, DeltaTime);
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
19
src/engine_main.h
Normal file
@ -0,0 +1,19 @@
|
||||
#ifndef H_ENGINE_MAIN
|
||||
#define H_ENGINE_MAIN
|
||||
|
||||
#define internal static
|
||||
#define global static
|
||||
|
||||
enum GameMode
|
||||
{
|
||||
SHOULD_EXIT,
|
||||
RUNNING
|
||||
};
|
||||
|
||||
typedef struct
|
||||
GameState
|
||||
{
|
||||
enum GameMode mode;
|
||||
} GameState;
|
||||
|
||||
#endif
|
BIN
src/engine_main.o
Normal file
396
src/engine_math.h
Normal file
@ -0,0 +1,396 @@
|
||||
#ifndef H_ENGINE_MATH
|
||||
#define H_ENGINE_MATH
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#define PI 3.14159265359
|
||||
#define DEG2RAD 0.0174533
|
||||
|
||||
typedef struct
|
||||
vec2f_t
|
||||
{
|
||||
float x;
|
||||
float y;
|
||||
} vec2f_t;
|
||||
|
||||
typedef struct
|
||||
vec3f_t
|
||||
{
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
} vec3f_t;
|
||||
|
||||
typedef struct
|
||||
vec4f_t
|
||||
{
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
float w;
|
||||
} vec4f_t;
|
||||
|
||||
typedef struct
|
||||
mat3f_t
|
||||
{
|
||||
|
||||
float mat[9];
|
||||
|
||||
} mat3f_t;
|
||||
|
||||
typedef struct
|
||||
mat4f_t
|
||||
{
|
||||
|
||||
float mat[16];
|
||||
|
||||
} mat4f_t;
|
||||
|
||||
typedef struct
|
||||
quack_t
|
||||
{
|
||||
vec3f_t x;
|
||||
vec3f_t y;
|
||||
vec3f_t w;
|
||||
vec3f_t h;
|
||||
} quack_t;
|
||||
|
||||
static //inline
|
||||
quack_t Quad(vec3f_t X, vec3f_t Y, vec3f_t W, vec3f_t H)
|
||||
{
|
||||
quack_t quad;
|
||||
quad.x = X;
|
||||
quad.y = Y;
|
||||
quad.w = W;
|
||||
quad.h = H;
|
||||
|
||||
return (quad);
|
||||
}
|
||||
|
||||
static //inline
|
||||
vec2f_t Vec2f(float x, float y)
|
||||
{
|
||||
vec2f_t v2;
|
||||
v2.x = x;
|
||||
v2.y = y;
|
||||
return v2;
|
||||
}
|
||||
|
||||
static //inline
|
||||
vec3f_t Vec3f(float x, float y, float z)
|
||||
{
|
||||
vec3f_t v3;
|
||||
|
||||
v3.x = x;
|
||||
v3.y = y;
|
||||
v3.z = z;
|
||||
|
||||
return v3;
|
||||
}
|
||||
|
||||
static //inline
|
||||
vec4f_t Vec4f(float x, float y, float z, float w)
|
||||
{
|
||||
vec4f_t v4;
|
||||
v4.x = x;
|
||||
v4.y = y;
|
||||
v4.z = z;
|
||||
v4.w = w;
|
||||
|
||||
return (v4);
|
||||
}
|
||||
|
||||
static //inline
|
||||
int Vec3f_Equals(vec3f_t V1, vec3f_t V2)
|
||||
{
|
||||
if (V1.x == V2.x &&
|
||||
V1.y == V2.y &&
|
||||
V1.z == V2.z)
|
||||
{
|
||||
return (1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static //inline
|
||||
mat3f_t Mat3f_Identity()
|
||||
{
|
||||
mat3f_t mat;
|
||||
|
||||
mat.mat[0] = 1.0f;
|
||||
mat.mat[1] = 0.0f;
|
||||
mat.mat[2] = 0.0f;
|
||||
|
||||
mat.mat[3] = 0.0f;
|
||||
mat.mat[4] = 1.0f;
|
||||
mat.mat[5] = 0.0f;
|
||||
|
||||
mat.mat[6] = 0.0f;
|
||||
mat.mat[7] = 0.0f;
|
||||
mat.mat[8] = 1.0f;
|
||||
|
||||
return mat;
|
||||
}
|
||||
|
||||
static //inline
|
||||
mat4f_t Mat4f_Identity()
|
||||
{
|
||||
mat4f_t mat;
|
||||
|
||||
mat.mat[0] = 1.0f;
|
||||
mat.mat[1] = 0.0f;
|
||||
mat.mat[2] = 0.0f;
|
||||
mat.mat[3] = 0.0f;
|
||||
|
||||
mat.mat[4] = 0.0f;
|
||||
mat.mat[5] = 1.0f;
|
||||
mat.mat[6] = 0.0f;
|
||||
mat.mat[7] = 0.0f;
|
||||
|
||||
mat.mat[8] = 0.0f;
|
||||
mat.mat[9] = 0.0f;
|
||||
mat.mat[10] = 1.0f;
|
||||
mat.mat[11] = 0.0f;
|
||||
|
||||
mat.mat[12] = 0.0f;
|
||||
mat.mat[13] = 0.0f;
|
||||
mat.mat[14] = 0.0f;
|
||||
mat.mat[15] = 1.0f;
|
||||
|
||||
return mat;
|
||||
}
|
||||
|
||||
static //inline
|
||||
vec3f_t NegativeVec3f(vec3f_t v)
|
||||
{
|
||||
v.x = -v.x;
|
||||
v.y = -v.y;
|
||||
v.z = -v.z;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
static //inline
|
||||
float DotProductVec2f(vec2f_t v1, vec2f_t v2)
|
||||
{
|
||||
return (v1.x*v2.x + v1.y*v2.y);
|
||||
}
|
||||
|
||||
static //inline
|
||||
float DotProductVec3f(vec3f_t v1, vec3f_t v2)
|
||||
{
|
||||
return (v1.x*v2.x + v1.y*v2.y + v1.z*v2.z);
|
||||
}
|
||||
|
||||
static //inline
|
||||
vec3f_t AddVec3f(vec3f_t v1, vec3f_t v2)
|
||||
{
|
||||
|
||||
vec3f_t v3;
|
||||
|
||||
v3.x = v2.x + v1.x;
|
||||
v3.y = v2.y + v1.y;
|
||||
v3.z = v2.z + v1.z;
|
||||
|
||||
return v3;
|
||||
}
|
||||
|
||||
static //inline
|
||||
vec3f_t SubtractVec3f(vec3f_t v1, vec3f_t v2)
|
||||
{
|
||||
vec3f_t v3;
|
||||
|
||||
v3.x = v2.x - v1.x;
|
||||
v3.y = v2.y - v1.y;
|
||||
v3.z = v2.z - v1.z;
|
||||
|
||||
return v3;
|
||||
}
|
||||
|
||||
static //inline
|
||||
vec3f_t MultiplyVec3f(vec3f_t v, float s)
|
||||
{
|
||||
v.x *= s;
|
||||
v.y *= s;
|
||||
v.z *= s;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
static //inline
|
||||
float MagnitudeVec3f(vec3f_t v)
|
||||
{
|
||||
return sqrt(v.x*v.x + v.y*v.y + v.z*v.z);
|
||||
}
|
||||
|
||||
static //inline
|
||||
vec3f_t NormalizeVec3f(vec3f_t v)
|
||||
{
|
||||
float vMag = MagnitudeVec3f(v);
|
||||
|
||||
v.x /= vMag;
|
||||
v.y /= vMag;
|
||||
v.z /= vMag;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
static //inline
|
||||
vec3f_t CrossProductVec3f(vec3f_t v1, vec3f_t v2)
|
||||
{
|
||||
vec3f_t v3;
|
||||
|
||||
v3.x = (v1.y * v2.z) - (v1.z * v2.y);
|
||||
v3.y = (v1.z * v2.x) - (v1.x * v2.z);
|
||||
v3.z = (v1.x * v2.y) - (v1.y * v2.x);
|
||||
|
||||
return v3;
|
||||
}
|
||||
|
||||
static //inline
|
||||
mat4f_t TranslationMat4f(float x, float y, float z)
|
||||
{
|
||||
mat4f_t trans = Mat4f_Identity();
|
||||
|
||||
trans.mat[12] = x;
|
||||
trans.mat[13] = y;
|
||||
trans.mat[14] = z;
|
||||
|
||||
return trans;
|
||||
}
|
||||
|
||||
static //inline
|
||||
mat4f_t ScalingMat4f(float x, float y, float z)
|
||||
{
|
||||
mat4f_t scale = Mat4f_Identity();
|
||||
|
||||
scale.mat[0] *= x;
|
||||
scale.mat[5] *= y;
|
||||
scale.mat[10] *= z;
|
||||
|
||||
return scale;
|
||||
}
|
||||
|
||||
static //inline
|
||||
mat4f_t RotationMat4f(float deg, int x, int y, int z)
|
||||
{
|
||||
|
||||
mat4f_t rot = Mat4f_Identity();
|
||||
|
||||
float rad = deg * DEG2RAD;
|
||||
|
||||
if (x)
|
||||
{
|
||||
rot.mat[5] = cos(rad);
|
||||
rot.mat[6] = sin(rad);
|
||||
rot.mat[9] = -sin(rad);
|
||||
rot.mat[10] = cos(rad);
|
||||
}
|
||||
else if (y)
|
||||
{
|
||||
rot.mat[0] = cos(rad);
|
||||
rot.mat[2]= -sin(rad);
|
||||
rot.mat[8] = sin(rad);
|
||||
rot.mat[10] = cos(rad);
|
||||
}
|
||||
else if (z)
|
||||
{
|
||||
rot.mat[0] = cos(rad);
|
||||
rot.mat[1] = sin(rad);
|
||||
rot.mat[4] = -sin(rad);
|
||||
rot.mat[5] = cos(rad);
|
||||
}
|
||||
|
||||
return rot;
|
||||
|
||||
}
|
||||
|
||||
static //inline
|
||||
vec4f_t MultiplyVec4fByMat4f(vec4f_t V, mat4f_t M)
|
||||
{
|
||||
vec4f_t Result;
|
||||
|
||||
Result.x = M.mat[0]*V.x + M.mat[4]*V.y + M.mat[8]*V.z + M.mat[12]*V.w;
|
||||
Result.y = M.mat[1]*V.x + M.mat[5]*V.y + M.mat[9]*V.z + M.mat[13]*V.w;
|
||||
Result.z = M.mat[2]*V.x + M.mat[6]*V.y + M.mat[10]*V.z + M.mat[14]*V.w;
|
||||
Result.w = M.mat[3]*V.x + M.mat[7]*V.y + M.mat[11]*V.z + M.mat[15]*V.w;
|
||||
|
||||
return (Result);
|
||||
}
|
||||
|
||||
|
||||
static //inline
|
||||
mat4f_t MultiplyMat4f(mat4f_t mat1, mat4f_t mat2)
|
||||
{
|
||||
mat4f_t mat3;
|
||||
|
||||
mat3.mat[0] = mat1.mat[0]*mat2.mat[0] + mat1.mat[4]*mat2.mat[1] +
|
||||
mat1.mat[8]*mat2.mat[2] + mat1.mat[12]*mat2.mat[3];
|
||||
|
||||
mat3.mat[4] = mat1.mat[0]*mat2.mat[4] + mat1.mat[4]*mat2.mat[5] +
|
||||
mat1.mat[8]*mat2.mat[6] + mat1.mat[12]*mat2.mat[7];
|
||||
|
||||
mat3.mat[8] = mat1.mat[0]*mat2.mat[8] + mat1.mat[4]*mat2.mat[9] +
|
||||
mat1.mat[8]*mat2.mat[10] + mat1.mat[12]*mat2.mat[11];
|
||||
|
||||
mat3.mat[12] = mat1.mat[0]*mat2.mat[12] + mat1.mat[4]*mat2.mat[13] +
|
||||
mat1.mat[8]*mat2.mat[14] + mat1.mat[12]*mat2.mat[15];
|
||||
|
||||
mat3.mat[1] = mat1.mat[1]*mat2.mat[0] + mat1.mat[5]*mat2.mat[1] +
|
||||
mat1.mat[9]*mat2.mat[2] + mat1.mat[13]*mat2.mat[3];
|
||||
|
||||
mat3.mat[5] = mat1.mat[1]*mat2.mat[4] + mat1.mat[5]*mat2.mat[5] +
|
||||
mat1.mat[9]*mat2.mat[6] + mat1.mat[13]*mat2.mat[7];
|
||||
|
||||
mat3.mat[9] = mat1.mat[1]*mat2.mat[8] + mat1.mat[5]*mat2.mat[9] +
|
||||
mat1.mat[9]*mat2.mat[10] + mat1.mat[13]*mat2.mat[11];
|
||||
|
||||
mat3.mat[13] = mat1.mat[1]*mat2.mat[12] + mat1.mat[5]*mat2.mat[13] +
|
||||
mat1.mat[9]*mat2.mat[14] + mat1.mat[13]*mat2.mat[15];
|
||||
|
||||
mat3.mat[2] = mat1.mat[2]*mat2.mat[0] + mat1.mat[6]*mat2.mat[1] +
|
||||
mat1.mat[10]*mat2.mat[2] + mat1.mat[14]*mat2.mat[3];
|
||||
|
||||
mat3.mat[6] = mat1.mat[2]*mat2.mat[4] + mat1.mat[6]*mat2.mat[5] +
|
||||
mat1.mat[10]*mat2.mat[6] + mat1.mat[14]*mat2.mat[7];
|
||||
|
||||
mat3.mat[10] = mat1.mat[2]*mat2.mat[8] + mat1.mat[6]*mat2.mat[9] +
|
||||
mat1.mat[10]*mat2.mat[10] + mat1.mat[14]*mat2.mat[11];
|
||||
|
||||
mat3.mat[14] = mat1.mat[2]*mat2.mat[12] + mat1.mat[6]*mat2.mat[13] +
|
||||
mat1.mat[10]*mat2.mat[14] + mat1.mat[14]*mat2.mat[15];
|
||||
|
||||
mat3.mat[3] = mat1.mat[3]*mat2.mat[0] + mat1.mat[7]*mat2.mat[1] +
|
||||
mat1.mat[11]*mat2.mat[2] + mat1.mat[115]*mat2.mat[3];
|
||||
|
||||
mat3.mat[7] = mat1.mat[3]*mat2.mat[4] + mat1.mat[7]*mat2.mat[5] +
|
||||
mat1.mat[11]*mat2.mat[6] + mat1.mat[115]*mat2.mat[7];
|
||||
|
||||
mat3.mat[11] = mat1.mat[3]*mat2.mat[8] + mat1.mat[7]*mat2.mat[9] +
|
||||
mat1.mat[11]*mat2.mat[10] + mat1.mat[115]*mat2.mat[11];
|
||||
|
||||
mat3.mat[15] = mat1.mat[3]*mat2.mat[12] + mat1.mat[7]*mat2.mat[13] +
|
||||
mat1.mat[11]*mat2.mat[14] + mat1.mat[15]*mat2.mat[15];
|
||||
|
||||
return mat3;
|
||||
|
||||
}
|
||||
|
||||
static //inline
|
||||
float VE_Fabs(float Num)
|
||||
{
|
||||
return (Num >= 0 ? Num : -(Num));
|
||||
}
|
||||
|
||||
static //inline
|
||||
vec3f_t Vec3f_Fabs(vec3f_t Vec)
|
||||
{
|
||||
Vec.x = VE_Fabs(Vec.x);
|
||||
Vec.y = VE_Fabs(Vec.y);
|
||||
Vec.z = VE_Fabs(Vec.z);
|
||||
|
||||
return (Vec);
|
||||
}
|
||||
|
||||
#endif
|
146
src/engine_physics.c
Normal file
@ -0,0 +1,146 @@
|
||||
#include "engine_physics.h"
|
||||
|
||||
void
|
||||
UpdatePhysicsBody(PhysicsBody* Body, float DeltaTime)
|
||||
{
|
||||
Body->Velocity = AddVec3f(Body->Gravity, Body->Velocity);
|
||||
|
||||
vec3f_t Vel = MultiplyVec3f(Body->Velocity, DeltaTime);
|
||||
|
||||
Body->Position = AddVec3f(Body->Position, Vel);
|
||||
}
|
||||
|
||||
int
|
||||
CheckAABBCollision(PhysicsAABB* AABB, PhysicsAABB* Other)
|
||||
{
|
||||
if (AABB->Max.x < Other->Min.x || AABB->Min.x > Other->Max.x) return (0);
|
||||
if (AABB->Max.y < Other->Min.y || AABB->Min.y > Other->Max.y) return (0);
|
||||
if (AABB->Max.z < Other->Min.z || AABB->Min.z > Other->Max.z) return (0);
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
int
|
||||
CheckStaticCollisions(PhysicsAABB* AABB,
|
||||
PhysicsStaticGeometry* Geometry,
|
||||
int ChunkDimension, int CubeSize,
|
||||
vec3f_t* PenetrationVector)
|
||||
{
|
||||
int HitCount = 0;
|
||||
|
||||
for (int i = 0; i < Geometry->AABBCount; i++)
|
||||
{
|
||||
// Check if there is any overlap between the AABB and the entire cube chunk
|
||||
if (CheckAABBCollision(AABB, &Geometry->AABBList[i]))
|
||||
{
|
||||
|
||||
PhysicsAABB CubeAABB;
|
||||
PhysicsAABB MDiff;
|
||||
|
||||
// Now check for specific cube collisions
|
||||
for (int X = 0; X < ChunkDimension; X++)
|
||||
{
|
||||
CubeAABB.Min.x = Geometry->AABBList[i].Min.x + X*CubeSize;
|
||||
|
||||
for (int Z = 0; Z < ChunkDimension; Z++)
|
||||
{
|
||||
CubeAABB.Min.z = Geometry->AABBList[i].Min.z + Z*CubeSize;
|
||||
for (int Y = 0; Y < ChunkDimension; Y++)
|
||||
{
|
||||
if (GetActive(&(*Geometry->ChunkList)[i].Grid[X][Y][Z]))
|
||||
{
|
||||
CubeAABB.Min.y = Geometry->AABBList[i].Min.y + Y*CubeSize;
|
||||
CubeAABB.Max.x = CubeAABB.Min.x + CubeSize;
|
||||
CubeAABB.Max.y = CubeAABB.Min.y + CubeSize;
|
||||
CubeAABB.Max.z = CubeAABB.Min.z + CubeSize;
|
||||
|
||||
if (HandleAABBCollision(AABB, &CubeAABB, &MDiff))
|
||||
{
|
||||
float MinDistX, MaxDistX,
|
||||
MinDistY, MaxDistY,
|
||||
MinDistZ, MaxDistZ;
|
||||
|
||||
vec3f_t PenVec;
|
||||
|
||||
MinDistX = VE_Fabs(MDiff.Min.x);
|
||||
MaxDistX = VE_Fabs(MDiff.Max.x);
|
||||
MinDistY = VE_Fabs(MDiff.Min.y);
|
||||
MaxDistY = VE_Fabs(MDiff.Max.y);
|
||||
MinDistZ = VE_Fabs(MDiff.Min.z);
|
||||
MaxDistZ = VE_Fabs(MDiff.Max.z);
|
||||
|
||||
float Minimum = MinDistX;
|
||||
PenVec = Vec3f(MDiff.Min.x, 0.0f, 0.0f);
|
||||
|
||||
if (MaxDistX < Minimum)
|
||||
{
|
||||
Minimum = MaxDistX;
|
||||
PenVec = Vec3f(MDiff.Max.x, 0.0f, 0.0f);
|
||||
}
|
||||
if (MinDistY < Minimum)
|
||||
{
|
||||
Minimum = MinDistY;
|
||||
PenVec = Vec3f(0.0f, MDiff.Min.y, 0.0f);
|
||||
}
|
||||
if (MaxDistY < Minimum)
|
||||
{
|
||||
Minimum = MaxDistY;
|
||||
PenVec = Vec3f(0.0f, MDiff.Max.y, 0.0f);
|
||||
}
|
||||
if (MinDistZ < Minimum)
|
||||
{
|
||||
Minimum = MinDistZ;
|
||||
PenVec = Vec3f(0.0f, 0.0f, MDiff.Min.z);
|
||||
}
|
||||
if (MaxDistZ < Minimum)
|
||||
{
|
||||
Minimum = MaxDistZ;
|
||||
PenVec = Vec3f(0.0f, 0.0f, MDiff.Max.z);
|
||||
}
|
||||
|
||||
*PenetrationVector = PenVec;
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
int
|
||||
HandleAABBCollision(PhysicsAABB* A, PhysicsAABB* B, PhysicsAABB* MDiff)
|
||||
{
|
||||
float MDiffX, MDiffY, MDiffZ,
|
||||
SumX, SumY, SumZ;
|
||||
|
||||
MDiffX = B->Min.x - A->Max.x;
|
||||
MDiffY = B->Min.y - A->Max.y;
|
||||
MDiffZ = B->Min.z - A->Max.z;
|
||||
|
||||
SumX = (A->Max.x - A->Min.x) + (B->Max.x - B->Min.x);
|
||||
SumY = (A->Max.y - A->Min.y) + (B->Max.y - B->Min.y);
|
||||
SumZ = (A->Max.z - A->Min.z) + (B->Max.z - B->Min.z);
|
||||
|
||||
// If it encompasses the origin, there is a collision
|
||||
if (MDiffX < 0 && (MDiffX + SumX) > 0 &&
|
||||
MDiffY < 0 && (MDiffY + SumY) > 0 &&
|
||||
MDiffZ < 0 && (MDiffZ + SumZ) > 0)
|
||||
{
|
||||
MDiff->Min.x = MDiffX;
|
||||
MDiff->Min.y = MDiffY;
|
||||
MDiff->Min.z = MDiffZ;
|
||||
|
||||
MDiff->Max.x = MDiffX + SumX;
|
||||
MDiff->Max.y = MDiffY + SumY;
|
||||
MDiff->Max.z = MDiffZ + SumZ;
|
||||
return (1);
|
||||
}
|
||||
else
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
}
|
51
src/engine_physics.h
Normal file
@ -0,0 +1,51 @@
|
||||
#ifndef H_ENGINE_PHYSICS
|
||||
#define H_ENGINE_PHYSICS
|
||||
|
||||
#include "engine_math.h"
|
||||
#include "engine_chunk.h"
|
||||
|
||||
typedef struct
|
||||
PhysicsBody
|
||||
{
|
||||
vec3f_t Position;
|
||||
vec3f_t Velocity;
|
||||
vec3f_t Gravity;
|
||||
} PhysicsBody;
|
||||
|
||||
typedef struct
|
||||
PhysicsAABB
|
||||
{
|
||||
vec3f_t Min;
|
||||
vec3f_t Max;
|
||||
} PhysicsAABB;
|
||||
|
||||
typedef struct
|
||||
PhysicsStaticGeometry
|
||||
{
|
||||
Chunk** ChunkList;
|
||||
PhysicsAABB* AABBList;
|
||||
int AABBCount;
|
||||
} PhysicsStaticGeometry;
|
||||
|
||||
void
|
||||
UpdatePhysicsBody(PhysicsBody* Body, float DeltaTime);
|
||||
|
||||
int
|
||||
CheckAABBCollision(PhysicsAABB* AABB, PhysicsAABB* Other);
|
||||
|
||||
int
|
||||
CheckStaticChunkCollisions(PhysicsAABB* AABB,
|
||||
PhysicsStaticGeometry* Geometry,
|
||||
int ChunkDimension, int CubeSize,
|
||||
vec3f_t* PenetrationVector);
|
||||
|
||||
int
|
||||
HandleAABBCollision(PhysicsAABB* A, PhysicsAABB* B, PhysicsAABB* MDiff);
|
||||
|
||||
int
|
||||
CheckStaticCollisions(PhysicsAABB* AABB,
|
||||
PhysicsStaticGeometry* Geometry,
|
||||
int ChunkDimension, int CubeSize,
|
||||
vec3f_t* PenetrationVector);
|
||||
|
||||
#endif
|
BIN
src/engine_physics.o
Normal file
193
src/engine_player.c
Normal file
@ -0,0 +1,193 @@
|
||||
#include "engine_player.h"
|
||||
|
||||
global VEAudioClip PlayerJump;
|
||||
global VEAudioClip PlayerFall;
|
||||
|
||||
void
|
||||
CreatePlayer(VEPlayer* Player,
|
||||
float StartX, float StartY, float StartZ,
|
||||
float HitboxWidth, float HitboxHeight)
|
||||
{
|
||||
VELoadAudioClip(&PlayerJump, "../data/assets/music/jump.ogg", 1);
|
||||
VELoadAudioClip(&PlayerFall, "../data/assets/music/fall.ogg", 2);
|
||||
|
||||
Player->Body.Position.x = StartX;
|
||||
Player->Body.Position.y = StartY;
|
||||
Player->Body.Position.z = StartZ;
|
||||
|
||||
Player->Body.Velocity.x = 0.0f;
|
||||
Player->Body.Velocity.y = 0.0f;
|
||||
Player->Body.Velocity.z = 0.0f;
|
||||
|
||||
Player->HitboxWidth = HitboxWidth;
|
||||
Player->HitboxHeight = HitboxHeight;
|
||||
|
||||
UpdatePlayerHitbox(Player);
|
||||
|
||||
Player->FlyMode = 0;
|
||||
Player->Body.Gravity.y = -0.0007f;
|
||||
}
|
||||
|
||||
void
|
||||
AttachFirstPersonCamera(VEPlayer* Player,
|
||||
float StartPitch, float StartYaw,
|
||||
vec3f_t CameraPosition)
|
||||
{
|
||||
Player->Camera.Position = Player->Body.Position;
|
||||
Player->Camera.Pitch = StartPitch;
|
||||
Player->Camera.Yaw = StartYaw;
|
||||
|
||||
Player->CameraPosition = CameraPosition;
|
||||
Player->Camera.Position = AddVec3f(Player->Camera.Position, Player->CameraPosition);
|
||||
}
|
||||
|
||||
void
|
||||
HandlePlayerInput(VEPlayer* Player, InputSDL* Inputs, float DeltaTime)
|
||||
{
|
||||
if (WasKeyPressed(Inputs, K_F))
|
||||
{
|
||||
Player->FlyMode = !(Player->FlyMode);
|
||||
|
||||
if (!Player->FlyMode)
|
||||
{
|
||||
Player->Body.Gravity.y = -0.0007f;
|
||||
}
|
||||
else
|
||||
{
|
||||
Player->Body.Gravity.y = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
if (Player->FlyMode)
|
||||
{
|
||||
if (Inputs->Keys[K_W])
|
||||
{
|
||||
vec3f_t Forward = FPCamFront(&Player->Camera);
|
||||
Forward = MultiplyVec3f(Forward, 0.15f*DeltaTime);
|
||||
Player->Body.Position = AddVec3f(Player->Body.Position, Forward);
|
||||
}
|
||||
if (Inputs->Keys[K_S])
|
||||
{
|
||||
vec3f_t Forward = FPCamFront(&Player->Camera);
|
||||
Forward = MultiplyVec3f(Forward, 0.15f*DeltaTime);
|
||||
Player->Body.Position = SubtractVec3f(Forward, Player->Body.Position);
|
||||
}
|
||||
if (Inputs->Keys[K_D])
|
||||
{
|
||||
vec3f_t Forward = FPCamFront(&Player->Camera);
|
||||
vec3f_t Right = FPCamRight(Forward);
|
||||
Right = MultiplyVec3f(Right, 0.15f*DeltaTime);
|
||||
Player->Body.Position = AddVec3f(Player->Body.Position, Right);
|
||||
}
|
||||
if (Inputs->Keys[K_A])
|
||||
{
|
||||
vec3f_t Forward = FPCamFront(&Player->Camera);
|
||||
vec3f_t Right = FPCamRight(Forward);
|
||||
Right = MultiplyVec3f(Right, 0.15f*DeltaTime);
|
||||
Player->Body.Position = SubtractVec3f(Right, Player->Body.Position);
|
||||
}
|
||||
}
|
||||
|
||||
if (!Player->FlyMode)
|
||||
{
|
||||
if (Inputs->Keys[K_W])
|
||||
{
|
||||
vec3f_t Forward = FPCamFront(&Player->Camera);
|
||||
Forward = MultiplyVec3f(Forward, 0.02f*DeltaTime);
|
||||
Player->Body.Position = AddVec3f(Player->Body.Position, Forward);
|
||||
}
|
||||
if (Inputs->Keys[K_S])
|
||||
{
|
||||
vec3f_t Forward = FPCamFront(&Player->Camera);
|
||||
Forward = MultiplyVec3f(Forward, 0.02f*DeltaTime);
|
||||
Player->Body.Position = SubtractVec3f(Forward, Player->Body.Position);
|
||||
}
|
||||
if (Inputs->Keys[K_D])
|
||||
{
|
||||
vec3f_t Forward = FPCamFront(&Player->Camera);
|
||||
vec3f_t Right = FPCamRight(Forward);
|
||||
Right = MultiplyVec3f(Right, 0.02f*DeltaTime);
|
||||
Player->Body.Position = AddVec3f(Player->Body.Position, Right);
|
||||
}
|
||||
if (Inputs->Keys[K_A])
|
||||
{
|
||||
vec3f_t Forward = FPCamFront(&Player->Camera);
|
||||
vec3f_t Right = FPCamRight(Forward);
|
||||
Right = MultiplyVec3f(Right, 0.02f*DeltaTime);
|
||||
Player->Body.Position = SubtractVec3f(Right, Player->Body.Position);
|
||||
}
|
||||
if (WasKeyPressed(Inputs, K_SPACE))
|
||||
{
|
||||
VEPlayAudioClip(&PlayerJump, 0);
|
||||
Player->Body.Velocity.y = 0.02f;
|
||||
}
|
||||
}
|
||||
|
||||
if (Inputs->Keys[K_ESCAPE])
|
||||
{
|
||||
Inputs->Quit = 1;
|
||||
}
|
||||
|
||||
int X, Y;
|
||||
|
||||
SDL_GetRelativeMouseState(&X, &Y);
|
||||
|
||||
Player->Camera.Yaw += X * 0.05f;
|
||||
Player->Camera.Pitch += Y * 0.05f;
|
||||
}
|
||||
|
||||
void
|
||||
UpdatePlayerHitbox(VEPlayer* Player)
|
||||
{
|
||||
Player->Hitbox.Min.x = Player->Body.Position.x - (Player->HitboxWidth/2.0);
|
||||
Player->Hitbox.Min.y = Player->Body.Position.y - (Player->HitboxHeight/2.0);
|
||||
Player->Hitbox.Min.z = Player->Body.Position.z - (Player->HitboxWidth/2.0);
|
||||
|
||||
Player->Hitbox.Max.x = Player->Body.Position.x + (Player->HitboxWidth/2.0);
|
||||
Player->Hitbox.Max.y = Player->Body.Position.y + (Player->HitboxHeight/2.0);
|
||||
Player->Hitbox.Max.z = Player->Body.Position.z + (Player->HitboxWidth/2.0);
|
||||
}
|
||||
|
||||
void
|
||||
UpdateVEPlayer(VEPlayer* Player, PhysicsStaticGeometry* VoxelGeography, float DeltaTime)
|
||||
{
|
||||
if (!Player->FlyMode)
|
||||
{
|
||||
UpdatePhysicsBody(&Player->Body, DeltaTime);
|
||||
UpdatePlayerHitbox(Player);
|
||||
|
||||
if (Player->Body.Velocity.y < -0.01 && !VEIsChannelPlaying(&PlayerFall))
|
||||
{
|
||||
VEPlayAudioClip(&PlayerFall, 0);
|
||||
}
|
||||
if (Player->Body.Velocity.y > -0.006 && VEIsChannelPlaying(&PlayerFall))
|
||||
{
|
||||
VEFadeAudioClip(&PlayerFall, 500);
|
||||
}
|
||||
|
||||
vec3f_t PenVec;
|
||||
|
||||
int ResolutionCount = 0;
|
||||
|
||||
while (CheckStaticCollisions(&Player->Hitbox, VoxelGeography, 32, 1, &PenVec))
|
||||
{
|
||||
Player->Body.Position = AddVec3f(Player->Body.Position, PenVec);
|
||||
Player->Hitbox.Min = AddVec3f(Player->Hitbox.Min, PenVec);
|
||||
Player->Hitbox.Max = AddVec3f(Player->Hitbox.Max, PenVec);
|
||||
|
||||
if (PenVec.y != 0)
|
||||
{
|
||||
Player->Body.Velocity.y = 0.0f;
|
||||
}
|
||||
|
||||
ResolutionCount++;
|
||||
|
||||
if (ResolutionCount >= 50)
|
||||
{
|
||||
Player->FlyMode = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
Player->Camera.Position = AddVec3f(Player->Body.Position, Player->CameraPosition);
|
||||
}
|
39
src/engine_player.h
Normal file
@ -0,0 +1,39 @@
|
||||
#ifndef H_ENGINE_PLAYER
|
||||
#define H_ENGINE_PLAYER
|
||||
|
||||
#include "engine_physics.h"
|
||||
#include "engine_camera.h"
|
||||
#include "engine_sdl.h"
|
||||
|
||||
typedef struct
|
||||
VEPlayer
|
||||
{
|
||||
PhysicsBody Body;
|
||||
PhysicsAABB Hitbox;
|
||||
float HitboxWidth;
|
||||
float HitboxHeight;
|
||||
FirstPersonCamera Camera;
|
||||
vec3f_t CameraPosition;
|
||||
int FlyMode;
|
||||
} VEPlayer;
|
||||
|
||||
void
|
||||
CreatePlayer(VEPlayer* Player,
|
||||
float StartX, float StartY, float StartZ,
|
||||
float HitboxWidth, float HitboxHeight);
|
||||
|
||||
void
|
||||
AttachFirstPersonCamera(VEPlayer* Player,
|
||||
float StartPitch, float StartYaw,
|
||||
vec3f_t CameraPosition);
|
||||
|
||||
void
|
||||
HandlePlayerInput(VEPlayer* Player, InputSDL* Inputs, float DeltaTime);
|
||||
|
||||
void
|
||||
UpdatePlayerHitbox(VEPlayer* Player);
|
||||
|
||||
void
|
||||
UpdateVEPlayer(VEPlayer* Player, PhysicsStaticGeometry* VoxelGeography, float DeltaTime);
|
||||
|
||||
#endif
|
BIN
src/engine_player.o
Normal file
510
src/engine_renderer.c
Normal file
@ -0,0 +1,510 @@
|
||||
#include "engine_renderer.h"
|
||||
#include "stb_image.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
void
|
||||
CreateTriangleVertexList(float* vertices,
|
||||
vec3f_t v1,
|
||||
vec3f_t v2,
|
||||
vec3f_t v3,
|
||||
vec3f_t normal,
|
||||
vec3f_t color)
|
||||
{
|
||||
|
||||
vertices[0] = v1.x;
|
||||
vertices[1] = v1.y;
|
||||
vertices[2] = v1.z;
|
||||
|
||||
vertices[3] = normal.x;
|
||||
vertices[4] = normal.y;
|
||||
vertices[5] = normal.z;
|
||||
|
||||
vertices[6] = color.x;
|
||||
vertices[7] = color.y;
|
||||
vertices[8] = color.z;
|
||||
|
||||
vertices[9] = v2.x;
|
||||
vertices[10] = v2.y;
|
||||
vertices[11] = v2.z;
|
||||
|
||||
vertices[12] = normal.x;
|
||||
vertices[13] = normal.y;
|
||||
vertices[14] = normal.z;
|
||||
|
||||
vertices[15] = color.x;
|
||||
vertices[16] = color.y;
|
||||
vertices[17] = color.z;
|
||||
|
||||
vertices[18] = v3.x;
|
||||
vertices[19] = v3.y;
|
||||
vertices[20] = v3.z;
|
||||
|
||||
vertices[21] = normal.x;
|
||||
vertices[22] = normal.y;
|
||||
vertices[23] = normal.z;
|
||||
|
||||
vertices[24] = color.x;
|
||||
vertices[25] = color.y;
|
||||
vertices[26] = color.z;
|
||||
|
||||
}
|
||||
|
||||
vec3f_t GetAmbientLightingDL(DirectionLight* Light)
|
||||
{
|
||||
return MultiplyVec3f(Light->LightColor, Light->AmbientStrength);
|
||||
}
|
||||
|
||||
void InitializeChunkRenderBuffers(Chunk* Chunk, float* RenderBuffer)
|
||||
{
|
||||
|
||||
int RenderByteSize = (Chunk->MeshVertexCount) * RENDER_FLOATS_PER_CUBE_VERTEX * sizeof(float);
|
||||
|
||||
glGenVertexArrays(1, &Chunk->VAO);
|
||||
glGenBuffers(1, &Chunk->VBO);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, Chunk->VBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, RenderByteSize,
|
||||
RenderBuffer, GL_STATIC_DRAW);
|
||||
|
||||
glBindVertexArray(Chunk->VAO);
|
||||
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 9*sizeof(GLfloat), (GLvoid*)0);
|
||||
glEnableVertexAttribArray(0);
|
||||
|
||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE,
|
||||
9*sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
|
||||
glEnableVertexAttribArray(1);
|
||||
|
||||
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 9*sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat)));
|
||||
glEnableVertexAttribArray(2);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
|
||||
glBindVertexArray(0);
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
FreeChunkRenderBuffers(Chunk* Chunk)
|
||||
{
|
||||
glDeleteVertexArrays(1, &Chunk->VAO);
|
||||
glDeleteBuffers(1, &Chunk->VBO);
|
||||
}
|
||||
|
||||
void
|
||||
UpdateChunkRenderBuffers(Chunk* Chunk, float* RenderBuffer)
|
||||
{
|
||||
int RenderByteSize = (Chunk->MeshVertexCount) * RENDER_FLOATS_PER_CUBE_VERTEX * sizeof(float);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, Chunk->VBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, RenderByteSize,
|
||||
RenderBuffer, GL_STATIC_DRAW);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
void
|
||||
RenderChunks(RenderConfig* Config, Chunk* Chunks, int ChunkCount,
|
||||
int Time, int ApocalypseMode)
|
||||
{
|
||||
|
||||
glUseProgram(Config->ChunkShaderProgram);
|
||||
|
||||
mat4f_t Model, View;
|
||||
|
||||
GLint ModelLoc = glGetUniformLocation(Config->ChunkShaderProgram, "model");
|
||||
GLint ViewLoc = glGetUniformLocation(Config->ChunkShaderProgram, "view");
|
||||
GLint ProjLoc = glGetUniformLocation(Config->ChunkShaderProgram, "projection");
|
||||
GLint LightColor0Loc = glGetUniformLocation(Config->ChunkShaderProgram, "lightColor0");
|
||||
GLint LightDir0Loc = glGetUniformLocation(Config->ChunkShaderProgram, "lightDirection0");
|
||||
GLint LightColor1Loc = glGetUniformLocation(Config->ChunkShaderProgram, "lightColor1");
|
||||
GLint LightDir1Loc = glGetUniformLocation(Config->ChunkShaderProgram, "lightDirection1");
|
||||
GLint AmbientLightLoc = glGetUniformLocation(Config->ChunkShaderProgram, "ambientLight");
|
||||
GLint TimeLoc = glGetUniformLocation(Config->ChunkShaderProgram, "time");
|
||||
GLint ApocalypseLoc = glGetUniformLocation(Config->ChunkShaderProgram, "apocalypse");
|
||||
|
||||
glUniform1f(TimeLoc, Time);
|
||||
glUniform1i(ApocalypseLoc, ApocalypseMode);
|
||||
|
||||
View = GetFirstPersonView(Config->FPSCamera);
|
||||
|
||||
glUniformMatrix4fv(ViewLoc, 1, GL_FALSE, View.mat);
|
||||
glUniformMatrix4fv(ProjLoc, 1, GL_FALSE, Config->ProjectionMatrix.mat);
|
||||
|
||||
glUniform3f(LightColor0Loc,
|
||||
Config->DirLight0->LightColor.x,
|
||||
Config->DirLight0->LightColor.y,
|
||||
Config->DirLight0->LightColor.z);
|
||||
|
||||
glUniform3f(LightDir0Loc,
|
||||
Config->DirLight0->LightDirection.x,
|
||||
Config->DirLight0->LightDirection.y,
|
||||
Config->DirLight0->LightDirection.z);
|
||||
|
||||
glUniform3f(LightColor1Loc,
|
||||
Config->DirLight1->LightColor.x,
|
||||
Config->DirLight1->LightColor.y,
|
||||
Config->DirLight1->LightColor.z);
|
||||
|
||||
glUniform3f(LightDir1Loc,
|
||||
Config->DirLight1->LightDirection.x,
|
||||
Config->DirLight1->LightDirection.y,
|
||||
Config->DirLight1->LightDirection.z);
|
||||
|
||||
vec3f_t Lighting = GetAmbientLightingDL(Config->DirLight0);
|
||||
|
||||
glUniform3f(AmbientLightLoc, Lighting.x, Lighting.y, Lighting.z);
|
||||
|
||||
for (int i = 0; i < ChunkCount; i++)
|
||||
{
|
||||
|
||||
Model = TranslationMat4f(Chunks[i].Transform.x,
|
||||
Chunks[i].Transform.y,
|
||||
Chunks[i].Transform.z);
|
||||
|
||||
glUniformMatrix4fv(ModelLoc, 1, GL_FALSE, Model.mat);
|
||||
|
||||
glBindVertexArray(Chunks[i].VAO);
|
||||
glDrawArrays(GL_TRIANGLES, 0, Chunks[i].MeshVertexCount);
|
||||
glBindVertexArray(0);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
GenerateQuadFace(float* vertices,
|
||||
vec3f_t v1,
|
||||
vec3f_t v2,
|
||||
vec3f_t v3,
|
||||
vec3f_t v4,
|
||||
vec3f_t normal,
|
||||
vec3f_t color)
|
||||
{
|
||||
|
||||
CreateTriangleVertexList(vertices, v1, v2, v3, normal, color);
|
||||
|
||||
CreateTriangleVertexList(vertices+(3*RENDER_FLOATS_PER_CUBE_VERTEX),
|
||||
v1, v3, v4, normal, color);
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
InitializeFontRenderer(FontRenderConfig* RenderConfig,
|
||||
TextureAtlas* Image,
|
||||
int VBOCount,
|
||||
int BufferSize,
|
||||
GLuint Shader)
|
||||
{
|
||||
|
||||
RenderConfig->FontShader = Shader;
|
||||
|
||||
glGenTextures(1, &RenderConfig->FontTexture);
|
||||
glBindTexture(GL_TEXTURE_2D, RenderConfig->FontTexture);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
|
||||
Image->Width,
|
||||
Image->Height,
|
||||
0,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
Image->ImageFile);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
RenderConfig->TextRenderBuffer = malloc(BufferSize * sizeof(float));
|
||||
RenderConfig->RenderIndexBuffer = malloc(BufferSize * sizeof(int));
|
||||
RenderConfig->GlyphCounts = malloc(VBOCount * sizeof(int));
|
||||
RenderConfig->VBOS = malloc(VBOCount * sizeof(GLuint*));
|
||||
RenderConfig->VAOS = malloc(VBOCount * sizeof(GLuint*));
|
||||
RenderConfig->EBOS = malloc(VBOCount * sizeof(GLuint*));
|
||||
|
||||
for (int i = 0; i < VBOCount; i++)
|
||||
{
|
||||
glGenVertexArrays(1, &RenderConfig->VAOS[i]);
|
||||
glGenBuffers(1, &RenderConfig->VBOS[i]);
|
||||
glGenBuffers(1, &RenderConfig->EBOS[i]);
|
||||
}
|
||||
|
||||
RenderConfig->BufferCount = VBOCount;
|
||||
RenderConfig->BufferLengths = BufferSize;
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
FreeFontRenderBuffers(FontRenderConfig* RenderConfig)
|
||||
{
|
||||
free(RenderConfig->TextRenderBuffer);
|
||||
free(RenderConfig->RenderIndexBuffer);
|
||||
}
|
||||
|
||||
void
|
||||
CreateTextBuffer(char* Text, int Buffer,
|
||||
FontRenderConfig* RenderConfig,
|
||||
FontTextureAtlas* Atlas,
|
||||
vec2f_t Origin,
|
||||
int FontSize,
|
||||
WindowSDL* Window)
|
||||
{
|
||||
|
||||
//vec2f_t GLOrigin = ScreenCoordToGLCoord(Origin.x, Origin.y, Window);
|
||||
vec2f_t GLOrigin;
|
||||
float XPos = 0.0f;
|
||||
float YOffset = 0.0f;
|
||||
|
||||
float GLBaseWidth = 0.03f * FontSize;
|
||||
float GLBaseHeight = 0.03f * FontSize;
|
||||
float GLBaseSpace = 0.0001 * FontSize;
|
||||
|
||||
float GLWidth, GLHeight;
|
||||
|
||||
int i = 0;
|
||||
|
||||
while (Text[i] != '\0')
|
||||
{
|
||||
vec2f_t TexOrigin;
|
||||
float TexWidth, TexHeight;
|
||||
|
||||
CharacterGetGLDimensions(&Atlas->Characters[Text[i]],
|
||||
&Atlas->AtlasImage,
|
||||
&TexOrigin,
|
||||
&TexWidth, &TexHeight, &YOffset);
|
||||
|
||||
GLWidth = TexWidth * GLBaseWidth;
|
||||
GLHeight = TexHeight * GLBaseHeight;
|
||||
|
||||
float TexX1 = TexOrigin.x;
|
||||
float TexX2 = TexOrigin.x + TexWidth;
|
||||
float TexY1 = TexOrigin.y;
|
||||
float TexY2 = TexOrigin.y + TexHeight;
|
||||
|
||||
GLOrigin = ScreenCoordToGLCoord(Origin.x,
|
||||
Origin.y,
|
||||
Window);
|
||||
|
||||
GLOrigin.x += XPos;
|
||||
|
||||
GLOrigin.y -= YOffset * GLBaseHeight;
|
||||
|
||||
RenderConfig->TextRenderBuffer[(i*20)] = GLOrigin.x + GLWidth;
|
||||
RenderConfig->TextRenderBuffer[(i*20)+1] = GLOrigin.y - GLHeight;
|
||||
RenderConfig->TextRenderBuffer[(i*20)+2] = 0.0f;
|
||||
RenderConfig->TextRenderBuffer[(i*20)+3] = TexX2;
|
||||
RenderConfig->TextRenderBuffer[(i*20)+4] = TexY2;
|
||||
|
||||
RenderConfig->TextRenderBuffer[(i*20)+5] = GLOrigin.x + GLWidth;
|
||||
RenderConfig->TextRenderBuffer[(i*20)+6] = GLOrigin.y;
|
||||
RenderConfig->TextRenderBuffer[(i*20)+7] = 0.0f;
|
||||
RenderConfig->TextRenderBuffer[(i*20)+8] = TexX2;
|
||||
RenderConfig->TextRenderBuffer[(i*20)+9] = TexY1;
|
||||
|
||||
RenderConfig->TextRenderBuffer[(i*20)+10] = GLOrigin.x;
|
||||
RenderConfig->TextRenderBuffer[(i*20)+11] = GLOrigin.y;
|
||||
RenderConfig->TextRenderBuffer[(i*20)+12] = 0.0f;
|
||||
RenderConfig->TextRenderBuffer[(i*20)+13] = TexX1;
|
||||
RenderConfig->TextRenderBuffer[(i*20)+14] = TexY1;
|
||||
|
||||
RenderConfig->TextRenderBuffer[(i*20)+15] = GLOrigin.x;
|
||||
RenderConfig->TextRenderBuffer[(i*20)+16] = GLOrigin.y - GLHeight;
|
||||
RenderConfig->TextRenderBuffer[(i*20)+17] = 0.0f;
|
||||
RenderConfig->TextRenderBuffer[(i*20)+18] = TexX1;
|
||||
RenderConfig->TextRenderBuffer[(i*20)+19] = TexY2;
|
||||
|
||||
RenderConfig->RenderIndexBuffer[(i*6)] = (i*4);
|
||||
RenderConfig->RenderIndexBuffer[(i*6)+1] = (i*4)+1;
|
||||
RenderConfig->RenderIndexBuffer[(i*6)+2] = (i*4)+3;
|
||||
RenderConfig->RenderIndexBuffer[(i*6)+3] = (i*4)+1;
|
||||
RenderConfig->RenderIndexBuffer[(i*6)+4] = (i*4)+2;
|
||||
RenderConfig->RenderIndexBuffer[(i*6)+5] = (i*4)+3;
|
||||
|
||||
XPos += GLWidth + GLBaseSpace;
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
glBindVertexArray(RenderConfig->VAOS[Buffer]);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, RenderConfig->VBOS[Buffer]);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*i*20,
|
||||
RenderConfig->TextRenderBuffer, GL_STATIC_DRAW);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, RenderConfig->EBOS[Buffer]);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(int)*i*6,
|
||||
RenderConfig->RenderIndexBuffer, GL_STATIC_DRAW);
|
||||
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), (GLvoid*)0);
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
|
||||
glEnableVertexAttribArray(1);
|
||||
|
||||
glBindVertexArray(0);
|
||||
|
||||
RenderConfig->GlyphCounts[Buffer] = i;
|
||||
}
|
||||
|
||||
void
|
||||
RenderText(int Buffer,
|
||||
FontRenderConfig* RenderConfig)
|
||||
{
|
||||
|
||||
glUseProgram(RenderConfig->FontShader);
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, RenderConfig->FontTexture);
|
||||
|
||||
glBindVertexArray(RenderConfig->VAOS[Buffer]);
|
||||
glDrawElements(GL_TRIANGLES, (6*RenderConfig->GlyphCounts[Buffer]), GL_UNSIGNED_INT, 0);
|
||||
glBindVertexArray(0);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
}
|
||||
|
||||
vec2f_t
|
||||
ScreenCoordToGLCoord(float X, float Y, WindowSDL* Window)
|
||||
{
|
||||
|
||||
float GLX, GLY;
|
||||
|
||||
float PercentX = X / (float)Window->ScreenWidth;
|
||||
GLX = (2*PercentX) - 1.0f;
|
||||
|
||||
float PercentY = Y / (float)Window->ScreenHeight;
|
||||
GLY = (2*PercentY) - 1.0f;
|
||||
|
||||
return (Vec2f(GLX, GLY));
|
||||
}
|
||||
|
||||
void
|
||||
LoadSkyBox(SkyBox* RSkybox, char** SkyBoxImages)
|
||||
{
|
||||
glGenTextures(1, &RSkybox->SkyBoxTexture);
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, RSkybox->SkyBoxTexture);
|
||||
|
||||
int ImageWidth[6], ImageHeight[6], BPP;
|
||||
unsigned char* Image[6];
|
||||
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
Image[i] = stbi_load(SkyBoxImages[i],
|
||||
&ImageWidth[i],
|
||||
&ImageHeight[i],
|
||||
&BPP, 0);
|
||||
|
||||
if (!Image[i])
|
||||
{
|
||||
printf("Loading of skybox texture failed\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA,
|
||||
ImageWidth[0], ImageHeight[0], 0, GL_RGBA, GL_UNSIGNED_BYTE, Image[0]);
|
||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA,
|
||||
ImageWidth[1], ImageHeight[1], 0, GL_RGBA, GL_UNSIGNED_BYTE, Image[1]);
|
||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA,
|
||||
ImageWidth[2], ImageHeight[2], 0, GL_RGBA, GL_UNSIGNED_BYTE, Image[2]);
|
||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA,
|
||||
ImageWidth[3], ImageHeight[3], 0, GL_RGBA, GL_UNSIGNED_BYTE, Image[3]);
|
||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA,
|
||||
ImageWidth[4], ImageHeight[4], 0, GL_RGBA, GL_UNSIGNED_BYTE, Image[4]);
|
||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA,
|
||||
ImageWidth[5], ImageHeight[5], 0, GL_RGBA, GL_UNSIGNED_BYTE, Image[5]);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
||||
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
|
||||
|
||||
GLfloat Vertices[] = {
|
||||
-10.0f, 10.0f, -10.0f,
|
||||
-10.0f, -10.0f, -10.0f,
|
||||
10.0f, -10.0f, -10.0f,
|
||||
10.0f, -10.0f, -10.0f,
|
||||
10.0f, 10.0f, -10.0f,
|
||||
-10.0f, 10.0f, -10.0f,
|
||||
|
||||
-10.0f, -10.0f, 10.0f,
|
||||
-10.0f, -10.0f, -10.0f,
|
||||
-10.0f, 10.0f, -10.0f,
|
||||
-10.0f, 10.0f, -10.0f,
|
||||
-10.0f, 10.0f, 10.0f,
|
||||
-10.0f, -10.0f, 10.0f,
|
||||
|
||||
10.0f, -10.0f, -10.0f,
|
||||
10.0f, -10.0f, 10.0f,
|
||||
10.0f, 10.0f, 10.0f,
|
||||
10.0f, 10.0f, 10.0f,
|
||||
10.0f, 10.0f, -10.0f,
|
||||
10.0f, -10.0f, -10.0f,
|
||||
|
||||
-10.0f, -10.0f, 10.0f,
|
||||
-10.0f, 10.0f, 10.0f,
|
||||
10.0f, 10.0f, 10.0f,
|
||||
10.0f, 10.0f, 10.0f,
|
||||
10.0f, -10.0f, 10.0f,
|
||||
-10.0f, -10.0f, 10.0f,
|
||||
|
||||
-10.0f, 10.0f, -10.0f,
|
||||
10.0f, 10.0f, -10.0f,
|
||||
10.0f, 10.0f, 10.0f,
|
||||
10.0f, 10.0f, 10.0f,
|
||||
-10.0f, 10.0f, 10.0f,
|
||||
-10.0f, 10.0f, -10.0f,
|
||||
|
||||
-10.0f, -10.0f, -10.0f,
|
||||
-10.0f, -10.0f, 10.0f,
|
||||
10.0f, -10.0f, -10.0f,
|
||||
10.0f, -10.0f, -10.0f,
|
||||
-10.0f, -10.0f, 10.0f,
|
||||
10.0f, -10.0f, 10.0f
|
||||
};
|
||||
|
||||
glGenVertexArrays(1, &RSkybox->VAO);
|
||||
glGenBuffers(1, &RSkybox->VBO);
|
||||
glBindVertexArray(RSkybox->VAO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, RSkybox->VBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, 108*sizeof(GLfloat), Vertices, GL_STATIC_DRAW);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3*sizeof(GLfloat), (GLvoid*)0);
|
||||
glEnableVertexAttribArray(0);
|
||||
|
||||
glBindVertexArray(0);
|
||||
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
stbi_image_free(Image[i]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
RenderSkyBox(SkyBox* RSkybox, RenderConfig* RConfig)
|
||||
{
|
||||
glDepthMask(GL_FALSE);
|
||||
glUseProgram(RSkybox->SkyBoxShader);
|
||||
|
||||
GLint ViewLoc = glGetUniformLocation(RSkybox->SkyBoxShader, "view");
|
||||
GLint ProjLoc = glGetUniformLocation(RSkybox->SkyBoxShader, "projection");
|
||||
|
||||
mat4f_t View = GetFirstPersonView(RConfig->FPSCamera);
|
||||
|
||||
View.mat[12] = 0;
|
||||
View.mat[13] = 0;
|
||||
View.mat[14] = 0;
|
||||
|
||||
glUniformMatrix4fv(ViewLoc, 1, GL_FALSE, View.mat);
|
||||
glUniformMatrix4fv(ProjLoc, 1, GL_FALSE, RConfig->ProjectionMatrix.mat);
|
||||
|
||||
glBindVertexArray(RSkybox->VAO);
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, RSkybox->SkyBoxTexture);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||
glBindVertexArray(0);
|
||||
|
||||
glDepthMask(GL_TRUE);
|
||||
}
|
123
src/engine_renderer.h
Normal file
@ -0,0 +1,123 @@
|
||||
#ifndef H_ENGINE_RENDERER
|
||||
#define H_ENGINE_RENDERER
|
||||
|
||||
#include "engine_math.h"
|
||||
#include "engine_camera.h"
|
||||
#include "engine_chunk.h"
|
||||
#include "engine_text.h"
|
||||
#include "engine_sdl.h"
|
||||
|
||||
#include <GL/glew.h>
|
||||
|
||||
typedef struct TextureAtlas TextureAtlas;
|
||||
|
||||
typedef struct
|
||||
DirectionLight
|
||||
{
|
||||
|
||||
vec3f_t LightColor;
|
||||
vec3f_t LightDirection;
|
||||
float AmbientStrength;
|
||||
|
||||
} DirectionLight;
|
||||
|
||||
typedef struct
|
||||
RenderConfig
|
||||
{
|
||||
|
||||
FirstPersonCamera* FPSCamera;
|
||||
mat4f_t ProjectionMatrix;
|
||||
GLuint ChunkShaderProgram;
|
||||
DirectionLight* DirLight0;
|
||||
DirectionLight* DirLight1;
|
||||
|
||||
} RenderConfig;
|
||||
|
||||
typedef struct
|
||||
FontRenderConfig
|
||||
{
|
||||
GLuint FontTexture;
|
||||
GLuint FontShader;
|
||||
float* TextRenderBuffer;
|
||||
int* RenderIndexBuffer;
|
||||
int BufferLengths;
|
||||
int BufferCount;
|
||||
int* GlyphCounts;
|
||||
GLuint* VBOS;
|
||||
GLuint* VAOS;
|
||||
GLuint* EBOS;
|
||||
} FontRenderConfig;
|
||||
|
||||
typedef struct
|
||||
SkyBox
|
||||
{
|
||||
GLuint SkyBoxShader;
|
||||
GLuint SkyBoxTexture;
|
||||
GLuint VAO;
|
||||
GLuint VBO;
|
||||
} SkyBox;
|
||||
|
||||
void
|
||||
CreateTriangleVertexList(float* vertices,
|
||||
vec3f_t v1,
|
||||
vec3f_t v2,
|
||||
vec3f_t v3,
|
||||
vec3f_t normal,
|
||||
vec3f_t color);
|
||||
|
||||
vec3f_t
|
||||
GetAmbientLightingDL(DirectionLight* Light);
|
||||
|
||||
void
|
||||
InitializeChunkRenderBuffers(Chunk* Chunk, float* RenderBuffer);
|
||||
|
||||
void
|
||||
UpdateChunkRenderBuffers(Chunk* Chunk, float* RenderBuffer);
|
||||
|
||||
void
|
||||
RenderChunks(RenderConfig* Config, Chunk* Chunks, int ChunkCount,
|
||||
int Time, int ApocalypseMode);
|
||||
|
||||
void
|
||||
GenerateQuadFace(float* vertices,
|
||||
vec3f_t v1,
|
||||
vec3f_t v2,
|
||||
vec3f_t v3,
|
||||
vec3f_t v4,
|
||||
vec3f_t normal,
|
||||
vec3f_t color);
|
||||
|
||||
void
|
||||
InitializeFontRenderer(FontRenderConfig* RenderConfig,
|
||||
TextureAtlas* Image,
|
||||
int VBOCount,
|
||||
int BufferSize,
|
||||
GLuint Shader);
|
||||
|
||||
void
|
||||
FreeFontRenderBuffers(FontRenderConfig* RenderConfig);
|
||||
|
||||
void
|
||||
CreateTextBuffer(char* Text, int Buffer,
|
||||
FontRenderConfig* RenderConfig,
|
||||
FontTextureAtlas* Atlas,
|
||||
vec2f_t Origin,
|
||||
int FontSize,
|
||||
WindowSDL* Window);
|
||||
|
||||
void
|
||||
RenderText(int Buffer,
|
||||
FontRenderConfig* RenderConfig);
|
||||
|
||||
vec2f_t
|
||||
ScreenCoordToGLCoord(float X, float Y, WindowSDL* Window);
|
||||
|
||||
void
|
||||
LoadSkyBox(SkyBox* RSkybox, char** SkyBoxImages);
|
||||
|
||||
void
|
||||
RenderSkyBox(SkyBox* RSkybox, RenderConfig* RConfig);
|
||||
|
||||
|
||||
void FreeChunkRenderBuffers(Chunk* Chunk);
|
||||
#endif
|
BIN
src/engine_renderer.o
Normal file
298
src/engine_sdl.c
Normal file
@ -0,0 +1,298 @@
|
||||
#include "engine_sdl.h"
|
||||
|
||||
#include <GL/glew.h>
|
||||
#include <stdio.h>
|
||||
|
||||
void CreateWindowAndGLContext(WindowSDL* Window,
|
||||
char* Title,
|
||||
int Width,
|
||||
int Height)
|
||||
{
|
||||
SDL_Init(SDL_INIT_EVERYTHING);
|
||||
|
||||
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
|
||||
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
|
||||
|
||||
Window->ScreenWidth = Width;
|
||||
Window->ScreenHeight = Height;
|
||||
|
||||
Window->Window = SDL_CreateWindow(Title,
|
||||
SDL_WINDOWPOS_CENTERED,
|
||||
SDL_WINDOWPOS_CENTERED,
|
||||
Width,
|
||||
Height,
|
||||
SDL_WINDOW_OPENGL);
|
||||
|
||||
if (Window->Window)
|
||||
{
|
||||
|
||||
Window->GLContext = SDL_GL_CreateContext(Window->Window);
|
||||
SDL_SetRelativeMouseMode(SDL_TRUE);
|
||||
|
||||
if (Window->GLContext)
|
||||
{
|
||||
GLenum GLEWError = glewInit();
|
||||
|
||||
if (!GLEWError)
|
||||
{
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glViewport(0, 0, Width, Height);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Failed to initialize GLEW\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Failed to create OpenGL Context\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Failed to create SDL window\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 2048) < 0)
|
||||
{
|
||||
printf("Failed to initialize SDL_mixer\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void InitializeInputs(InputSDL* Input)
|
||||
{
|
||||
Input->Quit = 0;
|
||||
Input->TextBufDirty = 0;
|
||||
|
||||
for (int i = 0; i < MAX_KEYS; i++)
|
||||
{
|
||||
Input->Keys[i] = 0;
|
||||
Input->LastKeysState[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int ScancodeToEngineKey(int Key)
|
||||
{
|
||||
|
||||
int EngineKey;
|
||||
|
||||
switch (Key)
|
||||
{
|
||||
case SDL_SCANCODE_UP: EngineKey = K_UP; break;
|
||||
case SDL_SCANCODE_DOWN: EngineKey = K_DOWN; break;
|
||||
case SDL_SCANCODE_RIGHT: EngineKey = K_RIGHT; break;
|
||||
case SDL_SCANCODE_LEFT: EngineKey = K_LEFT; break;
|
||||
case SDL_SCANCODE_W: EngineKey = K_W; break;
|
||||
case SDL_SCANCODE_S: EngineKey = K_S; break;
|
||||
case SDL_SCANCODE_A: EngineKey = K_A; break;
|
||||
case SDL_SCANCODE_D: EngineKey = K_D; break;
|
||||
case SDL_SCANCODE_F: EngineKey = K_F; break;
|
||||
case SDL_SCANCODE_SPACE: EngineKey = K_SPACE; break;
|
||||
case SDL_SCANCODE_U: EngineKey = K_U; break;
|
||||
case SDL_SCANCODE_Q: EngineKey = K_Q; break;
|
||||
case SDL_SCANCODE_E: EngineKey = K_E; break;
|
||||
case SDL_SCANCODE_R: EngineKey = K_R; break;
|
||||
case SDL_SCANCODE_T: EngineKey = K_T; break;
|
||||
case SDL_SCANCODE_Y: EngineKey = K_Y; break;
|
||||
case SDL_SCANCODE_I: EngineKey = K_I; break;
|
||||
case SDL_SCANCODE_O: EngineKey = K_O; break;
|
||||
case SDL_SCANCODE_P: EngineKey = K_P; break;
|
||||
case SDL_SCANCODE_G: EngineKey = K_G; break;
|
||||
case SDL_SCANCODE_H: EngineKey = K_H; break;
|
||||
case SDL_SCANCODE_J: EngineKey = K_J; break;
|
||||
case SDL_SCANCODE_K: EngineKey = K_K; break;
|
||||
case SDL_SCANCODE_L: EngineKey = K_L; break;
|
||||
case SDL_SCANCODE_Z: EngineKey = K_Z; break;
|
||||
case SDL_SCANCODE_X: EngineKey = K_X; break;
|
||||
case SDL_SCANCODE_C: EngineKey = K_C; break;
|
||||
case SDL_SCANCODE_V: EngineKey = K_V; break;
|
||||
case SDL_SCANCODE_B: EngineKey = K_B; break;
|
||||
case SDL_SCANCODE_N: EngineKey = K_N; break;
|
||||
case SDL_SCANCODE_M: EngineKey = K_M; break;
|
||||
case SDL_SCANCODE_GRAVE: EngineKey = K_TILDE; break;
|
||||
case SDL_SCANCODE_RETURN: EngineKey = K_ENTER; break;
|
||||
case SDL_SCANCODE_BACKSPACE: EngineKey = K_BACKSPACE; break;
|
||||
case SDL_SCANCODE_ESCAPE: EngineKey = K_ESCAPE; break;
|
||||
default: EngineKey = -1; break;
|
||||
}
|
||||
|
||||
return EngineKey;
|
||||
|
||||
}
|
||||
|
||||
void PollForInput(InputSDL* Input)
|
||||
{
|
||||
|
||||
for (int i = 0; i < MAX_KEYS; i++)
|
||||
{
|
||||
Input->LastKeysState[i] = Input->Keys[i];
|
||||
}
|
||||
|
||||
SDL_Event Event;
|
||||
while (SDL_PollEvent(&Event))
|
||||
{
|
||||
switch(Event.type)
|
||||
{
|
||||
case SDL_QUIT: {
|
||||
Input->Quit = 1;
|
||||
} break;
|
||||
case SDL_KEYDOWN: {
|
||||
|
||||
int KeyCode = ScancodeToEngineKey(Event.key.keysym.scancode);
|
||||
|
||||
if (KeyCode != -1)
|
||||
{
|
||||
Input->Keys[KeyCode] = 1;
|
||||
}
|
||||
|
||||
} break;
|
||||
case SDL_KEYUP: {
|
||||
|
||||
int KeyCode = ScancodeToEngineKey(Event.key.keysym.scancode);
|
||||
|
||||
if (KeyCode != -1)
|
||||
{
|
||||
Input->Keys[KeyCode] = 0;
|
||||
}
|
||||
|
||||
} break;
|
||||
case SDL_TEXTINPUT: {
|
||||
strcpy(Input->TextInputBuf, Event.text.text);
|
||||
Input->TextBufDirty = 1;
|
||||
} break;
|
||||
default: {
|
||||
|
||||
} break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
WasKeyPressed(InputSDL* Input, int Key)
|
||||
{
|
||||
if (!Input->LastKeysState[Key] &&
|
||||
Input->Keys[Key])
|
||||
{
|
||||
return (1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
StartCapturingTextInput()
|
||||
{
|
||||
SDL_StartTextInput();
|
||||
}
|
||||
|
||||
void
|
||||
StopCapturingTextInput()
|
||||
{
|
||||
SDL_StopTextInput();
|
||||
}
|
||||
|
||||
void
|
||||
PullTextInput(InputSDL* Input, char* Text)
|
||||
{
|
||||
if (!Text)
|
||||
{
|
||||
Input->TextBufDirty = 0;
|
||||
}
|
||||
|
||||
if (Input->TextBufDirty)
|
||||
{
|
||||
strcpy(Text, Input->TextInputBuf);
|
||||
Input->TextBufDirty = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
VELoadSong(VESong* Song, char* Path)
|
||||
{
|
||||
Song->Song = Mix_LoadMUS(Path);
|
||||
if (!Song->Song)
|
||||
{
|
||||
printf("Song failed to load: %s\n", Path);
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
VELoadAudioClip(VEAudioClip* Clip, char* Path, int Channel)
|
||||
{
|
||||
Clip->Clip = Mix_LoadWAV(Path);
|
||||
if (!Clip->Clip)
|
||||
{
|
||||
printf("Audio clip failed to load: %s\n", Path);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
Clip->Channel = Channel;
|
||||
}
|
||||
|
||||
int
|
||||
VEIsMusicPlaying()
|
||||
{
|
||||
return Mix_PlayingMusic();
|
||||
}
|
||||
|
||||
void
|
||||
VEPlayMusic(VESong* Song, int Loops)
|
||||
{
|
||||
if (Mix_PlayMusic(Song->Song, Loops) < 0)
|
||||
{
|
||||
printf("Catastrophic error when attempting to play music.\n");
|
||||
printf("SDL_mixer error: %s\n", Mix_GetError());
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
VEPauseMusic()
|
||||
{
|
||||
Mix_PauseMusic();
|
||||
}
|
||||
|
||||
void
|
||||
VEResumeMusic()
|
||||
{
|
||||
Mix_ResumeMusic();
|
||||
}
|
||||
|
||||
void
|
||||
VEStopMusic()
|
||||
{
|
||||
Mix_HaltMusic();
|
||||
}
|
||||
|
||||
void
|
||||
VEPlayAudioClip(VEAudioClip* Clip, int Loops)
|
||||
{
|
||||
Mix_PlayChannel(Clip->Channel, Clip->Clip, Loops);
|
||||
}
|
||||
|
||||
int
|
||||
VEIsChannelPlaying(VEAudioClip* Clip)
|
||||
{
|
||||
return (Mix_Playing(Clip->Channel));
|
||||
}
|
||||
|
||||
void
|
||||
VEStopAudioClip(VEAudioClip* Clip)
|
||||
{
|
||||
Mix_HaltChannel(Clip->Channel);
|
||||
}
|
||||
|
||||
void
|
||||
VEFadeAudioClip(VEAudioClip* Clip, int Milliseconds)
|
||||
{
|
||||
Mix_FadeOutChannel(Clip->Channel, Milliseconds);
|
||||
}
|
140
src/engine_sdl.h
Normal file
@ -0,0 +1,140 @@
|
||||
#ifndef H_ENGINE_SDL
|
||||
#define H_ENGINE_SDL
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
#include <SDL2/SDL_mixer.h>
|
||||
|
||||
#define MAX_TEXT_BUFFER 50
|
||||
#define MAX_KEYS 34
|
||||
|
||||
enum Keys
|
||||
{
|
||||
K_UP,
|
||||
K_DOWN,
|
||||
K_LEFT,
|
||||
K_RIGHT,
|
||||
K_W,
|
||||
K_A,
|
||||
K_S,
|
||||
K_D,
|
||||
K_F,
|
||||
K_SPACE,
|
||||
K_U,
|
||||
K_Q,
|
||||
K_E,
|
||||
K_R,
|
||||
K_T,
|
||||
K_Y,
|
||||
K_I,
|
||||
K_O,
|
||||
K_P,
|
||||
K_G,
|
||||
K_H,
|
||||
K_J,
|
||||
K_K,
|
||||
K_L,
|
||||
K_Z,
|
||||
K_X,
|
||||
K_C,
|
||||
K_V,
|
||||
K_B,
|
||||
K_N,
|
||||
K_M,
|
||||
K_TILDE,
|
||||
K_ENTER,
|
||||
K_ESCAPE,
|
||||
K_BACKSPACE
|
||||
};
|
||||
|
||||
typedef struct
|
||||
WindowSDL
|
||||
{
|
||||
|
||||
SDL_Window* Window;
|
||||
SDL_GLContext GLContext;
|
||||
|
||||
int ScreenWidth;
|
||||
int ScreenHeight;
|
||||
|
||||
} WindowSDL;
|
||||
|
||||
typedef struct
|
||||
InputSDL
|
||||
{
|
||||
int Quit;
|
||||
int LastKeysState[MAX_KEYS];
|
||||
int Keys[MAX_KEYS];
|
||||
char TextInputBuf[MAX_TEXT_BUFFER];
|
||||
int TextBufDirty;
|
||||
} InputSDL;
|
||||
|
||||
typedef struct
|
||||
VESong
|
||||
{
|
||||
Mix_Music* Song;
|
||||
} VESong;
|
||||
|
||||
typedef struct
|
||||
VEAudioClip
|
||||
{
|
||||
Mix_Chunk* Clip;
|
||||
int Channel;
|
||||
} VEAudioClip;
|
||||
|
||||
void CreateWindowAndGLContext(WindowSDL* Window,
|
||||
char* Title,
|
||||
int Width,
|
||||
int Height);
|
||||
|
||||
void InitializeInputs(InputSDL* Input);
|
||||
|
||||
int EngineInputToScancode(int key);
|
||||
|
||||
void PollForInput(InputSDL* Input);
|
||||
|
||||
int
|
||||
WasKeyPressed(InputSDL* Input, int Key);
|
||||
|
||||
void
|
||||
StartCapturingTextInput();
|
||||
|
||||
void
|
||||
StopCapturingTextInput();
|
||||
|
||||
void
|
||||
PullTextInput(InputSDL* Input, char* Text);
|
||||
|
||||
void
|
||||
VELoadSong(VESong* Song, char* Path);
|
||||
|
||||
void
|
||||
VELoadAudioClip(VEAudioClip* Clip, char* Path, int Channel);
|
||||
|
||||
int
|
||||
VEIsMusicPlaying();
|
||||
|
||||
void
|
||||
VEPlayMusic(VESong* Song, int Loops);
|
||||
|
||||
void
|
||||
VEPauseMusic();
|
||||
|
||||
void
|
||||
VEResumeMusic();
|
||||
|
||||
void
|
||||
VEStopMusic();
|
||||
|
||||
void
|
||||
VEPlayAudioClip(VEAudioClip* Clip, int Loops);
|
||||
|
||||
int
|
||||
VEIsChannelPlaying(VEAudioClip* Clip);
|
||||
|
||||
void
|
||||
VEStopAudioClip(VEAudioClip* Clip);
|
||||
|
||||
void
|
||||
VEFadeAudioClip(VEAudioClip* Clip, int Milliseconds);
|
||||
|
||||
#endif
|
BIN
src/engine_sdl.o
Normal file
110
src/engine_shader.c
Normal file
@ -0,0 +1,110 @@
|
||||
#include "engine_shader.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
void
|
||||
CreateShaderProgram(GLuint* Program, char* VertexShaderPath, char* FragmentShaderPath)
|
||||
{
|
||||
FILE *VertexShaderFile, *FragmentShaderFile;
|
||||
char *VertexShader, *FragmentShader;
|
||||
int fileSize, c;
|
||||
|
||||
VertexShaderFile = fopen(VertexShaderPath, "rb");
|
||||
|
||||
if (!VertexShaderFile)
|
||||
{
|
||||
printf("Vertex shader file does not exist");
|
||||
}
|
||||
|
||||
fseek(VertexShaderFile, 0, SEEK_END);
|
||||
fileSize = ftell(VertexShaderFile);
|
||||
fseek(VertexShaderFile, 0, SEEK_SET);
|
||||
|
||||
VertexShader = malloc(fileSize+1);
|
||||
|
||||
if (!VertexShader)
|
||||
{
|
||||
printf("Could not allocate memory for vertex shader");
|
||||
}
|
||||
|
||||
fread(VertexShader, 1, fileSize, VertexShaderFile);
|
||||
VertexShader[fileSize] = '\0';
|
||||
|
||||
fclose(VertexShaderFile);
|
||||
|
||||
FragmentShaderFile = fopen(FragmentShaderPath, "rb");
|
||||
|
||||
if (!FragmentShaderFile)
|
||||
{
|
||||
printf("Fragment shader file does not exist");
|
||||
}
|
||||
|
||||
fseek(FragmentShaderFile, 0, SEEK_END);
|
||||
fileSize = ftell(FragmentShaderFile);
|
||||
fseek(FragmentShaderFile, 0, SEEK_SET);
|
||||
|
||||
FragmentShader = malloc(fileSize+1);
|
||||
|
||||
if (!FragmentShader)
|
||||
{
|
||||
printf("Could not allocate memory for fragment shader");
|
||||
}
|
||||
|
||||
fread(FragmentShader, 1, fileSize, FragmentShaderFile);
|
||||
FragmentShader[fileSize] = '\0';
|
||||
|
||||
fclose(FragmentShaderFile);
|
||||
|
||||
GLuint GL_VertexShader, GL_FragmentShader;
|
||||
GLint Success;
|
||||
GLchar InfoLog[512];
|
||||
|
||||
GL_VertexShader = glCreateShader(GL_VERTEX_SHADER);
|
||||
glShaderSource(GL_VertexShader, 1,
|
||||
(const char * const*) &VertexShader, 0);
|
||||
glCompileShader(GL_VertexShader);
|
||||
|
||||
glGetShaderiv(GL_VertexShader, GL_COMPILE_STATUS, &Success);
|
||||
|
||||
if (!Success)
|
||||
{
|
||||
glGetShaderInfoLog(GL_VertexShader, 512, 0, InfoLog);
|
||||
printf("ERROR->SHADER->VERTEX->COMPILATION: SEE LOG BELOW\n");
|
||||
printf(InfoLog);
|
||||
}
|
||||
|
||||
GL_FragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
glShaderSource(GL_FragmentShader, 1, (const char * const*) &FragmentShader, 0);
|
||||
glCompileShader(GL_FragmentShader);
|
||||
|
||||
glGetShaderiv(GL_FragmentShader, GL_COMPILE_STATUS, &Success);
|
||||
|
||||
if (!Success)
|
||||
{
|
||||
glGetShaderInfoLog(GL_FragmentShader, 512, 0, InfoLog);
|
||||
printf("ERROR->SHADER->FRAGMENT->COMPILATION: SEE LOG BELOW\n");
|
||||
printf(InfoLog);
|
||||
}
|
||||
|
||||
*Program = glCreateProgram();
|
||||
|
||||
glAttachShader(*Program, GL_VertexShader);
|
||||
glAttachShader(*Program, GL_FragmentShader);
|
||||
glLinkProgram(*Program);
|
||||
|
||||
glGetProgramiv(*Program, GL_LINK_STATUS, &Success);
|
||||
|
||||
if (!Success)
|
||||
{
|
||||
glGetProgramInfoLog(*Program, 512, 0, InfoLog);
|
||||
printf("ERROR->PROGRAM->LINKING: SEE LOG BELOW\n");
|
||||
printf(InfoLog);
|
||||
}
|
||||
|
||||
glDeleteShader(GL_VertexShader);
|
||||
glDeleteShader(GL_FragmentShader);
|
||||
|
||||
free(VertexShader);
|
||||
free(FragmentShader);
|
||||
|
||||
}
|
9
src/engine_shader.h
Normal file
@ -0,0 +1,9 @@
|
||||
#ifndef H_ENGINE_SHADER
|
||||
#define H_ENGINE_SHADER
|
||||
|
||||
#include <GL/glew.h>
|
||||
#include <stdio.h>
|
||||
|
||||
void CreateShaderProgram(GLuint* Program, char* VertexShader, char* FragmentShader);
|
||||
|
||||
#endif
|
BIN
src/engine_shader.o
Normal file
131
src/engine_text.c
Normal file
@ -0,0 +1,131 @@
|
||||
#include "engine_text.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#include "stb_image.h"
|
||||
|
||||
void
|
||||
LoadCharacterMapping(FontTextureAtlas* Atlas,
|
||||
char* TexturePath,
|
||||
char* MappingPath)
|
||||
{
|
||||
FILE *MappingFile;
|
||||
|
||||
MappingFile = fopen(MappingPath, "rb");
|
||||
|
||||
if (!MappingFile)
|
||||
{
|
||||
printf("Mapping file does not exist");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
char Buffer[1000];
|
||||
char Line[1000];
|
||||
|
||||
// Skip first 3 lines for now
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
fgets(Buffer, 1000, MappingFile);
|
||||
}
|
||||
|
||||
// Get char count
|
||||
int CharCount;
|
||||
int Index = 0, LineIndex = 0;
|
||||
|
||||
fgets(Buffer, 1000, MappingFile);
|
||||
|
||||
for (; Buffer[Index] != '='; Index++) {};
|
||||
|
||||
Index++;
|
||||
for (; Buffer[Index] != '\n' && Buffer[Index] != ' '; Index++, LineIndex++)
|
||||
{
|
||||
Line[LineIndex] = Buffer[Index];
|
||||
}
|
||||
|
||||
Line[LineIndex] = '\n';
|
||||
|
||||
CharCount = atoi(Line);
|
||||
|
||||
for (int i = 0; i < CharCount; i++)
|
||||
{
|
||||
if (fgets(Buffer, 1000, MappingFile) != 0)
|
||||
{
|
||||
Index = 0;
|
||||
|
||||
// Get ASCII Character ID
|
||||
int ID = ParseIntValue(Buffer, &Index);
|
||||
|
||||
Atlas->Characters[ID].ID = ID;
|
||||
|
||||
// Get X position
|
||||
Atlas->Characters[ID].X = ParseIntValue(Buffer, &Index);
|
||||
|
||||
// Get Y position
|
||||
Atlas->Characters[ID].Y = ParseIntValue(Buffer, &Index);
|
||||
|
||||
// Get Width
|
||||
Atlas->Characters[ID].Width = ParseIntValue(Buffer, &Index);
|
||||
|
||||
// Get Height
|
||||
Atlas->Characters[ID].Height = ParseIntValue(Buffer, &Index);
|
||||
|
||||
// X Offset
|
||||
Atlas->Characters[ID].XOffset = ParseIntValue(Buffer, &Index);
|
||||
|
||||
// Y Offset
|
||||
Atlas->Characters[ID].YOffset = ParseIntValue(Buffer, &Index);
|
||||
}
|
||||
}
|
||||
|
||||
Atlas->AtlasImage.ImageFile = stbi_load("../data/font/font.png",
|
||||
&(Atlas->AtlasImage.Width),
|
||||
&(Atlas->AtlasImage.Height),
|
||||
&(Atlas->AtlasImage.BPP), 0);
|
||||
if (!(Atlas->AtlasImage.ImageFile))
|
||||
{
|
||||
printf("Loading of Bitmap Font File failed\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
FreeCharacterMapping(FontTextureAtlas* Atlas)
|
||||
{
|
||||
stbi_image_free(Atlas->AtlasImage.ImageFile);
|
||||
}
|
||||
|
||||
int
|
||||
ParseIntValue(char* Buffer, int* Index)
|
||||
{
|
||||
char Line[1000];
|
||||
memset(Line, '\n', sizeof(Line));
|
||||
int LineIndex = 0;
|
||||
|
||||
for (; Buffer[*Index] != '='; (*Index)++) {};
|
||||
(*Index)++;
|
||||
|
||||
for (; Buffer[(*Index)] != ' '; (*Index)++, LineIndex++)
|
||||
{
|
||||
Line[LineIndex] = Buffer[(*Index)];
|
||||
}
|
||||
|
||||
Line[LineIndex] = '\n';
|
||||
|
||||
return (atoi(Line));
|
||||
}
|
||||
|
||||
void
|
||||
CharacterGetGLDimensions(CharacterMapping* Character,
|
||||
TextureAtlas* Image,
|
||||
vec2f_t* Origin,
|
||||
float* Width, float* Height,
|
||||
float* YOffset)
|
||||
{
|
||||
|
||||
Origin->x = ((float)Character->X) / ((float)Image->Width);
|
||||
Origin->y = ((float)Character->Y) / ((float)Image->Height);
|
||||
*Width = (((float)Character->Width) / ((float)Image->Width));
|
||||
*Height = (((float)Character->Height) / ((float)Image->Height));
|
||||
*YOffset = (((float)Character->YOffset) / ((float)Image->Height));
|
||||
}
|
54
src/engine_text.h
Normal file
@ -0,0 +1,54 @@
|
||||
#ifndef H_ENGINE_TEXT
|
||||
#define H_ENGINE_TEXT
|
||||
|
||||
#include <GL/glew.h>
|
||||
|
||||
#include "engine_math.h"
|
||||
|
||||
typedef struct
|
||||
CharacterMapping
|
||||
{
|
||||
int ID;
|
||||
int X;
|
||||
int Y;
|
||||
int Width;
|
||||
int Height;
|
||||
int XOffset;
|
||||
int YOffset;
|
||||
} CharacterMapping;
|
||||
|
||||
typedef struct
|
||||
TextureAtlas
|
||||
{
|
||||
int Width;
|
||||
int Height;
|
||||
int BPP;
|
||||
unsigned char* ImageFile;
|
||||
} TextureAtlas;
|
||||
|
||||
typedef struct
|
||||
FontTextureAtlas
|
||||
{
|
||||
TextureAtlas AtlasImage;
|
||||
CharacterMapping Characters[256];
|
||||
} FontTextureAtlas;
|
||||
|
||||
void
|
||||
LoadCharacterMapping(FontTextureAtlas* Atlas,
|
||||
char* TexturePath,
|
||||
char* MappingPath);
|
||||
|
||||
void
|
||||
FreeCharacterMapping(FontTextureAtlas* Atlas);
|
||||
|
||||
int
|
||||
ParseIntValue(char* Buffer, int* Index);
|
||||
|
||||
void
|
||||
CharacterGetGLDimensions(CharacterMapping* Character,
|
||||
TextureAtlas* Image,
|
||||
vec2f_t* Origin,
|
||||
float* Width, float* Height,
|
||||
float* YOffset);
|
||||
|
||||
#endif
|
BIN
src/engine_text.o
Normal file
190
src/engine_ui.c
Normal file
@ -0,0 +1,190 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "engine_ui.h"
|
||||
#include "engine_shader.h"
|
||||
|
||||
global FontRenderConfig TextRenderConfig;
|
||||
global FontTextureAtlas FontAtlas;
|
||||
global GLuint FontShaderProgram;
|
||||
|
||||
global VUI_TextElement FPSCounter;
|
||||
global VUI_TextElement CubeCounter;
|
||||
global VUI_TextElement PhysicsInfo;
|
||||
global VUI_TextElement PlayerInfo;
|
||||
global VUI_TextElement ConsoleBox;
|
||||
|
||||
global WindowSDL* WindowRef;
|
||||
|
||||
global float SumTime = 0;
|
||||
global int Wait = 300;
|
||||
|
||||
void
|
||||
LayoutTextElements(WindowSDL* Window, int CubeTotal)
|
||||
{
|
||||
WindowRef = Window;
|
||||
|
||||
CreateShaderProgram(&FontShaderProgram, "../data/shaders/text_vertex.vert",
|
||||
"../data/shaders/text_fragment.frag");
|
||||
|
||||
LoadCharacterMapping(&FontAtlas, 0, "../data/font/font.fnt");
|
||||
|
||||
InitializeFontRenderer(&TextRenderConfig,
|
||||
&FontAtlas.AtlasImage,
|
||||
5,
|
||||
2500,
|
||||
FontShaderProgram);
|
||||
|
||||
// FPS COUNTER
|
||||
|
||||
FPSCounter.Text = malloc(sizeof(char)*10);
|
||||
sprintf(FPSCounter.Text, "FPS: %.1f", 0.0);
|
||||
|
||||
FPSCounter.RenderConfig = &TextRenderConfig;
|
||||
FPSCounter.Buffer = 0;
|
||||
FPSCounter.Position = Vec2f(15.0f, 30.0f);
|
||||
|
||||
CreateTextBuffer(FPSCounter.Text, 0,
|
||||
&TextRenderConfig,
|
||||
&FontAtlas,
|
||||
FPSCounter.Position,
|
||||
12,
|
||||
Window);
|
||||
// CUBE COUNTER
|
||||
CubeCounter.Text = malloc(sizeof(char)*50);
|
||||
sprintf(CubeCounter.Text, "Rendered Voxels: %d", CubeTotal);
|
||||
CubeCounter.RenderConfig = &TextRenderConfig;
|
||||
CubeCounter.Buffer = 1;
|
||||
CubeCounter.Position = Vec2f(15.0f, Window->ScreenHeight-10.0f);
|
||||
|
||||
CreateTextBuffer(CubeCounter.Text, 1,
|
||||
&TextRenderConfig,
|
||||
&FontAtlas,
|
||||
CubeCounter.Position,
|
||||
12,
|
||||
Window);
|
||||
|
||||
// PHYSICS INFORMATION
|
||||
PhysicsInfo.Text = malloc(sizeof(char)*200);
|
||||
sprintf(PhysicsInfo.Text, "Physics Info:");
|
||||
PhysicsInfo.RenderConfig = &TextRenderConfig;
|
||||
PhysicsInfo.Buffer = 2;
|
||||
PhysicsInfo.Position = Vec2f(15.0f, Window->ScreenHeight-35.0f);
|
||||
|
||||
CreateTextBuffer(PhysicsInfo.Text, 2,
|
||||
&TextRenderConfig,
|
||||
&FontAtlas,
|
||||
PhysicsInfo.Position,
|
||||
8,
|
||||
Window);
|
||||
|
||||
// PLAYER INFORMATION
|
||||
PlayerInfo.Text = malloc(sizeof(char)*200);
|
||||
sprintf(PlayerInfo.Text, "Free Fly Mode:");
|
||||
PlayerInfo.RenderConfig = &TextRenderConfig;
|
||||
PlayerInfo.Buffer = 3;
|
||||
PlayerInfo.Position = Vec2f(Window->ScreenWidth-225.0, 30.0f);
|
||||
|
||||
CreateTextBuffer(PlayerInfo.Text, 3,
|
||||
&TextRenderConfig,
|
||||
&FontAtlas,
|
||||
PlayerInfo.Position,
|
||||
12,
|
||||
Window);
|
||||
|
||||
// CONSOLE
|
||||
ConsoleBox.Text = malloc(sizeof(char)*600);
|
||||
sprintf(ConsoleBox.Text, "");
|
||||
ConsoleBox.RenderConfig = &TextRenderConfig;
|
||||
ConsoleBox.Buffer = 4;
|
||||
ConsoleBox.Position = Vec2f(300, 500);
|
||||
|
||||
CreateTextBuffer(ConsoleBox.Text, 4,
|
||||
&TextRenderConfig,
|
||||
&FontAtlas,
|
||||
ConsoleBox.Position,
|
||||
16,
|
||||
Window);
|
||||
}
|
||||
|
||||
void
|
||||
UpdateTextElements(GameClock* Clock, VEPlayer* Player, VEConsole* Console,
|
||||
int CubeTotal)
|
||||
{
|
||||
|
||||
SumTime += Clock->DeltaTime;
|
||||
|
||||
if (SumTime > Wait)
|
||||
{
|
||||
|
||||
sprintf(FPSCounter.Text, "FPS: %.1f", Clock->FPS);
|
||||
CreateTextBuffer(FPSCounter.Text, 0,
|
||||
&TextRenderConfig,
|
||||
&FontAtlas,
|
||||
FPSCounter.Position,
|
||||
12,
|
||||
WindowRef);
|
||||
|
||||
SumTime = 0;
|
||||
}
|
||||
|
||||
sprintf(CubeCounter.Text, "Rendered Voxels: %d", CubeTotal);
|
||||
CreateTextBuffer(CubeCounter.Text, 1,
|
||||
&TextRenderConfig,
|
||||
&FontAtlas,
|
||||
CubeCounter.Position,
|
||||
12,
|
||||
WindowRef);
|
||||
|
||||
sprintf(PhysicsInfo.Text, "Physics Info: Position(%.3f, %.3f, %.3f)",
|
||||
Player->Body.Position.x, Player->Body.Position.y, Player->Body.Position.z);
|
||||
|
||||
CreateTextBuffer(PhysicsInfo.Text, 2,
|
||||
&TextRenderConfig,
|
||||
&FontAtlas,
|
||||
PhysicsInfo.Position,
|
||||
10,
|
||||
WindowRef);
|
||||
|
||||
if (Player->FlyMode)
|
||||
{
|
||||
sprintf(PlayerInfo.Text, "Free Fly Mode: On");
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(PlayerInfo.Text, "Free Fly Mode: Off");
|
||||
}
|
||||
|
||||
CreateTextBuffer(PlayerInfo.Text, 3,
|
||||
&TextRenderConfig,
|
||||
&FontAtlas,
|
||||
PlayerInfo.Position,
|
||||
12,
|
||||
WindowRef);
|
||||
|
||||
if (Console->Enabled)
|
||||
{
|
||||
sprintf(ConsoleBox.Text, ">> %s", Console->CmdBuffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(ConsoleBox.Text, "");
|
||||
}
|
||||
|
||||
CreateTextBuffer(ConsoleBox.Text, 4,
|
||||
&TextRenderConfig,
|
||||
&FontAtlas,
|
||||
ConsoleBox.Position,
|
||||
16,
|
||||
WindowRef);
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
RenderUI()
|
||||
{
|
||||
RenderText(0, &TextRenderConfig);
|
||||
RenderText(1, &TextRenderConfig);
|
||||
RenderText(2, &TextRenderConfig);
|
||||
RenderText(3, &TextRenderConfig);
|
||||
RenderText(4, &TextRenderConfig);
|
||||
}
|
30
src/engine_ui.h
Normal file
@ -0,0 +1,30 @@
|
||||
#ifndef H_ENGINE_UI
|
||||
#define H_ENGINE_UI
|
||||
|
||||
#include "engine_renderer.h"
|
||||
#include "engine_math.h"
|
||||
#include "engine_player.h"
|
||||
#include "engine_clock.h"
|
||||
#include "engine_console.h"
|
||||
|
||||
typedef struct
|
||||
VUI_TextElement
|
||||
{
|
||||
|
||||
char* Text;
|
||||
FontRenderConfig* RenderConfig;
|
||||
int Buffer;
|
||||
vec2f_t Position;
|
||||
} VUI_TextElement;
|
||||
|
||||
void
|
||||
LayoutTextElements(WindowSDL* Window, int CubeTotal);
|
||||
|
||||
void
|
||||
UpdateTextElements(GameClock* Clock, VEPlayer* Player, VEConsole* Console,
|
||||
int CubeTotal);
|
||||
|
||||
void
|
||||
RenderUI();
|
||||
|
||||
#endif
|
BIN
src/engine_ui.o
Normal file
340
src/engine_world.c
Normal file
@ -0,0 +1,340 @@
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "engine_math.h"
|
||||
#include "engine_world.h"
|
||||
#include "engine_generation.h"
|
||||
#include "engine_camera.h"
|
||||
#include "engine_renderer.h"
|
||||
|
||||
void
|
||||
InitializeWorld(CubeWorld* World,
|
||||
CubeType* CubeTypes,
|
||||
int X, int Z, int Height,
|
||||
int ChunkSize,
|
||||
float PerlinXSeed, float PerlinZSeed, float Inc,
|
||||
int Octaves, float Persistence)
|
||||
{
|
||||
|
||||
float* RenderVertexBuffer;
|
||||
int RVBSize;
|
||||
|
||||
RVBSize = sizeof(float) * RENDER_FLOATS_PER_CUBE_VERTEX
|
||||
* ChunkSize * ChunkSize * ChunkSize
|
||||
* 6 * 6;
|
||||
|
||||
RenderVertexBuffer = malloc(RVBSize);
|
||||
|
||||
World->WorldChunks = malloc(sizeof(Chunk)*X*Z*Height);
|
||||
World->ChunkDirtyList = malloc(sizeof(int)*X*Z*Height);
|
||||
|
||||
World->WorldIsDirty = 0;
|
||||
World->TotalRebuild = 0;
|
||||
World->PhysicsModelDirty = 0;
|
||||
|
||||
World->CubeTypes = CubeTypes;
|
||||
|
||||
World->ChunkCount = X*Z*Height;
|
||||
World->ChunkDimension = ChunkSize;
|
||||
|
||||
World->XLength = X;
|
||||
World->ZLength = Z;
|
||||
World->StackHeight = Height;
|
||||
|
||||
World->PerlinXSeed = PerlinXSeed;
|
||||
World->PerlinZSeed = PerlinZSeed;
|
||||
World->Increment = Inc;
|
||||
World->Octaves = Octaves;
|
||||
World->Persistence = Persistence;
|
||||
|
||||
World->DayNightCycle = 0;
|
||||
World->Apocalypse = 0;
|
||||
World->Spheres = 0;
|
||||
|
||||
for (int s = 0; s < SPHERE_DEMO_COUNT; s++)
|
||||
{
|
||||
InitializeChunk(&World->Sphere[s], ChunkSize,
|
||||
Vec3f(s*ChunkSize,
|
||||
0,
|
||||
-ChunkSize));
|
||||
|
||||
GenerateSphereChunk(&World->Sphere[s]);
|
||||
|
||||
GreedyMesh(&World->Sphere[s], World->CubeTypes, RenderVertexBuffer, &RVBSize);
|
||||
InitializeChunkRenderBuffers(&World->Sphere[s], RenderVertexBuffer);
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
|
||||
for (int y = 0; y < Height; y++)
|
||||
{
|
||||
for (int z = 0; z < Z; z++)
|
||||
{
|
||||
for (int x = 0; x < X; x++)
|
||||
{
|
||||
World->ChunkDirtyList[i] = 0;
|
||||
|
||||
InitializeChunk(&World->WorldChunks[i], ChunkSize,
|
||||
Vec3f(x*ChunkSize,
|
||||
y*ChunkSize,
|
||||
z*ChunkSize));
|
||||
|
||||
GenerateOctavedPerlinChunk(PerlinXSeed+(x*Inc*ChunkSize),
|
||||
PerlinZSeed+(z*Inc*ChunkSize),
|
||||
Inc,
|
||||
&World->WorldChunks[i], y, Height,
|
||||
Octaves, Persistence);
|
||||
|
||||
ChunkEarthBiomeWash(&World->WorldChunks[i]);
|
||||
|
||||
GreedyMesh(&World->WorldChunks[i], World->CubeTypes, RenderVertexBuffer, &RVBSize);
|
||||
|
||||
InitializeChunkRenderBuffers(&World->WorldChunks[i], RenderVertexBuffer);
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(RenderVertexBuffer);
|
||||
}
|
||||
|
||||
void
|
||||
ReseedWorld(CubeWorld* World,
|
||||
CubeType* CubeTypes,
|
||||
float PerlinXSeed, float PerlinZSeed, float Inc,
|
||||
int Octaves, float Persistence)
|
||||
{
|
||||
World->WorldIsDirty = 1;
|
||||
|
||||
World->PerlinXSeed = PerlinXSeed;
|
||||
World->PerlinZSeed = PerlinZSeed;
|
||||
World->Increment = Inc;
|
||||
World->Octaves = Octaves;
|
||||
World->Persistence = Persistence;
|
||||
|
||||
int RVBSize;
|
||||
|
||||
RVBSize = sizeof(float) * RENDER_FLOATS_PER_CUBE_VERTEX
|
||||
* World->ChunkDimension * World->ChunkDimension * World->ChunkDimension
|
||||
* 6 * 6;
|
||||
|
||||
World->RenderVertexBuffer = malloc(RVBSize);
|
||||
|
||||
int i = 0;
|
||||
|
||||
for (int y = 0; y < World->StackHeight; y++)
|
||||
{
|
||||
for (int z = 0; z < World->ZLength; z++)
|
||||
{
|
||||
for (int x = 0; x < World->XLength; x++)
|
||||
{
|
||||
World->ChunkDirtyList[i] = 1;
|
||||
World->WorldChunks[i].PerlinXSeed = PerlinXSeed + (x*Inc*World->ChunkDimension);
|
||||
World->WorldChunks[i].PerlinZSeed = PerlinZSeed + (z*Inc*World->ChunkDimension);
|
||||
World->WorldChunks[i].YLevel = y;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
UpdateWorld(CubeWorld* World)
|
||||
{
|
||||
if (World->WorldIsDirty)
|
||||
{
|
||||
|
||||
int ChkIndex = 0;
|
||||
|
||||
while (ChkIndex < World->ChunkCount && !World->ChunkDirtyList[ChkIndex])
|
||||
{
|
||||
ChkIndex++;
|
||||
}
|
||||
|
||||
if (ChkIndex < World->ChunkCount && World->ChunkDirtyList[ChkIndex])
|
||||
{
|
||||
int RVBSize;
|
||||
|
||||
RVBSize = sizeof(float) * RENDER_FLOATS_PER_CUBE_VERTEX
|
||||
* World->ChunkDimension * World->ChunkDimension * World->ChunkDimension
|
||||
* 6 * 6;
|
||||
|
||||
GenerateOctavedPerlinChunk(World->WorldChunks[ChkIndex].PerlinXSeed,
|
||||
World->WorldChunks[ChkIndex].PerlinZSeed,
|
||||
World->Increment,
|
||||
&World->WorldChunks[ChkIndex],
|
||||
World->WorldChunks[ChkIndex].YLevel,
|
||||
World->StackHeight,
|
||||
World->Octaves, World->Persistence);
|
||||
|
||||
ChunkEarthBiomeWash(&World->WorldChunks[ChkIndex]);
|
||||
|
||||
GreedyMesh(&World->WorldChunks[ChkIndex], World->CubeTypes,
|
||||
World->RenderVertexBuffer, &RVBSize);
|
||||
|
||||
if (!World->TotalRebuild)
|
||||
{
|
||||
UpdateChunkRenderBuffers(&World->WorldChunks[ChkIndex], World->RenderVertexBuffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
InitializeChunkRenderBuffers(&World->WorldChunks[ChkIndex],
|
||||
World->RenderVertexBuffer);
|
||||
}
|
||||
|
||||
World->ChunkDirtyList[ChkIndex] = 0;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
World->WorldIsDirty = 0;
|
||||
World->TotalRebuild = 0;
|
||||
free(World->RenderVertexBuffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
InitializePlayer(CubeWorld* World, vec3f_t Position,
|
||||
float CameraPitch, float CameraYaw)
|
||||
{
|
||||
World->Player.Body.Position = Position;
|
||||
|
||||
World->Player.Camera.Position = World->Player.Body.Position;
|
||||
World->Player.Camera.Pitch = CameraPitch;
|
||||
World->Player.Camera.Yaw = CameraYaw;
|
||||
}
|
||||
|
||||
Chunk*
|
||||
GetChunkFromPosition(CubeWorld* World, vec3f_t Position)
|
||||
{
|
||||
|
||||
if (Position.x < 0 || Position.x >= World->XLength*World->ChunkDimension) return (0);
|
||||
if (Position.y < 0 || Position.y >= World->StackHeight*World->ChunkDimension) return (0);
|
||||
if (Position.z < 0 || Position.z >= World->ZLength*World->ChunkDimension) return (0);
|
||||
|
||||
int LowerBoundX = floor(Position.x / World->ChunkDimension);
|
||||
int LowerBoundZ = floor(Position.z / World->ChunkDimension);
|
||||
|
||||
return (&World->WorldChunks[LowerBoundZ*World->ZLength + LowerBoundX]);
|
||||
}
|
||||
|
||||
PhysicsStaticGeometry*
|
||||
GetStaticChunkGeometryInformation(CubeWorld* World)
|
||||
{
|
||||
PhysicsStaticGeometry* Geometry = malloc(sizeof(PhysicsStaticGeometry));
|
||||
Geometry->ChunkList = &(World->WorldChunks);
|
||||
Geometry->AABBList = malloc(sizeof(PhysicsAABB)*World->ChunkCount);
|
||||
Geometry->AABBCount = World->ChunkCount;
|
||||
|
||||
for (int i = 0; i < World->ChunkCount; i++)
|
||||
{
|
||||
Geometry->AABBList[i].Min = World->WorldChunks[i].Transform;
|
||||
Geometry->AABBList[i].Max = AddVec3f(World->WorldChunks[i].Transform,
|
||||
Vec3f(World->ChunkDimension, World->ChunkDimension, World->ChunkDimension));
|
||||
}
|
||||
|
||||
return (Geometry);
|
||||
}
|
||||
|
||||
void
|
||||
RebuildStaticChunkGeometryInformation(CubeWorld* World,
|
||||
PhysicsStaticGeometry* Geo)
|
||||
{
|
||||
Geo->ChunkList = &(World->WorldChunks);
|
||||
free(Geo->AABBList);
|
||||
Geo->AABBList = malloc(sizeof(PhysicsAABB)*World->ChunkCount);
|
||||
Geo->AABBCount = World->ChunkCount;
|
||||
|
||||
for (int i = 0; i < World->ChunkCount; i++)
|
||||
{
|
||||
Geo->AABBList[i].Min = World->WorldChunks[i].Transform;
|
||||
Geo->AABBList[i].Max = AddVec3f(World->WorldChunks[i].Transform,
|
||||
Vec3f(World->ChunkDimension, World->ChunkDimension, World->ChunkDimension));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
GetActiveCubeCount(CubeWorld* World)
|
||||
{
|
||||
int Sum = 0;
|
||||
for (int i = 0; i < World->ChunkCount; i++)
|
||||
{
|
||||
Sum += World->WorldChunks[i].ActiveCubes;
|
||||
}
|
||||
return (Sum);
|
||||
}
|
||||
|
||||
void
|
||||
RedoWorld(CubeWorld* World,
|
||||
int X, int Z, int Height,
|
||||
int ChunkSize,
|
||||
float PerlinXSeed, float PerlinZSeed, float Inc,
|
||||
int Octaves, float Persistence)
|
||||
{
|
||||
for (int i = 0; i < World->ChunkCount; i++)
|
||||
{
|
||||
FreeChunk(&World->WorldChunks[i]);
|
||||
FreeChunkRenderBuffers(&World->WorldChunks[i]);
|
||||
}
|
||||
|
||||
free(World->WorldChunks);
|
||||
free(World->ChunkDirtyList);
|
||||
|
||||
int RVBSize;
|
||||
|
||||
RVBSize = sizeof(float) * RENDER_FLOATS_PER_CUBE_VERTEX
|
||||
* ChunkSize * ChunkSize * ChunkSize
|
||||
* 6 * 6;
|
||||
|
||||
World->RenderVertexBuffer = malloc(RVBSize);
|
||||
|
||||
World->WorldChunks = malloc(sizeof(Chunk)*X*Z*Height);
|
||||
World->ChunkDirtyList = malloc(sizeof(int)*X*Z*Height);
|
||||
|
||||
World->WorldIsDirty = 1;
|
||||
World->TotalRebuild = 1;
|
||||
|
||||
World->ChunkCount = X*Z*Height;
|
||||
World->ChunkDimension = ChunkSize;
|
||||
|
||||
World->XLength = X;
|
||||
World->ZLength = Z;
|
||||
World->StackHeight = Height;
|
||||
|
||||
World->PerlinXSeed = PerlinXSeed;
|
||||
World->PerlinZSeed = PerlinZSeed;
|
||||
World->Increment = Inc;
|
||||
World->Octaves = Octaves;
|
||||
World->Persistence = Persistence;
|
||||
|
||||
World->DayNightCycle = 0;
|
||||
World->Apocalypse = 0;
|
||||
World->Spheres = 0;
|
||||
|
||||
World->PhysicsModelDirty = 1;
|
||||
|
||||
int i = 0;
|
||||
|
||||
for (int y = 0; y < World->StackHeight; y++)
|
||||
{
|
||||
for (int z = 0; z < World->ZLength; z++)
|
||||
{
|
||||
for (int x = 0; x < World->XLength; x++)
|
||||
{
|
||||
InitializeChunk(&World->WorldChunks[i], ChunkSize,
|
||||
Vec3f(x*ChunkSize,
|
||||
y*ChunkSize,
|
||||
z*ChunkSize));
|
||||
|
||||
World->ChunkDirtyList[i] = 1;
|
||||
World->WorldChunks[i].PerlinXSeed = PerlinXSeed + (x*Inc*World->ChunkDimension);
|
||||
World->WorldChunks[i].PerlinZSeed = PerlinZSeed + (z*Inc*World->ChunkDimension);
|
||||
World->WorldChunks[i].YLevel = y;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
89
src/engine_world.h
Normal file
@ -0,0 +1,89 @@
|
||||
#ifndef H_ENGINE_WORLD
|
||||
#define H_ENGINE_WORLD
|
||||
|
||||
#define SPHERE_DEMO_COUNT 3
|
||||
|
||||
#include "engine_math.h"
|
||||
#include "engine_chunk.h"
|
||||
#include "engine_cube.h"
|
||||
#include "engine_player.h"
|
||||
#include "engine_physics.h"
|
||||
|
||||
typedef struct
|
||||
CubeWorld
|
||||
{
|
||||
int ChunkCount;
|
||||
int ChunkDimension;
|
||||
|
||||
int XLength;
|
||||
int ZLength;
|
||||
int StackHeight;
|
||||
|
||||
Chunk* WorldChunks;
|
||||
CubeType* CubeTypes;
|
||||
|
||||
int* ChunkDirtyList;
|
||||
int WorldIsDirty;
|
||||
int TotalRebuild;
|
||||
int PhysicsModelDirty;
|
||||
|
||||
float* RenderVertexBuffer;
|
||||
|
||||
float PerlinXSeed;
|
||||
float PerlinZSeed;
|
||||
float Increment;
|
||||
int Octaves;
|
||||
float Persistence;
|
||||
|
||||
VEPlayer Player;
|
||||
|
||||
int DayNightCycle;
|
||||
int Apocalypse;
|
||||
int Spheres;
|
||||
|
||||
Chunk Sphere[SPHERE_DEMO_COUNT];
|
||||
|
||||
} CubeWorld;
|
||||
|
||||
void
|
||||
InitializeWorld(CubeWorld* World,
|
||||
CubeType* CubeTypes,
|
||||
int X, int Z, int Height,
|
||||
int ChunkSize,
|
||||
float PerlinXSeed, float PerlinZSeed, float Inc,
|
||||
int Octaves, float Persistence);
|
||||
|
||||
void
|
||||
InitializePlayer(CubeWorld* World, vec3f_t Position,
|
||||
float CameraPitch, float CameraYaw);
|
||||
|
||||
void
|
||||
ReseedWorld(CubeWorld* World,
|
||||
CubeType* CubeTypes,
|
||||
float PerlinXSeed, float PerlinZSeed, float Inc,
|
||||
int Octaves, float Persistence);
|
||||
|
||||
void
|
||||
UpdateWorld(CubeWorld* World);
|
||||
|
||||
void
|
||||
RebuildStaticChunkGeometryInformation(CubeWorld* World,
|
||||
PhysicsStaticGeometry* Geo);
|
||||
|
||||
Chunk*
|
||||
GetChunkFromPosition(CubeWorld* World, vec3f_t Position);
|
||||
|
||||
PhysicsStaticGeometry*
|
||||
GetStaticChunkGeometryInformation(CubeWorld* World);
|
||||
|
||||
int
|
||||
GetActiveCubeCount(CubeWorld* World);
|
||||
|
||||
void
|
||||
RedoWorld(CubeWorld* World,
|
||||
int X, int Z, int Height,
|
||||
int ChunkSize,
|
||||
float PerlinXSeed, float PerlinZSeed, float Inc,
|
||||
int Octaves, float Persistence);
|
||||
|
||||
#endif
|