Advertisement
Guest User

Untitled

a guest
Jun 17th, 2019
108
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.36 KB | None | 0 0
  1. #include <png++/png.hpp>
  2. #include <memory>
  3. #include <string>
  4.  
  5. #include "Octave.h"
  6.  
  7. constexpr unsigned IMAGE_SIZE = 512;
  8.  
  9. std::string numberToString(unsigned n, unsigned digits);
  10.  
  11. int main() {
  12. std::mt19937_64 rnd(0);
  13. auto octave = std::make_unique<Octave>(&rnd, 32, 1); //make_unique because Octave objects are too big to fit on the stack
  14.  
  15. for(unsigned z=0;z<625;++z){
  16. std::cout << z << "/625" << std::endl;
  17. png::image<png::rgb_pixel> image(IMAGE_SIZE, IMAGE_SIZE);
  18. for(unsigned x=0;x<IMAGE_SIZE;++x){
  19. for(unsigned y=0;y<IMAGE_SIZE;++y){
  20. unsigned brightness = (octave->noise(x, z*(64.0/300.0), y)*.5+.5)*255;
  21. image[y][x] = png::rgb_pixel(brightness, brightness, brightness);
  22. }
  23. }
  24. image.write("output/perlin-" + numberToString(z, 4) + ".png");
  25. }
  26.  
  27.  
  28. return 0;
  29. }
  30.  
  31. std::string numberToString(unsigned n, unsigned digits){
  32. std::string string = std::to_string(n);
  33. while(string.length() < digits){
  34. string = "0" + string;
  35. }
  36. return string;
  37. }
  38.  
  39. #pragma once
  40.  
  41. #include <array>
  42. #include <random>
  43.  
  44. class Octave{
  45. public:
  46. Octave(std::mt19937_64 *rnd, double frequency, double amplitude);
  47. double noise(double x, double y, double z);
  48.  
  49. private:
  50. static constexpr int PERMUTATION_TABLE_PART_SIZE = 1000000;
  51. static constexpr int PERMUTATION_TABLE_PART_COUNT = 3;
  52. static constexpr int PERMUTATION_TABLE_SIZE = PERMUTATION_TABLE_PART_SIZE*PERMUTATION_TABLE_PART_COUNT;
  53. std::array<int, PERMUTATION_TABLE_SIZE> m_permutationTable;
  54. double m_frequency, m_amplitude;
  55.  
  56. double influence(int x, int y, int z, double distanceX, double distanceY, double distanceZ);
  57.  
  58. inline static double square(double d) { return d*d; }
  59. inline static double vectorLength(double x, double y, double z);
  60. inline static double interpolate(double a, double b, double x);
  61.  
  62. };
  63.  
  64. #include "Octave.h"
  65.  
  66. #include <utility>
  67. #include <cmath>
  68. #include <iostream>
  69.  
  70. Octave::Octave(std::mt19937_64 *rnd, double frequency, double amplitude) : m_frequency(frequency), m_amplitude(amplitude) {
  71. //fill in basic array
  72. for(int i=0;i<PERMUTATION_TABLE_PART_SIZE;++i){
  73. for(int j=0;j<PERMUTATION_TABLE_PART_COUNT;++j){
  74. m_permutationTable[i+PERMUTATION_TABLE_PART_SIZE*j] = i;
  75. }
  76. }
  77.  
  78. //shuffle array
  79. for(int i=0;i<PERMUTATION_TABLE_SIZE;++i){
  80. int swapWith = ((*rnd)() % (PERMUTATION_TABLE_SIZE-i))+i;
  81. std::swap(m_permutationTable[i], m_permutationTable[swapWith]);
  82. }
  83. }
  84.  
  85. double Octave::noise(double x, double y, double z) {
  86. x /= m_frequency;
  87. y /= m_frequency;
  88. z /= m_frequency;
  89.  
  90. int intX = std::floor(x);
  91. int intY = std::floor(y);
  92. int intZ = std::floor(z);
  93.  
  94. double floatX = x - intX;
  95. double floatY = y - intY;
  96. double floatZ = z - intZ;
  97.  
  98. double influence1 = influence(intX, intY, intZ, floatX, floatY, floatZ);
  99. double influence2 = influence(intX+1, intY, intZ, floatX-1, floatY, floatZ);
  100. double influence3 = influence(intX+1, intY+1, intZ, floatX-1, floatY-1, floatZ);
  101. double influence4 = influence(intX, intY+1, intZ, floatX, floatY-1, floatZ);
  102. double influence5 = influence(intX, intY, intZ+1, floatX, floatY, floatZ-1);
  103. double influence6 = influence(intX+1, intY, intZ+1, floatX-1, floatY, floatZ);
  104. double influence7 = influence(intX+1, intY+1, intZ+1, floatX-1, floatY-1, floatZ-1);
  105. double influence8 = influence(intX, intY+1, intZ+1, floatX, floatY-1, floatZ-1);
  106.  
  107. double frontUpperInterpolatedValue = interpolate(influence4, influence3, floatX);
  108. double backUpperInterpolatedValue = interpolate(influence8, influence7, floatX);
  109. double frontLowerInterpolatedValue = interpolate(influence1, influence2, floatX);
  110. double backLowerInterpolatedValue = interpolate(influence5, influence6, floatX);
  111.  
  112. double upperInterpolatedValue = interpolate(frontUpperInterpolatedValue, backUpperInterpolatedValue, floatZ);
  113. double lowerInterpolatedValue = interpolate(frontLowerInterpolatedValue, backLowerInterpolatedValue, floatZ);
  114.  
  115. return interpolate(lowerInterpolatedValue, upperInterpolatedValue, floatY)*m_amplitude;
  116. }
  117.  
  118. double Octave::influence(int x, int y, int z, double distanceX, double distanceY, double distanceZ) {
  119. //create un-normalized gradient vector
  120. //the ordering of x, y, and z is arbitrary but different to produce different x y and z
  121. double gradientX = (m_permutationTable[m_permutationTable[m_permutationTable[x]+y]+z]/static_cast<double>(PERMUTATION_TABLE_PART_SIZE))*2-1;
  122. double gradientY = (m_permutationTable[m_permutationTable[m_permutationTable[y]+x]+z]/static_cast<double>(PERMUTATION_TABLE_PART_SIZE))*2-1;
  123. double gradientZ = (m_permutationTable[m_permutationTable[m_permutationTable[y]+x]+z]/static_cast<double>(PERMUTATION_TABLE_PART_SIZE))*2-1;
  124.  
  125. //normalize gradient vector
  126. double gradientVectorInverseLength = 1/vectorLength(gradientX, gradientY, gradientZ);
  127. gradientX *= gradientVectorInverseLength;
  128. gradientY *= gradientVectorInverseLength;
  129. gradientZ *= gradientVectorInverseLength;
  130.  
  131. //compute dot product
  132. double dot = gradientX*distanceX+gradientY*distanceY+gradientZ*distanceZ;
  133.  
  134. return dot;
  135. }
  136.  
  137. double Octave::vectorLength(double x, double y, double z) {
  138. return std::sqrt(square(x)+square(y)+square(z));
  139. }
  140.  
  141. double Octave::interpolate(double a, double b, double x) {
  142. return (b-a)*(6*x*x*x*x*x-15*x*x*x*x+10*x*x*x)+a;
  143. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement