summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt2
-rw-r--r--assets/images/atlas.pngbin3102 -> 3705 bytes
-rw-r--r--assets/images/atlas.ppm10492
-rw-r--r--src/Math/Common.hpp3
-rw-r--r--src/Math/Constants.hpp8
-rw-r--r--src/Math/Perlin.hpp3
-rw-r--r--src/Math/Sigmoid.hpp13
-rw-r--r--src/Math/Trig.hpp4
-rw-r--r--src/World/BiomeType.hpp22
-rw-r--r--src/World/BlockType.hpp6
-rw-r--r--src/World/Chunk.cpp64
-rw-r--r--src/World/Chunk.hpp25
-rw-r--r--src/World/Generator.cpp314
-rw-r--r--src/World/Generator.hpp59
-rw-r--r--src/World/World.cpp12
-rw-r--r--src/World/World.hpp3
16 files changed, 9558 insertions, 1472 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index af96c71..61fa09b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -43,6 +43,8 @@ add_executable(meowcraft
     src/Math/Grid.cpp
     src/Math/Perlin.cpp
     src/Compute/Queue.hpp
+    src/Math/Constants.hpp
+    src/Math/Sigmoid.hpp
 )
 target_link_libraries(meowcraft glfw GLEW::GLEW)
 
diff --git a/assets/images/atlas.png b/assets/images/atlas.png
index 1189fb6..b8b9dd7 100644
--- a/assets/images/atlas.png
+++ b/assets/images/atlas.png
Binary files differdiff --git a/assets/images/atlas.ppm b/assets/images/atlas.ppm
index 3e5ca88..df8dce7 100644
--- a/assets/images/atlas.ppm
+++ b/assets/images/atlas.ppm
@@ -1,6 +1,6 @@
 P3
 # Meowcraft atlas.ppm
-32 48
+64 64
 255
 129
 151
@@ -101,6 +101,102 @@ P3
 129
 151
 53
+129
+151
+53
+127
+149
+51
+109
+133
+36
+124
+147
+49
+124
+147
+49
+129
+151
+53
+129
+151
+53
+109
+133
+36
+129
+151
+53
+129
+151
+53
+129
+151
+53
+109
+133
+36
+129
+151
+53
+129
+151
+53
+129
+151
+53
+145
+140
+133
+118
+112
+104
+118
+112
+104
+145
+140
+133
+145
+140
+133
+145
+140
+133
+145
+140
+133
+145
+140
+133
+128
+122
+113
+118
+112
+104
+118
+112
+104
+125
+121
+113
+125
+121
+113
+136
+131
+123
+145
+140
+133
+145
+140
+133
+129
+151
+53
 124
 147
 49
@@ -197,6 +293,102 @@ P3
 129
 151
 53
+129
+151
+53
+113
+138
+40
+109
+133
+36
+113
+136
+39
+110
+133
+37
+124
+146
+48
+129
+151
+53
+109
+133
+36
+129
+151
+53
+129
+151
+53
+129
+151
+53
+109
+133
+36
+125
+148
+50
+129
+151
+53
+129
+151
+53
+145
+140
+133
+128
+122
+113
+118
+112
+104
+118
+112
+104
+128
+122
+113
+145
+140
+133
+145
+140
+133
+145
+140
+133
+145
+140
+133
+128
+122
+113
+128
+122
+113
+145
+140
+133
+145
+140
+133
+136
+131
+123
+136
+131
+123
+145
+140
+133
+129
+151
+53
 124
 147
 49
@@ -290,6 +482,102 @@ P3
 80
 46
 27
+129
+151
+53
+127
+149
+51
+111
+134
+38
+97
+122
+28
+113
+136
+38
+99
+123
+28
+107
+129
+35
+129
+151
+53
+109
+133
+36
+122
+146
+48
+128
+150
+52
+125
+148
+50
+128
+150
+52
+115
+138
+42
+121
+143
+45
+129
+151
+53
+145
+140
+133
+145
+140
+133
+145
+140
+133
+118
+112
+104
+118
+112
+104
+128
+122
+113
+145
+140
+133
+145
+140
+133
+145
+140
+133
+128
+122
+113
+128
+122
+113
+145
+140
+133
+145
+140
+133
+136
+131
+123
+136
+131
+123
+145
+140
+133
 124
 146
 48
@@ -386,6 +674,102 @@ P3
 93
 54
 35
+129
+151
+53
+129
+151
+53
+114
+137
+40
+95
+121
+27
+108
+132
+36
+65
+29
+15
+86
+109
+22
+119
+142
+45
+91
+115
+25
+102
+126
+32
+120
+142
+44
+109
+134
+36
+124
+146
+48
+88
+113
+23
+106
+131
+34
+129
+151
+53
+145
+140
+133
+157
+152
+144
+145
+140
+133
+145
+140
+133
+118
+112
+104
+118
+112
+104
+128
+122
+113
+136
+131
+123
+136
+131
+123
+136
+131
+123
+128
+122
+113
+128
+122
+113
+128
+122
+113
+136
+131
+123
+136
+131
+123
+145
+140
+133
 123
 146
 48
@@ -485,6 +869,102 @@ P3
 129
 151
 53
+123
+146
+48
+111
+135
+38
+79
+102
+17
+91
+117
+25
+65
+32
+18
+64
+89
+12
+85
+110
+21
+67
+92
+13
+93
+117
+27
+102
+126
+32
+97
+124
+28
+109
+134
+37
+85
+108
+21
+82
+108
+19
+125
+147
+49
+136
+131
+123
+157
+152
+144
+157
+152
+144
+145
+140
+133
+145
+140
+133
+118
+112
+104
+118
+112
+104
+136
+131
+123
+151
+146
+137
+157
+152
+144
+157
+152
+144
+145
+140
+133
+128
+122
+113
+128
+122
+113
+128
+122
+113
+136
+131
+123
+129
+151
+53
 124
 146
 48
@@ -578,6 +1058,102 @@ P3
 107
 62
 42
+123
+146
+48
+118
+141
+44
+101
+127
+33
+77
+102
+17
+51
+25
+11
+49
+23
+11
+62
+25
+14
+64
+90
+12
+37
+59
+3
+72
+97
+14
+74
+100
+15
+65
+32
+18
+88
+112
+22
+61
+86
+11
+74
+100
+15
+109
+133
+37
+136
+131
+123
+136
+131
+123
+145
+140
+133
+145
+140
+133
+145
+140
+133
+136
+131
+123
+118
+112
+104
+118
+112
+104
+136
+131
+123
+145
+140
+133
+157
+152
+144
+157
+152
+144
+145
+140
+133
+128
+122
+113
+128
+122
+113
+128
+122
+113
 108
 133
 35
@@ -674,6 +1250,102 @@ P3
 105
 60
 40
+100
+124
+30
+91
+115
+25
+80
+104
+19
+55
+27
+14
+56
+27
+14
+98
+54
+34
+95
+49
+32
+66
+28
+17
+79
+38
+21
+52
+23
+11
+42
+18
+7
+63
+30
+18
+63
+28
+16
+38
+58
+3
+77
+101
+17
+92
+118
+25
+128
+122
+113
+136
+131
+123
+136
+131
+123
+136
+131
+123
+136
+131
+123
+136
+131
+123
+128
+122
+113
+118
+112
+104
+118
+112
+104
+125
+121
+113
+145
+140
+133
+145
+140
+133
+145
+140
+133
+145
+140
+133
+145
+140
+133
+128
+122
+113
 125
 148
 50
@@ -770,6 +1442,102 @@ P3
 93
 54
 35
+83
+108
+20
+87
+112
+22
+64
+31
+17
+82
+45
+28
+87
+49
+31
+105
+60
+40
+105
+60
+40
+105
+60
+40
+105
+60
+40
+91
+52
+34
+78
+44
+26
+99
+55
+35
+87
+45
+26
+69
+35
+20
+84
+109
+21
+82
+107
+19
+128
+122
+113
+128
+122
+113
+136
+131
+123
+136
+131
+123
+136
+131
+123
+128
+122
+113
+157
+152
+144
+145
+140
+133
+128
+122
+113
+118
+112
+104
+125
+121
+113
+145
+140
+133
+145
+140
+133
+145
+140
+133
+145
+140
+133
+145
+140
+133
 129
 151
 53
@@ -866,6 +1634,102 @@ P3
 87
 49
 31
