2
.gitignore
vendored
@ -10,3 +10,5 @@ world
|
||||
.settings
|
||||
.cproject
|
||||
.project
|
||||
.git
|
||||
/Default/
|
||||
@ -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
|
||||
|
||||
@ -4,5 +4,5 @@
|
||||
|
||||
USER_OBJS :=
|
||||
|
||||
LIBS := -lglfw -lpng -lGL -lGLEW -lstdc++fs
|
||||
LIBS := -lglfw -lpng -lGL -lGLEW -lstdc++fs -lopenal
|
||||
|
||||
|
||||
@ -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 \
|
||||
|
||||
|
||||
27
Debug/src/audio/subdir.mk
Normal file
@ -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 ' '
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
|
||||
27
Debug/src/world/subdir.mk
Normal file
@ -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 ' '
|
||||
|
||||
|
||||
23
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)<br>
|
||||
[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 <mingw.thread.h>` get headers `mingw.thread.h` and `mingw.invoke.h` from:
|
||||
https://github.com/meganz/mingw-std-threads
|
||||
|
||||
BIN
res/block.png
|
Before Width: | Height: | Size: 8.1 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 8.1 KiB After Width: | Height: | Size: 8.1 KiB |
BIN
res/block_.png
|
Before Width: | Height: | Size: 4.8 KiB |
|
Before Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
BIN
res/font_0.png
Normal file
|
After Width: | Height: | Size: 6.3 KiB |
BIN
res/font_1.png
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
res/font_2.png
Normal file
|
After Width: | Height: | Size: 5.6 KiB |
BIN
res/font_3.png
Normal file
|
After Width: | Height: | Size: 5.3 KiB |
BIN
res/font_4.png
Normal file
|
After Width: | Height: | Size: 6.1 KiB |
BIN
res/img.png
|
Before Width: | Height: | Size: 342 B After Width: | Height: | Size: 793 B |
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
BIN
res/slot.png
Normal file
|
After Width: | Height: | Size: 257 KiB |
11
res/ui.glslf
Normal file
@ -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);
|
||||
}
|
||||
16
res/ui.glslv
Normal file
@ -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);
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -6,10 +6,12 @@
|
||||
|
||||
class Texture;
|
||||
class Shader;
|
||||
class Font;
|
||||
|
||||
class Assets {
|
||||
std::unordered_map<std::string, Texture*> textures;
|
||||
std::unordered_map<std::string, Shader*> shaders;
|
||||
std::unordered_map<std::string, Font*> 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_ */
|
||||
|
||||
188
src/audio/Audio.cpp
Normal file
@ -0,0 +1,188 @@
|
||||
#include "Audio.h"
|
||||
#include "audioutil.h"
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
#include <AL/al.h>
|
||||
#include <AL/alc.h>
|
||||
|
||||
ALCdevice* Audio::device;
|
||||
ALCcontext* Audio::context;
|
||||
unsigned Audio::maxSources;
|
||||
unsigned Audio::maxBuffers = 1024;
|
||||
std::vector<ALSource*> Audio::allsources;
|
||||
std::vector<ALSource*> Audio::freesources;
|
||||
std::vector<ALBuffer*> Audio::allbuffers;
|
||||
std::vector<ALBuffer*> 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<ALCint> attrs(size);
|
||||
alcGetIntegerv(device, ALC_ALL_ATTRIBUTES, size, &attrs[0]);
|
||||
for(size_t i=0; i<attrs.size(); ++i){
|
||||
if (attrs[i] == ALC_MONO_SOURCES){
|
||||
std::cout << "max mono sources: " << attrs[i+1] << std::endl;
|
||||
maxSources = attrs[i+1];
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Audio::finalize(){
|
||||
for (ALSource* source : allsources){
|
||||
if (source->isPlaying()){
|
||||
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<std::string>& 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();
|
||||
}
|
||||
62
src/audio/Audio.h
Normal file
@ -0,0 +1,62 @@
|
||||
#ifndef SRC_AUDIO_AUDIO_H_
|
||||
#define SRC_AUDIO_AUDIO_H_
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include <AL/al.h>
|
||||
#include <AL/alc.h>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
|
||||
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<ALSource*> allsources;
|
||||
static std::vector<ALSource*> freesources;
|
||||
|
||||
static std::vector<ALBuffer*> allbuffers;
|
||||
static std::vector<ALBuffer*> 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<std::string>& devicesVec);
|
||||
|
||||
static void setListener(glm::vec3 position, glm::vec3 velocity, glm::vec3 at, glm::vec3 up);
|
||||
|
||||
};
|
||||
|
||||
#endif /* SRC_AUDIO_AUDIO_H_ */
|
||||
194
src/audio/audioutil.cpp
Normal file
@ -0,0 +1,194 @@
|
||||
#include "audioutil.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <cstring>
|
||||
#include <type_traits>
|
||||
#include <AL/al.h>
|
||||
#include <AL/alc.h>
|
||||
|
||||
|
||||
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<char*>(&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;
|
||||
}
|
||||
44
src/audio/audioutil.h
Normal file
@ -0,0 +1,44 @@
|
||||
#ifndef SRC_AUDIO_AUDIOUTIL_H_
|
||||
#define SRC_AUDIO_AUDIOUTIL_H_
|
||||
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
#include <AL/al.h>
|
||||
|
||||
#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_ */
|
||||
154
src/declarations.cpp
Normal file
@ -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<Texture*> 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;
|
||||
}
|
||||
@ -2,113 +2,29 @@
|
||||
#define DECLARATIONS_H
|
||||
|
||||
#include <iostream>
|
||||
#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
|
||||
|
||||
|
||||
@ -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<long, char**>::iterator it;
|
||||
std::unordered_map<long, WorldRegion>::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<long, char**>::iterator it;
|
||||
std::unordered_map<long, WorldRegion>::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;
|
||||
|
||||
@ -3,27 +3,29 @@
|
||||
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
|
||||
#ifndef std::string
|
||||
#include <string>
|
||||
#endif
|
||||
class Player;
|
||||
|
||||
#define REGION_SIZE_BIT 5
|
||||
#define REGION_SIZE (1 << (REGION_SIZE_BIT))
|
||||
#define REGION_VOL ((REGION_SIZE) * (REGION_SIZE))
|
||||
|
||||
/* Требование:
|
||||
* - высота мира = 1 чанк (любых размеров)
|
||||
* Пример:
|
||||
* - CHUNK_W = 16, CHUNK_H = 128, CHUNK_D = 16
|
||||
* */
|
||||
struct WorldRegion {
|
||||
char** chunksData;
|
||||
bool unsaved;
|
||||
};
|
||||
|
||||
class WorldFiles {
|
||||
public:
|
||||
static unsigned long totalCompressed;
|
||||
std::unordered_map<long, char**> regions;
|
||||
std::unordered_map<long, WorldRegion> regions;
|
||||
std::string directory;
|
||||
char* mainBufferIn;
|
||||
char* mainBufferOut;
|
||||
|
||||
WorldFiles(const char* directory, size_t mainBufferCapacity);
|
||||
WorldFiles(std::string directory, size_t mainBufferCapacity);
|
||||
~WorldFiles();
|
||||
|
||||
void put(const char* chunkData, int x, int y);
|
||||
|
||||
@ -69,16 +69,17 @@ unsigned int decompressRLE(const char* src, unsigned int length, char* dst, unsi
|
||||
|
||||
unsigned int calcRLE(const char* src, unsigned int length) {
|
||||
unsigned int offset = 0;
|
||||
unsigned int counter = 1;
|
||||
unsigned int counter = 0;
|
||||
char c = src[0];
|
||||
for (unsigned int i = 0; i < length; i++){
|
||||
char cnext = src[i];
|
||||
if (cnext != c || counter == 256){
|
||||
if (cnext != c || counter == 255){
|
||||
offset += 2;
|
||||
c = cnext;
|
||||
counter = 0;
|
||||
} else {
|
||||
counter++;
|
||||
}
|
||||
counter++;
|
||||
}
|
||||
return offset + 2;
|
||||
}
|
||||
@ -86,19 +87,20 @@ unsigned int calcRLE(const char* src, unsigned int length) {
|
||||
// max result size = length * 2; returns compressed length
|
||||
unsigned int compressRLE(const char* src, unsigned int length, char* dst) {
|
||||
unsigned int offset = 0;
|
||||
unsigned int counter = 1;
|
||||
unsigned int counter = 0;
|
||||
char c = src[0];
|
||||
for (unsigned int i = 1; i < length; i++){
|
||||
char cnext = src[i];
|
||||
if (cnext != c || counter == 256){
|
||||
dst[offset++] = counter-1;
|
||||
if (cnext != c || counter == 255){
|
||||
dst[offset++] = counter;
|
||||
dst[offset++] = c;
|
||||
c = cnext;
|
||||
counter = 0;
|
||||
} else {
|
||||
counter++;
|
||||
}
|
||||
counter++;
|
||||
}
|
||||
dst[offset++] = counter-1;
|
||||
dst[offset++] = counter;
|
||||
dst[offset++] = c;
|
||||
return offset;
|
||||
}
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
#ifndef FILES_FILES_H_
|
||||
#define FILES_FILES_H_
|
||||
|
||||
#ifndef std::string
|
||||
#include <string>
|
||||
#endif
|
||||
|
||||
extern bool write_binary_file(std::string filename, const char* data, size_t size);
|
||||
extern unsigned int append_binary_file(std::string filename, const char* data, size_t size);
|
||||
|
||||
@ -1,18 +1,281 @@
|
||||
#include "Batch2D.h"
|
||||
#include "Mesh.h"
|
||||
#include "Texture.h"
|
||||
#include "Sprite.h"
|
||||
|
||||
Batch2D::Batch2D(size_t capacity) : capacity(capacity),
|
||||
offset(0),
|
||||
color(1.0f, 1.0f, 1.0f, 1.0f){
|
||||
#include <GL/glew.h>
|
||||
|
||||
#define VERTEX_SIZE 8
|
||||
|
||||
Batch2D::Batch2D(size_t capacity) : capacity(capacity), offset(0), color(1.0f, 1.0f, 1.0f, 1.0f){
|
||||
const int attrs[] = {
|
||||
2, 2, 4, 0 //null terminator
|
||||
};
|
||||
|
||||
buffer = new float[capacity];
|
||||
mesh = new Mesh(nullptr, 0, attrs);
|
||||
buffer = new float[capacity * VERTEX_SIZE];
|
||||
mesh = new Mesh(buffer, 0, attrs);
|
||||
index = 0;
|
||||
|
||||
unsigned char pixels[] = {
|
||||
255, 255, 255, 255,
|
||||
};
|
||||
blank = new Texture(pixels, 1, 1);
|
||||
_texture = nullptr;
|
||||
}
|
||||
|
||||
Batch2D::~Batch2D(){
|
||||
delete buffer;
|
||||
delete blank;
|
||||
delete[] buffer;
|
||||
delete mesh;
|
||||
}
|
||||
|
||||
void Batch2D::begin(){
|
||||
_texture = nullptr;
|
||||
blank->bind();
|
||||
}
|
||||
|
||||
void Batch2D::vertex(float x, float y,
|
||||
float u, float v,
|
||||
float r, float g, float b, float a) {
|
||||
buffer[index++] = x;
|
||||
buffer[index++] = y;
|
||||
buffer[index++] = u;
|
||||
buffer[index++] = v;
|
||||
buffer[index++] = r;
|
||||
buffer[index++] = g;
|
||||
buffer[index++] = b;
|
||||
buffer[index++] = a;
|
||||
}
|
||||
void Batch2D::vertex(vec2 point,
|
||||
vec2 uvpoint,
|
||||
float r, float g, float b, float a) {
|
||||
buffer[index++] = point.x;
|
||||
buffer[index++] = point.y;
|
||||
buffer[index++] = uvpoint.x;
|
||||
buffer[index++] = uvpoint.y;
|
||||
buffer[index++] = r;
|
||||
buffer[index++] = g;
|
||||
buffer[index++] = b;
|
||||
buffer[index++] = a;
|
||||
}
|
||||
|
||||
void Batch2D::texture(Texture* new_texture){
|
||||
if (_texture == new_texture)
|
||||
return;
|
||||
render();
|
||||
_texture = new_texture;
|
||||
if (new_texture == nullptr)
|
||||
blank->bind();
|
||||
else
|
||||
new_texture->bind();
|
||||
}
|
||||
|
||||
void Batch2D::rect(float x, float y, float w, float h){
|
||||
const float r = color.r;
|
||||
const float g = color.g;
|
||||
const float b = color.b;
|
||||
const float a = color.a;
|
||||
if (index + 6*VERTEX_SIZE >= capacity)
|
||||
render();
|
||||
|
||||
vertex(x, y, 0, 0, r,g,b,a);
|
||||
vertex(x+w, y+h, 1, 1, r,g,b,a);
|
||||
vertex(x, y+h, 0, 1, r,g,b,a);
|
||||
|
||||
vertex(x, y, 0, 0, r,g,b,a);
|
||||
vertex(x+w, y, 1, 0, r,g,b,a);
|
||||
vertex(x+w, y+h, 1, 1, r,g,b,a);
|
||||
}
|
||||
|
||||
void Batch2D::rect(
|
||||
float x, float y,
|
||||
float w, float h,
|
||||
float ox, float oy,
|
||||
float angle,
|
||||
UVRegion region,
|
||||
bool flippedX,
|
||||
bool flippedY,
|
||||
vec4 tint) {
|
||||
if (index + 6*VERTEX_SIZE >= capacity)
|
||||
render();
|
||||
|
||||
float centerX = w*ox;
|
||||
float centerY = h*oy;
|
||||
float acenterX = w-centerX;
|
||||
float acenterY = h-centerY;
|
||||
|
||||
float _x1 = -centerX;
|
||||
float _y1 = -centerY;
|
||||
|
||||
float _x2 = -centerX;
|
||||
float _y2 = +acenterY;
|
||||
|
||||
float _x3 = +acenterX;
|
||||
float _y3 = +acenterY;
|
||||
|
||||
float _x4 = +acenterX;
|
||||
float _y4 = -centerY;
|
||||
|
||||
float x1,y1,x2,y2,x3,y3,x4,y4;
|
||||
|
||||
if (angle != 0) {
|
||||
float s = sin(angle);
|
||||
float c = cos(angle);
|
||||
|
||||
x1 = c * _x1 - s * _y1;
|
||||
y1 = s * _x1 + c * _y1;
|
||||
|
||||
x2 = c * _x2 - s * _y2;
|
||||
y2 = s * _x2 + c * _y2;
|
||||
|
||||
x3 = c * _x3 - s * _y3;
|
||||
y3 = s * _x3 + c * _y3;
|
||||
|
||||
x4 = x1 + (x3 - x2);
|
||||
y4 = y3 - (y2 - y1);
|
||||
} else {
|
||||
x1 = _x1;
|
||||
y1 = _y1;
|
||||
x2 = _x2;
|
||||
y2 = _y2;
|
||||
x3 = _x3;
|
||||
y3 = _y3;
|
||||
x4 = _x4;
|
||||
y4 = _y4;
|
||||
}
|
||||
|
||||
x1 += x; x2 += x; x3 += x; x4 += x;
|
||||
y1 += y; y2 += y; y3 += y; y4 += y;
|
||||
|
||||
float u1 = region.u1;
|
||||
float v1 = region.v1;
|
||||
float u2 = region.u1;
|
||||
float v2 = region.v2;
|
||||
float u3 = region.u2;
|
||||
float v3 = region.v2;
|
||||
float u4 = region.u2;
|
||||
float v4 = region.v1;
|
||||
|
||||
if (flippedX) {
|
||||
float temp = u1;
|
||||
u1 = u3;
|
||||
u4 = temp;
|
||||
u2 = u3;
|
||||
u3 = temp;
|
||||
}
|
||||
if (flippedY) {
|
||||
float temp = v1;
|
||||
v1 = v2;
|
||||
v4 = v2;
|
||||
v2 = temp;
|
||||
v3 = temp;
|
||||
}
|
||||
|
||||
vertex(x1, y1, u1, v1, tint.r, tint.g, tint.b, tint.a);
|
||||
vertex(x2, y2, u2, v2, tint.r, tint.g, tint.b, tint.a);
|
||||
vertex(x3, y3, u3, v3, tint.r, tint.g, tint.b, tint.a);
|
||||
|
||||
/* Right down triangle */
|
||||
vertex(x1, y1, u1, v1, tint.r, tint.g, tint.b, tint.a);
|
||||
vertex(x3, y3, u3, v3, tint.r, tint.g, tint.b, tint.a);
|
||||
vertex(x4, y4, u4, v4, tint.r, tint.g, tint.b, tint.a);
|
||||
}
|
||||
|
||||
void Batch2D::sprite(Sprite* sprite) {
|
||||
vec2 position = sprite->position;
|
||||
vec2 size = sprite->size;
|
||||
vec2 origin = sprite->origin;
|
||||
texture(sprite->texture);
|
||||
rect(
|
||||
position.x, position.y,
|
||||
size.x, size.y,
|
||||
origin.x, origin.y,
|
||||
sprite->angle,
|
||||
sprite->region,
|
||||
sprite->flippedX,
|
||||
sprite->flippedY,
|
||||
sprite->color);
|
||||
}
|
||||
|
||||
void Batch2D::sprite(float x, float y, float w, float h, int atlasRes, int index, vec4 tint){
|
||||
float scale = 1.0f / (float)atlasRes;
|
||||
float u = (index % atlasRes) * scale;
|
||||
float v = 1.0f - ((index / atlasRes) * scale) - scale;
|
||||
rect(x, y, w, h, u, v, scale, scale, tint.r, tint.g, tint.b, tint.a);
|
||||
}
|
||||
|
||||
void Batch2D::blockSprite(float x, float y, float w, float h, int atlasRes, int index[6], vec4 tint){
|
||||
float scale = 1.0f / (float)atlasRes;
|
||||
float uu = (index[3] % atlasRes) * scale;
|
||||
float vu = 1.0f - ((index[3] / atlasRes) * scale) - scale;
|
||||
float uf = (index[0] % atlasRes) * scale;
|
||||
float vf = 1.0f - ((index[0] / atlasRes) * scale) - scale;
|
||||
if (this->index + 18*VERTEX_SIZE >= capacity)
|
||||
render();
|
||||
|
||||
float ar = 0.88f;
|
||||
float ox = x + (w * 0.5f);
|
||||
float sx = w * 0.5f * ar;
|
||||
vec2 points[7] = {vec2(ox, y+(h*0.5f)),
|
||||
vec2(ox-sx, y+(h*0.25f)),
|
||||
vec2(ox, y),
|
||||
vec2(ox+sx, y+(h*0.25f)),
|
||||
vec2(ox+sx, y+(h*0.75f)),
|
||||
vec2(ox, y+h),
|
||||
vec2(ox-sx, y+(h*0.75f))};
|
||||
|
||||
vec2 uvpoints[8] = {vec2(uu, vu),
|
||||
vec2(uu+scale, vu),
|
||||
vec2(uu+scale, vu+scale),
|
||||
vec2(uu, vu+scale),
|
||||
vec2(uf, vf),
|
||||
vec2(uf+scale, vf),
|
||||
vec2(uf+scale, vf+scale),
|
||||
vec2(uf, vf+scale)};
|
||||
|
||||
vertex(points[0], uvpoints[3], tint.r, tint.g, tint.b, tint.a);
|
||||
vertex(points[1], uvpoints[0], tint.r, tint.g, tint.b, tint.a);
|
||||
vertex(points[2], uvpoints[1], tint.r, tint.g, tint.b, tint.a);
|
||||
|
||||
vertex(points[0], uvpoints[3], tint.r, tint.g, tint.b, tint.a);
|
||||
vertex(points[2], uvpoints[1], tint.r, tint.g, tint.b, tint.a);
|
||||
vertex(points[3], uvpoints[2], tint.r, tint.g, tint.b, tint.a);
|
||||
|
||||
|
||||
vertex(points[0], uvpoints[7], tint.r, tint.g, tint.b, tint.a);
|
||||
vertex(points[3], uvpoints[6], tint.r, tint.g, tint.b, tint.a);
|
||||
vertex(points[4], uvpoints[5], tint.r, tint.g, tint.b, tint.a);
|
||||
|
||||
vertex(points[0], uvpoints[7], tint.r, tint.g, tint.b, tint.a);
|
||||
vertex(points[4], uvpoints[5], tint.r, tint.g, tint.b, tint.a);
|
||||
vertex(points[5], uvpoints[4], tint.r, tint.g, tint.b, tint.a);
|
||||
|
||||
|
||||
vertex(points[0], uvpoints[6], tint.r, tint.g, tint.b, tint.a);
|
||||
vertex(points[5], uvpoints[5], tint.r, tint.g, tint.b, tint.a);
|
||||
vertex(points[6], uvpoints[4], tint.r, tint.g, tint.b, tint.a);
|
||||
|
||||
vertex(points[0], uvpoints[6], tint.r, tint.g, tint.b, tint.a);
|
||||
vertex(points[6], uvpoints[4], tint.r, tint.g, tint.b, tint.a);
|
||||
vertex(points[1], uvpoints[7], tint.r, tint.g, tint.b, tint.a);
|
||||
}
|
||||
|
||||
void Batch2D::rect(float x, float y, float w, float h,
|
||||
float u, float v, float tx, float ty,
|
||||
float r, float g, float b, float a){
|
||||
if (index + 6*VERTEX_SIZE >= capacity)
|
||||
render();
|
||||
vertex(x, y, u, v+ty, r,g,b,a);
|
||||
vertex(x+w, y+h, u+tx, v, r,g,b,a);
|
||||
vertex(x, y+h, u, v, r,g,b,a);
|
||||
|
||||
vertex(x, y, u, v+ty, r,g,b,a);
|
||||
vertex(x+w, y, u+tx, v+ty, r,g,b,a);
|
||||
vertex(x+w, y+h, u+tx, v, r,g,b,a);
|
||||
}
|
||||
|
||||
void Batch2D::render() {
|
||||
mesh->reload(buffer, index / VERTEX_SIZE);
|
||||
mesh->draw(GL_TRIANGLES);
|
||||
index = 0;
|
||||
}
|
||||
|
||||
@ -4,23 +4,53 @@
|
||||
#include <stdlib.h>
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include "UVRegion.h"
|
||||
|
||||
using namespace glm;
|
||||
|
||||
class Mesh;
|
||||
class Texture;
|
||||
class Sprite;
|
||||
|
||||
class Batch2D {
|
||||
float* buffer;
|
||||
size_t capacity;
|
||||
size_t offset;
|
||||
glm::vec4 color;
|
||||
Mesh* mesh;
|
||||
size_t index;
|
||||
|
||||
Texture* blank;
|
||||
Texture* _texture;
|
||||
|
||||
void vertex(float x, float y,
|
||||
float u, float v,
|
||||
float r, float g, float b, float a);
|
||||
void vertex(vec2 point,
|
||||
vec2 uvpoint,
|
||||
float r, float g, float b, float a);
|
||||
|
||||
public:
|
||||
glm::vec4 color;
|
||||
|
||||
Batch2D(size_t capacity);
|
||||
~Batch2D();
|
||||
|
||||
void begin();
|
||||
void texture(Texture* texture);
|
||||
void sprite(float x, float y, float w, float h, int atlasRes, int index, vec4 tint);
|
||||
void sprite(Sprite* sprite);
|
||||
void blockSprite(float x, float y, float w, float h, int atlasRes, int index[6], vec4 tint);
|
||||
void rect(float x, float y,
|
||||
float w, float h,
|
||||
float ox, float oy,
|
||||
float angle, UVRegion region,
|
||||
bool flippedX, bool flippedY,
|
||||
vec4 tint);
|
||||
|
||||
void rect(float x, float y, float w, float h);
|
||||
void rect(float x, float y, float w, float h,
|
||||
float u, float v, float tx, float ty,
|
||||
float r, float g, float b, float a);
|
||||
void render();
|
||||
};
|
||||
|
||||
|
||||
165
src/graphics/Batch3D.cpp
Normal file
@ -0,0 +1,165 @@
|
||||
#include "Batch3D.h"
|
||||
|
||||
#include "Mesh.h"
|
||||
#include "Texture.h"
|
||||
|
||||
#include <GL/glew.h>
|
||||
|
||||
#define VERTEX_SIZE 9
|
||||
|
||||
Batch3D::Batch3D(size_t capacity) : capacity(capacity), offset(0), color(1.0f, 1.0f, 1.0f, 0.0f){
|
||||
const int attrs[] = {
|
||||
3, 2, 4, 0 //null terminator
|
||||
};
|
||||
|
||||
buffer = new float[capacity * VERTEX_SIZE];
|
||||
mesh = new Mesh(buffer, 0, attrs);
|
||||
index = 0;
|
||||
|
||||
unsigned char pixels[] = {
|
||||
255, 255, 255, 255,
|
||||
};
|
||||
blank = new Texture(pixels, 1, 1);
|
||||
_texture = nullptr;
|
||||
}
|
||||
|
||||
Batch3D::~Batch3D(){
|
||||
delete blank;
|
||||
delete[] buffer;
|
||||
delete mesh;
|
||||
}
|
||||
|
||||
void Batch3D::begin(){
|
||||
_texture = nullptr;
|
||||
blank->bind();
|
||||
}
|
||||
|
||||
void Batch3D::vertex(float x, float y, float z, float u, float v,
|
||||
float r, float g, float b, float a) {
|
||||
buffer[index++] = x;
|
||||
buffer[index++] = y;
|
||||
buffer[index++] = z;
|
||||
buffer[index++] = u;
|
||||
buffer[index++] = v;
|
||||
buffer[index++] = r;
|
||||
buffer[index++] = g;
|
||||
buffer[index++] = b;
|
||||
buffer[index++] = a;
|
||||
}
|
||||
void Batch3D::vertex(vec3 point,
|
||||
vec2 uvpoint,
|
||||
float r, float g, float b, float a) {
|
||||
buffer[index++] = point.x;
|
||||
buffer[index++] = point.y;
|
||||
buffer[index++] = point.z;
|
||||
buffer[index++] = uvpoint.x;
|
||||
buffer[index++] = uvpoint.y;
|
||||
buffer[index++] = r;
|
||||
buffer[index++] = g;
|
||||
buffer[index++] = b;
|
||||
buffer[index++] = a;
|
||||
}
|
||||
|
||||
void Batch3D::texture(Texture* new_texture){
|
||||
if (_texture == new_texture)
|
||||
return;
|
||||
render();
|
||||
_texture = new_texture;
|
||||
if (new_texture == nullptr)
|
||||
blank->bind();
|
||||
else
|
||||
new_texture->bind();
|
||||
}
|
||||
|
||||
void Batch3D::sprite(vec3 pos, vec3 up, vec3 right, float w, float h){
|
||||
const float r = color.r;
|
||||
const float g = color.g;
|
||||
const float b = color.b;
|
||||
const float a = color.a;
|
||||
if (index + 6*VERTEX_SIZE >= capacity)
|
||||
render();
|
||||
|
||||
vertex(pos.x - right.x * w - up.x * h,
|
||||
pos.y - right.y * w - up.y * h,
|
||||
pos.z - right.z * w - up.z * h,
|
||||
0, 0,
|
||||
r,g,b,a);
|
||||
|
||||
vertex(pos.x + right.x * w + up.x * h,
|
||||
pos.y + right.y * w + up.y * h,
|
||||
pos.z + right.z * w + up.z * h,
|
||||
1, 1,
|
||||
r,g,b,a);
|
||||
|
||||
vertex(pos.x - right.x * w - up.x * h,
|
||||
pos.y + right.y * w + up.y * h,
|
||||
pos.z - right.z * w - up.z * h,
|
||||
0, 1,
|
||||
r,g,b,a);
|
||||
|
||||
vertex(pos.x - right.x * w - up.x * h,
|
||||
pos.y - right.y * w - up.y * h,
|
||||
pos.z - right.z * w - up.z * h,
|
||||
0, 0,
|
||||
r,g,b,a);
|
||||
|
||||
vertex(pos.x + right.x * w + up.x * h,
|
||||
pos.y - right.y * w - up.y * h,
|
||||
pos.z + right.z * w + up.z * h,
|
||||
1, 0,
|
||||
r,g,b,a);
|
||||
|
||||
vertex(pos.x + right.x * w + up.x * h,
|
||||
pos.y + right.y * w + up.y * h,
|
||||
pos.z + right.z * w + up.z * h,
|
||||
1, 1,
|
||||
r,g,b,a);
|
||||
}
|
||||
|
||||
void Batch3D::sprite(vec3 pos, vec3 up, vec3 right, float w, float h, int atlasRes, int index, vec4 tint){
|
||||
float scale = 1.0f / (float)atlasRes;
|
||||
float u = (index % atlasRes) * scale;
|
||||
float v = 1.0f - ((index / atlasRes) * scale) - scale;
|
||||
|
||||
vertex(pos.x - right.x * w - up.x * h,
|
||||
pos.y - right.y * w - up.y * h,
|
||||
pos.z - right.z * w - up.z * h,
|
||||
u, v,
|
||||
tint.r,tint.g,tint.b,tint.a);
|
||||
|
||||
vertex(pos.x + right.x * w + up.x * h,
|
||||
pos.y + right.y * w + up.y * h,
|
||||
pos.z + right.z * w + up.z * h,
|
||||
u+scale, v+scale,
|
||||
tint.r,tint.g,tint.b,tint.a);
|
||||
|
||||
vertex(pos.x - right.x * w - up.x * h,
|
||||
pos.y + right.y * w + up.y * h,
|
||||
pos.z - right.z * w - up.z * h,
|
||||
u, v+scale,
|
||||
tint.r,tint.g,tint.b,tint.a);
|
||||
|
||||
vertex(pos.x - right.x * w - up.x * h,
|
||||
pos.y - right.y * w - up.y * h,
|
||||
pos.z - right.z * w - up.z * h,
|
||||
u, v,
|
||||
tint.r,tint.g,tint.b,tint.a);
|
||||
|
||||
vertex(pos.x + right.x * w + up.x * h,
|
||||
pos.y - right.y * w - up.y * h,
|
||||
pos.z + right.z * w + up.z * h,
|
||||
u+scale, v,
|
||||
tint.r,tint.g,tint.b,tint.a);
|
||||
|
||||
vertex(pos.x + right.x * w + up.x * h,
|
||||
pos.y + right.y * w + up.y * h,
|
||||
pos.z + right.z * w + up.z * h,
|
||||
u+scale, v+scale,
|
||||
tint.r,tint.g,tint.b,tint.a);
|
||||
}
|
||||
|
||||
void Batch3D::render() {
|
||||
mesh->reload(buffer, index / VERTEX_SIZE);
|
||||
mesh->draw(GL_TRIANGLES);
|
||||
index = 0;
|
||||
}
|
||||
40
src/graphics/Batch3D.h
Normal file
@ -0,0 +1,40 @@
|
||||
#ifndef GRAPHICS_BATCH3D_H_
|
||||
#define GRAPHICS_BATCH3D_H_
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
using namespace glm;
|
||||
|
||||
class Mesh;
|
||||
class Texture;
|
||||
|
||||
class Batch3D {
|
||||
float* buffer;
|
||||
size_t capacity;
|
||||
size_t offset;
|
||||
glm::vec4 color;
|
||||
Mesh* mesh;
|
||||
size_t index;
|
||||
|
||||
Texture* blank;
|
||||
Texture* _texture;
|
||||
|
||||
void vertex(float x, float y, float z,
|
||||
float u, float v,
|
||||
float r, float g, float b, float a);
|
||||
void vertex(vec3 point, vec2 uvpoint,
|
||||
float r, float g, float b, float a);
|
||||
|
||||
public:
|
||||
Batch3D(size_t capacity);
|
||||
~Batch3D();
|
||||
|
||||
void begin();
|
||||
void texture(Texture* texture);
|
||||
void sprite(vec3 pos, vec3 up, vec3 right, float w, float h, int atlasRes, int index, vec4 tint);
|
||||
void sprite(vec3 pos, vec3 up, vec3 right, float w, float h);
|
||||
void render();
|
||||
};
|
||||
|
||||
#endif /* GRAPHICS_BATCH3D_H_ */
|
||||
90
src/graphics/Font.cpp
Normal file
@ -0,0 +1,90 @@
|
||||
#include "Font.h"
|
||||
#include "Texture.h"
|
||||
#include "Batch2D.h"
|
||||
|
||||
Font::Font(std::vector<Texture*> pages) : pages(pages) {
|
||||
}
|
||||
|
||||
Font::~Font(){
|
||||
for (Texture* texture : pages)
|
||||
delete texture;
|
||||
}
|
||||
|
||||
int Font::getGlyphWidth(char c) {
|
||||
switch (c){
|
||||
case 'l':
|
||||
case 'i':
|
||||
case 'j':
|
||||
case '|':
|
||||
case '.':
|
||||
case ',':
|
||||
case ':':
|
||||
case ';': return 7;
|
||||
case 't': return 8;
|
||||
case ' ': return 7;
|
||||
}
|
||||
return 7;
|
||||
}
|
||||
|
||||
|
||||
bool Font::isPrintableChar(int c) {
|
||||
switch (c){
|
||||
case ' ':
|
||||
case '\t':
|
||||
case '\n':
|
||||
case '\f':
|
||||
case '\r':
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
#define RES 16
|
||||
|
||||
void Font::draw(Batch2D* batch, std::wstring text, int x, int y) {
|
||||
draw(batch, text, x, y, STYLE_NONE);
|
||||
}
|
||||
|
||||
void Font::draw(Batch2D* batch, std::wstring text, int x, int y, int style) {
|
||||
int page = 0;
|
||||
int next = 10000;
|
||||
int init_x = x;
|
||||
do {
|
||||
for (unsigned c : text){
|
||||
if (isPrintableChar(c)){
|
||||
int charpage = c >> 8;
|
||||
if (charpage == page){
|
||||
Texture* texture = pages[charpage];
|
||||
if (texture == nullptr){
|
||||
texture = pages[0];
|
||||
}
|
||||
batch->texture(pages[charpage]);
|
||||
|
||||
switch (style){
|
||||
case STYLE_SHADOW:
|
||||
batch->sprite(x+1, y+1, RES, RES, 16, c, vec4(0.0f, 0.0f, 0.0f, 1.0f));
|
||||
break;
|
||||
case STYLE_OUTLINE:
|
||||
for (int oy = -1; oy <= 1; oy++){
|
||||
for (int ox = -1; ox <= 1; ox++){
|
||||
if (ox || oy)
|
||||
batch->sprite(x+ox, y+oy, RES, RES, 16, c, vec4(0.0f, 0.0f, 0.0f, 1.0f));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
batch->sprite(x, y, RES, RES, 16, c, batch->color);
|
||||
}
|
||||
else if (charpage > page && charpage < next){
|
||||
next = charpage;
|
||||
}
|
||||
}
|
||||
x += getGlyphWidth(c);
|
||||
}
|
||||
page = next;
|
||||
next = 10000;
|
||||
x = init_x;
|
||||
} while (page < 10000);
|
||||
}
|
||||
26
src/graphics/Font.h
Normal file
@ -0,0 +1,26 @@
|
||||
#ifndef GRAPHICS_FONT_H_
|
||||
#define GRAPHICS_FONT_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class Texture;
|
||||
class Batch2D;
|
||||
|
||||
#define STYLE_NONE 0
|
||||
#define STYLE_SHADOW 1
|
||||
#define STYLE_OUTLINE 2
|
||||
|
||||
class Font {
|
||||
public:
|
||||
std::vector<Texture*> pages;
|
||||
Font(std::vector<Texture*> pages);
|
||||
~Font();
|
||||
|
||||
int getGlyphWidth(char c);
|
||||
bool isPrintableChar(int c);
|
||||
void draw(Batch2D* batch, std::wstring text, int x, int y);
|
||||
void draw(Batch2D* batch, std::wstring text, int x, int y, int style);
|
||||
};
|
||||
|
||||
#endif /* GRAPHICS_FONT_H_ */
|
||||
37
src/graphics/Framebuffer.cpp
Normal file
@ -0,0 +1,37 @@
|
||||
#include "Framebuffer.h"
|
||||
|
||||
#include <GL/glew.h>
|
||||
#include "Texture.h"
|
||||
|
||||
Framebuffer::Framebuffer(int width, int height) : width(width), height(height) {
|
||||
glGenFramebuffers(1, &fbo);
|
||||
bind();
|
||||
GLuint tex;
|
||||
glGenTextures(1, &tex);
|
||||
glBindTexture(GL_TEXTURE_2D, tex);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
|
||||
texture = new Texture(tex, width, height);
|
||||
glGenRenderbuffers(1, &depth);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, depth);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, width, height);
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depth);
|
||||
unbind();
|
||||
}
|
||||
|
||||
Framebuffer::~Framebuffer() {
|
||||
delete texture;
|
||||
glDeleteFramebuffers(1, &fbo);
|
||||
}
|
||||
|
||||
void Framebuffer::bind() {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
}
|
||||
|
||||
void Framebuffer::unbind() {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
}
|
||||
20
src/graphics/Framebuffer.h
Normal file
@ -0,0 +1,20 @@
|
||||
#ifndef SRC_GRAPHICS_FRAMEBUFFER_H_
|
||||
#define SRC_GRAPHICS_FRAMEBUFFER_H_
|
||||
|
||||
class Texture;
|
||||
|
||||
class Framebuffer {
|
||||
unsigned int fbo;
|
||||
unsigned int depth;
|
||||
public:
|
||||
int width;
|
||||
int height;
|
||||
Texture* texture;
|
||||
Framebuffer(int width, int height);
|
||||
~Framebuffer();
|
||||
|
||||
void bind();
|
||||
void unbind();
|
||||
};
|
||||
|
||||
#endif /* SRC_GRAPHICS_FRAMEBUFFER_H_ */
|
||||
17
src/graphics/Sprite.cpp
Normal file
@ -0,0 +1,17 @@
|
||||
#include "Sprite.h"
|
||||
|
||||
#include "Texture.h"
|
||||
|
||||
Sprite::Sprite(glm::vec2 position, glm::vec2 size, Texture* texture)
|
||||
: position(position),
|
||||
size(size),
|
||||
origin(0.5f, 0.5f),
|
||||
color(1.0f, 1.0f, 1.0f, 1.0f),
|
||||
angle(0.0f),
|
||||
texture(texture),
|
||||
region() {
|
||||
}
|
||||
|
||||
Sprite::~Sprite() {
|
||||
}
|
||||
|
||||
29
src/graphics/Sprite.h
Normal file
@ -0,0 +1,29 @@
|
||||
#ifndef SRC_GRAPHICS_SPRITE_H_
|
||||
#define SRC_GRAPHICS_SPRITE_H_
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include "UVRegion.h"
|
||||
|
||||
class Texture;
|
||||
|
||||
class Sprite {
|
||||
public:
|
||||
glm::vec2 position;
|
||||
glm::vec2 size;
|
||||
glm::vec2 origin;
|
||||
glm::vec4 color;
|
||||
float angle;
|
||||
bool flippedX = false;
|
||||
bool flippedY = false;
|
||||
Texture* texture;
|
||||
UVRegion region;
|
||||
|
||||
Sprite(glm::vec2 position, glm::vec2 size, Texture* texture);
|
||||
virtual ~Sprite();
|
||||
|
||||
void setTexture(Texture* texture) {
|
||||
this->texture = texture;
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* SRC_GRAPHICS_SPRITE_H_ */
|
||||
1
src/graphics/UVRegion.cpp
Normal file
@ -0,0 +1 @@
|
||||
#include "UVRegion.h"
|
||||
17
src/graphics/UVRegion.h
Normal file
@ -0,0 +1,17 @@
|
||||
#ifndef SRC_GRAPHICS_UVREGION_H_
|
||||
#define SRC_GRAPHICS_UVREGION_H_
|
||||
|
||||
class UVRegion {
|
||||
public:
|
||||
float u1;
|
||||
float v1;
|
||||
float u2;
|
||||
float v2;
|
||||
|
||||
UVRegion(float u1, float v1, float u2, float v2)
|
||||
: u1(u1), v1(v1), u2(u2), v2(v2){}
|
||||
|
||||
UVRegion() : u1(0.0f), v1(0.0f), u2(1.0f), v2(1.0f){}
|
||||
};
|
||||
|
||||
#endif /* SRC_GRAPHICS_UVREGION_H_ */
|
||||
@ -1,32 +1,33 @@
|
||||
#include "VoxelRenderer.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <math.h>
|
||||
#include "Mesh.h"
|
||||
#include "../voxels/Chunk.h"
|
||||
#include "../voxels/voxel.h"
|
||||
#include "../voxels/Block.h"
|
||||
#include "../lighting/Lightmap.h"
|
||||
|
||||
#define VERTEX_SIZE (3 + 2 + 4)
|
||||
|
||||
#define CDIV(X,A) (((X) < 0) ? ((X) / (A) - 1) : ((X) / (A)))
|
||||
#define LOCAL_NEG(X, SIZE) (((X) < 0) ? ((SIZE)+(X)) : (X))
|
||||
#define LOCAL(X, SIZE) ((X) >= (SIZE) ? ((X) - (SIZE)) : LOCAL_NEG(X, SIZE))
|
||||
#define IS_CHUNK(X,Y,Z) (GET_CHUNK(X,Y,Z) != nullptr)
|
||||
#define GET_CHUNK(X,Y,Z) (chunks[((CDIV(Y, CHUNK_H)+1) * 3 + CDIV(Z, CHUNK_D) + 1) * 3 + CDIV(X, CHUNK_W) + 1])
|
||||
#define GET_CHUNK(X,Y,Z) (chunks[(CDIV(Z, CHUNK_D) + 1) * 3 + CDIV(X, CHUNK_W) + 1])
|
||||
|
||||
#define LIGHT(X,Y,Z, CHANNEL) (IS_CHUNK(X,Y,Z) ? GET_CHUNK(X,Y,Z)->lightmap->get(LOCAL(X, CHUNK_W), LOCAL(Y, CHUNK_H), LOCAL(Z, CHUNK_D), (CHANNEL)) : 0)
|
||||
#define VOXEL(X,Y,Z) (GET_CHUNK(X,Y,Z)->voxels[(LOCAL(Y, CHUNK_H) * CHUNK_D + LOCAL(Z, CHUNK_D)) * CHUNK_W + LOCAL(X, CHUNK_W)])
|
||||
#define IS_BLOCKED(X,Y,Z,GROUP) ((!IS_CHUNK(X, Y, Z)) || Block::blocks[VOXEL(X, Y, Z).id]->drawGroup == (GROUP))
|
||||
|
||||
#define VERTEX(INDEX, X,Y,Z, U,V, R,G,B,S) buffer[INDEX+0] = (X);\
|
||||
buffer[INDEX+1] = (Y);\
|
||||
buffer[INDEX+2] = (Z);\
|
||||
buffer[INDEX+3] = (U);\
|
||||
buffer[INDEX+4] = (V);\
|
||||
buffer[INDEX+5] = (R);\
|
||||
buffer[INDEX+6] = (G);\
|
||||
buffer[INDEX+7] = (B);\
|
||||
buffer[INDEX+8] = (S);\
|
||||
INDEX += VERTEX_SIZE;
|
||||
#define VERTEX(INDEX, X,Y,Z, U,V, R,G,B,S) buffer.push_back(X);\
|
||||
buffer.push_back(Y);\
|
||||
buffer.push_back(Z);\
|
||||
buffer.push_back(U);\
|
||||
buffer.push_back(V);\
|
||||
buffer.push_back(R);\
|
||||
buffer.push_back(G);\
|
||||
buffer.push_back(B);\
|
||||
buffer.push_back(S);\
|
||||
INDEX += CHUNK_VERTEX_SIZE;
|
||||
|
||||
|
||||
#define SETUP_UV(INDEX) float u1 = ((INDEX) % 16) * uvsize;\
|
||||
@ -36,21 +37,13 @@
|
||||
|
||||
int chunk_attrs[] = {3,2,4, 0};
|
||||
|
||||
VoxelRenderer::VoxelRenderer(size_t capacity) : capacity(capacity) {
|
||||
buffer = new float[capacity * VERTEX_SIZE * 6];
|
||||
VoxelRenderer::VoxelRenderer() {
|
||||
}
|
||||
|
||||
VoxelRenderer::~VoxelRenderer(){
|
||||
delete[] buffer;
|
||||
}
|
||||
|
||||
inline void _renderBlock(float* buffer, int x, int y, int z, const Chunk** chunks, voxel vox, size_t& index){
|
||||
unsigned int id = vox.id;
|
||||
|
||||
if (!id){
|
||||
return;
|
||||
}
|
||||
|
||||
inline void _renderBlock(std::vector<float>& buffer, int x, int y, int z, const Chunk** chunks, unsigned int id, size_t& index){
|
||||
float l;
|
||||
float uvsize = 1.0f/16.0f;
|
||||
|
||||
@ -62,30 +55,30 @@ inline void _renderBlock(float* buffer, int x, int y, int z, const Chunk** chunk
|
||||
|
||||
SETUP_UV(block->textureFaces[3]);
|
||||
|
||||
float lr = LIGHT(x,y+1,z, 0) / 15.0f;
|
||||
float lg = LIGHT(x,y+1,z, 1) / 15.0f;
|
||||
float lb = LIGHT(x,y+1,z, 2) / 15.0f;
|
||||
float ls = LIGHT(x,y+1,z, 3) / 15.0f;
|
||||
const float lr = LIGHT(x,y+1,z, 0) / 15.0f;
|
||||
const float lg = LIGHT(x,y+1,z, 1) / 15.0f;
|
||||
const float lb = LIGHT(x,y+1,z, 2) / 15.0f;
|
||||
const float ls = LIGHT(x,y+1,z, 3) / 15.0f;
|
||||
|
||||
float lr0 = (LIGHT(x-1,y+1,z,0) + lr*30 + LIGHT(x-1,y+1,z-1,0) + LIGHT(x,y+1,z-1,0)) / 5.0f / 15.0f;
|
||||
float lr1 = (LIGHT(x-1,y+1,z,0) + lr*30 + LIGHT(x-1,y+1,z+1,0) + LIGHT(x,y+1,z+1,0)) / 5.0f / 15.0f;
|
||||
float lr2 = (LIGHT(x+1,y+1,z,0) + lr*30 + LIGHT(x+1,y+1,z+1,0) + LIGHT(x,y+1,z+1,0)) / 5.0f / 15.0f;
|
||||
float lr3 = (LIGHT(x+1,y+1,z,0) + lr*30 + LIGHT(x+1,y+1,z-1,0) + LIGHT(x,y+1,z-1,0)) / 5.0f / 15.0f;
|
||||
float lr0 = (LIGHT(x-1,y+1,z,0) + lr*30 + LIGHT(x-1,y+1,z-1,0) + LIGHT(x,y+1,z-1,0)) / 75.0f;
|
||||
float lr1 = (LIGHT(x-1,y+1,z,0) + lr*30 + LIGHT(x-1,y+1,z+1,0) + LIGHT(x,y+1,z+1,0)) / 75.0f;
|
||||
float lr2 = (LIGHT(x+1,y+1,z,0) + lr*30 + LIGHT(x+1,y+1,z+1,0) + LIGHT(x,y+1,z+1,0)) / 75.0f;
|
||||
float lr3 = (LIGHT(x+1,y+1,z,0) + lr*30 + LIGHT(x+1,y+1,z-1,0) + LIGHT(x,y+1,z-1,0)) / 75.0f;
|
||||
|
||||
float lg0 = (LIGHT(x-1,y+1,z,1) + lg*30 + LIGHT(x-1,y+1,z-1,1) + LIGHT(x,y+1,z-1,1)) / 5.0f / 15.0f;
|
||||
float lg1 = (LIGHT(x-1,y+1,z,1) + lg*30 + LIGHT(x-1,y+1,z+1,1) + LIGHT(x,y+1,z+1,1)) / 5.0f / 15.0f;
|
||||
float lg2 = (LIGHT(x+1,y+1,z,1) + lg*30 + LIGHT(x+1,y+1,z+1,1) + LIGHT(x,y+1,z+1,1)) / 5.0f / 15.0f;
|
||||
float lg3 = (LIGHT(x+1,y+1,z,1) + lg*30 + LIGHT(x+1,y+1,z-1,1) + LIGHT(x,y+1,z-1,1)) / 5.0f / 15.0f;
|
||||
float lg0 = (LIGHT(x-1,y+1,z,1) + lg*30 + LIGHT(x-1,y+1,z-1,1) + LIGHT(x,y+1,z-1,1)) / 75.0f;
|
||||
float lg1 = (LIGHT(x-1,y+1,z,1) + lg*30 + LIGHT(x-1,y+1,z+1,1) + LIGHT(x,y+1,z+1,1)) / 75.0f;
|
||||
float lg2 = (LIGHT(x+1,y+1,z,1) + lg*30 + LIGHT(x+1,y+1,z+1,1) + LIGHT(x,y+1,z+1,1)) / 75.0f;
|
||||
float lg3 = (LIGHT(x+1,y+1,z,1) + lg*30 + LIGHT(x+1,y+1,z-1,1) + LIGHT(x,y+1,z-1,1)) / 75.0f;
|
||||
|
||||
float lb0 = (LIGHT(x-1,y+1,z,2) + lb*30 + LIGHT(x-1,y+1,z-1,2) + LIGHT(x,y+1,z-1,2)) / 5.0f / 15.0f;
|
||||
float lb1 = (LIGHT(x-1,y+1,z,2) + lb*30 + LIGHT(x-1,y+1,z+1,2) + LIGHT(x,y+1,z+1,2)) / 5.0f / 15.0f;
|
||||
float lb2 = (LIGHT(x+1,y+1,z,2) + lb*30 + LIGHT(x+1,y+1,z+1,2) + LIGHT(x,y+1,z+1,2)) / 5.0f / 15.0f;
|
||||
float lb3 = (LIGHT(x+1,y+1,z,2) + lb*30 + LIGHT(x+1,y+1,z-1,2) + LIGHT(x,y+1,z-1,2)) / 5.0f / 15.0f;
|
||||
float lb0 = (LIGHT(x-1,y+1,z,2) + lb*30 + LIGHT(x-1,y+1,z-1,2) + LIGHT(x,y+1,z-1,2)) / 75.0f;
|
||||
float lb1 = (LIGHT(x-1,y+1,z,2) + lb*30 + LIGHT(x-1,y+1,z+1,2) + LIGHT(x,y+1,z+1,2)) / 75.0f;
|
||||
float lb2 = (LIGHT(x+1,y+1,z,2) + lb*30 + LIGHT(x+1,y+1,z+1,2) + LIGHT(x,y+1,z+1,2)) / 75.0f;
|
||||
float lb3 = (LIGHT(x+1,y+1,z,2) + lb*30 + LIGHT(x+1,y+1,z-1,2) + LIGHT(x,y+1,z-1,2)) / 75.0f;
|
||||
|
||||
float ls0 = (LIGHT(x-1,y+1,z,3) + ls*30 + LIGHT(x-1,y+1,z-1,3) + LIGHT(x,y+1,z-1,3)) / 5.0f / 15.0f;
|
||||
float ls1 = (LIGHT(x-1,y+1,z,3) + ls*30 + LIGHT(x-1,y+1,z+1,3) + LIGHT(x,y+1,z+1,3)) / 5.0f / 15.0f;
|
||||
float ls2 = (LIGHT(x+1,y+1,z,3) + ls*30 + LIGHT(x+1,y+1,z+1,3) + LIGHT(x,y+1,z+1,3)) / 5.0f / 15.0f;
|
||||
float ls3 = (LIGHT(x+1,y+1,z,3) + ls*30 + LIGHT(x+1,y+1,z-1,3) + LIGHT(x,y+1,z-1,3)) / 5.0f / 15.0f;
|
||||
float ls0 = (LIGHT(x-1,y+1,z,3) + ls*30 + LIGHT(x-1,y+1,z-1,3) + LIGHT(x,y+1,z-1,3)) / 75.0f;
|
||||
float ls1 = (LIGHT(x-1,y+1,z,3) + ls*30 + LIGHT(x-1,y+1,z+1,3) + LIGHT(x,y+1,z+1,3)) / 75.0f;
|
||||
float ls2 = (LIGHT(x+1,y+1,z,3) + ls*30 + LIGHT(x+1,y+1,z+1,3) + LIGHT(x,y+1,z+1,3)) / 75.0f;
|
||||
float ls3 = (LIGHT(x+1,y+1,z,3) + ls*30 + LIGHT(x+1,y+1,z-1,3) + LIGHT(x,y+1,z-1,3)) / 75.0f;
|
||||
|
||||
VERTEX(index, x-0.5f, y+0.5f, z-0.5f, u2,v1, lr0, lg0, lb0, ls0);
|
||||
VERTEX(index, x-0.5f, y+0.5f, z+0.5f, u2,v2, lr1, lg1, lb1, ls1);
|
||||
@ -100,30 +93,30 @@ inline void _renderBlock(float* buffer, int x, int y, int z, const Chunk** chunk
|
||||
|
||||
SETUP_UV(block->textureFaces[2]);
|
||||
|
||||
float lr = LIGHT(x,y-1,z, 0) / 15.0f;
|
||||
float lg = LIGHT(x,y-1,z, 1) / 15.0f;
|
||||
float lb = LIGHT(x,y-1,z, 2) / 15.0f;
|
||||
float ls = LIGHT(x,y-1,z, 3) / 15.0f;
|
||||
const float lr = LIGHT(x,y-1,z, 0) / 15.0f;
|
||||
const float lg = LIGHT(x,y-1,z, 1) / 15.0f;
|
||||
const float lb = LIGHT(x,y-1,z, 2) / 15.0f;
|
||||
const float ls = LIGHT(x,y-1,z, 3) / 15.0f;
|
||||
|
||||
float lr0 = (LIGHT(x-1,y-1,z-1,0) + lr*30 + LIGHT(x-1,y-1,z,0) + LIGHT(x,y-1,z-1,0)) / 5.0f / 15.0f;
|
||||
float lr1 = (LIGHT(x+1,y-1,z+1,0) + lr*30 + LIGHT(x+1,y-1,z,0) + LIGHT(x,y-1,z+1,0)) / 5.0f / 15.0f;
|
||||
float lr2 = (LIGHT(x-1,y-1,z+1,0) + lr*30 + LIGHT(x-1,y-1,z,0) + LIGHT(x,y-1,z+1,0)) / 5.0f / 15.0f;
|
||||
float lr3 = (LIGHT(x+1,y-1,z-1,0) + lr*30 + LIGHT(x+1,y-1,z,0) + LIGHT(x,y-1,z-1,0)) / 5.0f / 15.0f;
|
||||
float lr0 = (LIGHT(x-1,y-1,z-1,0) + lr*30 + LIGHT(x-1,y-1,z,0) + LIGHT(x,y-1,z-1,0)) / 75.0f;
|
||||
float lr1 = (LIGHT(x+1,y-1,z+1,0) + lr*30 + LIGHT(x+1,y-1,z,0) + LIGHT(x,y-1,z+1,0)) / 75.0f;
|
||||
float lr2 = (LIGHT(x-1,y-1,z+1,0) + lr*30 + LIGHT(x-1,y-1,z,0) + LIGHT(x,y-1,z+1,0)) / 75.0f;
|
||||
float lr3 = (LIGHT(x+1,y-1,z-1,0) + lr*30 + LIGHT(x+1,y-1,z,0) + LIGHT(x,y-1,z-1,0)) / 75.0f;
|
||||
|
||||
float lg0 = (LIGHT(x-1,y-1,z-1,1) + lg*30 + LIGHT(x-1,y-1,z,1) + LIGHT(x,y-1,z-1,1)) / 5.0f / 15.0f;
|
||||
float lg1 = (LIGHT(x+1,y-1,z+1,1) + lg*30 + LIGHT(x+1,y-1,z,1) + LIGHT(x,y-1,z+1,1)) / 5.0f / 15.0f;
|
||||
float lg2 = (LIGHT(x-1,y-1,z+1,1) + lg*30 + LIGHT(x-1,y-1,z,1) + LIGHT(x,y-1,z+1,1)) / 5.0f / 15.0f;
|
||||
float lg3 = (LIGHT(x+1,y-1,z-1,1) + lg*30 + LIGHT(x+1,y-1,z,1) + LIGHT(x,y-1,z-1,1)) / 5.0f / 15.0f;
|
||||
float lg0 = (LIGHT(x-1,y-1,z-1,1) + lg*30 + LIGHT(x-1,y-1,z,1) + LIGHT(x,y-1,z-1,1)) / 75.0f;
|
||||
float lg1 = (LIGHT(x+1,y-1,z+1,1) + lg*30 + LIGHT(x+1,y-1,z,1) + LIGHT(x,y-1,z+1,1)) / 75.0f;
|
||||
float lg2 = (LIGHT(x-1,y-1,z+1,1) + lg*30 + LIGHT(x-1,y-1,z,1) + LIGHT(x,y-1,z+1,1)) / 75.0f;
|
||||
float lg3 = (LIGHT(x+1,y-1,z-1,1) + lg*30 + LIGHT(x+1,y-1,z,1) + LIGHT(x,y-1,z-1,1)) / 75.0f;
|
||||
|
||||
float lb0 = (LIGHT(x-1,y-1,z-1,2) + lb*30 + LIGHT(x-1,y-1,z,2) + LIGHT(x,y-1,z-1,2)) / 5.0f / 15.0f;
|
||||
float lb1 = (LIGHT(x+1,y-1,z+1,2) + lb*30 + LIGHT(x+1,y-1,z,2) + LIGHT(x,y-1,z+1,2)) / 5.0f / 15.0f;
|
||||
float lb2 = (LIGHT(x-1,y-1,z+1,2) + lb*30 + LIGHT(x-1,y-1,z,2) + LIGHT(x,y-1,z+1,2)) / 5.0f / 15.0f;
|
||||
float lb3 = (LIGHT(x+1,y-1,z-1,2) + lb*30 + LIGHT(x+1,y-1,z,2) + LIGHT(x,y-1,z-1,2)) / 5.0f / 15.0f;
|
||||
float lb0 = (LIGHT(x-1,y-1,z-1,2) + lb*30 + LIGHT(x-1,y-1,z,2) + LIGHT(x,y-1,z-1,2)) / 75.0f;
|
||||
float lb1 = (LIGHT(x+1,y-1,z+1,2) + lb*30 + LIGHT(x+1,y-1,z,2) + LIGHT(x,y-1,z+1,2)) / 75.0f;
|
||||
float lb2 = (LIGHT(x-1,y-1,z+1,2) + lb*30 + LIGHT(x-1,y-1,z,2) + LIGHT(x,y-1,z+1,2)) / 75.0f;
|
||||
float lb3 = (LIGHT(x+1,y-1,z-1,2) + lb*30 + LIGHT(x+1,y-1,z,2) + LIGHT(x,y-1,z-1,2)) / 75.0f;
|
||||
|
||||
float ls0 = (LIGHT(x-1,y-1,z-1,3) + ls*30 + LIGHT(x-1,y-1,z,3) + LIGHT(x,y-1,z-1,3)) / 5.0f / 15.0f;
|
||||
float ls1 = (LIGHT(x+1,y-1,z+1,3) + ls*30 + LIGHT(x+1,y-1,z,3) + LIGHT(x,y-1,z+1,3)) / 5.0f / 15.0f;
|
||||
float ls2 = (LIGHT(x-1,y-1,z+1,3) + ls*30 + LIGHT(x-1,y-1,z,3) + LIGHT(x,y-1,z+1,3)) / 5.0f / 15.0f;
|
||||
float ls3 = (LIGHT(x+1,y-1,z-1,3) + ls*30 + LIGHT(x+1,y-1,z,3) + LIGHT(x,y-1,z-1,3)) / 5.0f / 15.0f;
|
||||
float ls0 = (LIGHT(x-1,y-1,z-1,3) + ls*30 + LIGHT(x-1,y-1,z,3) + LIGHT(x,y-1,z-1,3)) / 75.0f;
|
||||
float ls1 = (LIGHT(x+1,y-1,z+1,3) + ls*30 + LIGHT(x+1,y-1,z,3) + LIGHT(x,y-1,z+1,3)) / 75.0f;
|
||||
float ls2 = (LIGHT(x-1,y-1,z+1,3) + ls*30 + LIGHT(x-1,y-1,z,3) + LIGHT(x,y-1,z+1,3)) / 75.0f;
|
||||
float ls3 = (LIGHT(x+1,y-1,z-1,3) + ls*30 + LIGHT(x+1,y-1,z,3) + LIGHT(x,y-1,z-1,3)) / 75.0f;
|
||||
|
||||
VERTEX(index, x-0.5f, y-0.5f, z-0.5f, u1,v1, lr0,lg0,lb0,ls0);
|
||||
VERTEX(index, x+0.5f, y-0.5f, z+0.5f, u2,v2, lr1,lg1,lb1,ls1);
|
||||
@ -139,30 +132,30 @@ inline void _renderBlock(float* buffer, int x, int y, int z, const Chunk** chunk
|
||||
|
||||
SETUP_UV(block->textureFaces[1]);
|
||||
|
||||
float lr = LIGHT(x+1,y,z, 0) / 15.0f;
|
||||
float lg = LIGHT(x+1,y,z, 1) / 15.0f;
|
||||
float lb = LIGHT(x+1,y,z, 2) / 15.0f;
|
||||
float ls = LIGHT(x+1,y,z, 3) / 15.0f;
|
||||
const float lr = LIGHT(x+1,y,z, 0) / 15.0f;
|
||||
const float lg = LIGHT(x+1,y,z, 1) / 15.0f;
|
||||
const float lb = LIGHT(x+1,y,z, 2) / 15.0f;
|
||||
const float ls = LIGHT(x+1,y,z, 3) / 15.0f;
|
||||
|
||||
float lr0 = (LIGHT(x+1,y-1,z-1,0) + lr*30 + LIGHT(x+1,y,z-1,0) + LIGHT(x+1,y-1,z,0)) / 5.0f / 15.0f;
|
||||
float lr1 = (LIGHT(x+1,y+1,z-1,0) + lr*30 + LIGHT(x+1,y,z-1,0) + LIGHT(x+1,y+1,z,0)) / 5.0f / 15.0f;
|
||||
float lr2 = (LIGHT(x+1,y+1,z+1,0) + lr*30 + LIGHT(x+1,y,z+1,0) + LIGHT(x+1,y+1,z,0)) / 5.0f / 15.0f;
|
||||
float lr3 = (LIGHT(x+1,y-1,z+1,0) + lr*30 + LIGHT(x+1,y,z+1,0) + LIGHT(x+1,y-1,z,0)) / 5.0f / 15.0f;
|
||||
float lr0 = (LIGHT(x+1,y-1,z-1,0) + lr*30 + LIGHT(x+1,y,z-1,0) + LIGHT(x+1,y-1,z,0)) / 75.0f;
|
||||
float lr1 = (LIGHT(x+1,y+1,z-1,0) + lr*30 + LIGHT(x+1,y,z-1,0) + LIGHT(x+1,y+1,z,0)) / 75.0f;
|
||||
float lr2 = (LIGHT(x+1,y+1,z+1,0) + lr*30 + LIGHT(x+1,y,z+1,0) + LIGHT(x+1,y+1,z,0)) / 75.0f;
|
||||
float lr3 = (LIGHT(x+1,y-1,z+1,0) + lr*30 + LIGHT(x+1,y,z+1,0) + LIGHT(x+1,y-1,z,0)) / 75.0f;
|
||||
|
||||
float lg0 = (LIGHT(x+1,y-1,z-1,1) + lg*30 + LIGHT(x+1,y,z-1,1) + LIGHT(x+1,y-1,z,1)) / 5.0f / 15.0f;
|
||||
float lg1 = (LIGHT(x+1,y+1,z-1,1) + lg*30 + LIGHT(x+1,y,z-1,1) + LIGHT(x+1,y+1,z,1)) / 5.0f / 15.0f;
|
||||
float lg2 = (LIGHT(x+1,y+1,z+1,1) + lg*30 + LIGHT(x+1,y,z+1,1) + LIGHT(x+1,y+1,z,1)) / 5.0f / 15.0f;
|
||||
float lg3 = (LIGHT(x+1,y-1,z+1,1) + lg*30 + LIGHT(x+1,y,z+1,1) + LIGHT(x+1,y-1,z,1)) / 5.0f / 15.0f;
|
||||
float lg0 = (LIGHT(x+1,y-1,z-1,1) + lg*30 + LIGHT(x+1,y,z-1,1) + LIGHT(x+1,y-1,z,1)) / 75.0f;
|
||||
float lg1 = (LIGHT(x+1,y+1,z-1,1) + lg*30 + LIGHT(x+1,y,z-1,1) + LIGHT(x+1,y+1,z,1)) / 75.0f;
|
||||
float lg2 = (LIGHT(x+1,y+1,z+1,1) + lg*30 + LIGHT(x+1,y,z+1,1) + LIGHT(x+1,y+1,z,1)) / 75.0f;
|
||||
float lg3 = (LIGHT(x+1,y-1,z+1,1) + lg*30 + LIGHT(x+1,y,z+1,1) + LIGHT(x+1,y-1,z,1)) / 75.0f;
|
||||
|
||||
float lb0 = (LIGHT(x+1,y-1,z-1,2) + lb*30 + LIGHT(x+1,y,z-1,2) + LIGHT(x+1,y-1,z,2)) / 5.0f / 15.0f;
|
||||
float lb1 = (LIGHT(x+1,y+1,z-1,2) + lb*30 + LIGHT(x+1,y,z-1,2) + LIGHT(x+1,y+1,z,2)) / 5.0f / 15.0f;
|
||||
float lb2 = (LIGHT(x+1,y+1,z+1,2) + lb*30 + LIGHT(x+1,y,z+1,2) + LIGHT(x+1,y+1,z,2)) / 5.0f / 15.0f;
|
||||
float lb3 = (LIGHT(x+1,y-1,z+1,2) + lb*30 + LIGHT(x+1,y,z+1,2) + LIGHT(x+1,y-1,z,2)) / 5.0f / 15.0f;
|
||||
float lb0 = (LIGHT(x+1,y-1,z-1,2) + lb*30 + LIGHT(x+1,y,z-1,2) + LIGHT(x+1,y-1,z,2)) / 75.0f;
|
||||
float lb1 = (LIGHT(x+1,y+1,z-1,2) + lb*30 + LIGHT(x+1,y,z-1,2) + LIGHT(x+1,y+1,z,2)) / 75.0f;
|
||||
float lb2 = (LIGHT(x+1,y+1,z+1,2) + lb*30 + LIGHT(x+1,y,z+1,2) + LIGHT(x+1,y+1,z,2)) / 75.0f;
|
||||
float lb3 = (LIGHT(x+1,y-1,z+1,2) + lb*30 + LIGHT(x+1,y,z+1,2) + LIGHT(x+1,y-1,z,2)) / 75.0f;
|
||||
|
||||
float ls0 = (LIGHT(x+1,y-1,z-1,3) + ls*30 + LIGHT(x+1,y,z-1,3) + LIGHT(x+1,y-1,z,3)) / 5.0f / 15.0f;
|
||||
float ls1 = (LIGHT(x+1,y+1,z-1,3) + ls*30 + LIGHT(x+1,y,z-1,3) + LIGHT(x+1,y+1,z,3)) / 5.0f / 15.0f;
|
||||
float ls2 = (LIGHT(x+1,y+1,z+1,3) + ls*30 + LIGHT(x+1,y,z+1,3) + LIGHT(x+1,y+1,z,3)) / 5.0f / 15.0f;
|
||||
float ls3 = (LIGHT(x+1,y-1,z+1,3) + ls*30 + LIGHT(x+1,y,z+1,3) + LIGHT(x+1,y-1,z,3)) / 5.0f / 15.0f;
|
||||
float ls0 = (LIGHT(x+1,y-1,z-1,3) + ls*30 + LIGHT(x+1,y,z-1,3) + LIGHT(x+1,y-1,z,3)) / 75.0f;
|
||||
float ls1 = (LIGHT(x+1,y+1,z-1,3) + ls*30 + LIGHT(x+1,y,z-1,3) + LIGHT(x+1,y+1,z,3)) / 75.0f;
|
||||
float ls2 = (LIGHT(x+1,y+1,z+1,3) + ls*30 + LIGHT(x+1,y,z+1,3) + LIGHT(x+1,y+1,z,3)) / 75.0f;
|
||||
float ls3 = (LIGHT(x+1,y-1,z+1,3) + ls*30 + LIGHT(x+1,y,z+1,3) + LIGHT(x+1,y-1,z,3)) / 75.0f;
|
||||
|
||||
VERTEX(index, x+0.5f, y-0.5f, z-0.5f, u2,v1, lr0,lg0,lb0,ls0);
|
||||
VERTEX(index, x+0.5f, y+0.5f, z-0.5f, u2,v2, lr1,lg1,lb1,ls1);
|
||||
@ -177,30 +170,30 @@ inline void _renderBlock(float* buffer, int x, int y, int z, const Chunk** chunk
|
||||
|
||||
SETUP_UV(block->textureFaces[0]);
|
||||
|
||||
float lr = LIGHT(x-1,y,z, 0) / 15.0f;
|
||||
float lg = LIGHT(x-1,y,z, 1) / 15.0f;
|
||||
float lb = LIGHT(x-1,y,z, 2) / 15.0f;
|
||||
float ls = LIGHT(x-1,y,z, 3) / 15.0f;
|
||||
const float lr = LIGHT(x-1,y,z, 0) / 15.0f;
|
||||
const float lg = LIGHT(x-1,y,z, 1) / 15.0f;
|
||||
const float lb = LIGHT(x-1,y,z, 2) / 15.0f;
|
||||
const float ls = LIGHT(x-1,y,z, 3) / 15.0f;
|
||||
|
||||
float lr0 = (LIGHT(x-1,y-1,z-1,0) + lr*30 + LIGHT(x-1,y,z-1,0) + LIGHT(x-1,y-1,z,0)) / 5.0f / 15.0f;
|
||||
float lr1 = (LIGHT(x-1,y+1,z+1,0) + lr*30 + LIGHT(x-1,y,z+1,0) + LIGHT(x-1,y+1,z,0)) / 5.0f / 15.0f;
|
||||
float lr2 = (LIGHT(x-1,y+1,z-1,0) + lr*30 + LIGHT(x-1,y,z-1,0) + LIGHT(x-1,y+1,z,0)) / 5.0f / 15.0f;
|
||||
float lr3 = (LIGHT(x-1,y-1,z+1,0) + lr*30 + LIGHT(x-1,y,z+1,0) + LIGHT(x-1,y-1,z,0)) / 5.0f / 15.0f;
|
||||
float lr0 = (LIGHT(x-1,y-1,z-1,0) + lr*30 + LIGHT(x-1,y,z-1,0) + LIGHT(x-1,y-1,z,0)) / 75.0f;
|
||||
float lr1 = (LIGHT(x-1,y+1,z+1,0) + lr*30 + LIGHT(x-1,y,z+1,0) + LIGHT(x-1,y+1,z,0)) / 75.0f;
|
||||
float lr2 = (LIGHT(x-1,y+1,z-1,0) + lr*30 + LIGHT(x-1,y,z-1,0) + LIGHT(x-1,y+1,z,0)) / 75.0f;
|
||||
float lr3 = (LIGHT(x-1,y-1,z+1,0) + lr*30 + LIGHT(x-1,y,z+1,0) + LIGHT(x-1,y-1,z,0)) / 75.0f;
|
||||
|
||||
float lg0 = (LIGHT(x-1,y-1,z-1,1) + lg*30 + LIGHT(x-1,y,z-1,1) + LIGHT(x-1,y-1,z,1)) / 5.0f / 15.0f;
|
||||
float lg1 = (LIGHT(x-1,y+1,z+1,1) + lg*30 + LIGHT(x-1,y,z+1,1) + LIGHT(x-1,y+1,z,1)) / 5.0f / 15.0f;
|
||||
float lg2 = (LIGHT(x-1,y+1,z-1,1) + lg*30 + LIGHT(x-1,y,z-1,1) + LIGHT(x-1,y+1,z,1)) / 5.0f / 15.0f;
|
||||
float lg3 = (LIGHT(x-1,y-1,z+1,1) + lg*30 + LIGHT(x-1,y,z+1,1) + LIGHT(x-1,y-1,z,1)) / 5.0f / 15.0f;
|
||||
float lg0 = (LIGHT(x-1,y-1,z-1,1) + lg*30 + LIGHT(x-1,y,z-1,1) + LIGHT(x-1,y-1,z,1)) / 75.0f;
|
||||
float lg1 = (LIGHT(x-1,y+1,z+1,1) + lg*30 + LIGHT(x-1,y,z+1,1) + LIGHT(x-1,y+1,z,1)) / 75.0f;
|
||||
float lg2 = (LIGHT(x-1,y+1,z-1,1) + lg*30 + LIGHT(x-1,y,z-1,1) + LIGHT(x-1,y+1,z,1)) / 75.0f;
|
||||
float lg3 = (LIGHT(x-1,y-1,z+1,1) + lg*30 + LIGHT(x-1,y,z+1,1) + LIGHT(x-1,y-1,z,1)) / 75.0f;
|
||||
|
||||
float lb0 = (LIGHT(x-1,y-1,z-1,2) + lb*30 + LIGHT(x-1,y,z-1,2) + LIGHT(x-1,y-1,z,2)) / 5.0f / 15.0f;
|
||||
float lb1 = (LIGHT(x-1,y+1,z+1,2) + lb*30 + LIGHT(x-1,y,z+1,2) + LIGHT(x-1,y+1,z,2)) / 5.0f / 15.0f;
|
||||
float lb2 = (LIGHT(x-1,y+1,z-1,2) + lb*30 + LIGHT(x-1,y,z-1,2) + LIGHT(x-1,y+1,z,2)) / 5.0f / 15.0f;
|
||||
float lb3 = (LIGHT(x-1,y-1,z+1,2) + lb*30 + LIGHT(x-1,y,z+1,2) + LIGHT(x-1,y-1,z,2)) / 5.0f / 15.0f;
|
||||
float lb0 = (LIGHT(x-1,y-1,z-1,2) + lb*30 + LIGHT(x-1,y,z-1,2) + LIGHT(x-1,y-1,z,2)) / 75.0f;
|
||||
float lb1 = (LIGHT(x-1,y+1,z+1,2) + lb*30 + LIGHT(x-1,y,z+1,2) + LIGHT(x-1,y+1,z,2)) / 75.0f;
|
||||
float lb2 = (LIGHT(x-1,y+1,z-1,2) + lb*30 + LIGHT(x-1,y,z-1,2) + LIGHT(x-1,y+1,z,2)) / 75.0f;
|
||||
float lb3 = (LIGHT(x-1,y-1,z+1,2) + lb*30 + LIGHT(x-1,y,z+1,2) + LIGHT(x-1,y-1,z,2)) / 75.0f;
|
||||
|
||||
float ls0 = (LIGHT(x-1,y-1,z-1,3) + ls*30 + LIGHT(x-1,y,z-1,3) + LIGHT(x-1,y-1,z,3)) / 5.0f / 15.0f;
|
||||
float ls1 = (LIGHT(x-1,y+1,z+1,3) + ls*30 + LIGHT(x-1,y,z+1,3) + LIGHT(x-1,y+1,z,3)) / 5.0f / 15.0f;
|
||||
float ls2 = (LIGHT(x-1,y+1,z-1,3) + ls*30 + LIGHT(x-1,y,z-1,3) + LIGHT(x-1,y+1,z,3)) / 5.0f / 15.0f;
|
||||
float ls3 = (LIGHT(x-1,y-1,z+1,3) + ls*30 + LIGHT(x-1,y,z+1,3) + LIGHT(x-1,y-1,z,3)) / 5.0f / 15.0f;
|
||||
float ls0 = (LIGHT(x-1,y-1,z-1,3) + ls*30 + LIGHT(x-1,y,z-1,3) + LIGHT(x-1,y-1,z,3)) / 75.0f;
|
||||
float ls1 = (LIGHT(x-1,y+1,z+1,3) + ls*30 + LIGHT(x-1,y,z+1,3) + LIGHT(x-1,y+1,z,3)) / 75.0f;
|
||||
float ls2 = (LIGHT(x-1,y+1,z-1,3) + ls*30 + LIGHT(x-1,y,z-1,3) + LIGHT(x-1,y+1,z,3)) / 75.0f;
|
||||
float ls3 = (LIGHT(x-1,y-1,z+1,3) + ls*30 + LIGHT(x-1,y,z+1,3) + LIGHT(x-1,y-1,z,3)) / 75.0f;
|
||||
|
||||
VERTEX(index, x-0.5f, y-0.5f, z-0.5f, u1,v1, lr0,lg0,lb0,ls0);
|
||||
VERTEX(index, x-0.5f, y+0.5f, z+0.5f, u2,v2, lr1,lg1,lb1,ls1);
|
||||
@ -216,30 +209,30 @@ inline void _renderBlock(float* buffer, int x, int y, int z, const Chunk** chunk
|
||||
|
||||
SETUP_UV(block->textureFaces[5]);
|
||||
|
||||
float lr = LIGHT(x,y,z+1, 0) / 15.0f;
|
||||
float lg = LIGHT(x,y,z+1, 1) / 15.0f;
|
||||
float lb = LIGHT(x,y,z+1, 2) / 15.0f;
|
||||
float ls = LIGHT(x,y,z+1, 3) / 15.0f;
|
||||
const float lr = LIGHT(x,y,z+1, 0) / 15.0f;
|
||||
const float lg = LIGHT(x,y,z+1, 1) / 15.0f;
|
||||
const float lb = LIGHT(x,y,z+1, 2) / 15.0f;
|
||||
const float ls = LIGHT(x,y,z+1, 3) / 15.0f;
|
||||
|
||||
float lr0 = l*(LIGHT(x-1,y-1,z+1,0) + lr*30 + LIGHT(x,y-1,z+1,0) + LIGHT(x-1,y,z+1,0)) / 5.0f / 15.0f;
|
||||
float lr1 = l*(LIGHT(x+1,y+1,z+1,0) + lr*30 + LIGHT(x,y+1,z+1,0) + LIGHT(x+1,y,z+1,0)) / 5.0f / 15.0f;
|
||||
float lr2 = l*(LIGHT(x-1,y+1,z+1,0) + lr*30 + LIGHT(x,y+1,z+1,0) + LIGHT(x-1,y,z+1,0)) / 5.0f / 15.0f;
|
||||
float lr3 = l*(LIGHT(x+1,y-1,z+1,0) + lr*30 + LIGHT(x,y-1,z+1,0) + LIGHT(x+1,y,z+1,0)) / 5.0f / 15.0f;
|
||||
float lr0 = l*(LIGHT(x-1,y-1,z+1,0) + lr*30 + LIGHT(x,y-1,z+1,0) + LIGHT(x-1,y,z+1,0)) / 75.0f;
|
||||
float lr1 = l*(LIGHT(x+1,y+1,z+1,0) + lr*30 + LIGHT(x,y+1,z+1,0) + LIGHT(x+1,y,z+1,0)) / 75.0f;
|
||||
float lr2 = l*(LIGHT(x-1,y+1,z+1,0) + lr*30 + LIGHT(x,y+1,z+1,0) + LIGHT(x-1,y,z+1,0)) / 75.0f;
|
||||
float lr3 = l*(LIGHT(x+1,y-1,z+1,0) + lr*30 + LIGHT(x,y-1,z+1,0) + LIGHT(x+1,y,z+1,0)) / 75.0f;
|
||||
|
||||
float lg0 = l*(LIGHT(x-1,y-1,z+1,1) + lg*30 + LIGHT(x,y-1,z+1,1) + LIGHT(x-1,y,z+1,1)) / 5.0f / 15.0f;
|
||||
float lg1 = l*(LIGHT(x+1,y+1,z+1,1) + lg*30 + LIGHT(x,y+1,z+1,1) + LIGHT(x+1,y,z+1,1)) / 5.0f / 15.0f;
|
||||
float lg2 = l*(LIGHT(x-1,y+1,z+1,1) + lg*30 + LIGHT(x,y+1,z+1,1) + LIGHT(x-1,y,z+1,1)) / 5.0f / 15.0f;
|
||||
float lg3 = l*(LIGHT(x+1,y-1,z+1,1) + lg*30 + LIGHT(x,y-1,z+1,1) + LIGHT(x+1,y,z+1,1)) / 5.0f / 15.0f;
|
||||
float lg0 = l*(LIGHT(x-1,y-1,z+1,1) + lg*30 + LIGHT(x,y-1,z+1,1) + LIGHT(x-1,y,z+1,1)) / 75.0f;
|
||||
float lg1 = l*(LIGHT(x+1,y+1,z+1,1) + lg*30 + LIGHT(x,y+1,z+1,1) + LIGHT(x+1,y,z+1,1)) / 75.0f;
|
||||
float lg2 = l*(LIGHT(x-1,y+1,z+1,1) + lg*30 + LIGHT(x,y+1,z+1,1) + LIGHT(x-1,y,z+1,1)) / 75.0f;
|
||||
float lg3 = l*(LIGHT(x+1,y-1,z+1,1) + lg*30 + LIGHT(x,y-1,z+1,1) + LIGHT(x+1,y,z+1,1)) / 75.0f;
|
||||
|
||||
float lb0 = l*(LIGHT(x-1,y-1,z+1,2) + lb*30 + LIGHT(x,y-1,z+1,2) + LIGHT(x-1,y,z+1,2)) / 5.0f / 15.0f;
|
||||
float lb1 = l*(LIGHT(x+1,y+1,z+1,2) + lb*30 + LIGHT(x,y+1,z+1,2) + LIGHT(x+1,y,z+1,2)) / 5.0f / 15.0f;
|
||||
float lb2 = l*(LIGHT(x-1,y+1,z+1,2) + lb*30 + LIGHT(x,y+1,z+1,2) + LIGHT(x-1,y,z+1,2)) / 5.0f / 15.0f;
|
||||
float lb3 = l*(LIGHT(x+1,y-1,z+1,2) + lb*30 + LIGHT(x,y-1,z+1,2) + LIGHT(x+1,y,z+1,2)) / 5.0f / 15.0f;
|
||||
float lb0 = l*(LIGHT(x-1,y-1,z+1,2) + lb*30 + LIGHT(x,y-1,z+1,2) + LIGHT(x-1,y,z+1,2)) / 75.0f;
|
||||
float lb1 = l*(LIGHT(x+1,y+1,z+1,2) + lb*30 + LIGHT(x,y+1,z+1,2) + LIGHT(x+1,y,z+1,2)) / 75.0f;
|
||||
float lb2 = l*(LIGHT(x-1,y+1,z+1,2) + lb*30 + LIGHT(x,y+1,z+1,2) + LIGHT(x-1,y,z+1,2)) / 75.0f;
|
||||
float lb3 = l*(LIGHT(x+1,y-1,z+1,2) + lb*30 + LIGHT(x,y-1,z+1,2) + LIGHT(x+1,y,z+1,2)) / 75.0f;
|
||||
|
||||
float ls0 = l*(LIGHT(x-1,y-1,z+1,3) + ls*30 + LIGHT(x,y-1,z+1,3) + LIGHT(x-1,y,z+1,3)) / 5.0f / 15.0f;
|
||||
float ls1 = l*(LIGHT(x+1,y+1,z+1,3) + ls*30 + LIGHT(x,y+1,z+1,3) + LIGHT(x+1,y,z+1,3)) / 5.0f / 15.0f;
|
||||
float ls2 = l*(LIGHT(x-1,y+1,z+1,3) + ls*30 + LIGHT(x,y+1,z+1,3) + LIGHT(x-1,y,z+1,3)) / 5.0f / 15.0f;
|
||||
float ls3 = l*(LIGHT(x+1,y-1,z+1,3) + ls*30 + LIGHT(x,y-1,z+1,3) + LIGHT(x+1,y,z+1,3)) / 5.0f / 15.0f;
|
||||
float ls0 = l*(LIGHT(x-1,y-1,z+1,3) + ls*30 + LIGHT(x,y-1,z+1,3) + LIGHT(x-1,y,z+1,3)) / 75.0f;
|
||||
float ls1 = l*(LIGHT(x+1,y+1,z+1,3) + ls*30 + LIGHT(x,y+1,z+1,3) + LIGHT(x+1,y,z+1,3)) / 75.0f;
|
||||
float ls2 = l*(LIGHT(x-1,y+1,z+1,3) + ls*30 + LIGHT(x,y+1,z+1,3) + LIGHT(x-1,y,z+1,3)) / 75.0f;
|
||||
float ls3 = l*(LIGHT(x+1,y-1,z+1,3) + ls*30 + LIGHT(x,y-1,z+1,3) + LIGHT(x+1,y,z+1,3)) / 75.0f;
|
||||
|
||||
VERTEX(index, x-0.5f, y-0.5f, z+0.5f, u1,v1, lr0,lg0,lb0,ls0);
|
||||
VERTEX(index, x+0.5f, y+0.5f, z+0.5f, u2,v2, lr1,lg1,lb1,ls1);
|
||||
@ -254,30 +247,30 @@ inline void _renderBlock(float* buffer, int x, int y, int z, const Chunk** chunk
|
||||
|
||||
SETUP_UV(block->textureFaces[4]);
|
||||
|
||||
float lr = LIGHT(x,y,z-1, 0) / 15.0f;
|
||||
float lg = LIGHT(x,y,z-1, 1) / 15.0f;
|
||||
float lb = LIGHT(x,y,z-1, 2) / 15.0f;
|
||||
float ls = LIGHT(x,y,z-1, 3) / 15.0f;
|
||||
const float lr = LIGHT(x,y,z-1, 0) / 15.0f;
|
||||
const float lg = LIGHT(x,y,z-1, 1) / 15.0f;
|
||||
const float lb = LIGHT(x,y,z-1, 2) / 15.0f;
|
||||
const float ls = LIGHT(x,y,z-1, 3) / 15.0f;
|
||||
|
||||
float lr0 = l*(LIGHT(x-1,y-1,z-1,0) + lr*30 + LIGHT(x,y-1,z-1,0) + LIGHT(x-1,y,z-1,0)) / 5.0f / 15.0f;
|
||||
float lr1 = l*(LIGHT(x-1,y+1,z-1,0) + lr*30 + LIGHT(x,y+1,z-1,0) + LIGHT(x-1,y,z-1,0)) / 5.0f / 15.0f;
|
||||
float lr2 = l*(LIGHT(x+1,y+1,z-1,0) + lr*30 + LIGHT(x,y+1,z-1,0) + LIGHT(x+1,y,z-1,0)) / 5.0f / 15.0f;
|
||||
float lr3 = l*(LIGHT(x+1,y-1,z-1,0) + lr*30 + LIGHT(x,y-1,z-1,0) + LIGHT(x+1,y,z-1,0)) / 5.0f / 15.0f;
|
||||
float lr0 = l*(LIGHT(x-1,y-1,z-1,0) + lr*30 + LIGHT(x,y-1,z-1,0) + LIGHT(x-1,y,z-1,0)) / 75.0f;
|
||||
float lr1 = l*(LIGHT(x-1,y+1,z-1,0) + lr*30 + LIGHT(x,y+1,z-1,0) + LIGHT(x-1,y,z-1,0)) / 75.0f;
|
||||
float lr2 = l*(LIGHT(x+1,y+1,z-1,0) + lr*30 + LIGHT(x,y+1,z-1,0) + LIGHT(x+1,y,z-1,0)) / 75.0f;
|
||||
float lr3 = l*(LIGHT(x+1,y-1,z-1,0) + lr*30 + LIGHT(x,y-1,z-1,0) + LIGHT(x+1,y,z-1,0)) / 75.0f;
|
||||
|
||||
float lg0 = l*(LIGHT(x-1,y-1,z-1,1) + lg*30 + LIGHT(x,y-1,z-1,1) + LIGHT(x-1,y,z-1,1)) / 5.0f / 15.0f;
|
||||
float lg1 = l*(LIGHT(x-1,y+1,z-1,1) + lg*30 + LIGHT(x,y+1,z-1,1) + LIGHT(x-1,y,z-1,1)) / 5.0f / 15.0f;
|
||||
float lg2 = l*(LIGHT(x+1,y+1,z-1,1) + lg*30 + LIGHT(x,y+1,z-1,1) + LIGHT(x+1,y,z-1,1)) / 5.0f / 15.0f;
|
||||
float lg3 = l*(LIGHT(x+1,y-1,z-1,1) + lg*30 + LIGHT(x,y-1,z-1,1) + LIGHT(x+1,y,z-1,1)) / 5.0f / 15.0f;
|
||||
float lg0 = l*(LIGHT(x-1,y-1,z-1,1) + lg*30 + LIGHT(x,y-1,z-1,1) + LIGHT(x-1,y,z-1,1)) / 75.0f;
|
||||
float lg1 = l*(LIGHT(x-1,y+1,z-1,1) + lg*30 + LIGHT(x,y+1,z-1,1) + LIGHT(x-1,y,z-1,1)) / 75.0f;
|
||||
float lg2 = l*(LIGHT(x+1,y+1,z-1,1) + lg*30 + LIGHT(x,y+1,z-1,1) + LIGHT(x+1,y,z-1,1)) / 75.0f;
|
||||
float lg3 = l*(LIGHT(x+1,y-1,z-1,1) + lg*30 + LIGHT(x,y-1,z-1,1) + LIGHT(x+1,y,z-1,1)) / 75.0f;
|
||||
|
||||
float lb0 = l*(LIGHT(x-1,y-1,z-1,2) + lb*30 + LIGHT(x,y-1,z-1,2) + LIGHT(x-1,y,z-1,2)) / 5.0f / 15.0f;
|
||||
float lb1 = l*(LIGHT(x-1,y+1,z-1,2) + lb*30 + LIGHT(x,y+1,z-1,2) + LIGHT(x-1,y,z-1,2)) / 5.0f / 15.0f;
|
||||
float lb2 = l*(LIGHT(x+1,y+1,z-1,2) + lb*30 + LIGHT(x,y+1,z-1,2) + LIGHT(x+1,y,z-1,2)) / 5.0f / 15.0f;
|
||||
float lb3 = l*(LIGHT(x+1,y-1,z-1,2) + lb*30 + LIGHT(x,y-1,z-1,2) + LIGHT(x+1,y,z-1,2)) / 5.0f / 15.0f;
|
||||
float lb0 = l*(LIGHT(x-1,y-1,z-1,2) + lb*30 + LIGHT(x,y-1,z-1,2) + LIGHT(x-1,y,z-1,2)) / 75.0f;
|
||||
float lb1 = l*(LIGHT(x-1,y+1,z-1,2) + lb*30 + LIGHT(x,y+1,z-1,2) + LIGHT(x-1,y,z-1,2)) / 75.0f;
|
||||
float lb2 = l*(LIGHT(x+1,y+1,z-1,2) + lb*30 + LIGHT(x,y+1,z-1,2) + LIGHT(x+1,y,z-1,2)) / 75.0f;
|
||||
float lb3 = l*(LIGHT(x+1,y-1,z-1,2) + lb*30 + LIGHT(x,y-1,z-1,2) + LIGHT(x+1,y,z-1,2)) / 75.0f;
|
||||
|
||||
float ls0 = l*(LIGHT(x-1,y-1,z-1,3) + ls*30 + LIGHT(x,y-1,z-1,3) + LIGHT(x-1,y,z-1,3)) / 5.0f / 15.0f;
|
||||
float ls1 = l*(LIGHT(x-1,y+1,z-1,3) + ls*30 + LIGHT(x,y+1,z-1,3) + LIGHT(x-1,y,z-1,3)) / 5.0f / 15.0f;
|
||||
float ls2 = l*(LIGHT(x+1,y+1,z-1,3) + ls*30 + LIGHT(x,y+1,z-1,3) + LIGHT(x+1,y,z-1,3)) / 5.0f / 15.0f;
|
||||
float ls3 = l*(LIGHT(x+1,y-1,z-1,3) + ls*30 + LIGHT(x,y-1,z-1,3) + LIGHT(x+1,y,z-1,3)) / 5.0f / 15.0f;
|
||||
float ls0 = l*(LIGHT(x-1,y-1,z-1,3) + ls*30 + LIGHT(x,y-1,z-1,3) + LIGHT(x-1,y,z-1,3)) / 75.0f;
|
||||
float ls1 = l*(LIGHT(x-1,y+1,z-1,3) + ls*30 + LIGHT(x,y+1,z-1,3) + LIGHT(x-1,y,z-1,3)) / 75.0f;
|
||||
float ls2 = l*(LIGHT(x+1,y+1,z-1,3) + ls*30 + LIGHT(x,y+1,z-1,3) + LIGHT(x+1,y,z-1,3)) / 75.0f;
|
||||
float ls3 = l*(LIGHT(x+1,y-1,z-1,3) + ls*30 + LIGHT(x,y-1,z-1,3) + LIGHT(x+1,y,z-1,3)) / 75.0f;
|
||||
|
||||
VERTEX(index, x-0.5f, y-0.5f, z-0.5f, u2,v1, lr0,lg0,lb0,ls0);
|
||||
VERTEX(index, x-0.5f, y+0.5f, z-0.5f, u2,v2, lr1,lg1,lb1,ls1);
|
||||
@ -289,15 +282,196 @@ inline void _renderBlock(float* buffer, int x, int y, int z, const Chunk** chunk
|
||||
}
|
||||
}
|
||||
|
||||
Mesh* VoxelRenderer::render(Chunk* chunk, const Chunk** chunks){
|
||||
inline void _renderBlockShadeless(std::vector<float>& buffer, int x, int y, int z, const Chunk** chunks, unsigned int id, size_t& index){
|
||||
float l;
|
||||
float uvsize = 1.0f/16.0f;
|
||||
|
||||
Block* block = Block::blocks[id];
|
||||
unsigned char group = block->drawGroup;
|
||||
|
||||
if (!IS_BLOCKED(x,y+1,z,group)){
|
||||
SETUP_UV(block->textureFaces[3]);
|
||||
|
||||
VERTEX(index, x-0.5f, y+0.5f, z-0.5f, u2,v1, 1,1,1,0);
|
||||
VERTEX(index, x-0.5f, y+0.5f, z+0.5f, u2,v2, 1,1,1,0);
|
||||
VERTEX(index, x+0.5f, y+0.5f, z+0.5f, u1,v2, 1,1,1,0);
|
||||
|
||||
VERTEX(index, x-0.5f, y+0.5f, z-0.5f, u2,v1, 1,1,1,0);
|
||||
VERTEX(index, x+0.5f, y+0.5f, z+0.5f, u1,v2, 1,1,1,0);
|
||||
VERTEX(index, x+0.5f, y+0.5f, z-0.5f, u1,v1, 1,1,1,0);
|
||||
}
|
||||
if (!IS_BLOCKED(x,y-1,z,group)){
|
||||
SETUP_UV(block->textureFaces[2]);
|
||||
|
||||
VERTEX(index, x-0.5f, y-0.5f, z-0.5f, u1,v1, 1,1,1,0);
|
||||
VERTEX(index, x+0.5f, y-0.5f, z+0.5f, u2,v2, 1,1,1,0);
|
||||
VERTEX(index, x-0.5f, y-0.5f, z+0.5f, u1,v2, 1,1,1,0);
|
||||
|
||||
VERTEX(index, x-0.5f, y-0.5f, z-0.5f, u1,v1, 1,1,1,0);
|
||||
VERTEX(index, x+0.5f, y-0.5f, z-0.5f, u2,v1, 1,1,1,0);
|
||||
VERTEX(index, x+0.5f, y-0.5f, z+0.5f, u2,v2, 1,1,1,0);
|
||||
}
|
||||
|
||||
if (!IS_BLOCKED(x+1,y,z,group)){
|
||||
SETUP_UV(block->textureFaces[1]);
|
||||
|
||||
VERTEX(index, x+0.5f, y-0.5f, z-0.5f, u2,v1, 1,1,1,0);
|
||||
VERTEX(index, x+0.5f, y+0.5f, z-0.5f, u2,v2, 1,1,1,0);
|
||||
VERTEX(index, x+0.5f, y+0.5f, z+0.5f, u1,v2, 1,1,1,0);
|
||||
|
||||
VERTEX(index, x+0.5f, y-0.5f, z-0.5f, u2,v1, 1,1,1,0);
|
||||
VERTEX(index, x+0.5f, y+0.5f, z+0.5f, u1,v2, 1,1,1,0);
|
||||
VERTEX(index, x+0.5f, y-0.5f, z+0.5f, u1,v1, 1,1,1,0);
|
||||
}
|
||||
if (!IS_BLOCKED(x-1,y,z,group)){
|
||||
SETUP_UV(block->textureFaces[0]);
|
||||
|
||||
VERTEX(index, x-0.5f, y-0.5f, z-0.5f, u1,v1, 1,1,1,0);
|
||||
VERTEX(index, x-0.5f, y+0.5f, z+0.5f, u2,v2, 1,1,1,0);
|
||||
VERTEX(index, x-0.5f, y+0.5f, z-0.5f, u1,v2, 1,1,1,0);
|
||||
|
||||
VERTEX(index, x-0.5f, y-0.5f, z-0.5f, u1,v1, 1,1,1,0);
|
||||
VERTEX(index, x-0.5f, y-0.5f, z+0.5f, u2,v1, 1,1,1,0);
|
||||
VERTEX(index, x-0.5f, y+0.5f, z+0.5f, u2,v2, 1,1,1,0);
|
||||
}
|
||||
|
||||
if (!IS_BLOCKED(x,y,z+1,group)){
|
||||
SETUP_UV(block->textureFaces[5]);
|
||||
|
||||
VERTEX(index, x-0.5f, y-0.5f, z+0.5f, u1,v1, 1,1,1,0);
|
||||
VERTEX(index, x+0.5f, y+0.5f, z+0.5f, u2,v2, 1,1,1,0);
|
||||
VERTEX(index, x-0.5f, y+0.5f, z+0.5f, u1,v2, 1,1,1,0);
|
||||
|
||||
VERTEX(index, x-0.5f, y-0.5f, z+0.5f, u1,v1, 1,1,1,0);
|
||||
VERTEX(index, x+0.5f, y-0.5f, z+0.5f, u2,v1, 1,1,1,0);
|
||||
VERTEX(index, x+0.5f, y+0.5f, z+0.5f, u2,v2, 1,1,1,0);
|
||||
}
|
||||
if (!IS_BLOCKED(x,y,z-1,group)){
|
||||
SETUP_UV(block->textureFaces[4]);
|
||||
|
||||
VERTEX(index, x-0.5f, y-0.5f, z-0.5f, u2,v1, 1,1,1,0);
|
||||
VERTEX(index, x-0.5f, y+0.5f, z-0.5f, u2,v2, 1,1,1,0);
|
||||
VERTEX(index, x+0.5f, y+0.5f, z-0.5f, u1,v2, 1,1,1,0);
|
||||
|
||||
VERTEX(index, x-0.5f, y-0.5f, z-0.5f, u2,v1, 1,1,1,0);
|
||||
VERTEX(index, x+0.5f, y+0.5f, z-0.5f, u1,v2, 1,1,1,0);
|
||||
VERTEX(index, x+0.5f, y-0.5f, z-0.5f, u1,v1, 1,1,1,0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inline void _renderXBlock(std::vector<float>& buffer, int x, int y, int z, const Chunk** chunks, voxel vox, size_t& index){
|
||||
Block* block = Block::blocks[vox.id];
|
||||
|
||||
int rand = ((x * z + y) xor (z * y - x)) * (z + y);
|
||||
|
||||
float xs = (float)(char)rand / 512;
|
||||
float zs = (float)(char)(rand >> 8) / 512;
|
||||
|
||||
if (block->model != 2){
|
||||
return;
|
||||
}
|
||||
|
||||
float uvsize = 1.0f/16.0f;
|
||||
|
||||
float lr = LIGHT(x,y,z, 0) / 15.0f;
|
||||
float lg = LIGHT(x,y,z, 1) / 15.0f;
|
||||
float lb = LIGHT(x,y,z, 2) / 15.0f;
|
||||
float ls = LIGHT(x,y,z, 3) / 15.0f;
|
||||
|
||||
float lr0 = (LIGHT(x,y-1,z,0) + lr*30) / 45.0f;
|
||||
float lr1 = (LIGHT(x,y+1,z,0) + lr*30) / 45.0f;
|
||||
float lr2 = (LIGHT(x,y+1,z,0) + lr*30) / 45.0f;
|
||||
float lr3 = (LIGHT(x,y-1,z,0) + lr*30) / 45.0f;
|
||||
float lr4 = (LIGHT(x,y-1,z,0) + lr*30) / 45.0f;
|
||||
float lr5 = (LIGHT(x,y+1,z,0) + lr*30) / 45.0f;
|
||||
float lr6 = (LIGHT(x,y+1,z,0) + lr*30) / 45.0f;
|
||||
float lr7 = (LIGHT(x,y-1,z,0) + lr*30) / 45.0f;
|
||||
|
||||
float lg0 = (LIGHT(x,y-1,z,1) + lg*30) / 45.0f;
|
||||
float lg1 = (LIGHT(x,y+1,z,1) + lg*30) / 45.0f;
|
||||
float lg2 = (LIGHT(x,y+1,z,1) + lg*30) / 45.0f;
|
||||
float lg3 = (LIGHT(x,y-1,z,1) + lg*30) / 45.0f;
|
||||
float lg4 = (LIGHT(x,y-1,z,1) + lg*30) / 45.0f;
|
||||
float lg5 = (LIGHT(x,y+1,z,1) + lg*30) / 45.0f;
|
||||
float lg6 = (LIGHT(x,y+1,z,1) + lg*30) / 45.0f;
|
||||
float lg7 = (LIGHT(x,y-1,z,1) + lg*30) / 45.0f;
|
||||
|
||||
float lb0 = (LIGHT(x,y-1,z,2) + lb*30) / 45.0f;
|
||||
float lb1 = (LIGHT(x,y+1,z,2) + lb*30) / 45.0f;
|
||||
float lb2 = (LIGHT(x,y+1,z,2) + lb*30) / 45.0f;
|
||||
float lb3 = (LIGHT(x,y-1,z,2) + lb*30) / 45.0f;
|
||||
float lb4 = (LIGHT(x,y-1,z,2) + lb*30) / 45.0f;
|
||||
float lb5 = (LIGHT(x,y+1,z,2) + lb*30) / 45.0f;
|
||||
float lb6 = (LIGHT(x,y+1,z,2) + lb*30) / 45.0f;
|
||||
float lb7 = (LIGHT(x,y-1,z,2) + lb*30) / 45.0f;
|
||||
|
||||
float ls0 = (LIGHT(x,y-1,z,3) + ls*30) / 45.0f;
|
||||
float ls1 = (LIGHT(x,y+1,z,3) + ls*30) / 45.0f;
|
||||
float ls2 = (LIGHT(x,y+1,z,3) + ls*30) / 45.0f;
|
||||
float ls3 = (LIGHT(x,y-1,z,3) + ls*30) / 45.0f;
|
||||
float ls4 = (LIGHT(x,y-1,z,3) + ls*30) / 45.0f;
|
||||
float ls5 = (LIGHT(x,y+1,z,3) + ls*30) / 45.0f;
|
||||
float ls6 = (LIGHT(x,y+1,z,3) + ls*30) / 45.0f;
|
||||
float ls7 = (LIGHT(x,y-1,z,3) + ls*30) / 45.0f;
|
||||
|
||||
{SETUP_UV(block->textureFaces[1]);
|
||||
|
||||
VERTEX(index, x-0.5f+xs, y-0.5f, z-0.5f+zs, u2,v1, lr0,lg0,lb0,ls0);
|
||||
VERTEX(index, x-0.5f+xs, y+0.5f, z-0.5f+zs, u2,v2, lr1,lg1,lb1,ls1);
|
||||
VERTEX(index, x+0.5f+xs, y+0.5f, z+0.5f+zs, u1,v2, lr2,lg2,lb2,ls2);
|
||||
|
||||
VERTEX(index, x-0.5f+xs, y-0.5f, z-0.5f+zs, u2,v1, lr0,lg0,lb0,ls0);
|
||||
VERTEX(index, x+0.5f+xs, y+0.5f, z+0.5f+zs, u1,v2, lr2,lg2,lb2,ls2);
|
||||
VERTEX(index, x+0.5f+xs, y-0.5f, z+0.5f+zs, u1,v1, lr3,lg3,lb3,ls3);}
|
||||
|
||||
{SETUP_UV(block->textureFaces[0]);
|
||||
|
||||
VERTEX(index, x-0.5f+xs, y-0.5f, z-0.5f+zs, u1,v1, lr0,lg0,lb0,ls0);
|
||||
VERTEX(index, x+0.5f+xs, y+0.5f, z+0.5f+zs, u2,v2, lr1,lg1,lb1,ls1);
|
||||
VERTEX(index, x-0.5f+xs, y+0.5f, z-0.5f+zs, u1,v2, lr2,lg2,lb2,ls2);
|
||||
|
||||
VERTEX(index, x-0.5f+xs, y-0.5f, z-0.5f+zs, u1,v1, lr0,lg0,lb0,ls0);
|
||||
VERTEX(index, x+0.5f+xs, y-0.5f, z+0.5f+zs, u2,v1, lr3,lg3,lb3,ls3);
|
||||
VERTEX(index, x+0.5f+xs, y+0.5f, z+0.5f+zs, u2,v2, lr1,lg1,lb1,ls1);}
|
||||
|
||||
{SETUP_UV(block->textureFaces[5]);
|
||||
|
||||
VERTEX(index, x-0.5f+xs, y-0.5f, z+0.5f+zs, u1,v1, lr4,lg4,lb4,ls4);
|
||||
VERTEX(index, x+0.5f+xs, y+0.5f, z-0.5f+zs, u2,v2, lr5,lg5,lb5,ls5);
|
||||
VERTEX(index, x-0.5f+xs, y+0.5f, z+0.5f+zs, u1,v2, lr6,lg6,lb6,ls6);
|
||||
|
||||
VERTEX(index, x-0.5f+xs, y-0.5f, z+0.5f+zs, u1,v1, lr4,lg4,lb4,ls4);
|
||||
VERTEX(index, x+0.5f+xs, y-0.5f, z-0.5f+zs, u2,v1, lr7,lg7,lb7,ls7);
|
||||
VERTEX(index, x+0.5f+xs, y+0.5f, z-0.5f+zs, u2,v2, lr5,lg5,lb5,ls5);}
|
||||
|
||||
{SETUP_UV(block->textureFaces[4]);
|
||||
|
||||
VERTEX(index, x-0.5f+xs, y-0.5f, z+0.5f+zs, u2,v1, lr4,lg4,lb4,ls4);
|
||||
VERTEX(index, x-0.5f+xs, y+0.5f, z+0.5f+zs, u2,v2, lr5,lg5,lb5,ls5);
|
||||
VERTEX(index, x+0.5f+xs, y+0.5f, z-0.5f+zs, u1,v2, lr6,lg6,lb6,ls6);
|
||||
|
||||
VERTEX(index, x-0.5f+xs, y-0.5f, z+0.5f+zs, u2,v1, lr4,lg4,lb4,ls4);
|
||||
VERTEX(index, x+0.5f+xs, y+0.5f, z-0.5f+zs, u1,v2, lr6,lg6,lb6,ls6);
|
||||
VERTEX(index, x+0.5f+xs, y-0.5f, z-0.5f+zs, u1,v1, lr7,lg7,lb7,ls7);}
|
||||
}
|
||||
|
||||
const float* VoxelRenderer::render(Chunk* chunk, const Chunk** chunks, size_t& size){
|
||||
buffer.clear();
|
||||
size_t index = 0;
|
||||
for (int y = 0; y < CHUNK_H; y++){
|
||||
for (int z = 0; z < CHUNK_D; z++){
|
||||
for (int x = 0; x < CHUNK_W; x++){
|
||||
voxel vox = chunk->voxels[(y * CHUNK_D + z) * CHUNK_W + x];
|
||||
if (vox.id == 9 || vox.id == 4)
|
||||
if (vox.id == 0)
|
||||
continue;
|
||||
_renderBlock(buffer, x, y, z, chunks, vox, index);
|
||||
if (vox.id == 9 || vox.id == 4 || vox.id == 12 || vox.id == 13)
|
||||
continue;
|
||||
Block* block = Block::blocks[vox.id];
|
||||
if (block->emission[0] || block->emission[1] || block->emission[2]){
|
||||
continue;
|
||||
}
|
||||
_renderBlock(buffer, x, y, z, chunks, vox.id, index);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -306,9 +480,25 @@ Mesh* VoxelRenderer::render(Chunk* chunk, const Chunk** chunks){
|
||||
for (int z = 0; z < CHUNK_D; z++){
|
||||
for (int x = 0; x < CHUNK_W; x++){
|
||||
voxel vox = chunk->voxels[(y * CHUNK_D + z) * CHUNK_W + x];
|
||||
if (vox.id == 0)
|
||||
continue;
|
||||
Block* block = Block::blocks[vox.id];
|
||||
if (block->emission[0] || block->emission[1] || block->emission[2]){
|
||||
_renderBlockShadeless(buffer, x, y, z, chunks, vox.id, index);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int y = 0; y < CHUNK_H; y++){
|
||||
for (int z = 0; z < CHUNK_D; z++){
|
||||
for (int x = 0; x < CHUNK_W; x++){
|
||||
voxel vox = chunk->voxels[(y * CHUNK_D + z) * CHUNK_W + x];
|
||||
if (vox.id == 0)
|
||||
continue;
|
||||
if (vox.id != 9)
|
||||
continue;
|
||||
_renderBlock(buffer, x, y, z, chunks, vox, index);
|
||||
_renderBlock(buffer, x, y, z, chunks, vox.id, index);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -317,11 +507,27 @@ Mesh* VoxelRenderer::render(Chunk* chunk, const Chunk** chunks){
|
||||
for (int z = 0; z < CHUNK_D; z++){
|
||||
for (int x = 0; x < CHUNK_W; x++){
|
||||
voxel vox = chunk->voxels[(y * CHUNK_D + z) * CHUNK_W + x];
|
||||
if (vox.id != 4)
|
||||
if (vox.id == 0)
|
||||
continue;
|
||||
_renderBlock(buffer, x, y, z, chunks, vox, index);
|
||||
if (Block::blocks[vox.id]->model != BLOCK_MODEL_GRASS)
|
||||
continue;
|
||||
_renderXBlock(buffer, x, y, z, chunks, vox, index);
|
||||
}
|
||||
}
|
||||
}
|
||||
return new Mesh(buffer, index / VERTEX_SIZE, chunk_attrs);
|
||||
|
||||
for (int y = 0; y < CHUNK_H; y++){
|
||||
for (int z = 0; z < CHUNK_D; z++){
|
||||
for (int x = 0; x < CHUNK_W; x++){
|
||||
voxel vox = chunk->voxels[(y * CHUNK_D + z) * CHUNK_W + x];
|
||||
if (vox.id == 0)
|
||||
continue;
|
||||
if (vox.id != 4)
|
||||
continue;
|
||||
_renderBlock(buffer, x, y, z, chunks, vox.id, index);
|
||||
}
|
||||
}
|
||||
}
|
||||
size = buffer.size();
|
||||
return &buffer[0];
|
||||
}
|
||||
|
||||
@ -2,18 +2,21 @@
|
||||
#define GRAPHICS_VOXELRENDERER_H_
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <vector>
|
||||
|
||||
class Mesh;
|
||||
class Chunk;
|
||||
|
||||
#define CHUNK_VERTEX_SIZE (3 + 2 + 4)
|
||||
|
||||
class VoxelRenderer {
|
||||
float* buffer;
|
||||
size_t capacity;
|
||||
public:
|
||||
VoxelRenderer(size_t capacity);
|
||||
std::vector<float> buffer;
|
||||
unsigned char lights[27 * 4];
|
||||
VoxelRenderer();
|
||||
~VoxelRenderer();
|
||||
|
||||
Mesh* render(Chunk* chunk, const Chunk** chunks);
|
||||
const float* render(Chunk* chunk, const Chunk** chunks, size_t& size);
|
||||
};
|
||||
|
||||
#endif /* GRAPHICS_VOXELRENDERER_H_ */
|
||||
|
||||
140
src/hud_render.cpp
Normal file
@ -0,0 +1,140 @@
|
||||
#include "hud_render.h"
|
||||
|
||||
#include <GL/glew.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
#include "Assets.h"
|
||||
#include "graphics/Shader.h"
|
||||
#include "graphics/Batch2D.h"
|
||||
#include "graphics/Font.h"
|
||||
#include "graphics/Mesh.h"
|
||||
#include "window/Camera.h"
|
||||
#include "window/Window.h"
|
||||
#include "window/Events.h"
|
||||
#include "voxels/Chunks.h"
|
||||
#include "voxels/Block.h"
|
||||
#include "world/World.h"
|
||||
#include "world/Level.h"
|
||||
#include "objects/Player.h"
|
||||
|
||||
|
||||
HudRenderer::HudRenderer() {
|
||||
float vertices[] = {
|
||||
// x y
|
||||
-0.01f,-0.01f,
|
||||
0.01f, 0.01f,
|
||||
|
||||
-0.01f, 0.01f,
|
||||
0.01f,-0.01f,
|
||||
};
|
||||
int attrs[] = {
|
||||
2, 0 //null terminator
|
||||
};
|
||||
crosshair = new Mesh(vertices, 4, attrs);
|
||||
|
||||
batch = new Batch2D(1024);
|
||||
uicamera = new Camera(glm::vec3(), Window::height / 1.0f);
|
||||
uicamera->perspective = false;
|
||||
uicamera->flipped = true;
|
||||
}
|
||||
|
||||
HudRenderer::~HudRenderer() {
|
||||
delete crosshair;
|
||||
delete batch;
|
||||
delete uicamera;
|
||||
}
|
||||
|
||||
void HudRenderer::drawDebug(Level* level, Assets* assets, int fps, bool occlusion){
|
||||
Chunks* chunks = level->chunks;
|
||||
Player* player = level->player;
|
||||
|
||||
Font* font = assets->getFont("normal");
|
||||
|
||||
Shader* uishader = assets->getShader("ui");
|
||||
uishader->use();
|
||||
uishader->uniformMatrix("u_projview", uicamera->getProjection()*uicamera->getView());
|
||||
batch->color = vec4(1.0f);
|
||||
batch->begin();
|
||||
font->draw(batch, L"chunks: "+std::to_wstring(chunks->chunksCount), 16, 16, STYLE_OUTLINE);
|
||||
font->draw(batch, std::to_wstring((int)player->camera->position.x), 10, 30, STYLE_OUTLINE);
|
||||
font->draw(batch, std::to_wstring((int)player->camera->position.y), 50, 30, STYLE_OUTLINE);
|
||||
font->draw(batch, std::to_wstring((int)player->camera->position.z), 90, 30, STYLE_OUTLINE);
|
||||
font->draw(batch, L"fps:", 16, 42, STYLE_OUTLINE);
|
||||
font->draw(batch, std::to_wstring(fps), 44, 42, STYLE_OUTLINE);
|
||||
font->draw(batch, L"occlusion: "+std::to_wstring(occlusion), 16, 54, STYLE_OUTLINE);
|
||||
batch->render();
|
||||
}
|
||||
|
||||
|
||||
void HudRenderer::draw(Level* level, Assets* assets){
|
||||
uicamera->fov = Window::height;
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_CULL_FACE);
|
||||
|
||||
Shader* uishader = assets->getShader("ui");
|
||||
uishader->use();
|
||||
uishader->uniformMatrix("u_projview", uicamera->getProjection()*uicamera->getView());
|
||||
|
||||
// Chosen block preview
|
||||
Texture* blocks = assets->getTexture("block");
|
||||
Texture* sprite = assets->getTexture("slot");
|
||||
|
||||
if (!Events::_cursor_locked) {
|
||||
batch->texture(nullptr);
|
||||
batch->color = vec4(0.0f, 0.0f, 0.0f, 0.5f);
|
||||
batch->rect(0, 0, Window::width, Window::height);
|
||||
}
|
||||
|
||||
batch->color = vec4(1.0f);
|
||||
batch->texture(sprite);
|
||||
batch->sprite(16, uicamera->fov - 80, 64, 64, 16, 0, vec4(1.0f));
|
||||
|
||||
batch->texture(blocks);
|
||||
Player* player = level->player;
|
||||
{
|
||||
Block* cblock = Block::blocks[player->choosenBlock];
|
||||
if (cblock->model == BLOCK_MODEL_CUBE){
|
||||
batch->blockSprite(24, uicamera->fov - 72, 48, 48, 16, cblock->textureFaces, vec4(1.0f));
|
||||
} else if (cblock->model == BLOCK_MODEL_GRASS){
|
||||
batch->sprite(24, uicamera->fov - 72, 48, 48, 16, cblock->textureFaces[3], vec4(1.0f));
|
||||
}
|
||||
}
|
||||
|
||||
if (!Events::_cursor_locked) {
|
||||
for (unsigned i = 1; i < 256; i++) {
|
||||
Block* cblock = Block::blocks[i];
|
||||
if (cblock == nullptr)
|
||||
break;
|
||||
int size = 48;
|
||||
int step = 70;
|
||||
int x = 24 + (i-1) * step;
|
||||
int y = uicamera->fov - 72 - 70;
|
||||
y -= 72 * (x / (Window::width - step));
|
||||
x %= (Window::width - step);
|
||||
vec4 tint(1.0f);
|
||||
int mx = Events::x;
|
||||
int my = Events::y;
|
||||
if (mx > x && mx < x + size && my > y && my < y + size) {
|
||||
tint.r *= 2.0f;
|
||||
tint.g *= 2.0f;
|
||||
tint.b *= 2.0f;
|
||||
if (Events::jclicked(GLFW_MOUSE_BUTTON_LEFT)) {
|
||||
player->choosenBlock = i;
|
||||
}
|
||||
}
|
||||
if (cblock->model == BLOCK_MODEL_CUBE){
|
||||
batch->blockSprite(x, y, size, size, 16, cblock->textureFaces, tint);
|
||||
} else if (cblock->model == BLOCK_MODEL_GRASS){
|
||||
batch->sprite(x, y, size, size, 16, cblock->textureFaces[3], tint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
batch->render();
|
||||
|
||||
Shader* crosshairShader = assets->getShader("crosshair");
|
||||
crosshairShader->use();
|
||||
crosshairShader->uniform1f("u_ar", (float)Window::height / (float)Window::width);
|
||||
crosshairShader->uniform1f("u_scale", 1.0f / ((float)Window::height / 1000.0f));
|
||||
crosshair->draw(GL_LINES);
|
||||
}
|
||||
21
src/hud_render.h
Normal file
@ -0,0 +1,21 @@
|
||||
#ifndef SRC_HUD_RENDER_H_
|
||||
#define SRC_HUD_RENDER_H_
|
||||
|
||||
class Batch2D;
|
||||
class Camera;
|
||||
class Level;
|
||||
class Assets;
|
||||
class Mesh;
|
||||
|
||||
class HudRenderer {
|
||||
Batch2D* batch;
|
||||
Camera* uicamera;
|
||||
Mesh* crosshair;
|
||||
public:
|
||||
HudRenderer();
|
||||
~HudRenderer();
|
||||
void draw(Level* level, Assets* assets);
|
||||
void drawDebug(Level* level, Assets* assets, int fps, bool occlusion);
|
||||
};
|
||||
|
||||
#endif /* SRC_HUD_RENDER_H_ */
|
||||
@ -21,8 +21,8 @@ void LightSolver::add(int x, int y, int z, int emission) {
|
||||
addqueue.push(entry);
|
||||
|
||||
Chunk* chunk = chunks->getChunkByVoxel(entry.x, entry.y, entry.z);
|
||||
chunk->modified = true;
|
||||
chunk->lightmap->set(entry.x-chunk->x*CHUNK_W, entry.y-chunk->y*CHUNK_H, entry.z-chunk->z*CHUNK_D, channel, entry.light);
|
||||
chunk->setModified(true);
|
||||
chunk->lightmap->set(entry.x-chunk->x*CHUNK_W, entry.y, entry.z-chunk->z*CHUNK_D, channel, entry.light);
|
||||
}
|
||||
|
||||
void LightSolver::add(int x, int y, int z) {
|
||||
@ -35,7 +35,7 @@ void LightSolver::remove(int x, int y, int z) {
|
||||
if (chunk == nullptr)
|
||||
return;
|
||||
|
||||
int light = chunk->lightmap->get(x-chunk->x*CHUNK_W, y-chunk->y*CHUNK_H, z-chunk->z*CHUNK_D, channel);
|
||||
int light = chunk->lightmap->get(x-chunk->x*CHUNK_W, y, z-chunk->z*CHUNK_D, channel);
|
||||
if (light == 0){
|
||||
return;
|
||||
}
|
||||
@ -47,7 +47,7 @@ void LightSolver::remove(int x, int y, int z) {
|
||||
entry.light = light;
|
||||
remqueue.push(entry);
|
||||
|
||||
chunk->lightmap->set(entry.x-chunk->x*CHUNK_W, entry.y-chunk->y*CHUNK_H, entry.z-chunk->z*CHUNK_D, channel, 0);
|
||||
chunk->lightmap->set(entry.x-chunk->x*CHUNK_W, entry.y, entry.z-chunk->z*CHUNK_D, channel, 0);
|
||||
}
|
||||
|
||||
void LightSolver::solve(){
|
||||
@ -78,8 +78,8 @@ void LightSolver::solve(){
|
||||
nentry.z = z;
|
||||
nentry.light = light;
|
||||
remqueue.push(nentry);
|
||||
chunk->lightmap->set(x-chunk->x*CHUNK_W, y-chunk->y*CHUNK_H, z-chunk->z*CHUNK_D, channel, 0);
|
||||
chunk->modified = true;
|
||||
chunk->lightmap->set(x-chunk->x*CHUNK_W, y, z-chunk->z*CHUNK_D, channel, 0);
|
||||
chunk->setModified(true);
|
||||
}
|
||||
else if (light >= entry.light){
|
||||
lightentry nentry;
|
||||
@ -94,7 +94,7 @@ void LightSolver::solve(){
|
||||
}
|
||||
|
||||
while (!addqueue.empty()){
|
||||
lightentry entry = addqueue.front();
|
||||
const lightentry entry = addqueue.front();
|
||||
addqueue.pop();
|
||||
|
||||
if (entry.light <= 1)
|
||||
@ -110,8 +110,8 @@ void LightSolver::solve(){
|
||||
voxel* v = chunks->get(x,y,z);
|
||||
Block* block = Block::blocks[v->id];
|
||||
if (block->lightPassing && light+2 <= entry.light){
|
||||
chunk->lightmap->set(x-chunk->x*CHUNK_W, y-chunk->y*CHUNK_H, z-chunk->z*CHUNK_D, channel, entry.light-1);
|
||||
chunk->modified = true;
|
||||
chunk->lightmap->set(x-chunk->x*CHUNK_W, y, z-chunk->z*CHUNK_D, channel, entry.light-1);
|
||||
chunk->setModified(true);
|
||||
lightentry nentry;
|
||||
nentry.x = x;
|
||||
nentry.y = y;
|
||||
|
||||
@ -6,6 +6,8 @@
|
||||
#include "../voxels/voxel.h"
|
||||
#include "../voxels/Block.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
Lighting::Lighting(Chunks* chunks){
|
||||
this->chunks = chunks;
|
||||
solverR = new LightSolver(chunks, 0);
|
||||
@ -33,154 +35,94 @@ void Lighting::clear(){
|
||||
}
|
||||
}
|
||||
|
||||
void Lighting::onChunkLoaded(int cx, int cy, int cz, bool sky){
|
||||
Chunk* chunk = chunks->getChunk(cx, cy, cz);
|
||||
Chunk* chunkUpper = chunks->getChunk(cx, cy+1, cz);
|
||||
Chunk* chunkLower = chunks->getChunk(cx, cy-1, cz);
|
||||
if (chunkLower && sky){
|
||||
for (int z = 0; z < CHUNK_D; z++){
|
||||
for (int x = 0; x < CHUNK_W; x++){
|
||||
void Lighting::prebuildSkyLight(int cx, int cz){
|
||||
Chunk* chunk = chunks->getChunk(cx, cz);
|
||||
int highestPoint = 0;
|
||||
for (int z = 0; z < CHUNK_D; z++){
|
||||
for (int x = 0; x < CHUNK_W; x++){
|
||||
for (int y = CHUNK_H-1;;y--){
|
||||
if (y < 0)
|
||||
break;
|
||||
voxel* vox = &(chunk->voxels[(y * CHUNK_D + z) * CHUNK_W + x]);
|
||||
Block* block = Block::blocks[vox->id];
|
||||
if (!block->skyLightPassing) {
|
||||
if (highestPoint < y)
|
||||
highestPoint = y;
|
||||
break;
|
||||
}
|
||||
chunk->lightmap->setS(x,y,z, 15);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (highestPoint < CHUNK_H-1)
|
||||
highestPoint++;
|
||||
chunk->lightmap->highestPoint = highestPoint;
|
||||
}
|
||||
|
||||
void Lighting::buildSkyLight(int cx, int cz){
|
||||
Chunk* chunk = chunks->getChunk(cx, cz);
|
||||
for (int z = 0; z < CHUNK_D; z++){
|
||||
for (int x = 0; x < CHUNK_W; x++){
|
||||
for (int y = chunk->lightmap->highestPoint; y >= 0; y--){
|
||||
int gx = x + cx * CHUNK_W;
|
||||
int gz = z + cz * CHUNK_D;
|
||||
|
||||
int light = chunk->lightmap->getS(x,0,z);
|
||||
int ncy = cy-1;
|
||||
if (light < 15){
|
||||
Chunk* current = chunkLower;
|
||||
if (chunkLower->lightmap->getS(x,15,z) == 0)
|
||||
continue;
|
||||
for (int y = 15;;y--){
|
||||
if (y < 0){
|
||||
ncy--;
|
||||
y += CHUNK_H;
|
||||
}
|
||||
if (ncy != current->y)
|
||||
current = chunks->getChunk(cx,ncy,cz);
|
||||
if (!current)
|
||||
break;
|
||||
voxel* vox = &(current->voxels[(y * CHUNK_D + z) * CHUNK_W + x]);//chunks->get(gx,gy+y,gz);
|
||||
Block* block = Block::blocks[vox->id];
|
||||
if (!block->skyLightPassing)
|
||||
break;
|
||||
//current->lightmap->setS(x,y,z, 0);
|
||||
current->modified = true;
|
||||
solverS->remove(gx,y+ncy*CHUNK_H,gz);
|
||||
current->lightmap->setS(x,y,z, 0);
|
||||
while (y > 0 && !Block::blocks[chunk->voxels[(y * CHUNK_D + z) * CHUNK_W + x].id]->lightPassing) {
|
||||
y--;
|
||||
}
|
||||
if (chunk->lightmap->getS(x, y, z) != 15) {
|
||||
solverS->add(gx,y+1,gz);
|
||||
for (; y >= 0; y--){
|
||||
solverS->add(gx+1,y,gz);
|
||||
solverS->add(gx-1,y,gz);
|
||||
solverS->add(gx,y,gz+1);
|
||||
solverS->add(gx,y,gz-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (chunkUpper && sky){
|
||||
for (int z = 0; z < CHUNK_D; z++){
|
||||
for (int x = 0; x < CHUNK_W; x++){
|
||||
int gx = x + cx * CHUNK_W;
|
||||
int gy = cy * CHUNK_H;
|
||||
int gz = z + cz * CHUNK_D;
|
||||
int ncy = cy;
|
||||
solverS->solve();
|
||||
}
|
||||
|
||||
int light = chunkUpper->lightmap->getS(x,0,z);
|
||||
void Lighting::onChunkLoaded(int cx, int cz){
|
||||
const Chunk* chunk = chunks->getChunk(cx, cz);
|
||||
|
||||
Chunk* current = chunk;
|
||||
if (light == 15){
|
||||
for (int y = CHUNK_H-1;;y--){
|
||||
if (y < 0){
|
||||
ncy--;
|
||||
y += CHUNK_H;
|
||||
}
|
||||
if (ncy != current->y)
|
||||
current = chunks->getChunk(cx,ncy,cz);
|
||||
if (!current)
|
||||
break;
|
||||
voxel* vox = &(current->voxels[(y * CHUNK_D + z) * CHUNK_W + x]);//chunks->get(gx,gy+y,gz);
|
||||
Block* block = Block::blocks[vox->id];
|
||||
if (!block->skyLightPassing)
|
||||
break;
|
||||
current->lightmap->setS(x,y,z, 15);
|
||||
current->modified = true;
|
||||
solverS->add(gx,y+ncy*CHUNK_H,gz);
|
||||
}
|
||||
} else if (light){
|
||||
solverS->add(gx,gy+CHUNK_H,gz);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (sky){
|
||||
for (int z = 0; z < CHUNK_D; z++){
|
||||
for (int x = 0; x < CHUNK_W; x++){
|
||||
int gx = x + cx * CHUNK_W;
|
||||
int gz = z + cz * CHUNK_D;
|
||||
int ncy = cy;
|
||||
|
||||
Chunk* current = chunk;
|
||||
for (int y = CHUNK_H-1;;y--){
|
||||
if (y < 0){
|
||||
ncy--;
|
||||
y += CHUNK_H;
|
||||
}
|
||||
if (ncy != current->y)
|
||||
current = chunks->getChunk(cx,ncy,cz);
|
||||
if (!current)
|
||||
break;
|
||||
voxel* vox = &(current->voxels[(y * CHUNK_D + z) * CHUNK_W + x]);//chunks->get(gx,gy+y,gz);
|
||||
Block* block = Block::blocks[vox->id];
|
||||
if (!block->skyLightPassing)
|
||||
break;
|
||||
current->lightmap->setS(x,y,z, 15);
|
||||
current->modified = true;
|
||||
solverS->add(gx,y+ncy*CHUNK_H,gz);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//std::cout << "DONE" << std::endl;
|
||||
for (unsigned int y = 0; y < CHUNK_H; y++){
|
||||
for (unsigned int z = 0; z < CHUNK_D; z++){
|
||||
for (unsigned int x = 0; x < CHUNK_W; x++){
|
||||
voxel vox = chunk->voxels[(y * CHUNK_D + z) * CHUNK_W + x];
|
||||
Block* block = Block::blocks[vox.id];
|
||||
if (block->emission[0] || block->emission[1] || block->emission[2]){
|
||||
int gx = x + cx * CHUNK_W;
|
||||
int gy = y + cy * CHUNK_H;
|
||||
int gz = z + cz * CHUNK_D;
|
||||
solverR->add(gx,gy,gz,block->emission[0]);
|
||||
solverG->add(gx,gy,gz,block->emission[1]);
|
||||
solverB->add(gx,gy,gz,block->emission[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int y = -1; y <= CHUNK_H; y++){
|
||||
for (int z = -1; z <= CHUNK_D; z++){
|
||||
for (int x = -1; x <= CHUNK_W; x++){
|
||||
if (!(x == -1 || x == CHUNK_W || y == -1 || y == CHUNK_H || z == -1 || z == CHUNK_D))
|
||||
continue;
|
||||
int gx = x + cx * CHUNK_W;
|
||||
int gy = y + cy * CHUNK_H;
|
||||
int gz = z + cz * CHUNK_D;
|
||||
if (chunks->getLight(x,y,z)){
|
||||
solverR->add(gx,gy,gz);
|
||||
solverG->add(gx,gy,gz);
|
||||
solverB->add(gx,gy,gz);
|
||||
if (sky)
|
||||
solverS->add(gx,gy,gz);
|
||||
if (block->emission[0] || block->emission[1] || block->emission[2]){
|
||||
solverR->add(gx,y,gz,block->emission[0]);
|
||||
solverG->add(gx,y,gz,block->emission[1]);
|
||||
solverB->add(gx,y,gz,block->emission[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int y = -1; y <= CHUNK_H; y++){
|
||||
for (int z = -1; z <= CHUNK_D; z++){
|
||||
for (int x = -1; x <= CHUNK_W; x++){
|
||||
if (!(x == -1 || x == CHUNK_W || z == -1 || z == CHUNK_D))
|
||||
continue;
|
||||
int gx = x + cx * CHUNK_W;
|
||||
int gz = z + cz * CHUNK_D;
|
||||
if (chunks->getLight(x,y,z)){
|
||||
solverR->add(gx,y,gz);
|
||||
solverG->add(gx,y,gz);
|
||||
solverB->add(gx,y,gz);
|
||||
solverS->add(gx,y,gz);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
solverR->solve();
|
||||
solverG->solve();
|
||||
solverB->solve();
|
||||
solverS->solve();
|
||||
|
||||
Chunk* other;
|
||||
other = chunks->getChunk(cx-1,cy,cz); if (other) other->modified = true;
|
||||
other = chunks->getChunk(cx+1,cy,cz); if (other) other->modified = true;
|
||||
other = chunks->getChunk(cx,cy-1,cz); if (other) other->modified = true;
|
||||
other = chunks->getChunk(cx,cy+1,cz); if (other) other->modified = true;
|
||||
other = chunks->getChunk(cx,cy,cz-1); if (other) other->modified = true;
|
||||
other = chunks->getChunk(cx,cy,cz+1); if (other) other->modified = true;
|
||||
}
|
||||
|
||||
void Lighting::onBlockSet(int x, int y, int z, int id){
|
||||
@ -189,11 +131,9 @@ void Lighting::onBlockSet(int x, int y, int z, int id){
|
||||
solverR->remove(x,y,z);
|
||||
solverG->remove(x,y,z);
|
||||
solverB->remove(x,y,z);
|
||||
|
||||
solverR->solve();
|
||||
solverG->solve();
|
||||
solverB->solve();
|
||||
|
||||
if (chunks->getLight(x,y+1,z, 3) == 0xF){
|
||||
for (int i = y; i >= 0; i--){
|
||||
voxel* vox = chunks->get(x,i,z);
|
||||
@ -202,14 +142,12 @@ void Lighting::onBlockSet(int x, int y, int z, int id){
|
||||
solverS->add(x,i,z, 0xF);
|
||||
}
|
||||
}
|
||||
|
||||
solverR->add(x,y+1,z); solverG->add(x,y+1,z); solverB->add(x,y+1,z); solverS->add(x,y+1,z);
|
||||
solverR->add(x,y-1,z); solverG->add(x,y-1,z); solverB->add(x,y-1,z); solverS->add(x,y-1,z);
|
||||
solverR->add(x+1,y,z); solverG->add(x+1,y,z); solverB->add(x+1,y,z); solverS->add(x+1,y,z);
|
||||
solverR->add(x-1,y,z); solverG->add(x-1,y,z); solverB->add(x-1,y,z); solverS->add(x-1,y,z);
|
||||
solverR->add(x,y,z+1); solverG->add(x,y,z+1); solverB->add(x,y,z+1); solverS->add(x,y,z+1);
|
||||
solverR->add(x,y,z-1); solverG->add(x,y,z-1); solverB->add(x,y,z-1); solverS->add(x,y,z-1);
|
||||
|
||||
solverR->solve();
|
||||
solverG->solve();
|
||||
solverB->solve();
|
||||
|
||||
@ -15,7 +15,9 @@ public:
|
||||
~Lighting();
|
||||
|
||||
void clear();
|
||||
void onChunkLoaded(int cx, int cy, int cz, bool sky);
|
||||
void prebuildSkyLight(int cx, int cz);
|
||||
void buildSkyLight(int cx, int cz);
|
||||
void onChunkLoaded(int cx, int cz);
|
||||
void onBlockSet(int x, int y, int z, int id);
|
||||
};
|
||||
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
class Lightmap {
|
||||
public:
|
||||
unsigned short* map;
|
||||
int highestPoint = 0;
|
||||
Lightmap();
|
||||
~Lightmap();
|
||||
|
||||
|
||||
@ -102,6 +102,8 @@ int _png_load(const char* file, int* width, int* height){
|
||||
alpha, GL_UNSIGNED_BYTE, (GLvoid *) image_data);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 3);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
@ -210,6 +212,8 @@ int _png_load(const char* file, int* pwidth, int* pheight){
|
||||
alpha, GL_UNSIGNED_BYTE, (GLvoid *) flipped);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
pwidth[0] = ihdr.width;
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
#include "Player.h"
|
||||
#include "../physics/Hitbox.h"
|
||||
#include "../physics/PhysicsSolver.h"
|
||||
#include "../voxels/Chunks.h"
|
||||
#include "../window/Events.h"
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
|
||||
@ -5,6 +5,8 @@
|
||||
|
||||
class Camera;
|
||||
class Hitbox;
|
||||
class PhysicsSolver;
|
||||
class Chunks;
|
||||
|
||||
class Player {
|
||||
public:
|
||||
@ -12,6 +14,7 @@ public:
|
||||
Camera* camera;
|
||||
Hitbox* hitbox;
|
||||
bool flight = false;
|
||||
bool noclip = false;
|
||||
int choosenBlock;
|
||||
float camX, camY;
|
||||
float cameraShaking = 0.0f;
|
||||
|
||||
@ -10,7 +10,9 @@
|
||||
PhysicsSolver::PhysicsSolver(vec3 gravity) : gravity(gravity) {
|
||||
}
|
||||
|
||||
void PhysicsSolver::step(Chunks* chunks, Hitbox* hitbox, float delta, unsigned substeps, bool shifting, float gravityScale) {
|
||||
void PhysicsSolver::step(Chunks* chunks, Hitbox* hitbox, float delta, unsigned substeps, bool shifting,
|
||||
float gravityScale,
|
||||
bool collisions) {
|
||||
hitbox->grounded = false;
|
||||
for (unsigned i = 0; i < substeps; i++){
|
||||
float dt = delta / (float)substeps;
|
||||
@ -25,85 +27,87 @@ void PhysicsSolver::step(Chunks* chunks, Hitbox* hitbox, float delta, unsigned s
|
||||
float px = pos.x;
|
||||
float pz = pos.z;
|
||||
|
||||
if (vel.x < 0.0){
|
||||
for (int y = floor(pos.y-half.y+E); y <= floor(pos.y+half.y-E); y++){
|
||||
for (int z = floor(pos.z-half.z+E); z <= floor(pos.z+half.z-E); z++){
|
||||
int x = floor(pos.x-half.x-E);
|
||||
if (chunks->isObstacle(x,y,z)){
|
||||
vel.x *= 0.0;
|
||||
pos.x = x + 1 + half.x + E;
|
||||
break;
|
||||
if (collisions) {
|
||||
if (vel.x < 0.0){
|
||||
for (int y = floor(pos.y-half.y+E); y <= floor(pos.y+half.y-E); y++){
|
||||
for (int z = floor(pos.z-half.z+E); z <= floor(pos.z+half.z-E); z++){
|
||||
int x = floor(pos.x-half.x-E);
|
||||
if (chunks->isObstacle(x,y,z)){
|
||||
vel.x *= 0.0;
|
||||
pos.x = x + 1 + half.x + E;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (vel.x > 0.0){
|
||||
for (int y = floor(pos.y-half.y+E); y <= floor(pos.y+half.y-E); y++){
|
||||
for (int z = floor(pos.z-half.z+E); z <= floor(pos.z+half.z-E); z++){
|
||||
int x = floor(pos.x+half.x+E);
|
||||
if (chunks->isObstacle(x,y,z)){
|
||||
vel.x *= 0.0;
|
||||
pos.x = x - half.x - E;
|
||||
break;
|
||||
if (vel.x > 0.0){
|
||||
for (int y = floor(pos.y-half.y+E); y <= floor(pos.y+half.y-E); y++){
|
||||
for (int z = floor(pos.z-half.z+E); z <= floor(pos.z+half.z-E); z++){
|
||||
int x = floor(pos.x+half.x+E);
|
||||
if (chunks->isObstacle(x,y,z)){
|
||||
vel.x *= 0.0;
|
||||
pos.x = x - half.x - E;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (vel.z < 0.0){
|
||||
for (int y = floor(pos.y-half.y+E); y <= floor(pos.y+half.y-E); y++){
|
||||
if (vel.z < 0.0){
|
||||
for (int y = floor(pos.y-half.y+E); y <= floor(pos.y+half.y-E); y++){
|
||||
for (int x = floor(pos.x-half.x+E); x <= floor(pos.x+half.x-E); x++){
|
||||
int z = floor(pos.z-half.z-E);
|
||||
if (chunks->isObstacle(x,y,z)){
|
||||
vel.z *= 0.0;
|
||||
pos.z = z + 1 + half.z + E;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (vel.z > 0.0){
|
||||
for (int y = floor(pos.y-half.y+E); y <= floor(pos.y+half.y-E); y++){
|
||||
for (int x = floor(pos.x-half.x+E); x <= floor(pos.x+half.x-E); x++){
|
||||
int z = floor(pos.z+half.z+E);
|
||||
if (chunks->isObstacle(x,y,z)){
|
||||
vel.z *= 0.0;
|
||||
pos.z = z - half.z - E;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (vel.y < 0.0){
|
||||
for (int x = floor(pos.x-half.x+E); x <= floor(pos.x+half.x-E); x++){
|
||||
int z = floor(pos.z-half.z-E);
|
||||
if (chunks->isObstacle(x,y,z)){
|
||||
vel.z *= 0.0;
|
||||
pos.z = z + 1 + half.z + E;
|
||||
break;
|
||||
bool broken = false;
|
||||
for (int z = floor(pos.z-half.z+E); z <= floor(pos.z+half.z-E); z++){
|
||||
int y = floor(pos.y-half.y-E);
|
||||
if (chunks->isObstacle(x,y,z)){
|
||||
vel.y *= 0.0;
|
||||
pos.y = y + 1 + half.y;
|
||||
int f = DEFAULT_FRICTION;
|
||||
vel.x *= max(0.0, 1.0 - dt * f);
|
||||
vel.z *= max(0.0, 1.0 - dt * f);
|
||||
hitbox->grounded = true;
|
||||
broken = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (broken)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (vel.z > 0.0){
|
||||
for (int y = floor(pos.y-half.y+E); y <= floor(pos.y+half.y-E); y++){
|
||||
if (vel.y > 0.0){
|
||||
for (int x = floor(pos.x-half.x+E); x <= floor(pos.x+half.x-E); x++){
|
||||
int z = floor(pos.z+half.z+E);
|
||||
if (chunks->isObstacle(x,y,z)){
|
||||
vel.z *= 0.0;
|
||||
pos.z = z - half.z - E;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (vel.y < 0.0){
|
||||
for (int x = floor(pos.x-half.x+E); x <= floor(pos.x+half.x-E); x++){
|
||||
bool broken = false;
|
||||
for (int z = floor(pos.z-half.z+E); z <= floor(pos.z+half.z-E); z++){
|
||||
int y = floor(pos.y-half.y-E);
|
||||
if (chunks->isObstacle(x,y,z)){
|
||||
vel.y *= 0.0;
|
||||
pos.y = y + 1 + half.y;
|
||||
int f = DEFAULT_FRICTION;
|
||||
vel.x *= max(0.0, 1.0 - dt * f);
|
||||
vel.z *= max(0.0, 1.0 - dt * f);
|
||||
hitbox->grounded = true;
|
||||
broken = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (broken)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (vel.y > 0.0){
|
||||
for (int x = floor(pos.x-half.x+E); x <= floor(pos.x+half.x-E); x++){
|
||||
for (int z = floor(pos.z-half.z+E); z <= floor(pos.z+half.z-E); z++){
|
||||
int y = floor(pos.y+half.y+E);
|
||||
if (chunks->isObstacle(x,y,z)){
|
||||
vel.y *= 0.0;
|
||||
pos.y = y - half.y - E;
|
||||
break;
|
||||
for (int z = floor(pos.z-half.z+E); z <= floor(pos.z+half.z-E); z++){
|
||||
int y = floor(pos.y+half.y+E);
|
||||
if (chunks->isObstacle(x,y,z)){
|
||||
vel.y *= 0.0;
|
||||
pos.y = y - half.y - E;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -14,7 +14,13 @@ class PhysicsSolver {
|
||||
vec3 gravity;
|
||||
public:
|
||||
PhysicsSolver(vec3 gravity);
|
||||
void step(Chunks* chunks, Hitbox* hitbox, float delta, unsigned substeps, bool shifting, float gravityScale);
|
||||
void step(Chunks* chunks,
|
||||
Hitbox* hitbox,
|
||||
float delta,
|
||||
unsigned substeps,
|
||||
bool shifting,
|
||||
float gravityScale,
|
||||
bool collisions);
|
||||
bool isBlockInside(int x, int y, int z, Hitbox* hitbox);
|
||||
};
|
||||
|
||||
|
||||
211
src/player_control.cpp
Normal file
@ -0,0 +1,211 @@
|
||||
#include "player_control.h"
|
||||
|
||||
#include "objects/Player.h"
|
||||
#include "physics/PhysicsSolver.h"
|
||||
#include "physics/Hitbox.h"
|
||||
#include "lighting/Lighting.h"
|
||||
#include "world/Level.h"
|
||||
#include "voxels/Block.h"
|
||||
#include "voxels/voxel.h"
|
||||
#include "voxels/Chunks.h"
|
||||
#include "window/Camera.h"
|
||||
#include "window/Events.h"
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#define CROUCH_SPEED_MUL 0.25f
|
||||
#define CROUCH_SHIFT_Y -0.2f
|
||||
#define RUN_SPEED_MUL 1.5f
|
||||
#define CROUCH_ZOOM 0.9f
|
||||
#define RUN_ZOOM 1.1f
|
||||
#define C_ZOOM 0.1f
|
||||
#define ZOOM_SPEED 16.0f
|
||||
#define DEFAULT_AIR_DAMPING 0.1f
|
||||
#define PLAYER_NOT_ONGROUND_DAMPING 10.0f
|
||||
#define CAMERA_SHAKING_OFFSET 0.025f
|
||||
#define CAMERA_SHAKING_OFFSET_Y 0.031f
|
||||
#define CAMERA_SHAKING_SPEED 1.6f
|
||||
#define CAMERA_SHAKING_DELTA_K 10.0f
|
||||
#define FLIGHT_SPEED_MUL 4.0f
|
||||
#define CHEAT_SPEED_MUL 5.0f
|
||||
#define JUMP_FORCE 7.0f
|
||||
|
||||
PlayerController::PlayerController(Level* level) : level(level) {
|
||||
}
|
||||
|
||||
void PlayerController::update_controls(float delta){
|
||||
Player* player = level->player;
|
||||
|
||||
for (int i = 1; i < 10; i++){
|
||||
if (Events::jpressed(GLFW_KEY_0+i)){
|
||||
player->choosenBlock = i;
|
||||
}
|
||||
}
|
||||
|
||||
// Controls
|
||||
Camera* camera = player->camera;
|
||||
Hitbox* hitbox = player->hitbox;
|
||||
bool sprint = Events::pressed(GLFW_KEY_LEFT_CONTROL);
|
||||
bool shift = Events::pressed(GLFW_KEY_LEFT_SHIFT) && hitbox->grounded && !sprint;
|
||||
bool zoom = Events::pressed(GLFW_KEY_C);
|
||||
bool cheat = Events::pressed(GLFW_KEY_R);
|
||||
|
||||
float speed = player->speed;
|
||||
if (player->flight){
|
||||
speed *= FLIGHT_SPEED_MUL;
|
||||
}
|
||||
if (cheat){
|
||||
speed *= CHEAT_SPEED_MUL;
|
||||
}
|
||||
int substeps = (int)(delta * 1000);
|
||||
substeps = (substeps <= 0 ? 1 : (substeps > 100 ? 100 : substeps));
|
||||
level->physics->step(level->chunks, hitbox, delta, substeps, shift, player->flight ? 0.0f : 1.0f, !player->noclip);
|
||||
camera->position.x = hitbox->position.x;
|
||||
camera->position.y = hitbox->position.y + 0.7f;
|
||||
camera->position.z = hitbox->position.z;
|
||||
|
||||
if (player->flight && hitbox->grounded)
|
||||
player->flight = false;
|
||||
// Camera shaking
|
||||
player->interpVel = player->interpVel * (1.0f - delta * 5) + hitbox->velocity * delta * 0.1f;
|
||||
if (hitbox->grounded && player->interpVel.y < 0.0f){
|
||||
player->interpVel.y *= -30.0f;
|
||||
}
|
||||
float factor = hitbox->grounded ? length(vec2(hitbox->velocity.x, hitbox->velocity.z)) : 0.0f;
|
||||
player->cameraShakingTimer += delta * factor * CAMERA_SHAKING_SPEED;
|
||||
float shakeTimer = player->cameraShakingTimer;
|
||||
player->cameraShaking = player->cameraShaking * (1.0f - delta * CAMERA_SHAKING_DELTA_K) + factor * delta * CAMERA_SHAKING_DELTA_K;
|
||||
camera->position += camera->right * sin(shakeTimer) * CAMERA_SHAKING_OFFSET * player->cameraShaking;
|
||||
camera->position += camera->up * abs(cos(shakeTimer)) * CAMERA_SHAKING_OFFSET_Y * player->cameraShaking;
|
||||
camera->position -= min(player->interpVel * 0.05f, 1.0f);
|
||||
|
||||
if ((Events::jpressed(GLFW_KEY_F) && !player->noclip) ||
|
||||
(Events::jpressed(GLFW_KEY_N) && player->flight == player->noclip)){
|
||||
player->flight = !player->flight;
|
||||
if (player->flight){
|
||||
hitbox->velocity.y += 1;
|
||||
hitbox->grounded = false;
|
||||
}
|
||||
}
|
||||
if (Events::jpressed(GLFW_KEY_N)) {
|
||||
player->noclip = !player->noclip;
|
||||
}
|
||||
|
||||
// Field of view manipulations
|
||||
float dt = min(1.0f, delta * ZOOM_SPEED);
|
||||
float zoomValue = 1.0f;
|
||||
if (shift){
|
||||
speed *= CROUCH_SPEED_MUL;
|
||||
camera->position.y += CROUCH_SHIFT_Y;
|
||||
zoomValue = CROUCH_ZOOM;
|
||||
} else if (sprint){
|
||||
speed *= RUN_SPEED_MUL;
|
||||
zoomValue = RUN_ZOOM;
|
||||
}
|
||||
if (zoom)
|
||||
zoomValue *= C_ZOOM;
|
||||
camera->zoom = zoomValue * dt + camera->zoom * (1.0f - dt);
|
||||
|
||||
if (Events::pressed(GLFW_KEY_SPACE) && hitbox->grounded){
|
||||
hitbox->velocity.y = JUMP_FORCE;
|
||||
}
|
||||
|
||||
vec3 dir(0,0,0);
|
||||
if (Events::pressed(GLFW_KEY_W)){
|
||||
dir.x += camera->dir.x;
|
||||
dir.z += camera->dir.z;
|
||||
}
|
||||
if (Events::pressed(GLFW_KEY_S)){
|
||||
dir.x -= camera->dir.x;
|
||||
dir.z -= camera->dir.z;
|
||||
}
|
||||
if (Events::pressed(GLFW_KEY_D)){
|
||||
dir.x += camera->right.x;
|
||||
dir.z += camera->right.z;
|
||||
}
|
||||
if (Events::pressed(GLFW_KEY_A)){
|
||||
dir.x -= camera->right.x;
|
||||
dir.z -= camera->right.z;
|
||||
}
|
||||
|
||||
hitbox->linear_damping = DEFAULT_AIR_DAMPING;
|
||||
if (player->flight){
|
||||
hitbox->linear_damping = PLAYER_NOT_ONGROUND_DAMPING;
|
||||
hitbox->velocity.y *= 1.0f - delta * 9;
|
||||
if (Events::pressed(GLFW_KEY_SPACE)){
|
||||
hitbox->velocity.y += speed * delta * 9;
|
||||
}
|
||||
if (Events::pressed(GLFW_KEY_LEFT_SHIFT)){
|
||||
hitbox->velocity.y -= speed * delta * 9;
|
||||
}
|
||||
}
|
||||
if (length(dir) > 0.0f){
|
||||
dir = normalize(dir);
|
||||
|
||||
if (!hitbox->grounded)
|
||||
hitbox->linear_damping = PLAYER_NOT_ONGROUND_DAMPING;
|
||||
|
||||
hitbox->velocity.x += dir.x * speed * delta * 9;
|
||||
hitbox->velocity.z += dir.z * speed * delta * 9;
|
||||
}
|
||||
|
||||
if (Events::_cursor_locked){
|
||||
player->camY += -Events::deltaY / Window::height * 2;
|
||||
player->camX += -Events::deltaX / Window::height * 2;
|
||||
|
||||
if (player->camY < -radians(89.0f)){
|
||||
player->camY = -radians(89.0f);
|
||||
}
|
||||
if (player->camY > radians(89.0f)){
|
||||
player->camY = radians(89.0f);
|
||||
}
|
||||
|
||||
camera->rotation = mat4(1.0f);
|
||||
camera->rotate(player->camY, player->camX, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerController::update_interaction(){
|
||||
Chunks* chunks = level->chunks;
|
||||
Player* player = level->player;
|
||||
Lighting* lighting = level->lighting;
|
||||
Camera* camera = player->camera;
|
||||
vec3 end;
|
||||
vec3 norm;
|
||||
vec3 iend;
|
||||
voxel* vox = chunks->rayCast(camera->position, camera->front, 10.0f, end, norm, iend);
|
||||
if (vox != nullptr){
|
||||
selectedBlockId = vox->id;
|
||||
selectedBlockPosition = iend;
|
||||
|
||||
Block* block = Block::blocks[vox->id];
|
||||
if (Events::jclicked(GLFW_MOUSE_BUTTON_1) && block->breakable){
|
||||
int x = (int)iend.x;
|
||||
int y = (int)iend.y;
|
||||
int z = (int)iend.z;
|
||||
chunks->set(x,y,z, 0);
|
||||
lighting->onBlockSet(x,y,z,0);
|
||||
}
|
||||
if (Events::jclicked(GLFW_MOUSE_BUTTON_2)){
|
||||
int x = (int)(iend.x)+(int)(norm.x);
|
||||
int y = (int)(iend.y)+(int)(norm.y);
|
||||
int z = (int)(iend.z)+(int)(norm.z);
|
||||
if (block->model == BLOCK_MODEL_GRASS){
|
||||
x = (int)iend.x;
|
||||
y = (int)iend.y;
|
||||
z = (int)iend.z;
|
||||
}
|
||||
if (!level->physics->isBlockInside(x,y,z, player->hitbox)){
|
||||
chunks->set(x, y, z, player->choosenBlock);
|
||||
lighting->onBlockSet(x,y,z, player->choosenBlock);
|
||||
}
|
||||
}
|
||||
if (Events::jclicked(GLFW_MOUSE_BUTTON_3)){
|
||||
int x = (int)iend.x;
|
||||
int y = (int)iend.y;
|
||||
int z = (int)iend.z;
|
||||
player->choosenBlock = chunks->get(x,y,z)->id;
|
||||
}
|
||||
} else {
|
||||
selectedBlockId = -1;
|
||||
}
|
||||
}
|
||||
21
src/player_control.h
Normal file
@ -0,0 +1,21 @@
|
||||
#ifndef PLAYER_CONTROL_H_
|
||||
#define PLAYER_CONTROL_H_
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
class PhysicsSolver;
|
||||
class Chunks;
|
||||
class Player;
|
||||
class Level;
|
||||
|
||||
class PlayerController {
|
||||
Level* level;
|
||||
public:
|
||||
glm::vec3 selectedBlockPosition;
|
||||
int selectedBlockId = -1;
|
||||
PlayerController(Level* level);
|
||||
void update_controls(float delta);
|
||||
void update_interaction();
|
||||
};
|
||||
|
||||
#endif /* PLAYER_CONTROL_H_ */
|
||||
@ -2,6 +2,7 @@
|
||||
// sudo apt install libgl-dev libglew-dev libglfw3-dev libpng-dev libglm-dev
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
#include <stdint.h>
|
||||
|
||||
#define GLEW_STATIC
|
||||
#include <GL/glew.h>
|
||||
@ -22,6 +23,8 @@ using namespace glm;
|
||||
#include "graphics/Mesh.h"
|
||||
#include "graphics/VoxelRenderer.h"
|
||||
#include "graphics/LineBatch.h"
|
||||
#include "graphics/Batch2D.h"
|
||||
#include "graphics/Framebuffer.h"
|
||||
#include "window/Window.h"
|
||||
#include "window/Events.h"
|
||||
#include "window/Camera.h"
|
||||
@ -39,305 +42,163 @@ using namespace glm;
|
||||
#include "lighting/Lighting.h"
|
||||
#include "physics/Hitbox.h"
|
||||
#include "physics/PhysicsSolver.h"
|
||||
#include "world/World.h"
|
||||
#include "world/Level.h"
|
||||
|
||||
#include "audio/Audio.h"
|
||||
#include "audio/audioutil.h"
|
||||
#include "Assets.h"
|
||||
#include "objects/Player.h"
|
||||
|
||||
#include "declarations.h"
|
||||
#include "world_render.h"
|
||||
#include "hud_render.h"
|
||||
#include "player_control.h"
|
||||
|
||||
int WIDTH = 1280;
|
||||
int HEIGHT = 720;
|
||||
|
||||
// Save all world data to files
|
||||
void write_world(WorldFiles* wfile, Chunks* chunks){
|
||||
void write_world(World* world, Level* level){
|
||||
WorldFiles* wfile = world->wfile;
|
||||
Chunks* chunks = level->chunks;
|
||||
|
||||
for (unsigned int i = 0; i < chunks->volume; i++){
|
||||
Chunk* chunk = chunks->chunks[i];
|
||||
if (chunk == nullptr)
|
||||
if (chunk == nullptr || !chunk->isUnsaved())
|
||||
continue;
|
||||
wfile->put((const char*)chunk->voxels, chunk->x, chunk->z);
|
||||
}
|
||||
|
||||
wfile->write();
|
||||
|
||||
world->wfile->writePlayer(level->player);
|
||||
}
|
||||
|
||||
// Deleting world data from memory
|
||||
void close_world(WorldFiles* wfile, Chunks* chunks){
|
||||
delete chunks;
|
||||
delete wfile;
|
||||
void update_level(World* world, Level* level, float delta, long frame, VoxelRenderer* renderer) {
|
||||
level->playerController->update_controls(delta);
|
||||
if (Events::_cursor_locked)
|
||||
level->playerController->update_interaction();
|
||||
|
||||
vec3 position = level->player->hitbox->position;
|
||||
level->chunks->setCenter(world->wfile, position.x, position.z);
|
||||
}
|
||||
|
||||
#define CROUCH_SPEED_MUL 0.25f
|
||||
#define CROUCH_SHIFT_Y -0.2f
|
||||
#define RUN_SPEED_MUL 1.5f
|
||||
#define CROUCH_ZOOM 0.9f
|
||||
#define RUN_ZOOM 1.1f
|
||||
#define C_ZOOM 0.1f
|
||||
#define ZOOM_SPEED 16.0f
|
||||
#define DEFAULT_AIR_DAMPING 0.1f
|
||||
#define PLAYER_NOT_ONGROUND_DAMPING 10.0f
|
||||
#define CAMERA_SHAKING_OFFSET 0.025f
|
||||
#define CAMERA_SHAKING_OFFSET_Y 0.031f
|
||||
#define CAMERA_SHAKING_SPEED 1.6f
|
||||
#define CAMERA_SHAKING_DELTA_K 10.0f
|
||||
#define FLIGHT_SPEED_MUL 5.0f
|
||||
#define JUMP_FORCE 7.0f
|
||||
Level* load_level(World* world, Player* player) {
|
||||
Level* level = new Level(world, player, new Chunks(56, 56, 0, 0), new PhysicsSolver(vec3(0, -19.6f, 0)));
|
||||
world->wfile->readPlayer(player);
|
||||
|
||||
void update_controls(PhysicsSolver* physics,
|
||||
Chunks* chunks,
|
||||
Player* player,
|
||||
float delta){
|
||||
|
||||
if (Events::jpressed(GLFW_KEY_TAB)){
|
||||
Events::toogleCursor();
|
||||
}
|
||||
|
||||
for (int i = 1; i < 10; i++){
|
||||
if (Events::jpressed(GLFW_KEY_0+i)){
|
||||
player->choosenBlock = i;
|
||||
}
|
||||
}
|
||||
|
||||
// Controls
|
||||
Camera* camera = player->camera;
|
||||
Hitbox* hitbox = player->hitbox;
|
||||
bool sprint = Events::pressed(GLFW_KEY_LEFT_CONTROL);
|
||||
bool shift = Events::pressed(GLFW_KEY_LEFT_SHIFT) && hitbox->grounded && !sprint;
|
||||
bool zoom = Events::pressed(GLFW_KEY_C);
|
||||
|
||||
float speed = player->speed;
|
||||
if (player->flight){
|
||||
speed *= FLIGHT_SPEED_MUL;
|
||||
}
|
||||
int substeps = (int)(delta * 1000);
|
||||
substeps = (substeps <= 0 ? 1 : (substeps > 100 ? 100 : substeps));
|
||||
physics->step(chunks, hitbox, delta, substeps, shift, player->flight ? 0.0f : 1.0f);
|
||||
camera->position.x = hitbox->position.x;
|
||||
camera->position.y = hitbox->position.y + 0.5f;
|
||||
camera->position.z = hitbox->position.z;
|
||||
|
||||
if (player->flight && hitbox->grounded)
|
||||
player->flight = false;
|
||||
// Camera shaking
|
||||
player->interpVel = player->interpVel * (1.0f - delta * 5) + hitbox->velocity * delta * 0.1f;
|
||||
if (hitbox->grounded && player->interpVel.y < 0.0f){
|
||||
player->interpVel.y *= -30.0f;
|
||||
}
|
||||
float factor = hitbox->grounded ? length(vec2(hitbox->velocity.x, hitbox->velocity.z)) : 0.0f;
|
||||
player->cameraShakingTimer += delta * factor * CAMERA_SHAKING_SPEED;
|
||||
float shakeTimer = player->cameraShakingTimer;
|
||||
player->cameraShaking = player->cameraShaking * (1.0f - delta * CAMERA_SHAKING_DELTA_K) + factor * delta * CAMERA_SHAKING_DELTA_K;
|
||||
camera->position += camera->right * sin(shakeTimer) * CAMERA_SHAKING_OFFSET * player->cameraShaking;
|
||||
camera->position += camera->up * abs(cos(shakeTimer)) * CAMERA_SHAKING_OFFSET_Y * player->cameraShaking;
|
||||
camera->position -= min(player->interpVel * 0.05f, 1.0f);
|
||||
|
||||
if (Events::jpressed(GLFW_KEY_F)){
|
||||
player->flight = !player->flight;
|
||||
if (player->flight){
|
||||
hitbox->velocity.y += 1;
|
||||
hitbox->grounded = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Field of view manipulations
|
||||
float dt = min(1.0f, delta * ZOOM_SPEED);
|
||||
if (dt > 1.0f)
|
||||
dt = 1.0f;
|
||||
float zoomValue = 1.0f;
|
||||
if (shift){
|
||||
speed *= CROUCH_SPEED_MUL;
|
||||
camera->position.y += CROUCH_SHIFT_Y;
|
||||
zoomValue = CROUCH_ZOOM;
|
||||
} else if (sprint){
|
||||
speed *= RUN_SPEED_MUL;
|
||||
zoomValue = RUN_ZOOM;
|
||||
}
|
||||
if (zoom)
|
||||
zoomValue *= C_ZOOM;
|
||||
camera->zoom = zoomValue * dt + camera->zoom * (1.0f - dt);
|
||||
|
||||
if (Events::pressed(GLFW_KEY_SPACE) && hitbox->grounded){
|
||||
hitbox->velocity.y = JUMP_FORCE;
|
||||
}
|
||||
|
||||
vec3 dir(0,0,0);
|
||||
if (Events::pressed(GLFW_KEY_W)){
|
||||
dir.x += camera->dir.x;
|
||||
dir.z += camera->dir.z;
|
||||
}
|
||||
if (Events::pressed(GLFW_KEY_S)){
|
||||
dir.x -= camera->dir.x;
|
||||
dir.z -= camera->dir.z;
|
||||
}
|
||||
if (Events::pressed(GLFW_KEY_D)){
|
||||
dir.x += camera->right.x;
|
||||
dir.z += camera->right.z;
|
||||
}
|
||||
if (Events::pressed(GLFW_KEY_A)){
|
||||
dir.x -= camera->right.x;
|
||||
dir.z -= camera->right.z;
|
||||
}
|
||||
|
||||
hitbox->linear_damping = DEFAULT_AIR_DAMPING;
|
||||
if (player->flight){
|
||||
hitbox->linear_damping = PLAYER_NOT_ONGROUND_DAMPING;
|
||||
hitbox->velocity.y *= 1.0f - delta * 9;
|
||||
if (Events::pressed(GLFW_KEY_SPACE)){
|
||||
hitbox->velocity.y += speed * delta * 9;
|
||||
}
|
||||
if (Events::pressed(GLFW_KEY_LEFT_SHIFT)){
|
||||
hitbox->velocity.y -= speed * delta * 9;
|
||||
}
|
||||
}
|
||||
if (length(dir) > 0.0f){
|
||||
dir = normalize(dir);
|
||||
|
||||
if (!hitbox->grounded)
|
||||
hitbox->linear_damping = PLAYER_NOT_ONGROUND_DAMPING;
|
||||
|
||||
hitbox->velocity.x += dir.x * speed * delta * 9;
|
||||
hitbox->velocity.z += dir.z * speed * delta * 9;
|
||||
}
|
||||
|
||||
if (Events::_cursor_locked){
|
||||
player->camY += -Events::deltaY / Window::height * 2;
|
||||
player->camX += -Events::deltaX / Window::height * 2;
|
||||
|
||||
if (player->camY < -radians(89.0f)){
|
||||
player->camY = -radians(89.0f);
|
||||
}
|
||||
if (player->camY > radians(89.0f)){
|
||||
player->camY = radians(89.0f);
|
||||
}
|
||||
|
||||
camera->rotation = mat4(1.0f);
|
||||
camera->rotate(player->camY, player->camX, 0);
|
||||
}
|
||||
camera->rotation = mat4(1.0f);
|
||||
camera->rotate(player->camY, player->camX, 0);
|
||||
return level;
|
||||
}
|
||||
|
||||
void update_interaction(Chunks* chunks, PhysicsSolver* physics, Player* player, Lighting* lighting){
|
||||
Camera* camera = player->camera;
|
||||
vec3 end;
|
||||
vec3 norm;
|
||||
vec3 iend;
|
||||
voxel* vox = chunks->rayCast(camera->position, camera->front, 10.0f, end, norm, iend);
|
||||
if (vox != nullptr){
|
||||
lineBatch->box(iend.x+0.5f, iend.y+0.5f, iend.z+0.5f, 1.005f,1.005f,1.005f, 0,0,0,0.5f);
|
||||
|
||||
if (Events::jclicked(GLFW_MOUSE_BUTTON_1)){
|
||||
int x = (int)iend.x;
|
||||
int y = (int)iend.y;
|
||||
int z = (int)iend.z;
|
||||
chunks->set(x,y,z, 0);
|
||||
lighting->onBlockSet(x,y,z,0);
|
||||
}
|
||||
if (Events::jclicked(GLFW_MOUSE_BUTTON_2)){
|
||||
int x = (int)(iend.x)+(int)(norm.x);
|
||||
int y = (int)(iend.y)+(int)(norm.y);
|
||||
int z = (int)(iend.z)+(int)(norm.z);
|
||||
if (!physics->isBlockInside(x,y,z, player->hitbox)){
|
||||
chunks->set(x, y, z, player->choosenBlock);
|
||||
lighting->onBlockSet(x,y,z, player->choosenBlock);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int WIDTH = 1280;
|
||||
int HEIGHT = 720;
|
||||
|
||||
#define GRAVITY 19.6f
|
||||
#define DEFAULT_PLAYER_SPEED 4.0f
|
||||
|
||||
vec3 spawnpoint(-320, 255, 32);
|
||||
|
||||
|
||||
int main() {
|
||||
setup_definitions();
|
||||
|
||||
Window::initialize(WIDTH, HEIGHT, "VoxelEngine Part-11");
|
||||
int initialize(Assets*& assets) {
|
||||
Window::initialize(WIDTH, HEIGHT, "VoxelEngine-Cpp v12");
|
||||
Events::initialize();
|
||||
|
||||
assets = new Assets();
|
||||
std::cout << "-- loading assets" << std::endl;
|
||||
Assets* assets = new Assets();
|
||||
int result = initialize_assets(assets);
|
||||
if (result){
|
||||
delete assets;
|
||||
Window::terminate();
|
||||
return result;
|
||||
}
|
||||
std::cout << "-- loading world" << std::endl;
|
||||
|
||||
Camera *camera = new Camera(spawnpoint, radians(90.0f));
|
||||
WorldFiles *wfile = new WorldFiles("world/", REGION_VOL * (CHUNK_VOL * 2 + 8));
|
||||
Chunks *chunks = new Chunks(34,1,34, 0,0,0);
|
||||
|
||||
|
||||
Player* player = new Player(vec3(camera->position), DEFAULT_PLAYER_SPEED, camera);
|
||||
wfile->readPlayer(player);
|
||||
camera->rotation = mat4(1.0f);
|
||||
camera->rotate(player->camY, player->camX, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mainloop(Level* level, Assets* assets) {
|
||||
Camera* camera = level->player->camera;
|
||||
std::cout << "-- preparing systems" << std::endl;
|
||||
|
||||
VoxelRenderer renderer(1024*1024);
|
||||
PhysicsSolver physics(vec3(0,-GRAVITY,0));
|
||||
Lighting lighting(chunks);
|
||||
|
||||
init_renderer();
|
||||
|
||||
ChunksController chunksController(chunks, &lighting);
|
||||
|
||||
World* world = level->world;
|
||||
WorldRenderer worldRenderer(level, assets);
|
||||
HudRenderer hud;
|
||||
long frame = 0;
|
||||
float lastTime = glfwGetTime();
|
||||
float delta = 0.0f;
|
||||
|
||||
long frame = 0;
|
||||
|
||||
bool occlusion = false;
|
||||
|
||||
glfwSwapInterval(1);
|
||||
|
||||
std::cout << "-- initializing finished" << std::endl;
|
||||
|
||||
bool occlusion = true;
|
||||
bool devdata = false;
|
||||
Window::swapInterval(0);
|
||||
while (!Window::isShouldClose()){
|
||||
frame++;
|
||||
float currentTime = glfwGetTime();
|
||||
delta = currentTime - lastTime;
|
||||
lastTime = currentTime;
|
||||
|
||||
int fps = 1 / delta;
|
||||
if (Events::jpressed(GLFW_KEY_ESCAPE)){
|
||||
Window::setShouldClose(true);
|
||||
}
|
||||
|
||||
if (Events::jpressed(GLFW_KEY_TAB)){
|
||||
Events::toggleCursor();
|
||||
}
|
||||
if (Events::jpressed(GLFW_KEY_O)){
|
||||
occlusion = !occlusion;
|
||||
}
|
||||
if (Events::jpressed(GLFW_KEY_F3)){
|
||||
devdata = !devdata;
|
||||
}
|
||||
if (Events::jpressed(GLFW_KEY_F5)){
|
||||
for (unsigned i = 0; i < level->chunks->volume; i++) {
|
||||
Chunk* chunk = level->chunks->chunks[i];
|
||||
if (chunk != nullptr && chunk->isReady()){
|
||||
chunk->setModified(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
update_controls(&physics, chunks, player, delta);
|
||||
update_interaction(chunks, &physics, player, &lighting);
|
||||
|
||||
chunks->setCenter(wfile, camera->position.x,0,camera->position.z);
|
||||
chunksController._buildMeshes(&renderer, frame);
|
||||
|
||||
int freeLoaders = chunksController.countFreeLoaders();
|
||||
update_level(world, level, delta, frame, worldRenderer.renderer);
|
||||
int freeLoaders = level->chunksController->countFreeLoaders();
|
||||
for (int i = 0; i < freeLoaders; i++)
|
||||
chunksController.loadVisible(wfile);
|
||||
level->chunksController->_buildMeshes(worldRenderer.renderer, frame);
|
||||
freeLoaders = level->chunksController->countFreeLoaders();
|
||||
for (int i = 0; i < freeLoaders; i++)
|
||||
level->chunksController->calculateLights();
|
||||
freeLoaders = level->chunksController->countFreeLoaders();
|
||||
for (int i = 0; i < freeLoaders; i++)
|
||||
level->chunksController->loadVisible(world->wfile);
|
||||
|
||||
draw_world(camera, assets, chunks, occlusion);
|
||||
worldRenderer.draw(world, camera, occlusion);
|
||||
hud.draw(level, assets);
|
||||
if (devdata) {
|
||||
hud.drawDebug(level, assets, fps, occlusion);
|
||||
}
|
||||
|
||||
Window::swapBuffers();
|
||||
Events::pullEvents();
|
||||
}
|
||||
std::cout << "-- saving world" << std::endl;
|
||||
}
|
||||
|
||||
wfile->writePlayer(player);
|
||||
write_world(wfile, chunks);
|
||||
close_world(wfile, chunks);
|
||||
int main() {
|
||||
setup_definitions();
|
||||
|
||||
Assets* assets;
|
||||
int status = initialize(assets);
|
||||
if (status) return status;
|
||||
|
||||
std::cout << "-- loading world" << std::endl;
|
||||
vec3 playerPosition = vec3(0,150,-10);
|
||||
Camera* camera = new Camera(playerPosition, radians(90.0f));
|
||||
World* world = new World("world-1", "world/", 42);
|
||||
Player* player = new Player(playerPosition, 4.0f, camera);
|
||||
Level* level = load_level(world, player);
|
||||
|
||||
std::cout << "-- initializing finished" << std::endl;
|
||||
|
||||
Audio::initialize();
|
||||
mainloop(level, assets);
|
||||
Audio::finalize();
|
||||
|
||||
std::cout << "-- saving world" << std::endl;
|
||||
write_world(world, level);
|
||||
|
||||
delete level;
|
||||
delete world;
|
||||
|
||||
std::cout << "-- shutting down" << std::endl;
|
||||
|
||||
delete assets;
|
||||
finalize_renderer();
|
||||
Events::finalize();
|
||||
Window::terminate();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -1,6 +1,9 @@
|
||||
#ifndef VOXELS_BLOCK_H_
|
||||
#define VOXELS_BLOCK_H_
|
||||
|
||||
#define BLOCK_MODEL_CUBE 1
|
||||
#define BLOCK_MODEL_GRASS 2
|
||||
|
||||
class Block {
|
||||
public:
|
||||
static Block* blocks[256];
|
||||
@ -14,6 +17,8 @@ public:
|
||||
bool skyLightPassing = false;
|
||||
bool obstacle = true;
|
||||
bool selectable = true;
|
||||
bool breakable = true;
|
||||
unsigned char model = 1;
|
||||
|
||||
Block(unsigned int id, int texture);
|
||||
};
|
||||
|
||||
@ -2,12 +2,12 @@
|
||||
#include "voxel.h"
|
||||
#include "../lighting/Lightmap.h"
|
||||
|
||||
|
||||
Chunk::Chunk(int xpos, int ypos, int zpos) : x(xpos), y(ypos), z(zpos){
|
||||
Chunk::Chunk(int xpos, int zpos) : x(xpos), z(zpos){
|
||||
voxels = new voxel[CHUNK_VOL];
|
||||
for (unsigned int i = 0; i < CHUNK_VOL; i++)
|
||||
voxels[i].id = 1;
|
||||
lightmap = new Lightmap();
|
||||
renderData.vertices = nullptr;
|
||||
}
|
||||
|
||||
Chunk::~Chunk(){
|
||||
@ -29,7 +29,7 @@ bool Chunk::isEmpty(){
|
||||
}
|
||||
|
||||
Chunk* Chunk::clone() const {
|
||||
Chunk* other = new Chunk(x,y,z);
|
||||
Chunk* other = new Chunk(x,z);
|
||||
for (int i = 0; i < CHUNK_VOL; i++)
|
||||
other->voxels[i] = voxels[i];
|
||||
other->lightmap->set(lightmap);
|
||||
|
||||
@ -1,25 +1,42 @@
|
||||
#ifndef VOXELS_CHUNK_H_
|
||||
#define VOXELS_CHUNK_H_
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#define CHUNK_W 16
|
||||
#define CHUNK_H 256
|
||||
#define CHUNK_D 16
|
||||
#define CHUNK_VOL (CHUNK_W * CHUNK_H * CHUNK_D)
|
||||
|
||||
#define CHUNK_MODIFIED 0x1
|
||||
#define CHUNK_READY 0x2
|
||||
#define CHUNK_LOADED 0x4
|
||||
#define CHUNK_LIGHTED 0x8
|
||||
#define CHUNK_UNSAVED 0x10
|
||||
|
||||
class voxel;
|
||||
class Lightmap;
|
||||
|
||||
struct RenderData {
|
||||
float* vertices;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
#define BIT_ON(f,i) do{f|= i;} while(0)
|
||||
#define BIT_OFF(f,i) do{f&=~(i);} while(0)
|
||||
#define BITSET(f,i,s) if (s) BIT_ON(f,i); else BIT_OFF(f,i);
|
||||
|
||||
class Chunk {
|
||||
public:
|
||||
int x,y,z;
|
||||
int x, z;
|
||||
voxel* voxels;
|
||||
Lightmap* lightmap;
|
||||
bool modified = true;
|
||||
bool ready = false;
|
||||
bool loaded = false;
|
||||
int flags = 0;
|
||||
int surrounding = 0;
|
||||
int references = 1;
|
||||
Chunk(int x, int y, int z);
|
||||
RenderData renderData;
|
||||
|
||||
Chunk(int x, int z);
|
||||
~Chunk();
|
||||
|
||||
bool isEmpty();
|
||||
@ -27,6 +44,28 @@ public:
|
||||
Chunk* clone() const;
|
||||
void incref();
|
||||
void decref();
|
||||
|
||||
// flags getters/setters below
|
||||
|
||||
inline bool isUnsaved() const {return flags & CHUNK_UNSAVED;}
|
||||
|
||||
inline bool isModified() const {return flags & CHUNK_MODIFIED;}
|
||||
|
||||
inline bool isLighted() const {return flags & CHUNK_LIGHTED;}
|
||||
|
||||
inline bool isLoaded() const {return flags & CHUNK_LOADED;}
|
||||
|
||||
inline bool isReady() const {return flags & CHUNK_READY;}
|
||||
|
||||
inline void setUnsaved(bool flag) {BITSET(flags, CHUNK_UNSAVED, flag);}
|
||||
|
||||
inline void setModified(bool flag) {BITSET(flags, CHUNK_MODIFIED, flag);}
|
||||
|
||||
inline void setLoaded(bool flag) {BITSET(flags, CHUNK_LOADED, flag);}
|
||||
|
||||
inline void setLighted(bool flag) {BITSET(flags, CHUNK_LIGHTED, flag);}
|
||||
|
||||
inline void setReady(bool flag) {BITSET(flags, CHUNK_READY, flag);}
|
||||
};
|
||||
|
||||
#endif /* VOXELS_CHUNK_H_ */
|
||||
|
||||
@ -11,8 +11,8 @@
|
||||
#include <math.h>
|
||||
#include <limits.h>
|
||||
|
||||
Chunks::Chunks(int w, int h, int d, int ox, int oy, int oz) : w(w), h(h), d(d), ox(ox), oy(oy), oz(oz){
|
||||
volume = w*h*d;
|
||||
Chunks::Chunks(int w, int d, int ox, int oz) : w(w), d(d), ox(ox), oz(oz){
|
||||
volume = w*d;
|
||||
chunks = new Chunk*[volume];
|
||||
chunksSecond = new Chunk*[volume];
|
||||
|
||||
@ -23,6 +23,7 @@ Chunks::Chunks(int w, int h, int d, int ox, int oy, int oz) : w(w), h(h), d(d),
|
||||
chunks[i] = nullptr;
|
||||
meshes[i] = nullptr;
|
||||
}
|
||||
chunksCount = 0;
|
||||
}
|
||||
|
||||
Chunks::~Chunks(){
|
||||
@ -35,7 +36,6 @@ Chunks::~Chunks(){
|
||||
|
||||
voxel* Chunks::get(int x, int y, int z){
|
||||
x -= ox * CHUNK_W;
|
||||
y -= oy * CHUNK_H;
|
||||
z -= oz * CHUNK_D;
|
||||
int cx = x / CHUNK_W;
|
||||
int cy = y / CHUNK_H;
|
||||
@ -43,7 +43,7 @@ voxel* Chunks::get(int x, int y, int z){
|
||||
if (x < 0) cx--;
|
||||
if (y < 0) cy--;
|
||||
if (z < 0) cz--;
|
||||
if (cx < 0 || cy < 0 || cz < 0 || cx >= w || cy >= h || cz >= d)
|
||||
if (cx < 0 || cy < 0 || cz < 0 || cx >= w || cy >= 1 || cz >= d)
|
||||
return nullptr;
|
||||
Chunk* chunk = chunks[(cy * d + cz) * w + cx];
|
||||
if (chunk == nullptr)
|
||||
@ -63,7 +63,6 @@ bool Chunks::isObstacle(int x, int y, int z){
|
||||
|
||||
unsigned char Chunks::getLight(int x, int y, int z, int channel){
|
||||
x -= ox * CHUNK_W;
|
||||
y -= oy * CHUNK_H;
|
||||
z -= oz * CHUNK_D;
|
||||
int cx = x / CHUNK_W;
|
||||
int cy = y / CHUNK_H;
|
||||
@ -71,7 +70,7 @@ unsigned char Chunks::getLight(int x, int y, int z, int channel){
|
||||
if (x < 0) cx--;
|
||||
if (y < 0) cy--;
|
||||
if (z < 0) cz--;
|
||||
if (cx < 0 || cy < 0 || cz < 0 || cx >= w || cy >= h || cz >= d)
|
||||
if (cx < 0 || cy < 0 || cz < 0 || cx >= w || cy >= 1 || cz >= d)
|
||||
return 0;
|
||||
Chunk* chunk = chunks[(cy * d + cz) * w + cx];
|
||||
if (chunk == nullptr)
|
||||
@ -84,7 +83,6 @@ unsigned char Chunks::getLight(int x, int y, int z, int channel){
|
||||
|
||||
unsigned short Chunks::getLight(int x, int y, int z){
|
||||
x -= ox * CHUNK_W;
|
||||
y -= oy * CHUNK_H;
|
||||
z -= oz * CHUNK_D;
|
||||
int cx = x / CHUNK_W;
|
||||
int cy = y / CHUNK_H;
|
||||
@ -92,7 +90,7 @@ unsigned short Chunks::getLight(int x, int y, int z){
|
||||
if (x < 0) cx--;
|
||||
if (y < 0) cy--;
|
||||
if (z < 0) cz--;
|
||||
if (cx < 0 || cy < 0 || cz < 0 || cx >= w || cy >= h || cz >= d)
|
||||
if (cx < 0 || cy < 0 || cz < 0 || cx >= w || cy >= 1 || cz >= d)
|
||||
return 0;
|
||||
Chunk* chunk = chunks[(cy * d + cz) * w + cx];
|
||||
if (chunk == nullptr)
|
||||
@ -105,7 +103,6 @@ unsigned short Chunks::getLight(int x, int y, int z){
|
||||
|
||||
Chunk* Chunks::getChunkByVoxel(int x, int y, int z){
|
||||
x -= ox * CHUNK_W;
|
||||
y -= oy * CHUNK_H;
|
||||
z -= oz * CHUNK_D;
|
||||
int cx = x / CHUNK_W;
|
||||
int cy = y / CHUNK_H;
|
||||
@ -113,48 +110,44 @@ Chunk* Chunks::getChunkByVoxel(int x, int y, int z){
|
||||
if (x < 0) cx--;
|
||||
if (y < 0) cy--;
|
||||
if (z < 0) cz--;
|
||||
if (cx < 0 || cy < 0 || cz < 0 || cx >= w || cy >= h || cz >= d)
|
||||
if (cx < 0 || cy < 0 || cz < 0 || cx >= w || cy >= 1 || cz >= d)
|
||||
return nullptr;
|
||||
return chunks[(cy * d + cz) * w + cx];
|
||||
}
|
||||
|
||||
Chunk* Chunks::getChunk(int x, int y, int z){
|
||||
Chunk* Chunks::getChunk(int x, int z){
|
||||
x -= ox;
|
||||
y -= oy;
|
||||
z -= oz;
|
||||
if (x < 0 || y < 0 || z < 0 || x >= w || y >= h || z >= d)
|
||||
if (x < 0 || z < 0 || x >= w || z >= d)
|
||||
return nullptr;
|
||||
return chunks[(y * d + z) * w + x];
|
||||
return chunks[z * w + x];
|
||||
}
|
||||
|
||||
void Chunks::set(int x, int y, int z, int id){
|
||||
x -= ox * CHUNK_W;
|
||||
y -= oy * CHUNK_H;
|
||||
z -= oz * CHUNK_D;
|
||||
int cx = x / CHUNK_W;
|
||||
int cy = y / CHUNK_H;
|
||||
if (y < 0 || y >= CHUNK_H)
|
||||
return;
|
||||
int cz = z / CHUNK_D;
|
||||
if (x < 0) cx--;
|
||||
if (y < 0) cy--;
|
||||
if (z < 0) cz--;
|
||||
if (cx < 0 || cy < 0 || cz < 0 || cx >= w || cy >= h || cz >= d)
|
||||
if (cx < 0 || cz < 0 || cx >= w || cz >= d)
|
||||
return;
|
||||
Chunk* chunk = chunks[(cy * d + cz) * w + cx];
|
||||
Chunk* chunk = chunks[cz * w + cx];
|
||||
if (chunk == nullptr)
|
||||
return;
|
||||
int lx = x - cx * CHUNK_W;
|
||||
int ly = y - cy * CHUNK_H;
|
||||
int lz = z - cz * CHUNK_D;
|
||||
chunk->voxels[(ly * CHUNK_D + lz) * CHUNK_W + lx].id = id;
|
||||
chunk->modified = true;
|
||||
chunk->voxels[(y * CHUNK_D + lz) * CHUNK_W + lx].id = id;
|
||||
chunk->setUnsaved(true);
|
||||
chunk->setModified(true);
|
||||
|
||||
if (lx == 0 && (chunk = getChunk(cx+ox-1, cy+oy, cz+oz))) chunk->modified = true;
|
||||
if (ly == 0 && (chunk = getChunk(cx+ox, cy+oy-1, cz+oz))) chunk->modified = true;
|
||||
if (lz == 0 && (chunk = getChunk(cx+ox, cy+oy, cz+oz-1))) chunk->modified = true;
|
||||
if (lx == 0 && (chunk = getChunk(cx+ox-1, cz+oz))) chunk->setModified(true);
|
||||
if (lz == 0 && (chunk = getChunk(cx+ox, cz+oz-1))) chunk->setModified(true);
|
||||
|
||||
if (lx == CHUNK_W-1 && (chunk = getChunk(cx+ox+1, cy+oy, cz+oz))) chunk->modified = true;
|
||||
if (ly == CHUNK_H-1 && (chunk = getChunk(cx+ox, cy+oy+1, cz+oz))) chunk->modified = true;
|
||||
if (lz == CHUNK_D-1 && (chunk = getChunk(cx+ox, cy+oy, cz+oz+1))) chunk->modified = true;
|
||||
if (lx == CHUNK_W-1 && (chunk = getChunk(cx+ox+1, cz+oz))) chunk->setModified(true);
|
||||
if (lz == CHUNK_D-1 && (chunk = getChunk(cx+ox, cz+oz+1))) chunk->setModified(true);
|
||||
}
|
||||
|
||||
voxel* Chunks::rayCast(vec3 a, vec3 dir, float maxDist, vec3& end, vec3& norm, vec3& iend) {
|
||||
@ -245,47 +238,42 @@ voxel* Chunks::rayCast(vec3 a, vec3 dir, float maxDist, vec3& end, vec3& norm, v
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Chunks::setCenter(WorldFiles* worldFiles, int x, int y, int z) {
|
||||
void Chunks::setCenter(WorldFiles* worldFiles, int x, int z) {
|
||||
int cx = x / CHUNK_W;
|
||||
int cy = y / CHUNK_H;
|
||||
int cz = z / CHUNK_D;
|
||||
cx -= ox;
|
||||
cy -= oy;
|
||||
cz -= oz;
|
||||
if (x < 0) cx--;
|
||||
if (y < 0) cy--;
|
||||
if (z < 0) cz--;
|
||||
cx -= w/2;
|
||||
cy -= h/2;
|
||||
cz -= d/2;
|
||||
if (cx != 0 || cy != 0 || cz != 0)
|
||||
translate(worldFiles, cx,cy,cz);
|
||||
if (cx | cz) {
|
||||
translate(worldFiles, cx,cz);
|
||||
}
|
||||
}
|
||||
|
||||
void Chunks::translate(WorldFiles* worldFiles, int dx, int dy, int dz){
|
||||
void Chunks::translate(WorldFiles* worldFiles, int dx, int dz){
|
||||
for (unsigned int i = 0; i < volume; i++){
|
||||
chunksSecond[i] = nullptr;
|
||||
meshesSecond[i] = nullptr;
|
||||
}
|
||||
for (unsigned int y = 0; y < h; y++){
|
||||
for (unsigned int z = 0; z < d; z++){
|
||||
for (unsigned int x = 0; x < w; x++){
|
||||
Chunk* chunk = chunks[(y * d + z) * w + x];
|
||||
int nx = x - dx;
|
||||
int ny = y - dy;
|
||||
int nz = z - dz;
|
||||
if (chunk == nullptr)
|
||||
continue;
|
||||
Mesh* mesh = meshes[(y * d + z) * w + x];
|
||||
if (nx < 0 || ny < 0 || nz < 0 || nx >= w || ny >= h || nz >= d){
|
||||
worldFiles->put((const char*)chunk->voxels, chunk->x, chunk->z);
|
||||
chunk->decref();
|
||||
delete mesh;
|
||||
continue;
|
||||
}
|
||||
meshesSecond[(ny * d + nz) * w + nx] = mesh;
|
||||
chunksSecond[(ny * d + nz) * w + nx] = chunk;
|
||||
for (int z = 0; z < d; z++){
|
||||
for (int x = 0; x < w; x++){
|
||||
Chunk* chunk = chunks[z * w + x];
|
||||
int nx = x - dx;
|
||||
int nz = z - dz;
|
||||
if (chunk == nullptr)
|
||||
continue;
|
||||
Mesh* mesh = meshes[z * w + x];
|
||||
if (nx < 0 || nz < 0 || nx >= w || nz >= d){
|
||||
worldFiles->put((const char*)chunk->voxels, chunk->x, chunk->z);
|
||||
chunk->decref();
|
||||
delete mesh;
|
||||
chunksCount--;
|
||||
continue;
|
||||
}
|
||||
meshesSecond[nz * w + nx] = mesh;
|
||||
chunksSecond[nz * w + nx] = chunk;
|
||||
}
|
||||
}
|
||||
Chunk** ctemp = chunks;
|
||||
@ -297,26 +285,23 @@ void Chunks::translate(WorldFiles* worldFiles, int dx, int dy, int dz){
|
||||
meshesSecond = mtemp;
|
||||
|
||||
ox += dx;
|
||||
oy += dy;
|
||||
oz += dz;
|
||||
}
|
||||
|
||||
void Chunks::_setOffset(int x, int y, int z){
|
||||
void Chunks::_setOffset(int x, int z){
|
||||
ox = x;
|
||||
oy = y;
|
||||
oz = z;
|
||||
}
|
||||
|
||||
bool Chunks::putChunk(Chunk* chunk) {
|
||||
int x = chunk->x;
|
||||
int y = chunk->y;
|
||||
int z = chunk->z;
|
||||
x -= ox;
|
||||
y -= oy;
|
||||
z -= oz;
|
||||
if (x < 0 || y < 0 || z < 0 || x >= w || y >= h || z >= d)
|
||||
if (x < 0 || z < 0 || x >= w || z >= d)
|
||||
return false;
|
||||
chunks[(y * d + z) * w + x] = chunk;
|
||||
chunks[z * w + x] = chunk;
|
||||
chunksCount++;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -329,4 +314,5 @@ void Chunks::clear(bool freeMemory){
|
||||
chunks[i] = nullptr;
|
||||
meshes[i] = nullptr;
|
||||
}
|
||||
chunksCount = 0;
|
||||
}
|
||||
|
||||
@ -20,15 +20,16 @@ public:
|
||||
Mesh** meshes;
|
||||
Mesh** meshesSecond;
|
||||
size_t volume;
|
||||
unsigned int w,h,d;
|
||||
int ox,oy,oz;
|
||||
size_t chunksCount;
|
||||
int w,d;
|
||||
int ox,oz;
|
||||
|
||||
Chunks(int w, int h, int d, int ox, int oy, int oz);
|
||||
Chunks(int w, int d, int ox, int oz);
|
||||
~Chunks();
|
||||
|
||||
bool putChunk(Chunk* chunk);
|
||||
|
||||
Chunk* getChunk(int x, int y, int z);
|
||||
Chunk* getChunk(int x, int z);
|
||||
Chunk* getChunkByVoxel(int x, int y, int z);
|
||||
voxel* get(int x, int y, int z);
|
||||
unsigned short getLight(int x, int y, int z);
|
||||
@ -39,10 +40,10 @@ public:
|
||||
bool isObstacle(int x, int y, int z);
|
||||
|
||||
// does not move chunks inside
|
||||
void _setOffset(int x, int y, int z);
|
||||
void _setOffset(int x, int z);
|
||||
|
||||
void setCenter(WorldFiles* worldFiles, int x, int y, int z);
|
||||
void translate(WorldFiles* worldFiles, int x, int y, int z);
|
||||
void setCenter(WorldFiles* worldFiles, int x, int z);
|
||||
void translate(WorldFiles* worldFiles, int x, int z);
|
||||
|
||||
void clear(bool freeMemory);
|
||||
};
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
#include "../files/WorldFiles.h"
|
||||
#include "ChunksLoader.h"
|
||||
#include <iostream>
|
||||
#include <limits.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#define _WIN32_WINNT 0x0501
|
||||
@ -19,13 +20,13 @@
|
||||
#define MIN_SURROUNDING 9
|
||||
|
||||
|
||||
ChunksController::ChunksController(Chunks* chunks, Lighting* lighting) : chunks(chunks), lighting(lighting){
|
||||
loadersCount = std::thread::hardware_concurrency() - 1;
|
||||
ChunksController::ChunksController(World* world, Chunks* chunks, Lighting* lighting) : chunks(chunks), lighting(lighting){
|
||||
loadersCount = std::thread::hardware_concurrency() * 2 - 1;
|
||||
if (loadersCount <= 0)
|
||||
loadersCount = 1;
|
||||
loaders = new ChunksLoader*[loadersCount];
|
||||
for (int i = 0; i < loadersCount; i++){
|
||||
loaders[i] = new ChunksLoader();
|
||||
loaders[i] = new ChunksLoader(world);
|
||||
}
|
||||
std::cout << "created " << loadersCount << " loaders" << std::endl;
|
||||
}
|
||||
@ -47,50 +48,78 @@ int ChunksController::countFreeLoaders(){
|
||||
|
||||
bool ChunksController::loadVisible(WorldFiles* worldFiles){
|
||||
const int w = chunks->w;
|
||||
const int h = chunks->h;
|
||||
const int d = chunks->d;
|
||||
const int ox = chunks->ox;
|
||||
const int oy = chunks->oy;
|
||||
const int oz = chunks->oz;
|
||||
int nearX = 0;
|
||||
int nearY = 0;
|
||||
int nearZ = 0;
|
||||
int minDistance = (w/2)*(w/2);
|
||||
for (int y = 0; y < h; y++){
|
||||
for (int z = 2; z < d-2; z++){
|
||||
for (int x = 2; x < w-2; x++){
|
||||
int index = (y * d + z) * w + x;
|
||||
Chunk* chunk = chunks->chunks[index];
|
||||
if (chunk != nullptr){
|
||||
int surrounding = 0;
|
||||
for (int oz = -1; oz <= 1; oz++){
|
||||
for (int ox = -1; ox <= 1; ox++){
|
||||
Chunk* other = chunks->getChunk(chunk->x+ox, chunk->y, chunk->z+oz);
|
||||
if (other != nullptr && other->ready) surrounding++;
|
||||
}
|
||||
for (int z = 2; z < d-2; z++){
|
||||
for (int x = 2; x < w-2; x++){
|
||||
int index = z * w + x;
|
||||
Chunk* chunk = chunks->chunks[index];
|
||||
if (chunk != nullptr){
|
||||
int surrounding = 0;
|
||||
for (int oz = -1; oz <= 1; oz++){
|
||||
for (int ox = -1; ox <= 1; ox++){
|
||||
Chunk* other = chunks->getChunk(chunk->x+ox, chunk->z+oz);
|
||||
if (other != nullptr && other->isReady()) surrounding++;
|
||||
}
|
||||
chunk->surrounding = surrounding;
|
||||
continue;
|
||||
}
|
||||
int lx = x - w / 2;
|
||||
int ly = y - h / 2;
|
||||
int lz = z - d / 2;
|
||||
int distance = (lx * lx + ly * ly + lz * lz);
|
||||
if (distance < minDistance){
|
||||
minDistance = distance;
|
||||
nearX = x;
|
||||
nearY = y;
|
||||
nearZ = z;
|
||||
}
|
||||
chunk->surrounding = surrounding;
|
||||
continue;
|
||||
}
|
||||
int lx = x - w / 2;
|
||||
int lz = z - d / 2;
|
||||
int distance = (lx * lx + lz * lz);
|
||||
if (distance < minDistance){
|
||||
minDistance = distance;
|
||||
nearX = x;
|
||||
nearZ = z;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int index = (nearY * d + nearZ) * w + nearX;
|
||||
int index = nearZ * w + nearX;
|
||||
Chunk* chunk = chunks->chunks[index];
|
||||
if (chunk != nullptr)
|
||||
return false;
|
||||
|
||||
ChunksLoader* freeLoader = getFreeLoader();
|
||||
if (freeLoader == nullptr)
|
||||
return false;
|
||||
|
||||
chunk = new Chunk(nearX+ox, nearZ+oz);
|
||||
if (worldFiles->getChunk(chunk->x, chunk->z, (char*)chunk->voxels))
|
||||
chunk->setLoaded(true);
|
||||
|
||||
chunks->putChunk(chunk);
|
||||
|
||||
Chunk* closes[9];
|
||||
for (int i = 0; i < 9; i++)
|
||||
closes[i] = nullptr;
|
||||
for (size_t j = 0; j < chunks->volume; j++){
|
||||
Chunk* other = chunks->chunks[j];
|
||||
if (other == nullptr)
|
||||
continue;
|
||||
if (!other->isReady())
|
||||
continue;
|
||||
|
||||
int ox = other->x - chunk->x;
|
||||
int oz = other->z - chunk->z;
|
||||
|
||||
if (abs(ox) > 1 || abs(oz) > 1)
|
||||
continue;
|
||||
|
||||
ox += 1;
|
||||
oz += 1;
|
||||
closes[oz * 3 + ox] = other;
|
||||
}
|
||||
freeLoader->load(chunk, (Chunk**)closes);
|
||||
return true;
|
||||
}
|
||||
|
||||
ChunksLoader* ChunksController::getFreeLoader() {
|
||||
ChunksLoader* freeLoader = nullptr;
|
||||
for (int i = 0; i < loadersCount; i++){
|
||||
ChunksLoader* loader = loaders[i];
|
||||
@ -100,116 +129,151 @@ bool ChunksController::loadVisible(WorldFiles* worldFiles){
|
||||
freeLoader = loader;
|
||||
break;
|
||||
}
|
||||
return freeLoader;
|
||||
}
|
||||
|
||||
void ChunksController::calculateLights() {
|
||||
ChunksLoader* freeLoader = getFreeLoader();
|
||||
if (freeLoader == nullptr)
|
||||
return false;
|
||||
chunk = new Chunk(nearX+ox,nearY+oy,nearZ+oz);
|
||||
if (worldFiles->getChunk(chunk->x, chunk->z, (char*)chunk->voxels))
|
||||
chunk->loaded = true;
|
||||
|
||||
chunks->chunks[index] = chunk;
|
||||
|
||||
Chunk* closes[27];
|
||||
for (int i = 0; i < 27; i++)
|
||||
return;
|
||||
const int w = chunks->w;
|
||||
const int d = chunks->d;
|
||||
int nearX = 0;
|
||||
int nearZ = 0;
|
||||
int minDistance = INT_MAX;
|
||||
for (int z = 1; z < d-1; z++){
|
||||
for (int x = 1; x < w-1; x++){
|
||||
int index = z * w + x;
|
||||
Chunk* chunk = chunks->chunks[index];
|
||||
if (chunk == nullptr)
|
||||
continue;
|
||||
if (chunk->isLighted() || chunk->surrounding < MIN_SURROUNDING){
|
||||
continue;
|
||||
}
|
||||
int lx = x - w / 2;
|
||||
int lz = z - d / 2;
|
||||
int distance = (lx * lx + lz * lz);
|
||||
if (distance < minDistance){
|
||||
minDistance = distance;
|
||||
nearX = x;
|
||||
nearZ = z;
|
||||
}
|
||||
}
|
||||
}
|
||||
int index = nearZ * w + nearX;
|
||||
Chunk* chunk = chunks->chunks[index];
|
||||
if (chunk == nullptr)
|
||||
return;
|
||||
Chunk* closes[9];
|
||||
for (int i = 0; i < 9; i++)
|
||||
closes[i] = nullptr;
|
||||
for (size_t j = 0; j < chunks->volume; j++){
|
||||
Chunk* other = chunks->chunks[j];
|
||||
if (other == nullptr)
|
||||
continue;
|
||||
if (!other->ready)
|
||||
continue;
|
||||
|
||||
int ox = other->x - chunk->x;
|
||||
int oy = other->y - chunk->y;
|
||||
int oz = other->z - chunk->z;
|
||||
|
||||
if (abs(ox) > 1 || abs(oy) > 1 || abs(oz) > 1)
|
||||
if (abs(ox) > 1|| abs(oz) > 1)
|
||||
continue;
|
||||
|
||||
ox += 1;
|
||||
oy += 1;
|
||||
oz += 1;
|
||||
closes[(oy * 3 + oz) * 3 + ox] = other;
|
||||
closes[oz * 3 + ox] = other;
|
||||
}
|
||||
freeLoader->perform(chunk, (Chunk**)closes);
|
||||
return true;
|
||||
freeLoader->lights(chunk, (Chunk**)closes);
|
||||
}
|
||||
|
||||
bool ChunksController::_buildMeshes(VoxelRenderer* renderer, int tick) {
|
||||
const int w = chunks->w;
|
||||
const int h = chunks->h;
|
||||
const int d = chunks->d;
|
||||
|
||||
int nearX = 0;
|
||||
int nearY = 0;
|
||||
int nearZ = 0;
|
||||
int minDistance = 1000000000;
|
||||
for (int y = 0; y < h; y++){
|
||||
for (int z = 1; z < d-1; z++){
|
||||
for (int x = 1; x < w-1; x++){
|
||||
int index = (y * d + z) * w + x;
|
||||
Chunk* chunk = chunks->chunks[index];
|
||||
if (chunk == nullptr)
|
||||
continue;
|
||||
Mesh* mesh = chunks->meshes[index];
|
||||
if (mesh != nullptr && !chunk->modified)
|
||||
continue;
|
||||
if (!chunk->ready || chunk->surrounding < MIN_SURROUNDING){
|
||||
continue;
|
||||
}
|
||||
int lx = x - w / 2;
|
||||
int ly = y - h / 2;
|
||||
int lz = z - d / 2;
|
||||
int distance = (lx * lx + ly * ly + lz * lz);
|
||||
if (distance < minDistance){
|
||||
minDistance = distance;
|
||||
nearX = x;
|
||||
nearY = y;
|
||||
nearZ = z;
|
||||
}
|
||||
for (int z = 1; z < d-1; z++){
|
||||
for (int x = 1; x < w-1; x++){
|
||||
int index = z * w + x;
|
||||
Chunk* chunk = chunks->chunks[index];
|
||||
if (chunk == nullptr)
|
||||
continue;
|
||||
if (chunk->renderData.vertices > (void*)1){
|
||||
const int chunk_attrs[] = {3,2,4, 0};
|
||||
Mesh* mesh = new Mesh(chunk->renderData.vertices, chunk->renderData.size / CHUNK_VERTEX_SIZE, chunk_attrs);
|
||||
if (chunks->meshes[index])
|
||||
delete chunks->meshes[index];
|
||||
chunks->meshes[index] = mesh;
|
||||
delete[] chunk->renderData.vertices;
|
||||
chunk->renderData.vertices = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
ChunksLoader* freeLoader = getFreeLoader();
|
||||
if (freeLoader == nullptr)
|
||||
return false;
|
||||
|
||||
int index = (nearY * d + nearZ) * w + nearX;
|
||||
|
||||
|
||||
int nearX = 0;
|
||||
int nearZ = 0;
|
||||
int minDistance = INT_MAX;
|
||||
for (int z = 1; z < d-1; z++){
|
||||
for (int x = 1; x < w-1; x++){
|
||||
int index = z * w + x;
|
||||
Chunk* chunk = chunks->chunks[index];
|
||||
if (chunk == nullptr)
|
||||
continue;
|
||||
Mesh* mesh = chunks->meshes[index];
|
||||
if (mesh != nullptr && !chunk->isModified())
|
||||
continue;
|
||||
if (!chunk->isReady() || !chunk->isLighted() || chunk->surrounding < MIN_SURROUNDING){
|
||||
continue;
|
||||
}
|
||||
int lx = x - w / 2;
|
||||
int lz = z - d / 2;
|
||||
int distance = (lx * lx + lz * lz);
|
||||
if (distance < minDistance){
|
||||
minDistance = distance;
|
||||
nearX = x;
|
||||
nearZ = z;
|
||||
}
|
||||
}
|
||||
}
|
||||
int index = nearZ * w + nearX;
|
||||
Chunk* chunk = chunks->chunks[index];
|
||||
if (chunk == nullptr){
|
||||
return false;
|
||||
}
|
||||
Mesh* mesh = chunks->meshes[index];
|
||||
if (mesh == nullptr || chunk->modified){
|
||||
Chunk* closes[27];
|
||||
if (mesh != nullptr)
|
||||
delete mesh;
|
||||
if (mesh == nullptr || chunk->isModified()){
|
||||
if (chunk->renderData.vertices != nullptr) {
|
||||
return false;
|
||||
}
|
||||
Chunk* closes[9];
|
||||
if (chunk->isEmpty()){
|
||||
chunks->meshes[index] = nullptr;
|
||||
return false;
|
||||
}
|
||||
chunk->modified = false;
|
||||
for (int i = 0; i < 27; i++)
|
||||
|
||||
for (int i = 0; i < 9; i++)
|
||||
closes[i] = nullptr;
|
||||
for (size_t j = 0; j < chunks->volume; j++){
|
||||
Chunk* other = chunks->chunks[j];
|
||||
if (other == nullptr)
|
||||
continue;
|
||||
if (!other->ready)
|
||||
continue;
|
||||
|
||||
int ox = other->x - chunk->x;
|
||||
int oy = other->y - chunk->y;
|
||||
int oz = other->z - chunk->z;
|
||||
|
||||
if (abs(ox) > 1 || abs(oy) > 1 || abs(oz) > 1)
|
||||
if (abs(ox) > 1 || abs(oz) > 1)
|
||||
continue;
|
||||
|
||||
ox += 1;
|
||||
oy += 1;
|
||||
oz += 1;
|
||||
closes[(oy * 3 + oz) * 3 + ox] = other;
|
||||
if ((!other->isReady() || !other->isLighted()) && other != chunk)
|
||||
return false;
|
||||
closes[oz * 3 + ox] = other;
|
||||
}
|
||||
mesh = renderer->render(chunk, (const Chunk**)closes);
|
||||
chunks->meshes[index] = mesh;
|
||||
chunk->setModified(false);
|
||||
chunk->renderData.vertices = (float*)1;
|
||||
freeLoader->render(chunk, (Chunk**)closes);
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
#ifndef VOXELS_CHUNKSCONTROLLER_H_
|
||||
#define VOXELS_CHUNKSCONTROLLER_H_
|
||||
|
||||
class World;
|
||||
class Chunks;
|
||||
class Lighting;
|
||||
class WorldFiles;
|
||||
@ -14,11 +15,13 @@ private:
|
||||
ChunksLoader** loaders;
|
||||
int loadersCount;
|
||||
public:
|
||||
ChunksController(Chunks* chunks, Lighting* lighting);
|
||||
ChunksController(World* world, Chunks* chunks, Lighting* lighting);
|
||||
~ChunksController();
|
||||
|
||||
ChunksLoader* getFreeLoader();
|
||||
int countFreeLoaders();
|
||||
bool loadVisible(WorldFiles* worldFiles);
|
||||
void calculateLights();
|
||||
bool _buildMeshes(VoxelRenderer* renderer, int tick);
|
||||
};
|
||||
|
||||
|
||||
@ -3,65 +3,108 @@
|
||||
|
||||
#include "Chunk.h"
|
||||
#include "Chunks.h"
|
||||
#include "Block.h"
|
||||
#include "voxel.h"
|
||||
#include "../world/World.h"
|
||||
#include "WorldGenerator.h"
|
||||
#include "../lighting/Lighting.h"
|
||||
#include "../graphics/VoxelRenderer.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#define CLOSES_C 27
|
||||
#define SURROUNDINGS_C 9
|
||||
|
||||
void ChunksLoader::_thread(){
|
||||
Chunks chunks(3,3,3, -1,-1,-1);
|
||||
Chunks chunks(3, 3, -1, -1);
|
||||
Lighting lighting(&chunks);
|
||||
while (working){
|
||||
VoxelRenderer renderer;
|
||||
while (state != OFF){
|
||||
if (current == nullptr){
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
continue;
|
||||
}
|
||||
Chunk* chunk = current;
|
||||
chunks._setOffset(chunk->x-1, chunk->y-1, chunk->z-1);
|
||||
for (size_t i = 0; i < CLOSES_C; i++){
|
||||
Chunk* other = closes[i];
|
||||
chunks._setOffset(chunk->x-1, chunk->z-1);
|
||||
for (size_t i = 0; i < SURROUNDINGS_C; i++){
|
||||
Chunk* other = surroundings[i];
|
||||
if (other){
|
||||
chunks.putChunk(other);
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunk->loaded){
|
||||
WorldGenerator::generate(chunk->voxels, chunk->x, chunk->y, chunk->z);
|
||||
if (state == LOAD){
|
||||
chunks.putChunk(chunk);
|
||||
if (!chunk->isLoaded()){
|
||||
WorldGenerator::generate(chunk->voxels, chunk->x, chunk->z, world->seed);
|
||||
chunk->setUnsaved(true);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < CHUNK_VOL; i++){
|
||||
if (Block::blocks[chunk->voxels[i].id] == nullptr){
|
||||
std::cout << "corruped block detected at " << i << " of chunk " << chunk->x << "x" << chunk->z << std::endl;
|
||||
chunk->voxels[i].id = 11;
|
||||
}
|
||||
}
|
||||
lighting.prebuildSkyLight(chunk->x, chunk->z);
|
||||
}
|
||||
else if (state == LIGHTS) {
|
||||
lighting.buildSkyLight(chunk->x, chunk->z);
|
||||
lighting.onChunkLoaded(chunk->x, chunk->z);
|
||||
chunk->setLighted(true);
|
||||
}
|
||||
else if (state == RENDER){
|
||||
chunk->setModified(false);
|
||||
size_t size;
|
||||
renderer.render(chunk, (const Chunk**)(surroundings.load()), size);
|
||||
float* vertices = new float[size];
|
||||
for (size_t i = 0; i < size; i++)
|
||||
vertices[i] = renderer.buffer[i];
|
||||
chunk->renderData.vertices = vertices;
|
||||
chunk->renderData.size = size;
|
||||
}
|
||||
|
||||
chunks.putChunk(chunk);
|
||||
lighting.onChunkLoaded(chunk->x, chunk->y, chunk->z, true);
|
||||
chunks.clear(false);
|
||||
for (int i = 0; i < CLOSES_C; i++){
|
||||
Chunk* other = closes[i];
|
||||
for (int i = 0; i < SURROUNDINGS_C; i++){
|
||||
Chunk* other = surroundings[i];
|
||||
if (other)
|
||||
other->decref();
|
||||
}
|
||||
chunk->ready = true;
|
||||
chunk->setReady(true);
|
||||
current = nullptr;
|
||||
chunk->decref();
|
||||
}
|
||||
}
|
||||
|
||||
void ChunksLoader::perform(Chunk* chunk, Chunk** closes_passed){
|
||||
void ChunksLoader::perform(Chunk* chunk, Chunk** surroundings_passed, LoaderMode mode){
|
||||
if (isBusy()){
|
||||
std::cerr << "performing while busy" << std::endl;
|
||||
return;
|
||||
}
|
||||
chunk->incref();
|
||||
if (closes == nullptr){
|
||||
closes = new Chunk*[CLOSES_C];
|
||||
if (surroundings == nullptr){
|
||||
surroundings = new Chunk*[SURROUNDINGS_C];
|
||||
}
|
||||
for (int i = 0; i < CLOSES_C; i++){
|
||||
Chunk* other = closes_passed[i];
|
||||
for (int i = 0; i < SURROUNDINGS_C; i++){
|
||||
Chunk* other = surroundings_passed[i];
|
||||
if (other == nullptr)
|
||||
closes[i] = nullptr;
|
||||
surroundings[i] = nullptr;
|
||||
else {
|
||||
other->incref();
|
||||
closes[i] = other;
|
||||
surroundings[i] = other;
|
||||
}
|
||||
}
|
||||
current = chunk;
|
||||
state = mode;
|
||||
}
|
||||
|
||||
void ChunksLoader::load(Chunk* chunk, Chunk** closes_passed){
|
||||
perform(chunk, closes_passed, LOAD);
|
||||
}
|
||||
|
||||
void ChunksLoader::lights(Chunk* chunk, Chunk** closes_passed){
|
||||
perform(chunk, closes_passed, LIGHTS);
|
||||
}
|
||||
|
||||
void ChunksLoader::render(Chunk* chunk, Chunk** closes_passed){
|
||||
perform(chunk, closes_passed, RENDER);
|
||||
}
|
||||
|
||||
@ -11,20 +11,28 @@
|
||||
#include <atomic>
|
||||
|
||||
class Chunk;
|
||||
class World;
|
||||
|
||||
enum LoaderMode {
|
||||
OFF, IDLE, LOAD, LIGHTS, RENDER,
|
||||
};
|
||||
|
||||
class ChunksLoader final {
|
||||
private:
|
||||
std::thread loaderThread;
|
||||
void _thread();
|
||||
std::atomic<Chunk*> current {nullptr};
|
||||
std::atomic<Chunk**> closes {nullptr};
|
||||
std::atomic<bool> working {true};
|
||||
std::atomic<Chunk**> surroundings {nullptr};
|
||||
std::atomic<LoaderMode> state {IDLE};
|
||||
World* world;
|
||||
|
||||
void perform(Chunk* chunk, Chunk** closes_passed, LoaderMode mode);
|
||||
public:
|
||||
ChunksLoader() : loaderThread{} {
|
||||
ChunksLoader(World* world) : loaderThread{}, world(world) {
|
||||
loaderThread = std::thread{&ChunksLoader::_thread, this};
|
||||
}
|
||||
~ChunksLoader(){
|
||||
working = false;
|
||||
state = OFF;
|
||||
loaderThread.join();
|
||||
}
|
||||
|
||||
@ -32,10 +40,12 @@ public:
|
||||
return current != nullptr;
|
||||
}
|
||||
|
||||
void perform(Chunk* chunk, Chunk** closes_passed);
|
||||
void load(Chunk* chunk, Chunk** closes_passed);
|
||||
void lights(Chunk* chunk, Chunk** closes_passed);
|
||||
void render(Chunk* chunk, Chunk** closes_passed);
|
||||
|
||||
void stop(){
|
||||
working = false;
|
||||
state = OFF;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
#include "voxel.h"
|
||||
#include "Chunk.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <math.h>
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/noise.hpp>
|
||||
@ -9,54 +10,64 @@
|
||||
#include "../maths/FastNoiseLite.h"
|
||||
#include <time.h>
|
||||
|
||||
#include "../declarations.h"
|
||||
|
||||
class PseudoRandom {
|
||||
unsigned seed;
|
||||
unsigned short seed;
|
||||
public:
|
||||
PseudoRandom(){
|
||||
seed = (unsigned)time(0);
|
||||
seed = (unsigned short)time(0);
|
||||
}
|
||||
|
||||
int rand(){
|
||||
seed = (8253729 * seed + 2396403);
|
||||
return seed % 32768;
|
||||
seed = (seed + 0x7ed5 + (seed << 6));
|
||||
seed = (seed ^ 0xc23c ^ (seed >> 9));
|
||||
seed = (seed + 0x1656 + (seed << 3));
|
||||
seed = ((seed + 0xa264) ^ (seed << 4));
|
||||
seed = (seed + 0xfd70 - (seed << 3));
|
||||
seed = (seed ^ 0xba49 ^ (seed >> 8));
|
||||
|
||||
return (int)seed;
|
||||
}
|
||||
|
||||
void setSeed(int number){
|
||||
seed = (unsigned)number+8253729;
|
||||
seed = ((unsigned short)number+23729 xor (unsigned short)number+16786);
|
||||
rand();
|
||||
}
|
||||
};
|
||||
|
||||
float calc_height(fnl_state *noise, int real_x, int real_z){
|
||||
const float s = 0.2f;
|
||||
float height = fnlGetNoise3D(noise, real_x*0.0125f*s*32,real_z*0.0125f*s*32, 0.0f);
|
||||
height += fnlGetNoise3D(noise, real_x*0.025f*s*32,real_z*0.025f*s*32, 0.0f)*0.5f;
|
||||
height += fnlGetNoise3D(noise, real_x*0.05f*s*32,real_z*0.05f*s*32, 0.0f)*0.25f;
|
||||
height += fnlGetNoise3D(noise, real_x*0.1f*s*32,real_z*0.1f*s*32, 0.0f)*0.225f;
|
||||
height += fnlGetNoise3D(noise, real_x*0.2f*s*32,real_z*0.2f*s*32, 0.0f)*0.125f;
|
||||
height += fnlGetNoise3D(noise, real_x*0.4f*s*32,real_z*0.4f*s*32, 0.0f)*0.125f*0.5F;
|
||||
height = height * 0.5f + 0.5f;
|
||||
height *= height;
|
||||
height *= (140.0f)*0.12f/s;
|
||||
height += (42)*0.12f/s;
|
||||
float height = fnlGetNoise3D(noise, real_x*0.0125f*8,real_z*0.0125f*8, 0.0f);
|
||||
height += fnlGetNoise3D(noise, real_x*0.025f*8,real_z*0.025f*8, 0.0f)*0.5f;
|
||||
height += fnlGetNoise3D(noise, real_x*0.05f*8,real_z*0.05f*8, 0.0f)*0.25f;
|
||||
height += fnlGetNoise3D(noise,
|
||||
real_x*0.2f*8 + fnlGetNoise3D(noise, real_x*0.1f*8,real_z*0.1f*8, 0.0f)*50,
|
||||
real_z*0.2f*8 + fnlGetNoise3D(noise, real_x*0.1f*8+4363,real_z*0.1f*8, 0.0f)*50,
|
||||
0.0f)*0.1f;
|
||||
height += fnlGetNoise3D(noise, real_x*0.1f*8,real_z*0.1f*8, 0.0f)*0.125f;
|
||||
height += fnlGetNoise3D(noise, real_x*0.4f*8,real_z*0.4f*8, 0.0f)*0.0625f;
|
||||
height += fnlGetNoise3D(noise, real_x*8,real_z*8, 0.0f)*0.03f*(fnlGetNoise3D(noise, -real_x*0.0125f*8-1000,real_z*0.0125f*8+2000, 0.0f)/2+0.5f);
|
||||
height *= fnlGetNoise3D(noise, real_x*0.0125f*8+1000,real_z*0.0125f*8+1000, 0.0f)/2+0.5f;
|
||||
height += 1.0f;
|
||||
height *= 64.0f;
|
||||
return height;
|
||||
}
|
||||
|
||||
float calc_height_faster(fnl_state *noise, int real_x, int real_z){
|
||||
const float s = 0.2f;
|
||||
float height = fnlGetNoise3D(noise, real_x*0.0125f*s*32,real_z*0.0125f*s*32, 0.0f);
|
||||
height += fnlGetNoise3D(noise, real_x*0.025f*s*32,real_z*0.025f*s*32, 0.0f)*0.5f;
|
||||
height += fnlGetNoise3D(noise, real_x*0.05f*s*32,real_z*0.05f*s*32, 0.0f)*0.25f;
|
||||
height += fnlGetNoise3D(noise, real_x*0.1f*s*32,real_z*0.1f*s*32, 0.0f)*0.225f;
|
||||
height += fnlGetNoise3D(noise, real_x*0.2f*s*32,real_z*0.2f*s*32, 0.0f)*0.125f;
|
||||
//height += fnlGetNoise3D(noise, real_x*0.4f*s*32,real_z*0.4f*s*32, 0.0f)*0.125f*0.5F;
|
||||
height = height * 0.5f + 0.5f;
|
||||
height *= height;
|
||||
height *= (140.0f)*0.12f/s;
|
||||
height += (42)*0.12f/s;
|
||||
float height = fnlGetNoise3D(noise, real_x*0.0125f*8,real_z*0.0125f*8, 0.0f);
|
||||
height += fnlGetNoise3D(noise, real_x*0.025f*8,real_z*0.025f*8, 0.0f)*0.5f;
|
||||
height += fnlGetNoise3D(noise, real_x*0.05f*8,real_z*0.05f*8, 0.0f)*0.25f;
|
||||
height += fnlGetNoise3D(noise,
|
||||
real_x*0.2f*8 + fnlGetNoise3D(noise, real_x*0.1f*8,real_z*0.1f*8, 0.0f)*50,
|
||||
real_z*0.2f*8 + fnlGetNoise3D(noise, real_x*0.1f*8+4363,real_z*0.1f*8, 0.0f)*50,
|
||||
0.0f)*0.1f;
|
||||
height += fnlGetNoise3D(noise, real_x*0.1f*8,real_z*0.1f*8, 0.0f)*0.125f;
|
||||
height *= fnlGetNoise3D(noise, real_x*0.0125f*8+1000,real_z*0.0125f*8+1000, 0.0f)/2+0.5f;
|
||||
height += 1.0f;
|
||||
height *= 64.0f;
|
||||
return height;
|
||||
}
|
||||
#include <iostream>
|
||||
|
||||
int generate_tree(fnl_state *noise, PseudoRandom* random, const float* heights, int real_x, int real_y, int real_z, int tileSize){
|
||||
const int tileX = floor((double)real_x/(double)tileSize);
|
||||
const int tileY = floor((double)real_z/(double)tileSize);
|
||||
@ -71,7 +82,7 @@ int generate_tree(fnl_state *noise, PseudoRandom* random, const float* heights,
|
||||
int centerX = tileX * tileSize + tileSize/2 + randomX;
|
||||
int centerY = tileY * tileSize + tileSize/2 + randomZ;
|
||||
int height = (int)calc_height_faster(noise, centerX, centerY);
|
||||
if (height < 55)
|
||||
if ((height < 57) || (fnlGetNoise3D(noise, real_x*0.025f,real_z*0.025f, 0.0f)*0.5f > 0.5))
|
||||
return 0;
|
||||
int lx = real_x - centerX;
|
||||
int radius = random->rand() % 4 + 3;
|
||||
@ -84,11 +95,11 @@ int generate_tree(fnl_state *noise, PseudoRandom* random, const float* heights,
|
||||
return 0;
|
||||
}
|
||||
|
||||
void WorldGenerator::generate(voxel* voxels, int cx, int cy, int cz){
|
||||
void WorldGenerator::generate(voxel* voxels, int cx, int cz, int seed){
|
||||
fnl_state noise = fnlCreateState();
|
||||
noise.noise_type = FNL_NOISE_OPENSIMPLEX2;
|
||||
|
||||
PseudoRandom random;
|
||||
noise.seed = seed * 60617077 % 25896307;
|
||||
PseudoRandom randomtree;
|
||||
|
||||
float heights[CHUNK_VOL];
|
||||
|
||||
@ -102,34 +113,41 @@ void WorldGenerator::generate(voxel* voxels, int cx, int cy, int cz){
|
||||
}
|
||||
|
||||
for (int z = 0; z < CHUNK_D; z++){
|
||||
int real_z = z + cz * CHUNK_D;
|
||||
for (int x = 0; x < CHUNK_W; x++){
|
||||
int real_x = x + cx * CHUNK_W;
|
||||
int real_z = z + cz * CHUNK_D;
|
||||
float height = heights[z*CHUNK_W+x];
|
||||
|
||||
for (int y = 0; y < CHUNK_H; y++){
|
||||
int real_y = y + cy * CHUNK_H;
|
||||
int id = real_y < 55 ? 9 : 0;
|
||||
if (real_y == (int)height)
|
||||
id = 2;
|
||||
else if (real_y < height){
|
||||
if (real_y < height-6)
|
||||
id = 8;
|
||||
else
|
||||
id = 1;
|
||||
int real_y = y;
|
||||
int id = real_y < 55 ? BLOCK_WATER : BLOCK_AIR;
|
||||
if ((real_y == (int)height) && (54 < real_y)) {
|
||||
id = BLOCK_GRASS_BLOCK;
|
||||
} else if (real_y < (height - 6)){
|
||||
id = BLOCK_STONE;
|
||||
} else if (real_y < height){
|
||||
id = BLOCK_DIRT;
|
||||
} else {
|
||||
int tree = generate_tree(&noise, &random, heights, real_x, real_y, real_z, 16);
|
||||
if (tree)
|
||||
int tree = generate_tree(&noise, &randomtree, heights, real_x, real_y, real_z, 16);
|
||||
if (tree) {
|
||||
id = tree;
|
||||
else if ((tree = generate_tree(&noise, &random, heights, real_x, real_y, real_z, 19))){
|
||||
} else if ((tree = generate_tree(&noise, &randomtree, heights, real_x, real_y, real_z, 19))){
|
||||
id = tree;
|
||||
}else if ((tree = generate_tree(&noise, &random, heights, real_x, real_y, real_z, 23))){
|
||||
} else if ((tree = generate_tree(&noise, &randomtree, heights, real_x, real_y, real_z, 23))){
|
||||
id = tree;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ((height - (1.5 - 0.2 * pow(height - 54, 4))) < real_y) && (real_y < height)){
|
||||
id = BLOCK_SAND;
|
||||
}
|
||||
if (real_y <= 2)
|
||||
id = 2;
|
||||
id = BLOCK_BEDROCK;
|
||||
if ((id == 0) && (real_y > 55) && ((int)height + 1 == real_y) && ((unsigned short)random() > 56000)){
|
||||
id = BLOCK_GRASS;
|
||||
}
|
||||
if ((id == 0) && (real_y > 55) && ((int)height + 1 == real_y) && ((unsigned short)random() > 64000)){
|
||||
id = BLOCK_FLOWER;
|
||||
}
|
||||
voxels[(y * CHUNK_D + z) * CHUNK_W + x].id = id;
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,7 +5,7 @@ class voxel;
|
||||
|
||||
class WorldGenerator {
|
||||
public:
|
||||
static void generate(voxel* voxels, int x, int y, int z);
|
||||
static void generate(voxel* voxels, int x, int z, int seed);
|
||||
};
|
||||
|
||||
#endif /* VOXELS_WORLDGENERATOR_H_ */
|
||||
|
||||
@ -1,10 +1,3 @@
|
||||
/*
|
||||
* Camera.cpp
|
||||
*
|
||||
* Created on: Feb 11, 2020
|
||||
* Author: MihailRis
|
||||
*/
|
||||
|
||||
#include "Camera.h"
|
||||
#include "Window.h"
|
||||
|
||||
@ -36,10 +29,22 @@ void Camera::rotate(float x, float y, float z){
|
||||
}
|
||||
|
||||
mat4 Camera::getProjection(){
|
||||
float aspect = (float)Window::width / (float)Window::height;
|
||||
return glm::perspective(fov*zoom, aspect, 0.05f, 1500.0f);
|
||||
float aspect = this->aspect;
|
||||
if (aspect == 0.0f){
|
||||
aspect = (float)Window::width / (float)Window::height;
|
||||
}
|
||||
if (perspective)
|
||||
return glm::perspective(fov*zoom, aspect, 0.05f, 1500.0f);
|
||||
else
|
||||
if (flipped)
|
||||
return glm::ortho(0.0f, fov*aspect, fov, 0.0f);
|
||||
else
|
||||
return glm::ortho(0.0f, fov*aspect, 0.0f, fov);
|
||||
}
|
||||
|
||||
mat4 Camera::getView(){
|
||||
return glm::lookAt(position, position+front, up);
|
||||
if (perspective)
|
||||
return glm::lookAt(position, position+front, up);
|
||||
else
|
||||
return glm::translate(glm::mat4(1.0f), position);
|
||||
}
|
||||
|
||||
@ -1,10 +1,3 @@
|
||||
/*
|
||||
* Camera.h
|
||||
*
|
||||
* Created on: Feb 11, 2020
|
||||
* Author: MihailRis
|
||||
*/
|
||||
|
||||
#ifndef WINDOW_CAMERA_H_
|
||||
#define WINDOW_CAMERA_H_
|
||||
|
||||
@ -23,6 +16,9 @@ public:
|
||||
float fov;
|
||||
float zoom;
|
||||
mat4 rotation;
|
||||
bool perspective = true;
|
||||
bool flipped = false;
|
||||
float aspect = 0.0f;
|
||||
Camera(vec3 position, float fov);
|
||||
|
||||
void rotate(float x, float y, float z);
|
||||
|
||||
@ -97,7 +97,7 @@ bool Events::jclicked(int button){
|
||||
return _keys[index] && _frames[index] == _current;
|
||||
}
|
||||
|
||||
void Events::toogleCursor(){
|
||||
void Events::toggleCursor(){
|
||||
_cursor_locked = !_cursor_locked;
|
||||
Window::setCursorMode(_cursor_locked ? GLFW_CURSOR_DISABLED : GLFW_CURSOR_NORMAL);
|
||||
}
|
||||
|
||||
@ -27,7 +27,7 @@ public:
|
||||
static bool clicked(int button);
|
||||
static bool jclicked(int button);
|
||||
|
||||
static void toogleCursor();
|
||||
static void toggleCursor();
|
||||
};
|
||||
|
||||
#endif /* WINDOW_EVENTS_H_ */
|
||||
|
||||
@ -41,6 +41,10 @@ int Window::initialize(int width, int height, const char* title){
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Window::viewport(int x, int y, int width, int height){
|
||||
glViewport(x, y, width, height);
|
||||
}
|
||||
|
||||
void Window::setCursorMode(int mode){
|
||||
glfwSetInputMode(window, GLFW_CURSOR, mode);
|
||||
}
|
||||
@ -57,6 +61,10 @@ void Window::setShouldClose(bool flag){
|
||||
glfwSetWindowShouldClose(window, flag);
|
||||
}
|
||||
|
||||
void Window::swapInterval(int interval){
|
||||
glfwSwapInterval(interval);
|
||||
}
|
||||
|
||||
void Window::swapBuffers(){
|
||||
glfwSwapBuffers(window);
|
||||
}
|
||||
|
||||
@ -11,10 +11,12 @@ public:
|
||||
static int initialize(int width, int height, const char* title);
|
||||
static void terminate();
|
||||
|
||||
static void viewport(int x, int y, int width, int height);
|
||||
static void setCursorMode(int mode);
|
||||
static bool isShouldClose();
|
||||
static void setShouldClose(bool flag);
|
||||
static void swapBuffers();
|
||||
static void swapInterval(int interval);
|
||||
};
|
||||
|
||||
#endif /* WINDOW_WINDOW_H_ */
|
||||
|
||||
23
src/world/Level.cpp
Normal file
@ -0,0 +1,23 @@
|
||||
#include "Level.h"
|
||||
#include "../lighting/Lighting.h"
|
||||
#include "../voxels/ChunksController.h"
|
||||
#include "../player_control.h"
|
||||
|
||||
Level::Level(World* world, Player* player, Chunks* chunks, PhysicsSolver* physics) :
|
||||
world(world),
|
||||
player(player),
|
||||
chunks(chunks),
|
||||
physics(physics) {
|
||||
lighting = new Lighting(chunks);
|
||||
chunksController = new ChunksController(world, chunks, lighting);
|
||||
playerController = new PlayerController(this);
|
||||
}
|
||||
|
||||
Level::~Level(){
|
||||
delete chunks;
|
||||
delete physics;
|
||||
delete player;
|
||||
delete lighting;
|
||||
delete chunksController;
|
||||
delete playerController;
|
||||
}
|
||||
25
src/world/Level.h
Normal file
@ -0,0 +1,25 @@
|
||||
#ifndef WORLD_LEVEL_H_
|
||||
#define WORLD_LEVEL_H_
|
||||
|
||||
class World;
|
||||
class Player;
|
||||
class Chunks;
|
||||
class Lighting;
|
||||
class PhysicsSolver;
|
||||
class ChunksController;
|
||||
class PlayerController;
|
||||
|
||||
class Level {
|
||||
public:
|
||||
World* world;
|
||||
Player* player;
|
||||
Chunks* chunks;
|
||||
PhysicsSolver* physics;
|
||||
Lighting* lighting;
|
||||
ChunksController* chunksController;
|
||||
PlayerController* playerController;
|
||||
Level(World* world, Player* player, Chunks* chunks, PhysicsSolver* physics);
|
||||
~Level();
|
||||
};
|
||||
|
||||
#endif /* WORLD_LEVEL_H_ */
|
||||
13
src/world/World.cpp
Normal file
@ -0,0 +1,13 @@
|
||||
#include "World.h"
|
||||
|
||||
#include "../files/WorldFiles.h"
|
||||
#include "../voxels/Chunk.h"
|
||||
#include "../voxels/Chunks.h"
|
||||
|
||||
World::World(std::string name, std::string directory, int seed) : name(name), seed(seed) {
|
||||
wfile = new WorldFiles(directory, REGION_VOL * (CHUNK_VOL * 2 + 8));
|
||||
}
|
||||
|
||||
World::~World(){
|
||||
delete wfile;
|
||||
}
|
||||
19
src/world/World.h
Normal file
@ -0,0 +1,19 @@
|
||||
#ifndef WORLD_WORLD_H_
|
||||
#define WORLD_WORLD_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
class WorldFiles;
|
||||
class Chunks;
|
||||
|
||||
class World {
|
||||
public:
|
||||
std::string name;
|
||||
WorldFiles* wfile;
|
||||
int seed;
|
||||
|
||||
World(std::string name, std::string directory, int seed);
|
||||
~World();
|
||||
};
|
||||
|
||||
#endif /* WORLD_WORLD_H_ */
|
||||
153
src/world_render.cpp
Normal file
@ -0,0 +1,153 @@
|
||||
#include "world_render.h"
|
||||
|
||||
#include <iostream>
|
||||
#include "graphics/VoxelRenderer.h"
|
||||
|
||||
#include "window/Window.h"
|
||||
#include "window/Camera.h"
|
||||
#include "graphics/Mesh.h"
|
||||
#include "graphics/Shader.h"
|
||||
#include "graphics/Texture.h"
|
||||
#include "graphics/LineBatch.h"
|
||||
#include "graphics/Batch3D.h"
|
||||
#include "voxels/Chunks.h"
|
||||
#include "voxels/Chunk.h"
|
||||
#include "voxels/Block.h"
|
||||
#include "world/World.h"
|
||||
#include "world/Level.h"
|
||||
#include "objects/Player.h"
|
||||
#include "Assets.h"
|
||||
#include "player_control.h"
|
||||
|
||||
float _camera_cx;
|
||||
float _camera_cz;
|
||||
|
||||
WorldRenderer::WorldRenderer(Level* level, Assets* assets) : assets(assets), level(level) {
|
||||
lineBatch = new LineBatch(4096);
|
||||
batch3d = new Batch3D(1024);
|
||||
renderer = new VoxelRenderer();
|
||||
}
|
||||
|
||||
WorldRenderer::~WorldRenderer() {
|
||||
delete batch3d;
|
||||
delete lineBatch;
|
||||
delete renderer;
|
||||
}
|
||||
|
||||
Chunks* _chunks = nullptr;
|
||||
|
||||
bool chunks_distance_compare(size_t i, size_t j) {
|
||||
Chunk* a = _chunks->chunks[i];
|
||||
Chunk* b = _chunks->chunks[j];
|
||||
return ((a->x + 0.5f - _camera_cx)*(a->x + 0.5f - _camera_cx) + (a->z + 0.5f - _camera_cz)*(a->z + 0.5f - _camera_cz) >
|
||||
(b->x + 0.5f - _camera_cx)*(b->x + 0.5f - _camera_cx) + (b->z + 0.5f - _camera_cz)*(b->z + 0.5f - _camera_cz));
|
||||
}
|
||||
|
||||
bool WorldRenderer::drawChunk(size_t index, Camera* camera, Shader* shader, bool occlusion){
|
||||
Chunk* chunk = level->chunks->chunks[index];
|
||||
Mesh* mesh = level->chunks->meshes[index];
|
||||
if (mesh == nullptr)
|
||||
return false;
|
||||
|
||||
// Simple frustum culling
|
||||
if (occlusion){
|
||||
float y = camera->position.y+camera->front.y * CHUNK_H * 0.5f;
|
||||
if (y < 0.0f)
|
||||
y = 0.0f;
|
||||
if (y > CHUNK_H)
|
||||
y = CHUNK_H;
|
||||
vec3 v = vec3(chunk->x*CHUNK_W, y, chunk->z*CHUNK_D)-camera->position;
|
||||
if (v.x*v.x+v.z*v.z > (CHUNK_W*3)*(CHUNK_W*3)) {
|
||||
if (dot(camera->front, v) < 0.0f){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mat4 model = glm::translate(mat4(1.0f), vec3(chunk->x*CHUNK_W+0.5f, 0.5f, chunk->z*CHUNK_D+0.5f));
|
||||
shader->uniformMatrix("u_model", model);
|
||||
mesh->draw(GL_TRIANGLES);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void WorldRenderer::draw(World* world, Camera* camera, bool occlusion){
|
||||
Chunks* chunks = level->chunks;
|
||||
|
||||
vec4 skyColor(0.7f, 0.81f, 1.0f, 1.0f);
|
||||
glClearColor(skyColor.r, skyColor.g, skyColor.b, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
Window::viewport(0, 0, Window::width, Window::height);
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glEnable(GL_CULL_FACE);
|
||||
|
||||
Texture* texture = assets->getTexture("block");
|
||||
Shader* shader = assets->getShader("main");
|
||||
Shader* linesShader = assets->getShader("lines");
|
||||
shader->use();
|
||||
shader->uniformMatrix("u_proj", camera->getProjection());
|
||||
shader->uniformMatrix("u_view", camera->getView());
|
||||
shader->uniform1f("u_gamma", 1.6f);
|
||||
shader->uniform3f("u_skyLightColor", 1.1f,1.1f,1.1f);
|
||||
shader->uniform3f("u_fogColor", skyColor.r,skyColor.g,skyColor.b);
|
||||
shader->uniform1f("u_fogFactor", 0.025f);
|
||||
shader->uniform3f("u_cameraPos", camera->position.x,camera->position.y,camera->position.z);
|
||||
|
||||
Block* cblock = Block::blocks[level->player->choosenBlock];
|
||||
shader->uniform3f("u_torchlightColor",
|
||||
cblock->emission[0] / 15.0f,
|
||||
cblock->emission[1] / 15.0f,
|
||||
cblock->emission[2] / 15.0f);
|
||||
shader->uniform1f("u_torchlightDistance", 6.0f);
|
||||
shader->uniform1f("u_fogFactor", 0.025f);
|
||||
texture->bind();
|
||||
|
||||
std::vector<size_t> indices;
|
||||
|
||||
for (size_t i = 0; i < chunks->volume; i++){
|
||||
Chunk* chunk = chunks->chunks[i];
|
||||
if (chunk == nullptr)
|
||||
continue;
|
||||
if (chunks->meshes[i] != nullptr)
|
||||
indices.push_back(i);
|
||||
}
|
||||
|
||||
float px = camera->position.x / (float)CHUNK_W;
|
||||
float pz = camera->position.z / (float)CHUNK_D;
|
||||
|
||||
_camera_cx = px;
|
||||
_camera_cz = pz;
|
||||
_chunks = chunks;
|
||||
std::sort(indices.begin(), indices.end(), chunks_distance_compare);
|
||||
|
||||
|
||||
int occludedChunks = 0;
|
||||
for (size_t i = 0; i < indices.size(); i++){
|
||||
occludedChunks += drawChunk(indices[i], camera, shader, occlusion);
|
||||
}
|
||||
|
||||
shader->uniformMatrix("u_model", mat4(1.0f));
|
||||
batch3d->begin();
|
||||
// draw 3D stuff here
|
||||
batch3d->render();
|
||||
|
||||
linesShader->use();
|
||||
linesShader->uniformMatrix("u_projview", camera->getProjection()*camera->getView());
|
||||
glLineWidth(2.0f);
|
||||
lineBatch->line(camera->position.x, camera->position.y-0.1f, camera->position.z, camera->position.x+0.01f, camera->position.y-0.1f, camera->position.z, 1, 0, 0, 1);
|
||||
lineBatch->line(camera->position.x, camera->position.y-0.1f, camera->position.z, camera->position.x, camera->position.y-0.1f, camera->position.z+0.01f, 0, 0, 1, 1);
|
||||
lineBatch->line(camera->position.x, camera->position.y-0.1f, camera->position.z, camera->position.x, camera->position.y-0.1f+0.01f, camera->position.z, 0, 1, 0, 1);
|
||||
lineBatch->render();
|
||||
|
||||
if (level->playerController->selectedBlockId != -1){
|
||||
Block* selectedBlock = Block::blocks[level->playerController->selectedBlockId];
|
||||
vec3 pos = level->playerController->selectedBlockPosition;
|
||||
if (selectedBlock->model == 1){
|
||||
lineBatch->box(pos.x+0.5f, pos.y+0.5f, pos.z+0.5f, 1.005f,1.005f,1.005f, 0,0,0,0.5f);
|
||||
} else if (selectedBlock->model == 2){
|
||||
lineBatch->box(pos.x+0.4f, pos.y+0.3f, pos.z+0.4f, 0.805f,0.805f,0.805f, 0,0,0,0.5f);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -5,152 +5,40 @@
|
||||
#include <algorithm>
|
||||
#include <GL/glew.h>
|
||||
|
||||
#ifndef std::string
|
||||
#include <string>
|
||||
#endif
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/ext.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
|
||||
#include "window/Window.h"
|
||||
#include "window/Camera.h"
|
||||
#include "graphics/Mesh.h"
|
||||
#include "graphics/Shader.h"
|
||||
#include "graphics/Texture.h"
|
||||
#include "graphics/LineBatch.h"
|
||||
#include "voxels/Chunks.h"
|
||||
#include "voxels/Chunk.h"
|
||||
class World;
|
||||
class Level;
|
||||
class Camera;
|
||||
class Assets;
|
||||
class LineBatch;
|
||||
class Batch3D;
|
||||
class VoxelRenderer;
|
||||
class Shader;
|
||||
class Texture;
|
||||
class Framebuffer;
|
||||
|
||||
float _camera_cx;
|
||||
float _camera_cz;
|
||||
Chunks* _chunks;
|
||||
|
||||
Mesh *crosshair;
|
||||
class WorldRenderer {
|
||||
Batch3D *batch3d;
|
||||
Assets* assets;
|
||||
Level* level;
|
||||
bool drawChunk(size_t index, Camera* camera, Shader* shader, bool occlusion);
|
||||
public:
|
||||
VoxelRenderer *renderer;
|
||||
LineBatch *lineBatch;
|
||||
|
||||
float vertices[] = {
|
||||
// x y
|
||||
-0.01f,-0.01f,
|
||||
0.01f, 0.01f,
|
||||
WorldRenderer(Level* level, Assets* assets);
|
||||
~WorldRenderer();
|
||||
|
||||
-0.01f, 0.01f,
|
||||
0.01f,-0.01f,
|
||||
void draw(World* world, Camera* camera, bool occlusion);
|
||||
};
|
||||
|
||||
int attrs[] = {
|
||||
2, 0 //null terminator
|
||||
};
|
||||
|
||||
LineBatch *lineBatch;
|
||||
|
||||
void init_renderer(){
|
||||
crosshair = new Mesh(vertices, 4, attrs);
|
||||
lineBatch = new LineBatch(4096);
|
||||
}
|
||||
|
||||
|
||||
void finalize_renderer(){
|
||||
delete crosshair;
|
||||
delete lineBatch;
|
||||
}
|
||||
|
||||
void draw_chunk(size_t index, Camera* camera, Shader* shader, bool occlusion){
|
||||
Chunk* chunk = _chunks->chunks[index];
|
||||
Mesh* mesh = _chunks->meshes[index];
|
||||
if (mesh == nullptr)
|
||||
return;
|
||||
|
||||
// Simple frustum culling (culling chunks behind the camera in 2D - XZ)
|
||||
if (occlusion){
|
||||
const float cameraX = camera->position.x;
|
||||
const float cameraZ = camera->position.z;
|
||||
const float camDirX = camera->dir.x;
|
||||
const float camDirZ = camera->dir.z;
|
||||
|
||||
bool unoccluded = false;
|
||||
do {
|
||||
if ((chunk->x*CHUNK_W-cameraX)*camDirX + (chunk->z*CHUNK_D-cameraZ)*camDirZ >= 0.0){
|
||||
unoccluded = true; break;
|
||||
}
|
||||
if (((chunk->x+1)*CHUNK_W-cameraX)*camDirX + (chunk->z*CHUNK_D-cameraZ)*camDirZ >= 0.0){
|
||||
unoccluded = true; break;
|
||||
}
|
||||
if (((chunk->x+1)*CHUNK_W-cameraX)*camDirX + ((chunk->z+1)*CHUNK_D-cameraZ)*camDirZ >= 0.0){
|
||||
unoccluded = true; break;
|
||||
}
|
||||
if ((chunk->x*CHUNK_W-cameraX)*camDirX + ((chunk->z+1)*CHUNK_D-cameraZ)*camDirZ >= 0.0){
|
||||
unoccluded = true; break;
|
||||
}
|
||||
} while (false);
|
||||
if (!unoccluded)
|
||||
return;
|
||||
}
|
||||
|
||||
mat4 model = glm::translate(mat4(1.0f), vec3(chunk->x*CHUNK_W+0.5f, chunk->y*CHUNK_H+0.5f, chunk->z*CHUNK_D+0.5f));
|
||||
shader->uniformMatrix("u_model", model);
|
||||
mesh->draw(GL_TRIANGLES);
|
||||
}
|
||||
|
||||
bool chunks_comparator(size_t i, size_t j) {
|
||||
Chunk* a = _chunks->chunks[i];
|
||||
Chunk* b = _chunks->chunks[j];
|
||||
return ((a->x + 0.5f - _camera_cx)*(a->x + 0.5f - _camera_cx) + (a->z + 0.5f - _camera_cz)*(a->z + 0.5f - _camera_cz)
|
||||
>
|
||||
(b->x + 0.5f - _camera_cx)*(b->x + 0.5f - _camera_cx) + (b->z + 0.5f - _camera_cz)*(b->z + 0.5f - _camera_cz));
|
||||
}
|
||||
|
||||
|
||||
void draw_world(Camera* camera, Assets* assets,
|
||||
Chunks* chunks, bool occlusion){
|
||||
glClearColor(0.7f,0.71f,0.73f,1);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
_chunks = chunks;
|
||||
|
||||
// Draw VAO
|
||||
Texture* texture = assets->getTexture("block");
|
||||
Shader* shader = assets->getShader("main");
|
||||
Shader* crosshairShader = assets->getShader("crosshair");
|
||||
Shader* linesShader = assets->getShader("lines");
|
||||
shader->use();
|
||||
shader->uniformMatrix("u_proj", camera->getProjection());
|
||||
shader->uniformMatrix("u_view", camera->getView());
|
||||
shader->uniform1f("u_gamma", 1.6f);
|
||||
shader->uniform3f("u_skyLightColor", 1.8f,1.8f,1.8f);
|
||||
shader->uniform3f("u_fogColor", 0.7f,0.71f,0.73f);
|
||||
shader->uniform3f("u_cameraPos", camera->position.x,camera->position.y,camera->position.z);
|
||||
texture->bind();
|
||||
|
||||
std::vector<size_t> indices;
|
||||
|
||||
for (size_t i = 0; i < chunks->volume; i++){
|
||||
Chunk* chunk = chunks->chunks[i];
|
||||
if (chunk == nullptr)
|
||||
continue;
|
||||
if (chunks->meshes[i] != nullptr)
|
||||
indices.push_back(i);
|
||||
}
|
||||
|
||||
float px = camera->position.x / (float)CHUNK_W;
|
||||
float pz = camera->position.z / (float)CHUNK_D;
|
||||
|
||||
_camera_cx = px;
|
||||
_camera_cz = pz;
|
||||
|
||||
std::sort(indices.begin(), indices.end(), chunks_comparator);
|
||||
|
||||
|
||||
for (size_t i = 0; i < indices.size(); i++){
|
||||
draw_chunk(indices[i], camera, shader, occlusion);
|
||||
}
|
||||
|
||||
crosshairShader->use();
|
||||
crosshairShader->uniform1f("u_ar", (float)Window::height / (float)Window::width);
|
||||
crosshairShader->uniform1f("u_scale", 1.0f / ((float)Window::height / 1000.0f));
|
||||
crosshair->draw(GL_LINES);
|
||||
|
||||
linesShader->use();
|
||||
linesShader->uniformMatrix("u_projview", camera->getProjection()*camera->getView());
|
||||
glLineWidth(2.0f);
|
||||
lineBatch->line(camera->position.x, camera->position.y-0.5f, camera->position.z, camera->position.x+0.1f, camera->position.y-0.5f, camera->position.z, 1, 0, 0, 1);
|
||||
lineBatch->line(camera->position.x, camera->position.y-0.5f, camera->position.z, camera->position.x, camera->position.y-0.5f, camera->position.z+0.1f, 0, 0, 1, 1);
|
||||
lineBatch->render();
|
||||
}
|
||||
|
||||
#endif // WORLD_RENDERER_CPP
|
||||
|
||||