Compare commits
28 Commits
pre-alpha-
...
main
Author | SHA1 | Date | |
---|---|---|---|
|
ccacb3088f | ||
|
93897037b8 | ||
|
90f1cc59d5 | ||
|
b4e22d076b | ||
|
41e3abe45e | ||
|
70157a4f7f | ||
|
a34f2fd9a3 | ||
|
28cc58d2c6 | ||
|
7d074585c1 | ||
|
bffb488446 | ||
|
cced9a2b95 | ||
|
ec70bb48ac | ||
|
7788b5f6be | ||
|
734030edcb | ||
|
6c3f2ddd84 | ||
|
34ba20188f | ||
|
f58173649b | ||
|
4e1c4fe98a | ||
|
117e2c321d | ||
|
e7dd7d13d3 | ||
|
d8aaa00f1a | ||
|
8b26492b78 | ||
|
5d485b21a5 | ||
|
adee5b3da3 | ||
|
5d993ce1b7 | ||
|
749347981f | ||
|
ad910a47f1 | ||
|
87228cc4e8 |
6
.gitignore
vendored
6
.gitignore
vendored
@ -407,4 +407,8 @@ FodyWeavers.xsd
|
|||||||
*.msp
|
*.msp
|
||||||
|
|
||||||
# JetBrains Rider
|
# JetBrains Rider
|
||||||
*.sln.iml
|
*.sln.iml
|
||||||
|
|
||||||
|
imgui.ini
|
||||||
|
|
||||||
|
build/
|
||||||
|
29
README.md
29
README.md
@ -1,2 +1,31 @@
|
|||||||
# Scuffed Minecraft
|
# Scuffed Minecraft
|
||||||
A Minecraft clone made in C++ and OpenGL
|
A Minecraft clone made in C++ and OpenGL
|
||||||
|
|
||||||
|
## How to Run
|
||||||
|
To run the game, download the ScuffedMinecraft zip file from the [latest release](https://github.com/EvanatorM/ScuffedMinecraft/releases/latest), unzip the file, and run ScuffedMinecraft.exe. The assets folder must be in the same place as the exe file.
|
||||||
|
|
||||||
|
## Building
|
||||||
|
|
||||||
|
### Building with Visual Studio
|
||||||
|
Import the project in Visual Studio 17 or higher and build it.
|
||||||
|
|
||||||
|
### Building with CMake
|
||||||
|
In the project root directory:
|
||||||
|
Create CMake files:
|
||||||
|
```sh
|
||||||
|
mkdir -p build
|
||||||
|
cd build
|
||||||
|
cmake ../ScuffedMinecraft
|
||||||
|
```
|
||||||
|
After that you can build the project using:
|
||||||
|
```sh
|
||||||
|
cmake --build ./build
|
||||||
|
```
|
||||||
|
Run the build command in the project root directory.
|
||||||
|
|
||||||
|
The final executable can be found at `(project root)/ScuffedMinecraft/bin`
|
||||||
|
|
||||||
|
#### Note for building with CMake
|
||||||
|
If you're running from a command line, make sure to run
|
||||||
|
the executable in the same directory as it is located
|
||||||
|
to ensure all resources are loaded properly.
|
||||||
|
26
ScuffedMinecraft/CMakeLists.txt
Normal file
26
ScuffedMinecraft/CMakeLists.txt
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.10)
|
||||||
|
set(CMAKE_CXX_STANDARD 20)
|
||||||
|
|
||||||
|
project(ScuffedMinecraft)
|
||||||
|
|
||||||
|
# output directories
|
||||||
|
set(CMAKE_BINARY_DIR ${CMAKE_SOURCE_DIR}/bin)
|
||||||
|
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
||||||
|
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
||||||
|
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
||||||
|
|
||||||
|
# copy assets
|
||||||
|
add_custom_target(copy_assets ALL
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
||||||
|
${CMAKE_SOURCE_DIR}/assets
|
||||||
|
${CMAKE_BINARY_DIR}/assets
|
||||||
|
COMMENT "Copying assets")
|
||||||
|
|
||||||
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||||
|
|
||||||
|
# global dependency directories
|
||||||
|
include_directories(../Dependencies/include/)
|
||||||
|
link_directories(../Dependencies/lib/)
|
||||||
|
|
||||||
|
add_subdirectory(vendor/imgui)
|
||||||
|
add_subdirectory(src)
|
@ -71,20 +71,20 @@
|
|||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
<PropertyGroup Label="UserMacros" />
|
<PropertyGroup Label="UserMacros" />
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
<IncludePath>C:\dev\C++\ScuffedMinecraft\Dependencies\include;$(IncludePath)</IncludePath>
|
<IncludePath>$(SolutionDir)Dependencies\include;$(IncludePath)</IncludePath>
|
||||||
<LibraryPath>C:\dev\C++\ScuffedMinecraft\Dependencies\lib;$(LibraryPath)</LibraryPath>
|
<LibraryPath>$(SolutionDir)Dependencies\lib;$(LibraryPath)</LibraryPath>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
<IncludePath>C:\dev\C++\ScuffedMinecraft\Dependencies\include;$(IncludePath)</IncludePath>
|
<IncludePath>$(SolutionDir)Dependencies\include;$(IncludePath)</IncludePath>
|
||||||
<LibraryPath>C:\dev\C++\ScuffedMinecraft\Dependencies\lib;$(LibraryPath)</LibraryPath>
|
<LibraryPath>$(SolutionDir)Dependencies\lib;$(LibraryPath)</LibraryPath>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
<IncludePath>C:\dev\C++\ScuffedMinecraft\Dependencies\include;$(IncludePath)</IncludePath>
|
<IncludePath>$(SolutionDir)Dependencies\include;$(IncludePath)</IncludePath>
|
||||||
<LibraryPath>C:\dev\C++\ScuffedMinecraft\Dependencies\lib;$(LibraryPath)</LibraryPath>
|
<LibraryPath>$(SolutionDir)Dependencies\lib;$(LibraryPath)</LibraryPath>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
<IncludePath>C:\dev\C++\ScuffedMinecraft\Dependencies\include;$(IncludePath)</IncludePath>
|
<IncludePath>$(SolutionDir)Dependencies\include;$(IncludePath)</IncludePath>
|
||||||
<LibraryPath>C:\dev\C++\ScuffedMinecraft\Dependencies\lib;$(LibraryPath)</LibraryPath>
|
<LibraryPath>$(SolutionDir)Dependencies\lib;$(LibraryPath)</LibraryPath>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
@ -130,6 +130,7 @@
|
|||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<AdditionalDependencies>glfw3.lib;opengl32.lib;$(CoreLibraryDependencies);%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>glfw3.lib;opengl32.lib;$(CoreLibraryDependencies);%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
<AdditionalOptions>/ignore:4099 %(AdditionalOptions)</AdditionalOptions>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
@ -148,6 +149,7 @@
|
|||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<AdditionalDependencies>glfw3.lib;opengl32.lib;$(CoreLibraryDependencies);%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>glfw3.lib;opengl32.lib;$(CoreLibraryDependencies);%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
<AdditionalOptions>/ignore:4099 %(AdditionalOptions)</AdditionalOptions>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@ -155,9 +157,14 @@
|
|||||||
<ClCompile Include="src\Block.cpp" />
|
<ClCompile Include="src\Block.cpp" />
|
||||||
<ClCompile Include="src\Camera.cpp" />
|
<ClCompile Include="src\Camera.cpp" />
|
||||||
<ClCompile Include="src\Chunk.cpp" />
|
<ClCompile Include="src\Chunk.cpp" />
|
||||||
|
<ClCompile Include="src\ChunkData.cpp" />
|
||||||
|
<ClCompile Include="src\ChunkPos.cpp" />
|
||||||
|
<ClCompile Include="src\NoiseSettings.cpp" />
|
||||||
|
<ClCompile Include="src\Physics.cpp" />
|
||||||
<ClCompile Include="src\Planet.cpp" />
|
<ClCompile Include="src\Planet.cpp" />
|
||||||
<ClCompile Include="src\Shader.cpp" />
|
<ClCompile Include="src\Shader.cpp" />
|
||||||
<ClCompile Include="src\TupleHash.h" />
|
<ClCompile Include="src\SurfaceFeature.cpp" />
|
||||||
|
<ClCompile Include="src\ChunkPosHash.h" />
|
||||||
<ClCompile Include="src\WorldGen.cpp" />
|
<ClCompile Include="src\WorldGen.cpp" />
|
||||||
<ClCompile Include="src\WorldGen.h" />
|
<ClCompile Include="src\WorldGen.h" />
|
||||||
<ClCompile Include="vendor\glad.c" />
|
<ClCompile Include="vendor\glad.c" />
|
||||||
@ -174,8 +181,14 @@
|
|||||||
<ClInclude Include="src\Blocks.h" />
|
<ClInclude Include="src\Blocks.h" />
|
||||||
<ClInclude Include="src\Camera.h" />
|
<ClInclude Include="src\Camera.h" />
|
||||||
<ClInclude Include="src\Chunk.h" />
|
<ClInclude Include="src\Chunk.h" />
|
||||||
|
<ClInclude Include="src\ChunkData.h" />
|
||||||
|
<ClInclude Include="src\ChunkPos.h" />
|
||||||
|
<ClInclude Include="src\NoiseSettings.h" />
|
||||||
|
<ClInclude Include="src\Physics.h" />
|
||||||
<ClInclude Include="src\Planet.h" />
|
<ClInclude Include="src\Planet.h" />
|
||||||
<ClInclude Include="src\Shader.h" />
|
<ClInclude Include="src\Shader.h" />
|
||||||
|
<ClInclude Include="src\SurfaceFeature.h" />
|
||||||
|
<ClInclude Include="src\Vertex.h" />
|
||||||
<ClInclude Include="vendor\imgui\imconfig.h" />
|
<ClInclude Include="vendor\imgui\imconfig.h" />
|
||||||
<ClInclude Include="vendor\imgui\imgui.h" />
|
<ClInclude Include="vendor\imgui\imgui.h" />
|
||||||
<ClInclude Include="vendor\imgui\imgui_impl_glfw.h" />
|
<ClInclude Include="vendor\imgui\imgui_impl_glfw.h" />
|
||||||
@ -189,13 +202,22 @@
|
|||||||
<ClInclude Include="vendor\stb_image.h" />
|
<ClInclude Include="vendor\stb_image.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="assets\shaders\fragment_shader.glsl" />
|
<None Include="assets\shaders\billboard_frag.glsl" />
|
||||||
<None Include="assets\shaders\vertex_shader.glsl" />
|
<None Include="assets\shaders\billboard_vert.glsl" />
|
||||||
|
<None Include="assets\shaders\block_outline_frag.glsl" />
|
||||||
|
<None Include="assets\shaders\block_outline_vert.glsl" />
|
||||||
|
<None Include="assets\shaders\crosshair_frag.glsl" />
|
||||||
|
<None Include="assets\shaders\crosshair_vert.glsl" />
|
||||||
|
<None Include="assets\shaders\framebuffer_frag.glsl" />
|
||||||
|
<None Include="assets\shaders\framebuffer_vert.glsl" />
|
||||||
|
<None Include="assets\shaders\main_frag.glsl" />
|
||||||
|
<None Include="assets\shaders\main_vert.glsl" />
|
||||||
|
<None Include="assets\shaders\water_frag.glsl" />
|
||||||
|
<None Include="assets\shaders\water_vert.glsl" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Image Include="assets\sprites\block_map.png" />
|
<Image Include="assets\sprites\block_map.png" />
|
||||||
<Image Include="assets\sprites\direction_test.png" />
|
<Image Include="assets\sprites\crosshair.png" />
|
||||||
<Image Include="assets\sprites\grass_block_side.png" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Text Include="vendor\imgui\LICENSE.txt" />
|
<Text Include="vendor\imgui\LICENSE.txt" />
|
||||||
|
@ -33,7 +33,7 @@
|
|||||||
<ClCompile Include="src\Block.cpp">
|
<ClCompile Include="src\Block.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="src\TupleHash.h">
|
<ClCompile Include="src\ChunkPosHash.h">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="src\WorldGen.h">
|
<ClCompile Include="src\WorldGen.h">
|
||||||
@ -66,6 +66,21 @@
|
|||||||
<ClCompile Include="vendor\imgui\imgui_widgets.cpp">
|
<ClCompile Include="vendor\imgui\imgui_widgets.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\NoiseSettings.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\SurfaceFeature.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Physics.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\ChunkPos.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\ChunkData.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="src\Shader.h">
|
<ClInclude Include="src\Shader.h">
|
||||||
@ -119,21 +134,46 @@
|
|||||||
<ClInclude Include="vendor\imgui\imstb_truetype.h">
|
<ClInclude Include="vendor\imgui\imstb_truetype.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\NoiseSettings.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\SurfaceFeature.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Vertex.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Physics.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\ChunkPos.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\ChunkData.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="assets\shaders\vertex_shader.glsl" />
|
<None Include="assets\shaders\main_vert.glsl" />
|
||||||
<None Include="assets\shaders\fragment_shader.glsl" />
|
<None Include="assets\shaders\main_frag.glsl" />
|
||||||
|
<None Include="assets\shaders\water_frag.glsl" />
|
||||||
|
<None Include="assets\shaders\water_vert.glsl" />
|
||||||
|
<None Include="assets\shaders\billboard_vert.glsl" />
|
||||||
|
<None Include="assets\shaders\billboard_frag.glsl" />
|
||||||
|
<None Include="assets\shaders\framebuffer_vert.glsl" />
|
||||||
|
<None Include="assets\shaders\framebuffer_frag.glsl" />
|
||||||
|
<None Include="assets\shaders\block_outline_vert.glsl" />
|
||||||
|
<None Include="assets\shaders\block_outline_frag.glsl" />
|
||||||
|
<None Include="assets\shaders\crosshair_frag.glsl" />
|
||||||
|
<None Include="assets\shaders\crosshair_vert.glsl" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Image Include="assets\sprites\grass_block_side.png">
|
|
||||||
<Filter>Resource Files</Filter>
|
|
||||||
</Image>
|
|
||||||
<Image Include="assets\sprites\direction_test.png">
|
|
||||||
<Filter>Resource Files</Filter>
|
|
||||||
</Image>
|
|
||||||
<Image Include="assets\sprites\block_map.png">
|
<Image Include="assets\sprites\block_map.png">
|
||||||
<Filter>Resource Files</Filter>
|
<Filter>Resource Files</Filter>
|
||||||
</Image>
|
</Image>
|
||||||
|
<Image Include="assets\sprites\crosshair.png">
|
||||||
|
<Filter>Resource Files</Filter>
|
||||||
|
</Image>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Text Include="vendor\imgui\LICENSE.txt" />
|
<Text Include="vendor\imgui\LICENSE.txt" />
|
||||||
|
27
ScuffedMinecraft/assets/shaders/billboard_frag.glsl
Normal file
27
ScuffedMinecraft/assets/shaders/billboard_frag.glsl
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#version 330 core
|
||||||
|
|
||||||
|
in vec2 TexCoord;
|
||||||
|
|
||||||
|
out vec4 FragColor;
|
||||||
|
|
||||||
|
uniform sampler2D tex;
|
||||||
|
|
||||||
|
const vec3 ambient = vec3(.5);
|
||||||
|
const vec3 lightDirection = vec3(0.8, 1, 0.7);
|
||||||
|
|
||||||
|
const vec3 normal = vec3( 0, -1, 0);
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec3 lightDir = normalize(-lightDirection);
|
||||||
|
|
||||||
|
float diff = max(dot(normal, lightDir), 0.0);
|
||||||
|
vec3 diffuse = diff * vec3(1);
|
||||||
|
|
||||||
|
vec4 result = vec4(ambient + diffuse, 1.0);
|
||||||
|
|
||||||
|
vec4 texResult = texture(tex, TexCoord);
|
||||||
|
if (texResult.a == 0)
|
||||||
|
discard;
|
||||||
|
FragColor = texResult * result;
|
||||||
|
}
|
@ -4,6 +4,7 @@ layout (location = 0) in vec3 aPos;
|
|||||||
layout (location = 1) in vec2 aTexCoord;
|
layout (location = 1) in vec2 aTexCoord;
|
||||||
|
|
||||||
out vec2 TexCoord;
|
out vec2 TexCoord;
|
||||||
|
out vec3 Normal;
|
||||||
|
|
||||||
uniform float texMultiplier;
|
uniform float texMultiplier;
|
||||||
|
|
10
ScuffedMinecraft/assets/shaders/block_outline_frag.glsl
Normal file
10
ScuffedMinecraft/assets/shaders/block_outline_frag.glsl
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#version 330 core
|
||||||
|
|
||||||
|
out vec4 FragColor;
|
||||||
|
|
||||||
|
uniform float time;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
FragColor = vec4(0.0, 0.0, 0.0, 1.0);
|
||||||
|
}
|
12
ScuffedMinecraft/assets/shaders/block_outline_vert.glsl
Normal file
12
ScuffedMinecraft/assets/shaders/block_outline_vert.glsl
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#version 330 core
|
||||||
|
|
||||||
|
layout (location = 0) in vec3 aPos;
|
||||||
|
|
||||||
|
uniform vec3 model;
|
||||||
|
uniform mat4 view;
|
||||||
|
uniform mat4 projection;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_Position = projection * view * vec4(aPos + model, 1.0);
|
||||||
|
}
|
18
ScuffedMinecraft/assets/shaders/crosshair_frag.glsl
Normal file
18
ScuffedMinecraft/assets/shaders/crosshair_frag.glsl
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#version 330 core
|
||||||
|
|
||||||
|
in vec2 TexCoord;
|
||||||
|
|
||||||
|
out vec4 FragColor;
|
||||||
|
|
||||||
|
uniform sampler2D tex;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec4 texResult = texture(tex, TexCoord);
|
||||||
|
|
||||||
|
if (texResult.a == 0)
|
||||||
|
discard;
|
||||||
|
|
||||||
|
texResult.a = 0.8;
|
||||||
|
FragColor = texResult;
|
||||||
|
}
|
14
ScuffedMinecraft/assets/shaders/crosshair_vert.glsl
Normal file
14
ScuffedMinecraft/assets/shaders/crosshair_vert.glsl
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#version 330 core
|
||||||
|
|
||||||
|
layout (location = 0) in vec2 inPos;
|
||||||
|
layout (location = 1) in vec2 inTexCoords;
|
||||||
|
|
||||||
|
uniform mat4 projection;
|
||||||
|
|
||||||
|
out vec2 TexCoord;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_Position = projection * vec4(inPos, 0.0, 1.0);
|
||||||
|
TexCoord = inTexCoords;
|
||||||
|
}
|
@ -1,12 +0,0 @@
|
|||||||
#version 330 core
|
|
||||||
|
|
||||||
in vec2 TexCoord;
|
|
||||||
|
|
||||||
out vec4 FragColor;
|
|
||||||
|
|
||||||
uniform sampler2D tex;
|
|
||||||
|
|
||||||
void main()
|
|
||||||
{
|
|
||||||
FragColor = texture(tex, TexCoord);
|
|
||||||
}
|
|
32
ScuffedMinecraft/assets/shaders/framebuffer_frag.glsl
Normal file
32
ScuffedMinecraft/assets/shaders/framebuffer_frag.glsl
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#version 330 core
|
||||||
|
|
||||||
|
out vec4 FragColor;
|
||||||
|
in vec2 TexCoords;
|
||||||
|
|
||||||
|
uniform sampler2D screenTexture;
|
||||||
|
uniform sampler2D depthTexture;
|
||||||
|
|
||||||
|
uniform bool underwater;
|
||||||
|
|
||||||
|
const vec3 fogColor = vec3(0, 0, 0.25);
|
||||||
|
const float fogNear = 0.9;
|
||||||
|
const float fogFar = 1.0;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec3 color = texture(screenTexture, TexCoords).rgb;
|
||||||
|
float depth = texture(depthTexture, TexCoords).r;
|
||||||
|
|
||||||
|
vec3 finalColor = color;
|
||||||
|
|
||||||
|
// Calculate fog
|
||||||
|
if (underwater)
|
||||||
|
{
|
||||||
|
float fogFactor = (fogFar - depth) / (fogFar - fogNear);
|
||||||
|
fogFactor = clamp(fogFactor, 0.0, 1.0);
|
||||||
|
|
||||||
|
finalColor = mix(fogColor, color, fogFactor);
|
||||||
|
}
|
||||||
|
|
||||||
|
FragColor = vec4(vec3(finalColor), 1.0);
|
||||||
|
}
|
12
ScuffedMinecraft/assets/shaders/framebuffer_vert.glsl
Normal file
12
ScuffedMinecraft/assets/shaders/framebuffer_vert.glsl
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#version 330 core
|
||||||
|
|
||||||
|
layout (location = 0) in vec2 inPos;
|
||||||
|
layout (location = 1) in vec2 inTexCoords;
|
||||||
|
|
||||||
|
out vec2 TexCoords;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_Position = vec4(inPos.x, inPos.y, 0.0, 1.0);
|
||||||
|
TexCoords = inTexCoords;
|
||||||
|
}
|
26
ScuffedMinecraft/assets/shaders/main_frag.glsl
Normal file
26
ScuffedMinecraft/assets/shaders/main_frag.glsl
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#version 330 core
|
||||||
|
|
||||||
|
in vec2 TexCoord;
|
||||||
|
in vec3 Normal;
|
||||||
|
|
||||||
|
out vec4 FragColor;
|
||||||
|
|
||||||
|
uniform sampler2D tex;
|
||||||
|
|
||||||
|
vec3 ambient = vec3(.5);
|
||||||
|
vec3 lightDirection = vec3(0.8, 1, 0.7);
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec3 lightDir = normalize(-lightDirection);
|
||||||
|
|
||||||
|
float diff = max(dot(Normal, lightDir), 0.0);
|
||||||
|
vec3 diffuse = diff * vec3(1);
|
||||||
|
|
||||||
|
vec4 result = vec4(ambient + diffuse, 1.0);
|
||||||
|
|
||||||
|
vec4 texResult = texture(tex, TexCoord);
|
||||||
|
if (texResult.a == 0)
|
||||||
|
discard;
|
||||||
|
FragColor = texResult * result;
|
||||||
|
}
|
34
ScuffedMinecraft/assets/shaders/main_vert.glsl
Normal file
34
ScuffedMinecraft/assets/shaders/main_vert.glsl
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#version 330 core
|
||||||
|
|
||||||
|
layout (location = 0) in vec3 aPos;
|
||||||
|
layout (location = 1) in vec2 aTexCoord;
|
||||||
|
layout (location = 2) in int aDirection;
|
||||||
|
|
||||||
|
out vec2 TexCoord;
|
||||||
|
out vec3 Normal;
|
||||||
|
|
||||||
|
uniform float texMultiplier;
|
||||||
|
|
||||||
|
uniform mat4 model;
|
||||||
|
uniform mat4 view;
|
||||||
|
uniform mat4 projection;
|
||||||
|
uniform float time;
|
||||||
|
|
||||||
|
// Array of possible normals based on direction
|
||||||
|
const vec3 normals[] = vec3[](
|
||||||
|
vec3( 0, 0, 1), // 0
|
||||||
|
vec3( 0, 0, -1), // 1
|
||||||
|
vec3( 1, 0, 0), // 2
|
||||||
|
vec3(-1, 0, 0), // 3
|
||||||
|
vec3( 0, 1, 0), // 4
|
||||||
|
vec3( 0, -1, 0), // 5
|
||||||
|
vec3( 0, -1, 0) // 6
|
||||||
|
);
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_Position = projection * view * model * vec4(aPos, 1.0);
|
||||||
|
TexCoord = aTexCoord * texMultiplier;
|
||||||
|
|
||||||
|
Normal = normals[aDirection];
|
||||||
|
}
|
26
ScuffedMinecraft/assets/shaders/water_frag.glsl
Normal file
26
ScuffedMinecraft/assets/shaders/water_frag.glsl
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#version 330 core
|
||||||
|
|
||||||
|
in vec2 TexCoord;
|
||||||
|
in vec3 Normal;
|
||||||
|
|
||||||
|
out vec4 FragColor;
|
||||||
|
|
||||||
|
uniform sampler2D tex;
|
||||||
|
|
||||||
|
vec3 ambient = vec3(.5);
|
||||||
|
vec3 lightDirection = vec3(0.8, 1, 0.7);
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec3 lightDir = normalize(-lightDirection);
|
||||||
|
|
||||||
|
float diff = max(dot(Normal, lightDir), 0.0);
|
||||||
|
vec3 diffuse = diff * vec3(1);
|
||||||
|
|
||||||
|
vec4 result = vec4(ambient + diffuse, 1.0);
|
||||||
|
|
||||||
|
vec4 texResult = texture(tex, TexCoord);
|
||||||
|
if (texResult.a == 0)
|
||||||
|
discard;
|
||||||
|
FragColor = texResult * result;
|
||||||
|
}
|
47
ScuffedMinecraft/assets/shaders/water_vert.glsl
Normal file
47
ScuffedMinecraft/assets/shaders/water_vert.glsl
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
#version 330 core
|
||||||
|
|
||||||
|
layout (location = 0) in vec3 aPos;
|
||||||
|
layout (location = 1) in vec2 aTexCoord;
|
||||||
|
layout (location = 2) in int aDirection;
|
||||||
|
layout (location = 3) in int aTop;
|
||||||
|
|
||||||
|
out vec2 TexCoord;
|
||||||
|
out vec3 Normal;
|
||||||
|
|
||||||
|
uniform float texMultiplier;
|
||||||
|
|
||||||
|
uniform mat4 model;
|
||||||
|
uniform mat4 view;
|
||||||
|
uniform mat4 projection;
|
||||||
|
uniform float time;
|
||||||
|
|
||||||
|
// Array of possible normals based on direction
|
||||||
|
const vec3 normals[] = vec3[](
|
||||||
|
vec3( 0, 0, 1), // 0
|
||||||
|
vec3( 0, 0, -1), // 1
|
||||||
|
vec3( 1, 0, 0), // 2
|
||||||
|
vec3(-1, 0, 0), // 3
|
||||||
|
vec3( 0, 1, 0), // 4
|
||||||
|
vec3( 0, -1, 0), // 5
|
||||||
|
vec3( 0, -1, 0) // 6
|
||||||
|
);
|
||||||
|
|
||||||
|
const int aFrames = 32;
|
||||||
|
const float animationTime = 5;
|
||||||
|
const int texNum = 16;
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec3 pos = aPos;
|
||||||
|
if (aTop == 1)
|
||||||
|
{
|
||||||
|
pos.y -= .1;
|
||||||
|
pos.y += (sin(pos.x * 3.1415926535 / 2 + time) + sin(pos.z * 3.1415926535 / 2 + time * 1.5)) * .05;
|
||||||
|
}
|
||||||
|
gl_Position = projection * view * model * vec4(pos, 1.0);
|
||||||
|
vec2 currentTex = aTexCoord;
|
||||||
|
currentTex.x += mod(floor(mod(time / animationTime, 1) * aFrames), texNum);
|
||||||
|
currentTex.y += floor(floor(mod(time / animationTime, 1) * aFrames) / texNum);
|
||||||
|
TexCoord = currentTex * texMultiplier;
|
||||||
|
|
||||||
|
Normal = normals[aDirection];
|
||||||
|
}
|
Binary file not shown.
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 9.1 KiB |
BIN
ScuffedMinecraft/assets/sprites/block_map.psd
Normal file
BIN
ScuffedMinecraft/assets/sprites/block_map.psd
Normal file
Binary file not shown.
BIN
ScuffedMinecraft/assets/sprites/crosshair.png
Normal file
BIN
ScuffedMinecraft/assets/sprites/crosshair.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 246 B |
Binary file not shown.
Before Width: | Height: | Size: 672 B |
Binary file not shown.
Before Width: | Height: | Size: 672 B |
@ -1,80 +0,0 @@
|
|||||||
[Window][Debug##Default]
|
|
||||||
Pos=60,60
|
|
||||||
Size=400,400
|
|
||||||
|
|
||||||
[Window][Test]
|
|
||||||
Pos=22,22
|
|
||||||
Size=543,95
|
|
||||||
|
|
||||||
[Window][Dear ImGui Demo]
|
|
||||||
Pos=650,20
|
|
||||||
Size=550,680
|
|
||||||
|
|
||||||
[Table][0xC9935533,3]
|
|
||||||
Column 0 Weight=1.0000
|
|
||||||
Column 1 Weight=1.0000
|
|
||||||
Column 2 Weight=1.0000
|
|
||||||
|
|
||||||
[Table][0x64418101,3]
|
|
||||||
RefScale=13
|
|
||||||
Column 0 Width=63
|
|
||||||
Column 1 Width=63
|
|
||||||
Column 2 Width=63
|
|
||||||
|
|
||||||
[Table][0x47600645,3]
|
|
||||||
RefScale=13
|
|
||||||
Column 0 Width=63
|
|
||||||
Column 1 Width=63
|
|
||||||
Column 2 Weight=1.0000
|
|
||||||
|
|
||||||
[Table][0xDE6957FF,6]
|
|
||||||
RefScale=13
|
|
||||||
Column 0 Width=63
|
|
||||||
Column 1 Width=63
|
|
||||||
Column 2 Width=-1
|
|
||||||
Column 3 Weight=1.0000
|
|
||||||
Column 4 Weight=1.0000
|
|
||||||
Column 5 Weight=-1.0000
|
|
||||||
|
|
||||||
[Table][0x861D378E,3]
|
|
||||||
Column 0 Weight=1.0000
|
|
||||||
Column 1 Weight=1.0000
|
|
||||||
Column 2 Weight=1.0000
|
|
||||||
|
|
||||||
[Table][0x1F146634,3]
|
|
||||||
RefScale=13
|
|
||||||
Column 0 Width=63
|
|
||||||
Column 1 Width=63
|
|
||||||
Column 2 Width=63
|
|
||||||
|
|
||||||
[Table][0x8DFA6E86,2]
|
|
||||||
Column 0 Weight=1.0000
|
|
||||||
Column 1 Weight=1.0000
|
|
||||||
|
|
||||||
[Table][0xFABAAEF7,2]
|
|
||||||
Column 0 Weight=1.0000
|
|
||||||
Column 1 Weight=1.0000
|
|
||||||
|
|
||||||
[Table][0xA43C3885,3]
|
|
||||||
RefScale=13
|
|
||||||
Column 0 Width=56
|
|
||||||
Column 1 Width=56
|
|
||||||
Column 2 Width=56
|
|
||||||
|
|
||||||
[Table][0x49F8DCEA,3]
|
|
||||||
RefScale=13
|
|
||||||
Column 0 Weight=1.0000
|
|
||||||
Column 1 Width=84
|
|
||||||
Column 2 Width=126
|
|
||||||
|
|
||||||
[Table][0x82CBB907,3]
|
|
||||||
Column 0 Weight=1.0000
|
|
||||||
Column 1 Weight=1.0000
|
|
||||||
Column 2 Weight=1.0000
|
|
||||||
|
|
||||||
[Table][0x49D11DC0,3]
|
|
||||||
RefScale=13
|
|
||||||
Column 0 Width=86
|
|
||||||
Column 1 Width=86
|
|
||||||
Column 2 Width=86
|
|
||||||
|
|
@ -2,6 +2,13 @@
|
|||||||
#include "imgui_impl_glfw.h"
|
#include "imgui_impl_glfw.h"
|
||||||
#include "imgui_impl_opengl3.h"
|
#include "imgui_impl_opengl3.h"
|
||||||
|
|
||||||
|
#ifdef LINUX
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <glad/glad.h>
|
#include <glad/glad.h>
|
||||||
#include <GLFW/glfw3.h>
|
#include <GLFW/glfw3.h>
|
||||||
#define STB_IMAGE_IMPLEMENTATION
|
#define STB_IMAGE_IMPLEMENTATION
|
||||||
@ -16,11 +23,14 @@
|
|||||||
#include "Shader.h"
|
#include "Shader.h"
|
||||||
#include "Camera.h"
|
#include "Camera.h"
|
||||||
#include "Planet.h"
|
#include "Planet.h"
|
||||||
|
#include "Blocks.h"
|
||||||
|
#include "Physics.h"
|
||||||
|
|
||||||
void framebufferSizeCallback(GLFWwindow* window, int width, int height);
|
void framebufferSizeCallback(GLFWwindow* window, int width, int height);
|
||||||
void processInput(GLFWwindow* window);
|
void processInput(GLFWwindow* window);
|
||||||
void mouse_callback(GLFWwindow* window, double xpos, double ypos);
|
void mouse_callback(GLFWwindow* window, double xpos, double ypos);
|
||||||
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
|
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
|
||||||
|
void mouse_button_callback(GLFWwindow* window, int button, int action, int mods);
|
||||||
|
|
||||||
float deltaTime = 0.0f;
|
float deltaTime = 0.0f;
|
||||||
float lastFrame = 0.0f;
|
float lastFrame = 0.0f;
|
||||||
@ -34,17 +44,94 @@ bool firstMouse = true;
|
|||||||
|
|
||||||
bool menuMode = false;
|
bool menuMode = false;
|
||||||
bool escapeDown = false;
|
bool escapeDown = false;
|
||||||
|
bool f1Down = false;
|
||||||
|
|
||||||
|
// Window settings
|
||||||
float windowX = 1920;
|
float windowX = 1920;
|
||||||
float windowY = 1080;
|
float windowY = 1080;
|
||||||
|
bool vsync = true;
|
||||||
|
|
||||||
|
uint16_t selectedBlock = 1;
|
||||||
|
|
||||||
|
bool uiEnabled = true;
|
||||||
|
|
||||||
Camera camera;
|
Camera camera;
|
||||||
|
|
||||||
// Window options
|
GLuint framebufferTexture;
|
||||||
#define VSYNC 1 // 0 for off, 1 for on
|
GLuint depthTexture;
|
||||||
|
|
||||||
int main()
|
float rectangleVertices[] =
|
||||||
{
|
{
|
||||||
|
// Coords // TexCoords
|
||||||
|
1.0f, -1.0f, 1.0f, 0.0f,
|
||||||
|
-1.0f, -1.0f, 0.0f, 0.0f,
|
||||||
|
-1.0f, 1.0f, 0.0f, 1.0f,
|
||||||
|
|
||||||
|
1.0f, 1.0f, 1.0f, 1.0f,
|
||||||
|
1.0f, -1.0f, 1.0f, 0.0f,
|
||||||
|
-1.0f, 1.0f, 0.0f, 1.0f
|
||||||
|
};
|
||||||
|
|
||||||
|
float outlineVertices[] =
|
||||||
|
{
|
||||||
|
-.001f, -.001f, -.001f, 1.001f, -.001f, -.001f,
|
||||||
|
1.001f, -.001f, -.001f, 1.001f, 1.001f, -.001f,
|
||||||
|
1.001f, 1.001f, -.001f, -.001f, 1.001f, -.001f,
|
||||||
|
-.001f, 1.001f, -.001f, -.001f, -.001f, -.001f,
|
||||||
|
|
||||||
|
-.001f, -.001f, -.001f, -.001f, -.001f, 1.001f,
|
||||||
|
-.001f, -.001f, 1.001f, -.001f, 1.001f, 1.001f,
|
||||||
|
-.001f, 1.001f, 1.001f, -.001f, 1.001f, -.001f,
|
||||||
|
|
||||||
|
1.001f, -.001f, -.001f, 1.001f, -.001f, 1.001f,
|
||||||
|
1.001f, -.001f, 1.001f, 1.001f, 1.001f, 1.001f,
|
||||||
|
1.001f, 1.001f, 1.001f, 1.001f, 1.001f, -.001f,
|
||||||
|
|
||||||
|
-.001f, -.001f, 1.001f, 1.001f, -.001f, 1.001f,
|
||||||
|
-.001f, 1.001f, 1.001f, 1.001f, 1.001f, 1.001f,
|
||||||
|
};
|
||||||
|
|
||||||
|
float crosshairVertices[] =
|
||||||
|
{
|
||||||
|
windowX / 2 - 13.5, windowY / 2 - 13.5, 0.0f, 0.0f,
|
||||||
|
windowX / 2 + 13.5, windowY / 2 - 13.5, 1.0f, 0.0f,
|
||||||
|
windowX / 2 + 13.5, windowY / 2 + 13.5, 1.0f, 1.0f,
|
||||||
|
|
||||||
|
windowX / 2 - 13.5, windowY / 2 - 13.5, 0.0f, 0.0f,
|
||||||
|
windowX / 2 - 13.5, windowY / 2 + 13.5, 0.0f, 1.0f,
|
||||||
|
windowX / 2 + 13.5, windowY / 2 + 13.5, 1.0f, 1.0f,
|
||||||
|
};
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
#ifdef LINUX
|
||||||
|
char* resolved_path = realpath(argv[0], NULL);
|
||||||
|
if (resolved_path == NULL) {
|
||||||
|
printf("%s: Please do not place binary in PATH\n", argv[0]);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
size_t resolved_length = strlen(resolved_path);
|
||||||
|
// remove executable from path
|
||||||
|
for (size_t i = resolved_length; i > 0; i--) {
|
||||||
|
if (resolved_path[i] == '/' && resolved_path[i + 1] != 0) {
|
||||||
|
resolved_path[i + 1] = 0;
|
||||||
|
resolved_length = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
char* assets_path = (char*)malloc(resolved_length + strlen("assets") + 2);
|
||||||
|
strcpy(assets_path, resolved_path);
|
||||||
|
strcpy(assets_path + resolved_length + 1, "assets");
|
||||||
|
struct stat path_stat;
|
||||||
|
if (stat(assets_path, &path_stat) == -1 || !S_ISDIR(path_stat.st_mode)) {
|
||||||
|
printf("%s: Asset directory not found\n", argv[0]);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
free(assets_path);
|
||||||
|
|
||||||
|
chdir(resolved_path);
|
||||||
|
free(resolved_path);
|
||||||
|
#endif
|
||||||
// Initialize GLFW
|
// Initialize GLFW
|
||||||
glfwInit();
|
glfwInit();
|
||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||||
@ -52,15 +139,15 @@ int main()
|
|||||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||||
|
|
||||||
// Create window
|
// Create window
|
||||||
GLFWwindow* window = glfwCreateWindow(windowX, windowY, "Scuffed Minecraft", NULL, NULL);
|
GLFWwindow* window = glfwCreateWindow(windowX, windowY, "Scuffed Minecraft", nullptr, nullptr);
|
||||||
if (window == NULL)
|
if (window == nullptr)
|
||||||
{
|
{
|
||||||
std::cout << "Failed to create GLFW window\n";
|
std::cout << "Failed to create GLFW window\n";
|
||||||
glfwTerminate();
|
glfwTerminate();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
glfwMakeContextCurrent(window);
|
glfwMakeContextCurrent(window);
|
||||||
glfwSwapInterval(VSYNC);
|
glfwSwapInterval(vsync ? 1 : 0);
|
||||||
|
|
||||||
// Initialize GLAD
|
// Initialize GLAD
|
||||||
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
|
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
|
||||||
@ -74,6 +161,7 @@ int main()
|
|||||||
glfwSetFramebufferSizeCallback(window, framebufferSizeCallback);
|
glfwSetFramebufferSizeCallback(window, framebufferSizeCallback);
|
||||||
glfwSetCursorPosCallback(window, mouse_callback);
|
glfwSetCursorPosCallback(window, mouse_callback);
|
||||||
glfwSetScrollCallback(window, scroll_callback);
|
glfwSetScrollCallback(window, scroll_callback);
|
||||||
|
glfwSetMouseButtonCallback(window, mouse_button_callback);
|
||||||
|
|
||||||
glClearColor(0.6f, 0.8f, 1.0f, 1.0f);
|
glClearColor(0.6f, 0.8f, 1.0f, 1.0f);
|
||||||
|
|
||||||
@ -84,13 +172,93 @@ int main()
|
|||||||
|
|
||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
|
||||||
// Create shader
|
// Create shaders
|
||||||
Shader shader("assets/shaders/vertex_shader.glsl", "assets/shaders/fragment_shader.glsl");
|
Shader shader("assets/shaders/main_vert.glsl", "assets/shaders/main_frag.glsl");
|
||||||
shader.use();
|
shader.use();
|
||||||
|
|
||||||
shader.setFloat("texMultiplier", .5f);
|
shader.setFloat("texMultiplier", 0.0625f);
|
||||||
|
|
||||||
// Create texture
|
Shader waterShader("assets/shaders/water_vert.glsl", "assets/shaders/water_frag.glsl");
|
||||||
|
waterShader.use();
|
||||||
|
|
||||||
|
waterShader.setFloat("texMultiplier", 0.0625f);
|
||||||
|
|
||||||
|
Shader billboardShader("assets/shaders/billboard_vert.glsl", "assets/shaders/billboard_frag.glsl");
|
||||||
|
billboardShader.use();
|
||||||
|
|
||||||
|
billboardShader.setFloat("texMultiplier", 0.0625f);
|
||||||
|
|
||||||
|
Shader framebufferShader("assets/shaders/framebuffer_vert.glsl", "assets/shaders/framebuffer_frag.glsl");
|
||||||
|
|
||||||
|
Shader outlineShader("assets/shaders/block_outline_vert.glsl", "assets/shaders/block_outline_frag.glsl");
|
||||||
|
|
||||||
|
Shader crosshairShader("assets/shaders/crosshair_vert.glsl", "assets/shaders/crosshair_frag.glsl");
|
||||||
|
|
||||||
|
// Create post-processing framebuffer
|
||||||
|
unsigned int FBO;
|
||||||
|
glGenFramebuffers(1, &FBO);
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, FBO);
|
||||||
|
|
||||||
|
glGenTextures(1, &framebufferTexture);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, framebufferTexture);
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, windowX, windowY, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
|
||||||
|
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_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, framebufferTexture, 0);
|
||||||
|
|
||||||
|
glGenTextures(1, &depthTexture);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, depthTexture);
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, windowX, windowY, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
|
||||||
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0);
|
||||||
|
|
||||||
|
auto fboStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||||
|
if (fboStatus != GL_FRAMEBUFFER_COMPLETE)
|
||||||
|
std::cout << "Framebuffer error: " << fboStatus << '\n';
|
||||||
|
|
||||||
|
unsigned int rectVAO, rectVBO;
|
||||||
|
glGenVertexArrays(1, &rectVAO);
|
||||||
|
glGenBuffers(1, &rectVBO);
|
||||||
|
glBindVertexArray(rectVAO);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, rectVBO);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, sizeof(rectangleVertices), &rectangleVertices, GL_STATIC_DRAW);
|
||||||
|
glEnableVertexAttribArray(0);
|
||||||
|
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)0);
|
||||||
|
glEnableVertexAttribArray(1);
|
||||||
|
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float)));
|
||||||
|
|
||||||
|
framebufferShader.use();
|
||||||
|
glUniform1i(glGetUniformLocation(framebufferShader.ID, "screenTexture"), 0);
|
||||||
|
glUniform1i(glGetUniformLocation(framebufferShader.ID, "depthTexture"), 1);
|
||||||
|
|
||||||
|
unsigned int outlineVAO, outlineVBO;
|
||||||
|
glGenVertexArrays(1, &outlineVAO);
|
||||||
|
glGenBuffers(1, &outlineVBO);
|
||||||
|
glBindVertexArray(outlineVAO);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, outlineVBO);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, sizeof(outlineVertices), &outlineVertices, GL_STATIC_DRAW);
|
||||||
|
glEnableVertexAttribArray(0);
|
||||||
|
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
|
||||||
|
|
||||||
|
unsigned int crosshairVAO, crosshairVBO;
|
||||||
|
glGenVertexArrays(1, &crosshairVAO);
|
||||||
|
glGenBuffers(1, &crosshairVBO);
|
||||||
|
glBindVertexArray(crosshairVAO);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, crosshairVBO);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, sizeof(crosshairVertices), &crosshairVertices, GL_STATIC_DRAW);
|
||||||
|
glEnableVertexAttribArray(0);
|
||||||
|
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)0);
|
||||||
|
glEnableVertexAttribArray(1);
|
||||||
|
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float)));
|
||||||
|
|
||||||
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
|
||||||
|
// Create terrain texture
|
||||||
unsigned int texture;
|
unsigned int texture;
|
||||||
glGenTextures(1, &texture);
|
glGenTextures(1, &texture);
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
@ -117,12 +285,38 @@ int main()
|
|||||||
|
|
||||||
stbi_image_free(data);
|
stbi_image_free(data);
|
||||||
|
|
||||||
|
// Create crosshair texture
|
||||||
|
unsigned int crosshairTexture;
|
||||||
|
glGenTextures(1, &crosshairTexture);
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, crosshairTexture);
|
||||||
|
|
||||||
|
// Set texture parameters
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
|
||||||
|
// Load Crosshair Texture
|
||||||
|
unsigned char* data2 = stbi_load("assets/sprites/crosshair.png", &width, &height, &nrChannels, 0);
|
||||||
|
if (data2)
|
||||||
|
{
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data2);
|
||||||
|
glGenerateMipmap(GL_TEXTURE_2D);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout << "Failed to load texture\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
stbi_image_free(data2);
|
||||||
|
|
||||||
// Create camera
|
// Create camera
|
||||||
camera = Camera(glm::vec3(0.0f, 25.0f, 0.0f));
|
camera = Camera(glm::vec3(0.0f, 25.0f, 0.0f));
|
||||||
|
|
||||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
||||||
|
|
||||||
Planet::planet = new Planet();
|
Planet::planet = new Planet(&shader, &waterShader, &billboardShader);
|
||||||
|
|
||||||
|
glm::mat4 ortho = glm::ortho(0.0f, (float)windowX, (float)windowY, 0.0f, 0.0f, 10.0f);
|
||||||
|
|
||||||
// Initialize ImGui
|
// Initialize ImGui
|
||||||
IMGUI_CHECKVERSION();
|
IMGUI_CHECKVERSION();
|
||||||
@ -149,7 +343,7 @@ int main()
|
|||||||
highestFps = fps;
|
highestFps = fps;
|
||||||
fpsCount++;
|
fpsCount++;
|
||||||
std::chrono::steady_clock::time_point currentTimePoint = std::chrono::steady_clock::now();
|
std::chrono::steady_clock::time_point currentTimePoint = std::chrono::steady_clock::now();
|
||||||
if (std::chrono::duration_cast<std::chrono::milliseconds>(currentTimePoint - fpsStartTime).count() > 1000)
|
if (std::chrono::duration_cast<std::chrono::seconds>(currentTimePoint - fpsStartTime).count() >= 1)
|
||||||
{
|
{
|
||||||
avgFps = fpsCount;
|
avgFps = fpsCount;
|
||||||
lowestFps = -1;
|
lowestFps = -1;
|
||||||
@ -158,11 +352,21 @@ int main()
|
|||||||
fpsStartTime = currentTimePoint;
|
fpsStartTime = currentTimePoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
waterShader.use();
|
||||||
|
waterShader.setFloat("time", currentFrame);
|
||||||
|
outlineShader.use();
|
||||||
|
outlineShader.setFloat("time", currentFrame);
|
||||||
|
|
||||||
// Input
|
// Input
|
||||||
processInput(window);
|
processInput(window);
|
||||||
|
|
||||||
// Rendering
|
// Rendering
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, FBO);
|
||||||
|
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, texture);
|
||||||
|
|
||||||
// New ImGui frame
|
// New ImGui frame
|
||||||
ImGui_ImplOpenGL3_NewFrame();
|
ImGui_ImplOpenGL3_NewFrame();
|
||||||
@ -173,31 +377,151 @@ int main()
|
|||||||
glm::mat4 view = camera.GetViewMatrix();
|
glm::mat4 view = camera.GetViewMatrix();
|
||||||
|
|
||||||
glm::mat4 projection;
|
glm::mat4 projection;
|
||||||
projection = glm::perspective(glm::radians(camera.Zoom), windowX / windowY, 0.1f, 100.0f);
|
projection = glm::perspective(glm::radians(camera.Zoom), windowX / windowY, 0.1f, 1000.0f);
|
||||||
|
|
||||||
|
shader.use();
|
||||||
unsigned int viewLoc = glGetUniformLocation(shader.ID, "view");
|
unsigned int viewLoc = glGetUniformLocation(shader.ID, "view");
|
||||||
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
|
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
|
||||||
unsigned int projectionLoc = glGetUniformLocation(shader.ID, "projection");
|
unsigned int projectionLoc = glGetUniformLocation(shader.ID, "projection");
|
||||||
glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, glm::value_ptr(projection));
|
glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, glm::value_ptr(projection));
|
||||||
|
|
||||||
unsigned int modelLoc = glGetUniformLocation(shader.ID, "model");
|
waterShader.use();
|
||||||
|
viewLoc = glGetUniformLocation(waterShader.ID, "view");
|
||||||
|
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
|
||||||
|
projectionLoc = glGetUniformLocation(waterShader.ID, "projection");
|
||||||
|
glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, glm::value_ptr(projection));
|
||||||
|
|
||||||
std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now();
|
billboardShader.use();
|
||||||
Planet::planet->Update(camera.Position.x, camera.Position.y, camera.Position.z, modelLoc);
|
viewLoc = glGetUniformLocation(billboardShader.ID, "view");
|
||||||
std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
|
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
|
||||||
|
projectionLoc = glGetUniformLocation(billboardShader.ID, "projection");
|
||||||
|
glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, glm::value_ptr(projection));
|
||||||
|
|
||||||
std::cout << "Planet Update: "
|
outlineShader.use();
|
||||||
<< std::chrono::duration_cast<std::chrono::milliseconds>(end - begin).count()
|
viewLoc = glGetUniformLocation(outlineShader.ID, "view");
|
||||||
<< "[ms]\n";
|
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
|
||||||
|
projectionLoc = glGetUniformLocation(outlineShader.ID, "projection");
|
||||||
|
glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, glm::value_ptr(projection));
|
||||||
|
|
||||||
// Draw ImGui UI
|
Planet::planet->Update(camera.Position);
|
||||||
ImGui::Begin("Test");
|
|
||||||
ImGui::Text("FPS: %f (Avg: %f, Min: %f, Max: %f)", fps, avgFps, lowestFps, highestFps);
|
|
||||||
ImGui::Text("MS: %f", deltaTime * 100.0f);
|
|
||||||
ImGui::Text("Chunks: %d (%d rendered)", Planet::planet->numChunks, Planet::planet->numChunksRendered);
|
|
||||||
ImGui::End();
|
|
||||||
|
|
||||||
ImGui::Render();
|
// -- Render block outline -- //
|
||||||
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
if (uiEnabled)
|
||||||
|
{
|
||||||
|
// Get block position
|
||||||
|
auto result = Physics::Raycast(camera.Position, camera.Front, 5);
|
||||||
|
if (result.hit)
|
||||||
|
{
|
||||||
|
outlineShader.use();
|
||||||
|
|
||||||
|
// Set outline view to position
|
||||||
|
unsigned int modelLoc = glGetUniformLocation(outlineShader.ID, "model");
|
||||||
|
glUniform3f(modelLoc, result.blockX, result.blockY, result.blockZ);
|
||||||
|
|
||||||
|
// Render
|
||||||
|
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||||
|
//glEnable(GL_COLOR_LOGIC_OP);
|
||||||
|
glLogicOp(GL_INVERT);
|
||||||
|
glDisable(GL_CULL_FACE);
|
||||||
|
glBindVertexArray(outlineVAO);
|
||||||
|
glLineWidth(2.0);
|
||||||
|
glDrawArrays(GL_LINES, 0, 24);
|
||||||
|
|
||||||
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||||
|
glEnable(GL_CULL_FACE);
|
||||||
|
//glDisable(GL_COLOR_LOGIC_OP);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
framebufferShader.use();
|
||||||
|
|
||||||
|
// -- Post Processing Stuff -- //
|
||||||
|
|
||||||
|
// Check if player is underwater
|
||||||
|
int blockX = camera.Position.x < 0 ? camera.Position.x - 1 : camera.Position.x;
|
||||||
|
int blockY = camera.Position.y < 0 ? camera.Position.y - 1 : camera.Position.y;
|
||||||
|
int blockZ = camera.Position.z < 0 ? camera.Position.z - 1 : camera.Position.z;
|
||||||
|
|
||||||
|
int chunkX = blockX < 0 ? floorf(blockX / (float)CHUNK_SIZE) : blockX / (int)CHUNK_SIZE;
|
||||||
|
int chunkY = blockY < 0 ? floorf(blockY / (float)CHUNK_SIZE) : blockY / (int)CHUNK_SIZE;
|
||||||
|
int chunkZ = blockZ < 0 ? floorf(blockZ / (float)CHUNK_SIZE) : blockZ / (int)CHUNK_SIZE;
|
||||||
|
|
||||||
|
int localBlockX = blockX - (chunkX * CHUNK_SIZE);
|
||||||
|
int localBlockY = blockY - (chunkY * CHUNK_SIZE);
|
||||||
|
int localBlockZ = blockZ - (chunkZ * CHUNK_SIZE);
|
||||||
|
|
||||||
|
Chunk* chunk = Planet::planet->GetChunk(ChunkPos(chunkX, chunkY, chunkZ));
|
||||||
|
if (chunk != nullptr)
|
||||||
|
{
|
||||||
|
unsigned int blockType = chunk->GetBlockAtPos(
|
||||||
|
localBlockX,
|
||||||
|
localBlockY,
|
||||||
|
localBlockZ);
|
||||||
|
|
||||||
|
if (Blocks::blocks[blockType].blockType == Block::LIQUID)
|
||||||
|
{
|
||||||
|
framebufferShader.setBool("underwater", true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
framebufferShader.setBool("underwater", false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Post Processing
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
|
glBindVertexArray(rectVAO);
|
||||||
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, framebufferTexture);
|
||||||
|
glActiveTexture(GL_TEXTURE1);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, depthTexture);
|
||||||
|
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||||
|
|
||||||
|
if (uiEnabled)
|
||||||
|
{
|
||||||
|
// -- Render Crosshair -- //
|
||||||
|
|
||||||
|
// Render
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, crosshairTexture);
|
||||||
|
|
||||||
|
crosshairShader.use();
|
||||||
|
glDisable(GL_CULL_FACE);
|
||||||
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
glEnable(GL_BLEND);
|
||||||
|
glEnable(GL_COLOR_LOGIC_OP);
|
||||||
|
|
||||||
|
unsigned int crosshairProjLoc = glGetUniformLocation(crosshairShader.ID, "projection");
|
||||||
|
glUniformMatrix4fv(crosshairProjLoc, 1, GL_FALSE, glm::value_ptr(ortho));
|
||||||
|
glBindVertexArray(crosshairVAO);
|
||||||
|
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||||
|
|
||||||
|
glEnable(GL_CULL_FACE);
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
glDisable(GL_BLEND);
|
||||||
|
glDisable(GL_COLOR_LOGIC_OP);
|
||||||
|
|
||||||
|
// Draw ImGui UI
|
||||||
|
ImGui::Begin("Test");
|
||||||
|
ImGui::Text("FPS: %d (Avg: %d, Min: %d, Max: %d)", (int)fps, (int)avgFps, (int)lowestFps, (int)highestFps);
|
||||||
|
ImGui::Text("MS: %f", deltaTime * 100.0f);
|
||||||
|
if (ImGui::Checkbox("VSYNC", &vsync))
|
||||||
|
glfwSwapInterval(vsync ? 1 : 0);
|
||||||
|
ImGui::Text("Chunks: %d (%d rendered)", Planet::planet->numChunks, Planet::planet->numChunksRendered);
|
||||||
|
ImGui::Text("Position: x: %f, y: %f, z: %f", camera.Position.x, camera.Position.y, camera.Position.z);
|
||||||
|
ImGui::Text("Direction: x: %f, y: %f, z: %f", camera.Front.x, camera.Front.y, camera.Front.z);
|
||||||
|
ImGui::Text("Selected Block: %s", Blocks::blocks[selectedBlock].blockName.c_str());
|
||||||
|
if (ImGui::SliderInt("Render Distance", &Planet::planet->renderDistance, 0, 30))
|
||||||
|
Planet::planet->ClearChunkQueue();
|
||||||
|
if (ImGui::SliderInt("Render Height", &Planet::planet->renderHeight, 0, 10))
|
||||||
|
Planet::planet->ClearChunkQueue();
|
||||||
|
ImGui::Checkbox("Use absolute Y axis for camera vertical movement", &camera.absoluteVerticalMovement);
|
||||||
|
ImGui::End();
|
||||||
|
|
||||||
|
ImGui::Render();
|
||||||
|
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
||||||
|
}
|
||||||
|
|
||||||
// Check and call events and swap buffers
|
// Check and call events and swap buffers
|
||||||
glfwSwapBuffers(window);
|
glfwSwapBuffers(window);
|
||||||
@ -206,6 +530,8 @@ int main()
|
|||||||
//std::cout << camera.Position.x << ", " << camera.Position.y << ", " << camera.Position.z << '\n';
|
//std::cout << camera.Position.x << ", " << camera.Position.y << ", " << camera.Position.z << '\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
delete Planet::planet;
|
||||||
|
|
||||||
ImGui_ImplOpenGL3_Shutdown();
|
ImGui_ImplOpenGL3_Shutdown();
|
||||||
ImGui_ImplGlfw_Shutdown();
|
ImGui_ImplGlfw_Shutdown();
|
||||||
ImGui::DestroyContext();
|
ImGui::DestroyContext();
|
||||||
@ -218,10 +544,18 @@ void framebufferSizeCallback(GLFWwindow* window, int width, int height)
|
|||||||
windowX = width;
|
windowX = width;
|
||||||
windowY = height;
|
windowY = height;
|
||||||
glViewport(0, 0, width, height);
|
glViewport(0, 0, width, height);
|
||||||
|
|
||||||
|
// resize framebuffer texture
|
||||||
|
glBindTexture(GL_TEXTURE_2D, framebufferTexture);
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, windowX, windowY, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
|
||||||
|
// resize framebuffer depth texture
|
||||||
|
glBindTexture(GL_TEXTURE_2D, depthTexture);
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, windowX, windowY, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void processInput(GLFWwindow* window)
|
void processInput(GLFWwindow* window)
|
||||||
{
|
{
|
||||||
|
// Pause
|
||||||
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
|
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
|
||||||
{
|
{
|
||||||
if (escapeDown)
|
if (escapeDown)
|
||||||
@ -236,8 +570,25 @@ void processInput(GLFWwindow* window)
|
|||||||
else
|
else
|
||||||
escapeDown = false;
|
escapeDown = false;
|
||||||
|
|
||||||
|
// UI Toggle
|
||||||
|
if (glfwGetKey(window, GLFW_KEY_F1) == GLFW_PRESS)
|
||||||
|
{
|
||||||
|
if (f1Down)
|
||||||
|
return;
|
||||||
|
|
||||||
|
f1Down = true;
|
||||||
|
uiEnabled = !uiEnabled;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
f1Down = false;
|
||||||
|
|
||||||
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
|
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
|
||||||
camera.ProcessKeyboard(FORWARD, deltaTime);
|
{
|
||||||
|
if (glfwGetKey(window, GLFW_KEY_SPACE) == GLFW_PRESS)
|
||||||
|
camera.ProcessKeyboard(FORWARD_NO_Y, deltaTime);
|
||||||
|
else
|
||||||
|
camera.ProcessKeyboard(FORWARD, deltaTime);
|
||||||
|
}
|
||||||
if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
|
if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
|
||||||
camera.ProcessKeyboard(BACKWARD, deltaTime);
|
camera.ProcessKeyboard(BACKWARD, deltaTime);
|
||||||
if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
|
if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
|
||||||
@ -250,6 +601,61 @@ void processInput(GLFWwindow* window)
|
|||||||
camera.ProcessKeyboard(DOWN, deltaTime);
|
camera.ProcessKeyboard(DOWN, deltaTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void mouse_button_callback(GLFWwindow* window, int button, int action, int mods)
|
||||||
|
{
|
||||||
|
if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS)
|
||||||
|
{
|
||||||
|
auto result = Physics::Raycast(camera.Position, camera.Front, 5);
|
||||||
|
if (!result.hit)
|
||||||
|
return;
|
||||||
|
|
||||||
|
result.chunk->UpdateBlock(result.localBlockX, result.localBlockY, result.localBlockZ, 0);
|
||||||
|
}
|
||||||
|
else if (button == GLFW_MOUSE_BUTTON_MIDDLE && action == GLFW_PRESS)
|
||||||
|
{
|
||||||
|
auto result = Physics::Raycast(camera.Position, camera.Front, 5);
|
||||||
|
if (!result.hit)
|
||||||
|
return;
|
||||||
|
|
||||||
|
selectedBlock = result.chunk->GetBlockAtPos(result.localBlockX, result.localBlockY, result.localBlockZ);
|
||||||
|
}
|
||||||
|
else if (button == GLFW_MOUSE_BUTTON_RIGHT && action == GLFW_PRESS)
|
||||||
|
{
|
||||||
|
auto result = Physics::Raycast(camera.Position, camera.Front, 5);
|
||||||
|
if (!result.hit)
|
||||||
|
return;
|
||||||
|
|
||||||
|
float distX = result.hitPos.x - (result.blockX + .5f);
|
||||||
|
float distY = result.hitPos.y - (result.blockY + .5f);
|
||||||
|
float distZ = result.hitPos.z - (result.blockZ + .5f);
|
||||||
|
|
||||||
|
int blockX = result.blockX;
|
||||||
|
int blockY = result.blockY;
|
||||||
|
int blockZ = result.blockZ;
|
||||||
|
|
||||||
|
// Choose face to place on
|
||||||
|
if (abs(distX) > abs(distY) && abs(distX) > abs(distZ))
|
||||||
|
blockX += (distX > 0 ? 1 : -1);
|
||||||
|
else if (abs(distY) > abs(distX) && abs(distY) > abs(distZ))
|
||||||
|
blockY += (distY > 0 ? 1 : -1);
|
||||||
|
else
|
||||||
|
blockZ += (distZ > 0 ? 1 : -1);
|
||||||
|
|
||||||
|
int chunkX = blockX < 0 ? floorf(blockX / (float)CHUNK_SIZE) : blockX / (int)CHUNK_SIZE;
|
||||||
|
int chunkY = blockY < 0 ? floorf(blockY / (float)CHUNK_SIZE) : blockY / (int)CHUNK_SIZE;
|
||||||
|
int chunkZ = blockZ < 0 ? floorf(blockZ / (float)CHUNK_SIZE) : blockZ / (int)CHUNK_SIZE;
|
||||||
|
|
||||||
|
int localBlockX = blockX - (chunkX * CHUNK_SIZE);
|
||||||
|
int localBlockY = blockY - (chunkY * CHUNK_SIZE);
|
||||||
|
int localBlockZ = blockZ - (chunkZ * CHUNK_SIZE);
|
||||||
|
|
||||||
|
Chunk* chunk = Planet::planet->GetChunk(ChunkPos(chunkX, chunkY, chunkZ));
|
||||||
|
uint16_t blockToReplace = chunk->GetBlockAtPos(localBlockX, localBlockY, localBlockZ);
|
||||||
|
if (chunk != nullptr && (blockToReplace == 0 || Blocks::blocks[blockToReplace].blockType == Block::LIQUID))
|
||||||
|
chunk->UpdateBlock(localBlockX, localBlockY, localBlockZ, selectedBlock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void mouse_callback(GLFWwindow* window, double xpos, double ypos)
|
void mouse_callback(GLFWwindow* window, double xpos, double ypos)
|
||||||
{
|
{
|
||||||
if (menuMode)
|
if (menuMode)
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "Block.h"
|
#include "Block.h"
|
||||||
|
|
||||||
Block::Block(char minX, char minY, char maxX, char maxY)
|
Block::Block(char minX, char minY, char maxX, char maxY, BLOCK_TYPE blockType, std::string blockName)
|
||||||
|
: blockType(blockType), blockName(blockName)
|
||||||
{
|
{
|
||||||
topMinX = minX;
|
topMinX = minX;
|
||||||
topMinY = minY;
|
topMinY = minY;
|
||||||
@ -20,7 +21,8 @@ Block::Block(char minX, char minY, char maxX, char maxY)
|
|||||||
|
|
||||||
Block::Block(char topMinX, char topMinY, char topMaxX, char topMaxY,
|
Block::Block(char topMinX, char topMinY, char topMaxX, char topMaxY,
|
||||||
char bottomMinX, char bottomMinY, char bottomMaxX, char bottomMaxY,
|
char bottomMinX, char bottomMinY, char bottomMaxX, char bottomMaxY,
|
||||||
char sideMinX, char sideMinY, char sideMaxX, char sideMaxY)
|
char sideMinX, char sideMinY, char sideMaxX, char sideMaxY, BLOCK_TYPE blockType, std::string blockName)
|
||||||
|
: blockType(blockType), blockName(blockName)
|
||||||
{
|
{
|
||||||
this->topMinX = topMinX;
|
this->topMinX = topMinX;
|
||||||
this->topMinY = topMinY;
|
this->topMinY = topMinY;
|
||||||
|
@ -1,14 +1,28 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
struct Block
|
struct Block
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
enum BLOCK_TYPE
|
||||||
|
{
|
||||||
|
SOLID,
|
||||||
|
TRANSPARENT,
|
||||||
|
LEAVES,
|
||||||
|
BILLBOARD,
|
||||||
|
LIQUID
|
||||||
|
};
|
||||||
|
|
||||||
char topMinX, topMinY, topMaxX, topMaxY;
|
char topMinX, topMinY, topMaxX, topMaxY;
|
||||||
char bottomMinX, bottomMinY, bottomMaxX, bottomMaxY;
|
char bottomMinX, bottomMinY, bottomMaxX, bottomMaxY;
|
||||||
char sideMinX, sideMinY, sideMaxX, sideMaxY;
|
char sideMinX, sideMinY, sideMaxX, sideMaxY;
|
||||||
|
BLOCK_TYPE blockType;
|
||||||
|
std::string blockName;
|
||||||
|
|
||||||
Block(char minX, char minY, char maxX, char maxY);
|
Block(char minX, char minY, char maxX, char maxY, BLOCK_TYPE blockType, std::string blockName);
|
||||||
Block(char topMinX, char topMinY, char topMaxX, char topMaxY,
|
Block(char topMinX, char topMinY, char topMaxX, char topMaxY,
|
||||||
char bottomMinX, char bottomMinY, char bottomMaxX, char bottomMaxY,
|
char bottomMinX, char bottomMinY, char bottomMaxX, char bottomMaxY,
|
||||||
char sideMinX, char sideMinY, char sideMaxX, char sideMaxY);
|
char sideMinX, char sideMinY, char sideMaxX, char sideMaxY, BLOCK_TYPE blockType, std::string blockName);
|
||||||
|
|
||||||
};
|
};
|
@ -1,20 +1,36 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <array>
|
||||||
|
|
||||||
#include "Block.h"
|
#include "Block.h"
|
||||||
|
|
||||||
namespace Blocks
|
namespace Blocks
|
||||||
{
|
{
|
||||||
const std::vector<Block> blocks{
|
const std::vector<Block> blocks{
|
||||||
Block(0, 0, 0, 0), // Air block
|
Block(0, 0, 0, 0, Block::TRANSPARENT, "Air"), // Air block
|
||||||
Block(0, 0, 1, 1), // Dirt block
|
Block(0, 0, 1, 1, Block::SOLID, "Dirt"), // Dirt block
|
||||||
|
|
||||||
Block(1, 1, 2, 2, // Grass block
|
Block(1, 1, 2, 2, // Grass block
|
||||||
0, 0, 1, 1,
|
0, 0, 1, 1,
|
||||||
1, 0, 2, 1),
|
1, 0, 2, 1, Block::SOLID, "Grass Block"),
|
||||||
|
|
||||||
Block(0, 1, 1, 2) // Stone block
|
Block(0, 1, 1, 2, Block::SOLID, "Stone"), // Stone block
|
||||||
|
|
||||||
|
Block(2, 1, 3, 2, // Log
|
||||||
|
2, 1, 3, 2,
|
||||||
|
2, 0, 3, 1, Block::SOLID, "Log"),
|
||||||
|
|
||||||
|
Block(0, 2, 1, 3, Block::LEAVES, "Leaves"), // Leaves
|
||||||
|
Block(1, 2, 2, 3, Block::BILLBOARD, "Grass"), // Grass
|
||||||
|
Block(3, 0, 4, 1, Block::BILLBOARD, "Tall Grass Bottom"), // Tall Grass Bottom
|
||||||
|
Block(3, 1, 4, 2, Block::BILLBOARD, "Tall Grass Top"), // Tall Grass Top
|
||||||
|
Block(0, 3, 1, 4, Block::BILLBOARD, "Poppy"), // Poppy
|
||||||
|
Block(2, 2, 3, 3, Block::BILLBOARD, "White Tulip"), // White Tulip
|
||||||
|
Block(3, 2, 4, 3, Block::BILLBOARD, "Pink Tulip"), // Pink Tulip
|
||||||
|
Block(1, 3, 2, 4, Block::BILLBOARD, "Orange Tulip"), // Orange Tulip
|
||||||
|
Block(0, 4, 1, 5, Block::LIQUID, "Water"), // Water
|
||||||
|
Block(4, 0, 5, 1, Block::SOLID, "Sand"), // Sand
|
||||||
};
|
};
|
||||||
|
|
||||||
enum BLOCKS
|
enum BLOCKS
|
||||||
@ -22,6 +38,17 @@ namespace Blocks
|
|||||||
AIR = 0,
|
AIR = 0,
|
||||||
DIRT_BLOCK = 1,
|
DIRT_BLOCK = 1,
|
||||||
GRASS_BLOCK = 2,
|
GRASS_BLOCK = 2,
|
||||||
STONE_BLOCK = 3
|
STONE_BLOCK = 3,
|
||||||
|
LOG = 4,
|
||||||
|
LEAVES = 5,
|
||||||
|
GRASS = 6,
|
||||||
|
TALL_GRASS_BOTTOM = 7,
|
||||||
|
TALL_GRASS_TOP = 8,
|
||||||
|
POPPY = 9,
|
||||||
|
WHITE_TULIP = 10,
|
||||||
|
PINK_TULIP = 11,
|
||||||
|
ORANGE_TULIP = 12,
|
||||||
|
WATER = 13,
|
||||||
|
SAND = 14,
|
||||||
};
|
};
|
||||||
}
|
}
|
15
ScuffedMinecraft/src/CMakeLists.txt
Normal file
15
ScuffedMinecraft/src/CMakeLists.txt
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
add_executable(scuffed_mc
|
||||||
|
Application.cpp Chunk.cpp Shader.cpp
|
||||||
|
Block.cpp NoiseSettings.cpp SurfaceFeature.cpp
|
||||||
|
ChunkData.cpp ChunkPos.cpp Physics.cpp
|
||||||
|
Camera.cpp Planet.cpp WorldGen.cpp ../vendor/glad.c
|
||||||
|
)
|
||||||
|
|
||||||
|
if(LINUX)
|
||||||
|
add_compile_definitions(LINUX)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# make sure the program runs in the right place from visual studio
|
||||||
|
set_target_properties(scuffed_mc PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/bin")
|
||||||
|
|
||||||
|
target_link_libraries(scuffed_mc imgui $<IF:$<PLATFORM_ID:Windows>,glfw3,glfw>)
|
@ -38,9 +38,16 @@ void Camera::ProcessKeyboard(Camera_Movement direction, float deltaTime)
|
|||||||
if (direction == RIGHT)
|
if (direction == RIGHT)
|
||||||
Position += Right * velocity;
|
Position += Right * velocity;
|
||||||
if (direction == UP)
|
if (direction == UP)
|
||||||
Position += Up * velocity;
|
Position += (absoluteVerticalMovement ? glm::vec3(0, 1, 0) : Up) * velocity;
|
||||||
if (direction == DOWN)
|
if (direction == DOWN)
|
||||||
Position -= Up * velocity;
|
Position -= (absoluteVerticalMovement ? glm::vec3(0, 1, 0) : Up) * velocity;
|
||||||
|
if (direction == FORWARD_NO_Y)
|
||||||
|
{
|
||||||
|
glm::vec3 moveDir = Front;
|
||||||
|
moveDir.y = 0;
|
||||||
|
moveDir = glm::normalize(moveDir);
|
||||||
|
Position += moveDir * velocity;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// processes input received from a mouse input system. Expects the offset value in both the x and y direction.
|
// processes input received from a mouse input system. Expects the offset value in both the x and y direction.
|
||||||
|
@ -9,7 +9,8 @@ enum Camera_Movement {
|
|||||||
LEFT,
|
LEFT,
|
||||||
RIGHT,
|
RIGHT,
|
||||||
UP,
|
UP,
|
||||||
DOWN
|
DOWN,
|
||||||
|
FORWARD_NO_Y
|
||||||
};
|
};
|
||||||
|
|
||||||
// Default camera values
|
// Default camera values
|
||||||
@ -35,6 +36,7 @@ public:
|
|||||||
float MovementSpeed;
|
float MovementSpeed;
|
||||||
float MouseSensitivity;
|
float MouseSensitivity;
|
||||||
float Zoom;
|
float Zoom;
|
||||||
|
bool absoluteVerticalMovement = true;
|
||||||
|
|
||||||
Camera(glm::vec3 position = glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3 up = glm::vec3(0.0f, 1.0f, 0.0f), float yaw = YAW, float pitch = PITCH);
|
Camera(glm::vec3 position = glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3 up = glm::vec3(0.0f, 1.0f, 0.0f), float yaw = YAW, float pitch = PITCH);
|
||||||
|
|
||||||
|
@ -2,23 +2,21 @@
|
|||||||
|
|
||||||
#include <glad/glad.h>
|
#include <glad/glad.h>
|
||||||
#include <GLFW/glfw3.h>
|
#include <GLFW/glfw3.h>
|
||||||
|
#include <iostream>
|
||||||
#include <glm/gtc/matrix_transform.hpp>
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
#include <glm/gtc/type_ptr.hpp>
|
#include <glm/gtc/type_ptr.hpp>
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
#include "Planet.h"
|
#include "Planet.h"
|
||||||
#include "Blocks.h"
|
#include "Blocks.h"
|
||||||
#include "WorldGen.h"
|
#include "WorldGen.h"
|
||||||
|
|
||||||
Chunk::Chunk(unsigned int chunkSize, glm::vec3 chunkPos)
|
Chunk::Chunk(ChunkPos chunkPos, Shader* shader, Shader* waterShader)
|
||||||
|
: chunkPos(chunkPos)
|
||||||
{
|
{
|
||||||
this->chunkSize = chunkSize;
|
worldPos = glm::vec3(chunkPos.x * (float)CHUNK_SIZE, chunkPos.y * (float)CHUNK_SIZE, chunkPos.z * (float)CHUNK_SIZE);
|
||||||
this->chunkPos = chunkPos;
|
|
||||||
worldPos = glm::vec3(chunkPos.x * chunkSize, chunkPos.y * chunkSize, chunkPos.z * chunkSize);
|
|
||||||
|
|
||||||
ready = false;
|
ready = false;
|
||||||
generated = false;
|
generated = false;
|
||||||
chunkThread = std::thread(&Chunk::GenerateChunk, this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Chunk::~Chunk()
|
Chunk::~Chunk()
|
||||||
@ -26,224 +24,401 @@ Chunk::~Chunk()
|
|||||||
if (chunkThread.joinable())
|
if (chunkThread.joinable())
|
||||||
chunkThread.join();
|
chunkThread.join();
|
||||||
|
|
||||||
glDeleteBuffers(1, &vbo);
|
glDeleteBuffers(1, &mainVBO);
|
||||||
glDeleteBuffers(1, &ebo);
|
glDeleteBuffers(1, &mainEBO);
|
||||||
glDeleteVertexArrays(1, &vertexArrayObject);
|
glDeleteVertexArrays(1, &mainVAO);
|
||||||
|
|
||||||
|
glDeleteBuffers(1, &waterVBO);
|
||||||
|
glDeleteBuffers(1, &waterEBO);
|
||||||
|
glDeleteVertexArrays(1, &waterVAO);
|
||||||
|
|
||||||
|
glDeleteBuffers(1, &billboardVBO);
|
||||||
|
glDeleteBuffers(1, &billboardEBO);
|
||||||
|
glDeleteVertexArrays(1, &billboardVAO);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Chunk::GenerateChunk()
|
void Chunk::GenerateChunkMesh()
|
||||||
{
|
{
|
||||||
//std::cout << "Started thread: " << std::this_thread::get_id() << '\n';
|
mainVertices.clear();
|
||||||
|
mainIndices.clear();
|
||||||
WorldGen::GenerateChunkData(chunkPos.x, chunkPos.y, chunkPos.z, chunkSize, &chunkData);
|
waterVertices.clear();
|
||||||
std::vector<unsigned int> northData, southData, eastData, westData, upData, downData;
|
waterIndices.clear();
|
||||||
|
billboardVertices.clear();
|
||||||
WorldGen::GenerateChunkData(chunkPos.x, chunkPos.y, chunkPos.z - 1, chunkSize, &northData);
|
billboardIndices.clear();
|
||||||
WorldGen::GenerateChunkData(chunkPos.x, chunkPos.y, chunkPos.z + 1, chunkSize, &southData);
|
numTrianglesMain = 0;
|
||||||
WorldGen::GenerateChunkData(chunkPos.x + 1, chunkPos.y, chunkPos.z, chunkSize, &eastData);
|
numTrianglesWater = 0;
|
||||||
WorldGen::GenerateChunkData(chunkPos.x - 1, chunkPos.y, chunkPos.z, chunkSize, &westData);
|
numTrianglesBillboard = 0;
|
||||||
WorldGen::GenerateChunkData(chunkPos.x, chunkPos.y + 1, chunkPos.z, chunkSize, &upData);
|
|
||||||
WorldGen::GenerateChunkData(chunkPos.x, chunkPos.y - 1, chunkPos.z, chunkSize, &downData);
|
|
||||||
//auto northData = Planet::planet->GetChunkData(chunkPos.x, chunkPos.y, chunkPos.z - 1);
|
|
||||||
//auto southData = Planet::planet->GetChunkData(chunkPos.x, chunkPos.y, chunkPos.z + 1);
|
|
||||||
//auto eastData = Planet::planet->GetChunkData(chunkPos.x + 1, chunkPos.y, chunkPos.z);
|
|
||||||
//auto westData = Planet::planet->GetChunkData(chunkPos.x - 1, chunkPos.y, chunkPos.z);
|
|
||||||
//auto upData = Planet::planet->GetChunkData(chunkPos.x, chunkPos.y + 1, chunkPos.z);
|
|
||||||
//auto downData = Planet::planet->GetChunkData(chunkPos.x, chunkPos.y - 1, chunkPos.z);
|
|
||||||
|
|
||||||
//std::cout << "Got chunk data in thread: " << std::this_thread::get_id() << '\n';
|
|
||||||
|
|
||||||
unsigned int currentVertex = 0;
|
unsigned int currentVertex = 0;
|
||||||
for (char x = 0; x < chunkSize; x++)
|
unsigned int currentLiquidVertex = 0;
|
||||||
|
unsigned int currentBillboardVertex = 0;
|
||||||
|
for (char x = 0; x < CHUNK_SIZE; x++)
|
||||||
{
|
{
|
||||||
for (char z = 0; z < chunkSize; z++)
|
for (char z = 0; z < CHUNK_SIZE; z++)
|
||||||
{
|
{
|
||||||
for (char y = 0; y < chunkSize; y++)
|
for (char y = 0; y < CHUNK_SIZE; y++)
|
||||||
{
|
{
|
||||||
int index = x * chunkSize * chunkSize + z * chunkSize + y;
|
if (chunkData->GetBlock(x, y, z) == 0)
|
||||||
if (chunkData[index] == 0)
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const Block* block = &Blocks::blocks[chunkData[index]];
|
const Block* block = &Blocks::blocks[chunkData->GetBlock(x, y, z)];
|
||||||
|
|
||||||
// North
|
int topBlock;
|
||||||
|
if (y < CHUNK_SIZE - 1)
|
||||||
{
|
{
|
||||||
int northBlock;
|
topBlock = chunkData->GetBlock(x, y + 1, z);
|
||||||
if (z > 0)
|
}
|
||||||
{
|
else
|
||||||
int northIndex = x * chunkSize * chunkSize + (z - 1) * chunkSize + y;
|
{
|
||||||
northBlock = chunkData[northIndex];
|
int blockIndex = x * CHUNK_SIZE * CHUNK_SIZE + z * CHUNK_SIZE + 0;
|
||||||
}
|
topBlock = upData->GetBlock(x, 0, z);
|
||||||
else
|
|
||||||
{
|
|
||||||
int northIndex = x * chunkSize * chunkSize + (chunkSize - 1) * chunkSize + y;
|
|
||||||
northBlock = northData[northIndex];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (northBlock == 0)
|
|
||||||
{
|
|
||||||
vertices.push_back(Vertex(x + 1, y + 0, z + 0, block->sideMinX, block->sideMinY));
|
|
||||||
vertices.push_back(Vertex(x + 0, y + 0, z + 0, block->sideMaxX, block->sideMinY));
|
|
||||||
vertices.push_back(Vertex(x + 1, y + 1, z + 0, block->sideMinX, block->sideMaxY));
|
|
||||||
vertices.push_back(Vertex(x + 0, y + 1, z + 0, block->sideMaxX, block->sideMaxY));
|
|
||||||
|
|
||||||
indices.push_back(currentVertex + 0);
|
|
||||||
indices.push_back(currentVertex + 3);
|
|
||||||
indices.push_back(currentVertex + 1);
|
|
||||||
indices.push_back(currentVertex + 0);
|
|
||||||
indices.push_back(currentVertex + 2);
|
|
||||||
indices.push_back(currentVertex + 3);
|
|
||||||
currentVertex += 4;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// South
|
const Block* topBlockType = &Blocks::blocks[topBlock];
|
||||||
{
|
char waterTopValue = topBlockType->blockType == Block::TRANSPARENT ? 1 : 0;
|
||||||
int southBlock;
|
|
||||||
if (z < chunkSize - 1)
|
|
||||||
{
|
|
||||||
int southIndex = x * chunkSize * chunkSize + (z + 1) * chunkSize + y;
|
|
||||||
southBlock = chunkData[southIndex];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int southIndex = x * chunkSize * chunkSize + 0 * chunkSize + y;
|
|
||||||
southBlock = southData[southIndex];
|
|
||||||
}
|
|
||||||
if (southBlock == 0)
|
|
||||||
{
|
|
||||||
vertices.push_back(Vertex(x + 0, y + 0, z + 1, block->sideMinX, block->sideMinY));
|
|
||||||
vertices.push_back(Vertex(x + 1, y + 0, z + 1, block->sideMaxX, block->sideMinY));
|
|
||||||
vertices.push_back(Vertex(x + 0, y + 1, z + 1, block->sideMinX, block->sideMaxY));
|
|
||||||
vertices.push_back(Vertex(x + 1, y + 1, z + 1, block->sideMaxX, block->sideMaxY));
|
|
||||||
|
|
||||||
indices.push_back(currentVertex + 0);
|
if (block->blockType == Block::BILLBOARD)
|
||||||
indices.push_back(currentVertex + 3);
|
{
|
||||||
indices.push_back(currentVertex + 1);
|
billboardVertices.push_back(BillboardVertex(x + .85355f, y + 0, z + .85355f, block->sideMinX, block->sideMinY));
|
||||||
indices.push_back(currentVertex + 0);
|
billboardVertices.push_back(BillboardVertex(x + .14645f, y + 0, z + .14645f, block->sideMaxX, block->sideMinY));
|
||||||
indices.push_back(currentVertex + 2);
|
billboardVertices.push_back(BillboardVertex(x + .85355f, y + 1, z + .85355f, block->sideMinX, block->sideMaxY));
|
||||||
indices.push_back(currentVertex + 3);
|
billboardVertices.push_back(BillboardVertex(x + .14645f, y + 1, z + .14645f, block->sideMaxX, block->sideMaxY));
|
||||||
currentVertex += 4;
|
|
||||||
}
|
billboardIndices.push_back(currentBillboardVertex + 0);
|
||||||
|
billboardIndices.push_back(currentBillboardVertex + 3);
|
||||||
|
billboardIndices.push_back(currentBillboardVertex + 1);
|
||||||
|
billboardIndices.push_back(currentBillboardVertex + 0);
|
||||||
|
billboardIndices.push_back(currentBillboardVertex + 2);
|
||||||
|
billboardIndices.push_back(currentBillboardVertex + 3);
|
||||||
|
currentBillboardVertex += 4;
|
||||||
|
|
||||||
|
billboardVertices.push_back(BillboardVertex(x + .14645f, y + 0, z + .85355f, block->sideMinX, block->sideMinY));
|
||||||
|
billboardVertices.push_back(BillboardVertex(x + .85355f, y + 0, z + .14645f, block->sideMaxX, block->sideMinY));
|
||||||
|
billboardVertices.push_back(BillboardVertex(x + .14645f, y + 1, z + .85355f, block->sideMinX, block->sideMaxY));
|
||||||
|
billboardVertices.push_back(BillboardVertex(x + .85355f, y + 1, z + .14645f, block->sideMaxX, block->sideMaxY));
|
||||||
|
|
||||||
|
billboardIndices.push_back(currentBillboardVertex + 0);
|
||||||
|
billboardIndices.push_back(currentBillboardVertex + 3);
|
||||||
|
billboardIndices.push_back(currentBillboardVertex + 1);
|
||||||
|
billboardIndices.push_back(currentBillboardVertex + 0);
|
||||||
|
billboardIndices.push_back(currentBillboardVertex + 2);
|
||||||
|
billboardIndices.push_back(currentBillboardVertex + 3);
|
||||||
|
currentBillboardVertex += 4;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
// West
|
|
||||||
{
|
{
|
||||||
int westBlock;
|
// North
|
||||||
if (x > 0)
|
|
||||||
{
|
{
|
||||||
int blockIndex = (x - 1) * chunkSize * chunkSize + z * chunkSize + y;
|
int northBlock;
|
||||||
westBlock = chunkData[blockIndex];
|
if (z > 0)
|
||||||
}
|
{
|
||||||
else
|
northBlock = chunkData->GetBlock(x, y, z - 1);
|
||||||
{
|
}
|
||||||
int blockIndex = (chunkSize - 1) *chunkSize * chunkSize + z * chunkSize + y;
|
else
|
||||||
westBlock = westData[blockIndex];
|
{
|
||||||
}
|
northBlock = northData->GetBlock(x, y, CHUNK_SIZE - 1);
|
||||||
if (westBlock == 0)
|
}
|
||||||
{
|
|
||||||
vertices.push_back(Vertex(x + 0, y + 0, z + 0, block->sideMinX, block->sideMinY));
|
|
||||||
vertices.push_back(Vertex(x + 0, y + 0, z + 1, block->sideMaxX, block->sideMinY));
|
|
||||||
vertices.push_back(Vertex(x + 0, y + 1, z + 0, block->sideMinX, block->sideMaxY));
|
|
||||||
vertices.push_back(Vertex(x + 0, y + 1, z + 1, block->sideMaxX, block->sideMaxY));
|
|
||||||
|
|
||||||
indices.push_back(currentVertex + 0);
|
const Block* northBlockType = &Blocks::blocks[northBlock];
|
||||||
indices.push_back(currentVertex + 3);
|
|
||||||
indices.push_back(currentVertex + 1);
|
|
||||||
indices.push_back(currentVertex + 0);
|
|
||||||
indices.push_back(currentVertex + 2);
|
|
||||||
indices.push_back(currentVertex + 3);
|
|
||||||
currentVertex += 4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// East
|
if (northBlockType->blockType == Block::LEAVES
|
||||||
{
|
|| northBlockType->blockType == Block::TRANSPARENT
|
||||||
int eastBlock;
|
|| northBlockType->blockType == Block::BILLBOARD
|
||||||
if (x < chunkSize - 1)
|
|| (northBlockType->blockType == Block::LIQUID && block->blockType != Block::LIQUID))
|
||||||
{
|
{
|
||||||
int blockIndex = (x + 1) * chunkSize * chunkSize + z * chunkSize + y;
|
if (block->blockType == Block::LIQUID)
|
||||||
eastBlock = chunkData[blockIndex];
|
{
|
||||||
}
|
waterVertices.push_back(WaterVertex(x + 1, y + 0, z + 0, block->sideMinX, block->sideMinY, 0, 0));
|
||||||
else
|
waterVertices.push_back(WaterVertex(x + 0, y + 0, z + 0, block->sideMaxX, block->sideMinY, 0, 0));
|
||||||
{
|
waterVertices.push_back(WaterVertex(x + 1, y + 1, z + 0, block->sideMinX, block->sideMaxY, 0, waterTopValue));
|
||||||
int blockIndex = 0 * chunkSize * chunkSize + z * chunkSize + y;
|
waterVertices.push_back(WaterVertex(x + 0, y + 1, z + 0, block->sideMaxX, block->sideMaxY, 0, waterTopValue));
|
||||||
eastBlock = eastData[blockIndex];
|
|
||||||
}
|
|
||||||
if (eastBlock == 0)
|
|
||||||
{
|
|
||||||
vertices.push_back(Vertex(x + 1, y + 0, z + 1, block->sideMinX, block->sideMinY));
|
|
||||||
vertices.push_back(Vertex(x + 1, y + 0, z + 0, block->sideMaxX, block->sideMinY));
|
|
||||||
vertices.push_back(Vertex(x + 1, y + 1, z + 1, block->sideMinX, block->sideMaxY));
|
|
||||||
vertices.push_back(Vertex(x + 1, y + 1, z + 0, block->sideMaxX, block->sideMaxY));
|
|
||||||
|
|
||||||
indices.push_back(currentVertex + 0);
|
waterIndices.push_back(currentLiquidVertex + 0);
|
||||||
indices.push_back(currentVertex + 3);
|
waterIndices.push_back(currentLiquidVertex + 3);
|
||||||
indices.push_back(currentVertex + 1);
|
waterIndices.push_back(currentLiquidVertex + 1);
|
||||||
indices.push_back(currentVertex + 0);
|
waterIndices.push_back(currentLiquidVertex + 0);
|
||||||
indices.push_back(currentVertex + 2);
|
waterIndices.push_back(currentLiquidVertex + 2);
|
||||||
indices.push_back(currentVertex + 3);
|
waterIndices.push_back(currentLiquidVertex + 3);
|
||||||
currentVertex += 4;
|
currentLiquidVertex += 4;
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
|
{
|
||||||
|
mainVertices.push_back(Vertex(x + 1, y + 0, z + 0, block->sideMinX, block->sideMinY, 0));
|
||||||
|
mainVertices.push_back(Vertex(x + 0, y + 0, z + 0, block->sideMaxX, block->sideMinY, 0));
|
||||||
|
mainVertices.push_back(Vertex(x + 1, y + 1, z + 0, block->sideMinX, block->sideMaxY, 0));
|
||||||
|
mainVertices.push_back(Vertex(x + 0, y + 1, z + 0, block->sideMaxX, block->sideMaxY, 0));
|
||||||
|
|
||||||
// Bottom
|
mainIndices.push_back(currentVertex + 0);
|
||||||
{
|
mainIndices.push_back(currentVertex + 3);
|
||||||
int bottomBlock;
|
mainIndices.push_back(currentVertex + 1);
|
||||||
if (y > 0)
|
mainIndices.push_back(currentVertex + 0);
|
||||||
{
|
mainIndices.push_back(currentVertex + 2);
|
||||||
int blockIndex = x * chunkSize * chunkSize + z * chunkSize + (y - 1);
|
mainIndices.push_back(currentVertex + 3);
|
||||||
bottomBlock = chunkData[blockIndex];
|
currentVertex += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
int blockIndex = x * chunkSize * chunkSize + z * chunkSize + (chunkSize - 1);
|
|
||||||
bottomBlock = downData[blockIndex];
|
|
||||||
}
|
|
||||||
if (bottomBlock == 0)
|
|
||||||
{
|
|
||||||
vertices.push_back(Vertex(x + 1, y + 0, z + 1, block->bottomMinX, block->bottomMinY));
|
|
||||||
vertices.push_back(Vertex(x + 0, y + 0, z + 1, block->bottomMaxX, block->bottomMinY));
|
|
||||||
vertices.push_back(Vertex(x + 1, y + 0, z + 0, block->bottomMinX, block->bottomMaxY));
|
|
||||||
vertices.push_back(Vertex(x + 0, y + 0, z + 0, block->bottomMaxX, block->bottomMaxY));
|
|
||||||
|
|
||||||
indices.push_back(currentVertex + 0);
|
// South
|
||||||
indices.push_back(currentVertex + 3);
|
{
|
||||||
indices.push_back(currentVertex + 1);
|
int southBlock;
|
||||||
indices.push_back(currentVertex + 0);
|
if (z < CHUNK_SIZE - 1)
|
||||||
indices.push_back(currentVertex + 2);
|
{
|
||||||
indices.push_back(currentVertex + 3);
|
southBlock = chunkData->GetBlock(x, y, z + 1);
|
||||||
currentVertex += 4;
|
}
|
||||||
}
|
else
|
||||||
}
|
{
|
||||||
|
southBlock = southData->GetBlock(x, y, 0);
|
||||||
|
}
|
||||||
|
|
||||||
// Top
|
const Block* southBlockType = &Blocks::blocks[southBlock];
|
||||||
{
|
|
||||||
int topBlock;
|
|
||||||
if (y < chunkSize - 1)
|
|
||||||
{
|
|
||||||
int blockIndex = x * chunkSize * chunkSize + z * chunkSize + (y + 1);
|
|
||||||
topBlock = chunkData[blockIndex];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int blockIndex = x * chunkSize * chunkSize + z * chunkSize + 0;
|
|
||||||
topBlock = upData[blockIndex];
|
|
||||||
}
|
|
||||||
if (topBlock == 0)
|
|
||||||
{
|
|
||||||
vertices.push_back(Vertex(x + 0, y + 1, z + 1, block->topMinX, block->topMinY));
|
|
||||||
vertices.push_back(Vertex(x + 1, y + 1, z + 1, block->topMaxX, block->topMinY));
|
|
||||||
vertices.push_back(Vertex(x + 0, y + 1, z + 0, block->topMinX, block->topMaxY));
|
|
||||||
vertices.push_back(Vertex(x + 1, y + 1, z + 0, block->topMaxX, block->topMaxY));
|
|
||||||
|
|
||||||
indices.push_back(currentVertex + 0);
|
if (southBlockType->blockType == Block::LEAVES
|
||||||
indices.push_back(currentVertex + 3);
|
|| southBlockType->blockType == Block::TRANSPARENT
|
||||||
indices.push_back(currentVertex + 1);
|
|| southBlockType->blockType == Block::BILLBOARD
|
||||||
indices.push_back(currentVertex + 0);
|
|| (southBlockType->blockType == Block::LIQUID && block->blockType != Block::LIQUID))
|
||||||
indices.push_back(currentVertex + 2);
|
{
|
||||||
indices.push_back(currentVertex + 3);
|
if (block->blockType == Block::LIQUID)
|
||||||
currentVertex += 4;
|
{
|
||||||
|
waterVertices.push_back(WaterVertex(x + 0, y + 0, z + 1, block->sideMinX, block->sideMinY, 1, 0));
|
||||||
|
waterVertices.push_back(WaterVertex(x + 1, y + 0, z + 1, block->sideMaxX, block->sideMinY, 1, 0));
|
||||||
|
waterVertices.push_back(WaterVertex(x + 0, y + 1, z + 1, block->sideMinX, block->sideMaxY, 1, waterTopValue));
|
||||||
|
waterVertices.push_back(WaterVertex(x + 1, y + 1, z + 1, block->sideMaxX, block->sideMaxY, 1, waterTopValue));
|
||||||
|
|
||||||
|
waterIndices.push_back(currentLiquidVertex + 0);
|
||||||
|
waterIndices.push_back(currentLiquidVertex + 3);
|
||||||
|
waterIndices.push_back(currentLiquidVertex + 1);
|
||||||
|
waterIndices.push_back(currentLiquidVertex + 0);
|
||||||
|
waterIndices.push_back(currentLiquidVertex + 2);
|
||||||
|
waterIndices.push_back(currentLiquidVertex + 3);
|
||||||
|
currentLiquidVertex += 4;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mainVertices.push_back(Vertex(x + 0, y + 0, z + 1, block->sideMinX, block->sideMinY, 1));
|
||||||
|
mainVertices.push_back(Vertex(x + 1, y + 0, z + 1, block->sideMaxX, block->sideMinY, 1));
|
||||||
|
mainVertices.push_back(Vertex(x + 0, y + 1, z + 1, block->sideMinX, block->sideMaxY, 1));
|
||||||
|
mainVertices.push_back(Vertex(x + 1, y + 1, z + 1, block->sideMaxX, block->sideMaxY, 1));
|
||||||
|
|
||||||
|
mainIndices.push_back(currentVertex + 0);
|
||||||
|
mainIndices.push_back(currentVertex + 3);
|
||||||
|
mainIndices.push_back(currentVertex + 1);
|
||||||
|
mainIndices.push_back(currentVertex + 0);
|
||||||
|
mainIndices.push_back(currentVertex + 2);
|
||||||
|
mainIndices.push_back(currentVertex + 3);
|
||||||
|
currentVertex += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// West
|
||||||
|
{
|
||||||
|
int westBlock;
|
||||||
|
if (x > 0)
|
||||||
|
{
|
||||||
|
westBlock = chunkData->GetBlock(x - 1, y, z);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
westBlock = westData->GetBlock(CHUNK_SIZE - 1, y, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
const Block* westBlockType = &Blocks::blocks[westBlock];
|
||||||
|
|
||||||
|
if (westBlockType->blockType == Block::LEAVES
|
||||||
|
|| westBlockType->blockType == Block::TRANSPARENT
|
||||||
|
|| westBlockType->blockType == Block::BILLBOARD
|
||||||
|
|| (westBlockType->blockType == Block::LIQUID && block->blockType != Block::LIQUID))
|
||||||
|
{
|
||||||
|
if (block->blockType == Block::LIQUID)
|
||||||
|
{
|
||||||
|
waterVertices.push_back(WaterVertex(x + 0, y + 0, z + 0, block->sideMinX, block->sideMinY, 2, 0));
|
||||||
|
waterVertices.push_back(WaterVertex(x + 0, y + 0, z + 1, block->sideMaxX, block->sideMinY, 2, 0));
|
||||||
|
waterVertices.push_back(WaterVertex(x + 0, y + 1, z + 0, block->sideMinX, block->sideMaxY, 2, waterTopValue));
|
||||||
|
waterVertices.push_back(WaterVertex(x + 0, y + 1, z + 1, block->sideMaxX, block->sideMaxY, 2, waterTopValue));
|
||||||
|
|
||||||
|
waterIndices.push_back(currentLiquidVertex + 0);
|
||||||
|
waterIndices.push_back(currentLiquidVertex + 3);
|
||||||
|
waterIndices.push_back(currentLiquidVertex + 1);
|
||||||
|
waterIndices.push_back(currentLiquidVertex + 0);
|
||||||
|
waterIndices.push_back(currentLiquidVertex + 2);
|
||||||
|
waterIndices.push_back(currentLiquidVertex + 3);
|
||||||
|
currentLiquidVertex += 4;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mainVertices.push_back(Vertex(x + 0, y + 0, z + 0, block->sideMinX, block->sideMinY, 2));
|
||||||
|
mainVertices.push_back(Vertex(x + 0, y + 0, z + 1, block->sideMaxX, block->sideMinY, 2));
|
||||||
|
mainVertices.push_back(Vertex(x + 0, y + 1, z + 0, block->sideMinX, block->sideMaxY, 2));
|
||||||
|
mainVertices.push_back(Vertex(x + 0, y + 1, z + 1, block->sideMaxX, block->sideMaxY, 2));
|
||||||
|
|
||||||
|
mainIndices.push_back(currentVertex + 0);
|
||||||
|
mainIndices.push_back(currentVertex + 3);
|
||||||
|
mainIndices.push_back(currentVertex + 1);
|
||||||
|
mainIndices.push_back(currentVertex + 0);
|
||||||
|
mainIndices.push_back(currentVertex + 2);
|
||||||
|
mainIndices.push_back(currentVertex + 3);
|
||||||
|
currentVertex += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// East
|
||||||
|
{
|
||||||
|
int eastBlock;
|
||||||
|
if (x < CHUNK_SIZE - 1)
|
||||||
|
{
|
||||||
|
eastBlock = chunkData->GetBlock(x + 1, y, z);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
eastBlock = eastData->GetBlock(0, y, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
const Block* eastBlockType = &Blocks::blocks[eastBlock];
|
||||||
|
|
||||||
|
if (eastBlockType->blockType == Block::LEAVES
|
||||||
|
|| eastBlockType->blockType == Block::TRANSPARENT
|
||||||
|
|| eastBlockType->blockType == Block::BILLBOARD
|
||||||
|
|| (eastBlockType->blockType == Block::LIQUID && block->blockType != Block::LIQUID))
|
||||||
|
{
|
||||||
|
if (block->blockType == Block::LIQUID)
|
||||||
|
{
|
||||||
|
waterVertices.push_back(WaterVertex(x + 1, y + 0, z + 1, block->sideMinX, block->sideMinY, 3, 0));
|
||||||
|
waterVertices.push_back(WaterVertex(x + 1, y + 0, z + 0, block->sideMaxX, block->sideMinY, 3, 0));
|
||||||
|
waterVertices.push_back(WaterVertex(x + 1, y + 1, z + 1, block->sideMinX, block->sideMaxY, 3, waterTopValue));
|
||||||
|
waterVertices.push_back(WaterVertex(x + 1, y + 1, z + 0, block->sideMaxX, block->sideMaxY, 3, waterTopValue));
|
||||||
|
|
||||||
|
waterIndices.push_back(currentLiquidVertex + 0);
|
||||||
|
waterIndices.push_back(currentLiquidVertex + 3);
|
||||||
|
waterIndices.push_back(currentLiquidVertex + 1);
|
||||||
|
waterIndices.push_back(currentLiquidVertex + 0);
|
||||||
|
waterIndices.push_back(currentLiquidVertex + 2);
|
||||||
|
waterIndices.push_back(currentLiquidVertex + 3);
|
||||||
|
currentLiquidVertex += 4;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mainVertices.push_back(Vertex(x + 1, y + 0, z + 1, block->sideMinX, block->sideMinY, 3));
|
||||||
|
mainVertices.push_back(Vertex(x + 1, y + 0, z + 0, block->sideMaxX, block->sideMinY, 3));
|
||||||
|
mainVertices.push_back(Vertex(x + 1, y + 1, z + 1, block->sideMinX, block->sideMaxY, 3));
|
||||||
|
mainVertices.push_back(Vertex(x + 1, y + 1, z + 0, block->sideMaxX, block->sideMaxY, 3));
|
||||||
|
|
||||||
|
mainIndices.push_back(currentVertex + 0);
|
||||||
|
mainIndices.push_back(currentVertex + 3);
|
||||||
|
mainIndices.push_back(currentVertex + 1);
|
||||||
|
mainIndices.push_back(currentVertex + 0);
|
||||||
|
mainIndices.push_back(currentVertex + 2);
|
||||||
|
mainIndices.push_back(currentVertex + 3);
|
||||||
|
currentVertex += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bottom
|
||||||
|
{
|
||||||
|
int bottomBlock;
|
||||||
|
if (y > 0)
|
||||||
|
{
|
||||||
|
bottomBlock = chunkData->GetBlock(x, y - 1, z);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//int blockIndex = x * chunkSize * chunkSize + z * chunkSize + (chunkSize - 1);
|
||||||
|
bottomBlock = downData->GetBlock(x, CHUNK_SIZE - 1, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
const Block* bottomBlockType = &Blocks::blocks[bottomBlock];
|
||||||
|
|
||||||
|
if (bottomBlockType->blockType == Block::LEAVES
|
||||||
|
|| bottomBlockType->blockType == Block::TRANSPARENT
|
||||||
|
|| bottomBlockType->blockType == Block::BILLBOARD
|
||||||
|
|| (bottomBlockType->blockType == Block::LIQUID && block->blockType != Block::LIQUID))
|
||||||
|
{
|
||||||
|
if (block->blockType == Block::LIQUID)
|
||||||
|
{
|
||||||
|
waterVertices.push_back(WaterVertex(x + 1, y + 0, z + 1, block->bottomMinX, block->bottomMinY, 4, 0));
|
||||||
|
waterVertices.push_back(WaterVertex(x + 0, y + 0, z + 1, block->bottomMaxX, block->bottomMinY, 4, 0));
|
||||||
|
waterVertices.push_back(WaterVertex(x + 1, y + 0, z + 0, block->bottomMinX, block->bottomMaxY, 4, 0));
|
||||||
|
waterVertices.push_back(WaterVertex(x + 0, y + 0, z + 0, block->bottomMaxX, block->bottomMaxY, 4, 0));
|
||||||
|
|
||||||
|
waterIndices.push_back(currentLiquidVertex + 0);
|
||||||
|
waterIndices.push_back(currentLiquidVertex + 3);
|
||||||
|
waterIndices.push_back(currentLiquidVertex + 1);
|
||||||
|
waterIndices.push_back(currentLiquidVertex + 0);
|
||||||
|
waterIndices.push_back(currentLiquidVertex + 2);
|
||||||
|
waterIndices.push_back(currentLiquidVertex + 3);
|
||||||
|
currentLiquidVertex += 4;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mainVertices.push_back(Vertex(x + 1, y + 0, z + 1, block->bottomMinX, block->bottomMinY, 4));
|
||||||
|
mainVertices.push_back(Vertex(x + 0, y + 0, z + 1, block->bottomMaxX, block->bottomMinY, 4));
|
||||||
|
mainVertices.push_back(Vertex(x + 1, y + 0, z + 0, block->bottomMinX, block->bottomMaxY, 4));
|
||||||
|
mainVertices.push_back(Vertex(x + 0, y + 0, z + 0, block->bottomMaxX, block->bottomMaxY, 4));
|
||||||
|
|
||||||
|
mainIndices.push_back(currentVertex + 0);
|
||||||
|
mainIndices.push_back(currentVertex + 3);
|
||||||
|
mainIndices.push_back(currentVertex + 1);
|
||||||
|
mainIndices.push_back(currentVertex + 0);
|
||||||
|
mainIndices.push_back(currentVertex + 2);
|
||||||
|
mainIndices.push_back(currentVertex + 3);
|
||||||
|
currentVertex += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Top
|
||||||
|
{
|
||||||
|
if (block->blockType == Block::LIQUID)
|
||||||
|
{
|
||||||
|
if (topBlockType->blockType != Block::LIQUID)
|
||||||
|
{
|
||||||
|
waterVertices.push_back(WaterVertex(x + 0, y + 1, z + 1, block->topMinX, block->topMinY, 5, 1));
|
||||||
|
waterVertices.push_back(WaterVertex(x + 1, y + 1, z + 1, block->topMaxX, block->topMinY, 5, 1));
|
||||||
|
waterVertices.push_back(WaterVertex(x + 0, y + 1, z + 0, block->topMinX, block->topMaxY, 5, 1));
|
||||||
|
waterVertices.push_back(WaterVertex(x + 1, y + 1, z + 0, block->topMaxX, block->topMaxY, 5, 1));
|
||||||
|
|
||||||
|
waterIndices.push_back(currentLiquidVertex + 0);
|
||||||
|
waterIndices.push_back(currentLiquidVertex + 3);
|
||||||
|
waterIndices.push_back(currentLiquidVertex + 1);
|
||||||
|
waterIndices.push_back(currentLiquidVertex + 0);
|
||||||
|
waterIndices.push_back(currentLiquidVertex + 2);
|
||||||
|
waterIndices.push_back(currentLiquidVertex + 3);
|
||||||
|
currentLiquidVertex += 4;
|
||||||
|
|
||||||
|
waterVertices.push_back(WaterVertex(x + 1, y + 1, z + 1, block->topMinX, block->topMinY, 5, 1));
|
||||||
|
waterVertices.push_back(WaterVertex(x + 0, y + 1, z + 1, block->topMaxX, block->topMinY, 5, 1));
|
||||||
|
waterVertices.push_back(WaterVertex(x + 1, y + 1, z + 0, block->topMinX, block->topMaxY, 5, 1));
|
||||||
|
waterVertices.push_back(WaterVertex(x + 0, y + 1, z + 0, block->topMaxX, block->topMaxY, 5, 1));
|
||||||
|
|
||||||
|
waterIndices.push_back(currentLiquidVertex + 0);
|
||||||
|
waterIndices.push_back(currentLiquidVertex + 3);
|
||||||
|
waterIndices.push_back(currentLiquidVertex + 1);
|
||||||
|
waterIndices.push_back(currentLiquidVertex + 0);
|
||||||
|
waterIndices.push_back(currentLiquidVertex + 2);
|
||||||
|
waterIndices.push_back(currentLiquidVertex + 3);
|
||||||
|
currentLiquidVertex += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (topBlockType->blockType == Block::LEAVES
|
||||||
|
|| topBlockType->blockType == Block::TRANSPARENT
|
||||||
|
|| topBlockType->blockType == Block::BILLBOARD
|
||||||
|
|| topBlockType->blockType == Block::LIQUID)
|
||||||
|
{
|
||||||
|
mainVertices.push_back(Vertex(x + 0, y + 1, z + 1, block->topMinX, block->topMinY, 5));
|
||||||
|
mainVertices.push_back(Vertex(x + 1, y + 1, z + 1, block->topMaxX, block->topMinY, 5));
|
||||||
|
mainVertices.push_back(Vertex(x + 0, y + 1, z + 0, block->topMinX, block->topMaxY, 5));
|
||||||
|
mainVertices.push_back(Vertex(x + 1, y + 1, z + 0, block->topMaxX, block->topMaxY, 5));
|
||||||
|
|
||||||
|
mainIndices.push_back(currentVertex + 0);
|
||||||
|
mainIndices.push_back(currentVertex + 3);
|
||||||
|
mainIndices.push_back(currentVertex + 1);
|
||||||
|
mainIndices.push_back(currentVertex + 0);
|
||||||
|
mainIndices.push_back(currentVertex + 2);
|
||||||
|
mainIndices.push_back(currentVertex + 3);
|
||||||
|
currentVertex += 4;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -257,43 +432,252 @@ void Chunk::GenerateChunk()
|
|||||||
//std::cout << "Generated: " << generated << '\n';
|
//std::cout << "Generated: " << generated << '\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
void Chunk::Render(unsigned int modelLoc)
|
void Chunk::Render(Shader* mainShader, Shader* billboardShader)
|
||||||
{
|
{
|
||||||
if (!ready)
|
if (!ready)
|
||||||
{
|
{
|
||||||
if (generated)
|
if (generated)
|
||||||
{
|
{
|
||||||
numTriangles = indices.size();
|
// Solid
|
||||||
|
numTrianglesMain = mainIndices.size();
|
||||||
|
|
||||||
glGenVertexArrays(1, &vertexArrayObject);
|
glGenVertexArrays(1, &mainVAO);
|
||||||
glBindVertexArray(vertexArrayObject);
|
glGenBuffers(1, &mainVBO);
|
||||||
|
glGenBuffers(1, &mainEBO);
|
||||||
|
|
||||||
glGenBuffers(1, &vbo);
|
glBindVertexArray(mainVAO);
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
|
||||||
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex), vertices.data(), GL_STATIC_DRAW);
|
glBindBuffer(GL_ARRAY_BUFFER, mainVBO);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, mainVertices.size() * sizeof(Vertex), mainVertices.data(), GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mainEBO);
|
||||||
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, mainIndices.size() * sizeof(unsigned int), mainIndices.data(), GL_STATIC_DRAW);
|
||||||
|
|
||||||
glVertexAttribPointer(0, 3, GL_BYTE, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, posX));
|
glVertexAttribPointer(0, 3, GL_BYTE, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, posX));
|
||||||
glEnableVertexAttribArray(0);
|
glEnableVertexAttribArray(0);
|
||||||
glVertexAttribPointer(1, 2, GL_BYTE, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, texGridX));
|
glVertexAttribPointer(1, 2, GL_BYTE, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, texGridX));
|
||||||
glEnableVertexAttribArray(1);
|
glEnableVertexAttribArray(1);
|
||||||
|
glVertexAttribIPointer(2, 1, GL_BYTE, sizeof(Vertex), (void*)offsetof(Vertex, direction));
|
||||||
|
glEnableVertexAttribArray(2);
|
||||||
|
|
||||||
|
// Water
|
||||||
|
numTrianglesWater = waterIndices.size();
|
||||||
|
|
||||||
glGenBuffers(1, &ebo);
|
glGenVertexArrays(1, &waterVAO);
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
|
glGenBuffers(1, &waterVBO);
|
||||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), indices.data(), GL_STATIC_DRAW);
|
glGenBuffers(1, &waterEBO);
|
||||||
|
|
||||||
|
glBindVertexArray(waterVAO);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, waterVBO);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, waterVertices.size() * sizeof(WaterVertex), waterVertices.data(), GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, waterEBO);
|
||||||
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, waterIndices.size() * sizeof(unsigned int), waterIndices.data(), GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
glVertexAttribPointer(0, 3, GL_BYTE, GL_FALSE, sizeof(WaterVertex), (void*)offsetof(WaterVertex, posX));
|
||||||
|
glEnableVertexAttribArray(0);
|
||||||
|
glVertexAttribPointer(1, 2, GL_BYTE, GL_FALSE, sizeof(WaterVertex), (void*)offsetof(WaterVertex, texGridX));
|
||||||
|
glEnableVertexAttribArray(1);
|
||||||
|
glVertexAttribIPointer(2, 1, GL_BYTE, sizeof(WaterVertex), (void*)offsetof(WaterVertex, direction));
|
||||||
|
glEnableVertexAttribArray(2);
|
||||||
|
glVertexAttribIPointer(3, 1, GL_BYTE, sizeof(WaterVertex), (void*)offsetof(WaterVertex, top));
|
||||||
|
glEnableVertexAttribArray(3);
|
||||||
|
ready = true;
|
||||||
|
|
||||||
|
// Billboard
|
||||||
|
numTrianglesBillboard = billboardIndices.size();
|
||||||
|
|
||||||
|
glGenVertexArrays(1, &billboardVAO);
|
||||||
|
glGenBuffers(1, &billboardVBO);
|
||||||
|
glGenBuffers(1, &billboardEBO);
|
||||||
|
|
||||||
|
glBindVertexArray(billboardVAO);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, billboardVBO);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, billboardVertices.size() * sizeof(BillboardVertex), billboardVertices.data(), GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, billboardEBO);
|
||||||
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, billboardIndices.size() * sizeof(unsigned int), billboardIndices.data(), GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(BillboardVertex), (void*)offsetof(BillboardVertex, posX));
|
||||||
|
glEnableVertexAttribArray(0);
|
||||||
|
glVertexAttribPointer(1, 2, GL_BYTE, GL_FALSE, sizeof(BillboardVertex), (void*)offsetof(BillboardVertex, texGridX));
|
||||||
|
glEnableVertexAttribArray(1);
|
||||||
ready = true;
|
ready = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//std::cout << "Rendering chunk " << chunkPos.x << ", " << chunkPos.y << ", " << chunkPos.z << '\n'
|
//std::cout << "Rendering chunk " << chunkPos.x << ", " << chunkPos.y << ", " << chunkPos.z << '\n'
|
||||||
// << "Chunk VAO: " << vertexArrayObject << '\n' << "Triangles: " << numTriangles << '\n';
|
// << "Chunk VAO: " << vertexArrayObject << '\n' << "Triangles: " << numTriangles << '\n';
|
||||||
|
|
||||||
glBindVertexArray(vertexArrayObject);
|
// Calculate model matrix
|
||||||
|
glm::mat4 model = glm::mat4(1.0f);
|
||||||
|
model = glm::translate(model, worldPos);
|
||||||
|
|
||||||
|
// Render main mesh
|
||||||
|
mainShader->use();
|
||||||
|
|
||||||
|
modelLoc = glGetUniformLocation(mainShader->ID, "model");
|
||||||
|
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
|
||||||
|
|
||||||
|
glBindVertexArray(mainVAO);
|
||||||
|
glDrawElements(GL_TRIANGLES, numTrianglesMain, GL_UNSIGNED_INT, 0);
|
||||||
|
|
||||||
|
// Render billboard mesh
|
||||||
|
billboardShader->use();
|
||||||
|
|
||||||
|
modelLoc = glGetUniformLocation(billboardShader->ID, "model");
|
||||||
|
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
|
||||||
|
|
||||||
|
glDisable(GL_CULL_FACE);
|
||||||
|
glBindVertexArray(billboardVAO);
|
||||||
|
glDrawElements(GL_TRIANGLES, numTrianglesBillboard, GL_UNSIGNED_INT, 0);
|
||||||
|
glEnable(GL_CULL_FACE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Chunk::RenderWater(Shader* shader)
|
||||||
|
{
|
||||||
|
if (!ready)
|
||||||
|
return;
|
||||||
|
|
||||||
|
//std::cout << "Rendering chunk " << chunkPos.x << ", " << chunkPos.y << ", " << chunkPos.z << '\n'
|
||||||
|
// << "Chunk VAO: " << vertexArrayObject << '\n' << "Triangles: " << numTriangles << '\n';
|
||||||
|
|
||||||
|
modelLoc = glGetUniformLocation(shader->ID, "model");
|
||||||
|
glBindVertexArray(waterVAO);
|
||||||
|
|
||||||
glm::mat4 model = glm::mat4(1.0f);
|
glm::mat4 model = glm::mat4(1.0f);
|
||||||
model = glm::translate(model, worldPos);
|
model = glm::translate(model, worldPos);
|
||||||
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
|
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
|
||||||
|
|
||||||
glDrawElements(GL_TRIANGLES, numTriangles, GL_UNSIGNED_INT, 0);
|
glDrawElements(GL_TRIANGLES, numTrianglesWater, GL_UNSIGNED_INT, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint16_t Chunk::GetBlockAtPos(int x, int y, int z)
|
||||||
|
{
|
||||||
|
if (!ready)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return chunkData->GetBlock(x, y, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Chunk::UpdateBlock(int x, int y, int z, uint16_t newBlock)
|
||||||
|
{
|
||||||
|
chunkData->SetBlock(x, y, z, newBlock);
|
||||||
|
|
||||||
|
GenerateChunkMesh();
|
||||||
|
|
||||||
|
// Main
|
||||||
|
numTrianglesMain = mainIndices.size();
|
||||||
|
|
||||||
|
glBindVertexArray(mainVAO);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, mainVBO);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, mainVertices.size() * sizeof(Vertex), mainVertices.data(), GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mainEBO);
|
||||||
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, mainIndices.size() * sizeof(unsigned int), mainIndices.data(), GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
// Water
|
||||||
|
numTrianglesWater = waterIndices.size();
|
||||||
|
|
||||||
|
glBindVertexArray(waterVAO);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, waterVBO);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, waterVertices.size() * sizeof(WaterVertex), waterVertices.data(), GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, waterEBO);
|
||||||
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, waterIndices.size() * sizeof(unsigned int), waterIndices.data(), GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
// Billboard
|
||||||
|
numTrianglesBillboard = billboardIndices.size();;
|
||||||
|
|
||||||
|
glBindVertexArray(billboardVAO);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, billboardVBO);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, billboardVertices.size() * sizeof(BillboardVertex), billboardVertices.data(), GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, billboardEBO);
|
||||||
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, billboardIndices.size() * sizeof(unsigned int), billboardIndices.data(), GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
|
||||||
|
if (x == 0)
|
||||||
|
{
|
||||||
|
Chunk* westChunk = Planet::planet->GetChunk({ chunkPos.x - 1, chunkPos.y, chunkPos.z });
|
||||||
|
if (westChunk != nullptr)
|
||||||
|
westChunk->UpdateChunk();
|
||||||
|
}
|
||||||
|
else if (x == CHUNK_SIZE - 1)
|
||||||
|
{
|
||||||
|
Chunk* eastChunk = Planet::planet->GetChunk({ chunkPos.x + 1, chunkPos.y, chunkPos.z });
|
||||||
|
if (eastChunk != nullptr)
|
||||||
|
eastChunk->UpdateChunk();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (y == 0)
|
||||||
|
{
|
||||||
|
Chunk* downChunk = Planet::planet->GetChunk({ chunkPos.x, chunkPos.y - 1, chunkPos.z });
|
||||||
|
if (downChunk != nullptr)
|
||||||
|
downChunk->UpdateChunk();
|
||||||
|
}
|
||||||
|
else if (y == CHUNK_SIZE - 1)
|
||||||
|
{
|
||||||
|
Chunk* upChunk = Planet::planet->GetChunk({ chunkPos.x, chunkPos.y + 1, chunkPos.z });
|
||||||
|
if (upChunk != nullptr)
|
||||||
|
upChunk->UpdateChunk();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (z == 0)
|
||||||
|
{
|
||||||
|
Chunk* northChunk = Planet::planet->GetChunk({ chunkPos.x, chunkPos.y, chunkPos.z - 1 });
|
||||||
|
if (northChunk != nullptr)
|
||||||
|
northChunk->UpdateChunk();
|
||||||
|
}
|
||||||
|
else if (z == CHUNK_SIZE - 1)
|
||||||
|
{
|
||||||
|
Chunk* southChunk = Planet::planet->GetChunk({ chunkPos.x, chunkPos.y, chunkPos.z + 1 });
|
||||||
|
if (southChunk != nullptr)
|
||||||
|
southChunk->UpdateChunk();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Chunk::UpdateChunk()
|
||||||
|
{
|
||||||
|
GenerateChunkMesh();
|
||||||
|
|
||||||
|
// Main
|
||||||
|
numTrianglesMain = mainIndices.size();
|
||||||
|
|
||||||
|
glBindVertexArray(mainVAO);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, mainVBO);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, mainVertices.size() * sizeof(Vertex), mainVertices.data(), GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mainEBO);
|
||||||
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, mainIndices.size() * sizeof(unsigned int), mainIndices.data(), GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
// Water
|
||||||
|
numTrianglesWater = waterIndices.size();
|
||||||
|
|
||||||
|
glBindVertexArray(waterVAO);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, waterVBO);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, waterVertices.size() * sizeof(WaterVertex), waterVertices.data(), GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, waterEBO);
|
||||||
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, waterIndices.size() * sizeof(unsigned int), waterIndices.data(), GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
// Billboard
|
||||||
|
numTrianglesBillboard = billboardIndices.size();
|
||||||
|
|
||||||
|
glBindVertexArray(billboardVAO);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, billboardVBO);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, billboardVertices.size() * sizeof(BillboardVertex), billboardVertices.data(), GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, billboardEBO);
|
||||||
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, billboardIndices.size() * sizeof(unsigned int), billboardIndices.data(), GL_STATIC_DRAW);
|
||||||
|
}
|
@ -4,45 +4,49 @@
|
|||||||
#include <thread>
|
#include <thread>
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
struct Vertex
|
#include "Shader.h"
|
||||||
{
|
#include "Vertex.h"
|
||||||
char posX, posY, posZ;
|
#include "ChunkPos.h"
|
||||||
char texGridX, texGridY;
|
#include "ChunkData.h"
|
||||||
|
|
||||||
Vertex(char _posX, char _posY, char _posZ, char _texGridX, char _texGridY)
|
|
||||||
{
|
|
||||||
posX = _posX;
|
|
||||||
posY = _posY;
|
|
||||||
posZ = _posZ;
|
|
||||||
|
|
||||||
texGridX = _texGridX;
|
|
||||||
texGridY = _texGridY;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class Chunk
|
class Chunk
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Chunk(unsigned int chunkSize, glm::vec3 chunkPos);
|
Chunk(ChunkPos chunkPos, Shader* shader, Shader* waterShader);
|
||||||
~Chunk();
|
~Chunk();
|
||||||
|
|
||||||
void GenerateChunk();
|
void GenerateChunkMesh();
|
||||||
void Render(unsigned int modelLoc);
|
void Render(Shader* mainShader, Shader* billboardShader);
|
||||||
|
void RenderWater(Shader* shader);
|
||||||
|
uint16_t GetBlockAtPos(int x, int y, int z);
|
||||||
|
void UpdateBlock(int x, int y, int z, uint16_t newBlock);
|
||||||
|
void UpdateChunk();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
std::vector<unsigned int> chunkData;
|
ChunkData* chunkData;
|
||||||
glm::vec3 chunkPos;
|
ChunkData* northData;
|
||||||
|
ChunkData* southData;
|
||||||
|
ChunkData* upData;
|
||||||
|
ChunkData* downData;
|
||||||
|
ChunkData* eastData;
|
||||||
|
ChunkData* westData;
|
||||||
|
ChunkPos chunkPos;
|
||||||
bool ready;
|
bool ready;
|
||||||
bool generated;
|
bool generated;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
unsigned int vertexArrayObject;
|
|
||||||
unsigned int vbo, ebo;
|
|
||||||
unsigned int chunkSize;
|
|
||||||
unsigned int numTriangles;
|
|
||||||
glm::vec3 worldPos;
|
glm::vec3 worldPos;
|
||||||
std::thread chunkThread;
|
std::thread chunkThread;
|
||||||
|
|
||||||
std::vector<Vertex> vertices;
|
std::vector<Vertex> mainVertices;
|
||||||
std::vector<unsigned int> indices;
|
std::vector<unsigned int> mainIndices;
|
||||||
|
std::vector<WaterVertex> waterVertices;
|
||||||
|
std::vector<unsigned int> waterIndices;
|
||||||
|
std::vector<BillboardVertex> billboardVertices;
|
||||||
|
std::vector<unsigned int> billboardIndices;
|
||||||
|
|
||||||
|
unsigned int mainVAO, waterVAO, billboardVAO;
|
||||||
|
unsigned int mainVBO, mainEBO, waterVBO, waterEBO, billboardVBO, billboardEBO;
|
||||||
|
unsigned int numTrianglesMain, numTrianglesWater, numTrianglesBillboard;
|
||||||
|
unsigned int modelLoc;
|
||||||
};
|
};
|
39
ScuffedMinecraft/src/ChunkData.cpp
Normal file
39
ScuffedMinecraft/src/ChunkData.cpp
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
#include "ChunkData.h"
|
||||||
|
|
||||||
|
#include "Planet.h"
|
||||||
|
|
||||||
|
ChunkData::ChunkData(uint16_t* data)
|
||||||
|
: data(data)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ChunkData::~ChunkData()
|
||||||
|
{
|
||||||
|
delete[] data;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int ChunkData::GetIndex(int x, int y, int z) const
|
||||||
|
{
|
||||||
|
return x * CHUNK_SIZE * CHUNK_SIZE + z * CHUNK_SIZE + y;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int ChunkData::GetIndex(ChunkPos localBlockPos) const
|
||||||
|
{
|
||||||
|
return localBlockPos.x * CHUNK_SIZE * CHUNK_SIZE + localBlockPos.z * CHUNK_SIZE + localBlockPos.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t ChunkData::GetBlock(ChunkPos blockPos)
|
||||||
|
{
|
||||||
|
return data[GetIndex(blockPos)];
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t ChunkData::GetBlock(int x, int y, int z)
|
||||||
|
{
|
||||||
|
return data[GetIndex(x, y, z)];
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChunkData::SetBlock(int x, int y, int z, uint16_t block)
|
||||||
|
{
|
||||||
|
data[GetIndex(x, y, z)] = block;
|
||||||
|
}
|
20
ScuffedMinecraft/src/ChunkData.h
Normal file
20
ScuffedMinecraft/src/ChunkData.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
#include "ChunkPos.h"
|
||||||
|
|
||||||
|
struct ChunkData
|
||||||
|
{
|
||||||
|
uint16_t* data;
|
||||||
|
|
||||||
|
ChunkData(uint16_t* data);
|
||||||
|
~ChunkData();
|
||||||
|
|
||||||
|
inline int GetIndex(int x, int y, int z) const;
|
||||||
|
inline int GetIndex(ChunkPos localBlockPos) const;
|
||||||
|
|
||||||
|
uint16_t GetBlock(ChunkPos blockPos);
|
||||||
|
uint16_t GetBlock(int x, int y, int z);
|
||||||
|
void SetBlock(int x, int y, int z, uint16_t block);
|
||||||
|
};
|
18
ScuffedMinecraft/src/ChunkPos.cpp
Normal file
18
ScuffedMinecraft/src/ChunkPos.cpp
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#include "ChunkPos.h"
|
||||||
|
|
||||||
|
ChunkPos::ChunkPos()
|
||||||
|
: x(0), y(0), z(0)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ChunkPos::ChunkPos(int x, int y, int z)
|
||||||
|
: x(x), y(y), z(z)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ChunkPos::operator==(const ChunkPos& other) const
|
||||||
|
{
|
||||||
|
return other.x == x && other.y == y && other.z == z;
|
||||||
|
}
|
13
ScuffedMinecraft/src/ChunkPos.h
Normal file
13
ScuffedMinecraft/src/ChunkPos.h
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
struct ChunkPos
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
int z;
|
||||||
|
|
||||||
|
ChunkPos();
|
||||||
|
ChunkPos(int x, int y, int z);
|
||||||
|
|
||||||
|
bool operator==(const ChunkPos& other) const;
|
||||||
|
};
|
15
ScuffedMinecraft/src/ChunkPosHash.h
Normal file
15
ScuffedMinecraft/src/ChunkPosHash.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#include "ChunkPos.h"
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
struct ChunkPosHash
|
||||||
|
{
|
||||||
|
std::size_t operator()(const ChunkPos& key) const
|
||||||
|
{
|
||||||
|
std::size_t hx = std::hash<int>()(key.x);
|
||||||
|
std::size_t hy = std::hash<int>()(key.y);
|
||||||
|
std::size_t hz = std::hash<int>()(key.z);
|
||||||
|
|
||||||
|
// Combine the hashes using bitwise XOR and shifting
|
||||||
|
return hx ^ (hy << 1) ^ (hz << 2);
|
||||||
|
}
|
||||||
|
};
|
18
ScuffedMinecraft/src/NoiseSettings.cpp
Normal file
18
ScuffedMinecraft/src/NoiseSettings.cpp
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#include "NoiseSettings.h"
|
||||||
|
|
||||||
|
NoiseSettings::NoiseSettings(float _frequency, float _amplitude, float _offset)
|
||||||
|
: frequency(_frequency), amplitude(_amplitude), offset(_offset), chance(0), block(0)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
NoiseSettings::NoiseSettings(float _frequency, float _amplitude, float _offset, float _chance, unsigned int _block, int _maxHeight)
|
||||||
|
: frequency(_frequency), amplitude(_amplitude), offset(_offset), chance(_chance), block(_block), maxHeight(_maxHeight)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
NoiseSettings::~NoiseSettings()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
17
ScuffedMinecraft/src/NoiseSettings.h
Normal file
17
ScuffedMinecraft/src/NoiseSettings.h
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
struct NoiseSettings
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
float amplitude;
|
||||||
|
float frequency;
|
||||||
|
float offset;
|
||||||
|
|
||||||
|
float chance;
|
||||||
|
unsigned int block;
|
||||||
|
int maxHeight;
|
||||||
|
|
||||||
|
NoiseSettings(float _frequency, float _amplitude, float _offset);
|
||||||
|
NoiseSettings(float _frequency, float _amplitude, float _offset, float _chance, unsigned int _block, int _maxHeight);
|
||||||
|
~NoiseSettings();
|
||||||
|
};
|
47
ScuffedMinecraft/src/Physics.cpp
Normal file
47
ScuffedMinecraft/src/Physics.cpp
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
#include "Physics.h"
|
||||||
|
#include <iostream>
|
||||||
|
#include "Blocks.h"
|
||||||
|
|
||||||
|
Physics::RaycastResult Physics::Raycast(const glm::vec3 startPos, const glm::vec3 direction, const float maxDistance)
|
||||||
|
{
|
||||||
|
float currentDistance = 0;
|
||||||
|
|
||||||
|
while (currentDistance < maxDistance)
|
||||||
|
{
|
||||||
|
currentDistance += Physics::RAY_STEP;
|
||||||
|
if (currentDistance > maxDistance)
|
||||||
|
currentDistance = maxDistance;
|
||||||
|
|
||||||
|
// Get chunk
|
||||||
|
glm::vec3 resultPos = startPos + direction * currentDistance;
|
||||||
|
int chunkX = resultPos.x >= 0 ? resultPos.x / CHUNK_SIZE : resultPos.x / CHUNK_SIZE - 1;
|
||||||
|
int chunkY = resultPos.y >= 0 ? resultPos.y / CHUNK_SIZE : resultPos.y / CHUNK_SIZE - 1;
|
||||||
|
int chunkZ = resultPos.z >= 0 ? resultPos.z / CHUNK_SIZE : resultPos.z / CHUNK_SIZE - 1;
|
||||||
|
Chunk* chunk = Planet::planet->GetChunk(ChunkPos(chunkX, chunkY, chunkZ));
|
||||||
|
if (chunk == nullptr)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Get block pos
|
||||||
|
int localBlockX = (int)floor(resultPos.x) % CHUNK_SIZE;
|
||||||
|
int localBlockZ = (int)floor(resultPos.z) % CHUNK_SIZE;
|
||||||
|
int localBlockY = (int)floor(resultPos.y) % CHUNK_SIZE;
|
||||||
|
|
||||||
|
// Get block from chunk
|
||||||
|
unsigned int block = chunk->GetBlockAtPos(localBlockX, localBlockY, localBlockZ);
|
||||||
|
|
||||||
|
// Get result pos
|
||||||
|
int blockX = resultPos.x >= 0 ? (int)resultPos.x : (int)resultPos.x - 1;
|
||||||
|
int blockY = resultPos.y >= 0 ? (int)resultPos.y : (int)resultPos.y - 1;
|
||||||
|
int blockZ = resultPos.z >= 0 ? (int)resultPos.z : (int)resultPos.z - 1;
|
||||||
|
|
||||||
|
// Return true if it hit a block
|
||||||
|
if (block != 0 && Blocks::blocks[block].blockType != Block::LIQUID)
|
||||||
|
return { true, resultPos, chunk,
|
||||||
|
blockX, blockY, blockZ,
|
||||||
|
localBlockX, localBlockY, localBlockZ};
|
||||||
|
}
|
||||||
|
|
||||||
|
return { false, glm::vec3(0), nullptr,
|
||||||
|
0, 0, 0,
|
||||||
|
0, 0, 0};
|
||||||
|
}
|
30
ScuffedMinecraft/src/Physics.h
Normal file
30
ScuffedMinecraft/src/Physics.h
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "glm/glm.hpp"
|
||||||
|
#include "Planet.h"
|
||||||
|
|
||||||
|
namespace Physics
|
||||||
|
{
|
||||||
|
struct RaycastResult
|
||||||
|
{
|
||||||
|
bool hit;
|
||||||
|
glm::vec3 hitPos;
|
||||||
|
Chunk* chunk;
|
||||||
|
int blockX;
|
||||||
|
int blockY;
|
||||||
|
int blockZ;
|
||||||
|
int localBlockX;
|
||||||
|
int localBlockY;
|
||||||
|
int localBlockZ;
|
||||||
|
|
||||||
|
RaycastResult(bool hit, glm::vec3 hitPos, Chunk* chunk, int blockX, int blockY, int blockZ, int localBlockX, int localBlockY, int localBlockZ)
|
||||||
|
: hit(hit), hitPos(hitPos), chunk(chunk), blockX(blockX), blockY(blockY), blockZ(blockZ), localBlockX(localBlockX), localBlockY(localBlockY), localBlockZ(localBlockZ)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
RaycastResult Raycast(glm::vec3 startPos, glm::vec3 direction, float maxDistance);
|
||||||
|
|
||||||
|
static constexpr float RAY_STEP = 0.01f;
|
||||||
|
}
|
@ -1,167 +1,461 @@
|
|||||||
#include "Planet.h"
|
#include "Planet.h"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <glad/glad.h>
|
||||||
|
#include <GLFW/glfw3.h>
|
||||||
|
|
||||||
|
#include "WorldGen.h"
|
||||||
|
|
||||||
Planet* Planet::planet = nullptr;
|
Planet* Planet::planet = nullptr;
|
||||||
|
|
||||||
// Public
|
//static const unsigned int CHUNK_SIZE = 32;
|
||||||
Planet::Planet()
|
|
||||||
{
|
|
||||||
|
|
||||||
|
// Public
|
||||||
|
Planet::Planet(Shader* solidShader, Shader* waterShader, Shader* billboardShader)
|
||||||
|
: solidShader(solidShader), waterShader(waterShader), billboardShader(billboardShader)
|
||||||
|
{
|
||||||
|
chunkThread = std::thread(&Planet::ChunkThreadUpdate, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
Planet::~Planet()
|
Planet::~Planet()
|
||||||
{
|
{
|
||||||
|
shouldEnd = true;
|
||||||
|
chunkThread.join();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<unsigned int> Planet::GetChunkData(int chunkX, int chunkY, int chunkZ)
|
void Planet::Update(glm::vec3 cameraPos)
|
||||||
{
|
{
|
||||||
std::tuple<int, int, int> chunkTuple{ chunkX, chunkY, chunkZ };
|
camChunkX = cameraPos.x < 0 ? floor(cameraPos.x / CHUNK_SIZE) : cameraPos.x / CHUNK_SIZE;
|
||||||
|
camChunkY = cameraPos.y < 0 ? floor(cameraPos.y / CHUNK_SIZE) : cameraPos.y / CHUNK_SIZE;
|
||||||
|
camChunkZ = cameraPos.z < 0 ? floor(cameraPos.z / CHUNK_SIZE) : cameraPos.z / CHUNK_SIZE;
|
||||||
|
|
||||||
if (chunks.find(chunkTuple) == chunks.end())
|
glDisable(GL_BLEND);
|
||||||
{
|
|
||||||
return std::vector<unsigned int>{};
|
|
||||||
//return GenerateChunkData(chunkX, chunkY, chunkZ);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return std::vector<unsigned int>{};
|
|
||||||
//return chunks.at(chunkTuple).chunkData;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Planet::Update(float camX, float camY, float camZ, unsigned int modelLoc)
|
|
||||||
{
|
|
||||||
int camChunkX = camX < 0 ? floor(camX / chunkSize) : camX / chunkSize;
|
|
||||||
int camChunkY = camY < 0 ? floor(camY / chunkSize) : camY / chunkSize;
|
|
||||||
int camChunkZ = camZ < 0 ? floor(camZ / chunkSize) : camZ / chunkSize;
|
|
||||||
|
|
||||||
// Check if camera moved to new chunk
|
|
||||||
if (camChunkX != lastCamX || camChunkY != lastCamY || camChunkZ != lastCamZ)
|
|
||||||
{
|
|
||||||
// Player moved chunks, start new chunk queue
|
|
||||||
lastCamX = camChunkX;
|
|
||||||
lastCamY = camChunkY;
|
|
||||||
lastCamZ = camChunkZ;
|
|
||||||
|
|
||||||
// Current chunk
|
|
||||||
chunkQueue = {};
|
|
||||||
if (chunks.find({ camChunkX, camChunkY, camChunkZ }) == chunks.end())
|
|
||||||
chunkQueue.push({ camChunkX, camChunkY, camChunkZ });
|
|
||||||
|
|
||||||
for (int r = 0; r < renderDistance; r++)
|
|
||||||
{
|
|
||||||
// Add middle chunks
|
|
||||||
for (int y = 0; y <= renderHeight; y++)
|
|
||||||
{
|
|
||||||
chunkQueue.push({ camChunkX, y, camChunkZ + r });
|
|
||||||
chunkQueue.push({ camChunkX + r, y, camChunkZ });
|
|
||||||
chunkQueue.push({ camChunkX, y, camChunkZ - r });
|
|
||||||
chunkQueue.push({ camChunkX - r, y, camChunkZ });
|
|
||||||
|
|
||||||
if (y > 0)
|
|
||||||
{
|
|
||||||
chunkQueue.push({ camChunkX, -y, camChunkZ + r });
|
|
||||||
chunkQueue.push({ camChunkX + r, -y, camChunkZ });
|
|
||||||
chunkQueue.push({ camChunkX, -y, camChunkZ - r });
|
|
||||||
chunkQueue.push({ camChunkX - r, -y, camChunkZ });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add edges
|
|
||||||
for (int e = 1; e < r; e++)
|
|
||||||
{
|
|
||||||
for (int y = 0; y <= renderHeight; y++)
|
|
||||||
{
|
|
||||||
chunkQueue.push({ camChunkX + e, y, camChunkZ + r });
|
|
||||||
chunkQueue.push({ camChunkX - e, y, camChunkZ + r });
|
|
||||||
|
|
||||||
chunkQueue.push({ camChunkX + r, y, camChunkZ + e });
|
|
||||||
chunkQueue.push({ camChunkX + r, y, camChunkZ - e });
|
|
||||||
|
|
||||||
chunkQueue.push({ camChunkX + e, y, camChunkZ - r });
|
|
||||||
chunkQueue.push({ camChunkX - e, y, camChunkZ - r });
|
|
||||||
|
|
||||||
chunkQueue.push({ camChunkX - r, y, camChunkZ + e });
|
|
||||||
chunkQueue.push({ camChunkX - r, y, camChunkZ - e });
|
|
||||||
|
|
||||||
if (y > 0)
|
|
||||||
{
|
|
||||||
chunkQueue.push({ camChunkX + e, -y, camChunkZ + r });
|
|
||||||
chunkQueue.push({ camChunkX - e, -y, camChunkZ + r });
|
|
||||||
|
|
||||||
chunkQueue.push({ camChunkX + r, -y, camChunkZ + e });
|
|
||||||
chunkQueue.push({ camChunkX + r, -y, camChunkZ - e });
|
|
||||||
|
|
||||||
chunkQueue.push({ camChunkX + e, -y, camChunkZ - r });
|
|
||||||
chunkQueue.push({ camChunkX - e, -y, camChunkZ - r });
|
|
||||||
|
|
||||||
chunkQueue.push({ camChunkX - r, -y, camChunkZ + e });
|
|
||||||
chunkQueue.push({ camChunkX - r, -y, camChunkZ - e });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add corners
|
|
||||||
for (int y = 0; y <= renderHeight; y++)
|
|
||||||
{
|
|
||||||
chunkQueue.push({ camChunkX + r, y, camChunkZ + r });
|
|
||||||
chunkQueue.push({ camChunkX + r, y, camChunkZ - r });
|
|
||||||
chunkQueue.push({ camChunkX - r, y, camChunkZ + r });
|
|
||||||
chunkQueue.push({ camChunkX - r, y, camChunkZ - r });
|
|
||||||
|
|
||||||
if (y > 0)
|
|
||||||
{
|
|
||||||
chunkQueue.push({ camChunkX + r, -y, camChunkZ + r });
|
|
||||||
chunkQueue.push({ camChunkX + r, -y, camChunkZ - r });
|
|
||||||
chunkQueue.push({ camChunkX - r, -y, camChunkZ + r });
|
|
||||||
chunkQueue.push({ camChunkX - r, -y, camChunkZ - r });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (chunksLoading == 0 && !chunkQueue.empty())
|
|
||||||
{
|
|
||||||
// Queue is not empty. Process front item in queue
|
|
||||||
glm::vec3 next = chunkQueue.front();
|
|
||||||
chunkQueue.pop();
|
|
||||||
|
|
||||||
std::tuple<int, int, int> chunkTuple{ next.x, next.y, next.z };
|
|
||||||
|
|
||||||
if (chunks.find(chunkTuple) == chunks.end())
|
|
||||||
{
|
|
||||||
chunks.try_emplace(chunkTuple,
|
|
||||||
chunkSize, next
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
chunksLoading = 0;
|
chunksLoading = 0;
|
||||||
numChunks = 0;
|
numChunks = 0;
|
||||||
numChunksRendered = 0;
|
numChunksRendered = 0;
|
||||||
|
chunkMutex.lock();
|
||||||
for (auto it = chunks.begin(); it != chunks.end(); )
|
for (auto it = chunks.begin(); it != chunks.end(); )
|
||||||
{
|
{
|
||||||
numChunks++;
|
numChunks++;
|
||||||
|
|
||||||
if (!it->second.ready)
|
if (!(*it->second).ready)
|
||||||
chunksLoading++;
|
chunksLoading++;
|
||||||
|
|
||||||
int chunkX = it->second.chunkPos.x;
|
int chunkX = (*it->second).chunkPos.x;
|
||||||
int chunkY = it->second.chunkPos.y;
|
int chunkY = (*it->second).chunkPos.y;
|
||||||
int chunkZ = it->second.chunkPos.z;
|
int chunkZ = (*it->second).chunkPos.z;
|
||||||
if (it->second.ready && (abs(chunkX - camChunkX) > renderDistance ||
|
if ((*it->second).ready && (abs(chunkX - camChunkX) > renderDistance ||
|
||||||
abs(chunkY - camChunkY) > renderDistance ||
|
abs(chunkY - camChunkY) > renderDistance ||
|
||||||
abs(chunkZ - camChunkZ) > renderDistance))
|
abs(chunkZ - camChunkZ) > renderDistance))
|
||||||
{
|
{
|
||||||
it->second.~Chunk();
|
// Out of range
|
||||||
|
// Add chunk data to delete queue
|
||||||
|
chunkDataDeleteQueue.push({ chunkX, chunkY, chunkZ });
|
||||||
|
chunkDataDeleteQueue.push({ chunkX + 1, chunkY, chunkZ });
|
||||||
|
chunkDataDeleteQueue.push({ chunkX - 1, chunkY, chunkZ });
|
||||||
|
chunkDataDeleteQueue.push({ chunkX, chunkY + 1, chunkZ });
|
||||||
|
chunkDataDeleteQueue.push({ chunkX, chunkY - 1, chunkZ });
|
||||||
|
chunkDataDeleteQueue.push({ chunkX, chunkY, chunkZ + 1 });
|
||||||
|
chunkDataDeleteQueue.push({ chunkX, chunkY, chunkZ - 1 });
|
||||||
|
|
||||||
|
// Delete chunk
|
||||||
|
delete it->second;
|
||||||
it = chunks.erase(it);
|
it = chunks.erase(it);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
numChunksRendered++;
|
numChunksRendered++;
|
||||||
it->second.Render(modelLoc);
|
(*it->second).Render(solidShader, billboardShader);
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
glEnable(GL_BLEND);
|
||||||
|
waterShader->use();
|
||||||
|
for (auto it = chunks.begin(); it != chunks.end(); )
|
||||||
|
{
|
||||||
|
int chunkX = (*it->second).chunkPos.x;
|
||||||
|
int chunkY = (*it->second).chunkPos.y;
|
||||||
|
int chunkZ = (*it->second).chunkPos.z;
|
||||||
|
|
||||||
|
(*it->second).RenderWater(waterShader);
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
|
||||||
|
chunkMutex.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Planet::ChunkThreadUpdate()
|
||||||
|
{
|
||||||
|
while (!shouldEnd)
|
||||||
|
{
|
||||||
|
for (auto it = chunkData.begin(); it != chunkData.end(); )
|
||||||
|
{
|
||||||
|
ChunkPos pos = it->first;
|
||||||
|
|
||||||
|
if (chunks.find(pos) == chunks.end() &&
|
||||||
|
chunks.find({ pos.x + 1, pos.y, pos.z }) == chunks.end() &&
|
||||||
|
chunks.find({ pos.x - 1, pos.y, pos.z }) == chunks.end() &&
|
||||||
|
chunks.find({ pos.x, pos.y + 1, pos.z }) == chunks.end() &&
|
||||||
|
chunks.find({ pos.x, pos.y - 1, pos.z }) == chunks.end() &&
|
||||||
|
chunks.find({ pos.x, pos.y, pos.z + 1 }) == chunks.end() &&
|
||||||
|
chunks.find({ pos.x, pos.y, pos.z - 1 }) == chunks.end())
|
||||||
|
{
|
||||||
|
delete chunkData.at(pos);
|
||||||
|
chunkData.erase(pos);
|
||||||
|
}
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if camera moved to new chunk
|
||||||
|
if (camChunkX != lastCamX || camChunkY != lastCamY || camChunkZ != lastCamZ)
|
||||||
|
{
|
||||||
|
// Player moved chunks, start new chunk queue
|
||||||
|
lastCamX = camChunkX;
|
||||||
|
lastCamY = camChunkY;
|
||||||
|
lastCamZ = camChunkZ;
|
||||||
|
|
||||||
|
// Current chunk
|
||||||
|
chunkMutex.lock();
|
||||||
|
chunkQueue = {};
|
||||||
|
if (chunks.find({ camChunkX, camChunkY, camChunkZ }) == chunks.end())
|
||||||
|
chunkQueue.push({ camChunkX, camChunkY, camChunkZ });
|
||||||
|
|
||||||
|
for (int r = 0; r < renderDistance; r++)
|
||||||
|
{
|
||||||
|
// Add middle chunks
|
||||||
|
for (int y = 0; y <= renderHeight; y++)
|
||||||
|
{
|
||||||
|
chunkQueue.push({ camChunkX, camChunkY + y, camChunkZ + r });
|
||||||
|
chunkQueue.push({ camChunkX + r, camChunkY + y, camChunkZ });
|
||||||
|
chunkQueue.push({ camChunkX, camChunkY + y, camChunkZ - r });
|
||||||
|
chunkQueue.push({ camChunkX - r, camChunkY + y, camChunkZ });
|
||||||
|
|
||||||
|
if (y > 0)
|
||||||
|
{
|
||||||
|
chunkQueue.push({ camChunkX, camChunkY - y, camChunkZ + r });
|
||||||
|
chunkQueue.push({ camChunkX + r, camChunkY - y, camChunkZ });
|
||||||
|
chunkQueue.push({ camChunkX, camChunkY - y, camChunkZ - r });
|
||||||
|
chunkQueue.push({ camChunkX - r, camChunkY - y, camChunkZ });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add edges
|
||||||
|
for (int e = 1; e < r; e++)
|
||||||
|
{
|
||||||
|
for (int y = 0; y <= renderHeight; y++)
|
||||||
|
{
|
||||||
|
chunkQueue.push({ camChunkX + e, camChunkY + y, camChunkZ + r });
|
||||||
|
chunkQueue.push({ camChunkX - e, camChunkY + y, camChunkZ + r });
|
||||||
|
|
||||||
|
chunkQueue.push({ camChunkX + r, camChunkY + y, camChunkZ + e });
|
||||||
|
chunkQueue.push({ camChunkX + r, camChunkY + y, camChunkZ - e });
|
||||||
|
|
||||||
|
chunkQueue.push({ camChunkX + e, camChunkY + y, camChunkZ - r });
|
||||||
|
chunkQueue.push({ camChunkX - e, camChunkY + y, camChunkZ - r });
|
||||||
|
|
||||||
|
chunkQueue.push({ camChunkX - r, camChunkY + y, camChunkZ + e });
|
||||||
|
chunkQueue.push({ camChunkX - r, camChunkY + y, camChunkZ - e });
|
||||||
|
|
||||||
|
if (y > 0)
|
||||||
|
{
|
||||||
|
chunkQueue.push({ camChunkX + e, camChunkY - y, camChunkZ + r });
|
||||||
|
chunkQueue.push({ camChunkX - e, camChunkY - y, camChunkZ + r });
|
||||||
|
|
||||||
|
chunkQueue.push({ camChunkX + r, camChunkY - y, camChunkZ + e });
|
||||||
|
chunkQueue.push({ camChunkX + r, camChunkY - y, camChunkZ - e });
|
||||||
|
|
||||||
|
chunkQueue.push({ camChunkX + e, camChunkY - y, camChunkZ - r });
|
||||||
|
chunkQueue.push({ camChunkX - e, camChunkY - y, camChunkZ - r });
|
||||||
|
|
||||||
|
chunkQueue.push({ camChunkX - r, camChunkY - y, camChunkZ + e });
|
||||||
|
chunkQueue.push({ camChunkX - r, camChunkY - y, camChunkZ - e });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add corners
|
||||||
|
for (int y = 0; y <= renderHeight; y++)
|
||||||
|
{
|
||||||
|
chunkQueue.push({ camChunkX + r, camChunkY + y, camChunkZ + r });
|
||||||
|
chunkQueue.push({ camChunkX + r, camChunkY + y, camChunkZ - r });
|
||||||
|
chunkQueue.push({ camChunkX - r, camChunkY + y, camChunkZ + r });
|
||||||
|
chunkQueue.push({ camChunkX - r, camChunkY + y, camChunkZ - r });
|
||||||
|
|
||||||
|
if (y > 0)
|
||||||
|
{
|
||||||
|
chunkQueue.push({ camChunkX + r, camChunkY - y, camChunkZ + r });
|
||||||
|
chunkQueue.push({ camChunkX + r, camChunkY - y, camChunkZ - r });
|
||||||
|
chunkQueue.push({ camChunkX - r, camChunkY - y, camChunkZ + r });
|
||||||
|
chunkQueue.push({ camChunkX - r, camChunkY - y, camChunkZ - r });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
chunkMutex.unlock();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
chunkMutex.lock();
|
||||||
|
if (!chunkDataQueue.empty())
|
||||||
|
{
|
||||||
|
ChunkPos chunkPos = chunkDataQueue.front();
|
||||||
|
|
||||||
|
if (chunkData.find(chunkPos) != chunkData.end())
|
||||||
|
{
|
||||||
|
chunkDataQueue.pop();
|
||||||
|
chunkMutex.unlock();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
chunkMutex.unlock();
|
||||||
|
|
||||||
|
uint16_t* d = new uint16_t[CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE];
|
||||||
|
ChunkData* data = new ChunkData(d);
|
||||||
|
|
||||||
|
WorldGen::GenerateChunkData(chunkPos, d);
|
||||||
|
|
||||||
|
chunkMutex.lock();
|
||||||
|
chunkData[chunkPos] = data;
|
||||||
|
chunkDataQueue.pop();
|
||||||
|
chunkMutex.unlock();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!chunkQueue.empty())
|
||||||
|
{
|
||||||
|
// Check if chunk exists
|
||||||
|
ChunkPos chunkPos = chunkQueue.front();
|
||||||
|
if (chunks.find(chunkPos) != chunks.end())
|
||||||
|
{
|
||||||
|
chunkQueue.pop();
|
||||||
|
chunkMutex.unlock();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
chunkMutex.unlock();
|
||||||
|
|
||||||
|
// Create chunk object
|
||||||
|
Chunk* chunk = new Chunk(chunkPos, solidShader, waterShader);
|
||||||
|
|
||||||
|
// Set chunk data
|
||||||
|
{
|
||||||
|
chunkMutex.lock();
|
||||||
|
if (chunkData.find(chunkPos) == chunkData.end())
|
||||||
|
{
|
||||||
|
chunkMutex.unlock();
|
||||||
|
uint16_t* d = new uint16_t[CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE];
|
||||||
|
|
||||||
|
WorldGen::GenerateChunkData(chunkPos, d);
|
||||||
|
|
||||||
|
ChunkData* data = new ChunkData(d);
|
||||||
|
|
||||||
|
chunk->chunkData = data;
|
||||||
|
|
||||||
|
chunkMutex.lock();
|
||||||
|
chunkData[chunkPos] = data;
|
||||||
|
chunkMutex.unlock();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
chunk->chunkData = chunkData.at(chunkPos);
|
||||||
|
chunkMutex.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set top data
|
||||||
|
{
|
||||||
|
ChunkPos topPos(chunkPos.x, chunkPos.y + 1, chunkPos.z);
|
||||||
|
chunkMutex.lock();
|
||||||
|
if (chunkData.find(topPos) == chunkData.end())
|
||||||
|
{
|
||||||
|
chunkMutex.unlock();
|
||||||
|
uint16_t* d = new uint16_t[CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE];
|
||||||
|
|
||||||
|
WorldGen::GenerateChunkData(topPos, d);
|
||||||
|
|
||||||
|
ChunkData* data = new ChunkData(d);
|
||||||
|
|
||||||
|
chunk->upData = data;
|
||||||
|
|
||||||
|
chunkMutex.lock();
|
||||||
|
chunkData[topPos] = data;
|
||||||
|
chunkMutex.unlock();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
chunk->upData = chunkData.at(topPos);
|
||||||
|
chunkMutex.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set bottom data
|
||||||
|
{
|
||||||
|
ChunkPos bottomPos(chunkPos.x, chunkPos.y - 1, chunkPos.z);
|
||||||
|
chunkMutex.lock();
|
||||||
|
if (chunkData.find(bottomPos) == chunkData.end())
|
||||||
|
{
|
||||||
|
chunkMutex.unlock();
|
||||||
|
uint16_t* d = new uint16_t[CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE];
|
||||||
|
|
||||||
|
WorldGen::GenerateChunkData(bottomPos, d);
|
||||||
|
|
||||||
|
ChunkData* data = new ChunkData(d);
|
||||||
|
|
||||||
|
chunk->downData = data;
|
||||||
|
|
||||||
|
chunkMutex.lock();
|
||||||
|
chunkData[bottomPos] = data;
|
||||||
|
chunkMutex.unlock();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
chunk->downData = chunkData.at(bottomPos);
|
||||||
|
chunkMutex.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set north data
|
||||||
|
{
|
||||||
|
ChunkPos northPos(chunkPos.x, chunkPos.y, chunkPos.z - 1);
|
||||||
|
chunkMutex.lock();
|
||||||
|
if (chunkData.find(northPos) == chunkData.end())
|
||||||
|
{
|
||||||
|
chunkMutex.unlock();
|
||||||
|
uint16_t* d = new uint16_t[CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE];
|
||||||
|
|
||||||
|
WorldGen::GenerateChunkData(northPos, d);
|
||||||
|
|
||||||
|
ChunkData* data = new ChunkData(d);
|
||||||
|
|
||||||
|
chunk->northData = data;
|
||||||
|
|
||||||
|
chunkMutex.lock();
|
||||||
|
chunkData[northPos] = data;
|
||||||
|
chunkMutex.unlock();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
chunk->northData = chunkData.at(northPos);
|
||||||
|
chunkMutex.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set south data
|
||||||
|
{
|
||||||
|
ChunkPos southPos(chunkPos.x, chunkPos.y, chunkPos.z + 1);
|
||||||
|
chunkMutex.lock();
|
||||||
|
if (chunkData.find(southPos) == chunkData.end())
|
||||||
|
{
|
||||||
|
chunkMutex.unlock();
|
||||||
|
uint16_t* d = new uint16_t[CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE];
|
||||||
|
|
||||||
|
WorldGen::GenerateChunkData(southPos, d);
|
||||||
|
|
||||||
|
ChunkData* data = new ChunkData(d);
|
||||||
|
|
||||||
|
chunk->southData = data;
|
||||||
|
|
||||||
|
chunkMutex.lock();
|
||||||
|
chunkData[southPos] = data;
|
||||||
|
chunkMutex.unlock();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
chunk->southData = chunkData.at(southPos);
|
||||||
|
chunkMutex.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set east data
|
||||||
|
{
|
||||||
|
ChunkPos eastPos(chunkPos.x + 1, chunkPos.y, chunkPos.z);
|
||||||
|
chunkMutex.lock();
|
||||||
|
if (chunkData.find(eastPos) == chunkData.end())
|
||||||
|
{
|
||||||
|
chunkMutex.unlock();
|
||||||
|
uint16_t* d = new uint16_t[CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE];
|
||||||
|
|
||||||
|
WorldGen::GenerateChunkData(eastPos, d);
|
||||||
|
|
||||||
|
ChunkData* data = new ChunkData(d);
|
||||||
|
|
||||||
|
chunk->eastData = data;
|
||||||
|
|
||||||
|
chunkMutex.lock();
|
||||||
|
chunkData[eastPos] = data;
|
||||||
|
chunkMutex.unlock();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
chunk->eastData = chunkData.at(eastPos);
|
||||||
|
chunkMutex.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set west data
|
||||||
|
{
|
||||||
|
ChunkPos westPos(chunkPos.x - 1, chunkPos.y, chunkPos.z);
|
||||||
|
chunkMutex.lock();
|
||||||
|
if (chunkData.find(westPos) == chunkData.end())
|
||||||
|
{
|
||||||
|
chunkMutex.unlock();
|
||||||
|
uint16_t* d = new uint16_t[CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE];
|
||||||
|
|
||||||
|
WorldGen::GenerateChunkData(westPos, d);
|
||||||
|
|
||||||
|
ChunkData* data = new ChunkData(d);
|
||||||
|
|
||||||
|
chunk->westData = data;
|
||||||
|
|
||||||
|
chunkMutex.lock();
|
||||||
|
chunkData[westPos] = data;
|
||||||
|
chunkMutex.unlock();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
chunk->westData = chunkData.at(westPos);
|
||||||
|
chunkMutex.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate chunk mesh
|
||||||
|
chunk->GenerateChunkMesh();
|
||||||
|
|
||||||
|
// Finish
|
||||||
|
chunkMutex.lock();
|
||||||
|
chunks[chunkPos] = chunk;
|
||||||
|
chunkQueue.pop();
|
||||||
|
chunkMutex.unlock();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
chunkMutex.unlock();
|
||||||
|
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Chunk* Planet::GetChunk(ChunkPos chunkPos)
|
||||||
|
{
|
||||||
|
chunkMutex.lock();
|
||||||
|
if (chunks.find(chunkPos) == chunks.end())
|
||||||
|
{
|
||||||
|
chunkMutex.unlock();
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
chunkMutex.unlock();
|
||||||
|
return chunks.at(chunkPos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Planet::ClearChunkQueue()
|
||||||
|
{
|
||||||
|
lastCamX++;
|
||||||
}
|
}
|
@ -5,31 +5,55 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
|
#include <thread>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
#include "ChunkPos.h"
|
||||||
|
#include "ChunkData.h"
|
||||||
#include "Chunk.h"
|
#include "Chunk.h"
|
||||||
#include "TupleHash.h"
|
#include "ChunkPosHash.h"
|
||||||
|
|
||||||
|
constexpr unsigned int CHUNK_SIZE = 32;
|
||||||
|
|
||||||
class Planet
|
class Planet
|
||||||
{
|
{
|
||||||
// Methods
|
// Methods
|
||||||
public:
|
public:
|
||||||
Planet();
|
Planet(Shader* solidShader, Shader* waterShader, Shader* billboardShader);
|
||||||
~Planet();
|
~Planet();
|
||||||
|
|
||||||
std::vector<unsigned int> GetChunkData(int chunkX, int chunkY, int chunkZ);
|
ChunkData* GetChunkData(ChunkPos chunkPos);
|
||||||
void Update(float camX, float camY, float camZ, unsigned int modelLoc);
|
void Update(glm::vec3 cameraPos);
|
||||||
|
|
||||||
|
Chunk* GetChunk(ChunkPos chunkPos);
|
||||||
|
void ClearChunkQueue();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void ChunkThreadUpdate();
|
||||||
|
|
||||||
// Variables
|
// Variables
|
||||||
public:
|
public:
|
||||||
static Planet* planet;
|
static Planet* planet;
|
||||||
unsigned int numChunks = 0, numChunksRendered = 0;
|
unsigned int numChunks = 0, numChunksRendered = 0;
|
||||||
|
int renderDistance = 10;
|
||||||
|
int renderHeight = 3;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unordered_map<std::tuple<int, int, int>, Chunk> chunks;
|
std::unordered_map<ChunkPos, Chunk*, ChunkPosHash> chunks;
|
||||||
std::queue<glm::vec3> chunkQueue;
|
std::unordered_map<ChunkPos, ChunkData*, ChunkPosHash> chunkData;
|
||||||
int renderDistance = 3;
|
std::queue<ChunkPos> chunkQueue;
|
||||||
int renderHeight = 1;
|
std::queue<ChunkPos> chunkDataQueue;
|
||||||
unsigned int chunkSize = 32;
|
std::queue<ChunkPos> chunkDataDeleteQueue;
|
||||||
unsigned int chunksLoading = 0;
|
unsigned int chunksLoading = 0;
|
||||||
int lastCamX = -100, lastCamY = -100, lastCamZ = -100;
|
int lastCamX = -100, lastCamY = -100, lastCamZ = -100;
|
||||||
|
int camChunkX = -100, camChunkY = -100, camChunkZ = -100;
|
||||||
|
|
||||||
|
Shader* solidShader;
|
||||||
|
Shader* waterShader;
|
||||||
|
Shader* billboardShader;
|
||||||
|
|
||||||
|
std::thread chunkThread;
|
||||||
|
std::mutex chunkMutex;
|
||||||
|
|
||||||
|
bool shouldEnd = false;
|
||||||
};
|
};
|
@ -46,25 +46,25 @@ Shader::Shader(const char* vertexPath, const char* fragmentPath)
|
|||||||
|
|
||||||
// vertex shader
|
// vertex shader
|
||||||
vertex = glCreateShader(GL_VERTEX_SHADER);
|
vertex = glCreateShader(GL_VERTEX_SHADER);
|
||||||
glShaderSource(vertex, 1, &vShaderCode, NULL);
|
glShaderSource(vertex, 1, &vShaderCode, nullptr);
|
||||||
glCompileShader(vertex);
|
glCompileShader(vertex);
|
||||||
// print compile errors if any
|
// print compile errors if any
|
||||||
glGetShaderiv(vertex, GL_COMPILE_STATUS, &success);
|
glGetShaderiv(vertex, GL_COMPILE_STATUS, &success);
|
||||||
if (!success)
|
if (!success)
|
||||||
{
|
{
|
||||||
glGetShaderInfoLog(vertex, 512, NULL, infoLog);
|
glGetShaderInfoLog(vertex, 512, nullptr, infoLog);
|
||||||
std::cout << "Error compiling vertex shader!\n" << infoLog << '\n';
|
std::cout << "Error compiling vertex shader!\n" << infoLog << '\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
// fragment shader
|
// fragment shader
|
||||||
fragment = glCreateShader(GL_FRAGMENT_SHADER);
|
fragment = glCreateShader(GL_FRAGMENT_SHADER);
|
||||||
glShaderSource(fragment, 1, &fShaderCode, NULL);
|
glShaderSource(fragment, 1, &fShaderCode, nullptr);
|
||||||
glCompileShader(fragment);
|
glCompileShader(fragment);
|
||||||
// print compile errors if any
|
// print compile errors if any
|
||||||
glGetShaderiv(fragment, GL_COMPILE_STATUS, &success);
|
glGetShaderiv(fragment, GL_COMPILE_STATUS, &success);
|
||||||
if (!success)
|
if (!success)
|
||||||
{
|
{
|
||||||
glGetShaderInfoLog(fragment, 512, NULL, infoLog);
|
glGetShaderInfoLog(fragment, 512, nullptr, infoLog);
|
||||||
std::cout << "Error compiling fragment shader!\n" << infoLog << '\n';
|
std::cout << "Error compiling fragment shader!\n" << infoLog << '\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,7 +77,7 @@ Shader::Shader(const char* vertexPath, const char* fragmentPath)
|
|||||||
glGetProgramiv(ID, GL_LINK_STATUS, &success);
|
glGetProgramiv(ID, GL_LINK_STATUS, &success);
|
||||||
if (!success)
|
if (!success)
|
||||||
{
|
{
|
||||||
glGetProgramInfoLog(ID, 512, NULL, infoLog);
|
glGetProgramInfoLog(ID, 512, nullptr, infoLog);
|
||||||
std::cout << "Error linking shader program!\n" << infoLog << '\n';
|
std::cout << "Error linking shader program!\n" << infoLog << '\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
11
ScuffedMinecraft/src/SurfaceFeature.cpp
Normal file
11
ScuffedMinecraft/src/SurfaceFeature.cpp
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#include "SurfaceFeature.h"
|
||||||
|
|
||||||
|
SurfaceFeature::SurfaceFeature(NoiseSettings _noiseSettings, std::vector<unsigned int> _blocks, std::vector<bool> _replaceBlock,
|
||||||
|
int _sizeX, int _sizeY, int _sizeZ,
|
||||||
|
int _offsetX, int _offsetY, int _offsetZ)
|
||||||
|
: noiseSettings(_noiseSettings), blocks(_blocks), replaceBlock(_replaceBlock),
|
||||||
|
sizeX(_sizeX), sizeY(_sizeY), sizeZ(_sizeZ),
|
||||||
|
offsetX(_offsetX), offsetY(_offsetY), offsetZ(_offsetZ)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
17
ScuffedMinecraft/src/SurfaceFeature.h
Normal file
17
ScuffedMinecraft/src/SurfaceFeature.h
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "NoiseSettings.h"
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
struct SurfaceFeature
|
||||||
|
{
|
||||||
|
NoiseSettings noiseSettings;
|
||||||
|
std::vector<unsigned int> blocks;
|
||||||
|
std::vector<bool> replaceBlock;
|
||||||
|
int sizeX, sizeY, sizeZ;
|
||||||
|
int offsetX, offsetY, offsetZ;
|
||||||
|
|
||||||
|
SurfaceFeature(NoiseSettings _noiseSettings, std::vector<unsigned int> _blocks, std::vector<bool> _replaceBlock,
|
||||||
|
int _sizeX, int _sizeY, int _sizeZ,
|
||||||
|
int _offsetX, int _offsetY, int _offsetZ);
|
||||||
|
};
|
@ -1,53 +0,0 @@
|
|||||||
#include <tuple>
|
|
||||||
// function has to live in the std namespace
|
|
||||||
// so that it is picked up by argument-dependent name lookup (ADL).
|
|
||||||
namespace std {
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
|
|
||||||
// Code from boost
|
|
||||||
// Reciprocal of the golden ratio helps spread entropy
|
|
||||||
// and handles duplicates.
|
|
||||||
// See Mike Seymour in magic-numbers-in-boosthash-combine:
|
|
||||||
// https://stackoverflow.com/questions/4948780
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
inline void hash_combine(std::size_t& seed, T const& v)
|
|
||||||
{
|
|
||||||
seed ^= hash<T>()(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Recursive template code derived from Matthieu M.
|
|
||||||
template <class Tuple, size_t Index = std::tuple_size<Tuple>::value - 1>
|
|
||||||
struct HashValueImpl
|
|
||||||
{
|
|
||||||
static void apply(size_t& seed, Tuple const& tuple)
|
|
||||||
{
|
|
||||||
HashValueImpl<Tuple, Index - 1>::apply(seed, tuple);
|
|
||||||
hash_combine(seed, get<Index>(tuple));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class Tuple>
|
|
||||||
struct HashValueImpl<Tuple, 0>
|
|
||||||
{
|
|
||||||
static void apply(size_t& seed, Tuple const& tuple)
|
|
||||||
{
|
|
||||||
hash_combine(seed, get<0>(tuple));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename ... TT>
|
|
||||||
struct hash<std::tuple<TT...>>
|
|
||||||
{
|
|
||||||
size_t
|
|
||||||
operator()(std::tuple<TT...> const& tt) const
|
|
||||||
{
|
|
||||||
size_t seed = 0;
|
|
||||||
HashValueImpl<std::tuple<TT...> >::apply(seed, tt);
|
|
||||||
return seed;
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
}
|
|
58
ScuffedMinecraft/src/Vertex.h
Normal file
58
ScuffedMinecraft/src/Vertex.h
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
struct Vertex
|
||||||
|
{
|
||||||
|
char posX, posY, posZ;
|
||||||
|
char texGridX, texGridY;
|
||||||
|
char direction;
|
||||||
|
|
||||||
|
Vertex(char _posX, char _posY, char _posZ, char _texGridX, char _texGridY, char _direction)
|
||||||
|
{
|
||||||
|
posX = _posX;
|
||||||
|
posY = _posY;
|
||||||
|
posZ = _posZ;
|
||||||
|
|
||||||
|
texGridX = _texGridX;
|
||||||
|
texGridY = _texGridY;
|
||||||
|
|
||||||
|
direction = _direction;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct WaterVertex
|
||||||
|
{
|
||||||
|
char posX, posY, posZ;
|
||||||
|
char texGridX, texGridY;
|
||||||
|
char direction;
|
||||||
|
char top;
|
||||||
|
|
||||||
|
WaterVertex(char _posX, char _posY, char _posZ, char _texGridX, char _texGridY, char _direction, char _top)
|
||||||
|
{
|
||||||
|
posX = _posX;
|
||||||
|
posY = _posY;
|
||||||
|
posZ = _posZ;
|
||||||
|
|
||||||
|
texGridX = _texGridX;
|
||||||
|
texGridY = _texGridY;
|
||||||
|
|
||||||
|
direction = _direction;
|
||||||
|
|
||||||
|
top = _top;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BillboardVertex
|
||||||
|
{
|
||||||
|
float posX, posY, posZ;
|
||||||
|
char texGridX, texGridY;
|
||||||
|
|
||||||
|
BillboardVertex(float _posX, float _posY, float _posZ, char _texGridX, char _texGridY)
|
||||||
|
{
|
||||||
|
posX = _posX;
|
||||||
|
posY = _posY;
|
||||||
|
posZ = _posZ;
|
||||||
|
|
||||||
|
texGridX = _texGridX;
|
||||||
|
texGridY = _texGridY;
|
||||||
|
}
|
||||||
|
};
|
@ -1,53 +1,480 @@
|
|||||||
#include "WorldGen.h"
|
#include "WorldGen.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <iostream>
|
||||||
#include <OpenSimplexNoise.hh>
|
#include <OpenSimplexNoise.hh>
|
||||||
|
|
||||||
#include "Blocks.h"
|
#include "Blocks.h"
|
||||||
|
#include "Planet.h"
|
||||||
|
|
||||||
void WorldGen::GenerateChunkData(int chunkX, int chunkY, int chunkZ, int chunkSize, std::vector<unsigned int>* chunkData)
|
void WorldGen::GenerateChunkData(ChunkPos chunkPos, uint16_t* chunkData)
|
||||||
{
|
{
|
||||||
chunkData->reserve(chunkSize * chunkSize * chunkSize);
|
static int chunkSize = CHUNK_SIZE;
|
||||||
|
|
||||||
OSN::Noise<2> surfaceNoise;
|
// Init noise
|
||||||
OSN::Noise<3> caveNoise;
|
static OSN::Noise<2> noise2D;
|
||||||
int startX = chunkX * chunkSize;
|
static OSN::Noise<3> noise3D;
|
||||||
int startY = chunkY * chunkSize;
|
|
||||||
int startZ = chunkZ * chunkSize;
|
|
||||||
|
|
||||||
|
// Init noise settings
|
||||||
|
static NoiseSettings surfaceSettings[]{
|
||||||
|
{ 0.01f, 20.0f, 0 },
|
||||||
|
{ 0.05f, 3.0f, 0 }
|
||||||
|
};
|
||||||
|
static int surfaceSettingsLength = sizeof(surfaceSettings) / sizeof(*surfaceSettings);
|
||||||
|
|
||||||
|
static NoiseSettings caveSettings[]{
|
||||||
|
{ 0.05f, 1.0f, 0, .5f, 0, 100 }
|
||||||
|
};
|
||||||
|
static int caveSettingsLength = sizeof(caveSettings) / sizeof(*caveSettings);
|
||||||
|
|
||||||
|
static NoiseSettings oreSettings[]{
|
||||||
|
{ 0.075f, 1.0f, 8.54f, .75f, 1, 0 }
|
||||||
|
};
|
||||||
|
static int oreSettingsLength = sizeof(oreSettings) / sizeof(*oreSettings);
|
||||||
|
|
||||||
|
static SurfaceFeature surfaceFeatures[]{
|
||||||
|
// Pond
|
||||||
|
{
|
||||||
|
{ 0.43f, 1.0f, 2.35f, .85f, 1, 0 }, // Noise
|
||||||
|
{ // Blocks
|
||||||
|
0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 13, 13, 0, 0,
|
||||||
|
0, 0, 13, 13, 13, 0, 0,
|
||||||
|
0, 0, 0, 13, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0,
|
||||||
|
|
||||||
|
0, 2, 13, 13, 2, 0, 0,
|
||||||
|
0, 2, 13, 13, 13, 2, 0,
|
||||||
|
2, 13, 13, 13, 13, 13, 2,
|
||||||
|
2, 13, 13, 13, 13, 13, 2,
|
||||||
|
2, 13, 13, 13, 13, 13, 2,
|
||||||
|
0, 2, 13, 13, 13, 2, 0,
|
||||||
|
0, 0, 2, 13, 2, 0, 0,
|
||||||
|
|
||||||
|
0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0,
|
||||||
|
},
|
||||||
|
{ // Replace?
|
||||||
|
false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false,
|
||||||
|
false, false, false, true, true, false, false,
|
||||||
|
false, false, true, true, true, false, false,
|
||||||
|
false, false, false, true, false, false, false,
|
||||||
|
false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false,
|
||||||
|
|
||||||
|
false, false, true, true, false, false, false,
|
||||||
|
false, false, true, true, true, false, false,
|
||||||
|
false, true, true, true, true, true, false,
|
||||||
|
false, true, true, true, true, true, false,
|
||||||
|
false, true, true, true, true, true, false,
|
||||||
|
false, false, true, true, true, false, false,
|
||||||
|
false, false, false, true, false, false, false,
|
||||||
|
|
||||||
|
false, false, true, true, false, false, false,
|
||||||
|
false, false, true, true, true, true, false,
|
||||||
|
false, true, true, true, true, true, false,
|
||||||
|
false, true, true, true, true, true, false,
|
||||||
|
false, true, true, true, true, true, false,
|
||||||
|
false, false, true, true, true, false, false,
|
||||||
|
false, false, false, true, false, false, false,
|
||||||
|
},
|
||||||
|
7, 3, 7, // Size
|
||||||
|
-3, -2, -3 // Offset
|
||||||
|
},
|
||||||
|
// Tree
|
||||||
|
{
|
||||||
|
{ 4.23f, 1.0f, 8.54f, .8f, 1, 0 },
|
||||||
|
{
|
||||||
|
0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0,
|
||||||
|
0, 0, 1, 0, 0,
|
||||||
|
0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0,
|
||||||
|
|
||||||
|
0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0,
|
||||||
|
0, 0, 4, 0, 0,
|
||||||
|
0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0,
|
||||||
|
|
||||||
|
0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0,
|
||||||
|
0, 0, 4, 0, 0,
|
||||||
|
0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0,
|
||||||
|
|
||||||
|
0, 5, 5, 5, 0,
|
||||||
|
5, 5, 5, 5, 5,
|
||||||
|
5, 5, 4, 5, 5,
|
||||||
|
5, 5, 5, 5, 5,
|
||||||
|
0, 5, 5, 5, 0,
|
||||||
|
|
||||||
|
0, 5, 5, 5, 0,
|
||||||
|
5, 5, 5, 5, 5,
|
||||||
|
5, 5, 4, 5, 5,
|
||||||
|
5, 5, 5, 5, 5,
|
||||||
|
0, 5, 5, 5, 0,
|
||||||
|
|
||||||
|
0, 0, 0, 0, 0,
|
||||||
|
0, 0, 5, 0, 0,
|
||||||
|
0, 5, 5, 5, 0,
|
||||||
|
0, 0, 5, 0, 0,
|
||||||
|
0, 0, 0, 0, 0,
|
||||||
|
|
||||||
|
0, 0, 0, 0, 0,
|
||||||
|
0, 0, 5, 0, 0,
|
||||||
|
0, 5, 5, 5, 0,
|
||||||
|
0, 0, 5, 0, 0,
|
||||||
|
0, 0, 0, 0, 0,
|
||||||
|
|
||||||
|
},
|
||||||
|
{
|
||||||
|
false, false, false, false, false,
|
||||||
|
false, false, false, false, false,
|
||||||
|
false, false, true, false, false,
|
||||||
|
false, false, false, false, false,
|
||||||
|
false, false, false, false, false,
|
||||||
|
|
||||||
|
false, false, false, false, false,
|
||||||
|
false, false, false, false, false,
|
||||||
|
false, false, true, false, false,
|
||||||
|
false, false, false, false, false,
|
||||||
|
false, false, false, false, false,
|
||||||
|
|
||||||
|
false, false, false, false, false,
|
||||||
|
false, false, false, false, false,
|
||||||
|
false, false, true, false, false,
|
||||||
|
false, false, false, false, false,
|
||||||
|
false, false, false, false, false,
|
||||||
|
|
||||||
|
false, false, false, false, false,
|
||||||
|
false, false, false, false, false,
|
||||||
|
false, false, true, false, false,
|
||||||
|
false, false, false, false, false,
|
||||||
|
false, false, false, false, false,
|
||||||
|
|
||||||
|
false, false, false, false, false,
|
||||||
|
false, false, false, false, false,
|
||||||
|
false, false, true, false, false,
|
||||||
|
false, false, false, false, false,
|
||||||
|
false, false, false, false, false,
|
||||||
|
|
||||||
|
false, false, false, false, false,
|
||||||
|
false, false, false, false, false,
|
||||||
|
false, false, false, false, false,
|
||||||
|
false, false, false, false, false,
|
||||||
|
false, false, false, false, false,
|
||||||
|
|
||||||
|
false, false, false, false, false,
|
||||||
|
false, false, false, false, false,
|
||||||
|
false, false, false, false, false,
|
||||||
|
false, false, false, false, false,
|
||||||
|
false, false, false, false, false,
|
||||||
|
},
|
||||||
|
5,
|
||||||
|
7,
|
||||||
|
5,
|
||||||
|
-2,
|
||||||
|
0,
|
||||||
|
-2
|
||||||
|
},
|
||||||
|
// Tall Grass
|
||||||
|
{
|
||||||
|
{ 1.23f, 1.0f, 4.34f, .6f, 1, 0 },
|
||||||
|
{
|
||||||
|
2, 7, 8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
false, false, false
|
||||||
|
},
|
||||||
|
1,
|
||||||
|
3,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
},
|
||||||
|
// Grass
|
||||||
|
{
|
||||||
|
{ 2.65f, 1.0f, 8.54f, .5f, 1, 0 },
|
||||||
|
{
|
||||||
|
2, 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
false, false
|
||||||
|
},
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
},
|
||||||
|
// Poppy
|
||||||
|
{
|
||||||
|
{ 5.32f, 1.0f, 3.67f, .8f, 1, 0 },
|
||||||
|
{
|
||||||
|
2, 9
|
||||||
|
},
|
||||||
|
{
|
||||||
|
false, false
|
||||||
|
},
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
},
|
||||||
|
// White Tulip
|
||||||
|
{
|
||||||
|
{ 5.57f, 1.0f, 7.654f, .8f, 1, 0 },
|
||||||
|
{
|
||||||
|
2, 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
false, false
|
||||||
|
},
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
},
|
||||||
|
// Pink Tulip
|
||||||
|
{
|
||||||
|
{ 4.94f, 1.0f, 2.23f, .8f, 1, 0 },
|
||||||
|
{
|
||||||
|
2, 11
|
||||||
|
},
|
||||||
|
{
|
||||||
|
false, false
|
||||||
|
},
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
},
|
||||||
|
// Orange Tulip
|
||||||
|
{
|
||||||
|
{ 6.32f, 1.0f, 8.2f, .85f, 1, 0 },
|
||||||
|
{
|
||||||
|
2, 12
|
||||||
|
},
|
||||||
|
{
|
||||||
|
false, false
|
||||||
|
},
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
},
|
||||||
|
};
|
||||||
|
static int surfaceFeaturesLength = sizeof(surfaceFeatures) / sizeof(*surfaceFeatures);
|
||||||
|
|
||||||
|
static int waterLevel = 20;
|
||||||
|
|
||||||
|
// Account for chunk position
|
||||||
|
int startX = chunkPos.x * chunkSize;
|
||||||
|
int startY = chunkPos.y * chunkSize;
|
||||||
|
int startZ = chunkPos.z * chunkSize;
|
||||||
|
|
||||||
|
int currentIndex = 0;
|
||||||
for (int x = 0; x < chunkSize; x++)
|
for (int x = 0; x < chunkSize; x++)
|
||||||
{
|
{
|
||||||
for (int z = 0; z < chunkSize; z++)
|
for (int z = 0; z < chunkSize; z++)
|
||||||
{
|
{
|
||||||
int noiseY = (surfaceNoise.eval((float)(x + startX) * .1f, (float)(z + startZ) * .1f) * 3.0f) + 20;
|
// Surface noise
|
||||||
|
int noiseY = 20;
|
||||||
|
for (int i = 0; i < surfaceSettingsLength; i++)
|
||||||
|
{
|
||||||
|
noiseY += noise2D.eval(
|
||||||
|
(float)((x + startX) * surfaceSettings[i].frequency) + surfaceSettings[i].offset,
|
||||||
|
(float)((z + startZ) * surfaceSettings[i].frequency) + surfaceSettings[i].offset)
|
||||||
|
* surfaceSettings[i].amplitude;
|
||||||
|
}
|
||||||
|
|
||||||
for (int y = 0; y < chunkSize; y++)
|
for (int y = 0; y < chunkSize; y++)
|
||||||
{
|
{
|
||||||
//chunkData.push_back(0); // Empty
|
// Cave noise
|
||||||
//chunkData.push_back(1); // Full
|
bool cave = false;
|
||||||
//chunkData.push_back(((x + y + z) % 2 == 0) ? 1 : 0); // Checkerboard
|
for (int i = 0; i < caveSettingsLength; i++)
|
||||||
/*chunkData.push_back( // Edges
|
{
|
||||||
(x == 0 || x == chunkSize - 1) ||
|
if (y + startY > caveSettings[i].maxHeight)
|
||||||
(y == 0 || y == chunkSize - 1) ||
|
continue;
|
||||||
(z == 0 || z == chunkSize - 1)
|
|
||||||
? 1 : 0
|
|
||||||
);*/
|
|
||||||
|
|
||||||
float noiseCaves = caveNoise.eval(
|
float noiseCaves = noise3D.eval(
|
||||||
(float)(x + startX) * .1f,
|
(float)((x + startX) * caveSettings[i].frequency) + caveSettings[i].offset,
|
||||||
(float)(y + startY) * .1f,
|
(float)((y + startY) * caveSettings[i].frequency) + caveSettings[i].offset,
|
||||||
(float)(z + startZ) * .1f);
|
(float)((z + startZ) * caveSettings[i].frequency) + caveSettings[i].offset)
|
||||||
|
* caveSettings[i].amplitude;
|
||||||
|
|
||||||
|
if (noiseCaves > caveSettings[i].chance)
|
||||||
|
{
|
||||||
|
cave = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 1: Terrain Shape (surface and caves) and Ores
|
||||||
|
|
||||||
// Sky and Caves
|
// Sky and Caves
|
||||||
if (y + startY > noiseY)
|
if (y + startY > noiseY)
|
||||||
chunkData->push_back(0);
|
{
|
||||||
else if (noiseCaves > .5f)
|
if (y + startY <= waterLevel)
|
||||||
chunkData->push_back(0);
|
chunkData[currentIndex] = Blocks::WATER;
|
||||||
|
else
|
||||||
|
chunkData[currentIndex] = Blocks::AIR;
|
||||||
|
}
|
||||||
|
else if (cave)
|
||||||
|
chunkData[currentIndex] = Blocks::AIR;
|
||||||
// Ground
|
// Ground
|
||||||
else if (y + startY == noiseY)
|
|
||||||
chunkData->push_back(Blocks::GRASS_BLOCK);
|
|
||||||
else if (y + startY > 10)
|
|
||||||
chunkData->push_back(Blocks::DIRT_BLOCK);
|
|
||||||
else
|
else
|
||||||
chunkData->push_back(Blocks::STONE_BLOCK);
|
{
|
||||||
|
bool blockSet = false;
|
||||||
|
for (int i = 0; i < oreSettingsLength; i++)
|
||||||
|
{
|
||||||
|
if (y + startY > oreSettings[i].maxHeight)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
float noiseOre = noise3D.eval(
|
||||||
|
(float)((x + startX) * oreSettings[i].frequency) + oreSettings[i].offset,
|
||||||
|
(float)((y + startY) * oreSettings[i].frequency) + oreSettings[i].offset,
|
||||||
|
(float)((z + startZ) * oreSettings[i].frequency) + oreSettings[i].offset)
|
||||||
|
* oreSettings[i].amplitude;
|
||||||
|
|
||||||
|
if (noiseOre > oreSettings[i].chance)
|
||||||
|
{
|
||||||
|
chunkData[currentIndex] = oreSettings[i].block;
|
||||||
|
blockSet = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!blockSet)
|
||||||
|
{
|
||||||
|
if (y + startY == noiseY)
|
||||||
|
if (noiseY > waterLevel + 1)
|
||||||
|
chunkData[currentIndex] = Blocks::GRASS_BLOCK;
|
||||||
|
else
|
||||||
|
chunkData[currentIndex] = Blocks::SAND;
|
||||||
|
else if (y + startY > 10)
|
||||||
|
if (noiseY > waterLevel + 1)
|
||||||
|
chunkData[currentIndex] = Blocks::DIRT_BLOCK;
|
||||||
|
else
|
||||||
|
chunkData[currentIndex] = Blocks::SAND;
|
||||||
|
else
|
||||||
|
chunkData[currentIndex] = Blocks::STONE_BLOCK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
currentIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 3: Surface Features
|
||||||
|
for (int i = 0; i < surfaceFeaturesLength; i++)
|
||||||
|
{
|
||||||
|
for (int x = -surfaceFeatures[i].sizeX - surfaceFeatures[i].offsetX; x < chunkSize - surfaceFeatures[i].offsetX; x++)
|
||||||
|
{
|
||||||
|
for (int z = -surfaceFeatures[i].sizeZ - surfaceFeatures[i].offsetZ; z < chunkSize - surfaceFeatures[i].offsetZ; z++)
|
||||||
|
{
|
||||||
|
int noiseY = 20;
|
||||||
|
for (int s = 0; s < surfaceSettingsLength; s++)
|
||||||
|
{
|
||||||
|
noiseY += noise2D.eval(
|
||||||
|
(float)((x + startX) * surfaceSettings[s].frequency) + surfaceSettings[s].offset,
|
||||||
|
(float)((z + startZ) * surfaceSettings[s].frequency) + surfaceSettings[s].offset)
|
||||||
|
* surfaceSettings[s].amplitude;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (noiseY + surfaceFeatures[i].offsetY > startY + chunkSize || noiseY + surfaceFeatures[i].sizeY + surfaceFeatures[i].offsetY < startY)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Check if it's in water or on sand
|
||||||
|
if (noiseY < waterLevel + 2)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Check if it's in a cave
|
||||||
|
bool cave = false;
|
||||||
|
for (int i = 0; i < caveSettingsLength; i++)
|
||||||
|
{
|
||||||
|
if (noiseY + startY > caveSettings[i].maxHeight)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
float noiseCaves = noise3D.eval(
|
||||||
|
(float)((x + startX) * caveSettings[i].frequency) + caveSettings[i].offset,
|
||||||
|
(float)((noiseY) * caveSettings[i].frequency) + caveSettings[i].offset,
|
||||||
|
(float)((z + startZ) * caveSettings[i].frequency) + caveSettings[i].offset)
|
||||||
|
* caveSettings[i].amplitude;
|
||||||
|
|
||||||
|
if (noiseCaves > caveSettings[i].chance)
|
||||||
|
{
|
||||||
|
cave = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cave)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
float noise = noise2D.eval(
|
||||||
|
(float)((x + startX) * surfaceFeatures[i].noiseSettings.frequency) + surfaceFeatures[i].noiseSettings.offset,
|
||||||
|
(float)((z + startZ) * surfaceFeatures[i].noiseSettings.frequency) + surfaceFeatures[i].noiseSettings.offset);
|
||||||
|
|
||||||
|
if (noise > surfaceFeatures[i].noiseSettings.chance)
|
||||||
|
{
|
||||||
|
int featureX = x + startX;
|
||||||
|
int featureY = noiseY;
|
||||||
|
int featureZ = z + startZ;
|
||||||
|
|
||||||
|
for (int fX = 0; fX < surfaceFeatures[i].sizeX; fX++)
|
||||||
|
{
|
||||||
|
for (int fY = 0; fY < surfaceFeatures[i].sizeY; fY++)
|
||||||
|
{
|
||||||
|
for (int fZ = 0; fZ < surfaceFeatures[i].sizeZ; fZ++)
|
||||||
|
{
|
||||||
|
int localX = featureX + fX + surfaceFeatures[i].offsetX - startX;
|
||||||
|
//std::cout << "FeatureX: " << featureX << ", fX: " << fX << ", startX: " << startX << ", localX: " << localX << '\n';
|
||||||
|
int localY = featureY + fY + surfaceFeatures[i].offsetY - startY;
|
||||||
|
//std::cout << "FeatureY: " << featureY << ", fY: " << fY << ", startY: " << startY << ", localY: " << localY << '\n';
|
||||||
|
int localZ = featureZ + fZ + surfaceFeatures[i].offsetZ - startZ;
|
||||||
|
//std::cout << "FeatureZ: " << featureZ << ", fZ: " << fZ << ", startZ: " << startZ << ", localZ: " << localZ << '\n';
|
||||||
|
|
||||||
|
if (localX >= chunkSize || localX < 0)
|
||||||
|
continue;
|
||||||
|
if (localY >= chunkSize || localY < 0)
|
||||||
|
continue;
|
||||||
|
if (localZ >= chunkSize || localZ < 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int featureIndex = fY * surfaceFeatures[i].sizeX * surfaceFeatures[i].sizeZ +
|
||||||
|
fX * surfaceFeatures[i].sizeZ +
|
||||||
|
fZ;
|
||||||
|
//std::cout << "Feature Index: " << featureIndex << '\n';
|
||||||
|
int localIndex = localX * chunkSize * chunkSize + localZ * chunkSize + localY;
|
||||||
|
//std::cout << "Local Index: " << localIndex << ", Max Index: " << chunkData->size() << '\n';
|
||||||
|
|
||||||
|
if (surfaceFeatures[i].replaceBlock[featureIndex] || chunkData[localIndex] == 0)
|
||||||
|
chunkData[localIndex] = surfaceFeatures[i].blocks[featureIndex];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,12 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include "NoiseSettings.h"
|
||||||
|
#include "SurfaceFeature.h"
|
||||||
|
#include "ChunkData.h"
|
||||||
|
#include "glm/glm.hpp"
|
||||||
|
|
||||||
namespace WorldGen
|
namespace WorldGen
|
||||||
{
|
{
|
||||||
void GenerateChunkData(int chunkX, int chunkY, int chunkZ, int chunkSize, std::vector<unsigned int>* chunkData);
|
void GenerateChunkData(ChunkPos chunkPos, uint16_t* chunkData);
|
||||||
}
|
}
|
11
ScuffedMinecraft/vendor/imgui/CMakeLists.txt
vendored
Normal file
11
ScuffedMinecraft/vendor/imgui/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
add_library(imgui
|
||||||
|
imgui.cpp
|
||||||
|
imgui_demo.cpp
|
||||||
|
imgui_draw.cpp
|
||||||
|
imgui_impl_glfw.cpp
|
||||||
|
imgui_impl_opengl3.cpp
|
||||||
|
imgui_tables.cpp
|
||||||
|
imgui_widgets.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
target_include_directories(imgui PUBLIC ./)
|
Loading…
Reference in New Issue
Block a user