+55
+27
+13
+78
+38
+22
+97
+54
+34
+103
+58
+39
+93
+54
+35
+93
+54
+35
+105
+60
+40
+105
+60
+40
+93
+54
+35
+93
+54
+35
+105
+60
+40
+111
+66
+45
+109
+64
+43
+94
+50
+32
+65
+33
+19
+55
+25
+13
+145
+140
+133
+145
+140
+133
+128
+122
+113
+136
+131
+123
+136
+131
+123
+128
+122
+113
+157
+152
+144
+157
+152
+144
+145
+140
+133
+128
+122
+113
+118
+112
+104
+118
+112
+104
+136
+131
+123
+145
+140
+133
+145
+140
+133
+145
+140
+133
 129
 151
 53
@@ -962,6 +1826,102 @@ P3
 60
 31
 16
+72
+40
+22
+113
+67
+46
+117
+71
+50
+105
+60
+40
+93
+54
+35
+93
+54
+35
+93
+54
+35
+71
+38
+21
+91
+52
+34
+93
+54
+35
+109
+64
+44
+118
+72
+51
+105
+60
+40
+105
+60
+40
+93
+54
+35
+66
+35
+19
+145
+140
+133
+145
+140
+133
+145
+140
+133
+128
+122
+113
+136
+131
+123
+136
+131
+123
+145
+140
+133
+157
+152
+144
+157
+152
+144
+145
+140
+133
+128
+122
+113
+118
+112
+104
+118
+112
+104
+136
+131
+123
+145
+140
+133
+145
+140
+133
 129
 151
 53
@@ -1058,6 +2018,102 @@ P3
 66
 35
 19
+71
+38
+21
+100
+56
+37
+105
+60
+40
+95
+56
+37
+107
+62
+42
+105
+60
+40
+80
+46
+27
+66
+35
+19
+87
+49
+31
+93
+54
+35
+93
+54
+35
+105
+60
+40
+105
+60
+40
+105
+60
+40
+66
+35
+19
+66
+35
+19
+145
+140
+133
+145
+140
+133
+145
+140
+133
+128
+122
+113
+136
+131
+123
+136
+131
+123
+136
+131
+123
+145
+140
+133
+157
+152
+144
+157
+152
+144
+145
+140
+133
+145
+140
+133
+136
+131
+123
+128
+122
+113
+128
+122
+113
+128
+122
+113
 129
 151
 53
@@ -1154,279 +2210,36 @@ P3
 93
 54
 35
-109
-134
-36
-107
-132
-35
-124
-147
-49
-123
-146
-48
-100
-126
-31
-108
-132
-34
-107
-132
-34
-94
-119
-26
-91
-115
-25
-91
-115
-25
-88
-113
-22
-112
-137
-39
-117
-141
-43
-158
-184
-60
-117
-141
-43
-97
-123
-28
-81
-44
-27
-68
-36
-20
-117
 71
-50
-118
-72
-51
-105
-60
-40
-105
-60
-40
-80
-46
-27
-68
-36
-20
-68
-36
-20
-79
-42
-25
-93
-54
-35
-93
-54
-35
-81
-44
-27
+38
+21
 66
 35
 19
-93
-54
-35
-93
-54
-35
-123
-146
-48
-123
-146
-48
-123
-146
+80
+46
+27
+114
+69
 48
-103
-129
-32
-113
-138
-40
 114
-138
-40
-109
-134
-36
-124
-147
-49
-109
-134
-36
-107
-132
-35
-103
-129
-32
-102
-127
-31
-101
-127
-31
-101
-127
-31
-107
-132
-35
-107
-132
-35
-93
-54
-35
-84
-46
-28
-118
-72
-51
+69
+48
 105
 60
 40
 105
 60
 40
-93
-54
-35
-81
-44
-27
-79
-42
-25
-76
-43
-24
 66
 35
 19
-66
-35
-19
-66
-35
-19
-66
-35
-19
-68
-36
-20
-105
-60
-40
-105
-60
-40
-129
-151
-53
-129
-151
-53
-125
-148
-50
-95
-121
+80
+43
 26
-103
-128
-31
-129
-151
-53
-129
-151
-53
-124
-147
-49
-107
-132
-34
-129
-151
-53
-129
-151
-53
-109
-134
-36
-107
-132
-35
-107
-132
-35
-123
-146
-48
-129
-151
-53
-105
-60
-40
-79
-42
-25
-100
-56
-37
-105
-60
-40
-105
-60
-40
 93
 54
 35
-79
-42
-25
-100
-56
-37
-118
-72
-51
-105
-60
-40
-76
-43
-24
 93
 54
 35
@@ -1436,195 +2249,15 @@ P3
 105
 60
 40
-117
-71
-50
-105
-60
-40
-129
-151
-53
-129
-151
-53
-119
-143
-44
-98
-124
-28
-128
-150
-52
-129
-151
-53
-129
-151
-53
-107
-132
-34
-107
-132
-34
-129
-151
-53
-129
-151
-53
-129
-151
-53
-107
-132
-34
-129
-151
-53
-129
-151
-53
-129
-151
-53
-105
-60
-40
 66
 35
 19
-76
+80
 43
-24
-93
-54
-35
-93
-54
-35
-88
-50
-32
-79
-42
-25
-105
-60
-40
-116
-71
-49
-105
-60
-40
-105
-60
-40
-93
-54
-35
+26
 93
 54
 35
-105
-60
-40
-105
-60
-40
-105
-60
-40
-129
-151
-53
-129
-151
-53
-127
-149
-51
-109
-133
-36
-124
-147
-49
-124
-147
-49
-129
-151
-53
-129
-151
-53
-109
-133
-36
-129
-151
-53
-129
-151
-53
-129
-151
-53
-109
-133
-36
-129
-151
-53
-129
-151
-53
-129
-151
-53
-145
-140
-133
-118
-112
-104
-118
-112
-104
-145
-140
-133
-145
-140
-133
-145
-140
-133
-145
-140
-133
-145
-140
-133
-128
-122
-113
-118
-112
-104
-118
-112
-104
-125
-121
-113
-125
-121
-113
 136
 131
 123
@@ -1634,807 +2267,102 @@ P3
 145
 140
 133
-129
-151
-53
-129
-151
-53
-113
-138
-40
-109
-133
-36
-113
-136
-39
-110
-133
-37
-124
-146
-48
-129
-151
-53
-109
-133
-36
-129
-151
-53
-129
-151
-53
-129
-151
-53
-109
-133
-36
-125
-148
-50
-129
-151
-53
-129
-151
-53
-145
-140
-133
-128
-122
-113
-118
-112
-104
-118
-112
-104
-128
-122
-113
-145
-140
-133
-145
-140
-133
-145
-140
-133
-145
-140
-133
 128
 122
 113
-128
-122
-113
-145
-140
-133
-145
-140
-133
 136
 131
 123
 136
 131
 123
-145
-140
-133
-129
-151
-53
-127
-149
-51
-111
-134
-38
-97
-122
-28
-113
-136
-38
-99
-123
-28
-107
-129
-35
-129
-151
-53
-109
-133
-36
-122
-146
-48
-128
-150
-52
-125
-148
-50
-128
-150
-52
-115
-138
-42
-121
-143
-45
-129
-151
-53
-145
-140
-133
-145
-140
-133
-145
-140
-133
-118
-112
-104
-118
-112
-104
-128
-122
-113
-145
-140
-133
-145
-140
-133
-145
-140
-133
-128
-122
-113
-128
-122
-113
-145
-140
-133
-145
-140
-133
 136
 131
 123
 136
 131
 123
-145
-140
-133
-129
-151
-53
-129
-151
-53
-114
-137
-40
-95
-121
-27
-108
-132
-36
-65
-29
-15
-86
-109
-22
-119
-142
-45
-91
-115
-25
-102
-126
-32
-120
-142
-44
-109
-134
-36
-124
-146
-48
-88
+128
+122
 113
-23
-106
-131
-34
-129
-151
-53
 145
 140
 133
-157
-152
-144
 145
 140
 133
 145
 140
 133
-118
-112
-104
-118
-112
-104
-128
-122
-113
 136
 131
 123
 136
 131
 123
-136
-131
-123
-128
-122
-113
 128
 122
 113
 128
 122
 113
-136
-131
-123
-136
-131
-123
-145
-140
-133
-129
-151
-53
-123
-146
-48
-111
-135
-38
-79
-102
-17
-91
-117
-25
-65
-32
-18
-64
-89
-12
-85
-110
-21
-67
-92
-13
-93
-117
-27
-102
-126
-32
-97
-124
-28
 109
 134
-37
-85
-108
-21
-82
-108
-19
-125
+36
+107
+132
+35
+124
 147
 49
-136
-131
-123
-157
-152
-144
-157
-152
-144
-145
-140
-133
-145
-140
-133
-118
-112
-104
-118
-112
-104
-136
-131
-123
-151
-146
-137
-157
-152
-144
-157
-152
-144
-145
-140
-133
-128
-122
-113
-128
-122
-113
-128
-122
-113
-136
-131
-123
 123
 146
 48
-118
-141
-44
-101
-127
-33
-77
-102
-17
-51
-25
-11
-49
-23
-11
-62
-25
-14
-64
-90
-12
-37
-59
-3
-72
-97
-14
-74
-100
-15
-65
-32
-18
-88
-112
-22
-61
-86
-11
-74
 100
-15
-109
-133
-37
-136
-131
-123
-136
-131
-123
-145
-140
-133
-145
-140
-133
-145
-140
-133
-136
-131
-123
-118
-112
-104
-118
-112
-104
-136
-131
-123
-145
-140
-133
-157
-152
-144
-157
-152
-144
-145
-140
-133
-128
-122
-113
-128
-122
-113
-128
-122
-113
-100
-124
-30
+126
+31
+108
+132
+34
+107
+132
+34
+94
+119
+26
 91
 115
 25
-80
-104
-19
-55
-27
-14
-56
-27
-14
-98
-54
-34
-95
-49
-32
-66
-28
-17
-79
-38
-21
-52
-23
-11
-42
-18
-7
-63
-30
-18
-63
-28
-16
-38
-58
-3
-77
-101
-17
-92
-118
+91
+115
 25
-128
-122
-113
-136
-131
-123
-136
-131
-123
-136
-131
-123
-136
-131
-123
-136
-131
-123
-128
-122
-113
-118
-112
-104
-118
-112
-104
-125
-121
-113
-145
-140
-133
-145
-140
-133
-145
-140
-133
-145
-140
-133
-145
-140
-133
-128
-122
+88
 113
-83
-108
-20
-87
-112
 22
-64
-31
-17
-82
-45
-28
-87
-49
-31
-105
-60
-40
-105
-60
-40
-105
-60
-40
-105
-60
-40
-91
-52
-34
-78
-44
-26
-99
-55
-35
-87
-45
-26
-69
-35
-20
-84
-109
-21
-82
-107
-19
-128
-122
-113
-128
-122
-113
-136
-131
-123
-136
-131
-123
-136
-131
-123
-128
-122
-113
-157
-152
-144
-145
-140
-133
-128
-122
-113
-118
 112
-104
-125
-121
-113
-145
-140
-133
-145
-140
-133
-145
-140
-133
-145
-140
-133
-145
-140
-133
-55
-27
-13
-78
-38
-22
-97
-54
-34
-103
-58
+137
 39
-93
-54
-35
-93
-54
-35
-105
-60
-40
-105
-60
-40
-93
-54
-35
-93
-54
-35
-105
+117
+141
+43
+158
+184
 60
-40
-111
-66
-45
-109
-64
+117
+141
 43
-94
-50
-32
-65
-33
-19
-55
-25
-13
-145
-140
-133
-145
-140
-133
-128
-122
-113
-136
-131
-123
-136
-131
-123
-128
-122
-113
-157
-152
-144
-157
-152
-144
-145
-140
-133
-128
-122
-113
-118
-112
-104
-118
-112
-104
-136
-131
+97
 123
-145
-140
-133
-145
-140
-133
-145
-140
-133
-72
-40
-22
-113
-67
-46
+28
+81
+44
+27
+68
+36
+20
 117
 71
 50
-105
-60
-40
-93
-54
-35
-93
-54
-35
-93
-54
-35
-71
-38
-21
-91
-52
-34
-93
-54
-35
-109
-64
-44
 118
 72
 51
@@ -2444,252 +2372,36 @@ P3
 105
 60
 40
-93
-54
-35
-66
-35
-19
-145
-140
-133
-145
-140
-133
-145
-140
-133
-128
-122
-113
-136
-131
-123
-136
-131
-123
-145
-140
-133
-157
-152
-144
-157
-152
-144
-145
-140
-133
-128
-122
-113
-118
-112
-104
-118
-112
-104
-136
-131
-123
-145
-140
-133
-145
-140
-133
-71
-38
-21
-100
-56
-37
-105
-60
-40
-95
-56
-37
-107
-62
-42
-105
-60
-40
 80
 46
 27
-66
-35
-19
-87
-49
-31
+68
+36
+20
+68
+36
+20
+79
+42
+25
 93
 54
 35
 93
 54
 35
-105
-60
-40
-105
-60
-40
-105
-60
-40
-66
-35
-19
-66
-35
-19
-145
-140
-133
-145
-140
-133
-145
-140
-133
-128
-122
-113
-136
-131
-123
-136
-131
-123
-136
-131
-123
-145
-140
-133
-157
-152
-144
-157
-152
-144
-145
-140
-133
-145
-140
-133
-136
-131
-123
-128
-122
-113
-128
-122
-113
-128
-122
-113
-71
-38
-21
-66
-35
-19
-80
-46
+81
+44
 27
-114
-69
-48
-114
-69
-48
-105
-60
-40
-105
-60
-40
 66
 35
 19
-80
-43
-26
-93
-54
-35
 93
 54
 35
 93
 54
 35
-105
-60
-40
-66
-35
-19
-80
-43
-26
-93
-54
-35
-136
-131
-123
-145
-140
-133
-145
-140
-133
-128
-122
-113
-136
-131
-123
-136
-131
-123
-136
-131
-123
-136
-131
-123
-128
-122
-113
-145
-140
-133
-145
-140
-133
-145
-140
-133
-136
-131
-123
-136
-131
-123
-128
-122
-113
-128
-122
-113
 81
 44
 27
@@ -2786,6 +2498,102 @@ P3
 128
 122
 113
+123
+146
+48
+123
+146
+48
+123
+146
+48
+103
+129
+32
+113
+138
+40
+114
+138
+40
+109
+134
+36
+124
+147
+49
+109
+134
+36
+107
+132
+35
+103
+129
+32
+102
+127
+31
+101
+127
+31
+101
+127
+31
+107
+132
+35
+107
+132
+35
+93
+54
+35
+84
+46
+28
+118
+72
+51
+105
+60
+40
+105
+60
+40
+93
+54
+35
+81
+44
+27
+79
+42
+25
+76
+43
+24
+66
+35
+19
+66
+35
+19
+66
+35
+19
+66
+35
+19
+68
+36
+20
+105
+60
+40
+105
+60
+40
 93
 54
 35
@@ -2882,6 +2690,102 @@ P3
 128
 122
 113
+129
+151
+53
+129
+151
+53
+125
+148
+50
+95
+121
+26
+103
+128
+31
+129
+151
+53
+129
+151
+53
+124
+147
+49
+107
+132
+34
+129
+151
+53
+129
+151
+53
+109
+134
+36
+107
+132
+35
+107
+132
+35
+123
+146
+48
+129
+151
+53
+105
+60
+40
+79
+42
+25
+100
+56
+37
+105
+60
+40
+105
+60
+40
+93
+54
+35
+79
+42
+25
+100
+56
+37
+118
+72
+51
+105
+60
+40
+76
+43
+24
+93
+54
+35
+93
+54
+35
+105
+60
+40
+117
+71
+50
+105
+60
+40
 105
 60
 40
@@ -2978,6 +2882,102 @@ P3
 134
 129
 123
+129
+151
+53
+129
+151
+53
+119
+143
+44
+98
+124
+28
+128
+150
+52
+129
+151
+53
+129
+151
+53
+107
+132
+34
+107
+132
+34
+129
+151
+53
+129
+151
+53
+129
+151
+53
+107
+132
+34
+129
+151
+53
+129
+151
+53
+129
+151
+53
+105
+60
+40
+66
+35
+19
+76
+43
+24
+93
+54
+35
+93
+54
+35
+88
+50
+32
+79
+42
+25
+105
+60
+40
+116
+71
+49
+105
+60
+40
+105
+60
+40
+93
+54
+35
+93
+54
+35
+105
+60
+40
+105
+60
+40
+105
+60
+40
 105
 60
 40
@@ -3170,6 +3170,102 @@ P3
 93
 191
 225
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+236
+241
+247
+225
+230
+236
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+236
+241
+247
+236
+241
+247
+249
+250
+252
 255
 208
 144
@@ -3266,6 +3362,102 @@ P3
 120
 232
 236
+236
+241
+247
+236
+241
+247
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+236
+241
+247
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+236
+241
+247
+249
+250
+252
+249
+250
+252
+249
+250
+252
+236
+241
+247
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+236
+241
+247
+236
+241
+247
+249
+250
+252
 255
 208
 144
@@ -3362,6 +3554,102 @@ P3
 120
 232
 236
+249
+250
+252
+249
+250
+252
+236
+241
+247
+225
+230
+236
+249
+250
+252
+249
+250
+252
+249
+250
+252
+236
+241
+247
+225
+230
+236
+236
+241
+247
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+236
+241
+247
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+236
+241
+247
+236
+241
+247
+249
+250
+252
+249
+250
+252
+236
+241
+247
+236
+241
+247
+249
+250
+252
+236
+241
+247
+249
+250
+252
+249
+250
+252
+236
+241
+247
+225
+230
+236
 251
 199
 142
@@ -3458,6 +3746,102 @@ P3
 95
 199
 228
+249
+250
+252
+249
+250
+252
+249
+250
+252
+236
+241
+247
+249
+250
+252
+249
+250
+252
+249
+250
+252
+236
+241
+247
+236
+241
+247
+225
+230
+236
+236
+241
+247
+236
+241
+247
+249
+250
+252
+249
+250
+252
+236
+241
+247
+249
+250
+252
+236
+241
+247
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+236
+241
+247
+225
+230
+236
+249
+250
+252
+249
+250
+252
+249
+250
+252
+236
+241
+247
 251
 199
 142
@@ -3554,6 +3938,102 @@ P3
 93
 191
 225
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+236
+241
+247
+225
+230
+236
+225
+230
+236
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+225
+230
+236
+236
+241
+247
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+236
+241
+247
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+236
+241
+247
+249
+250
+252
+249
+250
+252
+249
+250
+252
+236
+241
+247
 251
 199
 142
@@ -3650,6 +4130,102 @@ P3
 93
 191
 225
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+236
+241
+247
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+236
+241
+247
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+225
+230
+236
+225
+230
+236
+236
+241
+247
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+236
+241
+247
+236
+241
+247
+236
+241
+247
+225
+230
+236
+249
+250
+252
+249
+250
+252
 251
 199
 142
@@ -3746,6 +4322,102 @@ P3
 84
 166
 219
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+236
+241
+247
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+236
+241
+247
+236
+241
+247
+249
+250
+252
+249
+250
+252
+225
+230
+236
+225
+230
+236
+55
+27
+14
+236
+241
+247
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+236
+241
+247
+236
+241
+247
+63
+28
+16
+236
+241
+247
+249
+250
+252
+249
+250
+252
 251
 199
 142
@@ -3842,6 +4514,102 @@ P3
 80
 154
 217
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+236
+241
+247
+225
+230
+236
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+225
+230
+236
+225
+230
+236
+236
+241
+247
+236
+241
+247
+225
+230
+236
+64
+31
+17
+79
+42
+25
+80
+43
+26
+236
+241
+247
+249
+250
+252
+249
+250
+252
+249
+250
+252
+236
+241
+247
+225
+230
+236
+55
+25
+13
+87
+45
+26
+69
+35
+20
+225
+230
+236
+236
+241
+247
 251
 199
 142
@@ -3938,6 +4706,102 @@ P3
 88
 177
 223
+236
+241
+247
+236
+241
+247
+236
+241
+247
+236
+241
+247
+236
+241
+247
+225
+230
+236
+225
+230
+236
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+236
+241
+247
+249
+250
+252
+249
+250
+252
+225
+230
+236
+55
+27
+13
+78
+38
+22
+97
+54
+34
+103
+58
+39
+93
+54
+35
+80
+43
+26
+236
+241
+247
+236
+241
+247
+225
+230
+236
+225
+230
+236
+55
+25
+13
+93
+54
+35
+93
+54
+35
+94
+50
+32
+65
+33
+19
+55
+25
+13
 242
 185
 131
@@ -4034,6 +4898,102 @@ P3
 90
 184
 225
+225
+230
+236
+249
+250
+252
+249
+250
+252
+225
+230
+236
+225
+230
+236
+249
+250
+252
+249
+250
+252
+236
+241
+247
+249
+250
+252
+249
+250
+252
+249
+250
+252
+236
+241
+247
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+72
+40
+22
+113
+67
+46
+117
+71
+50
+105
+60
+40
+93
+54
+35
+93
+54
+35
+80
+43
+26
+66
+35
+19
+55
+25
+13
+55
+25
+13
+118
+72
+51
+118
+72
+51
+105
+60
+40
+105
+60
+40
+93
+54
+35
+66
+35
+19
 242
 185
 131
@@ -4130,6 +5090,102 @@ P3
 112
 213
 232
+249
+250
+252
+236
+241
+247
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+236
+241
+247
+236
+241
+247
+236
+241
+247
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+71
+38
+21
+100
+56
+37
+105
+60
+40
+95
+56
+37
+107
+62
+42
+105
+60
+40
+80
+46
+27
+66
+35
+19
+87
+49
+31
+93
+54
+35
+93
+54
+35
+105
+60
+40
+105
+60
+40
+105
+60
+40
+66
+35
+19
+66
+35
+19
 255
 224
 152
@@ -4226,6 +5282,102 @@ P3
 120
 232
 236
+236
+241
+247
+249
+250
+252
+236
+241
+247
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+236
+241
+247
+225
+230
+236
+236
+241
+247
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+71
+38
+21
+66
+35
+19
+80
+46
+27
+114
+69
+48
+114
+69
+48
+105
+60
+40
+105
+60
+40
+66
+35
+19
+80
+43
+26
+93
+54
+35
+93
+54
+35
+93
+54
+35
+105
+60
+40
+66
+35
+19
+80
+43
+26
+93
+54
+35
 255
 224
 152
@@ -4322,6 +5474,102 @@ P3
 93
 191
 225
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+225
+230
+236
+249
+250
+252
+236
+241
+247
+236
+241
+247
+236
+241
+247
+236
+241
+247
+249
+250
+252
+225
+230
+236
+249
+250
+252
+249
+250
+252
+249
+250
+252
+236
+241
+247
+81
+44
+27
+68
+36
+20
+117
+71
+50
+118
+72
+51
+105
+60
+40
+105
+60
+40
+80
+46
+27
+68
+36
+20
+68
+36
+20
+79
+42
+25
+93
+54
+35
+93
+54
+35
+81
+44
+27
+66
+35
+19
+93
+54
+35
+93
+54
+35
 251
 199
 142
@@ -4418,6 +5666,102 @@ P3
 112
 217
 232
+249
+250
+252
+249
+250
+252
+249
+250
+252
+236
+241
+247
+236
+241
+247
+249
+250
+252
+249
+250
+252
+249
+250
+252
+236
+241
+247
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+236
+241
+247
+236
+241
+247
+225
+230
+236
+93
+54
+35
+84
+46
+28
+118
+72
+51
+105
+60
+40
+105
+60
+40
+93
+54
+35
+81
+44
+27
+79
+42
+25
+76
+43
+24
+66
+35
+19
+66
+35
+19
+66
+35
+19
+66
+35
+19
+68
+36
+20
+105
+60
+40
+105
+60
+40
 255
 216
 148
@@ -4514,6 +5858,102 @@ P3
 112
 217
 232
+249
+250
+252
+249
+250
+252
+249
+250
+252
+236
+241
+247
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+236
+241
+247
+236
+241
+247
+105
+60
+40
+79
+42
+25
+100
+56
+37
+105
+60
+40
+105
+60
+40
+93
+54
+35
+79
+42
+25
+100
+56
+37
+118
+72
+51
+105
+60
+40
+76
+43
+24
+93
+54
+35
+93
+54
+35
+105
+60
+40
+117
+71
+50
+105
+60
+40
 255
 216
 148
