Initial commit, building and working!

master
Pentium44 2021-02-17 00:19:42 -08:00
commit 9d2c737e5f
70 changed files with 12608 additions and 0 deletions

19
Makefile Normal file
View 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
View 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

Binary file not shown.

View 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

Binary file not shown.

BIN
data/assets/music/jump.ogg Normal file

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 236 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 190 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 236 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 236 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 236 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 231 B

102
data/font/font.fnt Normal file
View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

View 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);
}

View File

@ -0,0 +1,12 @@
#version 330 core
in vec3 textureCoordinates;
out vec4 color;
uniform samplerCube skyBoxTexture;
void main()
{
color = texture(skyBoxTexture, textureCoordinates);
}

View 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;
}

View 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;
}

View 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
View 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
View 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
View 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

Binary file not shown.

121
src/engine_camera.c Normal file
View 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
View 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

Binary file not shown.

359
src/engine_chunk.c Normal file
View 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
View 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

Binary file not shown.

43
src/engine_clock.c Normal file
View 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
View 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

Binary file not shown.

239
src/engine_console.c Normal file
View 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
View 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

Binary file not shown.

117
src/engine_cube.c Normal file
View 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
View 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

Binary file not shown.

285
src/engine_generation.c Normal file
View 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
View 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

Binary file not shown.

230
src/engine_main.c Normal file
View 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
View 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

Binary file not shown.

396
src/engine_math.h Normal file
View 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
View 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
View 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

Binary file not shown.

193
src/engine_player.c Normal file
View 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
View 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

Binary file not shown.

510
src/engine_renderer.c Normal file
View 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
View 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

Binary file not shown.

298
src/engine_sdl.c Normal file
View 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
View 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

Binary file not shown.

110
src/engine_shader.c Normal file
View 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
View 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

Binary file not shown.

131
src/engine_text.c Normal file
View 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
View 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

Binary file not shown.

190
src/engine_ui.c Normal file
View 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
View 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

Binary file not shown.

340
src/engine_world.c Normal file
View 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
View 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

BIN
src/engine_world.o Normal file

Binary file not shown.

7762
src/stb_image.h Normal file

File diff suppressed because it is too large Load Diff