Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "perlinnoise.h"
- #include <QtWidgets>
- PerlinNoise::PerlinNoise(QWidget *parent) :
- QWidget(parent)
- {
- //interface
- infoLabel = new QLabel();
- infoLabel->setText(info);
- drawButton = new QPushButton();
- drawButton->setText("Draw");
- fileWidthField = new QLineEdit();
- fileWidthField->setText("320");
- fileHeightField = new QLineEdit();
- fileHeightField->setText("320");
- fileWidthLabel = new QLabel();
- fileWidthLabel->setText("Set width");
- fileHeightLabel = new QLabel();
- fileHeightLabel->setText("Set height");
- gridSizeField = new QLineEdit();
- gridSizeField->setText("160");
- gridSizeLabel = new QLabel();
- gridSizeLabel->setText("Set grid size");
- colorField = new QLineEdit();
- colorField->setText("1000");
- colorLabel = new QLabel();
- colorLabel->setText("Set color");
- inputFileField = new QLineEdit();
- inputFileField->setText("D:/Projects/Qt/PerlinNoise/1.raw");
- inputFileLabel = new QLabel();
- inputFileLabel->setText("Input File");
- inputBrowseButton = new QPushButton();
- inputBrowseButton->setText("Browse...");
- outputFileField = new QLineEdit();
- outputFileField->setText("D:/Projects/Qt/PerlinNoise/3.raw");
- outputFileLabel = new QLabel();
- outputFileLabel->setText("Output File");
- outputBrowseButton = new QPushButton();
- outputBrowseButton->setText("Browse...");
- //layouts
- QGridLayout *mainLayout = new QGridLayout();
- QHBoxLayout *buttonLayout = new QHBoxLayout();
- buttonLayout->addWidget(drawButton);
- mainLayout->addWidget(inputFileLabel, 0, 0);
- mainLayout->addWidget(inputFileField, 0, 1);
- mainLayout->addWidget(inputBrowseButton, 0, 2);
- mainLayout->addWidget(outputFileLabel, 1, 0);
- mainLayout->addWidget(outputFileField, 1, 1);
- mainLayout->addWidget(outputBrowseButton, 1, 2);
- mainLayout->addWidget(fileWidthLabel, 2, 0);
- mainLayout->addWidget(fileWidthField, 2, 1);
- mainLayout->addWidget(fileHeightLabel, 3, 0);
- mainLayout->addWidget(fileHeightField, 3, 1);
- mainLayout->addWidget(gridSizeLabel, 4, 0);
- mainLayout->addWidget(gridSizeField, 4, 1);
- mainLayout->addWidget(colorLabel, 5, 0);
- mainLayout->addWidget(colorField, 5, 1);
- mainLayout->addLayout(buttonLayout, 6, 0);
- mainLayout->addWidget(infoLabel, 7, 0);
- this->setLayout(mainLayout);
- //slots
- connect(drawButton, &QAbstractButton::clicked, this, &PerlinNoise::drawImage);
- connect(inputBrowseButton, &QAbstractButton::clicked, this, &PerlinNoise::browseInputFile);
- connect(outputBrowseButton, &QAbstractButton::clicked, this, &PerlinNoise::browseOutputFile);
- }
- void PerlinNoise::openFile()
- {
- inputFilePath = inputFileField->text();
- map.clear();
- QFile file(inputFilePath);
- fileWidth = fileWidthField->text().toInt();
- fileHeight = fileHeightField->text().toInt();
- gridSize = gridSizeField->text().toInt();
- if(file.open(QIODevice::ReadWrite) && fileWidth*fileHeight*2 == file.size()) // 2-ка, потому что картинка 16-битная, а не 8-битная
- {
- info = inputFilePath;
- infoLabel->setText(info);
- QDataStream data(&file);
- data.setByteOrder(QDataStream::LittleEndian);
- while(!data.atEnd())
- {
- qint16 x;
- data >> x;
- map.append(x);
- }
- file.close();
- }
- else
- {
- info = "Error. File not opened.";
- infoLabel->setText(info);
- map.clear();
- }
- }
- void PerlinNoise::browseInputFile()
- {
- inputFileField->setText(QFileDialog::getOpenFileName(this,tr("Open file"), defaultFolder, tr("RAW files (*.raw)")));
- }
- void PerlinNoise::browseOutputFile()
- {
- outputFileField->setText(QFileDialog::getOpenFileName(this,tr("Open file"), defaultFolder, tr("RAW files (*.raw)")));
- }
- int PerlinNoise::randomAngle()
- {
- int a = QRandomGenerator::global()->bounded(360);
- return a;
- }
- float PerlinNoise::colorLerp(float a, float b, float t)
- {
- return (a + (b - a) * t);
- }
- float PerlinNoise::quinticCurve(float t)
- {
- return t * t * t * (t * (t * 6 - 15) + 10);
- }
- float PerlinNoise::normToOne(float n)
- {
- return n / (float)gridSize;
- }
- float PerlinNoise::normToGrid(float n)
- {
- return (n - ((float)gridSize * ((int)n / gridSize)));
- }
- float PerlinNoise::scalarMul(Vect v1, Vect v2)
- {
- float x1 = (float)v1.getEndPoint().getX() - (float)v1.getStartPoint().getX();
- float x2 = (float)v2.getEndPoint().getX() - (float)v2.getStartPoint().getX();
- float y1 = (float)v1.getEndPoint().getY() - (float)v1.getStartPoint().getY();
- float y2 = (float)v2.getEndPoint().getY() - (float)v2.getStartPoint().getY();
- return x1 * x2 + y1 * y2;
- }
- void PerlinNoise::assignGridNodesValues()
- {
- const float pi180 = 3.141593/180;
- if (gridSize >= 0)
- {
- for (int j = 0; j <= ceil((double)fileHeight/(double)gridSize); j ++)
- for (int i = 0; i <= ceil((double)fileWidth/(double)gridSize); i ++)
- {
- allGridNodes.append(Pixel(i * gridSize,j * gridSize, 0));
- float a = 45;//randomAngle();
- float cosa = cos(a * pi180);
- float sina = sin(a * pi180);
- allGridVectors.append(Pixel(gridSize * cosa + allGridNodes.last().getX(), gridSize * sina + allGridNodes.last().getY(), 0));
- }
- }
- else
- {
- info = "Error. Grid size must be larger than 0.";
- infoLabel->setText("Info");
- }
- }
- QVector<Pixel> PerlinNoise::getNearGridPoints(Pixel p, QVector<Pixel> v)
- {
- QVector<Pixel> nearGridPoints;
- int X = p.getX()/gridSize;
- int Y = p.getY()/gridSize;
- int gridWidth = fileWidth/gridSize + 1;
- int firstPointNumber = Y * gridWidth + X;
- Pixel A = v[firstPointNumber];
- Pixel B = v[firstPointNumber + 1];
- Pixel C = v[firstPointNumber + fileHeight/gridSize + 1 + 1];
- Pixel D = v[firstPointNumber + fileHeight/gridSize + 1];
- nearGridPoints << A << B << C << D;
- return nearGridPoints;
- }
- float PerlinNoise::makePerlinNoise(Pixel p)
- {
- if (gridSize >= 0)
- {
- QVector<Pixel> nearGridNodes = getNearGridPoints(p, allGridNodes);
- QVector<Pixel> nearGridVectors = getNearGridPoints(p, allGridVectors);
- int x = p.getX();
- int y = p.getY();
- Vect pa = Vect(nearGridNodes[0], p);
- Vect pb = Vect(nearGridNodes[1], p);
- Vect pc = Vect(nearGridNodes[2], p);
- Vect pd = Vect(nearGridNodes[3], p);
- Vect va = Vect(nearGridNodes[0], allGridVectors[0]);
- Vect vb = Vect(nearGridNodes[1], allGridVectors[1]);
- Vect vc = Vect(nearGridNodes[2], allGridVectors[2]);
- Vect vd = Vect(nearGridNodes[3], allGridVectors[3]);
- float gridRatio = gridSize*gridSize*sqrt2;
- float a = ((scalarMul(pa, va)/gridRatio)+1)/2;
- float b = ((scalarMul(pb, vb)/gridRatio)+1)/2;
- float c = ((scalarMul(pc, vc)/gridRatio)+1)/2;
- float d = ((scalarMul(pd, vd)/gridRatio)+1)/2;
- int gx = normToGrid(x);
- int gy = normToGrid(y);
- float ux = normToOne((float)gx);
- float uy = normToOne((float)gy);
- float sx = quinticCurve(ux);
- float sy = quinticCurve(uy);
- float upperNodes = colorLerp(b, a, sx);
- float lowerNodes = colorLerp(d, c, sx);
- float average = colorLerp(upperNodes, lowerNodes, sy);
- return average;
- }
- else
- {
- info = "Error. Grid size must be larger than 0.";
- infoLabel->setText("Info");
- }
- }
- void PerlinNoise::drawImage()
- {
- openFile();
- assignGridNodesValues();
- quint16 color = colorField->text().toInt();
- newMap = map;
- for (int i = 0; i < map.size(); i++)
- {
- int y = i / fileHeight;
- int x = i - y * fileWidth;
- Pixel p = Pixel(x, y, 0);
- float noiseColor = makePerlinNoise(p) * (float)color;
- quint16 average = noiseColor;
- newMap[i] = average;
- }
- outputFilePath = outputFileField->text();
- QFile file(outputFilePath);
- if(file.open(QIODevice::ReadWrite))
- {
- QDataStream data(&file);
- data.setByteOrder(QDataStream::LittleEndian);
- file.resize(0);
- for (int i = 0; i < newMap.size(); i++)
- {
- data << newMap[i];
- }
- }
- file.close();
- newMap.clear();
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement