|
1059 | 1059 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
|
1060 | 1060 | class perlin {
|
1061 | 1061 | public:
|
| 1062 | + perlin() { |
| 1063 | + init(); |
| 1064 | + } |
| 1065 | + |
| 1066 | + ~perlin() { |
| 1067 | + delete[] ranfloat; |
| 1068 | + delete[] perm_x; |
| 1069 | + delete[] perm_y; |
| 1070 | + delete[] perm_z; |
| 1071 | + } |
| 1072 | + |
1062 | 1073 | double noise(const vec3& p) const {
|
1063 | 1074 | auto u = p.x() - floor(p.x());
|
1064 | 1075 | auto v = p.y() - floor(p.y());
|
|
1069 | 1080 | return ranfloat[perm_x[i] ^ perm_y[j] ^ perm_z[k]];
|
1070 | 1081 | }
|
1071 | 1082 |
|
1072 |
| - public: |
| 1083 | + private: |
1073 | 1084 | static const int point_count = 256;
|
1074 |
| - static double* ranfloat; |
1075 |
| - static int* perm_x; |
1076 |
| - static int* perm_y; |
1077 |
| - static int* perm_z; |
1078 |
| - }; |
1079 |
| - |
1080 |
| - static double* perlin_generate() { |
1081 |
| - static double p[perlin::point_count]; |
| 1085 | + double* ranfloat; |
| 1086 | + int* perm_x; |
| 1087 | + int* perm_y; |
| 1088 | + int* perm_z; |
| 1089 | + |
| 1090 | + void init() { |
| 1091 | + ranfloat = new double[point_count]; |
| 1092 | + for (int i = 0; i < point_count; ++i) { |
| 1093 | + ranfloat[i] = random_double(); |
| 1094 | + } |
1082 | 1095 |
|
1083 |
| - for (int i = 0; i < perlin::point_count; ++i) |
1084 |
| - p[i] = random_double(); |
| 1096 | + perm_x = perlin_generate_perm(); |
| 1097 | + perm_y = perlin_generate_perm(); |
| 1098 | + perm_z = perlin_generate_perm(); |
| 1099 | + } |
1085 | 1100 |
|
1086 |
| - return p; |
1087 |
| - } |
| 1101 | + static int* perlin_generate_perm() { |
| 1102 | + auto p = new int[point_count]; |
1088 | 1103 |
|
1089 |
| - void permute(int* p, int n) { |
1090 |
| - for (int i = n-1; i > 0; i--) { |
1091 |
| - int target = random_int(0, i); |
1092 |
| - int tmp = p[i]; |
1093 |
| - p[i] = p[target]; |
1094 |
| - p[target] = tmp; |
1095 |
| - } |
1096 |
| - } |
1097 |
| - |
1098 |
| - static int* perlin_generate_perm(int p[]) { |
1099 |
| - for (int i = 0; i < perlin::point_count; i++) |
1100 |
| - p[i] = i; |
| 1104 | + for (int i = 0; i < perlin::point_count; i++) |
| 1105 | + p[i] = i; |
1101 | 1106 |
|
1102 |
| - permute(p, perlin::point_count); |
| 1107 | + permute(p, point_count); |
1103 | 1108 |
|
1104 |
| - return p; |
1105 |
| - } |
1106 |
| - |
1107 |
| - double* perlin::ranfloat = perlin_generate(); |
| 1109 | + return p; |
| 1110 | + } |
1108 | 1111 |
|
1109 |
| - int perlin_values[3][perlin::point_count]; |
1110 |
| - int* perlin::perm_x = perlin_generate_perm(perlin_values[0]); |
1111 |
| - int* perlin::perm_y = perlin_generate_perm(perlin_values[1]); |
1112 |
| - int* perlin::perm_z = perlin_generate_perm(perlin_values[2]); |
| 1112 | + void permute(int* p, int n) { |
| 1113 | + for (int i = n-1; i > 0; i--) { |
| 1114 | + int target = random_int(0, i); |
| 1115 | + int tmp = p[i]; |
| 1116 | + p[i] = p[target]; |
| 1117 | + p[target] = tmp; |
| 1118 | + } |
| 1119 | + } |
| 1120 | + }; |
1113 | 1121 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
1114 | 1122 | [Listing [perlin]: <kbd>[perlin.h]</kbd> A Perlin texture class and functions]
|
1115 | 1123 | </div>
|
|
1191 | 1199 |
|
1192 | 1200 | class perlin {
|
1193 | 1201 | public:
|
| 1202 | + ... |
1194 | 1203 | double noise(const vec3& p) const {
|
1195 | 1204 | auto u = p.x() - floor(p.x());
|
1196 | 1205 | auto v = p.y() - floor(p.y());
|
|
1199 | 1208 | int j = floor(p.y());
|
1200 | 1209 | int k = floor(p.z());
|
1201 | 1210 | double c[2][2][2];
|
| 1211 | + |
1202 | 1212 | for (int di=0; di < 2; di++)
|
1203 | 1213 | for (int dj=0; dj < 2; dj++)
|
1204 | 1214 | for (int dk=0; dk < 2; dk++)
|
|
1207 | 1217 | perm_y[(j+dj) & 255] ^
|
1208 | 1218 | perm_z[(k+dk) & 255]
|
1209 | 1219 | ];
|
| 1220 | + |
1210 | 1221 | return trilinear_interp(c, u, v, w);
|
1211 | 1222 | }
|
1212 |
| - |
1213 |
| - public: |
1214 |
| - static const int point_count = 256; |
1215 |
| - static int* perm_x; |
1216 |
| - static int* perm_y; |
1217 |
| - static int* perm_z; |
| 1223 | + ... |
1218 | 1224 | }
|
1219 | 1225 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
1220 | 1226 | [Listing [perlin-trilinear]: <kbd>[perlin.h]</kbd> Perlin with trilienear interpolation]
|
|
1235 | 1241 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
|
1236 | 1242 | class perlin (
|
1237 | 1243 | public:
|
| 1244 | + ... |
1238 | 1245 | double noise(const vec3& p) const {
|
1239 | 1246 | auto u = p.x() - floor(p.x());
|
1240 | 1247 | auto v = p.y() - floor(p.y());
|
|
1296 | 1303 | max off the lattice. So, first we need to change the random floats to random vectors:
|
1297 | 1304 |
|
1298 | 1305 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
|
1299 |
| - vec3* perlin::ranvec = perlin_generate(); |
1300 |
| - |
1301 |
| - int perlin_values[3][perlin::point_count]; |
1302 |
| - int* perlin::perm_x = perlin_generate_perm(perlin_values[0]); |
1303 |
| - int* perlin::perm_y = perlin_generate_perm(perlin_values[1]); |
1304 |
| - int* perlin::perm_z = perlin_generate_perm(perlin_values[2]); |
| 1306 | + class perlin { |
| 1307 | + public: |
| 1308 | + ... |
| 1309 | + ~perlin() { |
| 1310 | + delete[] ranvec; |
| 1311 | + delete[] perm_x; |
| 1312 | + delete[] perm_y; |
| 1313 | + delete[] perm_z; |
| 1314 | + } |
| 1315 | + ... |
| 1316 | + private: |
| 1317 | + vec3* ranvec; |
| 1318 | + int* perm_x; |
| 1319 | + int* perm_y; |
| 1320 | + int* perm_z; |
| 1321 | + ... |
| 1322 | + } |
1305 | 1323 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
1306 | 1324 | [Listing [perlin-randunit]: <kbd>[perlin.h]</kbd> Perlin with random unit translations]
|
1307 | 1325 | </div>
|
|
1311 | 1329 | exactly uniform:
|
1312 | 1330 |
|
1313 | 1331 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
|
1314 |
| - static vec3* perlin_generate() { |
1315 |
| - static vec3 p[perlin::point_count]; |
1316 |
| - |
1317 |
| - for (int i = 0; i < perlin::point_count; ++i) { |
1318 |
| - p[i] = unit_vector(vec3::random(-1,1)); |
1319 |
| - } |
| 1332 | + class perlin { |
| 1333 | + ... |
| 1334 | + private: |
| 1335 | + ... |
| 1336 | + void init() { |
| 1337 | + ranvec = new vec3[point_count]; |
| 1338 | + |
| 1339 | + for (int i = 0; i < point_count; ++i) { |
| 1340 | + ranvec[i] = unit_vector(vec3::random(-1,1)); |
| 1341 | + } |
1320 | 1342 |
|
1321 |
| - return p; |
| 1343 | + perm_x = perlin_generate_perm(); |
| 1344 | + perm_y = perlin_generate_perm(); |
| 1345 | + perm_z = perlin_generate_perm(); |
| 1346 | + } |
| 1347 | + ... |
1322 | 1348 | }
|
1323 | 1349 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
1324 | 1350 | [Listing [perlin-gen-2]: <kbd>[perlin.h]</kbd> New perlin_generate()]
|
|
1330 | 1356 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
|
1331 | 1357 | class perlin {
|
1332 | 1358 | public:
|
| 1359 | + ... |
1333 | 1360 | double noise(const vec3& p) const {
|
1334 | 1361 | auto u = p.x() - floor(p.x());
|
1335 | 1362 | auto v = p.y() - floor(p.y());
|
|
1338 | 1365 | int j = floor(p.y());
|
1339 | 1366 | int k = floor(p.z());
|
1340 | 1367 | vec3 c[2][2][2];
|
| 1368 | + |
1341 | 1369 | for (int di=0; di < 2; di++)
|
1342 | 1370 | for (int dj=0; dj < 2; dj++)
|
1343 | 1371 | for (int dk=0; dk < 2; dk++)
|
|
1346 | 1374 | perm_y[(j+dj) & 255] ^
|
1347 | 1375 | pexm_z[(k+dk) & 255]
|
1348 | 1376 | ];
|
| 1377 | + |
1349 | 1378 | return perlin_interp(c, u, v, w);
|
1350 | 1379 | }
|
1351 |
| - |
1352 |
| - public: |
1353 |
| - static const int point_count = 256; |
1354 |
| - static vec3* ranvec; |
1355 |
| - static int* perm_x; |
1356 |
| - static int* perm_y; |
1357 |
| - static int* perm_z; |
| 1380 | + ... |
1358 | 1381 | }
|
1359 | 1382 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
1360 | 1383 | [Listing [perlin-2]: <kbd>[perlin.h]</kbd> The perlin class so far]
|
|
1364 | 1387 | And the interpolation becomes a bit more complicated:
|
1365 | 1388 |
|
1366 | 1389 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
|
1367 |
| - inline double perlin_interp(vec3 c[2][2][2], double u, double v, double w) { |
1368 |
| - auto uu = u*u*(3-2*u); |
1369 |
| - auto vv = v*v*(3-2*v); |
1370 |
| - auto ww = w*w*(3-2*w); |
1371 |
| - auto accum = 0.0; |
1372 |
| - for (int i=0; i < 2; i++) |
1373 |
| - for (int j=0; j < 2; j++) |
1374 |
| - for (int k=0; k < 2; k++) { |
1375 |
| - vec3 weight_v(u-i, v-j, w-k); |
1376 |
| - accum += (i*uu + (1-i)*(1-uu)) |
1377 |
| - * (j*vv + (1-j)*(1-vv)) |
1378 |
| - * (k*ww + (1-k)*(1-ww)) |
1379 |
| - * dot(c[i][j][k], weight_v); |
1380 |
| - } |
1381 |
| - return accum; |
| 1390 | + class perlin { |
| 1391 | + ... |
| 1392 | + private: |
| 1393 | + ... |
| 1394 | + inline double perlin_interp(vec3 c[2][2][2], double u, double v, double w) { |
| 1395 | + auto uu = u*u*(3-2*u); |
| 1396 | + auto vv = v*v*(3-2*v); |
| 1397 | + auto ww = w*w*(3-2*w); |
| 1398 | + auto accum = 0.0; |
| 1399 | + |
| 1400 | + for (int i=0; i < 2; i++) |
| 1401 | + for (int j=0; j < 2; j++) |
| 1402 | + for (int k=0; k < 2; k++) { |
| 1403 | + vec3 weight_v(u-i, v-j, w-k); |
| 1404 | + accum += (i*uu + (1-i)*(1-uu)) |
| 1405 | + * (j*vv + (1-j)*(1-vv)) |
| 1406 | + * (k*ww + (1-k)*(1-ww)) |
| 1407 | + * dot(c[i][j][k], weight_v); |
| 1408 | + } |
| 1409 | + |
| 1410 | + return accum; |
| 1411 | + } |
| 1412 | + ... |
1382 | 1413 | }
|
1383 | 1414 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
1384 | 1415 | [Listing [perlin-interp]: <kbd>[perlin.h]</kbd> Perlin interpolation function so far]
|
|
1421 | 1452 | turbulence and is a sum of repeated calls to noise:
|
1422 | 1453 |
|
1423 | 1454 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
|
1424 |
| - double turb(const vec3& p, int depth=7) const { |
1425 |
| - auto accum = 0.0; |
1426 |
| - vec3 temp_p = p; |
1427 |
| - auto weight = 1.0; |
1428 |
| - for (int i = 0; i < depth; i++) { |
1429 |
| - accum += weight*noise(temp_p); |
1430 |
| - weight *= 0.5; |
1431 |
| - temp_p *= 2; |
1432 |
| - } |
1433 |
| - return fabs(accum); |
1434 |
| - } |
| 1455 | + class perlin { |
| 1456 | + ... |
| 1457 | + public: |
| 1458 | + ... |
| 1459 | + double turb(const vec3& p, int depth=7) const { |
| 1460 | + auto accum = 0.0; |
| 1461 | + vec3 temp_p = p; |
| 1462 | + auto weight = 1.0; |
| 1463 | + |
| 1464 | + for (int i = 0; i < depth; i++) { |
| 1465 | + accum += weight*noise(temp_p); |
| 1466 | + weight *= 0.5; |
| 1467 | + temp_p *= 2; |
| 1468 | + } |
| 1469 | + |
| 1470 | + return fabs(accum); |
| 1471 | + } |
| 1472 | + ... |
1435 | 1473 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
1436 | 1474 | [Listing [perlin-turb]: <kbd>[perlin.h]</kbd> Turbulence function]
|
1437 | 1475 | </div>
|
|
0 commit comments