@@ -4610,3 +6050,6243 @@ P3
 90
 184
 223
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+249
+250
+252
+236
+241
+247
+105
+60
+40
+66
+35
+19
+76
+43
+24
+93
+54
+35
+93
+54
+35
+88
+50
+32
+79
+42
+25
+105
+60
+40
+116
+71
+49
+105
+60
+40
+105
+60
+40
+93
+54
+35
+93
+54
+35
+105
+60
+40
+105
+60
+40
+105
+60
+40
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
+192
+0
+255
diff --git a/src/Math/Common.hpp b/src/Math/Common.hpp
index 94840b1..1ea75f2 100644
--- a/src/Math/Common.hpp
+++ b/src/Math/Common.hpp
@@ -3,4 +3,5 @@
 #include "Vector.hpp"
 #include "Matrix.hpp"
 #include "Rotation.hpp"
-#include "Trig.hpp"
\ No newline at end of file
+#include "Trig.hpp"
+#include "Constants.hpp"
\ No newline at end of file
diff --git a/src/Math/Constants.hpp b/src/Math/Constants.hpp
new file mode 100644
index 0000000..9c62e94
--- /dev/null
+++ b/src/Math/Constants.hpp
@@ -0,0 +1,8 @@
+#pragma once
+
+namespace Math {
+
+constexpr double PI = 3.14159265358979323846;
+constexpr double E = 2.71828182845904523536;
+
+}
\ No newline at end of file
diff --git a/src/Math/Perlin.hpp b/src/Math/Perlin.hpp
index c31697b..17d33fd 100644
--- a/src/Math/Perlin.hpp
+++ b/src/Math/Perlin.hpp
@@ -16,6 +16,7 @@ struct Noise {
 
     uint octaves = 3;
     float persistence = 0.3f;
+    float lacunarity = 2.0f;
 
     float at(Vector<D> pos) const {
         float result = 0;
@@ -27,7 +28,7 @@ struct Noise {
             result += raw((pos + offset).abs() / scale * frequency) * amplitude;
             max += amplitude;
 
-            frequency *= 2;
+            frequency *= lacunarity;
             amplitude *= persistence;
         }
 
diff --git a/src/Math/Sigmoid.hpp b/src/Math/Sigmoid.hpp
new file mode 100644
index 0000000..f2fa009
--- /dev/null
+++ b/src/Math/Sigmoid.hpp
@@ -0,0 +1,13 @@
+#pragma once
+
+#include <cmath>
+#include "Constants.hpp"
+
+namespace Math {
+
+template <typename T>
+T sigmoid(T x) {
+    return 1 / (1 + std::pow(E, -x));
+}
+
+}
diff --git a/src/Math/Trig.hpp b/src/Math/Trig.hpp
index c64e2f2..2a415f5 100644
--- a/src/Math/Trig.hpp
+++ b/src/Math/Trig.hpp
@@ -1,8 +1,8 @@
 #pragma once
 
-namespace Math {
+#include "Constants.hpp"
 
-constexpr double PI = 3.14159265358979323846;
+namespace Math {
 
 template<typename T>
 T radians(T degrees) {
diff --git a/src/World/BiomeType.hpp b/src/World/BiomeType.hpp
index 026b3ef..2e3d8c6 100644
--- a/src/World/BiomeType.hpp
+++ b/src/World/BiomeType.hpp
@@ -8,34 +8,32 @@ namespace MC::World {
 class BiomeType {
 public:
     enum Value : uint8_t {
-        Forest,
         Plains,
+        Forest,
+        Alpine,
         Desert,
+        Jungle,
+        Beach,
+        River,
         Ocean,
     };
 
-    static constexpr const size_t Size = 4;
+    static constexpr uint8_t Size = Ocean + 1;
 
-    BiomeType() = default;
-    BiomeType(Value biome) : m_biome(biome) {}
+    BiomeType() : m_biome(Plains) {}
+    BiomeType(const Value biome) : m_biome(biome) {}
 
     operator Value() const { return m_biome; }
 
     static std::vector<BiomeType> all() {
-        return {
-            Plains, Forest, Desert, Ocean
-        };
+        return { Plains, Forest, Alpine, Desert, Jungle, Beach, River, Ocean };
     }
 
     static std::vector<BiomeType> all_ground() {
-        return {
-            Plains, Forest, Desert
-        };
+        return { Plains, Forest, Alpine, Desert, Jungle, Beach };
     }
 
 private:
-
-
     Value m_biome;
 };
 
diff --git a/src/World/BlockType.hpp b/src/World/BlockType.hpp
index 65afe0d..dcb8e44 100644
--- a/src/World/BlockType.hpp
+++ b/src/World/BlockType.hpp
@@ -13,12 +13,13 @@ public:
         Grass,
         Stone,
         Sand,
+        Snow,
         Water,
     };
 
-    static constexpr const size_t Size = 6;
+    static constexpr uint8_t Size = Water + 1;
 
-    BlockType() = default;
+    BlockType() : m_block(Air) {}
     BlockType(Value block) : m_block(block) {}
 
     operator Value() const { return m_block; }
@@ -30,6 +31,7 @@ public:
             Grass,
             Stone,
             Sand,
+            Snow,
             Water,
         };
     }
diff --git a/src/World/Chunk.cpp b/src/World/Chunk.cpp
index 1874950..9642fa9 100644
--- a/src/World/Chunk.cpp
+++ b/src/World/Chunk.cpp
@@ -4,11 +4,11 @@
 namespace MC::World {
 
 void Chunk::set(uint32_t x, uint32_t y, uint32_t z, BlockData data) {
-    m_blocks[pos(x, y, z)] = data;
+    m_blocks.at(pos(x, y, z)) = data;
 }
 
-Chunk::BlockData Chunk::get(uint32_t x, uint32_t y, uint32_t z) {
-    return m_blocks[pos(x, y, z)];
+Chunk::BlockData Chunk::get(uint32_t x, uint32_t y, uint32_t z) const {
+    return m_blocks.at(pos(x, y, z));
 }
 
 GFX::Mesh Chunk::mesh() {
@@ -17,9 +17,9 @@ GFX::Mesh Chunk::mesh() {
     std::vector<Vector<2>> tex_coords{};
     std::vector<uint32_t> indices{};
 
-    for (int x = 0; x < Chunk::Width; x++) {
-        for (int y = 0; y < Chunk::Height; y++) {
-            for (int z = 0; z < Chunk::Width; z++) {
+    for (int x = 0; x < Width; x++) {
+        for (int y = 0; y < Height; y++) {
+            for (int z = 0; z < Width; z++) {
                 auto type = get(x, y, z).type;
                 if (type == BlockType::Air) {
                     continue;
@@ -31,8 +31,8 @@ GFX::Mesh Chunk::mesh() {
                     }
 
                     auto side_positions = side.face();
-                    auto side_normals = Chunk::face_normals(side);
-                    auto side_tex_coords = Chunk::face_tex_coords(type, side);
+                    auto side_normals = face_normals(side);
+                    auto side_tex_coords = face_tex_coords(type, side);
 
                     for (auto& position : side_positions) {
                         position = position + Vector<3>{static_cast<float>(x), static_cast<float>(y), static_cast<float>(z)};
@@ -87,9 +87,9 @@ bool Chunk::is_face_visible(uint32_t x, uint32_t y, uint32_t z, BlockSide side)
     };
 
     if (
-        neighbor_pos.x() >= Chunk::Width || neighbor_pos.x() < 0 ||
-        neighbor_pos.y() >= Chunk::Height || neighbor_pos.y() < 0 ||
-        neighbor_pos.z() >= Chunk::Width || neighbor_pos.z() < 0
+        neighbor_pos.x() >= Width || neighbor_pos.x() < 0 ||
+        neighbor_pos.y() >= Height || neighbor_pos.y() < 0 ||
+        neighbor_pos.z() >= Width || neighbor_pos.z() < 0
     ) {
         return true;
     }
@@ -103,8 +103,8 @@ bool Chunk::is_face_visible(uint32_t x, uint32_t y, uint32_t z, BlockSide side)
 }
 
 std::array<Vector<2>, 4> Chunk::face_tex_coords(BlockType type, BlockSide side) {
-    uint8_t atlas_width = 2;
-    uint8_t atlas_height = 3;
+    uint8_t atlas_width = 4;
+    uint8_t atlas_height = 4;
 
     float width_step = 1.0f / atlas_width;
     float height_step = 1.0f / atlas_height;
@@ -125,22 +125,34 @@ std::array<Vector<2>, 4> Chunk::face_tex_coords(BlockType type, BlockSide side)
             return block_coords(1, 0);
         case BlockType::Grass:
             switch (side) {
-                case BlockSide::Front:
-                case BlockSide::Back:
-                case BlockSide::Left:
-                case BlockSide::Right:
-                    return block_coords(0, 1);
-                case BlockSide::Top:
-                    return block_coords(0, 0);
-                case BlockSide::Bottom:
-                    return block_coords(1, 0);
+            case BlockSide::Front:
+            case BlockSide::Back:
+            case BlockSide::Left:
+            case BlockSide::Right:
+                return block_coords(2, 0);
+            case BlockSide::Bottom:
+                return block_coords(1, 0);
+            case BlockSide::Top:
+                return block_coords(0, 0);
             }
         case BlockType::Stone:
-            return block_coords(1, 1);
+            return block_coords(3, 0);
         case BlockType::Sand:
-            return block_coords(0, 2);
+            return block_coords(0, 1);
         case BlockType::Water:
-            return block_coords(1, 2);
+            return block_coords(1, 1);
+        case BlockType::Snow:
+            switch (side) {
+            case BlockSide::Front:
+            case BlockSide::Back:
+            case BlockSide::Left:
+            case BlockSide::Right:
+                return block_coords(3, 1);
+            case BlockSide::Bottom:
+                return block_coords(1, 0);
+            case BlockSide::Top:
+                return block_coords(2, 1);
+            }
         case BlockType::Air:
             return {};
     }
@@ -159,7 +171,7 @@ std::array<Vector<3>, 4> Chunk::face_normals(BlockSide side) {
 }
 
 uint64_t Chunk::pos(uint32_t x, uint32_t y, uint32_t z) {
-    return x + Chunk::Width * y + Chunk::Width * Chunk::Height * z;
+    return x + Width * y + Width * Height * z;
 }
 
 }
diff --git a/src/World/Chunk.hpp b/src/World/Chunk.hpp
index 2b0379c..d200039 100644
--- a/src/World/Chunk.hpp
+++ b/src/World/Chunk.hpp
@@ -1,29 +1,36 @@
 #pragma once
 
 #include <cstdint>
-#include <optional>
+#include "BiomeType.hpp"
 #include "BlockType.hpp"
 #include "../GFX/Mesh.hpp"
 #include "BlockSide.hpp"
-#include "../GFX/Binder.hpp"
 
 namespace MC::World {
 
 class Chunk {
 public:
-    static constexpr const uint32_t Width = 16;
-    static constexpr const uint32_t Height = 128;
+    static constexpr uint32_t Width = 16;
+    static constexpr uint32_t Height = 128;
 
     Chunk(int64_t x, int64_t y)
-        : m_blocks{Chunk::Width * Chunk::Height * Chunk::Width, {BlockType::Air}},
-        m_position{(float)x * Chunk::Width, 0.0f, (float)y * Chunk::Width} {};
+        : m_blocks{Width * Height * Width, {BlockType::Air}},
+        m_position{(float)x * Width, 0.0f, (float)y * Width} {}
 
     struct BlockData {
         BlockType type;
     };
 
-    void set(uint32_t x, uint32_t y, uint32_t z, BlockData type);
-    BlockData get(uint32_t x, uint32_t y, uint32_t z);
+    void set(uint32_t x, uint32_t y, uint32_t z, BlockData data);
+    BlockData get(uint32_t x, uint32_t y, uint32_t z) const;
+
+    struct Details {
+        Matrix<Width, Width> landmass_values{};
+        Matrix<Width, Width> hill_values{};
+        Matrix<Width, Width, BiomeType> biome_values{};
+    };
+    void set_details(const Details& details) { m_details = details; }
+    Details& details(){ return m_details; }
 
     Vector<3> position();
     GFX::Mesh mesh();
@@ -37,6 +44,8 @@ private:
 
     Vector<3> m_position;
     std::vector<BlockData> m_blocks;
+
+    Details m_details;
 };
 
 }
diff --git a/src/World/Generator.cpp b/src/World/Generator.cpp
index e8b3bbd..f528278 100644
--- a/src/World/Generator.cpp
+++ b/src/World/Generator.cpp
@@ -1,30 +1,320 @@
 #include "Generator.hpp"
-#include "../Math/Perlin.hpp"
+#include "../Math/Interpolation.hpp"
+#include "../Math/Sigmoid.hpp"
 
 namespace MC::World {
 
 Chunk Generator::generate(int64_t chunk_x, int64_t chunk_y) {
     Chunk chunk(chunk_x, chunk_y);
 
-    Math::Perlin::Noise<3> noise{.scale=20.0f, .octaves=2};
+    auto landmass_map = generate_landmass_map(chunk_x, chunk_y);
+    auto hill_map = generate_hill_map(chunk_x, chunk_y);
+    auto height_map = generate_height_map(landmass_map, hill_map, chunk_x, chunk_y);
+
+    auto biome_map = generate_biome_map(landmass_map, hill_map, height_map, chunk_x, chunk_y);
+    auto terrain_map = generate_terrain(height_map, chunk_x, chunk_y);
+
+    decorate_soil(chunk, biome_map, terrain_map);
+
+    chunk.set_details({{landmass_map.map}, {hill_map.map}, {biome_map.map}});
+
+    return chunk;
+}
+
+Generator::ChunkMap2D<float> Generator::generate_landmass_map(int64_t chunk_x, int64_t chunk_y) {
+    ChunkMap2D<float> landmass_map{};
+
+    for (uint x = 0; x < Chunk::Width; x++) {
+        for (uint y = 0; y < Chunk::Width; y++) {
+            landmass_map.set(x, y, get_landmass(chunk_position_to_world_vector(chunk_x, chunk_y, x, y)));
+        }
+    }
+
+    return landmass_map;
+}
+
+Generator::ChunkMap2D<float> Generator::generate_hill_map(int64_t chunk_x, int64_t chunk_y) {
+    ChunkMap2D<float> hill_map{};
+
+    for (uint x = 0; x < Chunk::Width; x++) {
+        for (uint y = 0; y < Chunk::Width; y++) {
+            hill_map.set(x, y, get_hill(chunk_position_to_world_vector(chunk_x, chunk_y, x, y)));
+        }
+    }
+
+    return hill_map;
+}
+
+Generator::ChunkMap2D<float> Generator::generate_height_map(ChunkMap2D<float>& landmass_map, ChunkMap2D<float>& hill_map, int64_t chunk_x, int64_t chunk_y) {
+    ChunkMap2D<float> height_map{};
 
     for (uint x = 0; x < Chunk::Width; x++) {
+        for (uint y = 0; y < Chunk::Width; y++) {
+            auto landmass_effect = landmass_map.get(x, y);
+            auto hill_effect = hill_map.get(x, y);
+
+            auto hill = hill_effect * landmass_effect * 1.4 - 0.4;
+            auto landmass = landmass_effect * 0.6 + 0.4;
+
+            auto height = (hill + landmass) / 2.0f;
+
+            height_map.set(x, y, height);
+        }
+    }
+
+    return height_map;
+}
+
+Generator::ChunkMap2D<BiomeType> Generator::generate_biome_map(ChunkMap2D<float>& landmass_map, ChunkMap2D<float>& hill_map, ChunkMap2D<float>& height_map, int64_t chunk_x, int64_t chunk_y) {
+    ChunkMap2D<BiomeType> biome_map{};
+
+    for (uint x = 0; x < Chunk::Width; x++) {
+        for (uint y = 0; y < Chunk::Width; y++) {
+            float landmass = landmass_map.get(x, y);
+            float hill = hill_map.get(x, y);
+
+            auto world_pos = chunk_position_to_world_vector(chunk_x, chunk_y, x, y);
+            float temperature = get_temperature(world_pos);
+            float humidity = get_humidity(world_pos);
+
+            HillSlice hill_slice;
+            if (hill > 0.9) { hill_slice = HillSlice::Mountain; }
+            else if (hill > 0.33) { hill_slice = HillSlice::Middle; }
+            else { hill_slice = HillSlice::Valley; }
+
+            LandmassSlice landmass_slice;
+            if (landmass > 0.8) { landmass_slice = LandmassSlice::Land; }
+            else if (landmass > 0.45) { landmass_slice = LandmassSlice::Beach; }
+            else { landmass_slice = LandmassSlice::Ocean; }
+
+            TemperatureZone temparature_zone;
+            if (temperature > 0.66) { temparature_zone = TemperatureZone::Hot; }
+            else if (temperature > 0.33) { temparature_zone = TemperatureZone::Fair; }
+            else { temparature_zone = TemperatureZone::Cold; }
+
+            HumidityZone humidity_zone;
+            if (humidity > 0.66) { humidity_zone = HumidityZone::Wet; }
+            else if (humidity > 0.33) { humidity_zone = HumidityZone::Temperate; }
+            else { humidity_zone = HumidityZone::Dry; }
+
+            auto biome = lookup_biome(hill_slice, landmass_slice, temparature_zone, humidity_zone);
+            biome_map.set(x, y, biome);
+        }
+    }
+
+    return biome_map;
+}
+
+Generator::ChunkMap3D<bool> Generator::generate_terrain(ChunkMap2D<float>& height_map, int64_t chunk_x, int64_t chunk_y) {
+    float jaggedness = 0.10f;
+
+    ChunkMap3D<bool> terrain_map{};
+    for (uint x = 0; x < Chunk::Width; x++) {
         for (uint z = 0; z < Chunk::Width; z++) {
+            auto height = height_map.get(x, z);
+
             for (uint y = 0; y < Chunk::Height; y++) {
-                auto value = noise.at({
-                    (float)(chunk_x * Chunk::Width + x),
-                    (float)y,
-                    (float)(chunk_y * Chunk::Width + z),
-                });
-
-                if (value > 0.6f && value < 0.7f) {
-                    chunk.set(x, y, z, {BlockType::Stone});
+                float density = get_density({Chunk::Width * chunk_x + (float)x, (float)y, Chunk::Width * chunk_y + (float)z});
+                float threshold = Math::sigmoid(((float)y / (Chunk::Height * height * 2) - 0.5f) / jaggedness);
+
+                if (density > threshold) {
+                    terrain_map.set(x, y, z, true);
                 }
             }
         }
     }
 
-    return chunk;
+    return terrain_map;
 }
 
-}
\ No newline at end of file
+void Generator::decorate_soil(Chunk& chunk, ChunkMap2D<BiomeType>& biome_map, ChunkMap3D<bool>& terrain_map) {
+    constexpr uint dirt_depth = 4;
+    constexpr uint water_height = 39;
+
+    for (uint x = 0; x < Chunk::Width; x++) {
+        for (uint z = 0; z < Chunk::Width; z++) {
+            auto biome = biome_map.get(x, z);
+
+            BlockType top_block{};
+            BlockType soil_block{};
+            switch (biome) {
+            case BiomeType::Beach:
+            case BiomeType::Desert:
+                top_block = BlockType::Sand;
+                soil_block = BlockType::Sand;
+                break;
+            case BiomeType::Jungle:
+            case BiomeType::Forest:
+            case BiomeType::Plains:
+            case BiomeType::River:
+            case BiomeType::Ocean:
+                top_block = BlockType::Grass;
+                soil_block = BlockType::Dirt;
+                break;
+            case BiomeType::Alpine:
+                top_block = BlockType::Snow;
+                soil_block = BlockType::Dirt;
+                break;
+            }
+
+            auto column_depth = 0;
+            for (uint y = Chunk::Height - 1; y > 0; y--) {
+                auto block = terrain_map.get(x, y, z);
+                if (block) {
+                    if (column_depth == 0 && y >= water_height - 1) {
+                        chunk.set(x, y, z, {top_block});
+                    } else if (column_depth < dirt_depth) {
+                        chunk.set(x, y, z, {soil_block});
+                    } else {
+                        chunk.set(x, y, z, {BlockType::Stone});
+                    }
+                    column_depth++;
+                } else {
+                    if (y < water_height) {
+                        chunk.set(x, y, z, {BlockType::Water});
+                    }
+                    column_depth = 0;
+                }
+            }
+        }
+    }
+}
+
+#define CURVE_START(y) constexpr auto lerp = Math::linear_interpolation; float _py = y; float _px = 0.0f;
+#define CURVE_POINT(x, y) if (v < x) return lerp({_py, y}, _px, x, v); _py = y; _px = x
+#define CURVE_END(y) return lerp({_py, y}, _px, 1.0f, v);
+
+float Generator::get_landmass(Vector<2> pos) const {
+    auto v = m_landmass_noise.at(pos);
+
+    CURVE_START(1.0f);
+    CURVE_POINT(0.1f, 0.8f);
+    CURVE_POINT(0.3f, 0.8f);
+    CURVE_POINT(0.37f, 0.125f);
+    CURVE_POINT(0.4f, 0.4f);
+    CURVE_POINT(0.46f, 0.45f);
+    CURVE_POINT(0.47f, 0.875f);
+    CURVE_POINT(0.48f, 0.9f);
+    CURVE_POINT(0.55f, 0.95f);
+    CURVE_END(1.0f);
+}
+
+float Generator::get_hill(Vector<2> pos) const {
+    auto v = m_hill_noise.at(pos);
+
+    CURVE_START(0.33f);
+    CURVE_POINT(0.25f, 1.0f);
+
+    CURVE_POINT(0.49f, 0.1f);
+    CURVE_POINT(0.5f, 0.0f);
+    CURVE_POINT(0.51f, 0.1f);
+
+    CURVE_POINT(0.75f, 1.0f);
+    CURVE_END(0.33f);
+}
+
+float Generator::get_humidity(Vector<2> pos) const {
+    auto v = m_humidity_noise.at(pos);
+    return v;
+}
+
+float Generator::get_temperature(Vector<2> pos) const {
+    auto v = m_temperature_noise.at(pos);
+    return v;
+}
+
+float Generator::get_density(Vector<3> pos) const {
+    auto v = m_density_noise.at(pos);
+    return v;
+}
+
+Vector<2> Generator::chunk_position_to_world_vector(int64_t chunk_x, int64_t chunk_y, uint x, uint y) {
+    return {(float)x + chunk_x * Chunk::Width, (float)y + chunk_y * Chunk::Width};
+}
+
+std::array<BiomeType, Generator::biome_lookup_table_size> Generator::create_biome_lookup_table() {
+    std::array<BiomeType, biome_lookup_table_size> table{};
+
+    auto inc = [](auto& x) { x = (std::remove_reference_t<decltype(x)>)((uint)x + 1); };
+    auto cmp = [](auto x, auto s) { return (uint)x < (uint)s; };
+
+    for (HillSlice hill_slice{}; cmp(hill_slice, HillSliceSize); inc(hill_slice)) {
+        for (LandmassSlice landmass_slice{}; cmp(landmass_slice, LandmassSliceSize); inc(landmass_slice)) {
+            for (TemperatureZone temperature_zone{}; cmp(temperature_zone, TemperatureZoneSize); inc(temperature_zone)) {
+                for (HumidityZone humidity_zone{}; cmp(humidity_zone, HumidityZoneSize); inc(humidity_zone)) {
+                    BiomeType biome{};
+                    if (landmass_slice == LandmassSlice::Ocean) {
+                        biome = BiomeType::Ocean;
+                        goto set;
+                    }
+                    if (landmass_slice == LandmassSlice::Beach) {
+                        biome = BiomeType::Beach;
+                        goto set;
+                    }
+
+                    if (hill_slice == HillSlice::Valley) {
+                        biome = BiomeType::River;
+                        goto set;
+                    }
+                    if (hill_slice == HillSlice::Mountain) {
+                        if (temperature_zone == TemperatureZone::Hot) {
+                            biome = BiomeType::Desert;
+                        } else {
+                            biome = BiomeType::Alpine;
+                        }
+                        goto set;
+                    }
+
+                    switch (temperature_zone) {
+                    case TemperatureZone::Hot:
+                        biome = BiomeType::Desert;
+                        break;
+                    case TemperatureZone::Fair:
+                        switch (humidity_zone) {
+                        case HumidityZone::Wet:
+                            biome = BiomeType::Jungle;
+                            break;
+                        case HumidityZone::Lush:
+                            biome = BiomeType::Forest;
+                            break;
+                        case HumidityZone::Temperate:
+                        case HumidityZone::Dry:
+                            biome = BiomeType::Plains;
+                            break;
+                        }
+                        break;
+                    case TemperatureZone::Cold:
+                        switch (humidity_zone) {
+                        case HumidityZone::Wet:
+                        case HumidityZone::Lush:
+                            biome = BiomeType::Alpine;
+                            break;
+                        case HumidityZone::Temperate:
+                        case HumidityZone::Dry:
+                            biome = BiomeType::Plains;
+                            break;
+                        }
+                        break;
+                    }
+
+                    set:
+                    table[biome_lookup_table_index(hill_slice, landmass_slice, temperature_zone, humidity_zone)] = biome;
+                }
+            }
+        }
+    }
+
+    return table;
+}
+
+size_t Generator::biome_lookup_table_index(HillSlice hill_slice, LandmassSlice landmass_slice, TemperatureZone temperature_zone, HumidityZone humidity_zone) {
+    auto hs = (uint8_t)hill_slice; auto ls = (uint8_t)landmass_slice; auto tz = (uint8_t)temperature_zone; auto hz = (uint8_t)humidity_zone;
+    auto LS_S = (uint8_t)LandmassSliceSize; auto TZ_S = (uint8_t)TemperatureZoneSize; auto HZ_S = (uint8_t)HumidityZoneSize;
+    return (hs * LS_S * TZ_S * HZ_S) + (ls * TZ_S * HZ_S) + (tz * HZ_S) + hz;
+}
+
+BiomeType Generator::lookup_biome(HillSlice hill_slice, LandmassSlice landmass_slice, TemperatureZone temperature_zone, HumidityZone humidity_zone) {
+    return biome_lookup_table.at(biome_lookup_table_index(hill_slice, landmass_slice, temperature_zone, humidity_zone));
+}
+
+}
diff --git a/src/World/Generator.hpp b/src/World/Generator.hpp
index afe43c6..523136a 100644
--- a/src/World/Generator.hpp
+++ b/src/World/Generator.hpp
@@ -3,6 +3,7 @@
 #include <cstdint>
 #include "Chunk.hpp"
 #include "BiomeType.hpp"
+#include "../Math/Perlin.hpp"
 
 namespace MC::World {
 
@@ -10,6 +11,64 @@ class Generator {
 public:
     Generator() = default;
     Chunk generate(int64_t chunk_x, int64_t chunk_y);
+private:
+    template <typename V>
+    struct ChunkMap2D {
+        V map[Chunk::Width * Chunk::Width];
+        void set(uint x, uint y, V v) { map[x * Chunk::Width + y] = v; }
+        V get(uint x, uint y) { return map[x * Chunk::Width + y]; }
+    };
+
+    template <typename V>
+    struct ChunkMap3D {
+        V map[Chunk::Width * Chunk::Width * Chunk::Height];
+        void set(uint x, uint y, uint z, V v) { map[pos(x, y, z)] = v; }
+        V get(uint x, uint y, uint z) { return map[pos(x, y, z)]; }
+        static uint pos(uint x, uint y, uint z) { return x + Chunk::Width * y + Chunk::Width * Chunk::Height * z; }
+    };
+
+    ChunkMap2D<float> generate_landmass_map(int64_t chunk_x, int64_t chunk_y);
+    ChunkMap2D<float> generate_hill_map(int64_t chunk_x, int64_t chunk_y);
+    ChunkMap2D<float> generate_height_map(ChunkMap2D<float>& landmass_map, ChunkMap2D<float>& hill_map, int64_t chunk_x, int64_t chunk_y);
+
+    ChunkMap2D<BiomeType> generate_biome_map(ChunkMap2D<float>& landmass_map, ChunkMap2D<float>& hill_map, ChunkMap2D<float>& height_map, int64_t chunk_x, int64_t chunk_y);
+
+    ChunkMap3D<bool> generate_terrain(ChunkMap2D<float>& height_map, int64_t chunk_x, int64_t chunk_y);
+
+    void decorate_soil(Chunk& chunk, ChunkMap2D<BiomeType>& biome_map, ChunkMap3D<bool>& terrain_map);
+
+    [[nodiscard]] float get_landmass(Vector<2> pos) const;
+    [[nodiscard]] float get_hill(Vector<2> pos) const;
+
+    [[nodiscard]] float get_humidity(Vector<2> pos) const;
+    [[nodiscard]] float get_temperature(Vector<2> pos) const;
+
+    [[nodiscard]] float get_density(Vector<3> pos) const;
+
+    static Vector<2> chunk_position_to_world_vector(int64_t chunk_x, int64_t chunk_y, uint x, uint y);
+
+    Math::Perlin::Noise<2> m_landmass_noise{.scale=800.0f, .octaves=4, .persistence=0.3f, .lacunarity=3.5f};
+    Math::Perlin::Noise<2> m_hill_noise{.scale=400.0f, .octaves=3, .persistence=0.5f, .lacunarity=2.0f};
+
+    Math::Perlin::Noise<2> m_temperature_noise{.scale=700.0f, .octaves=3, .persistence=0.5f, .lacunarity=2.0f};
+    Math::Perlin::Noise<2> m_humidity_noise{.scale=400.0f, .octaves=2, .persistence=0.5f, .lacunarity=2.0f};
+
+    Math::Perlin::Noise<3> m_density_noise{.scale=30.0f, .octaves=2, .persistence=0.7f, .lacunarity=2.0f};
+
+    enum class HillSlice { Mountain, Middle, Valley };
+    enum class LandmassSlice { Land, Beach, Ocean };
+    enum class TemperatureZone { Hot, Fair, Cold };
+    enum class HumidityZone { Wet, Lush, Temperate, Dry };
+    static constexpr uint HillSliceSize = (uint)HillSlice::Valley + 1;
+    static constexpr uint LandmassSliceSize = (uint)LandmassSlice::Ocean + 1;
+    static constexpr uint TemperatureZoneSize = (uint)TemperatureZone::Cold + 1;
+    static constexpr uint HumidityZoneSize = (uint)HumidityZone::Dry + 1;
+
+    static constexpr size_t biome_lookup_table_size = (size_t)HillSliceSize * (size_t)LandmassSliceSize * (size_t)TemperatureZoneSize * (size_t)HumidityZoneSize;
+    static std::array<BiomeType, biome_lookup_table_size> create_biome_lookup_table();
+    static size_t biome_lookup_table_index(HillSlice hill_slice, LandmassSlice landmass_slice, TemperatureZone temperature_zone, HumidityZone humidity_zone);
+    static BiomeType lookup_biome(HillSlice hill_slice, LandmassSlice landmass_slice, TemperatureZone temperature_zone, HumidityZone humidity_zone);
+    static inline std::array<BiomeType, biome_lookup_table_size> biome_lookup_table = create_biome_lookup_table();
 };
 
 }
diff --git a/src/World/World.cpp b/src/World/World.cpp
index 9d88af3..03ce60e 100644
--- a/src/World/World.cpp
+++ b/src/World/World.cpp
@@ -19,7 +19,7 @@ std::vector<World::ChunkData> World::get_visible_chunks(Vector<3> position) {
         m_visible_chunks = visible_chunks;
     }
 
-    std::vector<World::ChunkData> chunks{};
+    std::vector<ChunkData> chunks{};
     chunks.reserve(visible_chunks.size());
     for (auto index : visible_chunks) {
         auto& data = get(index);
@@ -31,6 +31,16 @@ std::vector<World::ChunkData> World::get_visible_chunks(Vector<3> position) {
     return chunks;
 }
 
+Chunk* World::get_chunk_for_positon(Vector<3> position) {
+    int32_t x = std::round(position.x() / Chunk::Width);
+    int32_t y = std::round(position.z() / Chunk::Width);
+    auto& data = get({x, y});
+    if (data.chunk.has_value()) {
+        return &data.chunk.value();
+    }
+    return nullptr;
+}
+
 void World::process_chunk_visibility_updates(std::unordered_set<ChunkIndex>& new_chunks, Vector<3> player) {
     for (auto new_index: new_chunks) {
         auto& data = get(new_index);
diff --git a/src/World/World.hpp b/src/World/World.hpp
index d842600..a5f73ec 100644
--- a/src/World/World.hpp
+++ b/src/World/World.hpp
@@ -3,9 +3,9 @@
 #include <memory>
 #include <unordered_map>
 #include <unordered_set>
-#include <utility>
 #include "Generator.hpp"
 #include "ChunkIndex.hpp"
+#include "../GFX/Binder.hpp"
 #include "../Compute/Queue.hpp"
 
 namespace MC::World {
@@ -28,6 +28,7 @@ public:
     };
 
     std::vector<ChunkData> get_visible_chunks(Vector<3> position);
+    Chunk* get_chunk_for_positon(Vector<3> position);
 private:
     std::unordered_set<ChunkIndex> get_visible_chunk_indices(Vector<3> position) const;
     std::unordered_set<ChunkIndex> load_finished_chunks_from_queue();