Compare commits

67 Commits

Author SHA1 Message Date
zhenyan121
f4114c2699 refactor: world generation (#17)
* refactor: use TBB for concurrent hash maps and parallelize chunk processing

* fix: tbb link fail

* refactor(chunk): remove biome check for caves in rivers and oceans

* refactor(random): replace std distributions with custom implementations

Avoid overhead and platform-dependent behavior of `<random>` distributions by using direct engine operations and integer arithmetic. This ensures deterministic, cross-platform results and improves performance.

* refactor(generation): use chunk seed for cave and river paths

- Use per-chunk seed instead of global path_id for cave and river generation.
- Remove unused m_sum variables and m_path_id members.
- Clamp river yaw within 10 degrees of initial direction.
- Fix river radius interpolation (use t instead of 1-t).
- Lower sea level from 64 to 63.
2026-06-14 11:36:37 +08:00
zhenyan121
932463663f feat: ocean (#16)
* feat(gameplay): add Ocean biome with water generation and heightmap adjustments

- Introduce Ocean biome enum, builder, and detection logic.
- Add ocean water building to all existing biomes and modify heightmap thresholds for low mountainous areas.
- Skip cave and river generation in Ocean (and River) biomes; avoid carving water blocks.
- Comment out border blending call and update block fill logic.

* fix(gameplay): re-enable border blending and protect water in cave gen

* refactor(generation): move ocean water build to later phase

* feat(block): add is_transitional property and refine border blending

* fix(block): set stone block as transitional

* fix(world): generate temporary chunks for surface blend neighbor data

* fix(gameplay): simplify block fill logic in blend_surface_blocks_borders

* refactor(tree): remove debug logging and unused include
2026-06-12 19:42:59 +08:00
zhenyan121
bac3df801b refactor: chunk render (#15)
* refactor(renderer): centralize VAO setup and rename init_underwater

* refactor(gameplay): replace VBO with VAO for vertex data

* fix(renderer): move depth test enable to world rendering

The `glEnable(GL_DEPTH_TEST)` call was incorrectly placed in the general `render()` function, affecting UI and text rendering. Moved it to the start of the world rendering loop to ensure depth testing is only active during 3D world pass.
2026-06-11 14:58:39 +08:00
zhenyan121
d0bc8d627f refactor: transparent render (#14)
* fix(renderer): defer uniform location retrieval and add view matrix in outline rendering

* refactor(gameplay): encapsulate per-type vertex data into VertexData struct

* feat(rendering): separate transparent blocks into discard and blend modes

* feat(renderer): implement order-independent transparency

* fix(shaders): reduce alpha discard threshold to 0.8
2026-06-11 12:21:19 +08:00
zhenyan121
2906106597 feat: water rendering (#13)
* refactor: update water texture

* feat(gameplay): implement transparent block rendering with depth sorting

* fix(world): use camera pos for distance calculations, make water passable

* refactor(player): use ivec3 for block pass check

* feat(camera): add underwater detection

* feat(renderer): add underwater effect with framebuffer post-processing

* feat(block): add gas property and refactor solid block check

* fix(assets): set leaf block transparency to false

* fix(block): set leaf as transparent
2026-05-30 15:11:40 +08:00
zhenyan121
a0139dd315 fix: msvc build fail (#12) 2026-05-28 21:55:44 +08:00
zhenyan121
5901ab7cd9 feat: grass (#11)
* feat: add grass texture and update grass_block texture

* feat: add block data

* feat: add blocks_tool

* feat: add sync info and change function in blocks_tools

* feat: add check and new function

* refactor: make block texture loading data-driven

* feat: add rendering for grass

* feat: passable grass

* feat: random grass place

* fix: memory leak in TextureManager::load_cross_plane_texture
2026-05-28 21:34:36 +08:00
zhenyan121
bbf8b4e969 refactor: river (#10)
* fix: correct snowy grass block texture

* refactor: river generation

* fix: water placement error due to interpolation

* perf: improve river naturalness

* feat: add river tab item

* fix: path truncation
2026-05-23 14:29:41 +08:00
zhenyan121
a54e87dbc6 refactor: terrain generation (#9)
* feat: add BlockType

* refactor: use fBM for heightmap generation

* feat: improve mountain realism

* refactor: adjust mountain spawn probability

* feat: add biome boundary blending

* refactor: remove resolve_biome_adjacency_conflict function

* feat: add snowy plain

* perf: speed up world generation

* refactor: lower overall terrain height
2026-05-23 10:33:52 +08:00
zhenyan121
1a26474a05 feat: add cave (#8)
* feat: add cave generate

* fix: incorrect blocks on cave surface

* fix: non-deterministic cave generator

* refactor: move all chunk generation to dedicated generation thread

* refactor: remove inital cave

* feat: add cave parameter adjustment

* refactor: adjust cave probability
2026-05-09 20:13:55 +08:00
zhenyan121
d986e03f9c fix: windows build fail (#7) 2026-05-03 19:45:14 +08:00
zhenyan121
9d200f31be refactor: chunk interpolate (#6)
* refactor: rewrite blend_heightmap_boundaries

* refactor: init_world

* fix: unnatural biome boundary transition
2026-05-03 16:02:01 +08:00
zhenyan121
a02bfad639 refactor: biome build (#5)
* refactor: rename Biome to BiomeType

* feat: add biome builder
2026-05-02 13:40:46 +08:00
zhenyan121
a63dfa7f47 feat: add river biome (#4)
* feat: add river biome

* fix: duplicate mountain terrain generation

* fix: safe_int_to_biome not include river
2026-05-01 19:18:46 +08:00
zhenyan121
d4d761b2aa Potential fix for code scanning alert no. 1: Workflow does not contain permissions (#3)
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2026-04-30 12:08:12 +08:00
zhenyan121
315c60e4a6 feat: block switching (#2)
* feat: add item tab item in dev panel

* feat: add block switching via mouse wheel
2026-04-30 11:53:35 +08:00
zhenyan121
9a8e76d25f refactor: set forest base y to 62 (#1) 2026-04-28 21:58:35 +08:00
14c942333c ci: upgrade clang image tag to latest 2026-04-28 12:46:01 +08:00
b88bc30756 ci: add find in include directory 2026-04-28 12:13:10 +08:00
a526d37f97 ci: use Docker instead of directly installing clang-format 2026-04-28 12:06:55 +08:00
fb86836e19 ci: upgrade clang-format version in CI 2026-04-28 09:38:22 +08:00
f2f00ce658 ci: add automated code style checking 2026-04-28 09:33:07 +08:00
611a795481 chore: add clang-format and pre-commit configuration 2026-04-28 09:22:55 +08:00
dc3be5a4bc refactor: adjust mountain frequency 2026-04-27 15:26:49 +08:00
932c11a646 fix: chunk conflict resolution not taking effort 2026-04-27 09:30:45 +08:00
5b2f06b3ec feat: add about tab item 2026-04-26 21:14:13 +08:00
bd5665c935 fix: can't find iota 2026-04-26 17:34:11 +08:00
59ab47d317 feat: add anisotropic filtering control 2026-04-26 17:29:58 +08:00
e34a20599d feat: add tp in devpanel 2026-04-26 14:26:39 +08:00
c5a78185ba feat: add ChunkGenerator 2026-04-26 14:10:09 +08:00
a3eb19e58f feat: smooth biome block transition 2026-04-26 11:35:16 +08:00
9402847e89 feat: add biome parameter adjustment 2026-04-25 22:23:24 +08:00
a95ad796ce feat: add world and player tab item 2026-04-25 18:36:13 +08:00
8b5717a655 refactor: extract constants into separate constants.hpp file 2026-04-25 16:25:47 +08:00
055c4d687b fix: load path failure
Co-authored-by: Copilot <copilot@github.com>
2026-04-25 14:33:43 +08:00
4ca2133ff3 feat: add DevPanel 2026-04-25 14:24:50 +08:00
ada0603a2f build: enable Freetype support 2026-04-25 13:42:14 +08:00
dc3926e47f chore: add imgui library 2026-04-24 21:25:01 +08:00
3e27ab675c fix: fullscreen resolution error on Windows 2026-04-24 18:01:17 +08:00
106cc3d398 feat: add Config class 2026-04-24 17:08:06 +08:00
2409734e89 chore: add toml++ library 2026-04-24 10:21:26 +08:00
8f8e2c1bd5 chore: remove dead code 2026-04-23 21:09:03 +08:00
2707748843 refactor: increase BLEND_RADIUS to 12 2026-04-23 15:40:40 +08:00
e90b0ce2f4 refactor: chunk generation logic 2026-04-23 15:19:34 +08:00
c7a0aff0c1 chore: add .clangd configuration 2026-04-21 22:53:34 +08:00
c2321a0a6e refactor: warp everything in Cubed namespace 2026-04-20 22:18:02 +08:00
6c74f4582c docs: add build guide 2026-04-19 18:01:09 +08:00
553955841b fix: missing face culling for old chunks during generation 2026-04-19 17:49:08 +08:00
ca82d6a447 feat: add Spectator Mode 2026-04-18 20:01:29 +08:00
0a0024361d fix: negative seed values 2026-04-18 19:11:58 +08:00
47ce4cf2d3 fix: is_init data race 2026-04-18 16:19:45 +08:00
af34d7eb82 fix: y is too height 2026-04-18 16:19:19 +08:00
03ea97055f fix: make Perlin noise seed reproducible 2026-04-18 15:50:48 +08:00
639648969b fix: range::iota build fail 2026-04-18 15:47:24 +08:00
de4df4b476 fix: data race in world::init_world() 2026-04-18 15:14:11 +08:00
11b6e88d0d feat: initialize world in multiple threads 2026-04-18 12:35:48 +08:00
099b1cbdd7 refactor: update log and leaf materials 2026-04-18 11:56:33 +08:00
955c4ddec7 fix: resolve transparency rendering issues 2026-04-18 11:55:53 +08:00
bb888fd7b7 feat: add tree generation 2026-04-18 10:59:37 +08:00
63930dcdc7 refactor: separate biome declaration and definition 2026-04-18 09:20:51 +08:00
30a4713092 refactor: extract biome logic into separate 2026-04-17 22:45:44 +08:00
f2328d19fd refactor: prevent desert from generation adjacent to mountain in biome generation 2026-04-17 22:24:29 +08:00
e69d38ad94 fix: array not include 2026-04-17 20:11:59 +08:00
5723c17f94 feat: add 4 biomes 2026-04-17 19:55:47 +08:00
be176ff18a build: upgrade C++ standard to C++23 2026-04-17 18:07:47 +08:00
68e062faa1 feat: add cpu show for windows 2026-04-17 10:52:47 +08:00
2f1edc4723 feat: add opengl version cpu gpu info show 2026-04-17 10:44:06 +08:00
190 changed files with 68948 additions and 1968 deletions

321
.clang-format Normal file
View File

@@ -0,0 +1,321 @@
---
Language: Cpp
AlignAfterOpenBracket: true
AccessModifierOffset: -4
AlignArrayOfStructures: None
AlignConsecutiveAssignments:
Enabled: false
AcrossEmptyLines: false
AcrossComments: false
AlignCompound: false
AlignFunctionDeclarations: false
AlignFunctionPointers: false
PadOperators: true
AlignConsecutiveBitFields:
Enabled: false
AcrossEmptyLines: false
AcrossComments: false
AlignCompound: false
AlignFunctionDeclarations: false
AlignFunctionPointers: false
PadOperators: false
AlignConsecutiveDeclarations:
Enabled: false
AcrossEmptyLines: false
AcrossComments: false
AlignCompound: false
AlignFunctionDeclarations: true
AlignFunctionPointers: false
PadOperators: false
AlignConsecutiveMacros:
Enabled: false
AcrossEmptyLines: false
AcrossComments: false
AlignCompound: false
AlignFunctionDeclarations: false
AlignFunctionPointers: false
PadOperators: false
AlignConsecutiveShortCaseStatements:
Enabled: false
AcrossEmptyLines: false
AcrossComments: false
AlignCaseArrows: false
AlignCaseColons: false
AlignConsecutiveTableGenBreakingDAGArgColons:
Enabled: false
AcrossEmptyLines: false
AcrossComments: false
AlignCompound: false
AlignFunctionDeclarations: false
AlignFunctionPointers: false
PadOperators: false
AlignConsecutiveTableGenCondOperatorColons:
Enabled: false
AcrossEmptyLines: false
AcrossComments: false
AlignCompound: false
AlignFunctionDeclarations: false
AlignFunctionPointers: false
PadOperators: false
AlignConsecutiveTableGenDefinitionColons:
Enabled: false
AcrossEmptyLines: false
AcrossComments: false
AlignCompound: false
AlignFunctionDeclarations: false
AlignFunctionPointers: false
PadOperators: false
AlignEscapedNewlines: Right
AlignOperands: Align
AlignTrailingComments:
AlignPPAndNotPP: true
Kind: Always
OverEmptyLines: 0
AllowAllArgumentsOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowBreakBeforeNoexceptSpecifier: Never
AllowBreakBeforeQtProperty: false
AllowShortBlocksOnASingleLine: Never
AllowShortCaseExpressionOnASingleLine: true
AllowShortCaseLabelsOnASingleLine: false
AllowShortCompoundRequirementOnASingleLine: true
AllowShortEnumsOnASingleLine: true
AllowShortFunctionsOnASingleLine: All
AllowShortIfStatementsOnASingleLine: Never
AllowShortLambdasOnASingleLine: All
AllowShortLoopsOnASingleLine: false
AllowShortNamespacesOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AttributeMacros:
- __capability
BinPackArguments: true
BinPackLongBracedList: true
BinPackParameters: BinPack
BitFieldColonSpacing: Both
BracedInitializerIndentWidth: -1
BraceWrapping:
AfterCaseLabel: false
AfterClass: false
AfterControlStatement: Never
AfterEnum: false
AfterExternBlock: false
AfterFunction: false
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
BeforeCatch: false
BeforeElse: false
BeforeLambdaBody: false
BeforeWhile: false
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakAdjacentStringLiterals: true
BreakAfterAttributes: Leave
BreakAfterJavaFieldAnnotations: false
BreakAfterOpenBracketBracedList: false
BreakAfterOpenBracketFunction: false
BreakAfterOpenBracketIf: false
BreakAfterOpenBracketLoop: false
BreakAfterOpenBracketSwitch: false
BreakAfterReturnType: None
BreakArrays: true
BreakBeforeBinaryOperators: None
BreakBeforeCloseBracketBracedList: false
BreakBeforeCloseBracketFunction: false
BreakBeforeCloseBracketIf: false
BreakBeforeCloseBracketLoop: false
BreakBeforeCloseBracketSwitch: false
BreakBeforeConceptDeclarations: Always
BreakBeforeBraces: Attach
BreakBeforeInlineASMColon: OnlyMultiline
BreakBeforeTemplateCloser: false
BreakBeforeTernaryOperators: true
BreakBinaryOperations: Never
BreakConstructorInitializers: BeforeColon
BreakFunctionDefinitionParameters: false
BreakInheritanceList: BeforeColon
BreakStringLiterals: true
BreakTemplateDeclarations: MultiLine
ColumnLimit: 80
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: AlignFirstComment
DerivePointerAlignment: false
DisableFormat: false
EmptyLineAfterAccessModifier: Never
EmptyLineBeforeAccessModifier: LogicalBlock
EnumTrailingComma: Leave
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true
ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
IfMacros:
- KJ_IF_MAYBE
IncludeBlocks: Regroup
IncludeCategories:
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
Priority: 2
SortPriority: 0
CaseSensitive: false
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
Priority: 3
SortPriority: 0
CaseSensitive: false
- Regex: '.*'
Priority: 1
SortPriority: 0
CaseSensitive: false
IncludeIsMainRegex: '(Test)?$'
IncludeIsMainSourceRegex: ''
IndentAccessModifiers: false
IndentCaseBlocks: false
IndentCaseLabels: false
IndentExportBlock: true
IndentExternBlock: AfterExternBlock
IndentGotoLabels: true
IndentPPDirectives: None
IndentRequiresClause: true
IndentWidth: 4
IndentWrappedFunctionNames: false
InsertBraces: false
InsertNewlineAtEOF: false
InsertTrailingCommas: None
IntegerLiteralSeparator:
Binary: 0
BinaryMinDigitsInsert: 0
BinaryMaxDigitsRemove: 0
Decimal: 0
DecimalMinDigitsInsert: 0
DecimalMaxDigitsRemove: 0
Hex: 0
HexMinDigitsInsert: 0
HexMaxDigitsRemove: 0
BinaryMinDigits: 0
DecimalMinDigits: 0
HexMinDigits: 0
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLines:
AtEndOfFile: false
AtStartOfBlock: true
AtStartOfFile: true
KeepFormFeed: false
LambdaBodyIndentation: Signature
LineEnding: DeriveLF
MacroBlockBegin: ''
MacroBlockEnd: ''
MainIncludeChar: Quote
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
NumericLiteralCase:
ExponentLetter: Leave
HexDigit: Leave
Prefix: Leave
Suffix: Leave
ObjCBinPackProtocolList: Auto
ObjCBlockIndentWidth: 2
ObjCBreakBeforeNestedBlockParam: true
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
OneLineFormatOffRegex: ''
PackConstructorInitializers: BinPack
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakBeforeMemberAccess: 150
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakOpenParenthesis: 0
PenaltyBreakScopeResolution: 500
PenaltyBreakString: 1000
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000
PenaltyIndentedWhitespace: 0
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Left
PPIndentWidth: -1
QualifierAlignment: Leave
ReferenceAlignment: Pointer
ReflowComments: Always
RemoveBracesLLVM: false
RemoveEmptyLinesInUnwrappedLines: false
RemoveParentheses: Leave
RemoveSemicolon: false
RequiresClausePosition: OwnLine
RequiresExpressionIndentation: OuterScope
SeparateDefinitionBlocks: Leave
ShortNamespaceLines: 1
SkipMacroDefinitionBody: false
SortIncludes:
Enabled: true
IgnoreCase: false
IgnoreExtension: false
SortJavaStaticImport: Before
SortUsingDeclarations: LexicographicNumeric
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterOperatorKeyword: false
SpaceAfterTemplateKeyword: true
SpaceAroundPointerQualifiers: Default
SpaceBeforeAssignmentOperators: true
SpaceBeforeCaseColon: false
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeJsonColon: false
SpaceBeforeParens: ControlStatements
SpaceBeforeParensOptions:
AfterControlStatements: true
AfterForeachMacros: true
AfterFunctionDefinitionName: false
AfterFunctionDeclarationName: false
AfterIfMacros: true
AfterNot: false
AfterOverloadedOperator: false
AfterPlacementOperator: true
AfterRequiresInClause: false
AfterRequiresInExpression: false
BeforeNonEmptyParentheses: false
SpaceBeforeRangeBasedForLoopColon: true
SpaceBeforeSquareBrackets: false
SpaceInEmptyBraces: Never
SpacesBeforeTrailingComments: 1
SpacesInAngles: Never
SpacesInContainerLiterals: true
SpacesInLineCommentPrefix:
Minimum: 1
Maximum: -1
SpacesInParens: Never
SpacesInParensOptions:
ExceptDoubleParentheses: false
InCStyleCasts: false
InConditionalStatements: false
InEmptyParentheses: false
Other: false
SpacesInSquareBrackets: false
Standard: Latest
StatementAttributeLikeMacros:
- Q_EMIT
StatementMacros:
- Q_UNUSED
- QT_REQUIRE_VERSION
TableGenBreakInsideDAGArg: DontBreak
TabWidth: 8
UseTab: Never
VerilogBreakBetweenInstancePorts: true
WhitespaceSensitiveMacros:
- BOOST_PP_STRINGIZE
- CF_SWIFT_NAME
- NS_SWIFT_NAME
- PP_STRINGIZE
- STRINGIZE
WrapNamespaceBodyWithEmptyLines: Leave
...

3
.clang-format-ignore Normal file
View File

@@ -0,0 +1,3 @@
third_party/
build/
vendor/

2
.clangd Normal file
View File

@@ -0,0 +1,2 @@
CompileFlags:
Add: [-Wall, -Wextra, -Wpedantic, -Wno-unused-parameter]

17
.github/workflows/format-check.yml vendored Normal file
View File

@@ -0,0 +1,17 @@
# .github/workflows/format-check.yml
name: Code Format Check
on: [push, pull_request]
permissions:
contents: read
jobs:
formatting:
runs-on: ubuntu-latest
container: silkeh/clang:latest
steps:
- uses: actions/checkout@v4
- name: Run clang-format
run: |
find src include -name '*.cpp' -o -name '*.h' -print0 | xargs -0 clang-format --dry-run --Werror

2
.gitignore vendored
View File

@@ -40,3 +40,5 @@ CMakeError.log
*.swo *.swo
*~ *~
.DS_Store .DS_Store
assets/config.toml
.venv/

8
.pre-commit-config.yaml Normal file
View File

@@ -0,0 +1,8 @@
repos:
- repo: https://github.com/pre-commit/mirrors-clang-format
rev: "v22.1.4"
hooks:
- id: clang-format
args: ["--style=file"]
types_or: ["c++", "c"]
exclude: '^third_party/.*$'

1
.python-version Normal file
View File

@@ -0,0 +1 @@
3.14

View File

@@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.14...3.24) cmake_minimum_required(VERSION 3.14...3.24)
project(Cubed LANGUAGES C CXX) project(Cubed LANGUAGES C CXX)
set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON) set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
@@ -58,6 +58,21 @@ if (WIN32)
if(TARGET freetype) if(TARGET freetype)
add_library(Freetype::Freetype ALIAS freetype) add_library(Freetype::Freetype ALIAS freetype)
endif() endif()
set(_BUILD_SHARED_LIBS_SAVED ${BUILD_SHARED_LIBS})
set(BUILD_SHARED_LIBS ON)
FetchContent_Declare(
onetbb
GIT_REPOSITORY https://github.com/uxlfoundation/oneTBB.git
GIT_TAG v2023.0.0
)
set(BUILD_TESTING OFF CACHE BOOL "Build tests" FORCE)
set(TBB_TEST OFF CACHE BOOL "Build TBB tests" FORCE)
FetchContent_MakeAvailable(onetbb)
set(BUILD_SHARED_LIBS ${_BUILD_SHARED_LIBS_SAVED})
unset(_BUILD_SHARED_LIBS_SAVED)
endif() endif()
FetchContent_Declare( FetchContent_Declare(
@@ -74,6 +89,14 @@ FetchContent_Declare(
) )
FetchContent_MakeAvailable(soil2) FetchContent_MakeAvailable(soil2)
FetchContent_Declare(
tomlplusplus
GIT_REPOSITORY https://github.com/marzer/tomlplusplus.git
GIT_TAG v3.4.0
)
FetchContent_MakeAvailable(tomlplusplus)
add_subdirectory(third_party/imgui)
set(INCLUDE_DIR ${PROJECT_SOURCE_DIR}/include) set(INCLUDE_DIR ${PROJECT_SOURCE_DIR}/include)
@@ -82,34 +105,55 @@ add_executable(${PROJECT_NAME}
src/app.cpp src/app.cpp
src/debug_collector.cpp src/debug_collector.cpp
src/camera.cpp src/camera.cpp
src/config.cpp
src/dev_panel.cpp
src/gameplay/biome.cpp
src/gameplay/chunk.cpp src/gameplay/chunk.cpp
src/gameplay/chunk_generator.cpp
src/gameplay/player.cpp src/gameplay/player.cpp
src/gameplay/tree.cpp
src/gameplay/world.cpp src/gameplay/world.cpp
src/input.cpp src/input.cpp
src/map_table.cpp src/map_table.cpp
src/renderer.cpp src/renderer.cpp
src/shader.cpp src/shader.cpp
src/texture_manager.cpp src/texture_manager.cpp
src/tools/cubed_random.cpp
src/tools/math_tools.cpp src/tools/math_tools.cpp
src/tools/shader_tools.cpp src/tools/shader_tools.cpp
src/tools/font.cpp src/tools/font.cpp
src/tools/log.cpp
src/tools/perlin_noise.cpp src/tools/perlin_noise.cpp
src/ui/text.cpp src/ui/text.cpp
src/window.cpp src/window.cpp
src/gameplay/builders/biome_builder.cpp
src/gameplay/builders/plain_builder.cpp
src/gameplay/builders/mountain_builder.cpp
src/gameplay/builders/river_builder.cpp
src/gameplay/builders/desert_builder.cpp
src/gameplay/builders/forest_builder.cpp
src/gameplay/cave_carver.cpp
src/gameplay/cave_path.cpp
src/gameplay/builders/snowy_plain_builder.cpp
src/gameplay/river_worm.cpp
src/gameplay/river_path.cpp
src/block.cpp
src/gameplay/vertex_data.cpp
src/gameplay/builders/ocean_builder.cpp
) )
if(CMAKE_BUILD_TYPE STREQUAL "Debug") if(CMAKE_BUILD_TYPE STREQUAL "Debug")
message(STATUS "Building with AddressSanitizer enabled for target: ${PROJECT_NAME}") message(STATUS "Building with AddressSanitizer enabled for target: ${PROJECT_NAME}")
target_compile_options(${PROJECT_NAME} PRIVATE target_compile_options(${PROJECT_NAME} PRIVATE
-fsanitize=address #-fsanitize=address
#-fsanitize=thread
-fno-omit-frame-pointer -fno-omit-frame-pointer
-g -g
) )
target_link_options(${PROJECT_NAME} PRIVATE target_link_options(${PROJECT_NAME} PRIVATE
-fsanitize=address #-fsanitize=address
#-fsanitize=thread
) )
target_compile_definitions(${PROJECT_NAME} PRIVATE DEBUG_MODE) target_compile_definitions(${PROJECT_NAME} PRIVATE DEBUG_MODE)
@@ -132,8 +176,15 @@ target_link_libraries(${PROJECT_NAME}
OpenGL::GL OpenGL::GL
soil2 soil2
Freetype::Freetype Freetype::Freetype
tomlplusplus::tomlplusplus
imgui
tbb
) )
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
# target_link_libraries(${PROJECT_NAME} PRIVATE tbb)
endif()
if (UNIX AND NOT APPLE) if (UNIX AND NOT APPLE)
target_link_libraries(${PROJECT_NAME} target_link_libraries(${PROJECT_NAME}
PRIVATE PRIVATE
@@ -151,3 +202,19 @@ if (UNIX AND NOT APPLE)
target_compile_options(${PROJECT_NAME} PRIVATE ${EGL_CFLAGS_OTHER} ${Wayland_CFLAGS_OTHER}) target_compile_options(${PROJECT_NAME} PRIVATE ${EGL_CFLAGS_OTHER} ${Wayland_CFLAGS_OTHER})
endif() endif()
if (WIN32)
foreach(TBB_LIB IN ITEMS tbb tbbmalloc tbbmalloc_proxy)
if(TARGET ${TBB_LIB})
add_custom_command(
TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
$<TARGET_FILE:${TBB_LIB}>
$<TARGET_FILE_DIR:${PROJECT_NAME}>
COMMENT "Copying ${TBB_LIB}.dll"
)
else()
message(STATUS "Target ${TBB_LIB} not found, skipping copy")
endif()
endforeach()
endif()

View File

@@ -1,2 +1,21 @@
## What's it ## What's it
A cube game like Minecraft, using C++ and OpenGL. A cube game like Minecraft, using C++ and OpenGL.
## Build Guide
### Prerequisites
- **CMake** (>= 3.24)
- **C++ 23** compatible compiler
### Step
1. Clone the repository
```bash
git clone https://github.com/zhenyan121/Cubed.git && cd Cubed
```
2. Configure with CMake
```bash
mkdir build && cd build
cmake -G "Ninja" ..
```
3. Build the project
```bash
ninja
```

View File

@@ -0,0 +1,10 @@
id = 0
is_blend = false
is_cross_plane = false
is_discard = true
is_gas = true
is_liquid = false
is_passable = true
is_transitional = false
is_transparent = true
name = 'air'

View File

@@ -0,0 +1,10 @@
id = 2
is_blend = false
is_cross_plane = false
is_discard = false
is_gas = false
is_liquid = false
is_passable = false
is_transitional = true
is_transparent = false
name = 'dirt'

View File

@@ -0,0 +1,10 @@
id = 9
is_blend = false
is_cross_plane = true
is_discard = true
is_gas = false
is_liquid = false
is_passable = true
is_transitional = false
is_transparent = true
name = 'grass'

View File

@@ -0,0 +1,10 @@
id = 1
is_blend = false
is_cross_plane = false
is_discard = false
is_gas = false
is_liquid = false
is_passable = false
is_transitional = true
is_transparent = false
name = 'grass_block'

View File

@@ -0,0 +1,10 @@
id = 6
is_blend = false
is_cross_plane = false
is_discard = true
is_gas = false
is_liquid = false
is_passable = false
is_transitional = false
is_transparent = true
name = 'leaf'

View File

@@ -0,0 +1,10 @@
id = 5
is_blend = false
is_cross_plane = false
is_discard = false
is_gas = false
is_liquid = false
is_passable = false
is_transitional = false
is_transparent = false
name = 'log'

View File

@@ -0,0 +1,10 @@
id = 4
is_blend = false
is_cross_plane = false
is_discard = false
is_gas = false
is_liquid = false
is_passable = false
is_transitional = true
is_transparent = false
name = 'sand'

View File

@@ -0,0 +1,10 @@
id = 8
is_blend = false
is_cross_plane = false
is_discard = false
is_gas = false
is_liquid = false
is_passable = false
is_transitional = true
is_transparent = false
name = 'snowy_grass_block'

View File

@@ -0,0 +1,10 @@
id = 3
is_blend = false
is_cross_plane = false
is_discard = false
is_gas = false
is_liquid = false
is_passable = false
is_transitional = true
is_transparent = false
name = 'stone'

View File

@@ -0,0 +1,10 @@
name = "template"
id = 0
is_liquid = false
is_gas = false
is_passable = false
is_cross_plane = false
is_transparent = false
is_discard = false
is_blend = false
is_transitional = false

View File

@@ -0,0 +1,10 @@
id = 7
is_blend = true
is_cross_plane = false
is_discard = false
is_gas = false
is_liquid = true
is_passable = true
is_transitional = false
is_transparent = true
name = 'water'

View File

@@ -0,0 +1,28 @@
#version 460
layout (location = 0) out vec4 accum;
layout (location = 1) out float reveal;
in vec2 tc;
flat in int tex_layer;
in float v_depth;
layout (binding = 0) uniform sampler2DArray samp;
float weight(float z, float a) {
float intermediate = 0.03 / (1e-5 + pow(z / 200.0, 4.0));
return a * clamp(intermediate, 1e-2, 3e2);
}
void main() {
vec4 color = texture(samp, vec3(tc, tex_layer));
float alpha = color.a;
if (alpha < 1e-4) discard;
float w = weight(v_depth, alpha);
accum = vec4(color.rgb * alpha * w, alpha * w);
reveal = alpha;
}

View File

@@ -0,0 +1,21 @@
#version 460
layout (location = 0) in vec3 pos;
layout (location = 1) in vec2 texCoord;
layout (location = 2) in float layer;
out vec2 tc;
flat out int tex_layer;
out float v_depth;
uniform mat4 mv_matrix;
uniform mat4 proj_matrix;
void main(void) {
vec4 view_pos = mv_matrix * vec4(pos, 1.0);
gl_Position = proj_matrix * view_pos;
tc = texCoord;
tex_layer = int(layer);
v_depth = -view_pos.z;
}

View File

@@ -0,0 +1,19 @@
#version 460
uniform sampler2D u_accumTex;
uniform sampler2D u_revealTex;
in vec2 TexCoord;
out vec4 FragColor;
void main() {
vec4 a = texture(u_accumTex, TexCoord);
float r = texture(u_revealTex, TexCoord).r;
if (a.a < 1e-4) discard;
vec3 color = a.rgb / max(a.a, 1e-5);
float transmittance = r;
float opacity = 1.0 - transmittance;
FragColor = vec4(color * opacity, opacity);
}

View File

@@ -0,0 +1,11 @@
#version 460
layout (location = 0) in vec2 pos;
layout (location = 1) in vec2 texCoord;
out vec2 TexCoord;
void main() {
gl_Position = vec4(pos.x, pos.y, 0.0, 1.0);
TexCoord = texCoord;
}

View File

@@ -8,5 +8,8 @@ layout (binding = 0) uniform sampler2DArray samp;
void main(void) { void main(void) {
color = texture(samp, vec3(tc, tex_layer)); color = texture(samp, vec3(tc, tex_layer));
if (color.a < 0.8) {
discard;
}
//color = varyingColor; //color = varyingColor;
} }

View File

@@ -0,0 +1,35 @@
#version 460
in vec2 TexCoord;
out vec4 FragColor;
uniform sampler2D u_sceneTexture;
uniform float u_time;
uniform bool u_underwater;
uniform vec3 u_waterColor;
uniform float u_fogDensity;
void main() {
vec4 original = texture(u_sceneTexture, TexCoord);
if (!u_underwater) {
FragColor = original;
return;
}
vec2 distoredUV = TexCoord;
float strength = 0.003;
distoredUV.x += sin(TexCoord.y * 15.0 + u_time * 5.0) * strength;
distoredUV.y += cos(TexCoord.x * 15.0 + u_time * 4.3) * strength;
distoredUV = clamp(distoredUV, 0.001, 0.999);
vec4 distorted = texture(u_sceneTexture, distoredUV);
float caustic = 0.9 + 0.1 * sin(TexCoord.x * 20.0 + u_time) * cos(TexCoord.y * 20.0 + u_time * 1.2);
vec3 causticLight = vec3(caustic, caustic * 0.95, caustic * 0.9);
//vec3 causticLight = vec3(1.0);
float fogFactor = clamp(1.0 - (TexCoord.y * u_fogDensity * 10.0), 0.0, 1.0);
vec3 mixed = mix(u_waterColor, distorted.rgb * causticLight, fogFactor);
FragColor = vec4(mixed, 1.0);
}

View File

@@ -0,0 +1,11 @@
#version 460
layout (location = 0) in vec2 pos;
layout (location = 1) in vec2 texCoord;
out vec2 TexCoord;
void main() {
gl_Position = vec4(pos.x, pos.y, 0.0, 1.0);
TexCoord = texCoord;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 277 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 563 B

After

Width:  |  Height:  |  Size: 555 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 563 B

After

Width:  |  Height:  |  Size: 555 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 563 B

After

Width:  |  Height:  |  Size: 555 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 563 B

After

Width:  |  Height:  |  Size: 555 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 399 B

After

Width:  |  Height:  |  Size: 381 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 398 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 398 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 398 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 398 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 398 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 398 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 259 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 215 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 259 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 259 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 259 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 215 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 391 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 391 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 391 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 391 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 391 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 391 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 568 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 482 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 568 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 568 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 568 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 394 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 382 B

After

Width:  |  Height:  |  Size: 418 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 382 B

After

Width:  |  Height:  |  Size: 418 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 382 B

After

Width:  |  Height:  |  Size: 418 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 382 B

After

Width:  |  Height:  |  Size: 418 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 382 B

After

Width:  |  Height:  |  Size: 418 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 382 B

After

Width:  |  Height:  |  Size: 418 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 261 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 261 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 261 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 261 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 261 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 261 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 882 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 277 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 499 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 890 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 874 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 877 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 914 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 915 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 874 B

View File

@@ -1,15 +1,14 @@
#pragma once #pragma once
#include <glm/glm.hpp> #include <glm/glm.hpp>
namespace Cubed {
struct AABB { struct AABB {
glm::vec3 min{0.0f, 0.0f, 0.0f}; glm::vec3 min{0.0f, 0.0f, 0.0f};
glm::vec3 max{0.0f, 0.0f, 0.0f}; glm::vec3 max{0.0f, 0.0f, 0.0f};
AABB(glm::vec3 min_point, glm::vec3 max_point): AABB(glm::vec3 min_point, glm::vec3 max_point)
min(min_point), : min(min_point), max(max_point) {}
max(max_point)
{
}
bool intersects(const AABB& other) const { bool intersects(const AABB& other) const {
return (min.x <= other.max.x && max.x >= other.min.x) && return (min.x <= other.max.x && max.x >= other.min.x) &&
@@ -17,3 +16,5 @@ struct AABB {
(min.z <= other.max.z && max.z >= other.min.z); (min.z <= other.max.z && max.z >= other.min.z);
} }
}; };
} // namespace Cubed

View File

@@ -1,31 +1,49 @@
#pragma once #pragma once
#define GLFW_INCLUDE_NONE
#include <Cubed/camera.hpp> #include "Cubed/camera.hpp"
#include <Cubed/gameplay/world.hpp> #include "Cubed/dev_panel.hpp"
#include <Cubed/input.hpp> #include "Cubed/gameplay/world.hpp"
#include <Cubed/renderer.hpp> #include "Cubed/renderer.hpp"
#include <Cubed/texture_manager.hpp> #include "Cubed/texture_manager.hpp"
#include <Cubed/window.hpp> #include "Cubed/window.hpp"
namespace Cubed {
class App { class App {
public: public:
App(); App();
~App(); ~App();
static void cursor_position_callback(GLFWwindow* window, double xpos, double ypos); static void cursor_position_callback(GLFWwindow* window, double xpos,
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods); double ypos);
static void mouse_button_callback(GLFWwindow* window, int button, int action, int mods); static void key_callback(GLFWwindow* window, int key, int scancode,
int action, int mods);
static void mouse_button_callback(GLFWwindow* window, int button,
int action, int mods);
static void window_focus_callback(GLFWwindow* window, int focused); static void window_focus_callback(GLFWwindow* window, int focused);
static void window_reshape_callback(GLFWwindow* window, int new_width, int new_height); static void window_reshape_callback(GLFWwindow* window, int new_width,
int new_height);
static void mouse_scroll_callback(GLFWwindow* window, double xoffset,
double yoffset);
static void cursor_enter_callback(GLFWwindow* window, int entered);
static void char_callback(GLFWwindow* window, unsigned int ch);
static int start_cubed_application(int argc, char** argv); static int start_cubed_application(int argc, char** argv);
static unsigned int seed(); static unsigned int seed();
static float delte_time(); static float delte_time();
static float get_fps(); static float get_fps();
Camera& camera();
DevPanel& dev_panel();
Renderer& renderer();
TextureManager& texture_manager();
Window& window();
World& world();
private: private:
Camera m_camera; Camera m_camera;
TextureManager m_texture_manager; TextureManager m_texture_manager;
World m_world; World m_world;
Renderer m_renderer{m_camera, m_world, m_texture_manager}; DevPanel m_dev_panel{*this};
Renderer m_renderer{m_camera, m_world, m_texture_manager, m_dev_panel};
Window m_window{m_renderer}; Window m_window{m_renderer};
@@ -35,7 +53,6 @@ private:
inline static double fps_time_count = 0.0f; inline static double fps_time_count = 0.0f;
inline static int frame_count = 0; inline static int frame_count = 0;
inline static int fps = 0; inline static int fps = 0;
inline static unsigned int m_seed = 0;
void init(); void init();
@@ -47,3 +64,5 @@ private:
void run(); void run();
void update(); void update();
}; };
} // namespace Cubed

View File

@@ -1,35 +1,37 @@
#pragma once #pragma once
#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
#include <glm/glm.hpp> #include <glm/glm.hpp>
#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 <glad/glad.h>
#include <GLFW/glfw3.h> namespace Cubed {
class Player; class Player;
class Camera { class Camera {
private: private:
bool m_firse_mouse = true; bool m_firse_mouse = true;
Player* m_player; Player* m_player;
float m_last_mouse_x, m_last_mouse_y; float m_last_mouse_x, m_last_mouse_y;
glm::vec3 m_camera_pos; glm::vec3 m_camera_pos;
bool m_under_water = false;
public: public:
Camera(); Camera();
void update_move_camera(); void update_move_camera();
void camera_init(Player* player); void camera_init(Player* player);
void hot_reload();
void reset_camera(); void reset_camera();
void update_cursor_position_camera(double xpos, double ypos); void update_cursor_position_camera(double xpos, double ypos);
const glm::mat4 get_camera_lookat() const; const glm::mat4 get_camera_lookat() const;
const glm::vec3& get_camera_pos() const; const glm::vec3& get_camera_pos() const;
bool is_under_water() const;
}; };
} // namespace Cubed

View File

@@ -1,150 +1,107 @@
#pragma once #pragma once
constexpr int WORLD_SIZE_Y = 256; #include "Cubed/tools/cubed_assert.hpp"
constexpr int MAX_BLOCK_NUM = 4;
constexpr int MAX_UI_NUM = 1;
constexpr int CHUCK_SIZE = 16; #include <toml++/toml.hpp>
constexpr int DISTANCE = 16;
constexpr int MAX_BLOCK_STATUS = 1;
constexpr int MAX_CHARACTER = 128;
constexpr float NORMAL_FOV = 70.0f;
constexpr int SEED = 999; namespace Cubed {
constexpr float VERTICES_POS[6][6][3] = { template <typename T>
// ===== front (z = +1) ===== concept TomlValueType =
0.0f, 0.0f, 1.0f, // bottom left std::same_as<T, int> || std::same_as<T, bool> || std::same_as<T, double> ||
0.0f, 1.0f, 1.0f, // top left std::same_as<T, const char*> || std::same_as<T, toml::date> ||
1.0f, 1.0f, 1.0f, // top right std::same_as<T, toml::time> || std::same_as<T, toml::date_time> ||
1.0f, 1.0f, 1.0f, // top right std::same_as<T, std::string>;
1.0f, 0.0f, 1.0f, // bottom right
0.0f, 0.0f, 1.0f, // bottom left
// ===== right (x = +1) =====
1.0f, 0.0f, 1.0f, // bottom front
1.0f, 0.0f, 0.0f, // bottom back
1.0f, 1.0f, 0.0f, // top back
1.0f, 1.0f, 0.0f, // top back
1.0f, 1.0f, 1.0f, // top front
1.0f, 0.0f, 1.0f, // bottom front
// ===== back (z = -1) =====
0.0f, 0.0f, 0.0f, // bottom left
1.0f, 0.0f, 0.0f, // bottom right
1.0f, 1.0f, 0.0f, // top right
1.0f, 1.0f, 0.0f, // top right
0.0f, 1.0f, 0.0f, // top left
0.0f, 0.0f, 0.0f, // bottom left
// ===== left (x = -1) =====
0.0f, 0.0f, 0.0f, // bottom back
0.0f, 0.0f, 1.0f, // bottom front
0.0f, 1.0f, 1.0f, // top front
0.0f, 1.0f, 1.0f, // top front
0.0f, 1.0f, 0.0f, // top back
0.0f, 0.0f, 0.0f, // bottom back
// ===== top (y = +1) =====
0.0f, 1.0f, 0.0f, // back left
1.0f, 1.0f, 0.0f, // back right
1.0f, 1.0f, 1.0f, // front right
1.0f, 1.0f, 1.0f, // front right
0.0f, 1.0f, 1.0f, // front left
0.0f, 1.0f, 0.0f, // back left
// ===== bottom (y = -1) =====
0.0f, 0.0f, 1.0f, // front left
1.0f, 0.0f, 1.0f, // front right
1.0f, 0.0f, 0.0f, // back right
1.0f, 0.0f, 0.0f, // back right
0.0f, 0.0f, 0.0f, // back left
0.0f, 0.0f, 1.0f // front left
};
constexpr float TEX_COORDS[6][6][2] = { class Config {
// ===== front (z = +1) ===== public:
0.0f, 1.0f, // bottom left Config();
0.0f, 0.0f, // top left ~Config();
1.0f, 0.0f, // top right
1.0f, 0.0f, // top right static Config& get();
1.0f, 1.0f, // bottom right
0.0f, 1.0f, // bottom left toml::table& table();
// ===== right (x = +1) =====
0.0f, 1.0f, // bottom front void load_or_create_config();
1.0f, 1.0f, // bottom back void save_to_file();
1.0f, 0.0f, // top back
1.0f, 0.0f, // top back template <TomlValueType T> T get(std::string_view key) const {
0.0f, 0.0f, // top front size_t cur = 0;
0.0f, 1.0f, // bottom front auto pos = key.find('.');
// ===== back (z = -1) ===== const toml::table* table = &m_tbl;
1.0f, 1.0f, // bottom left while (pos != std::string_view::npos) {
0.0f, 1.0f, // bottom right std::string_view s = key.substr(cur, pos - cur);
0.0f, 0.0f, // top right if (s.empty()) {
0.0f, 0.0f, // top right Logger::error("Empty key/table name in path '{}'", key);
1.0f, 0.0f, // top left ASSERT(false);
1.0f, 1.0f, // bottom left std::abort();
// ===== left (x = -1) ===== }
1.0f, 1.0f, // bottom back cur = pos + 1;
0.0f, 1.0f, // bottom front pos = key.find('.', cur);
0.0f, 0.0f, // top front if (auto* next = (*table)[s].as_table()) {
0.0f, 0.0f, // top front table = next;
1.0f, 0.0f, // top back } else {
1.0f, 1.0f, // bottom back Logger::error("Can't find table {}", s);
// ===== top (y = +1) ===== ASSERT(false);
0.0f, 0.0f, // back left std::abort();
1.0f, 0.0f, // back right }
1.0f, 1.0f, // front right }
1.0f, 1.0f, // front right std::string_view n_key = key.substr(cur);
0.0f, 1.0f, // front left if (n_key.empty()) {
0.0f, 0.0f, // back left Logger::error("Trailing dot in path '{}'", key);
// ===== bottom (y = -1) ===== ASSERT(false);
0.0f, 0.0f, // front left std::abort();
1.0f, 0.0f, // front right }
1.0f, 1.0f, // back right auto opt = (*table)[n_key].value<T>();
1.0f, 1.0f, // back right if (opt) {
0.0f, 1.0f, // back left return *opt;
0.0f, 0.0f, // front left } else {
Logger::error("Can't find key {}", n_key);
ASSERT(false);
std::abort();
}
}
template <typename T> void set(std::string_view key, T&& val) {
if constexpr (!TomlValueType<std::decay_t<T>>) {
static_assert(false, "Type Not Support");
}
size_t cur = 0;
auto pos = key.find('.');
toml::table* table = &m_tbl;
while (pos != std::string_view::npos) {
std::string_view s = key.substr(cur, pos - cur);
if (s.empty()) {
Logger::error("Empty key/table name in path '{}'", key);
ASSERT(false);
std::abort();
}
cur = pos + 1;
pos = key.find('.', cur);
if (auto* next = (*table)[s].as_table()) {
table = next;
} else {
auto [it, inserted] = table->insert_or_assign(s, toml::table{});
table = it->second.as_table();
}
}
std::string_view n_key = key.substr(cur);
if (n_key.empty()) {
Logger::error("Trailing dot in path '{}'", key);
ASSERT(false);
std::abort();
}
table->insert_or_assign(n_key, std::forward<T>(val));
}
template <typename T> void set_and_save(std::string_view key, T&& val) {
set(key, std::forward(val));
save_to_file();
}
toml::node_view<toml::node> val_view(std::string_view key);
private:
toml::table m_tbl;
constexpr static inline std::string_view CONGIF_PATH =
ASSETS_PATH "config.toml";
void create_config();
}; };
constexpr float CUBE_VER[24] = { } // namespace Cubed
0.0, 0.0, 0.0,
1.0, 0.0, 0.0,
1.0, 1.0, 0.0,
0.0, 1.0, 0.0,
0.0, 0.0, 1.0,
1.0, 0.0, 1.0,
1.0, 1.0, 1.0,
0.0, 1.0, 1.0
};
constexpr int OUTLINE_CUBE_INDICES[24] = {
0,1, 1,2, 2,3, 3,0,
4,5, 5,6, 6,7, 7,4,
0,4, 1,5, 2,6, 3,7
};
constexpr float SQUARE_VERTICES[6][2] = {
-0.5f, -0.5f, // bottom left
-0.5f, 0.5f, // top left
0.5f, 0.5f, // top right
0.5f, 0.5f, // top right
0.5f, -0.5f, // bottom right
-0.5f, -0.5f // bottom left
};
constexpr float SQUARE_TEXTURE_POS[6][2] = {
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
1.0f, 1.0f,
1.0f, 0.0f,
0.0f, 0.0f,
};
struct Vertex {
float x = 0.0f, y = 0.0f, z = 0.0f;
float s = 0.0f, t = 0.0f;
float layer = 0.0f;
};
struct Vertex2D {
float x = 0.0f, y = 0.0f;
float s = 0.0f, t = 0.0f;
float layer = 0.0f;
};

View File

@@ -0,0 +1,35 @@
#pragma once
#include "Cubed/gameplay/chunk_pos.hpp"
#include <array>
namespace Cubed {
constexpr int WORLD_SIZE_Y = 256;
constexpr int CHUNK_SIZE = 16;
constexpr int SEA_LEVEL = 63;
constexpr int MAX_UI_NUM = 1;
constexpr int MAX_BLOCK_STATUS = 1;
constexpr int MAX_BIOME_SUM = 4;
constexpr int MAX_CHARACTER = 128;
constexpr int PRE_LOAD_DISTANCE = 24;
constexpr int MAX_DISTANCE = 128;
constexpr int CROSS_PLANE_DISTANCE = 8;
constexpr float DEFAULT_FOV = 70.0f;
constexpr float DEFAULT_MAX_WALK_SPEED = 4.5f;
constexpr float DEFAULT_MAX_RUN_SPEED = 7.0f;
constexpr float DEFAULT_ACCELERATION = 10.0f;
constexpr float DEFAULT_DECELERATION = 15.0f;
constexpr float DEFAULT_G = 22.5f;
static constexpr int SIZE_X = CHUNK_SIZE;
static constexpr int SIZE_Y = WORLD_SIZE_Y;
static constexpr int SIZE_Z = CHUNK_SIZE;
constexpr ChunkPos CHUNK_DIR[]{{1, 0}, {-1, 0}, {0, 1}, {0, -1},
{1, 1}, {-1, 1}, {1, -1}, {-1, -1}};
using HeightMapArray = std::array<std::array<int, CHUNK_SIZE>, CHUNK_SIZE>;
} // namespace Cubed

View File

@@ -1,9 +1,11 @@
#pragma once #pragma once
#include <Cubed/ui/text.hpp> #include "Cubed/ui/text.hpp"
#include <unordered_map> #include <unordered_map>
namespace Cubed {
class DebugCollector { class DebugCollector {
public: public:
static DebugCollector& get(); static DebugCollector& get();
@@ -18,3 +20,5 @@ public:
private: private:
std::unordered_map<std::size_t, Text> m_texts; std::unordered_map<std::size_t, Text> m_texts;
}; };
} // namespace Cubed

View File

@@ -0,0 +1,60 @@
#pragma once
#include <toml++/toml.hpp>
namespace Cubed {
class App;
class Player;
class DevPanel {
struct ConfigView {
float fov = 70.0f;
bool fullscreen = false;
bool v_sync = true;
float mouse_sensitivity = 0.15f;
int width = 800;
int height = 600;
int rendering_distance = 24;
int aniso = 1;
int max_aniso = 1;
bool is_enable_aniso = false;
bool is_support_aniso = true;
bool is_reload = true;
};
struct PlayerProfile {
int game_mode = 0;
int gait = 0;
float pos[3] = {0.0f, 0.0f, 0.0f};
};
struct TextEditing {
bool perlin_seed = false;
};
public:
DevPanel(App& app);
void init();
void render();
private:
App& m_app;
ConfigView m_config;
Player* m_player;
PlayerProfile m_player_profile;
TextEditing m_text_editing;
bool m_need_save_config = false;
bool m_gen_thread_running = true;
int m_theme = 0;
void show_about_table_bar();
void show_biome_table_bar();
void show_cave_table_bar();
void show_river_table_bar();
void show_settings_tab_item();
void show_world_tab_item();
void show_player_tab_item();
void show_items_tab_item();
void update_config_view();
void update_player_profile();
};
} // namespace Cubed

View File

@@ -0,0 +1,80 @@
#pragma once
#include <array>
#include <string>
#include <vector>
namespace Cubed {
constexpr float BIOME_NOISE_FREQUENCY = 0.06f;
constexpr float HEIGHTMAP_NOISE_FREQUENCY = 0.001f;
constexpr float MOUNTAINOUS_NOISE_FREQUENCY = 0.003f;
enum class BiomeType {
PLAIN = 0,
FOREST,
DESERT,
MOUNTAIN,
RIVER,
SNOWY_PLAIN,
OCEAN,
NONE
};
struct BiomeConditions {
float temp = 0.0f;
float humid = 0.0f;
float mountainous = 0.0f;
};
struct BiomeHeightRange {
int base_y;
int amplitude;
};
struct BiomeNonAdjacent {
BiomeType first;
std::vector<BiomeType> second;
BiomeType replace;
};
static inline const std::vector<BiomeNonAdjacent> NON_ADJACENT{
{{BiomeType::PLAIN, {BiomeType::DESERT}, BiomeType::RIVER},
{BiomeType::FOREST, {BiomeType::DESERT}, BiomeType::RIVER},
{BiomeType::DESERT, {BiomeType::FOREST}, BiomeType::RIVER},
{BiomeType::MOUNTAIN, {BiomeType::NONE}, BiomeType::RIVER}}};
struct BaseBiomeParams {
BiomeType biome;
std::pair<float, float> temp;
std::pair<float, float> humid;
std::array<float, 3> frequencies;
BiomeHeightRange height_range;
};
struct PlainParams : public BaseBiomeParams {};
struct ForestParams : public BaseBiomeParams {
float tree_frequency;
};
struct DesertParams : public BaseBiomeParams {};
struct MountainParams : public BaseBiomeParams {};
struct RiverParams : public BaseBiomeParams {};
std::string get_biome_str(BiomeType biome);
// std::array<float, 3> get_noise_frequencies_for_biome(BiomeType biome);
// BiomeHeightRange get_biome_height_range(BiomeType biome);
BiomeType safe_int_to_biome(int x);
int get_interpolated_height(float world_x, float world_z, float temp,
float humid);
BiomeType determine_biome(const BiomeConditions& conditions);
PlainParams& plain_params();
ForestParams& forest_params();
DesertParams& desert_params();
MountainParams& mountain_params();
RiverParams& river_params();
} // namespace Cubed

View File

@@ -1,10 +1,13 @@
#pragma once #pragma once
#include <glad/glad.h> #include <glad/glad.h>
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <string> #include <string>
#include <vector> #include <vector>
namespace Cubed {
using BlockType = uint8_t;
struct BlockTexture { struct BlockTexture {
std::string name; std::string name;
@@ -12,9 +15,7 @@ struct BlockTexture {
std::vector<GLuint> texture; std::vector<GLuint> texture;
}; };
struct Block : public BlockTexture{ struct Block : public BlockTexture {};
};
struct BlockRenderData { struct BlockRenderData {
std::vector<bool> draw_face; std::vector<bool> draw_face;
@@ -22,12 +23,8 @@ struct BlockRenderData {
BlockRenderData() = default; BlockRenderData() = default;
BlockRenderData(const BlockRenderData&) = default; BlockRenderData(const BlockRenderData&) = default;
BlockRenderData& operator=(const BlockRenderData&) = default; BlockRenderData& operator=(const BlockRenderData&) = default;
BlockRenderData(BlockRenderData&& data) : BlockRenderData(BlockRenderData&& data)
draw_face(std::move(data.draw_face)), : draw_face(std::move(data.draw_face)), block_id(data.block_id) {}
block_id(data.block_id)
{
}
BlockRenderData& operator=(BlockRenderData&& data) { BlockRenderData& operator=(BlockRenderData&& data) {
draw_face = std::move(data.draw_face); draw_face = std::move(data.draw_face);
block_id = data.block_id; block_id = data.block_id;
@@ -39,3 +36,56 @@ struct LookBlock {
glm::ivec3 pos; glm::ivec3 pos;
glm::ivec3 normal; glm::ivec3 normal;
}; };
struct BlockData {
std::string name;
BlockType id = 0;
bool is_liquid = false;
bool is_gas = false;
bool is_passable = false;
bool is_cross_plane = false;
bool is_transparent = false;
bool is_discard = false;
bool is_blend = false;
bool is_transitional = false;
BlockData(BlockType b_id, std::string_view b_name, bool liquid,
bool passable, bool cross_plane, bool transparent, bool gas,
bool discard, bool blend, bool transitional)
: name(b_name), id(b_id), is_liquid(liquid), is_gas(gas),
is_passable(passable), is_cross_plane(cross_plane),
is_transparent(transparent), is_discard(discard), is_blend(blend),
is_transitional(transitional) {}
};
class BlockManager {
public:
static const std::vector<BlockData>& datas();
static void init();
static unsigned sums();
static unsigned cross_plane_sum();
static const std::string& name_form_id(BlockType id);
static bool is_gas(BlockType id);
static bool is_liquid(BlockType id);
static bool is_cross_plane(BlockType id);
static bool is_transparent(BlockType id);
static bool is_passable(BlockType id);
static bool is_discard(BlockType id);
static bool is_blend(BlockType id);
static bool is_transitional(BlockType id);
static BlockType cross_plane_index(BlockType id);
private:
static void set_up_cross_plane_map();
static inline std::vector<BlockData> m_datas;
static inline bool is_init = false;
static inline std::unordered_map<BlockType, BlockType> m_cross_plane_map;
};
} // namespace Cubed

View File

@@ -0,0 +1,18 @@
#pragma once
namespace Cubed {
class ChunkGenerator;
class BiomeBuilder {
public:
BiomeBuilder() = default;
virtual ~BiomeBuilder() = default;
virtual ChunkGenerator& get_chunk_generator() = 0;
virtual void build_biome() = 0;
virtual void build_vegetation() = 0;
void ocean_water_build();
protected:
void build_bottom();
void place_grass();
};
} // namespace Cubed

View File

@@ -0,0 +1,21 @@
#pragma once
#include "Cubed/gameplay/builders/biome_builder.hpp"
namespace Cubed {
class ChunkGenerator;
class DesertBuilder : public BiomeBuilder {
public:
DesertBuilder(ChunkGenerator& chunk_generator);
void build_biome() override;
ChunkGenerator& get_chunk_generator() override;
void build_vegetation() override;
private:
ChunkGenerator& m_chunk_generator;
void build_blocks();
};
} // namespace Cubed

View File

@@ -0,0 +1,21 @@
#pragma once
#include "Cubed/gameplay/builders/biome_builder.hpp"
namespace Cubed {
class ChunkGenerator;
class ForestBuilder : public BiomeBuilder {
public:
ForestBuilder(ChunkGenerator& chunk_generator);
void build_biome() override;
ChunkGenerator& get_chunk_generator() override;
void build_vegetation() override;
private:
ChunkGenerator& m_chunk_generator;
void build_blocks();
};
} // namespace Cubed

View File

@@ -0,0 +1,21 @@
#pragma once
#include "Cubed/gameplay/builders/biome_builder.hpp"
namespace Cubed {
class ChunkGenerator;
class MountainBuilder : public BiomeBuilder {
public:
MountainBuilder(ChunkGenerator& chunk_generator);
void build_biome() override;
ChunkGenerator& get_chunk_generator() override;
void build_vegetation() override;
private:
ChunkGenerator& m_chunk_generator;
void build_blocks();
};
} // namespace Cubed

View File

@@ -0,0 +1,23 @@
#pragma once
#pragma once
#include "Cubed/gameplay/builders/biome_builder.hpp"
namespace Cubed {
class ChunkGenerator;
class OceanBuilder : public BiomeBuilder {
public:
OceanBuilder(ChunkGenerator& chunk_generator);
void build_biome() override;
ChunkGenerator& get_chunk_generator() override;
void build_vegetation() override;
private:
ChunkGenerator& m_chunk_generator;
void build_blocks();
};
} // namespace Cubed

View File

@@ -0,0 +1,21 @@
#pragma once
#include "Cubed/gameplay/builders/biome_builder.hpp"
namespace Cubed {
class ChunkGenerator;
class PlainBuilder : public BiomeBuilder {
public:
PlainBuilder(ChunkGenerator& chunk_generator);
void build_biome() override;
ChunkGenerator& get_chunk_generator() override;
void build_vegetation() override;
private:
ChunkGenerator& m_chunk_generator;
void build_blocks();
};
} // namespace Cubed

View File

@@ -0,0 +1,21 @@
#pragma once
#include "Cubed/gameplay/builders/biome_builder.hpp"
namespace Cubed {
class ChunkGenerator;
class RiverBuilder : public BiomeBuilder {
public:
RiverBuilder(ChunkGenerator& chunk_generator);
void build_biome() override;
ChunkGenerator& get_chunk_generator() override;
void build_vegetation() override;
private:
ChunkGenerator& m_chunk_generator;
void build_blocks();
};
} // namespace Cubed

View File

@@ -0,0 +1,21 @@
#pragma once
#include "Cubed/gameplay/builders/biome_builder.hpp"
namespace Cubed {
class ChunkGenerator;
class SnowyPlainBuilder : public BiomeBuilder {
public:
SnowyPlainBuilder(ChunkGenerator& chunk_generator);
void build_biome() override;
ChunkGenerator& get_chunk_generator() override;
void build_vegetation() override;
private:
ChunkGenerator& m_chunk_generator;
void build_blocks();
};
} // namespace Cubed

View File

@@ -0,0 +1,27 @@
#pragma once
#include "Cubed/gameplay/cave_path.hpp"
#include <tbb/concurrent_hash_map.h>
namespace Cubed {
class CaveCarver {
using CaveHashMap = tbb::concurrent_hash_map<unsigned, CavePath>;
public:
CaveCarver();
CaveHashMap& paths();
void init(unsigned world_seed);
void reload(unsigned world_seed);
void add_path(const glm::vec3& pos, unsigned chunk_seed);
void try_to_add_path(const ChunkPos& pos, unsigned chunk_seed);
void cleanup_finished_caves();
int cave_sum() const;
float& cave_probability();
private:
CaveHashMap m_paths;
unsigned m_seed = 0;
Random m_random;
float m_cave_probability = 0.035f;
};
} // namespace Cubed

View File

@@ -0,0 +1,54 @@
#pragma once
#include "Cubed/gameplay/chunk_pos.hpp"
#include "Cubed/gameplay/path_point.hpp"
#include "Cubed/tools/cubed_random.hpp"
#include <glm/glm.hpp>
#include <tbb/concurrent_hash_map.h>
namespace Cubed {
class CavePath {
using ChunkPosSet =
tbb::concurrent_hash_map<ChunkPos, bool, ChunkPos::TBBHash>;
public:
CavePath(unsigned int chunk_seed, unsigned world_seed,
const glm::vec3& start_pos);
const std::vector<PathPoint>& points() const;
void clear_chunk(const ChunkPos& pos);
bool is_finished() const;
static float& radius_xz_min();
static float& radius_xz_max();
static float& radius_y_min();
static float& radius_y_max();
static float& delta_angle_min();
static float& delta_angle_max();
static int& step_min();
static int& step_max();
private:
static inline float m_radius_xz_min = 5.0f;
static inline float m_radius_xz_max = 15.0f;
static inline float m_radius_y_min = 4.0f;
static inline float m_radius_y_max = 10.0f;
static inline float m_delta_angle_min = -5.0f;
static inline float m_delta_angle_max = 5.0f;
static inline int m_step_min = 10;
static inline int m_step_max = 400;
unsigned int m_seed = 0;
float m_yaw = 0.0f;
float m_pitch = 0.0f;
int m_step = 0;
float m_step_len = 1.0f;
PathPoint m_start_path_point{{0.0f, 0.0f, 0.0f}, 0.0f, 0.0f};
Random m_random;
std::vector<PathPoint> m_points;
ChunkPosSet m_pending_chunks;
void collect_path_points();
void precompute_chunk_coverage();
};
} // namespace Cubed

View File

@@ -1,59 +1,134 @@
#pragma once #pragma once
#include <atomic> #include "Cubed/gameplay/biome.hpp"
#include <cstdint> #include "Cubed/gameplay/block.hpp"
#include "Cubed/gameplay/chunk_generator.hpp"
#include "Cubed/gameplay/chunk_pos.hpp"
#include "Cubed/gameplay/vertex_data.hpp"
#include <Cubed/config.hpp> #include <atomic>
#include <Cubed/gameplay/chunk_status.hpp> #include <mutex>
#include <Cubed/gameplay/block.hpp> namespace Cubed {
class World; class World;
// if want to use, do init_chunk(), gen_vertex_data() and // if want to use, do init_chunk(), gen_vertex_data() and
class Chunk { class Chunk {
private: private:
std::atomic<bool> m_dirty {false}; using OptionalBlockVectorArray =
std::array<std::optional<std::vector<BlockType>>, 4>;
static constexpr int SIZE_X = CHUCK_SIZE; static constexpr int SIZE_X = CHUNK_SIZE;
static constexpr int SIZE_Y = WORLD_SIZE_Y; static constexpr int SIZE_Y = WORLD_SIZE_Y;
static constexpr int SIZE_Z = CHUCK_SIZE; static constexpr int SIZE_Z = CHUNK_SIZE;
static constexpr int VERTEX_DATA_SUM = 4;
std::atomic<bool> m_dirty{false};
std::atomic<bool> m_need_upload{true};
std::atomic<bool> m_is_on_gen_vertex_data{false};
std::atomic<BiomeType> m_biome = BiomeType::PLAIN;
std::mutex m_vertexs_data_mutex;
std::unique_ptr<ChunkGenerator> m_generator;
ChunkPos m_chunk_pos; ChunkPos m_chunk_pos;
World& m_world; World& m_world;
HeightMapArray m_heightmap;
// the index is a array of block id // the index is a array of block id
std::vector<uint8_t> m_blocks; std::vector<BlockType> m_blocks;
GLuint m_vbo = 0;
std::vector<Vertex> m_vertexs_data;
/*
0 - normal
1 - cross_plane
2 - normal_discard
3 - transparent and blend
*/
std::vector<VertexData> m_vertex_data;
float frequency = 0.01f; float frequency = 0.01f;
float height = 80; float height = 80;
unsigned m_seed = 0;
BiomeConditions m_conditions;
void clear_dirty(); void clear_dirty();
void gen_vertices(const OptionalBlockVectorArray& neighbor_block);
void gen_cross_plane_vertices(int world_x, int world_y, int world_z,
BlockType id);
public: public:
Chunk(World& world, ChunkPos chunk_pos); Chunk(World& world, ChunkPos chunk_pos);
~Chunk(); ~Chunk();
Chunk(const Chunk&) = delete; Chunk(const Chunk&) = delete;
Chunk& operator=(const Chunk&) = delete; Chunk& operator=(const Chunk&) = delete;
Chunk(Chunk&&); Chunk(Chunk&&) noexcept;
Chunk& operator=(Chunk&&); Chunk& operator=(Chunk&&) noexcept;
const std::vector<uint8_t>& get_chunk_blocks() const;
static int get_index(int x, int y, int z); static std::tuple<int, int, int> world_to_block(int world_x, int world_y,
int world_z, int chunk_x,
void init_chunk(); int chunk_z);
void gen_vertex_data(); static std::tuple<int, int, int> world_to_block(const glm::ivec3& block_pos,
ChunkPos chunk_pos);
static std::tuple<int, int, int> block_to_world(int x, int y, int z,
int chunk_x, int chunk_z);
static std::tuple<int, int, int> block_to_world(const glm::ivec3& block_pos,
ChunkPos chunk_pos);
BiomeType get_biome() const;
ChunkPos get_chunk_pos() const;
const std::vector<BlockType>& get_chunk_blocks() const;
HeightMapArray get_heightmap() const;
static int index(int x, int y, int z);
static int index(const glm::vec3& pos);
// Init Chunk
// Determine biome from temperature and humidity noise
void gen_phase_one();
// Resolve biome adjacency conflicts with neighbor chunks
void gen_phase_two(const std::array<const Chunk*, 8>& adj_chunks);
// Generate heightmap using biome-specific noise
void gen_phase_three();
// Blend heightmap with neighbors for smooth transitions
void gen_phase_four(
const std::array<std::optional<HeightMapArray>, 8>& neighbor_heightmap,
const std::array<BiomeType, 8>& neighbor_biome);
// Generate terrain blocks from heightmap and biome
void gen_phase_five();
// Blend surface blocks at chunk borders with neighbors
void gen_phase_six(const std::array<std::optional<std::vector<BlockType>>,
4>& neighbor_block);
// Generate biome-specific vegetation/structures
void gen_phase_seven();
// void gen_vertex_data();
// 0 : (1, 0) // 0 : (1, 0)
// 1 : (-1, 0) // 1 : (-1, 0)
// 2 : (0, 1) // 2 : (0, 1)
// 3 : (0, -1) // 3 : (0, -1)
void gen_vertex_data(const std::vector<const std::vector<uint8_t>*>& neighbor_block); void gen_vertex_data(const OptionalBlockVectorArray& neighbor_block);
void upload_to_gpu(); void upload_to_gpu();
GLuint get_vbo() const; GLuint get_normal_vao() const;
const std::vector<Vertex>& get_vertex_data() const; size_t get_normal_vertices_sum() const;
GLuint get_cross_vao() const;
size_t get_cross_vertices_sum() const;
GLuint get_normal_discard_vao() const;
size_t get_normal_discard_vertices_sum() const;
GLuint get_normal_blend_vao() const;
size_t get_normal_blend_vertices_sum() const;
bool is_dirty() const; bool is_dirty() const;
void mark_dirty(); void mark_dirty();
bool is_need_upload() const;
void need_upload();
void set_chunk_block(int index, unsigned id); void set_chunk_block(int index, unsigned id);
ChunkPos chunk_pos() const;
BiomeType biome() const;
void biome(BiomeType b);
HeightMapArray& heightmap();
std::vector<BlockType>& blocks();
World& world();
unsigned seed() const;
BiomeConditions& conditions();
}; };
} // namespace Cubed

View File

@@ -0,0 +1,70 @@
#pragma once
#include "Cubed/constants.hpp"
#include "Cubed/gameplay/biome.hpp"
#include "Cubed/gameplay/block.hpp"
#include "Cubed/gameplay/builders/biome_builder.hpp"
#include "Cubed/gameplay/path_point.hpp"
#include "Cubed/tools/cubed_random.hpp"
#include <atomic>
#include <memory>
#include <optional>
namespace Cubed {
class Chunk;
class ChunkGenerator {
public:
ChunkGenerator(Chunk& chunk);
static void init();
static void reload();
static const unsigned& seed();
static void seed(unsigned s);
unsigned chunk_seed() const;
// Generate Biome
void assign_chunk_biome();
// Adjust Biome
void resolve_biome_adjacency_conflict(
const std::array<const Chunk*, 8>& adj_chunks);
// Generate Heightmap
void generate_heightmap();
// Adjust Height
void blend_heightmap_boundaries(
const std::array<std::optional<HeightMapArray>, 8>& neighbor_heightmap,
const std::array<BiomeType, 8>& neighbor_biome);
// Generate Block
void generate_terrain_blocks();
// Adjust Block;
void blend_surface_blocks_borders(
const std::array<std::optional<std::vector<BlockType>>, 4>&
neighbor_block);
// Generate Structure
void generate_vegetation();
BiomeType get_biome_at(float world_x, float world_z);
Chunk& chunk();
Random& random();
const std::array<BiomeType, 8>& neighbor_biome() const;
void ocean_build();
void generate_cave();
void generate_river();
private:
static inline std::atomic<bool> is_init{false};
static inline unsigned m_generator_seed{0};
static inline std::atomic<bool> is_seed_change{false};
Chunk& m_chunk;
Random m_random;
std::unique_ptr<BiomeBuilder> m_biome_builder{nullptr};
bool is_cur_chunk_ins = false;
std::array<BiomeType, 8> m_neighbor_biome;
unsigned m_chunk_seed = 0;
void make_biome_builder();
void
carve_worm(const std::vector<PathPoint>& points, const ChunkPos& chunk_pos,
std::function<void(int /*x*/, int /*y*/, int /*z*/)> on_hit);
};
} // namespace Cubed

Some files were not shown because too many files have changed in this diff Show More