Skip to content

Instantly share code, notes, and snippets.

@Auburn
Last active April 1, 2019 19:41
Show Gist options
  • Save Auburn/6c26380869f99e998c5122d044036f2c to your computer and use it in GitHub Desktop.
Save Auburn/6c26380869f99e998c5122d044036f2c to your computer and use it in GitHub Desktop.
#include "MyForm.h"
#include "FastNoise.h"
#include <cmath>
#include <Windows.h>
using namespace Project1;
using namespace System::Windows::Forms;
[STAThread]
int main(array<String^>^ args)
{
Application::EnableVisualStyles();
Application::SetCompatibleTextRenderingDefault(false);
Project1::MyForm form;
Application::Run(%form);
return 0;
}
typedef struct RGB
{
unsigned char r;
unsigned char g;
unsigned char b;
} RGB;
typedef struct HSV
{
unsigned char h;
unsigned char s;
unsigned char v;
} HSV;
static RGB HSV2RGB(HSV hsv);
void MyForm::TextEnter(System::Object^ sender, System::Windows::Forms::KeyEventArgs^ e)
{
if (e->KeyCode.Equals(Keys::Enter))
{
e->Handled = true;
RebuildBitmap(nullptr, nullptr);
}
}
void MyForm::MouseScroll(System::Object^ sender, System::Windows::Forms::MouseEventArgs^ e)
{
auto textBox = dynamic_cast<System::Windows::Forms::TextBox^>(sender);
if (!textBox || e->Delta == 0)
return;
float newValue = 0;
try { newValue = Convert::ToSingle(textBox->Text, format); }
catch (System::FormatException^ e) { MessageBox::Show(e->Message); }
if (e->Delta > 0)
newValue *= 1.25f * (e->Delta / WHEEL_DELTA);
else
newValue /= -1.25f * (e->Delta / WHEEL_DELTA);
textBox->Text = newValue.ToString();
RebuildBitmap(nullptr, nullptr);
}
void MyForm::MouseScrollFix(System::Object^ sender, System::Windows::Forms::MouseEventArgs^ e)
{
auto updown = dynamic_cast<System::Windows::Forms::NumericUpDown^>(sender);
if (!updown || e->Delta == 0)
return;
auto hlm = dynamic_cast<System::Windows::Forms::HandledMouseEventArgs^>(e);
if (hlm)
hlm->Handled = true;
System::Decimal newValue = 0;
newValue = min(max(System::Decimal::Add(updown->Value, updown->Increment * (e->Delta / WHEEL_DELTA))
, updown->Minimum), updown->Maximum);
updown->Value = newValue;
}
void Project1::MyForm::randSeed_Click(System::Object ^ sender, System::EventArgs ^ e)
{
Random^ r = gcnew Random();
seedBox->Text = r->Next().ToString();
RebuildBitmap(nullptr, nullptr);
}
void MyForm::RebuildBitmap(System::Object^ sender, System::EventArgs^ e)
{
FastNoise fNoise;
FastNoise perturbNoise;
perturbNoise.SetFrequency(0.015f);
int size = 512;
try { size = Convert::ToInt32(sizeBox->Text); }
catch (System::FormatException^ e) { MessageBox::Show("Size: " + e->Message); }
if (!noiseTypeList->Text->Contains("Vector"))
fNoise.SetNoiseType((FastNoise::NoiseType)noiseTypeList->SelectedIndex);
fNoise.SetInterp((FastNoise::Interp)interpBox->SelectedIndex);
try { fNoise.SetSeed(Convert::ToInt32(seedBox->Text)); }
catch (System::FormatException^ e) { MessageBox::Show("Seed: " + e->Message); }
try { fNoise.SetFrequency(Convert::ToSingle(frequencyBox->Text, format)); }
catch (System::FormatException^ e) { MessageBox::Show("Frequency: " + e->Message); }
fNoise.SetFractalType((FastNoise::FractalType)fractalTypeBox->SelectedIndex);
try { fNoise.SetFractalOctaves(Convert::ToInt32(octavesBox->Value)); }
catch (System::FormatException^ e) { MessageBox::Show("Fractal octaves: " + e->Message); }
try { fNoise.SetFractalLacunarity(Convert::ToSingle(lacunarityBox->Text, format)); }
catch (System::FormatException^ e) { MessageBox::Show("Fractal lacunarity: " + e->Message); }
try { fNoise.SetFractalGain(Convert::ToSingle(gainBox->Text, format)); }
catch (System::FormatException^ e) { MessageBox::Show("Fractal gain: " + e->Message); }
try
{
fNoise.SetGradientPerturbAmp(Convert::ToSingle(warpAmpBox->Text, format));
perturbNoise.SetGradientPerturbAmp(Convert::ToSingle(warpAmpBox->Text, format));
}
catch (System::FormatException^ e) { MessageBox::Show("Warp amplitude: " + e->Message); }
try { perturbNoise.SetFrequency(Convert::ToSingle(perturbFreqBox->Text, format)); }
catch (System::FormatException^ e) { MessageBox::Show("Perturb frequency: " + e->Message); }
fNoise.SetCellularDistanceFunction((FastNoise::CellularDistanceFunction)distanceFunctionBox->SelectedIndex);
fNoise.SetCellularReturnType((FastNoise::CellularReturnType)cellReturnTypeBox->SelectedIndex);
fNoise.SetCellularDistance2Indices(Convert::ToInt32(distance2index0->Value), Convert::ToInt32(distance2index1->Value));
try { fNoise.SetCellularJitter(Convert::ToSingle(jitterBox->Text, format)); }
catch (System::FormatException^ e) { MessageBox::Show("Cellular jitter: " + e->Message); }
FastNoise* lookupNoise = new FastNoise();
lookupNoise->SetFrequency(0.2f);
lookupNoise->SetNoiseType(FastNoise::Simplex);
fNoise.SetCellularNoiseLookup(lookupNoise);
Bitmap^ bitmap = (gcnew Bitmap(size, size));
FN_DECIMAL noise;
FN_DECIMAL minN = 99999;
FN_DECIMAL maxN = -99999;
FN_DECIMAL avg = 0;
LARGE_INTEGER ticks;
LARGE_INTEGER start;
LARGE_INTEGER end;
LONGLONG current = 0;
QueryPerformanceFrequency(&ticks);
bool get3d = checkBox3D->Checked;
int halfSize = size / 2;
int index = 0;
if (!noiseTypeList->Text->Contains("Perturb"))
{
FN_DECIMAL* noiseValues = new FN_DECIMAL[size*size];
int warpIndex = positionWarpBox->SelectedIndex;
QueryPerformanceCounter(&start);
if (get3d)
{
for (int x = 0; x < size; x++)
{
for (int y = 0; y < size; y++)
{
FN_DECIMAL xf = FN_DECIMAL(x - halfSize);
FN_DECIMAL yf = FN_DECIMAL(y - halfSize);
FN_DECIMAL zf = FN_DECIMAL(zPos);
switch (warpIndex)
{
case 1:
perturbNoise.GradientPerturb(xf, yf, zf);
break;
case 2:
perturbNoise.GradientPerturbFractal(xf, yf, zf);
break;
}
noise = fNoise.GetNoise(xf, yf, zf);
avg += noise;
maxN = fmax(maxN, noise);
minN = fmin(minN, noise);
noiseValues[index++] = noise;
}
}
}
else
{
for (int x = 0; x < size; x++)
{
for (int y = 0; y < size; y++)
{
FN_DECIMAL xf = FN_DECIMAL(x - halfSize);
FN_DECIMAL yf = FN_DECIMAL(y - halfSize);
switch (warpIndex)
{
case 1:
perturbNoise.GradientPerturb(xf, yf);
break;
case 2:
perturbNoise.GradientPerturbFractal(xf, yf);
break;
}
noise = fNoise.GetNoise(xf, yf);
avg += noise;
maxN = fmax(maxN, noise);
minN = fmin(minN, noise);
noiseValues[index++] = noise;
}
}
}
QueryPerformanceCounter(&end);
current += end.QuadPart - start.QuadPart;
avg /= index - 1;
index = 0;
FN_DECIMAL scale = 255 / (maxN - minN);
for (int x = 0; x < size; x++)
{
for (int y = 0; y < size; y++)
{
noise = noiseValues[index++];
unsigned char value = (unsigned char)fmax(0, fmin(255, (noise - minN) * scale));
if (invertBox->Checked)
value = 255 - value;
bitmap->SetPixel(x, y, Color::FromArgb(255, value, value, value));
}
}
delete[] noiseValues;
}
else
{
FN_DECIMAL* noiseValues = new FN_DECIMAL[size*size * 3];
bool fractal = noiseTypeList->Text->Contains("Fractal");
QueryPerformanceCounter(&start);
if (get3d)
{
for (int x = 0; x < size; x++)
{
for (int y = 0; y < size; y++)
{
FN_DECIMAL xf = (FN_DECIMAL)x;
FN_DECIMAL yf = (FN_DECIMAL)y;
FN_DECIMAL zf = (FN_DECIMAL)zPos;
if (fractal)
fNoise.GradientPerturbFractal(xf, yf, zf);
else
fNoise.GradientPerturb(xf, yf, zf);
xf -= x;
yf -= y;
zf -= zPos;
avg += xf + yf + zf;
maxN = fmax(maxN, fmax(fmax(xf, yf), zf));
minN = fmin(minN, fmin(fmin(xf, yf), zf));
noiseValues[index++] = xf;
noiseValues[index++] = yf;
noiseValues[index++] = zf;
}
}
}
else
{
for (int x = 0; x < size; x++)
{
for (int y = 0; y < size; y++)
{
FN_DECIMAL xf = (FN_DECIMAL)x;
FN_DECIMAL yf = (FN_DECIMAL)y;
if (fractal)
fNoise.GradientPerturbFractal(xf, yf);
else
fNoise.GradientPerturb(xf, yf);
xf -= x;
yf -= y;
avg += xf + yf;
maxN = fmax(maxN, fmax(xf, yf));
minN = fmin(minN, fmin(xf, yf));
noiseValues[index++] = xf;
noiseValues[index++] = yf;
}
}
}
QueryPerformanceCounter(&end);
current += end.QuadPart - start.QuadPart;
if (get3d)
avg /= (index - 1) * 3;
else
avg /= (index - 1) * 2;
index = 0;
FN_DECIMAL scale = 255 / (maxN - minN);
for (int x = 0; x < size; x++)
{
for (int y = 0; y < size; y++)
{
unsigned char red;
unsigned char green;
unsigned char blue;
if (get3d)
{
red = (unsigned char)fmax(0, fmin(255, (noiseValues[index++] - minN) * scale));
green = (unsigned char)fmax(0, fmin(255, (noiseValues[index++] - minN) * scale));
blue = (unsigned char)fmax(0, fmin(255, (noiseValues[index++] - minN) * scale));
}
else
{
RGB rgb = HSV2RGB(HSV{ (unsigned char)((noiseValues[index++] - minN) * scale), 255, (unsigned char)((noiseValues[index++] - minN) * scale) });
red = rgb.r;
green = rgb.g;
blue = rgb.b;
}
if (invertBox->Checked)
{
red = 255 - red;
green = 255 - green;
blue = 255 - blue;
}
bitmap->SetPixel(x, y, Color::FromArgb(255, red, green, blue));
}
}
delete noiseValues;
}
delete pictureBox1->Image;
pictureBox1->Image = bitmap;
maxLabel->Text = maxN.ToString();
minLabel->Text = minN.ToString();
meanLabel->Text = avg.ToString();
timeLabel->Text = long(current / (ticks.QuadPart * 0.001)).ToString();
}
void MyForm::MyForm_Load(System::Object^ sender, System::EventArgs^ e)
{
UpdateBoxes(nullptr, nullptr);
}
void MyForm::UpdateBoxes(System::Object^ sender, System::EventArgs^ e)
{
distance2index0->Value = min(
Convert::ToInt32(distance2index0->Value),
Convert::ToInt32(distance2index1->Value) - 1);
bool fractal = noiseTypeList->Text->Contains("Fractal");
bool position = noiseTypeList->Text->Contains("Perturb");
fractalTypeBox->Enabled = fractal && !position;
octavesBox->Enabled = fractal;
lacunarityBox->Enabled = fractal;
gainBox->Enabled = fractal;
bool cellular = noiseTypeList->Text->Contains("Cellular");
bool white = noiseTypeList->Text->Contains("White");
bool simplex = noiseTypeList->Text->Contains("Simplex");
bool cubic = noiseTypeList->Text->Contains("Cubic");
bool distance2 = cellular && cellReturnTypeBox->Text->Contains("Distance2");
interpBox->Enabled = !(cellular || white || simplex || cubic);
distanceFunctionBox->Enabled = cellular;
cellReturnTypeBox->Enabled = cellular;
jitterBox->Enabled = cellular;
distance2index0->Enabled = distance2;
distance2index1->Enabled = distance2;
upButton->Enabled = checkBox3D->Checked;
downButton->Enabled = checkBox3D->Checked;
positionWarpBox->Enabled = !position;
warpAmpBox->Enabled = positionWarpBox->SelectedIndex > 0 && !position;
perturbFreqBox->Enabled = positionWarpBox->SelectedIndex > 0 && !position;
if (position)
{
if (checkBox3D->Checked)
noteLabel->Text = "Visualisation of gradient perturb:\nRed = X offset, Green = Y offset, Blue = Z offset";
else
noteLabel->Text = "Visualisation of gradient perturb:\nHue = X offset, Brightness = Y offset";
}
else
noteLabel->Text = "";
RebuildBitmap(nullptr, nullptr);
}
void MyForm::upButton_Click(System::Object^ sender, System::EventArgs^ e)
{
zPos += Convert::ToSingle(frequencyBox->Text) * 100.f;
RebuildBitmap(nullptr, nullptr);
}
void MyForm::downButton_Click(System::Object^ sender, System::EventArgs^ e)
{
zPos -= Convert::ToSingle(frequencyBox->Text) * 100.f;
RebuildBitmap(nullptr, nullptr);
}
static RGB HSV2RGB(HSV hsv)
{
RGB rgb;
unsigned char region, remainder, p, q, t;
if (hsv.s == 0)
{
rgb.r = hsv.v;
rgb.g = hsv.v;
rgb.b = hsv.v;
return rgb;
}
region = hsv.h / 43;
remainder = (hsv.h - (region * 43)) * 6;
p = (hsv.v * (255 - hsv.s)) >> 8;
q = (hsv.v * (255 - ((hsv.s * remainder) >> 8))) >> 8;
t = (hsv.v * (255 - ((hsv.s * (255 - remainder)) >> 8))) >> 8;
switch (region)
{
case 0:
rgb.r = hsv.v; rgb.g = t; rgb.b = p;
break;
case 1:
rgb.r = q; rgb.g = hsv.v; rgb.b = p;
break;
case 2:
rgb.r = p; rgb.g = hsv.v; rgb.b = t;
break;
case 3:
rgb.r = p; rgb.g = q; rgb.b = hsv.v;
break;
case 4:
rgb.r = t; rgb.g = p; rgb.b = hsv.v;
break;
default:
rgb.r = hsv.v; rgb.g = p; rgb.b = q;
break;
}
return rgb;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment