This commit is contained in:
Tobias Berger 2021-11-16 22:40:57 +01:00
parent 7edd606fee
commit 18f2b62f37
3 changed files with 50 additions and 255 deletions

View file

@ -1,27 +0,0 @@
typedef struct
{
int xsv, ysv;
double dx, dy;
} LatticePoint2D;
typedef struct
{
double dx, dy;
} Grad2;
typedef struct
{
short *perm;
Grad2 *permGrad2;
} OpenSimplexGradients;
typedef struct
{
Grad2 *GRADIENTS_2D;
LatticePoint2D **LOOKUP_2D;
} OpenSimplexEnv;
OpenSimplexEnv *initOpenSimplex();
OpenSimplexGradients *newOpenSimplexGradients(OpenSimplexEnv *ose, long seed);
double noise2(OpenSimplexEnv *ose, OpenSimplexGradients *osg, double x, double y);
double noise2_XBeforeY(OpenSimplexEnv *ose, OpenSimplexGradients *osg, double x, double y);

View file

@ -1,203 +0,0 @@
#include <stdlib.h>
#include <math.h>
#include <stdbool.h>
#include <string.h>
#include "OpenSimplex2F.h"
#define PSIZE 2048
#define PMASK 2047
#define N2 0.01001634121365712
/*
* Utility
*/
int inline _fastFloor(double x)
{
int xi = (int)x;
return x < xi ? xi - 1 : xi;
}
Grad2 inline *_newGrad2Arr(unsigned int size)
{
return (Grad2 *)malloc(sizeof(Grad2) * size);
}
short inline *_newShortArr(unsigned int size)
{
return (short *)malloc(sizeof(short) * size);
}
Grad2 _newGrad2(double dx, double dy)
{
Grad2 grad2;
grad2.dx = dx;
grad2.dy = dy;
return grad2;
}
Grad2 *_newGrad2ConstArray()
{
Grad2 *arr = (Grad2 *)malloc(sizeof(Grad2) * 24);
int i = 0;
arr[i++] = _newGrad2(0.130526192220052, 0.99144486137381);
arr[i++] = _newGrad2(0.38268343236509, 0.923879532511287);
arr[i++] = _newGrad2(0.608761429008721, 0.793353340291235);
arr[i++] = _newGrad2(0.793353340291235, 0.608761429008721);
arr[i++] = _newGrad2(0.923879532511287, 0.38268343236509);
arr[i++] = _newGrad2(0.99144486137381, 0.130526192220051);
arr[i++] = _newGrad2(0.99144486137381, -0.130526192220051);
arr[i++] = _newGrad2(0.923879532511287, -0.38268343236509);
arr[i++] = _newGrad2(0.793353340291235, -0.60876142900872);
arr[i++] = _newGrad2(0.608761429008721, -0.793353340291235);
arr[i++] = _newGrad2(0.38268343236509, -0.923879532511287);
arr[i++] = _newGrad2(0.130526192220052, -0.99144486137381);
arr[i++] = _newGrad2(-0.130526192220052, -0.99144486137381);
arr[i++] = _newGrad2(-0.38268343236509, -0.923879532511287);
arr[i++] = _newGrad2(-0.608761429008721, -0.793353340291235);
arr[i++] = _newGrad2(-0.793353340291235, -0.608761429008721);
arr[i++] = _newGrad2(-0.923879532511287, -0.38268343236509);
arr[i++] = _newGrad2(-0.99144486137381, -0.130526192220052);
arr[i++] = _newGrad2(-0.99144486137381, 0.130526192220051);
arr[i++] = _newGrad2(-0.923879532511287, 0.38268343236509);
arr[i++] = _newGrad2(-0.793353340291235, 0.608761429008721);
arr[i++] = _newGrad2(-0.608761429008721, 0.793353340291235);
arr[i++] = _newGrad2(-0.38268343236509, 0.923879532511287);
arr[i++] = _newGrad2(-0.130526192220052, 0.99144486137381);
Grad2 *gradients2D = _newGrad2Arr(PSIZE);
for (int i = 0; i < 24; i++)
{
arr[i].dx /= N2;
arr[i].dy /= N2;
}
for (int i = 0; i < PSIZE; i++)
{
gradients2D[i] = arr[i % 24];
}
return gradients2D;
}
LatticePoint2D *_newLatticePoint2D(int xsv, int ysv)
{
LatticePoint2D *plp2D = (LatticePoint2D *)malloc(sizeof(LatticePoint2D));
plp2D->xsv = xsv;
plp2D->ysv = ysv;
double ssv = (xsv + ysv) * -0.211324865405187;
plp2D->dx = -xsv - ssv;
plp2D->dy = -ysv - ssv;
return plp2D;
}
LatticePoint2D **_newLatticePoint2DConstArray()
{
LatticePoint2D **plp2DArr = (LatticePoint2D **)malloc(sizeof(LatticePoint2D *) * 4);
plp2DArr[0] = _newLatticePoint2D(1, 0);
plp2DArr[1] = _newLatticePoint2D(0, 0);
plp2DArr[2] = _newLatticePoint2D(1, 1);
plp2DArr[3] = _newLatticePoint2D(0, 1);
return plp2DArr;
}
/*
* Noise Evaluators
*/
/**
* 2D Simplex noise base.
* Lookup table implementation inspired by DigitalShadow.
*/
double _noise2_Base(OpenSimplexEnv *ose, OpenSimplexGradients *osg, double xs, double ys)
{
double value = 0;
// Get base points and offsets
int xsb = _fastFloor(xs), ysb = _fastFloor(ys);
double xsi = xs - xsb, ysi = ys - ysb;
// Index to point list
int index = (int)((ysi - xsi) / 2 + 1);
double ssi = (xsi + ysi) * -0.211324865405187;
double xi = xsi + ssi, yi = ysi + ssi;
// Point contributions
for (int i = 0; i < 3; i++)
{
LatticePoint2D *c = ose->LOOKUP_2D[index + i];
double dx = xi + c->dx, dy = yi + c->dy;
double attn = 0.5 - dx * dx - dy * dy;
if (attn <= 0)
continue;
int pxm = (xsb + c->xsv) & PMASK, pym = (ysb + c->ysv) & PMASK;
Grad2 grad = osg->permGrad2[osg->perm[pxm] ^ pym];
double extrapolation = grad.dx * dx + grad.dy * dy;
attn *= attn;
value += attn * attn * extrapolation;
}
return value;
}
/**
* 2D Simplex noise, standard lattice orientation.
*/
double noise2(OpenSimplexEnv *ose, OpenSimplexGradients *osg, double x, double y)
{
// Get points for A2* lattice
double s = 0.366025403784439 * (x + y);
double xs = x + s, ys = y + s;
return _noise2_Base(ose, osg, xs, ys);
}
/**
* 2D Simplex noise, with Y pointing down the main diagonal.
* Might be better for a 2D sandbox style game, where Y is vertical.
* Probably slightly less optimal for heightmaps or continent maps.
*/
double noise2_XBeforeY(OpenSimplexEnv *ose, OpenSimplexGradients *osg, double x, double y)
{
// Skew transform and rotation baked into one.
double xx = x * 0.7071067811865476;
double yy = y * 1.224744871380249;
return _noise2_Base(ose, osg, yy + xx, yy - xx);
}
OpenSimplexEnv *initOpenSimplex()
{
OpenSimplexEnv *ose = (OpenSimplexEnv *)malloc(sizeof(OpenSimplexEnv));
ose->GRADIENTS_2D = _newGrad2ConstArray();
ose->LOOKUP_2D = _newLatticePoint2DConstArray();
return ose;
}
OpenSimplexGradients *newOpenSimplexGradients(OpenSimplexEnv *ose, long seed)
{
OpenSimplexGradients *osg = (OpenSimplexGradients *)malloc(sizeof(OpenSimplexGradients));
osg->perm = _newShortArr(PSIZE);
osg->permGrad2 = _newGrad2Arr(PSIZE);
short *source = _newShortArr(PSIZE);
for (short i = 0; i < PSIZE; i++)
{
source[i] = i;
}
for (int i = PSIZE - 1; i >= 0; i--)
{
seed = seed * 6364136223846793005L + 1442695040888963407L;
int r = (int)((seed + 31) % (i + 1));
if (r < 0)
{
r += (i + 1);
}
osg->perm[i] = source[r];
osg->permGrad2[i] = ose->GRADIENTS_2D[osg->perm[i]];
source[r] = source[i];
}
return osg;
}

