diff --git a/.gitignore b/.gitignore
index da925adf..30c69d45 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,3 +10,5 @@ world
.settings
.cproject
.project
+.git
+/Default/
\ No newline at end of file
diff --git a/Debug/makefile b/Debug/makefile
index cbc3aa03..0247a747 100644
--- a/Debug/makefile
+++ b/Debug/makefile
@@ -8,6 +8,7 @@ RM := rm -rf
# All of the sources participating in the build are defined here
-include sources.mk
+-include src/world/subdir.mk
-include src/window/subdir.mk
-include src/voxels/subdir.mk
-include src/physics/subdir.mk
@@ -16,6 +17,7 @@ RM := rm -rf
-include src/lighting/subdir.mk
-include src/graphics/subdir.mk
-include src/files/subdir.mk
+-include src/audio/subdir.mk
-include src/subdir.mk
-include subdir.mk
-include objects.mk
diff --git a/Debug/objects.mk b/Debug/objects.mk
index 471b1bf6..b7d25c5b 100644
--- a/Debug/objects.mk
+++ b/Debug/objects.mk
@@ -4,5 +4,5 @@
USER_OBJS :=
-LIBS := -lglfw -lpng -lGL -lGLEW -lstdc++fs
+LIBS := -lglfw -lpng -lGL -lGLEW -lstdc++fs -lopenal
diff --git a/Debug/res b/Debug/res
new file mode 120000
index 00000000..85ee7023
--- /dev/null
+++ b/Debug/res
@@ -0,0 +1 @@
+../res
\ No newline at end of file
diff --git a/Debug/sources.mk b/Debug/sources.mk
index fb65165d..39d73484 100644
--- a/Debug/sources.mk
+++ b/Debug/sources.mk
@@ -24,6 +24,7 @@ CPP_DEPS :=
# Every subdirectory with source files must be described here
SUBDIRS := \
src \
+src/audio \
src/files \
src/graphics \
src/lighting \
@@ -32,4 +33,5 @@ src/objects \
src/physics \
src/voxels \
src/window \
+src/world \
diff --git a/Debug/src/audio/subdir.mk b/Debug/src/audio/subdir.mk
new file mode 100644
index 00000000..a12515df
--- /dev/null
+++ b/Debug/src/audio/subdir.mk
@@ -0,0 +1,27 @@
+################################################################################
+# Automatically-generated file. Do not edit!
+################################################################################
+
+# Add inputs and outputs from these tool invocations to the build variables
+CPP_SRCS += \
+../src/audio/Audio.cpp \
+../src/audio/audioutil.cpp
+
+OBJS += \
+./src/audio/Audio.o \
+./src/audio/audioutil.o
+
+CPP_DEPS += \
+./src/audio/Audio.d \
+./src/audio/audioutil.d
+
+
+# Each subdirectory must supply rules for building sources it contributes
+src/audio/%.o: ../src/audio/%.cpp src/audio/subdir.mk
+ @echo 'Building file: $<'
+ @echo 'Invoking: Cross G++ Compiler'
+ g++ -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$@" -o "$@" "$<"
+ @echo 'Finished building: $<'
+ @echo ' '
+
+
diff --git a/Debug/src/graphics/subdir.mk b/Debug/src/graphics/subdir.mk
index db314574..743d753c 100644
--- a/Debug/src/graphics/subdir.mk
+++ b/Debug/src/graphics/subdir.mk
@@ -5,26 +5,41 @@
# Add inputs and outputs from these tool invocations to the build variables
CPP_SRCS += \
../src/graphics/Batch2D.cpp \
+../src/graphics/Batch3D.cpp \
+../src/graphics/Font.cpp \
../src/graphics/LineBatch.cpp \
../src/graphics/Mesh.cpp \
../src/graphics/Shader.cpp \
../src/graphics/Texture.cpp \
+../src/graphics/Sprite.cpp \
+../src/graphics/UVRegion.cpp \
+../src/graphics/Framebuffer.cpp \
../src/graphics/VoxelRenderer.cpp
OBJS += \
./src/graphics/Batch2D.o \
+./src/graphics/Batch3D.o \
+./src/graphics/Font.o \
./src/graphics/LineBatch.o \
./src/graphics/Mesh.o \
./src/graphics/Shader.o \
./src/graphics/Texture.o \
+./src/graphics/Sprite.o \
+./src/graphics/UVRegion.o \
+./src/graphics/Framebuffer.o \
./src/graphics/VoxelRenderer.o
CPP_DEPS += \
./src/graphics/Batch2D.d \
+./src/graphics/Batch3D.d \
+./src/graphics/Font.d \
./src/graphics/LineBatch.d \
./src/graphics/Mesh.d \
./src/graphics/Shader.d \
./src/graphics/Texture.d \
+./src/graphics/Sprite.d \
+./src/graphics/UVRegion.d \
+./src/graphics/Framebuffer.d \
./src/graphics/VoxelRenderer.d
diff --git a/Debug/src/subdir.mk b/Debug/src/subdir.mk
index 5919ac83..60c123c4 100644
--- a/Debug/src/subdir.mk
+++ b/Debug/src/subdir.mk
@@ -5,14 +5,26 @@
# Add inputs and outputs from these tool invocations to the build variables
CPP_SRCS += \
../src/Assets.cpp \
+../src/player_control.cpp \
+../src/hud_render.cpp \
+../src/world_render.cpp \
+../src/declarations.cpp \
../src/voxel_engine.cpp
OBJS += \
./src/Assets.o \
+./src/player_control.o \
+./src/hud_render.o \
+./src/world_render.o \
+./src/declarations.o \
./src/voxel_engine.o
CPP_DEPS += \
./src/Assets.d \
+./src/player_control.d \
+./src/hud_render.d \
+./src/world_render.d \
+./src/declarations.d \
./src/voxel_engine.d
diff --git a/Debug/src/world/subdir.mk b/Debug/src/world/subdir.mk
new file mode 100644
index 00000000..0d5d11aa
--- /dev/null
+++ b/Debug/src/world/subdir.mk
@@ -0,0 +1,27 @@
+################################################################################
+# Automatically-generated file. Do not edit!
+################################################################################
+
+# Add inputs and outputs from these tool invocations to the build variables
+CPP_SRCS += \
+../src/world/Level.cpp \
+../src/world/World.cpp
+
+OBJS += \
+./src/world/Level.o \
+./src/world/World.o
+
+CPP_DEPS += \
+./src/world/Level.d \
+./src/world/World.d
+
+
+# Each subdirectory must supply rules for building sources it contributes
+src/world/%.o: ../src/world/%.cpp src/world/subdir.mk
+ @echo 'Building file: $<'
+ @echo 'Invoking: Cross G++ Compiler'
+ g++ -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$@" -o "$@" "$<"
+ @echo 'Finished building: $<'
+ @echo ' '
+
+
diff --git a/README.md b/README.md
index 80e6234f..c42ff866 100644
--- a/README.md
+++ b/README.md
@@ -1,28 +1,25 @@
-# Run in windows with compiled executable file
+# Run in windows with compiled executable file:
[EXE for windows](https://drive.google.com/file/d/1lkFc5nyYOs0Yyu1wmOoAAwEp4r9jO1tE/view?usp=sharing)
[MinGW libraries (include & lib) + glew32.dll](https://drive.google.com/file/d/1k1Hnbz2Uhr4-03upt2yHxKws396HQDra/view?usp=sharing)
-# Run in linux with
+# Run in linux:
`$ git clone https://github.com/MihailRis/VoxelEngine-Cpp.git`
`$ cd VoxelEngine-Cpp/Debug`
-### Debian-based distro:
-
- $ sudo apt install libglfw3-dev libglfw3 libglew-dev libglm-dev libpng-dev
-
-### RHEL-based distro:
-
- $ sudo dnf install glfw-devel glfw glew-devel glm-devel libpng-devel
-
`$ make`
-`$ cd ..`
+`$ ./voxel_engine`
-`$ ./Debug/voxel_engine`
+## Instal libs:
+#### Debian-based distro:
+`$ sudo apt install libglfw3-dev libglfw3 libglew-dev libglm-dev libpng-dev libopenal-dev`
-# Note for MinGW compiling
+#### RHEL-based distro:
+`$ sudo dnf install glfw-devel glfw glew-devel glm-devel libpng-devel openal-devel`
+
+# Note for MinGW compiling:
To fix problem with `#include ` get headers `mingw.thread.h` and `mingw.invoke.h` from:
https://github.com/meganz/mingw-std-threads
diff --git a/res/block.png b/res/block.png
index 5e2512c7..e7c090d1 100644
Binary files a/res/block.png and b/res/block.png differ
diff --git a/res/block (copy).png b/res/block.png.old
similarity index 100%
rename from res/block (copy).png
rename to res/block.png.old
diff --git a/res/block_.png b/res/block_.png
deleted file mode 100644
index d4941919..00000000
Binary files a/res/block_.png and /dev/null differ
diff --git a/res/block_white.png b/res/block_white.png
deleted file mode 100644
index cfb6a408..00000000
Binary files a/res/block_white.png and /dev/null differ
diff --git a/res/ascii.png b/res/font.png
similarity index 100%
rename from res/ascii.png
rename to res/font.png
diff --git a/res/font_0.png b/res/font_0.png
new file mode 100644
index 00000000..0f156612
Binary files /dev/null and b/res/font_0.png differ
diff --git a/res/font_1.png b/res/font_1.png
new file mode 100644
index 00000000..92d7b2b3
Binary files /dev/null and b/res/font_1.png differ
diff --git a/res/font_2.png b/res/font_2.png
new file mode 100644
index 00000000..984affe8
Binary files /dev/null and b/res/font_2.png differ
diff --git a/res/font_3.png b/res/font_3.png
new file mode 100644
index 00000000..49b44eec
Binary files /dev/null and b/res/font_3.png differ
diff --git a/res/font_4.png b/res/font_4.png
new file mode 100644
index 00000000..b2c0445c
Binary files /dev/null and b/res/font_4.png differ
diff --git a/res/img.png b/res/img.png
index f7704de1..63e4fba6 100644
Binary files a/res/img.png and b/res/img.png differ
diff --git a/res/main.glslf b/res/main.glslf
index 1b998767..9127e7ac 100644
--- a/res/main.glslf
+++ b/res/main.glslf
@@ -7,11 +7,15 @@ out vec4 f_color;
uniform sampler2D u_texture0;
uniform vec3 u_fogColor;
+uniform float u_fogFactor;
void main(){
vec4 tex_color = texture(u_texture0, a_texCoord);
- //if (tex_color.a < 0.5)
- // discard;
- float depth = (a_distance/256.0)*(a_distance/256.0)*256.0;
- f_color = mix(a_color * tex_color, vec4(u_fogColor,1.0), min(1.0, depth/256.0/1.0f));
+ float depth = (a_distance/256.0);
+ float alpha = a_color.a * tex_color.a;
+ // anyway it's any alpha-test alternative required
+ if (alpha < 0.1f)
+ discard;
+ f_color = mix(a_color * tex_color, vec4(u_fogColor,1.0), min(1.0, depth*u_fogFactor));
+ f_color.a = alpha;
}
diff --git a/res/main.glslv b/res/main.glslv
index 8f3e237e..98a7acc3 100644
--- a/res/main.glslv
+++ b/res/main.glslv
@@ -15,12 +15,19 @@ uniform vec3 u_skyLightColor;
uniform vec3 u_cameraPos;
uniform float u_gamma;
+uniform vec3 u_torchlightColor;
+uniform float u_torchlightDistance;
+
void main(){
vec2 pos2d = (u_model * vec4(v_position, 1.0)).xz-u_cameraPos.xz;
- vec4 viewmodelpos = u_view * u_model * vec4(v_position+vec3(0,pow(length(pos2d)*0.0, 3.0),0), 1.0);
- a_color = vec4(pow(v_light.rgb, vec3(u_gamma)),1.0f);
+ vec4 modelpos = u_model * vec4(v_position+vec3(0,pow(length(pos2d)*0.0, 3.0),0), 1.0);
+ vec4 viewmodelpos = u_view * modelpos;
+ vec3 light = v_light.rgb;
+ float torchlight = max(0.0, 1.0-distance(u_cameraPos, modelpos.xyz)/u_torchlightDistance);
+ light += torchlight * u_torchlightColor;
+ a_color = vec4(pow(light, vec3(u_gamma)),1.0f);
a_texCoord = v_texCoord;
- a_color.rgb += u_skyLightColor * v_light.a*0.5;
- a_distance = length(viewmodelpos);
+ a_color.rgb += u_skyLightColor * v_light.a;
+ a_distance = pow(length(viewmodelpos), 1.5);
gl_Position = u_proj * viewmodelpos;
}
diff --git a/res/slot.png b/res/slot.png
new file mode 100644
index 00000000..65c5d3ad
Binary files /dev/null and b/res/slot.png differ
diff --git a/res/ui.glslf b/res/ui.glslf
new file mode 100644
index 00000000..ef51d8bf
--- /dev/null
+++ b/res/ui.glslf
@@ -0,0 +1,11 @@
+#version 330 core
+
+in vec2 a_textureCoord;
+in vec4 a_color;
+out vec4 f_color;
+
+uniform sampler2D u_texture;
+
+void main(){
+ f_color = a_color * texture(u_texture, a_textureCoord);
+}
diff --git a/res/ui.glslv b/res/ui.glslv
new file mode 100644
index 00000000..2b65d101
--- /dev/null
+++ b/res/ui.glslv
@@ -0,0 +1,16 @@
+#version 330 core
+
+layout (location = 0) in vec2 v_position;
+layout (location = 1) in vec2 v_textureCoord;
+layout (location = 2) in vec4 v_color;
+
+out vec2 a_textureCoord;
+out vec4 a_color;
+
+uniform mat4 u_projview;
+
+void main(){
+ a_textureCoord = v_textureCoord;
+ a_color = v_color;
+ gl_Position = u_projview * vec4(v_position, 0.5, 1.0);
+}
diff --git a/src/Assets.cpp b/src/Assets.cpp
index fbaaa21e..64f7d6b5 100644
--- a/src/Assets.cpp
+++ b/src/Assets.cpp
@@ -2,6 +2,7 @@
#include "graphics/Texture.h"
#include "graphics/Shader.h"
+#include "graphics/Font.h"
Assets::~Assets() {
for (auto& iter : shaders){
@@ -11,6 +12,10 @@ Assets::~Assets() {
for (auto& iter : textures){
delete iter.second;
}
+
+ for (auto& iter : fonts){
+ delete iter.second;
+ }
}
Texture* Assets::getTexture(std::string name){
@@ -29,3 +34,12 @@ Shader* Assets::getShader(std::string name){
void Assets::store(Shader* shader, std::string name){
shaders[name] = shader;
}
+
+
+Font* Assets::getFont(std::string name){
+ return fonts[name];
+}
+
+void Assets::store(Font* font, std::string name){
+ fonts[name] = font;
+}
diff --git a/src/Assets.h b/src/Assets.h
index daca7d19..3dc9fa5d 100644
--- a/src/Assets.h
+++ b/src/Assets.h
@@ -6,10 +6,12 @@
class Texture;
class Shader;
+class Font;
class Assets {
std::unordered_map textures;
std::unordered_map shaders;
+ std::unordered_map fonts;
public:
~Assets();
Texture* getTexture(std::string name);
@@ -17,6 +19,9 @@ public:
Shader* getShader(std::string name);
void store(Shader* shader, std::string name);
+
+ Font* getFont(std::string name);
+ void store(Font* font, std::string name);
};
#endif /* SRC_ASSETS_H_ */
diff --git a/src/audio/Audio.cpp b/src/audio/Audio.cpp
new file mode 100644
index 00000000..5562d2e9
--- /dev/null
+++ b/src/audio/Audio.cpp
@@ -0,0 +1,188 @@
+#include "Audio.h"
+#include "audioutil.h"
+#include
+#include
+
+#include
+#include
+
+ALCdevice* Audio::device;
+ALCcontext* Audio::context;
+unsigned Audio::maxSources;
+unsigned Audio::maxBuffers = 1024;
+std::vector Audio::allsources;
+std::vector Audio::freesources;
+std::vector Audio::allbuffers;
+std::vector Audio::freebuffers;
+
+bool ALSource::setBuffer(ALBuffer* buffer) {
+ alSourcei(id, AL_BUFFER, buffer->id);
+ return alCheck();
+}
+
+bool ALSource::play(){
+ alSourcePlay(id);
+ return alCheck();
+}
+
+bool ALSource::isPlaying() {
+ int state;
+ alGetSourcei(id, AL_SOURCE_STATE, &state);
+ return state == AL_PLAYING;
+}
+
+bool ALSource::setPosition(glm::vec3 position) {
+ alSource3f(id, AL_POSITION, position.x, position.y, position.z);
+ return alCheck();
+}
+
+bool ALSource::setVelocity(glm::vec3 velocity) {
+ alSource3f(id, AL_VELOCITY, velocity.x, velocity.y, velocity.z);
+ return alCheck();
+}
+
+bool ALSource::setLoop(bool loop) {
+ alSourcei(id, AL_LOOPING, AL_TRUE ? loop : AL_FALSE);
+ return alCheck();
+}
+
+bool ALSource::setGain(float gain) {
+ alSourcef(id, AL_GAIN, gain);
+ return alCheck();
+}
+
+
+bool ALSource::setPitch(float pitch) {
+ alSourcef(id, AL_PITCH, pitch);
+ return alCheck();
+}
+
+bool ALBuffer::load(int format, const char* data, int size, int freq) {
+ alBufferData(id, format, data, size, freq);
+ return alCheck();
+}
+
+
+bool Audio::initialize() {
+ device = alcOpenDevice(nullptr);
+ if (device == nullptr)
+ return false;
+ context = alcCreateContext(device, nullptr);
+ if (!alcMakeContextCurrent(context)){
+ alcCloseDevice(device);
+ return false;
+ }
+ if (!alCheck())
+ return false;
+
+ ALCint size;
+ alcGetIntegerv(device, ALC_ATTRIBUTES_SIZE, 1, &size);
+ std::vector attrs(size);
+ alcGetIntegerv(device, ALC_ALL_ATTRIBUTES, size, &attrs[0]);
+ for(size_t i=0; iisPlaying()){
+ alSourceStop(source->id); alCheck();
+ }
+ alDeleteSources(1, &source->id); alCheck();
+ }
+
+ for (ALBuffer* buffer : allbuffers){
+ alDeleteBuffers(1, &buffer->id); alCheck();
+ }
+
+ alcMakeContextCurrent(context);
+ alcDestroyContext(context);
+ if (!alcCloseDevice(device)){
+ std::cerr << "device not closed!" << std::endl;
+ }
+ device = nullptr;
+ context = nullptr;
+}
+
+ALSource* Audio::getFreeSource(){
+ if (!freesources.empty()){
+ ALSource* source = freesources.back();
+ freesources.pop_back();
+ return source;
+ }
+ if (allsources.size() == maxSources){
+ std::cerr << "attempted to create new source, but limit is " << maxSources << std::endl;
+ return nullptr;
+ }
+ ALuint id;
+ alGenSources(1, &id);
+ if (!alCheck())
+ return nullptr;
+
+ ALSource* source = new ALSource(id);
+ allsources.push_back(source);
+ return source;
+}
+
+ALBuffer* Audio::getFreeBuffer(){
+ if (!freebuffers.empty()){
+ ALBuffer* buffer = freebuffers.back();
+ freebuffers.pop_back();
+ return buffer;
+ }
+ if (allbuffers.size() == maxBuffers){
+ std::cerr << "attempted to create new ALbuffer, but limit is " << maxBuffers << std::endl;
+ return nullptr;
+ }
+ ALuint id;
+ alGenBuffers(1, &id);
+ if (!alCheck())
+ return nullptr;
+
+ ALBuffer* buffer = new ALBuffer(id);
+ allbuffers.push_back(buffer);
+ return buffer;
+}
+
+void Audio::freeSource(ALSource* source){
+ freesources.push_back(source);
+}
+
+void Audio::freeBuffer(ALBuffer* buffer){
+ freebuffers.push_back(buffer);
+}
+
+bool Audio::get_available_devices(std::vector& devicesVec){
+ const ALCchar* devices;
+ devices = alcGetString(device, ALC_DEVICE_SPECIFIER);
+ if (!alCheck())
+ return false;
+
+ const char* ptr = devices;
+
+ devicesVec.clear();
+
+ do {
+ devicesVec.push_back(std::string(ptr));
+ ptr += devicesVec.back().size() + 1;
+ }
+ while(*(ptr + 1) != '\0');
+
+ return true;
+}
+
+void Audio::setListener(glm::vec3 position, glm::vec3 velocity, glm::vec3 at, glm::vec3 up){
+ ALfloat listenerOri[] = { at.x, at.y, at.z, up.x, up.y, up.z };
+
+ alListener3f(AL_POSITION, position.x, position.y, position.z);
+ alCheck();
+ alListener3f(AL_VELOCITY, velocity.x, velocity.y, velocity.z);
+ alCheck();
+ alListenerfv(AL_ORIENTATION, listenerOri);
+ alCheck();
+}
diff --git a/src/audio/Audio.h b/src/audio/Audio.h
new file mode 100644
index 00000000..af0663f3
--- /dev/null
+++ b/src/audio/Audio.h
@@ -0,0 +1,62 @@
+#ifndef SRC_AUDIO_AUDIO_H_
+#define SRC_AUDIO_AUDIO_H_
+
+#include
+#include
+
+#include
+#include
+
+#include
+
+
+struct ALBuffer;
+
+struct ALSource {
+ ALuint id;
+ ALSource(ALuint id) : id(id) {}
+
+ bool isPlaying();
+ bool setPosition(glm::vec3 position);
+ bool setVelocity(glm::vec3 velocity);
+ bool setBuffer(ALBuffer* buffer);
+ bool setLoop(bool loop);
+ bool setGain(float gain);
+ bool setPitch(float pitch);
+ bool play();
+};
+
+struct ALBuffer {
+ ALuint id;
+ ALBuffer(ALuint id) : id(id) {}
+ bool load(int format, const char* data, int size, int freq);
+};
+
+class Audio {
+ static ALCdevice* device;
+ static ALCcontext* context;
+
+ static std::vector allsources;
+ static std::vector freesources;
+
+ static std::vector allbuffers;
+ static std::vector freebuffers;
+
+ static unsigned maxSources;
+ static unsigned maxBuffers;
+
+public:
+ static ALSource* getFreeSource();
+ static ALBuffer* getFreeBuffer();
+ static void freeSource(ALSource* source);
+ static void freeBuffer(ALBuffer* buffer);
+
+ static bool initialize();
+ static void finalize();
+ static bool get_available_devices(std::vector& devicesVec);
+
+ static void setListener(glm::vec3 position, glm::vec3 velocity, glm::vec3 at, glm::vec3 up);
+
+};
+
+#endif /* SRC_AUDIO_AUDIO_H_ */
diff --git a/src/audio/audioutil.cpp b/src/audio/audioutil.cpp
new file mode 100644
index 00000000..cfedfdec
--- /dev/null
+++ b/src/audio/audioutil.cpp
@@ -0,0 +1,194 @@
+#include "audioutil.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+
+bool is_big_endian(void){
+ union {
+ uint32_t i;
+ char c[4];
+ } bint = {0x01020304};
+
+ return bint.c[0] == 1;
+}
+
+std::int32_t convert_to_int(char* buffer, std::size_t len){
+ std::int32_t a = 0;
+ if(!is_big_endian())
+ std::memcpy(&a, buffer, len);
+ else
+ for(std::size_t i = 0; i < len; ++i)
+ reinterpret_cast(&a)[3 - i] = buffer[i];
+ return a;
+}
+
+bool check_al_errors(const std::string& filename, const std::uint_fast32_t line){
+ ALenum error = alGetError();
+ if(error != AL_NO_ERROR){
+ std::cerr << "OpenAL ERROR (" << filename << ": " << line << ")\n" ;
+ switch(error){
+ case AL_INVALID_NAME:
+ std::cerr << "AL_INVALID_NAME: a bad name (ID) was passed to an OpenAL function";
+ break;
+ case AL_INVALID_ENUM:
+ std::cerr << "AL_INVALID_ENUM: an invalid enum value was passed to an OpenAL function";
+ break;
+ case AL_INVALID_VALUE:
+ std::cerr << "AL_INVALID_VALUE: an invalid value was passed to an OpenAL function";
+ break;
+ case AL_INVALID_OPERATION:
+ std::cerr << "AL_INVALID_OPERATION: the requested operation is not valid";
+ break;
+ case AL_OUT_OF_MEMORY:
+ std::cerr << "AL_OUT_OF_MEMORY: the requested operation resulted in OpenAL running out of memory";
+ break;
+ default:
+ std::cerr << "UNKNOWN AL ERROR: " << error;
+ }
+ std::cerr << std::endl;
+ return false;
+ }
+ return true;
+}
+
+bool load_wav_file_header(std::ifstream& file,
+ std::uint8_t& channels,
+ std::int32_t& sampleRate,
+ std::uint8_t& bitsPerSample,
+ ALsizei& size){
+ char buffer[4];
+ if(!file.is_open())
+ return false;
+
+ // the RIFF
+ if(!file.read(buffer, 4)){
+ std::cerr << "ERROR: could not read RIFF" << std::endl;
+ return false;
+ }
+ if(std::strncmp(buffer, "RIFF", 4) != 0){
+ std::cerr << "ERROR: file is not a valid WAVE file (header doesn't begin with RIFF)" << std::endl;
+ return false;
+ }
+
+ // the size of the file
+ if(!file.read(buffer, 4)){
+ std::cerr << "ERROR: could not read size of file" << std::endl;
+ return false;
+ }
+
+ // the WAVE
+ if(!file.read(buffer, 4)){
+ std::cerr << "ERROR: could not read WAVE" << std::endl;
+ return false;
+ }
+ if(std::strncmp(buffer, "WAVE", 4) != 0){
+ std::cerr << "ERROR: file is not a valid WAVE file (header doesn't contain WAVE)" << std::endl;
+ return false;
+ }
+
+ // "fmt/0"
+ if(!file.read(buffer, 4)){
+ std::cerr << "ERROR: could not read fmt/0" << std::endl;
+ return false;
+ }
+
+ // this is always 16, the size of the fmt data chunk
+ if(!file.read(buffer, 4)){
+ std::cerr << "ERROR: could not read the 16" << std::endl;
+ return false;
+ }
+
+ // PCM should be 1?
+ if(!file.read(buffer, 2)){
+ std::cerr << "ERROR: could not read PCM" << std::endl;
+ return false;
+ }
+
+ // the number of channels
+ if(!file.read(buffer, 2)){
+ std::cerr << "ERROR: could not read number of channels" << std::endl;
+ return false;
+ }
+ channels = convert_to_int(buffer, 2);
+
+ // sample rate
+ if(!file.read(buffer, 4)){
+ std::cerr << "ERROR: could not read sample rate" << std::endl;
+ return false;
+ }
+ sampleRate = convert_to_int(buffer, 4);
+
+ // (sampleRate * bitsPerSample * channels) / 8
+ if(!file.read(buffer, 4)){
+ std::cerr << "ERROR: could not read (sampleRate * bitsPerSample * channels) / 8" << std::endl;
+ return false;
+ }
+
+ // ?? dafaq
+ if(!file.read(buffer, 2)){
+ std::cerr << "ERROR: could not read dafaq" << std::endl;
+ return false;
+ }
+
+ // bitsPerSample
+ if(!file.read(buffer, 2)){
+ std::cerr << "ERROR: could not read bits per sample" << std::endl;
+ return false;
+ }
+ bitsPerSample = convert_to_int(buffer, 2);
+
+ // data chunk header "data"
+ if(!file.read(buffer, 4)){
+ std::cerr << "ERROR: could not read data chunk header" << std::endl;
+ return false;
+ }
+ if(std::strncmp(buffer, "data", 4) != 0){
+ std::cerr << "ERROR: file is not a valid WAVE file (doesn't have 'data' tag)" << std::endl;
+ return false;
+ }
+
+ // size of data
+ if(!file.read(buffer, 4)){
+ std::cerr << "ERROR: could not read data size" << std::endl;
+ return false;
+ }
+ size = convert_to_int(buffer, 4);
+
+ /* cannot be at the end of file */
+ if(file.eof()){
+ std::cerr << "ERROR: reached EOF on the file" << std::endl;
+ return false;
+ }
+ if(file.fail()){
+ std::cerr << "ERROR: fail state set on the file" << std::endl;
+ return false;
+ }
+ return true;
+}
+
+char* load_wav(const std::string& filename,
+ std::uint8_t& channels,
+ std::int32_t& sampleRate,
+ std::uint8_t& bitsPerSample,
+ ALsizei& size){
+ std::ifstream in(filename, std::ios::binary);
+ if(!in.is_open()){
+ std::cerr << "ERROR: Could not open \"" << filename << "\"" << std::endl;
+ return nullptr;
+ }
+ if(!load_wav_file_header(in, channels, sampleRate, bitsPerSample, size)){
+ std::cerr << "ERROR: Could not load wav header of \"" << filename << "\"" << std::endl;
+ return nullptr;
+ }
+
+ char* data = new char[size];
+
+ in.read(data, size);
+
+ return data;
+}
diff --git a/src/audio/audioutil.h b/src/audio/audioutil.h
new file mode 100644
index 00000000..f62a06cb
--- /dev/null
+++ b/src/audio/audioutil.h
@@ -0,0 +1,44 @@
+#ifndef SRC_AUDIO_AUDIOUTIL_H_
+#define SRC_AUDIO_AUDIOUTIL_H_
+
+#include
+#include
+
+#include
+
+#define alCheck() check_al_errors(__FILE__, __LINE__)
+
+bool check_al_errors(const std::string& filename, const std::uint_fast32_t line);
+
+bool load_wav_file_header(std::ifstream& file,
+ std::uint8_t& channels,
+ std::int32_t& sampleRate,
+ std::uint8_t& bitsPerSample,
+ ALsizei& size);
+
+char* load_wav(const std::string& filename,
+ std::uint8_t& channels,
+ std::int32_t& sampleRate,
+ std::uint8_t& bitsPerSample,
+ ALsizei& size);
+
+static inline ALenum to_al_format(short channels, short samples){
+ bool stereo = (channels > 1);
+
+ switch (samples) {
+ case 16:
+ if (stereo)
+ return AL_FORMAT_STEREO16;
+ else
+ return AL_FORMAT_MONO16;
+ case 8:
+ if (stereo)
+ return AL_FORMAT_STEREO8;
+ else
+ return AL_FORMAT_MONO8;
+ default:
+ return -1;
+ }
+}
+
+#endif /* SRC_AUDIO_AUDIOUTIL_H_ */
diff --git a/src/declarations.cpp b/src/declarations.cpp
new file mode 100644
index 00000000..ddb6bd1d
--- /dev/null
+++ b/src/declarations.cpp
@@ -0,0 +1,154 @@
+#include "declarations.h"
+
+#include "Assets.h"
+#include "graphics/Shader.h"
+#include "graphics/Texture.h"
+#include "graphics/Font.h"
+#include "window/Window.h"
+
+#include "voxels/Block.h"
+
+// Shaders, textures
+bool _load_shader(Assets* assets, std::string vertex_file, std::string fragment_file, std::string name){
+ Shader* shader = load_shader(vertex_file, fragment_file);
+ if (shader == nullptr){
+ std::cerr << "failed to load shader '" << name << "'" << std::endl;
+ return false;
+ }
+ assets->store(shader, name);
+ return true;
+}
+
+bool _load_texture(Assets* assets, std::string filename, std::string name){
+ Texture* texture = load_texture(filename);
+ if (texture == nullptr){
+ std::cerr << "failed to load texture '" << name << "'" << std::endl;
+ return false;
+ }
+ assets->store(texture, name);
+ return true;
+}
+
+bool _load_font(Assets* assets, std::string filename, std::string name){
+ std::vector pages;
+ for (size_t i = 0; i <= 4; i++){
+ Texture* texture = load_texture(filename+"_"+std::to_string(i)+".png");
+ if (texture == nullptr){
+ std::cerr << "failed to load bitmap font '" << name << "' (missing page " << std::to_string(i) << ")" << std::endl;
+ return false;
+ }
+ pages.push_back(texture);
+ }
+ Font* font = new Font(pages);
+ assets->store(font, name);
+ return true;
+}
+
+int initialize_assets(Assets* assets) {
+#define LOAD_SHADER(VERTEX, FRAGMENT, NAME) \
+ if (!_load_shader(assets, VERTEX, FRAGMENT, NAME))\
+ return 1;
+#define LOAD_TEXTURE(FILENAME, NAME) \
+ if (!_load_texture(assets, FILENAME, NAME))\
+ return 1;
+#define LOAD_FONT(FILENAME, NAME) \
+ if (!_load_font(assets, FILENAME, NAME))\
+ return 1;
+
+ LOAD_SHADER("res/main.glslv", "res/main.glslf", "main");
+ LOAD_SHADER("res/crosshair.glslv", "res/crosshair.glslf", "crosshair");
+ LOAD_SHADER("res/lines.glslv", "res/lines.glslf", "lines");
+ LOAD_SHADER("res/ui.glslv", "res/ui.glslf", "ui");
+
+ LOAD_TEXTURE("res/block.png", "block");
+ LOAD_TEXTURE("res/slot.png", "slot");
+
+ LOAD_FONT("res/font", "normal");
+ return 0;
+}
+
+// All in-game definitions (blocks, items, etc..)
+void setup_definitions() {
+ for (size_t i = 0; i < 256; i++)
+ Block::blocks[i] = nullptr;
+
+ Block* block = new Block(BLOCK_AIR, 0);
+ block->drawGroup = 1;
+ block->lightPassing = true;
+ block->skyLightPassing = true;
+ block->obstacle = false;
+ block->selectable = false;
+ block->model = 0;
+ Block::blocks[block->id] = block;
+
+ block = new Block(BLOCK_DIRT, 2);
+ Block::blocks[block->id] = block;
+
+ block = new Block(BLOCK_GRASS_BLOCK, 4);
+ block->textureFaces[2] = 2;
+ block->textureFaces[3] = 1;
+ Block::blocks[block->id] = block;
+
+ block = new Block(BLOCK_LAMP, 3);
+ block->emission[0] = 15;
+ block->emission[1] = 14;
+ block->emission[2] = 13;
+ Block::blocks[block->id] = block;
+
+ block = new Block(BLOCK_GLASS,5);
+ block->drawGroup = 2;
+ block->lightPassing = true;
+ Block::blocks[block->id] = block;
+
+ block = new Block(BLOCK_PLANKS, 6);
+ Block::blocks[block->id] = block;
+
+ block = new Block(BLOCK_WOOD, 7);
+ block->textureFaces[2] = 8;
+ block->textureFaces[3] = 8;
+ Block::blocks[block->id] = block;
+
+ block = new Block(BLOCK_LEAVES, 9);
+ Block::blocks[block->id] = block;
+
+ block = new Block(BLOCK_STONE, 10);
+ Block::blocks[block->id] = block;
+
+ block = new Block(BLOCK_WATER, 11);
+ block->drawGroup = 4;
+ block->lightPassing = true;
+ block->skyLightPassing = false;
+ block->obstacle = false;
+ block->selectable = false;
+ Block::blocks[block->id] = block;
+
+ block = new Block(BLOCK_SAND, 12);
+ Block::blocks[block->id] = block;
+
+ block = new Block(BLOCK_BEDROCK, 13);
+ block->breakable = false;
+ Block::blocks[block->id] = block;
+
+ block = new Block(BLOCK_GRASS, 14);
+ block->drawGroup = 5;
+ block->lightPassing = true;
+ block->obstacle = false;
+ block->model = 2;
+ Block::blocks[block->id] = block;
+
+ block = new Block(BLOCK_FLOWER, 16);
+ block->drawGroup = 5;
+ block->lightPassing = true;
+ block->obstacle = false;
+ block->model = 2;
+ Block::blocks[block->id] = block;
+
+ block = new Block(BLOCK_BRICK, 17);
+ Block::blocks[block->id] = block;
+
+ block = new Block(BLOCK_METAL, 18);
+ Block::blocks[block->id] = block;
+
+ block = new Block(BLOCK_RUST, 19);
+ Block::blocks[block->id] = block;
+}
diff --git a/src/declarations.h b/src/declarations.h
index b49304bf..13ff14be 100644
--- a/src/declarations.h
+++ b/src/declarations.h
@@ -2,113 +2,29 @@
#define DECLARATIONS_H
#include
-#include "Assets.h"
-#include "graphics/Shader.h"
-#include "graphics/Texture.h"
-#include "window/Window.h"
-#include "voxels/Block.h"
+#define BLOCK_AIR 0
+#define BLOCK_DIRT 1
+#define BLOCK_GRASS_BLOCK 2
+#define BLOCK_LAMP 3
+#define BLOCK_GLASS 4
+#define BLOCK_PLANKS 5
+#define BLOCK_WOOD 6
+#define BLOCK_LEAVES 7
+#define BLOCK_STONE 8
+#define BLOCK_WATER 9
+#define BLOCK_SAND 10
+#define BLOCK_BEDROCK 11
+#define BLOCK_GRASS 12
+#define BLOCK_FLOWER 13
+#define BLOCK_BRICK 14
+#define BLOCK_METAL 15
+#define BLOCK_RUST 16
+class Assets;
-// Shaders, textures, renderers
+int initialize_assets(Assets* assets);
+void setup_definitions();
-bool _load_shader(Assets* assets, std::string vertex_file, std::string fragment_file, std::string name){
- Shader* shader = load_shader(vertex_file, fragment_file);
- if (shader == nullptr){
- std::cerr << "failed to load shader '" << name << "'" << std::endl;
- return false;
- }
- assets->store(shader, name);
- return true;
-}
-
-bool _load_texture(Assets* assets, std::string filename, std::string name){
- Texture* texture = load_texture(filename);
- if (texture == nullptr){
- std::cerr << "failed to load texture '" << name << "'" << std::endl;
- return false;
- }
- assets->store(texture, name);
- return true;
-}
-
-int initialize_assets(Assets* assets) {
-#define LOAD_SHADER(VERTEX, FRAGMENT, NAME) \
- if (!_load_shader(assets, VERTEX, FRAGMENT, NAME))\
- return 1;
-#define LOAD_TEXTURE(FILENAME, NAME) \
- if (!_load_texture(assets, FILENAME, NAME))\
- return 1;
-
- LOAD_SHADER("res/main.glslv", "res/main.glslf", "main");
- LOAD_SHADER("res/crosshair.glslv", "res/crosshair.glslf", "crosshair");
- LOAD_SHADER("res/lines.glslv", "res/lines.glslf", "lines");
-
- LOAD_TEXTURE("res/block.png", "block");
- return 0;
-}
-
-
-// All in-game definitions (blocks, items, etc..)
-void setup_definitions() {
- // AIR
- Block* block = new Block(0,0);
- block->drawGroup = 1;
- block->lightPassing = true;
- block->skyLightPassing = true;
- block->obstacle = false;
- block->selectable = false;
- Block::blocks[block->id] = block;
-
- // STONE
- block = new Block(1,2);
- Block::blocks[block->id] = block;
-
- // GRASS
- block = new Block(2,4);
- block->textureFaces[2] = 2;
- block->textureFaces[3] = 1;
- Block::blocks[block->id] = block;
-
- // LAMP
- block = new Block(3,3);
- block->emission[0] = 15;
- block->emission[1] = 14;
- block->emission[2] = 13;
- Block::blocks[block->id] = block;
-
- // GLASS
- block = new Block(4,5);
- block->drawGroup = 2;
- block->lightPassing = true;
- Block::blocks[block->id] = block;
-
- // PLANKS
- block = new Block(5,6);
- Block::blocks[block->id] = block;
-
- // WOOD
- block = new Block(6,7);
- block->textureFaces[2] = 8;
- block->textureFaces[3] = 8;
- Block::blocks[block->id] = block;
-
- // LEAVES
- block = new Block(7,9);
- Block::blocks[block->id] = block;
-
- // ACTUAL STONE
- block = new Block(8,10);
- Block::blocks[block->id] = block;
-
- // WATER
- block = new Block(9,11);
- block->drawGroup = 4;
- block->lightPassing = true;
- block->skyLightPassing = false;
- block->obstacle = false;
- block->selectable = false;
- Block::blocks[block->id] = block;
-}
#endif // DECLARATIONS_H
diff --git a/src/files/WorldFiles.cpp b/src/files/WorldFiles.cpp
index 17fee0f0..84388a72 100644
--- a/src/files/WorldFiles.cpp
+++ b/src/files/WorldFiles.cpp
@@ -19,6 +19,9 @@ union {
#define SECTION_POSITION 1
#define SECTION_ROTATION 2
+#define SECTION_FLAGS 3
+#define PLAYER_FLAG_FLIGHT 0x1
+#define PLAYER_FLAG_NOCLIP 0x2
unsigned long WorldFiles::totalCompressed = 0;
@@ -33,7 +36,7 @@ void int2Bytes(int value, char* dest, unsigned int offset){
dest[offset+3] = (char) (value >> 0 & 255);
}
-void float2Bytes(float fvalue, char* dest, unsigned int offset){
+void floatToBytes(float fvalue, char* dest, unsigned int offset){
uint32_t value = *((uint32_t*)&fvalue);
dest[offset] = (char) (value >> 24 & 255);
dest[offset+1] = (char) (value >> 16 & 255);
@@ -50,7 +53,7 @@ float bytes2Float(char* srcs, unsigned int offset){
return *(float*)(&value);
}
-WorldFiles::WorldFiles(const char* directory, size_t mainBufferCapacity) : directory(directory){
+WorldFiles::WorldFiles(std::string directory, size_t mainBufferCapacity) : directory(directory){
mainBufferIn = new char[CHUNK_VOL*2];
mainBufferOut = new char[mainBufferCapacity];
}
@@ -58,15 +61,15 @@ WorldFiles::WorldFiles(const char* directory, size_t mainBufferCapacity) : direc
WorldFiles::~WorldFiles(){
delete[] mainBufferIn;
delete[] mainBufferOut;
- std::unordered_map::iterator it;
+ std::unordered_map::iterator it;
for (it = regions.begin(); it != regions.end(); it++){
- char** region = it->second;
- if (region == nullptr)
+ WorldRegion region = it->second;
+ if (region.chunksData == nullptr)
continue;
for (unsigned int i = 0; i < REGION_VOL; i++){
- delete[] region[i];
+ delete[] region.chunksData[i];
}
- delete[] region;
+ delete[] region.chunksData;
}
regions.clear();
}
@@ -82,17 +85,17 @@ void WorldFiles::put(const char* chunkData, int x, int y){
_tempcoords._coords[0] = regionX;
_tempcoords._coords[1] = regionY;
- char** region = regions[_tempcoords._key];
- if (region == nullptr){
- region = new char*[REGION_VOL];
+ WorldRegion& region = regions[_tempcoords._key];
+ region.unsaved = true;
+ if (region.chunksData == nullptr){
+ region.chunksData = new char*[REGION_VOL];
for (unsigned int i = 0; i < REGION_VOL; i++)
- region[i] = nullptr;
- regions[_tempcoords._key] = region;
+ region.chunksData[i] = nullptr;
}
- char* targetChunk = region[localY * REGION_SIZE + localX];
+ char* targetChunk = region.chunksData[localY * REGION_SIZE + localX];
if (targetChunk == nullptr){
targetChunk = new char[CHUNK_VOL];
- region[localY * REGION_SIZE + localX] = targetChunk;
+ region.chunksData[localY * REGION_SIZE + localX] = targetChunk;
totalCompressed += CHUNK_VOL;
}
for (unsigned int i = 0; i < CHUNK_VOL; i++)
@@ -122,11 +125,11 @@ bool WorldFiles::getChunk(int x, int y, char* out){
_tempcoords._coords[0] = regionX;
_tempcoords._coords[1] = regionY;
- char** region = regions[_tempcoords._key];
- if (region == nullptr)
+ WorldRegion& region = regions[_tempcoords._key];
+ if (region.chunksData == nullptr)
return readChunk(x,y,out);
- char* chunk = region[chunkIndex];
+ char* chunk = region.chunksData[chunkIndex];
if (chunk == nullptr)
return readChunk(x,y,out);
for (unsigned int i = 0; i < CHUNK_VOL; i++)
@@ -174,34 +177,38 @@ bool WorldFiles::readChunk(int x, int y, char* out){
}
void WorldFiles::write(){
- std::unordered_map::iterator it;
+ std::unordered_map::iterator it;
for (it = regions.begin(); it != regions.end(); it++){
- if (it->second == nullptr)
+ if (it->second.chunksData == nullptr || !it->second.unsaved)
continue;
int x;
int y;
longToCoords(x,y, it->first);
- unsigned int size = writeRegion(mainBufferOut, x,y, it->second);
+ unsigned int size = writeRegion(mainBufferOut, x,y, it->second.chunksData);
write_binary_file(getRegionFile(x,y), mainBufferOut, size);
}
}
void WorldFiles::writePlayer(Player* player){
- char dst[1+3*4 + 1+2*4];
+ char dst[1+3*4 + 1+2*4 + 1+1];
glm::vec3 position = player->hitbox->position;
size_t offset = 0;
dst[offset++] = SECTION_POSITION;
- float2Bytes(position.x, dst, offset); offset += 4;
- float2Bytes(position.y, dst, offset); offset += 4;
- float2Bytes(position.z, dst, offset); offset += 4;
+ floatToBytes(position.x, dst, offset); offset += 4;
+ floatToBytes(position.y, dst, offset); offset += 4;
+ floatToBytes(position.z, dst, offset); offset += 4;
dst[offset++] = SECTION_ROTATION;
- float2Bytes(player->camX, dst, offset); offset += 4;
- float2Bytes(player->camY, dst, offset); offset += 4;
+ floatToBytes(player->camX, dst, offset); offset += 4;
+ floatToBytes(player->camY, dst, offset); offset += 4;
+
+ dst[offset++] = SECTION_FLAGS;
+ dst[offset++] = player->flight * PLAYER_FLAG_FLIGHT |
+ player->noclip * PLAYER_FLAG_NOCLIP;
write_binary_file(getPlayerFile(), (const char*)dst, sizeof(dst));
}
@@ -210,7 +217,7 @@ bool WorldFiles::readPlayer(Player* player) {
size_t length = 0;
char* data = read_binary_file(getPlayerFile(), length);
if (data == nullptr){
- std::cerr << "could not to read player.bin" << std::endl;
+ std::cerr << "could not to read player.bin (ignored)" << std::endl;
return false;
}
glm::vec3 position = player->hitbox->position;
@@ -227,6 +234,13 @@ bool WorldFiles::readPlayer(Player* player) {
player->camX = bytes2Float(data, offset); offset += 4;
player->camY = bytes2Float(data, offset); offset += 4;
break;
+ case SECTION_FLAGS:
+ {
+ unsigned char flags = data[offset++];
+ player->flight = flags & PLAYER_FLAG_FLIGHT;
+ player->noclip = flags & PLAYER_FLAG_NOCLIP;
+ }
+ break;
}
}
player->hitbox->position = position;
diff --git a/src/files/WorldFiles.h b/src/files/WorldFiles.h
index e79aed04..93d50db0 100644
--- a/src/files/WorldFiles.h
+++ b/src/files/WorldFiles.h
@@ -3,27 +3,29 @@
#include