Compare commits

42 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
162 changed files with 68174 additions and 2511 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/

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

@@ -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,8 +105,11 @@ 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/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/tree.cpp
src/gameplay/world.cpp src/gameplay/world.cpp
@@ -99,20 +125,34 @@ add_executable(${PROJECT_NAME}
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 #-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 #-fsanitize=thread
) )
@@ -136,10 +176,13 @@ 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") if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
target_link_libraries(${PROJECT_NAME} PRIVATE tbb) # target_link_libraries(${PROJECT_NAME} PRIVATE tbb)
endif() endif()
if (UNIX AND NOT APPLE) if (UNIX AND NOT APPLE)
@@ -159,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

@@ -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,7 +8,7 @@ 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.5) { if (color.a < 0.8) {
discard; 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: 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.

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

@@ -3,17 +3,12 @@
namespace Cubed { 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) &&
@@ -22,4 +17,4 @@ struct AABB {
} }
}; };
} } // namespace Cubed

View File

@@ -1,33 +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 { 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,
static void mouse_scroll_callback(GLFWwindow* window, double xoffset, double yoffset); 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};
@@ -49,4 +65,4 @@ private:
void update(); void update();
}; };
} } // namespace Cubed

View File

@@ -1,39 +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 { 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,156 +1,107 @@
#pragma once #pragma once
#include <array> #include "Cubed/tools/cubed_assert.hpp"
#include <toml++/toml.hpp>
namespace Cubed { namespace Cubed {
constexpr int WORLD_SIZE_Y = 256; template <typename T>
constexpr int MAX_BLOCK_NUM = 7; concept TomlValueType =
constexpr int MAX_UI_NUM = 1; std::same_as<T, int> || std::same_as<T, bool> || std::same_as<T, double> ||
std::same_as<T, const char*> || std::same_as<T, toml::date> ||
std::same_as<T, toml::time> || std::same_as<T, toml::date_time> ||
std::same_as<T, std::string>;
constexpr int CHUCK_SIZE = 16; class Config {
constexpr int DISTANCE = 24; public:
constexpr int MAX_BLOCK_STATUS = 1; Config();
constexpr int MAX_CHARACTER = 128; ~Config();
constexpr float NORMAL_FOV = 70.0f;
constexpr int MAX_BIOME_SUM = 4; static Config& get();
using HeightMapArray = std::array<std::array<float, CHUCK_SIZE>, CHUCK_SIZE>;
constexpr float VERTICES_POS[6][6][3] = {
// ===== front (z = +1) =====
0.0f, 0.0f, 1.0f, // bottom left
0.0f, 1.0f, 1.0f, // top left
1.0f, 1.0f, 1.0f, // top right
1.0f, 1.0f, 1.0f, // top right
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] = { toml::table& table();
// ===== front (z = +1) =====
0.0f, 1.0f, // bottom left
0.0f, 0.0f, // top left
1.0f, 0.0f, // top right
1.0f, 0.0f, // top right
1.0f, 1.0f, // bottom right
0.0f, 1.0f, // bottom left
// ===== right (x = +1) =====
0.0f, 1.0f, // bottom front
1.0f, 1.0f, // bottom back
1.0f, 0.0f, // top back
1.0f, 0.0f, // top back
0.0f, 0.0f, // top front
0.0f, 1.0f, // bottom front
// ===== back (z = -1) =====
1.0f, 1.0f, // bottom left
0.0f, 1.0f, // bottom right
0.0f, 0.0f, // top right
0.0f, 0.0f, // top right
1.0f, 0.0f, // top left
1.0f, 1.0f, // bottom left
// ===== left (x = -1) =====
1.0f, 1.0f, // bottom back
0.0f, 1.0f, // bottom front
0.0f, 0.0f, // top front
0.0f, 0.0f, // top front
1.0f, 0.0f, // top back
1.0f, 1.0f, // bottom back
// ===== top (y = +1) =====
0.0f, 0.0f, // back left
1.0f, 0.0f, // back right
1.0f, 1.0f, // front right
1.0f, 1.0f, // front right
0.0f, 1.0f, // front left
0.0f, 0.0f, // back left
// ===== bottom (y = -1) =====
0.0f, 0.0f, // front left
1.0f, 0.0f, // front right
1.0f, 1.0f, // back right
1.0f, 1.0f, // back right
0.0f, 1.0f, // back left
0.0f, 0.0f, // front left
};
constexpr float CUBE_VER[24] = { void load_or_create_config();
0.0, 0.0, 0.0, void save_to_file();
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;
};
template <TomlValueType T> T get(std::string_view key) const {
size_t cur = 0;
auto pos = key.find('.');
const 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 {
Logger::error("Can't find table {}", s);
ASSERT(false);
std::abort();
}
}
std::string_view n_key = key.substr(cur);
if (n_key.empty()) {
Logger::error("Trailing dot in path '{}'", key);
ASSERT(false);
std::abort();
}
auto opt = (*table)[n_key].value<T>();
if (opt) {
return *opt;
} 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();
};
} // namespace Cubed

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,12 +1,11 @@
#pragma once #pragma once
#include <Cubed/ui/text.hpp> #include "Cubed/ui/text.hpp"
#include <unordered_map> #include <unordered_map>
namespace Cubed { namespace Cubed {
class DebugCollector { class DebugCollector {
public: public:
static DebugCollector& get(); static DebugCollector& get();
@@ -22,4 +21,4 @@ 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

@@ -5,36 +5,76 @@
namespace Cubed { namespace Cubed {
constexpr float BIOME_NOISE_FREQUENCY = 0.003f; constexpr float BIOME_NOISE_FREQUENCY = 0.06f;
constexpr float HEIGHTMAP_NOISE_FREQUENCY = 0.001f;
constexpr float PLAIN_FREQ = 0.4f; constexpr float MOUNTAINOUS_NOISE_FREQUENCY = 0.003f;
constexpr float FOREST_FREQ = 1.2f; enum class BiomeType {
constexpr float DESERT_FREQ = 1.2f;
constexpr float MOUNTAIN_FREQ = 2.0f;
enum class Biome {
PLAIN = 0, PLAIN = 0,
FOREST, FOREST,
DESERT, DESERT,
MOUNTAIN, MOUNTAIN,
RIVER,
SNOWY_PLAIN,
OCEAN,
NONE NONE
}; };
struct BiomeConditions {
float temp = 0.0f;
float humid = 0.0f;
float mountainous = 0.0f;
};
struct BiomeHeightRange { struct BiomeHeightRange {
int base_y; int base_y;
int amplitude; int amplitude;
}; };
struct BiomeNonAdjacent { struct BiomeNonAdjacent {
Biome first; BiomeType first;
std::vector<Biome> second; std::vector<BiomeType> second;
Biome replace; BiomeType replace;
}; };
std::string get_biome_str(Biome biome); static inline const std::vector<BiomeNonAdjacent> NON_ADJACENT{
Biome get_biome_from_noise(float temp, float humid); {{BiomeType::PLAIN, {BiomeType::DESERT}, BiomeType::RIVER},
std::array<float, 3> get_noise_frequencies_for_biome(Biome biome); {BiomeType::FOREST, {BiomeType::DESERT}, BiomeType::RIVER},
BiomeHeightRange get_biome_height_range(Biome biome); {BiomeType::DESERT, {BiomeType::FOREST}, BiomeType::RIVER},
Biome safe_int_to_biome(int x); {BiomeType::MOUNTAIN, {BiomeType::NONE}, BiomeType::RIVER}}};
int get_interpolated_height(float world_x, float world_z, float temp, float humid);
} 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,15 +1,13 @@
#pragma once #pragma once
#include <glad/glad.h> #include <glad/glad.h>
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <array>
#include <string> #include <string>
#include <vector> #include <vector>
#include <Cubed/config.hpp>
#include <Cubed/tools/cubed_assert.hpp>
namespace Cubed { namespace Cubed {
using BlockType = uint8_t;
struct BlockTexture { struct BlockTexture {
std::string name; std::string name;
@@ -17,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;
@@ -27,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;
@@ -45,30 +37,55 @@ struct LookBlock {
glm::ivec3 normal; glm::ivec3 normal;
}; };
constexpr std::array<std::string_view, MAX_BLOCK_NUM> BLOCK_REISTER{ struct BlockData {
"air", std::string name;
"grass_block", BlockType id = 0;
"dirt",
"stone", bool is_liquid = false;
"sand", bool is_gas = false;
"log",
"leaf" 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) {}
}; };
const std::array<bool, MAX_BLOCK_NUM> TRANSPARENT_MAP { class BlockManager {
true,
false, public:
false, static const std::vector<BlockData>& datas();
false, static void init();
false, static unsigned sums();
false, static unsigned cross_plane_sum();
true 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;
}; };
inline bool is_in_transparent_map(unsigned id) { } // namespace Cubed
ASSERT_MSG(id < MAX_BLOCK_NUM, "ID is invaild");
return TRANSPARENT_MAP[id];
};
}

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,54 +1,56 @@
#pragma once #pragma once
#include "Cubed/gameplay/biome.hpp"
#include "Cubed/gameplay/block.hpp"
#include "Cubed/gameplay/chunk_generator.hpp"
#include "Cubed/gameplay/chunk_pos.hpp"
#include "Cubed/gameplay/vertex_data.hpp"
#include <atomic> #include <atomic>
#include <cstdint> #include <mutex>
#include <Cubed/config.hpp>
#include <Cubed/gameplay/biome.hpp>
#include <Cubed/gameplay/chunk_pos.hpp>
#include <Cubed/gameplay/block.hpp>
namespace Cubed { 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:
static constexpr int SIZE_X = CHUCK_SIZE; using OptionalBlockVectorArray =
std::array<std::optional<std::vector<BlockType>>, 4>;
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;
static inline const std::vector<BiomeNonAdjacent> NON_ADJACENT {{
{Biome::PLAIN, {Biome::NONE}, Biome::PLAIN},
{Biome::FOREST, {Biome::DESERT}, Biome::PLAIN},
{Biome::DESERT, {Biome::MOUNTAIN, Biome::FOREST}, Biome::PLAIN},
{Biome::MOUNTAIN, {Biome::DESERT}, Biome::PLAIN}
}
};
using HeightMapArray = std::array<std::array<float, SIZE_Z>, SIZE_X>;
std::atomic<bool> m_dirty{false}; std::atomic<bool> m_dirty{false};
std::atomic<bool> m_need_upload{true}; std::atomic<bool> m_need_upload{true};
std::atomic<bool> m_is_on_gen_vertex_data{false}; std::atomic<bool> m_is_on_gen_vertex_data{false};
std::atomic<size_t> m_vertex_sum = 0; std::atomic<BiomeType> m_biome = BiomeType::PLAIN;
std::mutex m_vertexs_data_mutex; std::mutex m_vertexs_data_mutex;
std::atomic<Biome> m_biome = Biome::PLAIN; std::unique_ptr<ChunkGenerator> m_generator;
ChunkPos m_chunk_pos; ChunkPos m_chunk_pos;
World& m_world; World& m_world;
HeightMapArray m_heightmap; 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 resolve_biome(); void gen_cross_plane_vertices(int world_x, int world_y, int world_z,
void resolve_blocks(); BlockType id);
public: public:
Chunk(World& world, ChunkPos chunk_pos); Chunk(World& world, ChunkPos chunk_pos);
@@ -58,35 +60,58 @@ public:
Chunk(Chunk&&) noexcept; Chunk(Chunk&&) noexcept;
Chunk& operator=(Chunk&&) noexcept; Chunk& operator=(Chunk&&) noexcept;
Biome get_biome() const; static std::tuple<int, int, int> world_to_block(int world_x, int world_y,
int world_z, int chunk_x,
const std::vector<uint8_t>& get_chunk_blocks() const; int chunk_z);
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; HeightMapArray get_heightmap() const;
static int get_index(int x, int y, int z); static int index(int x, int y, int z);
static int get_index(const glm::vec3& pos); static int index(const glm::vec3& pos);
void init_chunk(); // Init Chunk
// Generate Biome // Determine biome from temperature and humidity noise
void gen_phase_one(); void gen_phase_one();
// Adjust Biome // Resolve biome adjacency conflicts with neighbor chunks
void gen_phase_two(const std::array<const Chunk*, 4>& adj_chunks); void gen_phase_two(const std::array<const Chunk*, 8>& adj_chunks);
// Generate Heightmap // Generate heightmap using biome-specific noise
void gen_phase_three(); void gen_phase_three();
// Adjust Height // Blend heightmap with neighbors for smooth transitions
void gen_phase_four(const std::array<std::optional<HeightMapArray>, 4>& neighbor_heightmap); void gen_phase_four(
// Generate Block 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(); void gen_phase_five();
// Generate Structure // Blend surface blocks at chunk borders with neighbors
void gen_phase_six(); 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(); // 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::array<const std::vector<uint8_t>*, 4>& 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;
size_t get_vertex_sum() 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();
@@ -96,7 +121,14 @@ public:
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

View File

@@ -1,13 +1,9 @@
#pragma once #pragma once
#include <functional> #include <functional>
#include <Cubed/tools/log.hpp>
#include <Cubed/tools/cubed_assert.hpp>
namespace Cubed { namespace Cubed {
struct ChunkPos { struct ChunkPos {
int x; int x;
int z; int z;
@@ -20,7 +16,14 @@ struct ChunkPos {
return h1 ^ (h2 + 0x9e3779b9 + (h1 << 6) + (h1 >> 2)); return h1 ^ (h2 + 0x9e3779b9 + (h1 << 6) + (h1 >> 2));
} }
}; };
struct TBBHash {
std::size_t hash(const ChunkPos& p) const {
return ChunkPos::Hash{}(p);
}
bool equal(const ChunkPos& a, const ChunkPos& b) const {
return a == b;
}
};
ChunkPos operator+(const ChunkPos& pos) const { ChunkPos operator+(const ChunkPos& pos) const {
return ChunkPos{x + pos.x, z + pos.z}; return ChunkPos{x + pos.x, z + pos.z};
} }
@@ -32,5 +35,4 @@ struct ChunkPos {
}; };
}; };
} // namespace Cubed
}

View File

@@ -5,11 +5,7 @@
namespace Cubed { namespace Cubed {
enum class GameMode { CREATIVE = 0, SPECTATOR };
enum class GameMode {
CREATIVE,
SPECTATOR
};
inline std::string to_str(GameMode mode) { inline std::string to_str(GameMode mode) {
using enum GameMode; using enum GameMode;
@@ -22,5 +18,4 @@ inline std::string to_str(GameMode mode) {
throw std::invalid_argument{"GameMode is invaild"}; throw std::invalid_argument{"GameMode is invaild"};
} }
} // namespace Cubed
}

View File

@@ -0,0 +1,36 @@
#pragma once
#include <glm/glm.hpp>
struct PathPoint {
glm::vec3 pos;
glm::vec3 tangent{0.0f, 0.0f, 1.0f};
float rad_xz;
float rad_y;
PathPoint(const glm::vec3& p, float rx, float ry)
: pos(p), rad_xz(rx), rad_y(ry) {}
bool contains(const glm::vec3& other_pos) const {
glm::vec3 to_point = other_pos - pos;
glm::vec3 world_up(0.0f, 1.0f, 0.0f);
glm::vec3 right = glm::normalize(glm::cross(tangent, world_up));
if (glm::length(right) < 0.001f) {
glm::vec3 alt_up(1.0f, 0.0f, 0.0f);
right = glm::normalize(glm::cross(tangent, alt_up));
}
glm::vec3 up = glm::normalize(glm::cross(right, tangent));
float horizontal_dist = glm::dot(to_point, right);
float vertical_dist = glm::dot(to_point, up);
float a = rad_xz;
float b = rad_y;
if (a <= 0.0f || b <= 0.0f)
return false;
float check = (horizontal_dist * horizontal_dist) / (a * a) +
(vertical_dist * vertical_dist) / (b * b);
return check <= 1.0f;
}
};

View File

@@ -1,55 +1,54 @@
#pragma once #pragma once
#include "Cubed/AABB.hpp"
#include "Cubed/constants.hpp"
#include "Cubed/gameplay/block.hpp"
#include "Cubed/gameplay/chunk_pos.hpp"
#include "Cubed/gameplay/game_mode.hpp"
#include "Cubed/input.hpp"
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <Cubed/AABB.hpp>
#include <Cubed/config.hpp>
#include <Cubed/gameplay/block.hpp>
#include <Cubed/gameplay/chunk_pos.hpp>
#include <Cubed/gameplay/game_mode.hpp>
#include <Cubed/input.hpp>
#include <optional> #include <optional>
#include <string> #include <string>
namespace Cubed { namespace Cubed {
enum class Gait{ enum class Gait { WALK = 0, RUN };
WALK,
RUN
};
class World; class World;
class Player { class Player {
private: private:
using enum GameMode; using enum GameMode;
constexpr static float WALK_SPEED = 4.5f; float m_max_walk_speed = DEFAULT_MAX_WALK_SPEED;
constexpr static float RUN_SPEED = 7.0f; float m_max_run_speed = DEFAULT_MAX_RUN_SPEED;
constexpr static float ACCELERATION = 10.0f; float m_acceleration = DEFAULT_ACCELERATION;
constexpr static float DECELERATION = 15.0f; float m_deceleration = DEFAULT_DECELERATION;
constexpr static float G = 22.5f; float m_g = DEFAULT_G;
constexpr static float MAX_SPACE_ON_TIME = 0.3f; constexpr static float MAX_SPACE_ON_TIME = 0.3f;
float m_yaw = 0.0f; float m_yaw = 0.0f;
float m_pitch = 0.0f; float m_pitch = 0.0f;
float m_sensitivity = 0.15f; float m_sensitivity = 0.15f;
float max_speed = WALK_SPEED; float m_max_speed = m_max_walk_speed;
float y_speed = 0.0f; float m_y_speed = 0.0f;
bool can_up = true; bool can_up = true;
float space_on_time = 0.0f; float space_on_time = 0.0f;
bool space_on = false; bool space_on = false;
bool is_fly = false; bool is_fly = false;
float speed = 0; float m_xz_speed = 0.0f;
unsigned m_place_block = 1;
glm::vec3 direction = glm::vec3(0.0f, 0.0f, 0.0f); glm::vec3 direction = glm::vec3(0.0f, 0.0f, 0.0f);
glm::vec3 move_distance{0.0f, 0.0f, 0.0f}; glm::vec3 move_distance{0.0f, 0.0f, 0.0f};
// player is tow block tall, the pos is the lower pos // player is tow block tall, the pos is the lower pos
glm::vec3 m_player_pos {0.0f, 120.0f, 0.0f}; glm::vec3 m_player_pos{0.0f, 255.0f, 0.0f};
ChunkPos m_player_chunk_pos{0, 0}; ChunkPos m_player_chunk_pos{0, 0};
glm::vec3 m_front{0, 0, -1}; glm::vec3 m_front{0, 0, -1};
@@ -63,7 +62,9 @@ private:
std::string m_name{}; std::string m_name{};
World& m_world; World& m_world;
bool ray_cast(const glm::vec3& start, const glm::vec3& dir, glm::ivec3& block_pos, glm::vec3& normal, float distance = 4.0f); bool ray_cast(const glm::vec3& start, const glm::vec3& dir,
glm::ivec3& block_pos, glm::vec3& normal,
float distance = 4.0f);
void check_player_chunk_transition(); void check_player_chunk_transition();
void update_direction(); void update_direction();
@@ -84,13 +85,26 @@ public:
const MoveState& get_move_state() const; const MoveState& get_move_state() const;
void change_mode(GameMode mode); void change_mode(GameMode mode);
void hot_reload();
void set_player_pos(const glm::vec3& pos); void set_player_pos(const glm::vec3& pos);
void set_place_block(unsigned id);
void update(float delta_time); void update(float delta_time);
void update_front_vec(float offset_x, float offset_y); void update_front_vec(float offset_x, float offset_y);
void update_player_move_state(int key, int action); void update_player_move_state(int key, int action);
void update_scroll(double yoffset); void update_scroll(double yoffset);
float& max_walk_speed();
float& max_run_speed();
float& max_speed();
float& acceleration();
float& deceleration();
float& g();
unsigned place_block() const;
Gait& gait();
GameMode& game_mode();
const World& get_world() const;
}; };
} // namespace Cubed
}

View File

@@ -0,0 +1,55 @@
#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 RiverPath {
using ChunkPosSet =
tbb::concurrent_hash_map<ChunkPos, bool, ChunkPos::TBBHash>;
public:
RiverPath(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 = 10.0f;
static inline float m_radius_y_min = 4.0f;
static inline float m_radius_y_max = 8.0f;
static inline float m_delta_angle_min = -3.0f;
static inline float m_delta_angle_max = 3.0f;
static inline int m_step_min = 200;
static inline int m_step_max = 400;
unsigned int m_seed = 0;
float m_yaw = 0.0f;
float m_initial_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

@@ -0,0 +1,32 @@
#pragma once
#include "Cubed/gameplay/chunk_pos.hpp"
#include "Cubed/gameplay/river.path.hpp"
#include "Cubed/tools/cubed_random.hpp"
#include <glm/glm.hpp>
#include <tbb/concurrent_hash_map.h>
namespace Cubed {
class RiverWorm {
using RiverHashMap = tbb::concurrent_hash_map<unsigned, RiverPath>;
public:
RiverWorm();
RiverHashMap& 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_rivers();
int river_sum() const;
float& river_probability();
private:
RiverHashMap m_paths;
unsigned m_seed = 0;
Random m_random;
float m_probability = 0.01f;
};
}; // namespace Cubed

View File

@@ -13,4 +13,4 @@ struct TreeStructNode {
bool build_tree(Chunk& chunk, const glm::ivec3& pos); bool build_tree(Chunk& chunk, const glm::ivec3& pos);
} } // namespace Cubed

View File

@@ -0,0 +1,25 @@
#pragma once
#include "Cubed/primitive_data.hpp"
#include <atomic>
#include <glad/glad.h>
#include <vector>
namespace Cubed {
class World;
struct VertexData {
std::vector<Vertex> m_vertices;
GLuint m_vbo = 0;
GLuint m_vao = 0;
std::atomic<std::size_t> m_sum{0};
World& m_world;
VertexData(World& world);
~VertexData();
VertexData(const VertexData&) = delete;
VertexData(VertexData&&) noexcept;
VertexData& operator=(const VertexData&) = delete;
VertexData& operator=(VertexData&&) noexcept;
void upload();
void update_sum();
};
} // namespace Cubed

View File

@@ -1,37 +1,46 @@
#pragma once #pragma once
#include "Cubed/AABB.hpp"
#include "Cubed/gameplay/cave_carver.hpp"
#include "Cubed/gameplay/chunk.hpp"
#include "Cubed/gameplay/river_worm.hpp"
#include <atomic> #include <atomic>
#include <condition_variable> #include <condition_variable>
#include <mutex> #include <mutex>
#include <thread>
#include <optional> #include <optional>
#include <thread>
#include <unordered_map> #include <unordered_map>
#include <unordered_set> #include <unordered_set>
#include <Cubed/AABB.hpp>
#include <Cubed/gameplay/chunk.hpp>
namespace Cubed { namespace Cubed {
struct ChunkRenderSnapshot { struct ChunkRenderSnapshot {
GLuint vbo; GLuint normal_vao;
size_t vertex_count; size_t normal_vertices_count;
GLuint cross_vao;
size_t cross_vertices_count;
GLuint normal_discard_vao;
size_t normal_discard_vertices_count;
GLuint normal_blend_vao;
size_t normal_blend_vertices_count;
glm::vec3 center; glm::vec3 center;
glm::vec3 half_extents; glm::vec3 half_extents;
}; };
class Player; class Player;
class TextureManager;
class World { class World {
private: private:
using OptionalBlockVectorArray =
std::array<std::optional<std::vector<BlockType>>, 4>;
using ChunkPtrUpdateList = std::vector<std::pair<ChunkPos, Chunk*>>; using ChunkPtrUpdateList = std::vector<std::pair<ChunkPos, Chunk*>>;
using ChunkUpdateList = std::vector<std::pair<ChunkPos, Chunk>>; using ChunkPairVector = std::vector<std::pair<ChunkPos, Chunk>>;
using ConstChunkMap = std::unordered_map<ChunkPos, const Chunk*, ChunkPos::Hash>; using ConstChunkMap =
std::unordered_map<ChunkPos, const Chunk*, ChunkPos::Hash>;
using ChunkPosSet = std::unordered_set<ChunkPos, ChunkPos::Hash>; using ChunkPosSet = std::unordered_set<ChunkPos, ChunkPos::Hash>;
using ChunkHashMap = std::unordered_map<ChunkPos, Chunk, ChunkPos::Hash>;
bool m_could_gen = true;
glm::vec3 m_gen_player_pos{0.0f, 0.0f, 0.0f}; glm::vec3 m_gen_player_pos{0.0f, 0.0f, 0.0f};
std::unordered_map<ChunkPos , Chunk, ChunkPos::Hash> m_chunks; ChunkHashMap m_chunks;
std::unordered_map<std::size_t, Player> m_players; std::unordered_map<std::size_t, Player> m_players;
std::vector<glm::vec4> m_planes; std::vector<glm::vec4> m_planes;
@@ -40,56 +49,82 @@ private:
std::mutex m_gen_signal_mutex; std::mutex m_gen_signal_mutex;
std::mutex m_new_chunk_queue_mutex; std::mutex m_new_chunk_queue_mutex;
std::mutex m_delete_vbo_mutex; std::mutex m_delete_vbo_mutex;
std::mutex m_delete_vao_mutex;
std::mutex m_gen_player_pos_mutex; std::mutex m_gen_player_pos_mutex;
std::vector<GLuint> m_pending_delete_vbo; std::vector<GLuint> m_pending_delete_vbo;
std::vector<GLuint> m_pending_delete_vao;
std::condition_variable m_gen_cv; std::condition_variable m_gen_cv;
std::atomic<bool> m_gen_running{false}; std::atomic<bool> m_gen_running{false};
std::atomic<bool> m_need_gen_chunk{false}; std::atomic<bool> m_need_gen_chunk{false};
std::atomic<bool> m_is_rebuilding{false};
std::atomic<bool> m_chunk_gen_finished{false};
std::atomic<bool> m_could_gen{true};
std::atomic<int> m_rendering_distance{24};
std::atomic<float> m_chunk_gen_fraction{0.0f};
std::vector<ChunkPos> m_dirty_queue; std::vector<ChunkPos> m_dirty_queue;
std::vector<ChunkRenderSnapshot> m_render_snapshots; std::vector<ChunkRenderSnapshot> m_render_snapshots;
std::vector<std::pair<ChunkPos, Chunk>> m_new_chunk; std::vector<std::pair<ChunkPos, Chunk>> m_new_chunk;
std::vector<std::pair<ChunkPos, Chunk>> m_new_chunk_queue; std::vector<std::pair<ChunkPos, Chunk>> m_new_chunk_queue;
CaveCarver m_cave_carcer;
RiverWorm m_river_worm;
void init_chunks(); void init_chunks();
void gen_chunks_internal(); void gen_chunks_internal();
void sync_player_pos(glm::vec3& player_pos); void sync_player_pos(glm::vec3& player_pos);
void compute_required_chunks(ChunkPosSet& required_chunks); void
void sync_and_collect_missing_chunks(std::vector<ChunkPos>& , const ChunkPosSet&); compute_required_chunks(ChunkPosSet& required_chunks,
void build_neighbor_context_for_new_chunks(ConstChunkMap& new_chunks_neighbor, ChunkPtrUpdateList& affected_neighbor, const ChunkUpdateList& new_chunks); ChunkPairVector& temp_neighbor,
void build_neighbor_context_for_affected_neighbors(ChunkPtrUpdateList&, ConstChunkMap&); std::vector<ChunkPos>& need_gen_temp_chunks_pos);
void start_gen_thread(); void sync_and_collect_missing_chunks(std::vector<ChunkPos>&,
void stop_gen_thread(); const ChunkPosSet&);
void
build_neighbor_context_for_new_chunks(ConstChunkMap& new_chunks_neighbor,
ChunkPtrUpdateList& affected_neighbor,
const ChunkPairVector& new_chunks);
void build_neighbor_context_for_affected_neighbors(ChunkPtrUpdateList&,
ConstChunkMap&);
public: public:
World(); World();
~World(); ~World();
bool can_move(const AABB& player_box) const; bool can_move(const AABB& player_box) const;
// const BlockRenderData& get_block_render_data(int x, int y ,int z); // const BlockRenderData& get_block_render_data(int x, int y ,int z);
const std::optional<LookBlock>& get_look_block_pos(const std::string& name) const; const std::optional<LookBlock>&
get_look_block_pos(const std::string& name) const;
const Chunk* get_chunk(const ChunkPos& pos) const; const Chunk* get_chunk(const ChunkPos& pos) const;
Player& get_player(const std::string& name); Player& get_player(const std::string& name);
void init_world(); void init_world();
bool is_aabb_in_frustum(const glm::vec3& center, const glm::vec3& half_extents);
int get_block(const glm::ivec3& block_pos) const; int get_block(const glm::ivec3& block_pos) const;
bool is_block(const glm::ivec3& block_pos) const; bool is_solid(const glm::ivec3& block_pos) const;
bool can_pass_block(const glm::ivec3& block_pos) const;
BlockType get_block_tpye(const glm::ivec3& block_pos) const;
static ChunkPos chunk_pos(int world_x, int world_z); static ChunkPos chunk_pos(int world_x, int world_z);
void need_gen(); void need_gen();
void render(const glm::mat4& mvp_matrix);
void set_block(const glm::ivec3& pos, unsigned id); void set_block(const glm::ivec3& pos, unsigned id);
void update(float delta_time); void update(float delta_time);
void push_delete_vbo(GLuint vbo); void push_delete_vbo(GLuint vbo);
void push_delete_vao(GLuint vao);
void hot_reload();
void rebuild_world();
float chunk_gen_fraction() const;
int rendering_distance() const;
void rendering_distance(int rendering_distance);
void start_gen_thread();
void stop_gen_thread();
CaveCarver& cave_carcer();
RiverWorm& river_worm();
std::vector<glm::vec4>& planes();
std::vector<ChunkRenderSnapshot>& render_snapshots();
}; };
} } // namespace Cubed

View File

@@ -4,7 +4,6 @@
namespace Cubed { namespace Cubed {
struct MoveState { struct MoveState {
bool forward = false; bool forward = false;
bool back = false; bool back = false;
@@ -32,8 +31,6 @@ struct InputState {
namespace Input { namespace Input {
InputState& get_input_state(); InputState& get_input_state();
} }
} // namespace Cubed
}

View File

@@ -1,19 +1,26 @@
#pragma once #pragma once
#include <string> // #include <string>
#include <unordered_map> // #include <unordered_map>
// #include <vector>
namespace Cubed { namespace Cubed {
class MapTable { class MapTable {
private: private:
static std::unordered_map<unsigned, std::string> id_to_name_map; /*
static std::unordered_map<size_t, unsigned> name_to_id_map; static inline std::unordered_map<unsigned, std::string> id_to_name_map;
static inline std::unordered_map<size_t, unsigned> name_to_id_map;
static inline std::vector<std::string> item_id_to_name;
*/
public: public:
// please using reference // please using reference
static const std::string& get_name_from_id(unsigned id); /*
static std::string_view get_name_from_id(unsigned id);
static unsigned get_id_from_name(const std::string& name); static unsigned get_id_from_name(const std::string& name);
static void init_map();
static std::string_view item_name(unsigned id);
static const std::vector<std::string>& item_map();
*/
static void init_map();
}; };
} } // namespace Cubed

View File

@@ -0,0 +1,171 @@
#pragma once
namespace Cubed {
#pragma region NORMAL_BLOCK
constexpr float VERTICES_POS[6][6][3] = {
// ===== front (z = +1) =====
{{0.0f, 0.0f, 1.0f}, // bottom left
{0.0f, 1.0f, 1.0f}, // top left
{1.0f, 1.0f, 1.0f}, // top right
{1.0f, 1.0f, 1.0f}, // top right
{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] = {
// ===== front (z = +1) =====
{{0.0f, 1.0f}, // bottom left
{0.0f, 0.0f}, // top left
{1.0f, 0.0f}, // top right
{1.0f, 0.0f}, // top right
{1.0f, 1.0f}, // bottom right
{0.0f, 1.0f}}, // bottom left
// ===== right (x = +1) =====
{{0.0f, 1.0f}, // bottom front
{1.0f, 1.0f}, // bottom back
{1.0f, 0.0f}, // top back
{1.0f, 0.0f}, // top back
{0.0f, 0.0f}, // top front
{0.0f, 1.0f}}, // bottom front
// ===== back (z = -1) =====
{{1.0f, 1.0f}, // bottom left
{0.0f, 1.0f}, // bottom right
{0.0f, 0.0f}, // top right
{0.0f, 0.0f}, // top right
{1.0f, 0.0f}, // top left
{1.0f, 1.0f}}, // bottom left
// ===== left (x = -1) =====
{{1.0f, 1.0f}, // bottom back
{0.0f, 1.0f}, // bottom front
{0.0f, 0.0f}, // top front
{0.0f, 0.0f}, // top front
{1.0f, 0.0f}, // top back
{1.0f, 1.0f}}, // bottom back
// ===== top (y = +1) =====
{{0.0f, 0.0f}, // back left
{1.0f, 0.0f}, // back right
{1.0f, 1.0f}, // front right
{1.0f, 1.0f}, // front right
{0.0f, 1.0f}, // front left
{0.0f, 0.0f}}, // back left
// ===== bottom (y = -1) =====
{{0.0f, 0.0f}, // front left
{1.0f, 0.0f}, // front right
{1.0f, 1.0f}, // back right
{1.0f, 1.0f}, // back right
{0.0f, 1.0f}, // back left
{0.0f, 0.0f}} // front left
};
#pragma endregion
constexpr float CUBE_VER[24] = {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},
};
#pragma region CROSS_PLANE
constexpr float CROSS_VERTICES_POS[2][6][3] = {
// ===== Plane 1: bottom-front-left to top-back-right =====
{{0.0f, 0.0f, 0.0f}, // bottom front left
{0.0f, 1.0f, 0.0f}, // top front left
{1.0f, 1.0f, 1.0f}, // top back right
{1.0f, 1.0f, 1.0f}, // top back right
{1.0f, 0.0f, 1.0f}, // bottom back right
{0.0f, 0.0f, 0.0f}}, // bottom front left
// ===== Plane 2: bottom-front-right to top-back-left =====
{{1.0f, 0.0f, 0.0f}, // bottom front right
{1.0f, 1.0f, 0.0f}, // top front right
{0.0f, 1.0f, 1.0f}, // top back left
{0.0f, 1.0f, 1.0f}, // top back left
{0.0f, 0.0f, 1.0f}, // bottom back left
{1.0f, 0.0f, 0.0f}}, // bottom front right
};
constexpr float CROSS_TEX_COORDS[2][6][2] = {
// ===== Plane 1: bottom-front-left to top-back-right =====
{{0.0f, 1.0f}, // bottom left
{0.0f, 0.0f}, // top left
{1.0f, 0.0f}, // top right
{1.0f, 0.0f}, // top right
{1.0f, 1.0f}, // bottom right
{0.0f, 1.0f}}, // bottom left
// ===== Plane 2: bottom-front-right to top-back-left =====
{{0.0f, 1.0f}, // bottom left
{0.0f, 0.0f}, // top left
{1.0f, 0.0f}, // top right
{1.0f, 0.0f}, // top right
{1.0f, 1.0f}, // bottom right
{0.0f, 1.0f}}, // bottom left
};
#pragma endregion
constexpr float QUAD_VERTICES[] = {
// postion // texcoorlds
-1.0f, 1.0f, 0.0f, 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, 0.0f,
-1.0f, 1.0f, 0.0f, 1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.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;
};
} // namespace Cubed

View File

@@ -1,10 +1,10 @@
#pragma once #pragma once
#include <Cubed/config.hpp> #include "Cubed/constants.hpp"
#include <Cubed/shader.hpp> #include "Cubed/primitive_data.hpp"
#include <Cubed/ui/text.hpp> #include "Cubed/shader.hpp"
#include "Cubed/ui/text.hpp"
#include <glad/glad.h>
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <vector> #include <vector>
namespace Cubed { namespace Cubed {
@@ -12,42 +12,73 @@ namespace Cubed {
class Camera; class Camera;
class TextureManager; class TextureManager;
class World; class World;
class DevPanel;
class Renderer { class Renderer {
public: public:
constexpr static int NUM_VAO = 5; constexpr static int NUM_VAO = 7;
Renderer(const Camera& camera, World& world, const TextureManager& texture_manager); Renderer(const Camera& camera, World& world,
const TextureManager& texture_manager, DevPanel& dev_panel);
~Renderer(); ~Renderer();
void hot_reload();
void init(); void init();
const Shader& get_shader(const std::string& name) const; const Shader& get_shader(const std::string& name) const;
void render(); void render();
void update(float delta_time);
void update_fov(float fov); void update_fov(float fov);
void update_proj_matrix(float aspect, float width, float height); void update_proj_matrix(float aspect, float width, float height);
private: void updata_framebuffer(int width, int height);
private:
const Camera& m_camera; const Camera& m_camera;
DevPanel& m_dev_panel;
const TextureManager& m_texture_manager; const TextureManager& m_texture_manager;
World& m_world; World& m_world;
float m_aspect = 0.0f; float m_aspect = 0.0f;
float m_fov = NORMAL_FOV; float m_fov = DEFAULT_FOV;
float m_delta_time = 0.0f;
float m_width = 0.0f;
float m_height = 0.0f;
glm::mat4 m_p_mat, m_v_mat, m_m_mat, m_mv_mat, m_mvp_mat; glm::mat4 m_p_mat, m_v_mat, m_m_mat, m_mv_mat, m_mvp_mat;
GLuint m_mv_loc; GLuint m_mv_loc = 0;
GLuint m_proj_loc; GLuint m_proj_loc = 0;
GLuint m_sky_vbo; GLuint m_sky_vbo = 0;
GLuint m_text_vbo; GLuint m_text_vbo = 0;
GLuint m_outline_indices_vbo; GLuint m_outline_indices_vbo = 0;
GLuint m_outline_vbo; GLuint m_outline_vbo = 0;
GLuint m_ui_vbo; GLuint m_ui_vbo = 0;
GLuint m_fbo = 0;
GLuint m_screen_texture = 0;
GLuint m_depth_render_buffer = 0;
GLuint m_oit_fbo = 0;
GLuint m_accum_texture = 0;
GLuint m_reveal_texture = 0;
GLuint m_oit_depth_render_buffer = 0;
GLuint m_quad_vbo = 0;
glm::mat4 m_ui_proj; glm::mat4 m_ui_proj;
glm::mat4 m_ui_m_matrix; glm::mat4 m_ui_m_matrix;
std::unordered_map<std::size_t, Shader> m_shaders; std::unordered_map<std::size_t, Shader> m_shaders;
/*
0 - quad vao
1 - sky vao
2 - outline vao
3 - ui vao
4 - text vao
*/
std::vector<GLuint> m_vao; std::vector<GLuint> m_vao;
std::vector<Vertex2D> m_ui; std::vector<Vertex2D> m_ui;
void init_quad();
void init_text(); void init_text();
void render_outline(); void render_outline();
@@ -55,6 +86,8 @@ private:
void render_text(); void render_text();
void render_ui(); void render_ui();
void render_world(); void render_world();
void render_underwater();
void render_dev_panel();
}; };
} } // namespace Cubed

View File

@@ -1,22 +1,22 @@
#pragma once #pragma once
#include <glad/glad.h> #include <glad/glad.h>
#include <string> #include <string>
#include <unordered_map>
namespace Cubed { namespace Cubed {
class Shader { class Shader {
public: public:
Shader(); Shader();
Shader(const std::string& name, const std::string& v_shader_path, const std::string& f_shader_path); Shader(const std::string& name, const std::string& v_shader_path,
const std::string& f_shader_path);
~Shader(); ~Shader();
Shader(const Shader&) = delete; Shader(const Shader&) = delete;
Shader& operator=(const Shader&) = delete; Shader& operator=(const Shader&) = delete;
Shader(Shader&& shader) noexcept; Shader(Shader&& shader) noexcept;
Shader& operator=(Shader&& shader) noexcept; Shader& operator=(Shader&& shader) noexcept;
void create(const std::string& name, const std::string& v_shader_path, const std::string& f_shader_path); void create(const std::string& name, const std::string& v_shader_path,
const std::string& f_shader_path);
std::size_t hash() const; std::size_t hash() const;
GLuint loc(const std::string& loc) const; GLuint loc(const std::string& loc) const;
const std::string& name() const; const std::string& name() const;
@@ -26,7 +26,7 @@ private:
GLuint m_program = 0; GLuint m_program = 0;
std::size_t m_hash = 0; std::size_t m_hash = 0;
std::string m_name = "-1"; std::string m_name = "-1";
mutable std::unordered_map<std::string, GLint> m_uniform_cache;
}; };
} } // namespace Cubed

View File

@@ -1,20 +1,31 @@
#pragma once #pragma once
#include "Cubed/gameplay/block.hpp"
#include <glad/glad.h> #include <glad/glad.h>
#include <Cubed/gameplay/block.hpp>
#include <Cubed/tools/shader_tools.hpp>
namespace Cubed { namespace Cubed {
class TextureManager { class TextureManager {
private: private:
bool m_need_reload = false; bool m_need_reload = false;
GLuint m_block_status_array; GLuint m_block_status_array = 0;
GLuint m_texture_array; GLuint m_texture_array = 0;
GLuint m_ui_array; GLuint m_cross_plane_array = 0;
GLuint m_ui_array = 0;
GLfloat m_max_aniso = 0.0f;
int m_aniso = 1;
std::vector<GLuint> m_item_textures;
void load_block_status(unsigned status_id); void load_block_status(unsigned status_id);
void load_block_texture(unsigned block_id); void load_block_texture(unsigned block_id);
void load_block_item_texture(unsigned id);
void load_cross_plane_texture(unsigned id);
void load_ui_texture(unsigned id); void load_ui_texture(unsigned id);
void init_item();
void init_block();
void init_ui();
void init_block_status();
public: public:
TextureManager(); TextureManager();
@@ -23,14 +34,15 @@ public:
void delet_texture(); void delet_texture();
GLuint get_block_status_array() const; GLuint get_block_status_array() const;
GLuint get_texture_array() const; GLuint get_texture_array() const;
GLuint get_cross_plane_array() const;
GLuint get_ui_array() const; GLuint get_ui_array() const;
const std::vector<GLuint>& item_textures() const;
// Must call after MapTable::init_map() and glfwMakeContextCurrent(window); // Must call after MapTable::init_map() and glfwMakeContextCurrent(window);
void init_texture(); void init_texture();
void hot_reload(); void hot_reload();
void need_reload(); void need_reload();
void update(); void update();
int max_aniso() const;
}; };
} // namespace Cubed
}

View File

@@ -1,24 +1,20 @@
#pragma once #pragma once
#include <Cubed/tools/log.hpp> #include "Cubed/tools/log.hpp"
namespace Cubed { namespace Cubed {
namespace Assert { namespace Assert {
inline void msg(const char* condition, const char* file, inline void msg(const char* condition, const char* file, int line,
int line, const char* func, const char* func, std::string_view message = "") {
std::string_view message = ""
) {
Logger::error("Assertion failed: {} at {}: {} in function {}", Logger::error("Assertion failed: {} at {}: {} in function {}", condition,
condition, file, line, func); file, line, func);
if (message.size()) { if (message.size()) {
Logger::error("Message: {}", message); Logger::error("Message: {}", message);
} }
std::abort(); std::abort();
}
} }
} // namespace Assert
#ifdef DEBUG_MODE #ifdef DEBUG_MODE
#define ASSERT(cond) \ #define ASSERT(cond) \
@@ -30,7 +26,8 @@ namespace Assert {
#define ASSERT_MSG(cond, message) \ #define ASSERT_MSG(cond, message) \
do { \ do { \
if (!(cond)) { \ if (!(cond)) { \
::Cubed::Assert::msg(#cond, __FILE__, __LINE__, __func__, message); \ ::Cubed::Assert::msg(#cond, __FILE__, __LINE__, __func__, \
message); \
} \ } \
} while (0) } while (0)
@@ -39,4 +36,4 @@ namespace Assert {
#define ASSERT_MSG(cond, message) ((void)0) #define ASSERT_MSG(cond, message) ((void)0)
#endif #endif
} } // namespace Cubed

View File

@@ -1,14 +1,44 @@
#pragma once #pragma once
#include <cstdint>
#include <string_view> #include <string_view>
namespace Cubed { namespace Cubed {
namespace HASH { namespace HASH {
inline std::size_t str(std::string_view value) { inline std::size_t str(std::string_view value) {
return std::hash<std::string_view>{}(value); return std::hash<std::string_view>{}(value);
} }
inline uint32_t combine_32(uint32_t seed, uint32_t v) {
seed ^= v + 0x9e3779b9 + (seed << 6) + (seed >> 2);
return seed;
} }
inline uint32_t chunk_seed_hash(int32_t a, int32_t b, uint32_t fixed_seed) {
uint32_t seed =
combine_32(combine_32(fixed_seed, (uint32_t)a), (uint32_t)b);
return seed;
} }
/*
inline uint32_t chunk_seed_hash(int32_t a, int32_t b, uint32_t fixed_seed) {
uint32_t h = fixed_seed;
h ^= (uint32_t)a * 0xcc9e2d51u;
h = (h << 15) | (h >> 17); // rotl 15
h *= 0x1b873593u;
h ^= (uint32_t)b * 0xcc9e2d51u;
h = (h << 15) | (h >> 17); // rotl 15
h *= 0x1b873593u;
// Finalizationavalanche
h ^= h >> 16;
h *= 0x85ebca6bu;
h ^= h >> 13;
h *= 0xc2b2ae35u;
h ^= h >> 16;
return h;
}
*/
} // namespace HASH
} // namespace Cubed

View File

@@ -4,19 +4,19 @@ namespace Cubed {
class Random { class Random {
public: public:
static unsigned get_base_seed(); Random();
static unsigned get_thread_seed(); Random(unsigned seed);
static Random& get();
bool random_bool(double probability); bool random_bool(double probability);
std::mt19937& engine(); std::mt19937& engine();
unsigned seed(); unsigned seed();
void init(unsigned seed);
int random_int(int min, int max);
float random_float(float min, float max);
private: private:
Random();
unsigned int m_seed = 0; unsigned int m_seed = 0;
std::mt19937 m_engine; std::mt19937 m_engine;
}; };
} // namespace Cubed
}

View File

@@ -2,17 +2,15 @@
#include <ft2build.h> #include <ft2build.h>
#include FT_FREETYPE_H #include FT_FREETYPE_H
#include "Cubed/primitive_data.hpp"
#include <glad/glad.h> #include <glad/glad.h>
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
#include <Cubed/config.hpp>
namespace Cubed { namespace Cubed {
struct Character { struct Character {
glm::vec2 uv_min; glm::vec2 uv_min;
glm::vec2 uv_max; glm::vec2 uv_max;
@@ -28,8 +26,12 @@ public:
Font(); Font();
~Font(); ~Font();
static std::vector<Vertex2D> vertices(const std::string& text, float x = 0.0f, float y = 0.0f, float scale = 1.0f); static std::vector<Vertex2D> vertices(const std::string& text,
float x = 0.0f, float y = 0.0f,
float scale = 1.0f);
static GLuint text_texture(); static GLuint text_texture();
static const std::string& font_path();
private: private:
FT_Library m_ft; FT_Library m_ft;
FT_Face m_face; FT_Face m_face;
@@ -38,12 +40,12 @@ private:
float m_texture_height = 64; float m_texture_height = 64;
static inline GLuint m_text_texture; static inline GLuint m_text_texture;
static inline std::string m_font_path{ASSETS_PATH
"fonts/IBMPlexSans-Regular.ttf"};
std::unordered_map<char8_t, Character> m_characters; std::unordered_map<char8_t, Character> m_characters;
void load_character(char8_t c); void load_character(char8_t c);
void setup_font_character(); void setup_font_character();
}; };
} } // namespace Cubed

View File

@@ -1,83 +1,70 @@
#pragma once #pragma once
#include <syncstream>
#include <iostream>
#include <chrono> #include <chrono>
#include <format> #include <format>
#include <iostream>
#include <source_location> #include <source_location>
#include <string> #include <string>
#include <syncstream>
namespace Cubed { namespace Cubed {
namespace Logger { namespace Logger {
enum class Level { enum class Level { TRACE, DEBUG, INFO, ERROR, WARN };
TRACE,
DEBUG,
INFO,
ERROR,
WARN
};
template <typename... Args> template <typename... Args>
inline void info(std::format_string<Args...> fmt, Args&&... args) { inline void info(std::format_string<Args...> fmt, Args&&... args) {
auto now_time = std::chrono:: auto now_time = std::chrono::time_point_cast<std::chrono::seconds>(
time_point_cast<std::chrono::seconds> std::chrono::system_clock::now());
(std::chrono::system_clock::now());
std::string msg = std::vformat(fmt.get(), std::make_format_args(args...)); std::string msg = std::vformat(fmt.get(), std::make_format_args(args...));
std::osyncstream(std::cout) << "\033[1;32m" std::osyncstream(std::cout)
<< std::format("[INFO][{:%Y-%m-%d %H:%M:%S}]", now_time) << "\033[1;32m" << std::format("[INFO][{:%Y-%m-%d %H:%M:%S}]", now_time)
<< msg << msg << "\033[0m"
<< "\033[0m"
<< "\n"; << "\n";
} }
template <typename... Args> template <typename... Args>
inline void error(std::format_string<Args...> fmt, Args&&... args) { inline void error(std::format_string<Args...> fmt, Args&&... args) {
auto now_time = std::chrono:: auto now_time = std::chrono::time_point_cast<std::chrono::seconds>(
time_point_cast<std::chrono::seconds> std::chrono::system_clock::now());
(std::chrono::system_clock::now());
std::string msg = std::vformat(fmt.get(), std::make_format_args(args...)); std::string msg = std::vformat(fmt.get(), std::make_format_args(args...));
std::osyncstream(std::cerr) << "\033[1;31m" std::osyncstream(std::cerr)
<< std::format("[ERROR][{:%Y-%m-%d %H:%M:%S}]", now_time) << "\033[1;31m"
<< msg << std::format("[ERROR][{:%Y-%m-%d %H:%M:%S}]", now_time) << msg
<< "\033[0m" << "\033[0m"
<< "\n"; << "\n";
} }
template <typename... Args> template <typename... Args>
inline void warn(std::format_string<Args...> fmt, Args&&... args) { inline void warn(std::format_string<Args...> fmt, Args&&... args) {
auto now_time = std::chrono:: auto now_time = std::chrono::time_point_cast<std::chrono::seconds>(
time_point_cast<std::chrono::seconds> std::chrono::system_clock::now());
(std::chrono::system_clock::now());
std::string msg = std::vformat(fmt.get(), std::make_format_args(args...)); std::string msg = std::vformat(fmt.get(), std::make_format_args(args...));
std::osyncstream(std::cout) << "\033[1;33m" std::osyncstream(std::cout)
<< std::format("[WARN][{:%Y-%m-%d %H:%M:%S}]", now_time) << "\033[1;33m" << std::format("[WARN][{:%Y-%m-%d %H:%M:%S}]", now_time)
<< msg << msg << "\033[0m"
<< "\033[0m"
<< "\n"; << "\n";
} }
template <typename... Args> template <typename... Args>
inline void log(Level level, std::source_location loc, std::format_string<Args...> fmt, Args&&... args) { inline void log(Level level, std::source_location loc,
auto now_time = std::chrono:: std::format_string<Args...> fmt, Args&&... args) {
time_point_cast<std::chrono::seconds> auto now_time = std::chrono::time_point_cast<std::chrono::seconds>(
(std::chrono::system_clock::now()); std::chrono::system_clock::now());
std::string msg = std::vformat(fmt.get(), std::make_format_args(args...)); std::string msg = std::vformat(fmt.get(), std::make_format_args(args...));
switch (level) { switch (level) {
case Logger::Level::TRACE: case Logger::Level::TRACE:
std::osyncstream(std::cout) << "\033[1;34m" std::osyncstream(std::cout)
<< std::format("[TRACE][{:%Y-%m-%d %H:%M:%S}]", now_time) << "\033[1;34m"
<< "[" << loc.file_name() << ":" << loc.line() << "]" << std::format("[TRACE][{:%Y-%m-%d %H:%M:%S}]", now_time) << "["
<< "[" << loc.function_name() << "]" << loc.file_name() << ":" << loc.line() << "]"
<< msg << "[" << loc.function_name() << "]" << msg << "\033[0m"
<< "\033[0m"
<< "\n"; << "\n";
break; break;
case Logger::Level::DEBUG: case Logger::Level::DEBUG:
std::osyncstream(std::cout) << "\033[1;34m" std::osyncstream(std::cout)
<< std::format("[DEBUG][{:%Y-%m-%d %H:%M:%S}]", now_time) << "\033[1;34m"
<< msg << std::format("[DEBUG][{:%Y-%m-%d %H:%M:%S}]", now_time) << msg
<< "\033[0m" << "\033[0m"
<< "\n"; << "\n";
break; break;
@@ -90,13 +77,9 @@ namespace Logger {
case Logger::Level::ERROR: case Logger::Level::ERROR:
error(fmt, std::forward<Args>(args)...); error(fmt, std::forward<Args>(args)...);
break; break;
}
} }
} } // namespace Logger
}
}
} // namespace Cubed

View File

@@ -3,9 +3,15 @@
namespace Cubed { namespace Cubed {
namespace Math { namespace Math {
void extract_frustum_planes(const glm::mat4& mvp_matrix, std::vector<glm::vec4>& planes);
}
} void extract_frustum_planes(const glm::mat4& mvp_matrix,
std::vector<glm::vec4>& planes);
float smootherstep(float edge0, float edge1, float x);
bool is_aabb_in_frustum(const glm::vec3& center, const glm::vec3& half_extents,
const std::vector<glm::vec4>& planes);
float deterministic_random(int x, int z, uint64_t seed);
} // namespace Math
} // namespace Cubed

View File

@@ -4,18 +4,33 @@
namespace Cubed { namespace Cubed {
class PerlinNoise3D {
class PerlinNoise {
public: public:
static void init(); static void init(unsigned seed);
static float noise(float x, float y, float z); static float noise(float x, float y, float z);
static void reload(unsigned seed);
private:
static inline std::atomic<bool> is_init = false;
static inline std::vector<int> p;
static float fade(float t);
static float lerp(float t, float a, float b);
static float grad(int hash, float x, float y, float z);
};
class PerlinNoise2D {
public:
static void init(unsigned seed);
static float noise(float x, float y);
static void reload(unsigned seed);
private: private:
static inline std::atomic<bool> is_init = false; static inline std::atomic<bool> is_init = false;
static inline std::vector<int> p; static inline std::vector<int> p;
static float fade(float t); static float fade(float t);
static float lerp(float t, float a, float b); static float lerp(float t, float a, float b);
static float grad(int hash, float x, float y, float z); static float grad(int hash, float x, float y);
}; };
} } // namespace Cubed

View File

@@ -1,14 +1,14 @@
#pragma once #pragma once
#include <glad/glad.h>
#include <SOIL2.h> #include <SOIL2.h>
#include <glad/glad.h>
#include <string> #include <string>
namespace Cubed { namespace Cubed {
namespace Tools { namespace Tools {
GLuint create_shader_program(const std::string& v_shader_path, const std::string& f_shader_path); GLuint create_shader_program(const std::string& v_shader_path,
const std::string& f_shader_path);
void print_shader_log(GLuint shader); void print_shader_log(GLuint shader);
void print_program_info(int prog); void print_program_info(int prog);
bool check_opengl_error(); bool check_opengl_error();
@@ -16,6 +16,6 @@ namespace Tools {
void delete_image_data(unsigned char* data); void delete_image_data(unsigned char* data);
unsigned char* load_image_data(const std::string& tex_image_path); unsigned char* load_image_data(const std::string& tex_image_path);
} } // namespace Tools
} } // namespace Cubed

View File

@@ -1,36 +1,41 @@
#pragma once #pragma once
#include "Cubed/tools/log.hpp"
#include <string> #include <string>
#include <Cubed/tools/log.hpp>
#ifdef _WIN32 #ifdef _WIN32
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
// clang-format off
#include <windows.h> #include <windows.h>
#include <psapi.h> #include <psapi.h>
// clang-format on
typedef LONG(WINAPI* RtlGetVersionPtr)(PRTL_OSVERSIONINFOW); typedef LONG(WINAPI* RtlGetVersionPtr)(PRTL_OSVERSIONINFOW);
#elif defined(__linux__) #elif defined(__linux__)
#include <fstream>
#include <sys/resource.h> #include <sys/resource.h>
#include <unistd.h> #include <unistd.h>
#include <fstream>
#endif #endif
namespace Cubed { namespace Cubed {
namespace Tools { namespace Tools {
inline bool get_os_version(std::string& str) { inline bool get_os_version(std::string& str) {
#ifdef _WIN32 #ifdef _WIN32
HMODULE hntdll = GetModuleHandleW(L"ntdll.dll"); HMODULE hntdll = GetModuleHandleW(L"ntdll.dll");
if (!hntdll) return false; if (!hntdll)
return false;
auto prtl_get_version = reinterpret_cast<RtlGetVersionPtr>( auto prtl_get_version = reinterpret_cast<RtlGetVersionPtr>(
GetProcAddress(hntdll, "RtlGetVersion")); GetProcAddress(hntdll, "RtlGetVersion"));
if (!prtl_get_version) return false; if (!prtl_get_version)
return false;
RTL_OSVERSIONINFOW osvi = {0}; RTL_OSVERSIONINFOW osvi = {0};
osvi.dwOSVersionInfoSize = sizeof(osvi); osvi.dwOSVersionInfoSize = sizeof(osvi);
if (prtl_get_version(&osvi) != 0) return false; if (prtl_get_version(&osvi) != 0)
return false;
if (osvi.dwMajorVersion == 10) { if (osvi.dwMajorVersion == 10) {
if (osvi.dwBuildNumber >= 22000) { if (osvi.dwBuildNumber >= 22000) {
str = "Windows 11 Build " + std::to_string(osvi.dwBuildNumber); str = "Windows 11 Build " + std::to_string(osvi.dwBuildNumber);
@@ -74,7 +79,8 @@ inline bool get_os_version(std::string& str) {
inline size_t get_current_rss() { inline size_t get_current_rss() {
#ifdef _WIN32 #ifdef _WIN32
PROCESS_MEMORY_COUNTERS_EX pmc; PROCESS_MEMORY_COUNTERS_EX pmc;
if (GetProcessMemoryInfo(GetCurrentProcess(), (PROCESS_MEMORY_COUNTERS*)&pmc, sizeof(pmc))) { if (GetProcessMemoryInfo(GetCurrentProcess(),
(PROCESS_MEMORY_COUNTERS*)&pmc, sizeof(pmc))) {
return pmc.WorkingSetSize; return pmc.WorkingSetSize;
} }
return 0; return 0;
@@ -96,17 +102,23 @@ inline std::string get_cpu_info() {
std::string cpu_name; std::string cpu_name;
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", 0,
0, KEY_READ, &h_key) == ERROR_SUCCESS) { KEY_READ, &h_key) == ERROR_SUCCESS) {
DWORD dw_size = 0; DWORD dw_size = 0;
if (RegQueryValueExW(h_key, L"ProcessorNameString", NULL, NULL, NULL, &dw_size) == ERROR_SUCCESS && dw_size > 0) { if (RegQueryValueExW(h_key, L"ProcessorNameString", NULL, NULL, NULL,
&dw_size) == ERROR_SUCCESS &&
dw_size > 0) {
std::vector<wchar_t> buffer(dw_size / sizeof(wchar_t)); std::vector<wchar_t> buffer(dw_size / sizeof(wchar_t));
if (RegQueryValueExW(h_key, L"ProcessorNameString", NULL, NULL, (LPBYTE)buffer.data(), &dw_size) == ERROR_SUCCESS) { if (RegQueryValueExW(h_key, L"ProcessorNameString", NULL, NULL,
int len = WideCharToMultiByte(CP_UTF8, 0, buffer.data(), -1, NULL, 0, NULL, NULL); (LPBYTE)buffer.data(),
&dw_size) == ERROR_SUCCESS) {
int len = WideCharToMultiByte(CP_UTF8, 0, buffer.data(), -1,
NULL, 0, NULL, NULL);
if (len > 0) { if (len > 0) {
std::vector<char> narrow(len); std::vector<char> narrow(len);
WideCharToMultiByte(CP_UTF8, 0, buffer.data(), -1, narrow.data(), len, NULL, NULL); WideCharToMultiByte(CP_UTF8, 0, buffer.data(), -1,
narrow.data(), len, NULL, NULL);
cpu_name = narrow.data(); cpu_name = narrow.data();
} }
} }
@@ -141,8 +153,6 @@ inline std::string get_cpu_info() {
#endif #endif
} }
} // namespace Tools
} } // namespace Cubed
}

View File

@@ -1,10 +1,10 @@
#pragma once #pragma once
#include <Cubed/tools/cubed_assert.hpp> #include "Cubed/tools/cubed_assert.hpp"
#include <glm/glm.hpp> #include <glm/glm.hpp>
namespace Cubed { namespace Cubed {
enum class Color { enum class Color {
BLACK, BLACK,
WHITE, WHITE,
@@ -55,7 +55,6 @@ inline constexpr glm::vec4 color_value(Color color) {
ASSERT_MSG(false, "Unknown Color"); ASSERT_MSG(false, "Unknown Color");
return vec4{1.0f, 1.0f, 1.0f, 1.0f}; return vec4{1.0f, 1.0f, 1.0f, 1.0f};
} }
} }
inline glm::vec4 rgb255_to_float(int r, int g, int b, int a) { inline glm::vec4 rgb255_to_float(int r, int g, int b, int a) {
@@ -67,4 +66,4 @@ inline glm::vec4 rgb255_to_float(int r, int g, int b, int a) {
return glm::vec4{nr, ng, nb, na}; return glm::vec4{nr, ng, nb, na};
} }
} } // namespace Cubed

View File

@@ -1,21 +1,20 @@
#pragma once #pragma once
#include "Cubed/primitive_data.hpp"
#include "Cubed/ui/color.hpp"
#include <glad/glad.h> #include <glad/glad.h>
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <string> #include <string>
#include <vector>
#include <Cubed/config.hpp>
#include <Cubed/ui/color.hpp>
namespace Cubed { namespace Cubed {
class Shader; class Shader;
class Text { class Text {
public: public:
explicit Text(std::string_view name); explicit Text(std::string_view name);
Text(std::string_view name, std::string_view str, glm::vec2 pos = glm::vec2{0.0f, 0.0f}, Color color = Color::BLACK); Text(std::string_view name, std::string_view str,
glm::vec2 pos = glm::vec2{0.0f, 0.0f}, Color color = Color::BLACK);
~Text(); ~Text();
Text(const Text&) = delete; Text(const Text&) = delete;
Text(Text&&) noexcept; Text(Text&&) noexcept;
@@ -50,7 +49,6 @@ private:
void update_vertices(); void update_vertices();
void upload_to_gpu(); void upload_to_gpu();
}; };
} } // namespace Cubed

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