summaryrefslogtreecommitdiff
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.cpp312
-rw-r--r--src/World/Generator.hpp59
-rw-r--r--src/World/World.cpp12
-rw-r--r--src/World/World.hpp3
16 files changed, 9557 insertions, 1471 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 differ
diff --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),
- });
+ 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 (value > 0.6f && value < 0.7f) {
- chunk.set(x, y, z, {BlockType::Stone});
+ 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();