Advertisement
Guest User

perlinnoise.cpp

a guest
Jun 22nd, 2019
106
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 8.48 KB | None | 0 0
  1. #include "perlinnoise.h"
  2. #include <QtWidgets>
  3.  
  4. PerlinNoise::PerlinNoise(QWidget *parent) :
  5.     QWidget(parent)
  6. {
  7.     //interface
  8.     infoLabel = new QLabel();
  9.     infoLabel->setText(info);
  10.  
  11.     drawButton = new QPushButton();
  12.     drawButton->setText("Draw");
  13.  
  14.     fileWidthField = new QLineEdit();
  15.     fileWidthField->setText("320");
  16.  
  17.     fileHeightField = new QLineEdit();
  18.     fileHeightField->setText("320");
  19.  
  20.     fileWidthLabel = new QLabel();
  21.     fileWidthLabel->setText("Set width");
  22.  
  23.     fileHeightLabel = new QLabel();
  24.     fileHeightLabel->setText("Set height");
  25.  
  26.     gridSizeField = new QLineEdit();
  27.     gridSizeField->setText("160");
  28.     gridSizeLabel = new QLabel();
  29.     gridSizeLabel->setText("Set grid size");
  30.  
  31.     colorField = new QLineEdit();
  32.     colorField->setText("1000");
  33.     colorLabel = new QLabel();
  34.     colorLabel->setText("Set color");
  35.  
  36.     inputFileField = new QLineEdit();
  37.     inputFileField->setText("D:/Projects/Qt/PerlinNoise/1.raw");
  38.     inputFileLabel = new QLabel();
  39.     inputFileLabel->setText("Input File");
  40.     inputBrowseButton = new QPushButton();
  41.     inputBrowseButton->setText("Browse...");
  42.  
  43.     outputFileField = new QLineEdit();
  44.     outputFileField->setText("D:/Projects/Qt/PerlinNoise/3.raw");
  45.     outputFileLabel = new QLabel();
  46.     outputFileLabel->setText("Output File");
  47.     outputBrowseButton = new QPushButton();
  48.     outputBrowseButton->setText("Browse...");
  49.  
  50.  
  51.     //layouts
  52.     QGridLayout *mainLayout = new QGridLayout();
  53.  
  54.     QHBoxLayout *buttonLayout = new QHBoxLayout();
  55.  
  56.     buttonLayout->addWidget(drawButton);
  57.  
  58.     mainLayout->addWidget(inputFileLabel, 0, 0);
  59.     mainLayout->addWidget(inputFileField, 0, 1);
  60.     mainLayout->addWidget(inputBrowseButton, 0, 2);
  61.     mainLayout->addWidget(outputFileLabel, 1, 0);
  62.     mainLayout->addWidget(outputFileField, 1, 1);
  63.     mainLayout->addWidget(outputBrowseButton, 1, 2);
  64.     mainLayout->addWidget(fileWidthLabel, 2, 0);
  65.     mainLayout->addWidget(fileWidthField, 2, 1);
  66.     mainLayout->addWidget(fileHeightLabel, 3, 0);
  67.     mainLayout->addWidget(fileHeightField, 3, 1);
  68.     mainLayout->addWidget(gridSizeLabel, 4, 0);
  69.     mainLayout->addWidget(gridSizeField, 4, 1);
  70.     mainLayout->addWidget(colorLabel, 5, 0);
  71.     mainLayout->addWidget(colorField, 5, 1);
  72.     mainLayout->addLayout(buttonLayout, 6, 0);
  73.     mainLayout->addWidget(infoLabel, 7, 0);
  74.  
  75.  
  76.     this->setLayout(mainLayout);
  77.  
  78.     //slots
  79.     connect(drawButton, &QAbstractButton::clicked, this, &PerlinNoise::drawImage);
  80.     connect(inputBrowseButton, &QAbstractButton::clicked, this, &PerlinNoise::browseInputFile);
  81.     connect(outputBrowseButton, &QAbstractButton::clicked, this, &PerlinNoise::browseOutputFile);
  82. }
  83.  
  84. void PerlinNoise::openFile()
  85. {
  86.     inputFilePath = inputFileField->text();
  87.     map.clear();
  88.  
  89.  
  90.     QFile file(inputFilePath);
  91.  
  92.     fileWidth = fileWidthField->text().toInt();
  93.     fileHeight = fileHeightField->text().toInt();
  94.     gridSize = gridSizeField->text().toInt();
  95.  
  96.     if(file.open(QIODevice::ReadWrite) && fileWidth*fileHeight*2 == file.size()) // 2-ка, потому что картинка 16-битная, а не 8-битная
  97.     {
  98.         info = inputFilePath;
  99.         infoLabel->setText(info);
  100.  
  101.         QDataStream data(&file);
  102.         data.setByteOrder(QDataStream::LittleEndian);
  103.  
  104.         while(!data.atEnd())
  105.         {
  106.             qint16 x;
  107.             data >> x;
  108.             map.append(x);
  109.         }
  110.  
  111.         file.close();
  112.  
  113.  
  114.     }
  115.     else
  116.     {
  117.         info = "Error. File not opened.";
  118.         infoLabel->setText(info);
  119.         map.clear();
  120.     }
  121.  
  122. }
  123.  
  124. void PerlinNoise::browseInputFile()
  125. {
  126.     inputFileField->setText(QFileDialog::getOpenFileName(this,tr("Open file"), defaultFolder, tr("RAW files (*.raw)")));
  127. }
  128.  
  129. void PerlinNoise::browseOutputFile()
  130. {
  131.     outputFileField->setText(QFileDialog::getOpenFileName(this,tr("Open file"), defaultFolder, tr("RAW files (*.raw)")));
  132. }
  133.  
  134. int PerlinNoise::randomAngle()
  135. {
  136.     int a = QRandomGenerator::global()->bounded(360);
  137.     return a;
  138. }
  139.  
  140. float PerlinNoise::colorLerp(float a, float b, float t)
  141. {
  142.     return (a + (b - a) * t);
  143. }
  144.  
  145. float PerlinNoise::quinticCurve(float t)
  146. {
  147.     return t * t * t * (t * (t * 6 - 15) + 10);
  148. }
  149.  
  150. float PerlinNoise::normToOne(float n)
  151. {
  152.     return n / (float)gridSize;
  153. }
  154.  
  155. float PerlinNoise::normToGrid(float n)
  156. {
  157.     return (n - ((float)gridSize * ((int)n / gridSize)));
  158. }
  159.  
  160. float PerlinNoise::scalarMul(Vect v1, Vect v2)
  161. {
  162.     float x1 = (float)v1.getEndPoint().getX() - (float)v1.getStartPoint().getX();
  163.     float x2 = (float)v2.getEndPoint().getX() - (float)v2.getStartPoint().getX();
  164.     float y1 = (float)v1.getEndPoint().getY() - (float)v1.getStartPoint().getY();
  165.     float y2 = (float)v2.getEndPoint().getY() - (float)v2.getStartPoint().getY();
  166.  
  167.     return x1 * x2 + y1 * y2;
  168. }
  169.  
  170.  
  171. void PerlinNoise::assignGridNodesValues()
  172. {
  173.     const float pi180 = 3.141593/180;
  174.     if (gridSize >= 0)
  175.     {
  176.         for (int j = 0; j <= ceil((double)fileHeight/(double)gridSize); j ++)
  177.             for (int i = 0; i <= ceil((double)fileWidth/(double)gridSize); i ++)
  178.             {
  179.                 allGridNodes.append(Pixel(i * gridSize,j * gridSize, 0));
  180.                 float a = 45;//randomAngle();
  181.                 float cosa = cos(a * pi180);
  182.                 float sina = sin(a * pi180);
  183.                 allGridVectors.append(Pixel(gridSize * cosa + allGridNodes.last().getX(), gridSize * sina + allGridNodes.last().getY(), 0));
  184.             }
  185.  
  186.     }
  187.     else
  188.     {
  189.         info = "Error. Grid size must be larger than 0.";
  190.         infoLabel->setText("Info");
  191.     }
  192. }
  193.  
  194. QVector<Pixel> PerlinNoise::getNearGridPoints(Pixel p, QVector<Pixel> v)
  195. {
  196.     QVector<Pixel> nearGridPoints;
  197.     int X = p.getX()/gridSize;
  198.     int Y = p.getY()/gridSize;
  199.     int gridWidth = fileWidth/gridSize + 1;
  200.     int firstPointNumber = Y * gridWidth + X;
  201.     Pixel A = v[firstPointNumber];
  202.     Pixel B = v[firstPointNumber + 1];
  203.     Pixel C = v[firstPointNumber + fileHeight/gridSize + 1 + 1];
  204.     Pixel D = v[firstPointNumber + fileHeight/gridSize + 1];
  205.     nearGridPoints << A << B << C << D;
  206.     return nearGridPoints;
  207. }
  208.  
  209. float PerlinNoise::makePerlinNoise(Pixel p)
  210. {
  211.     if (gridSize >= 0)
  212.     {
  213.         QVector<Pixel> nearGridNodes = getNearGridPoints(p, allGridNodes);
  214.         QVector<Pixel> nearGridVectors = getNearGridPoints(p, allGridVectors);
  215.  
  216.         int x = p.getX();
  217.         int y = p.getY();
  218.  
  219.         Vect pa = Vect(nearGridNodes[0], p);
  220.         Vect pb = Vect(nearGridNodes[1], p);
  221.         Vect pc = Vect(nearGridNodes[2], p);
  222.         Vect pd = Vect(nearGridNodes[3], p);
  223.  
  224.         Vect va = Vect(nearGridNodes[0], allGridVectors[0]);
  225.         Vect vb = Vect(nearGridNodes[1], allGridVectors[1]);
  226.         Vect vc = Vect(nearGridNodes[2], allGridVectors[2]);
  227.         Vect vd = Vect(nearGridNodes[3], allGridVectors[3]);        
  228.  
  229.         float gridRatio = gridSize*gridSize*sqrt2;
  230.  
  231.         float a = ((scalarMul(pa, va)/gridRatio)+1)/2;
  232.         float b = ((scalarMul(pb, vb)/gridRatio)+1)/2;
  233.         float c = ((scalarMul(pc, vc)/gridRatio)+1)/2;
  234.         float d = ((scalarMul(pd, vd)/gridRatio)+1)/2;
  235.  
  236.         int gx = normToGrid(x);
  237.         int gy = normToGrid(y);
  238.  
  239.         float ux = normToOne((float)gx);
  240.         float uy = normToOne((float)gy);
  241.  
  242.         float sx = quinticCurve(ux);
  243.         float sy = quinticCurve(uy);
  244.  
  245.         float upperNodes = colorLerp(b, a, sx);
  246.         float lowerNodes = colorLerp(d, c, sx);
  247.         float average = colorLerp(upperNodes, lowerNodes, sy);
  248.         return average;
  249.     }
  250.     else
  251.     {
  252.         info = "Error. Grid size must be larger than 0.";
  253.         infoLabel->setText("Info");
  254.     }
  255.  
  256. }
  257.  
  258. void PerlinNoise::drawImage()
  259. {
  260.     openFile();
  261.     assignGridNodesValues();
  262.     quint16 color = colorField->text().toInt();
  263.  
  264.     newMap = map;
  265.  
  266.  
  267.     for (int i = 0; i < map.size(); i++)
  268.     {
  269.         int y = i / fileHeight;
  270.         int x = i - y * fileWidth;
  271.         Pixel p = Pixel(x, y, 0);
  272.         float noiseColor = makePerlinNoise(p) * (float)color;
  273.         quint16 average = noiseColor;
  274.         newMap[i] = average;
  275.     }
  276.  
  277.     outputFilePath = outputFileField->text();
  278.  
  279.     QFile file(outputFilePath);
  280.  
  281.     if(file.open(QIODevice::ReadWrite))
  282.     {
  283.         QDataStream data(&file);
  284.         data.setByteOrder(QDataStream::LittleEndian);
  285.  
  286.         file.resize(0);
  287.         for (int i = 0; i < newMap.size(); i++)
  288.         {
  289.             data << newMap[i];
  290.         }
  291.     }
  292.     file.close();
  293.     newMap.clear();
  294.  
  295. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement