From 5723c17f94e8cb8404b4c48757a02f77cb1f4441 Mon Sep 17 00:00:00 2001 From: zhenyan121 <3367366583@qq.com> Date: Fri, 17 Apr 2026 19:55:47 +0800 Subject: [PATCH] feat: add 4 biomes --- assets/texture/block/sand/back.png | Bin 0 -> 391 bytes assets/texture/block/sand/base.png | Bin 0 -> 391 bytes assets/texture/block/sand/front.png | Bin 0 -> 391 bytes assets/texture/block/sand/left.png | Bin 0 -> 391 bytes assets/texture/block/sand/right.png | Bin 0 -> 391 bytes assets/texture/block/sand/top.png | Bin 0 -> 391 bytes assets/texture/block/stone/back.png | Bin 382 -> 418 bytes assets/texture/block/stone/base.png | Bin 382 -> 418 bytes assets/texture/block/stone/front.png | Bin 382 -> 418 bytes assets/texture/block/stone/left.png | Bin 382 -> 418 bytes assets/texture/block/stone/right.png | Bin 382 -> 418 bytes assets/texture/block/stone/top.png | Bin 382 -> 418 bytes include/Cubed/config.hpp | 5 +- include/Cubed/gameplay/chunk.hpp | 8 ++ include/Cubed/gameplay/chunk_status.hpp | 88 ++++++++++++++++++ include/Cubed/gameplay/world.hpp | 5 +- include/Cubed/tools/math_tools.hpp | 1 + src/debug_collector.cpp | 6 ++ src/gameplay/chunk.cpp | 117 ++++++++++++++++-------- src/gameplay/player.cpp | 8 ++ src/gameplay/world.cpp | 9 ++ src/map_table.cpp | 3 +- src/tools/math_tools.cpp | 49 ++++++++++ 23 files changed, 259 insertions(+), 40 deletions(-) create mode 100644 assets/texture/block/sand/back.png create mode 100644 assets/texture/block/sand/base.png create mode 100644 assets/texture/block/sand/front.png create mode 100644 assets/texture/block/sand/left.png create mode 100644 assets/texture/block/sand/right.png create mode 100644 assets/texture/block/sand/top.png diff --git a/assets/texture/block/sand/back.png b/assets/texture/block/sand/back.png new file mode 100644 index 0000000000000000000000000000000000000000..93098c8f143ba102e07eb5127f13d93852558708 GIT binary patch literal 391 zcmV;20eJq2P)Px$K}keGR5*=olQC|?FbqY%wAf2DNt=fNUa|)8A#$c3syArKHuLe0F*4Smc|L&x&Q!N7Ss>{0DXv>>$1R?EGSu!#z_+Z=;J;_ zbi+mCES|;*HAHx4I=d`5rE^n^4Oq~A1Awm~!WrkbE=_X3$Jv=C_xV)-0J`A<0IHKC z(&|B$W#R$o*z6|vS(8ucta8XFUT^C2eTX`C$%1&jp_*h{h_D+5b_4bSrC0{Xc**jT zu&oQ+4vd{k7Cg5H%C6V0)dKZ&)DUq>XVsj>Ne?EClTPvd_0de?OBM}o>w@R@_(NRo zbF(Qc+0%LKz@%=tpqle#amw{{ay7@pvN8yj{*vXF0WXWUPh%&pnvC=gjuWu51^M6j l4Fel+J5+c0X)HK<2S5Lz=e+FC&jJ7d002ovPDHLkV1n!kt#beX literal 0 HcmV?d00001 diff --git a/assets/texture/block/sand/base.png b/assets/texture/block/sand/base.png new file mode 100644 index 0000000000000000000000000000000000000000..93098c8f143ba102e07eb5127f13d93852558708 GIT binary patch literal 391 zcmV;20eJq2P)Px$K}keGR5*=olQC|?FbqY%wAf2DNt=fNUa|)8A#$c3syArKHuLe0F*4Smc|L&x&Q!N7Ss>{0DXv>>$1R?EGSu!#z_+Z=;J;_ zbi+mCES|;*HAHx4I=d`5rE^n^4Oq~A1Awm~!WrkbE=_X3$Jv=C_xV)-0J`A<0IHKC z(&|B$W#R$o*z6|vS(8ucta8XFUT^C2eTX`C$%1&jp_*h{h_D+5b_4bSrC0{Xc**jT zu&oQ+4vd{k7Cg5H%C6V0)dKZ&)DUq>XVsj>Ne?EClTPvd_0de?OBM}o>w@R@_(NRo zbF(Qc+0%LKz@%=tpqle#amw{{ay7@pvN8yj{*vXF0WXWUPh%&pnvC=gjuWu51^M6j l4Fel+J5+c0X)HK<2S5Lz=e+FC&jJ7d002ovPDHLkV1n!kt#beX literal 0 HcmV?d00001 diff --git a/assets/texture/block/sand/front.png b/assets/texture/block/sand/front.png new file mode 100644 index 0000000000000000000000000000000000000000..93098c8f143ba102e07eb5127f13d93852558708 GIT binary patch literal 391 zcmV;20eJq2P)Px$K}keGR5*=olQC|?FbqY%wAf2DNt=fNUa|)8A#$c3syArKHuLe0F*4Smc|L&x&Q!N7Ss>{0DXv>>$1R?EGSu!#z_+Z=;J;_ zbi+mCES|;*HAHx4I=d`5rE^n^4Oq~A1Awm~!WrkbE=_X3$Jv=C_xV)-0J`A<0IHKC z(&|B$W#R$o*z6|vS(8ucta8XFUT^C2eTX`C$%1&jp_*h{h_D+5b_4bSrC0{Xc**jT zu&oQ+4vd{k7Cg5H%C6V0)dKZ&)DUq>XVsj>Ne?EClTPvd_0de?OBM}o>w@R@_(NRo zbF(Qc+0%LKz@%=tpqle#amw{{ay7@pvN8yj{*vXF0WXWUPh%&pnvC=gjuWu51^M6j l4Fel+J5+c0X)HK<2S5Lz=e+FC&jJ7d002ovPDHLkV1n!kt#beX literal 0 HcmV?d00001 diff --git a/assets/texture/block/sand/left.png b/assets/texture/block/sand/left.png new file mode 100644 index 0000000000000000000000000000000000000000..93098c8f143ba102e07eb5127f13d93852558708 GIT binary patch literal 391 zcmV;20eJq2P)Px$K}keGR5*=olQC|?FbqY%wAf2DNt=fNUa|)8A#$c3syArKHuLe0F*4Smc|L&x&Q!N7Ss>{0DXv>>$1R?EGSu!#z_+Z=;J;_ zbi+mCES|;*HAHx4I=d`5rE^n^4Oq~A1Awm~!WrkbE=_X3$Jv=C_xV)-0J`A<0IHKC z(&|B$W#R$o*z6|vS(8ucta8XFUT^C2eTX`C$%1&jp_*h{h_D+5b_4bSrC0{Xc**jT zu&oQ+4vd{k7Cg5H%C6V0)dKZ&)DUq>XVsj>Ne?EClTPvd_0de?OBM}o>w@R@_(NRo zbF(Qc+0%LKz@%=tpqle#amw{{ay7@pvN8yj{*vXF0WXWUPh%&pnvC=gjuWu51^M6j l4Fel+J5+c0X)HK<2S5Lz=e+FC&jJ7d002ovPDHLkV1n!kt#beX literal 0 HcmV?d00001 diff --git a/assets/texture/block/sand/right.png b/assets/texture/block/sand/right.png new file mode 100644 index 0000000000000000000000000000000000000000..93098c8f143ba102e07eb5127f13d93852558708 GIT binary patch literal 391 zcmV;20eJq2P)Px$K}keGR5*=olQC|?FbqY%wAf2DNt=fNUa|)8A#$c3syArKHuLe0F*4Smc|L&x&Q!N7Ss>{0DXv>>$1R?EGSu!#z_+Z=;J;_ zbi+mCES|;*HAHx4I=d`5rE^n^4Oq~A1Awm~!WrkbE=_X3$Jv=C_xV)-0J`A<0IHKC z(&|B$W#R$o*z6|vS(8ucta8XFUT^C2eTX`C$%1&jp_*h{h_D+5b_4bSrC0{Xc**jT zu&oQ+4vd{k7Cg5H%C6V0)dKZ&)DUq>XVsj>Ne?EClTPvd_0de?OBM}o>w@R@_(NRo zbF(Qc+0%LKz@%=tpqle#amw{{ay7@pvN8yj{*vXF0WXWUPh%&pnvC=gjuWu51^M6j l4Fel+J5+c0X)HK<2S5Lz=e+FC&jJ7d002ovPDHLkV1n!kt#beX literal 0 HcmV?d00001 diff --git a/assets/texture/block/sand/top.png b/assets/texture/block/sand/top.png new file mode 100644 index 0000000000000000000000000000000000000000..93098c8f143ba102e07eb5127f13d93852558708 GIT binary patch literal 391 zcmV;20eJq2P)Px$K}keGR5*=olQC|?FbqY%wAf2DNt=fNUa|)8A#$c3syArKHuLe0F*4Smc|L&x&Q!N7Ss>{0DXv>>$1R?EGSu!#z_+Z=;J;_ zbi+mCES|;*HAHx4I=d`5rE^n^4Oq~A1Awm~!WrkbE=_X3$Jv=C_xV)-0J`A<0IHKC z(&|B$W#R$o*z6|vS(8ucta8XFUT^C2eTX`C$%1&jp_*h{h_D+5b_4bSrC0{Xc**jT zu&oQ+4vd{k7Cg5H%C6V0)dKZ&)DUq>XVsj>Ne?EClTPvd_0de?OBM}o>w@R@_(NRo zbF(Qc+0%LKz@%=tpqle#amw{{ay7@pvN8yj{*vXF0WXWUPh%&pnvC=gjuWu51^M6j l4Fel+J5+c0X)HK<2S5Lz=e+FC&jJ7d002ovPDHLkV1n!kt#beX literal 0 HcmV?d00001 diff --git a/assets/texture/block/stone/back.png b/assets/texture/block/stone/back.png index a69ad7ab0e6a0b0bc12b34d77ebdccf2d866c6e0..5b860e6cfcc1a95552b2b333321ba6eae5a576cd 100644 GIT binary patch delta 378 zcmV-=0fqkl0-^(uF@Ic1L_t(IjdhbjYlA=#g};Qo_~Yvn5GA&O3JdJwrbLkfc6*1DsFC0A^yg?p}w7Lw`RYRsy>!bKWtIBYoEb zU}BjHrhrvaY|Q#S!5_QH9GO)~nf{R5b@$Nj$U-T=5>&WM%J zn#Q844i9C}h+U6CwJ;_y^CAVZNfsP;-mxi5ZnrkHsx?N9(H6949aWrrrqHM)1$yRq zEP1|EMw7~{iF0ur!$aNF`IrHW8uPN*PGrXC>*Wm5L}C@o|KxS|da{Mjj20`HyeK)J zj*}lqLB$H6AMX>{^AVf5VE}nihFzcMV#Q(w(|2vS%!`tr@2{{lP2B_o#R@jb!U}8r Y0t?FAjyc_Er~m)}07*qoM6N<$g7nz5qW}N^ delta 342 zcmV-c0jd6?1O5V#F@HEoL_t(Ija`$`j)fo$M2{^Pzk4^?Z#F{5eZV63`T{A~Ih~g6 z=lAbETj!{S^^-bgg|l@4j#`j9SB&%B!K_fE&h8`FLIC(S*0X(|8M|wWoULQP%o-Ba zjVnehRjz>QMo3&SV)Qr9R_X*6s`f7+FIvUVoCM7fG1{d2VZsZidu9 z6>ON7cjC606rkkhnw>C+K7U-zGfQBbC6(3fRLcFp*3&}G^Ym?`TIx+NvJ0!3>Hd08 z>Xfq$_kA1n@u02vwoqll^kJH4R;WIKrb*RpmSa{v2mwmg>6>Qou(#JCeW<2K+2XPe z%=gf=(4^XV4Np93;jpKS6=xlgRLeC>%Eb9@N)Ag45g~kgX@>eBn8QV_~Yvn5GA&O3JdJwrbLkfc6*1DsFC0A^yg?p}w7Lw`RYRsy>!bKWtIBYoEb zU}BjHrhrvaY|Q#S!5_QH9GO)~nf{R5b@$Nj$U-T=5>&WM%J zn#Q844i9C}h+U6CwJ;_y^CAVZNfsP;-mxi5ZnrkHsx?N9(H6949aWrrrqHM)1$yRq zEP1|EMw7~{iF0ur!$aNF`IrHW8uPN*PGrXC>*Wm5L}C@o|KxS|da{Mjj20`HyeK)J zj*}lqLB$H6AMX>{^AVf5VE}nihFzcMV#Q(w(|2vS%!`tr@2{{lP2B_o#R@jb!U}8r Y0t?FAjyc_Er~m)}07*qoM6N<$g7nz5qW}N^ delta 342 zcmV-c0jd6?1O5V#F@HEoL_t(Ija`$`j)fo$M2{^Pzk4^?Z#F{5eZV63`T{A~Ih~g6 z=lAbETj!{S^^-bgg|l@4j#`j9SB&%B!K_fE&h8`FLIC(S*0X(|8M|wWoULQP%o-Ba zjVnehRjz>QMo3&SV)Qr9R_X*6s`f7+FIvUVoCM7fG1{d2VZsZidu9 z6>ON7cjC606rkkhnw>C+K7U-zGfQBbC6(3fRLcFp*3&}G^Ym?`TIx+NvJ0!3>Hd08 z>Xfq$_kA1n@u02vwoqll^kJH4R;WIKrb*RpmSa{v2mwmg>6>Qou(#JCeW<2K+2XPe z%=gf=(4^XV4Np93;jpKS6=xlgRLeC>%Eb9@N)Ag45g~kgX@>eBn8QV_~Yvn5GA&O3JdJwrbLkfc6*1DsFC0A^yg?p}w7Lw`RYRsy>!bKWtIBYoEb zU}BjHrhrvaY|Q#S!5_QH9GO)~nf{R5b@$Nj$U-T=5>&WM%J zn#Q844i9C}h+U6CwJ;_y^CAVZNfsP;-mxi5ZnrkHsx?N9(H6949aWrrrqHM)1$yRq zEP1|EMw7~{iF0ur!$aNF`IrHW8uPN*PGrXC>*Wm5L}C@o|KxS|da{Mjj20`HyeK)J zj*}lqLB$H6AMX>{^AVf5VE}nihFzcMV#Q(w(|2vS%!`tr@2{{lP2B_o#R@jb!U}8r Y0t?FAjyc_Er~m)}07*qoM6N<$g7nz5qW}N^ delta 342 zcmV-c0jd6?1O5V#F@HEoL_t(Ija`$`j)fo$M2{^Pzk4^?Z#F{5eZV63`T{A~Ih~g6 z=lAbETj!{S^^-bgg|l@4j#`j9SB&%B!K_fE&h8`FLIC(S*0X(|8M|wWoULQP%o-Ba zjVnehRjz>QMo3&SV)Qr9R_X*6s`f7+FIvUVoCM7fG1{d2VZsZidu9 z6>ON7cjC606rkkhnw>C+K7U-zGfQBbC6(3fRLcFp*3&}G^Ym?`TIx+NvJ0!3>Hd08 z>Xfq$_kA1n@u02vwoqll^kJH4R;WIKrb*RpmSa{v2mwmg>6>Qou(#JCeW<2K+2XPe z%=gf=(4^XV4Np93;jpKS6=xlgRLeC>%Eb9@N)Ag45g~kgX@>eBn8QV_~Yvn5GA&O3JdJwrbLkfc6*1DsFC0A^yg?p}w7Lw`RYRsy>!bKWtIBYoEb zU}BjHrhrvaY|Q#S!5_QH9GO)~nf{R5b@$Nj$U-T=5>&WM%J zn#Q844i9C}h+U6CwJ;_y^CAVZNfsP;-mxi5ZnrkHsx?N9(H6949aWrrrqHM)1$yRq zEP1|EMw7~{iF0ur!$aNF`IrHW8uPN*PGrXC>*Wm5L}C@o|KxS|da{Mjj20`HyeK)J zj*}lqLB$H6AMX>{^AVf5VE}nihFzcMV#Q(w(|2vS%!`tr@2{{lP2B_o#R@jb!U}8r Y0t?FAjyc_Er~m)}07*qoM6N<$g7nz5qW}N^ delta 342 zcmV-c0jd6?1O5V#F@HEoL_t(Ija`$`j)fo$M2{^Pzk4^?Z#F{5eZV63`T{A~Ih~g6 z=lAbETj!{S^^-bgg|l@4j#`j9SB&%B!K_fE&h8`FLIC(S*0X(|8M|wWoULQP%o-Ba zjVnehRjz>QMo3&SV)Qr9R_X*6s`f7+FIvUVoCM7fG1{d2VZsZidu9 z6>ON7cjC606rkkhnw>C+K7U-zGfQBbC6(3fRLcFp*3&}G^Ym?`TIx+NvJ0!3>Hd08 z>Xfq$_kA1n@u02vwoqll^kJH4R;WIKrb*RpmSa{v2mwmg>6>Qou(#JCeW<2K+2XPe z%=gf=(4^XV4Np93;jpKS6=xlgRLeC>%Eb9@N)Ag45g~kgX@>eBn8QV_~Yvn5GA&O3JdJwrbLkfc6*1DsFC0A^yg?p}w7Lw`RYRsy>!bKWtIBYoEb zU}BjHrhrvaY|Q#S!5_QH9GO)~nf{R5b@$Nj$U-T=5>&WM%J zn#Q844i9C}h+U6CwJ;_y^CAVZNfsP;-mxi5ZnrkHsx?N9(H6949aWrrrqHM)1$yRq zEP1|EMw7~{iF0ur!$aNF`IrHW8uPN*PGrXC>*Wm5L}C@o|KxS|da{Mjj20`HyeK)J zj*}lqLB$H6AMX>{^AVf5VE}nihFzcMV#Q(w(|2vS%!`tr@2{{lP2B_o#R@jb!U}8r Y0t?FAjyc_Er~m)}07*qoM6N<$g7nz5qW}N^ delta 342 zcmV-c0jd6?1O5V#F@HEoL_t(Ija`$`j)fo$M2{^Pzk4^?Z#F{5eZV63`T{A~Ih~g6 z=lAbETj!{S^^-bgg|l@4j#`j9SB&%B!K_fE&h8`FLIC(S*0X(|8M|wWoULQP%o-Ba zjVnehRjz>QMo3&SV)Qr9R_X*6s`f7+FIvUVoCM7fG1{d2VZsZidu9 z6>ON7cjC606rkkhnw>C+K7U-zGfQBbC6(3fRLcFp*3&}G^Ym?`TIx+NvJ0!3>Hd08 z>Xfq$_kA1n@u02vwoqll^kJH4R;WIKrb*RpmSa{v2mwmg>6>Qou(#JCeW<2K+2XPe z%=gf=(4^XV4Np93;jpKS6=xlgRLeC>%Eb9@N)Ag45g~kgX@>eBn8QV_~Yvn5GA&O3JdJwrbLkfc6*1DsFC0A^yg?p}w7Lw`RYRsy>!bKWtIBYoEb zU}BjHrhrvaY|Q#S!5_QH9GO)~nf{R5b@$Nj$U-T=5>&WM%J zn#Q844i9C}h+U6CwJ;_y^CAVZNfsP;-mxi5ZnrkHsx?N9(H6949aWrrrqHM)1$yRq zEP1|EMw7~{iF0ur!$aNF`IrHW8uPN*PGrXC>*Wm5L}C@o|KxS|da{Mjj20`HyeK)J zj*}lqLB$H6AMX>{^AVf5VE}nihFzcMV#Q(w(|2vS%!`tr@2{{lP2B_o#R@jb!U}8r Y0t?FAjyc_Er~m)}07*qoM6N<$g7nz5qW}N^ delta 342 zcmV-c0jd6?1O5V#F@HEoL_t(Ija`$`j)fo$M2{^Pzk4^?Z#F{5eZV63`T{A~Ih~g6 z=lAbETj!{S^^-bgg|l@4j#`j9SB&%B!K_fE&h8`FLIC(S*0X(|8M|wWoULQP%o-Ba zjVnehRjz>QMo3&SV)Qr9R_X*6s`f7+FIvUVoCM7fG1{d2VZsZidu9 z6>ON7cjC606rkkhnw>C+K7U-zGfQBbC6(3fRLcFp*3&}G^Ym?`TIx+NvJ0!3>Hd08 z>Xfq$_kA1n@u02vwoqll^kJH4R;WIKrb*RpmSa{v2mwmg>6>Qou(#JCeW<2K+2XPe z%=gf=(4^XV4Np93;jpKS6=xlgRLeC>%Eb9@N)Ag45g~kgX@>eBn8QV& get_chunk_blocks() const; static int get_index(int x, int y, int z); diff --git a/include/Cubed/gameplay/chunk_status.hpp b/include/Cubed/gameplay/chunk_status.hpp index 1a3cbd3..fc1263e 100644 --- a/include/Cubed/gameplay/chunk_status.hpp +++ b/include/Cubed/gameplay/chunk_status.hpp @@ -1,5 +1,9 @@ #pragma once #include +#include + +#include +#include struct ChunkPos { int x; int z; @@ -24,6 +28,90 @@ struct ChunkPos { }; }; +enum class Biome { + PLAIN = 0, + FOREST, + DESERT, + MOUNTAIN +}; + +struct BiomeHeightRange { + int base_y; + int amplitude; +}; + +constexpr inline std::string get_biome_str(Biome biome) { + std::string str; + using enum Biome; + switch (biome) { + case PLAIN: + str = "Plain"; + break; + case FOREST: + str = "Forest"; + break; + case DESERT: + str = "Desert"; + break; + case MOUNTAIN: + str = "Mountain"; + break; + } + return str; +}; + +inline Biome get_biome_from_noise(float temp, float humid) { + if (temp < 0.5f && humid < 0.5f) return Biome::MOUNTAIN; + if (temp < 0.5f && humid >= 0.5f) return Biome::PLAIN; + if (temp >= 0.5f && humid < 0.5f) return Biome::DESERT; + return Biome::FOREST; +} + +constexpr inline std::array get_noise_frequencies_for_biome(Biome biome) { + using enum Biome; + switch (biome) { + case PLAIN: + return {0.003f, 0.008f, 0.018f}; + case FOREST: + return {0.004f, 0.012f, 0.022f}; + case DESERT: + return {0.003f, 0.008f, 0.018f}; + case MOUNTAIN: + return {0.006f, 0.015f, 0.03f}; + } + Logger::warn("Unknown Biome"); + return {0.003f, 0.015f, 0.06f}; +} + +constexpr inline BiomeHeightRange get_biome_height_range(Biome biome) { + using enum Biome; + switch (biome) { + case PLAIN: + return {62, 4}; + case FOREST: + return {64, 8}; + case DESERT: + return {61, 8}; + case MOUNTAIN: + return {70, 70}; + } + Logger::warn("Unknown Biome"); + return {62, 4}; +} + +inline Biome safe_int_to_biome(int x) { + using enum Biome; + static const std::unordered_map INT_TO_BIOME_MAP { + {0, PLAIN}, + {1, FOREST}, + {2, DESERT}, + {3, MOUNTAIN} + }; + + auto it = INT_TO_BIOME_MAP.find(x); + CUBED_ASSERT_MSG(it != INT_TO_BIOME_MAP.end(), ":Can't Find"); + return it->second; +} diff --git a/include/Cubed/gameplay/world.hpp b/include/Cubed/gameplay/world.hpp index 67f36d4..e1d1115 100644 --- a/include/Cubed/gameplay/world.hpp +++ b/include/Cubed/gameplay/world.hpp @@ -27,7 +27,7 @@ private: std::vector m_planes; std::thread m_gen_thread; - std::mutex m_chunks_mutex; + mutable std::mutex m_chunks_mutex; std::mutex m_gen_signal_mutex; std::mutex m_new_chunk_queue_mutex; std::mutex m_delete_vbo_mutex; @@ -54,7 +54,10 @@ public: bool can_move(const AABB& player_box) const; //const BlockRenderData& get_block_render_data(int x, int y ,int z); + const std::optional& get_look_block_pos(const std::string& name) const; + const Chunk* get_chunk(const ChunkPos& pos) const; + Player& get_player(const std::string& name); void init_world(); bool is_aabb_in_frustum(const glm::vec3& center, const glm::vec3& half_extents); diff --git a/include/Cubed/tools/math_tools.hpp b/include/Cubed/tools/math_tools.hpp index 9935d70..0707f22 100644 --- a/include/Cubed/tools/math_tools.hpp +++ b/include/Cubed/tools/math_tools.hpp @@ -2,4 +2,5 @@ #include namespace Math { void extract_frustum_planes(const glm::mat4& mvp_matrix, std::vector& planes); + int get_interpolated_height(float world_x, float world_z, float biome_noise, float temp, float humid); } \ No newline at end of file diff --git a/src/debug_collector.cpp b/src/debug_collector.cpp index 0c4dee4..fb81b25 100644 --- a/src/debug_collector.cpp +++ b/src/debug_collector.cpp @@ -21,6 +21,7 @@ void DebugCollector::init_text() { Text cpu_text("cpu"); Text gpu_text("gpu"); Text opengl_version_text("opengl_version"); + Text biome_text("biome"); version_text .position(0.0f, 100.0f) .scale(0.8f) @@ -68,6 +69,10 @@ void DebugCollector::init_text() { .text("OpenGL: " + std::to_string(GLVersion.major) + "." + std::to_string(GLVersion.minor)) .scale(0.7f) .position(0.0f, 450.0f); + biome_text + .text("Biome: ") + .scale(0.8f) + .position(0.0f, 500.0f); m_texts.insert({version_text.uuid(), std::move(version_text)}); m_texts.insert({fps_text.uuid(), std::move(fps_text)}); m_texts.insert({player_pos_text.uuid(), std::move(player_pos_text)}); @@ -77,6 +82,7 @@ void DebugCollector::init_text() { m_texts.insert({cpu_text.uuid(), std::move(cpu_text)}); m_texts.insert({gpu_text.uuid(), std::move(gpu_text)}); m_texts.insert({opengl_version_text.uuid(), std::move(opengl_version_text)}); + m_texts.insert({biome_text.uuid(), std::move(biome_text)}); } std::unordered_map& DebugCollector::all_texts() { diff --git a/src/gameplay/chunk.cpp b/src/gameplay/chunk.cpp index ec8849f..1623f27 100644 --- a/src/gameplay/chunk.cpp +++ b/src/gameplay/chunk.cpp @@ -2,7 +2,10 @@ #include #include #include +#include #include + +#include Chunk::Chunk(World& world, ChunkPos chunk_pos) : m_world(world), m_chunk_pos(chunk_pos) @@ -23,7 +26,8 @@ Chunk::Chunk(Chunk&& other) : m_world(other.m_world), m_blocks(std::move(other.m_blocks)), m_dirty(other.is_dirty()), - m_vertexs_data(std::move(other.m_vertexs_data)) + m_vertexs_data(std::move(other.m_vertexs_data)), + m_biome(other.m_biome) { other.m_vbo = 0; } @@ -35,9 +39,14 @@ Chunk& Chunk::operator=(Chunk&& other) { m_blocks = std::move(other.m_blocks); m_dirty = other.is_dirty(); m_vertexs_data = std::move(other.m_vertexs_data); + m_biome = other.m_biome; return *this; } +Biome Chunk::get_biome() const { + return m_biome; +} + const std::vector& Chunk::get_chunk_blocks() const{ return m_blocks; } @@ -212,41 +221,8 @@ const std::vector& Chunk::get_vertex_data() const{ } void Chunk::init_chunk() { - m_blocks.assign(CHUCK_SIZE * CHUCK_SIZE * WORLD_SIZE_Y, 0); - for (int x = 0; x < CHUCK_SIZE; x++) { - for (int y = 0; y < 5; y++) { - for (int z = 0; z < CHUCK_SIZE; z++) { - m_blocks[get_index(x, y, z)] = 3; - } - } - } - - for (int x = 0; x < CHUCK_SIZE; x++) { - for (int z = 0; z < CHUCK_SIZE; z++) { - - float world_x = static_cast(x + m_chunk_pos.x * CHUCK_SIZE); - float world_z = static_cast(z + m_chunk_pos.z * CHUCK_SIZE); - - float noise = - 0.5f * PerlinNoise::noise(world_x * 0.01f, world_z * 0.01f, 0.5f) + - 0.25f * PerlinNoise::noise(world_x * 0.02f, world_z * 0.02f, 0.5f) + - 0.125f * PerlinNoise::noise(world_x * 0.04f, world_z * 0.04f, 0.5f); - int y_max = height * noise; - - for (int y = 5; y < y_max - 5; y++) { - m_blocks[get_index(x, y, z)] = 3; - } - for (int y = y_max - 5; y < y_max - 1; y++) { - m_blocks[get_index(x, y, z)] = 2; - } - for (int y = y_max - 1; y < y_max; y++) { - m_blocks[get_index(x, y, z)] = 1; - } - } - } - - mark_dirty(); - + resolve_biome(); + resolve_blocks(); } void Chunk::upload_to_gpu() { @@ -281,3 +257,72 @@ void Chunk::set_chunk_block(int index ,unsigned id) { } +void Chunk::resolve_biome() { + float cx = (m_chunk_pos.x + 0.5f) * CHUCK_SIZE; + float cz = (m_chunk_pos.z + 0.5f) * CHUCK_SIZE; + float temp = PerlinNoise::noise(cx * BIOME_NOISE_FREQUENCY, 0.0f, cz * BIOME_NOISE_FREQUENCY); + float humid = PerlinNoise::noise(cx * BIOME_NOISE_FREQUENCY, 1.0f, cz * BIOME_NOISE_FREQUENCY); + m_biome = get_biome_from_noise(temp, humid); +} + +void Chunk::resolve_blocks() { + m_blocks.assign(CHUCK_SIZE * CHUCK_SIZE * WORLD_SIZE_Y, 0); + for (int x = 0; x < CHUCK_SIZE; x++) { + for (int y = 0; y < 5; y++) { + for (int z = 0; z < CHUCK_SIZE; z++) { + m_blocks[get_index(x, y, z)] = 3; + } + } + } + + for (int x = 0; x < CHUCK_SIZE; x++) { + for (int z = 0; z < CHUCK_SIZE; z++) { + + float world_x = static_cast(x + m_chunk_pos.x * CHUCK_SIZE); + float world_z = static_cast(z + m_chunk_pos.z * CHUCK_SIZE); + + float biome_noise = PerlinNoise::noise( + world_x * BIOME_NOISE_FREQUENCY, + 0.5f, + world_z * BIOME_NOISE_FREQUENCY + ); + + float temp = PerlinNoise::noise(world_x * BIOME_NOISE_FREQUENCY, 0.0f, world_z * BIOME_NOISE_FREQUENCY); + float humid = PerlinNoise::noise(world_x * BIOME_NOISE_FREQUENCY, 1.0f, world_z * BIOME_NOISE_FREQUENCY); + int height = Math::get_interpolated_height(world_x, world_z, biome_noise, temp, humid); + auto biome = get_biome_from_noise(temp, humid); + for (int y = 5; y < height - 5; y++) { + m_blocks[get_index(x, y, z)] = 3; + } + if (biome == Biome::MOUNTAIN) { + for (int y = height - 5; y < height - 1; y++) { + if (y > 101) { + m_blocks[get_index(x, y, z)] = 3; + } else { + m_blocks[get_index(x, y, z)] = 2; + } + + } + if (height - 1 > 101) { + m_blocks[get_index(x, height - 1, z)] = 3; + } else { + m_blocks[get_index(x, height - 1, z)] = 1; + } + } else if (biome == Biome::DESERT) { + for (int y = height - 5; y < height; y++) { + m_blocks[get_index(x, y, z)] = 4; + } + } else { + for (int y = height - 5; y < height - 1; y++) { + m_blocks[get_index(x, y, z)] = 2; + } + for (int y = height - 1; y < height; y++) { + m_blocks[get_index(x, y, z)] = 1; + } + } + + } + } + mark_dirty(); +} + diff --git a/src/gameplay/player.cpp b/src/gameplay/player.cpp index 5a35583..fe23ab7 100644 --- a/src/gameplay/player.cpp +++ b/src/gameplay/player.cpp @@ -235,6 +235,14 @@ void Player::check_player_chunk_transition() { if (cur_pos != m_player_chunk_pos) { m_world.need_gen(); m_player_chunk_pos = cur_pos; + auto chunk = m_world.get_chunk(cur_pos); + if (chunk == nullptr) { + DebugCollector::get().report("biome", "Biome: Unknown"); + } else { + DebugCollector::get() + .report("biome", "Biome: " + get_biome_str(chunk->get_biome())); + } + } } diff --git a/src/gameplay/world.cpp b/src/gameplay/world.cpp index 76c6918..ae0d63b 100644 --- a/src/gameplay/world.cpp +++ b/src/gameplay/world.cpp @@ -80,6 +80,15 @@ const std::optional& World::get_look_block_pos(const std::string& nam } +const Chunk* World::get_chunk(const ChunkPos& pos) const { + std::lock_guard lk(m_chunks_mutex); + auto it = m_chunks.find(pos); + if (it == m_chunks.end()) { + return nullptr; + } + return &it->second; +} + Player& World::get_player(const std::string& name){ auto it = m_players.find(HASH::str(name)); if (it == m_players.end()) { diff --git a/src/map_table.cpp b/src/map_table.cpp index bff0620..52ffdfd 100644 --- a/src/map_table.cpp +++ b/src/map_table.cpp @@ -12,7 +12,8 @@ constexpr std::array BLOCK_REISTER{ "air", "grass_block", "dirt", - "stone" + "stone", + "sand" }; diff --git a/src/tools/math_tools.cpp b/src/tools/math_tools.cpp index e6e5ed3..d689868 100644 --- a/src/tools/math_tools.cpp +++ b/src/tools/math_tools.cpp @@ -1,6 +1,13 @@ #include #include + +#include + +#include +#include +#include + namespace Math { void extract_frustum_planes(const glm::mat4& mvp_matrix, std::vector& planes) { if (planes.size() != 6) { @@ -26,4 +33,46 @@ namespace Math { p = glm::normalize(p); } } + + int get_interpolated_height(float world_x, float world_z, float biome_noise, float temp, float humid) { + + + auto weight = [](float t, float h, float ct, float ch) -> float { + float dt = t - ct; + float dh = h - ch; + float dist = std::sqrt(dt*dt + dh*dh); + return std::max(0.0f, 0.5f - dist); + }; + + float w_mountain = weight(temp, humid, 0.25f, 0.25f); + float w_plain = weight(temp, humid, 0.25f, 0.75f); + float w_desert = weight(temp, humid, 0.75f, 0.25f); + float w_forest = weight(temp, humid, 0.75f, 0.75f); + // adjust transitions between chunks + float pow_n = 8.0f; // the larger n is, the purer the biome + w_mountain = std::pow(w_mountain, pow_n); + w_plain = std::pow(w_plain, pow_n); + w_desert = std::pow(w_desert, pow_n); + w_forest = std::pow(w_forest, pow_n); + + float total = w_mountain + w_plain + w_desert + w_forest; + w_mountain /= total; w_plain /= total; w_desert /= total; w_forest /= total; + + auto sample_height = [&](Biome b) -> float { + auto range = get_biome_height_range(b); + auto [f1, f2, f3] = get_noise_frequencies_for_biome(b); + float n = + 1.00f * PerlinNoise::noise(world_x * f1, 0.5f, world_z * f1) + + 0.50f * PerlinNoise::noise(world_x * f2, 0.5f, world_z * f2) + + 0.25f * PerlinNoise::noise(world_x * f3, 0.5f, world_z * f3); + n /= 1.75f; + return range.base_y + n * range.amplitude; + }; + + float h = w_mountain * sample_height(Biome::MOUNTAIN) + + w_plain * sample_height(Biome::PLAIN) + + w_desert * sample_height(Biome::DESERT) + + w_forest * sample_height(Biome::FOREST); + return static_cast(h); + } } \ No newline at end of file