View file

@ -6,28 +6,30 @@
#define INITIAL_SCREEN_WIDTH 900
#define INITIAL_SCREEN_HEIGHT 900
#define SCALE 64
#define SCREEN_SCALE 8
// #define NOISE_PERIOD 4
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
int noisePeriod = 4;
SetTraceLogLevel(LOG_ALL);
SetConfigFlags(FLAG_WINDOW_RESIZABLE | FLAG_VSYNC_HINT);
SetConfigFlags(FLAG_WINDOW_RESIZABLE);
InitWindow(INITIAL_SCREEN_WIDTH, INITIAL_SCREEN_HEIGHT, "raylib [core] example - basic window");
SetTargetFPS(5); // Set our game to run at 60 frames-per-second
// SetTargetFPS(5);
fnl_state state = fnlCreateState();
state.seed = 0;
state.frequency = 1.0f / (float)SCALE;
state.frequency = 1.0f / (float)noisePeriod;
state.fractal_type = FNL_FRACTAL_FBM;
state.octaves = 1;
state.noise_type = FNL_NOISE_PERLIN;
state.noise_type = 0;
int virtualScreenWidth = GetScreenWidth() / SCALE;
int virtualScreenHeight = GetScreenHeight() / SCALE;
float virtualRatio = (float)virtualScreenWidth / (float)virtualScreenHeight;
int virtualScreenWidth = GetScreenWidth() / SCREEN_SCALE;
int virtualScreenHeight = GetScreenHeight() / SCREEN_SCALE;
RenderTexture2D *target = (RenderTexture2D *)MemAlloc(sizeof(RenderTexture2D));
@ -40,10 +42,10 @@ int main(void)
0.0f,
(float)target->texture.width,
-(float)target->texture.height};
Rectangle destRec = {-virtualRatio,
-virtualRatio,
GetScreenWidth() + (virtualRatio * 2.0f),
GetScreenHeight() + (virtualRatio * 2.0f)};
Rectangle destRec = {0.0f,
0.0f,
GetScreenWidth(),
GetScreenHeight()};
//--------------------------------------------------------------------------------------
@ -64,9 +66,8 @@ int main(void)
if (IsWindowResized())
{
TraceLog(LOG_DEBUG, "Resized.");
int virtualScreenWidth = GetScreenWidth() / SCALE;
int virtualScreenHeight = GetScreenHeight() / SCALE;
float virtualRatio = (float)virtualScreenWidth / (float)virtualScreenHeight;
virtualScreenWidth = GetScreenWidth() / SCREEN_SCALE;
virtualScreenHeight = GetScreenHeight() / SCREEN_SCALE;
UnloadRenderTexture(*target);
*target = LoadRenderTexture(virtualScreenWidth, virtualScreenHeight);
@ -74,7 +75,7 @@ int main(void)
sourceRec = (Rectangle){0.0f,
0.0f,
(float)target->texture.width,
(float)target->texture.height};
-(float)target->texture.height};
destRec = (Rectangle){0.0f,
0.0f,
@ -92,12 +93,37 @@ int main(void)
}
if (IsKeyPressed(KEY_UP) || IsKeyPressed(KEY_DOWN))
{
state.octaves = state.octaves <= 0 ? 1 : state.octaves;
TraceLog(LOG_INFO, TextFormat("Octaves: %i", state.octaves));
}
if (IsKeyPressed(KEY_LEFT))
{
noisePeriod--;
}
if (IsKeyPressed(KEY_RIGHT))
{
noisePeriod++;
}
if (IsKeyPressed(KEY_LEFT) || IsKeyPressed(KEY_RIGHT))
{
noisePeriod = noisePeriod <= 0 ? 1 : noisePeriod;
state.frequency = 1.0f / (float)noisePeriod;
TraceLog(LOG_INFO, TextFormat("Noise period: %i", noisePeriod));
}
if (IsKeyPressed(KEY_R))
{
noisePeriod = 4;
state.frequency = 1.0f / (float)noisePeriod;
state.octaves = 1;
}
float frameTime = GetFrameTime();
offset += (double)frameTime * 10.0;
TraceLog(LOG_INFO, TextFormat("fps: %f (%fms ; total %fs)", 1.0 / frameTime, frameTime * 1000.0, offset / 10.0));
offset += (double)frameTime * 10.0 * 0;
//----------------------------------------------------------------------------------
@ -112,9 +138,9 @@ int main(void)
{
for (int y = 0; y < virtualScreenHeight; y++)
{
int noise = (fnlGetNoise2D(&state, ((double)x) + offset, ((double)y) + offset / 2.0) + 1.0) / 2.0 * 255.0; //(noise2(simplexEnv, simplexGradiants, x / 64.0 + offset, y / 64.0 + offset / 2.0) + 1.0) / 2 * 255;
int noise = (fnlGetNoise2D(&state, ((double)x) + (int)offset, ((double)y) + (int)offset / 2.0) + 1.0) / 2.0 * 255.0;
DrawPixel(x, y, (Color){0, noise, noise, 255});
DrawPixel(x, y, (Color){255 - noise, noise, noise, 255});
}
}
@ -123,11 +149,10 @@ int main(void)
BeginDrawing();
{
ClearBackground(RAYWHITE);
// BeginMode2D();
{
DrawTexturePro(target->texture, sourceRec, destRec, (Vector2){0.0f, 0.0f}, 0.0f, WHITE);
}
// EndMode2D();
DrawTexturePro(target->texture, sourceRec, destRec, (Vector2){0.0f, 0.0f}, 0.0f, WHITE);
char const *drawText = TextFormat("Press [SPACEBAR] to cycle through different noise algorithms, arrow keys to control variables\n%i FPS\nNoise Period (Frequency): %i (%f)\nNoise Octaves: %i", GetFPS(), noisePeriod, state.frequency, state.octaves);
DrawRectangle(0, 0, MeasureText(drawText, 20), (int)(20 * 5.5), WHITE);
DrawText(drawText, 0, 0, 20, BLACK);
}
EndDrawing();
//----------------------------------------------------------------------------------