Initial commit, yay

This commit is contained in:
VegOwOtenks 2024-06-13 15:28:21 +02:00
commit 25e26756cd
85 changed files with 7077 additions and 0 deletions

2
src/rand/CMakeLists.txt Normal file
View file

@ -0,0 +1,2 @@
add_library(rand STATIC opensimplex.c
xoshiro256.c)

175
src/rand/opensimplex.c Normal file
View file

@ -0,0 +1,175 @@
/*
* This code is part of the strategy game operational-space.
* operational-space comes with ABSOLUTELY NO WARRANTY and is licensed under GPL-2.0.
* Copyright (C) 2024 VegOwOtenks, Sleppo04
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "opensimplex.h"
float GRADIENTS_2D[] = {6.9808965, 16.853374, 16.853374, 6.9808965, 16.853374, -6.9808965, 6.9808965, -16.853374, -6.9808965, -16.853374, -16.853374, -6.9808965, -16.853374, 6.9808965, -6.9808965, 16.853374, 2.3810537, 18.0859, 11.105002, 14.4723215, 14.4723215, 11.105002, 18.0859, 2.3810537, 18.0859, -2.3810537, 14.4723215, -11.105002, 11.105002, -14.4723215, 2.3810537, -18.0859, -2.3810537, -18.0859, -11.105002, -14.4723215, -14.4723215, -11.105002, -18.0859, -2.3810537, -18.0859, 2.3810537, -14.4723215, 11.105002, -11.105002, 14.4723215, -2.3810537, 18.0859, 6.9808965, 16.853374, 16.853374, 6.9808965, 16.853374, -6.9808965, 6.9808965, -16.853374, -6.9808965, -16.853374, -16.853374, -6.9808965, -16.853374, 6.9808965, -6.9808965, 16.853374, 2.3810537, 18.0859, 11.105002, 14.4723215, 14.4723215, 11.105002, 18.0859, 2.3810537, 18.0859, -2.3810537, 14.4723215, -11.105002, 11.105002, -14.4723215, 2.3810537, -18.0859, -2.3810537, -18.0859, -11.105002, -14.4723215, -14.4723215, -11.105002, -18.0859, -2.3810537, -18.0859, 2.3810537, -14.4723215, 11.105002, -11.105002, 14.4723215, -2.3810537, 18.0859, 6.9808965, 16.853374, 16.853374, 6.9808965, 16.853374, -6.9808965, 6.9808965, -16.853374, -6.9808965, -16.853374, -16.853374, -6.9808965, -16.853374, 6.9808965, -6.9808965, 16.853374, 2.3810537, 18.0859, 11.105002, 14.4723215, 14.4723215, 11.105002, 18.0859, 2.3810537, 18.0859, -2.3810537, 14.4723215, -11.105002, 11.105002, -14.4723215, 2.3810537, -18.0859, -2.3810537, -18.0859, -11.105002, -14.4723215, -14.4723215, -11.105002, -18.0859, -2.3810537, -18.0859, 2.3810537, -14.4723215, 11.105002, -11.105002, 14.4723215, -2.3810537, 18.0859, 6.9808965, 16.853374, 16.853374, 6.9808965, 16.853374, -6.9808965, 6.9808965, -16.853374, -6.9808965, -16.853374, -16.853374, -6.9808965, -16.853374, 6.9808965, -6.9808965, 16.853374, 2.3810537, 18.0859, 11.105002, 14.4723215, 14.4723215, 11.105002, 18.0859, 2.3810537, 18.0859, -2.3810537, 14.4723215, -11.105002, 11.105002, -14.4723215, 2.3810537, -18.0859, -2.3810537, -18.0859, -11.105002, -14.4723215, -14.4723215, -11.105002, -18.0859, -2.3810537, -18.0859, 2.3810537, -14.4723215, 11.105002, -11.105002, 14.4723215, -2.3810537, 18.0859, 6.9808965, 16.853374, 16.853374, 6.9808965, 16.853374, -6.9808965, 6.9808965, -16.853374, -6.9808965, -16.853374, -16.853374, -6.9808965, -16.853374, 6.9808965, -6.9808965, 16.853374, 2.3810537, 18.0859, 11.105002, 14.4723215, 14.4723215, 11.105002, 18.0859, 2.3810537, 18.0859, -2.3810537, 14.4723215, -11.105002, 11.105002, -14.4723215, 2.3810537, -18.0859, -2.3810537, -18.0859, -11.105002, -14.4723215, -14.4723215, -11.105002, -18.0859, -2.3810537, -18.0859, 2.3810537, -14.4723215, 11.105002, -11.105002, 14.4723215, -2.3810537, 18.0859, 6.9808965, 16.853374, 16.853374, 6.9808965, 16.853374, -6.9808965, 6.9808965, -16.853374, -6.9808965, -16.853374, -16.853374, -6.9808965, -16.853374, 6.9808965, -6.9808965, 16.853374};
int OpenSimplex_Floor(double n)
{
return (int) floor(n);
}
float OpenSimplex_2DGrad(int64_t seed, int64_t xsvp, int64_t ysvp, float dx, float dy) {
int64_t hash = seed ^ xsvp ^ ysvp;
hash *= HASH_MULTIPLIER;
hash ^= hash >> (64 - N_GRADS_2D_EXPONENT + 1);
int gi = (int)hash & ((N_GRADS_2D - 1) << 1);
return GRADIENTS_2D[gi | 0] * dx + GRADIENTS_2D[gi | 1] * dy;
}
/**
* 2D OpenSimplex2S/SuperSimplex noise base.
*/
float OpenSimplex_2DNoise_UnskewedBase(int64_t seed, double xs, double ys) {
// Get base points and offsets.
int xsb = OpenSimplex_Floor(xs), ysb = OpenSimplex_Floor(ys);
float xi = (float)(xs - xsb), yi = (float)(ys - ysb);
// Prime pre-multiplication for hash.
int64_t xsbp = xsb * PRIME_X, ysbp = ysb * PRIME_Y;
// Unskew.
float t = (xi + yi) * (float)UNSKEW_2D;
float dx0 = xi + t, dy0 = yi + t;
// First vertex.
float a0 = RSQUARED_2D - dx0 * dx0 - dy0 * dy0;
float value = (a0 * a0) * (a0 * a0) * OpenSimplex_2DGrad(seed, xsbp, ysbp, dx0, dy0);
// Second vertex.
float a1 = (float)(2 * (1 + 2 * UNSKEW_2D) * (1 / UNSKEW_2D + 2)) * t + ((float)(-2 * (1 + 2 * UNSKEW_2D) * (1 + 2 * UNSKEW_2D)) + a0);
float dx1 = dx0 - (float)(1 + 2 * UNSKEW_2D);
float dy1 = dy0 - (float)(1 + 2 * UNSKEW_2D);
value += (a1 * a1) * (a1 * a1) * OpenSimplex_2DGrad(seed, xsbp + PRIME_X, ysbp + PRIME_Y, dx1, dy1);
// Third and fourth vertices.
// Nested conditionals were faster than compact bit logic/arithmetic.
float xmyi = xi - yi;
if (t < UNSKEW_2D) {
if (xi + xmyi > 1) {
float dx2 = dx0 - (float)(3 * UNSKEW_2D + 2);
float dy2 = dy0 - (float)(3 * UNSKEW_2D + 1);
float a2 = RSQUARED_2D - dx2 * dx2 - dy2 * dy2;
if (a2 > 0) {
value += (a2 * a2) * (a2 * a2) * OpenSimplex_2DGrad(seed, xsbp + (PRIME_X << 1), ysbp + PRIME_Y, dx2, dy2);
}
}
else
{
float dx2 = dx0 - (float)UNSKEW_2D;
float dy2 = dy0 - (float)(UNSKEW_2D + 1);
float a2 = RSQUARED_2D - dx2 * dx2 - dy2 * dy2;
if (a2 > 0) {
value += (a2 * a2) * (a2 * a2) * OpenSimplex_2DGrad(seed, xsbp, ysbp + PRIME_Y, dx2, dy2);
}
}
if (yi - xmyi > 1) {
float dx3 = dx0 - (float)(3 * UNSKEW_2D + 1);
float dy3 = dy0 - (float)(3 * UNSKEW_2D + 2);
float a3 = RSQUARED_2D - dx3 * dx3 - dy3 * dy3;
if (a3 > 0) {
value += (a3 * a3) * (a3 * a3) * OpenSimplex_2DGrad(seed, xsbp + PRIME_X, ysbp + (PRIME_Y << 1), dx3, dy3);
}
}
else
{
float dx3 = dx0 - (float)(UNSKEW_2D + 1);
float dy3 = dy0 - (float)UNSKEW_2D;
float a3 = RSQUARED_2D - dx3 * dx3 - dy3 * dy3;
if (a3 > 0) {
value += (a3 * a3) * (a3 * a3) * OpenSimplex_2DGrad(seed, xsbp + PRIME_X, ysbp, dx3, dy3);
}
}
}
else
{
if (xi + xmyi < 0) {
float dx2 = dx0 + (float)(1 + UNSKEW_2D);
float dy2 = dy0 + (float)UNSKEW_2D;
float a2 = RSQUARED_2D - dx2 * dx2 - dy2 * dy2;
if (a2 > 0) {
value += (a2 * a2) * (a2 * a2) * OpenSimplex_2DGrad(seed, xsbp - PRIME_X, ysbp, dx2, dy2);
}
}
else
{
float dx2 = dx0 - (float)(UNSKEW_2D + 1);
float dy2 = dy0 - (float)UNSKEW_2D;
float a2 = RSQUARED_2D - dx2 * dx2 - dy2 * dy2;
if (a2 > 0) {
value += (a2 * a2) * (a2 * a2) * OpenSimplex_2DGrad(seed, xsbp + PRIME_X, ysbp, dx2, dy2);
}
}
if (yi < xmyi) {
float dx2 = dx0 + (float)UNSKEW_2D;
float dy2 = dy0 + (float)(UNSKEW_2D + 1);
float a2 = RSQUARED_2D - dx2 * dx2 - dy2 * dy2;
if (a2 > 0) {
value += (a2 * a2) * (a2 * a2) * OpenSimplex_2DGrad(seed, xsbp, ysbp - PRIME_Y, dx2, dy2);
}
}
else
{
float dx2 = dx0 - (float)UNSKEW_2D;
float dy2 = dy0 - (float)(UNSKEW_2D + 1);
float a2 = RSQUARED_2D - dx2 * dx2 - dy2 * dy2;
if (a2 > 0) {
value += (a2 * a2) * (a2 * a2) * OpenSimplex_2DGrad(seed, xsbp, ysbp + PRIME_Y, dx2, dy2);
}
}
}
return value;
}
/*
* Noise Evaluators
*/
/**
* 2D OpenSimplex2S/SuperSimplex noise, standard lattice orientation.
*/
float OpenSimplex_2DNoise(int64_t seed, double x, double y) {
// Get points for A2* lattice
double s = SKEW_2D * (x + y);
double xs = x + s, ys = y + s;
return OpenSimplex_2DNoise_UnskewedBase(seed, xs, ys);
}
/**
* 2D OpenSimplex2S/SuperSimplex 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,
* unless your map is centered around an equator. It's a slight
* difference, but the option is here to make it easy.
*/
float OpenSimplex_2DNoise_ImprovedX(int64_t seed, double x, double y) {
// Skew transform and rotation baked into one.
double xx = x * ROOT2OVER2;
double yy = y * (ROOT2OVER2 * (1 + 2 * SKEW_2D));
return OpenSimplex_2DNoise_UnskewedBase(seed, yy + xx, yy - xx);
}

52
src/rand/opensimplex.h Normal file
View file

@ -0,0 +1,52 @@
/*
* This code is part of the strategy game operational-space.
* operational-space comes with ABSOLUTELY NO WARRANTY and is licensed under GPL-2.0.
* Copyright (C) 2024 VegOwOtenks, Sleppo04
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef OPENSIMPLEX2S_H
#define OPENSIMPLEX2S_H
#include <stdint.h>
#include <math.h>
#define PRIME_X (0x5205402B9270C86FL)
#define PRIME_Y (0x598CD327003817B5L)
#define HASH_MULTIPLIER (0x53A3F72DEEC546F5L)
#define ROOT2OVER2 (0.7071067811865476)
#define SKEW_2D (0.366025403784439)
#define UNSKEW_2D (-0.21132486540518713)
#define N_GRADS_2D_EXPONENT (7)
#define N_GRADS_2D (1 << N_GRADS_2D_EXPONENT)
#define NORMALIZER_2D (0.05481866495625118)
#define RSQUARED_2D (2.0f / 3.0f)
/// @brief Get the standard noise using the at position x and y with seed seed
/// @param seed
/// @param x
/// @param y
/// @return noise at x, y with seed seed
// TODO: Don't use this one, it has weird diagonal artifacts
float OpenSimplex_2DNoise(int64_t seed, double x, double y);
float OpenSimplex_2DNoise_ImprovedX(int64_t seed, double x, double y);
#endif

106
src/rand/xoshiro256.c Normal file
View file

@ -0,0 +1,106 @@
/*
* This code is part of the strategy game operational-space.
* operational-space comes with ABSOLUTELY NO WARRANTY and is licensed under GPL-2.0.
* Copyright (C) 2024 VegOwOtenks, Sleppo04
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "xoshiro256.h"
uint64_t rotate_uint64_left(uint64_t bytes, int degree)
{
return (bytes << degree) | (bytes >> (64 - degree));
}
uint64_t xoshiro256_next(xoshiro256_state_t* state) {
uint64_t* uint64_state = state->state;
const uint64_t result = rotate_uint64_left(uint64_state[0] + uint64_state[3], 23) + uint64_state[0];
const uint64_t t = uint64_state[1] << 17;
uint64_state[2] ^= uint64_state[0];
uint64_state[3] ^= uint64_state[1];
uint64_state[1] ^= uint64_state[2];
uint64_state[0] ^= uint64_state[3];
uint64_state[2] ^= t;
uint64_state[3] = rotate_uint64_left(uint64_state[3], 45);
return result;
}
/* This is the jump function for the generator. It is equivalent
to 2^128 calls to next(); it can be used to generate 2^128
non-overlapping subsequences for parallel computations. */
void jump(xoshiro256_state_t* state) {
uint64_t* uint64_state = state->state;
static const uint64_t JUMP[] = { 0x180ec6d33cfd0aba, 0xd5a61266f0c9392c, 0xa9582618e03fc9aa, 0x39abdc4529b1661c };
uint64_t s0 = 0;
uint64_t s1 = 0;
uint64_t s2 = 0;
uint64_t s3 = 0;
for(uint64_t i = 0; i < sizeof JUMP / sizeof *JUMP; i++)
for(int b = 0; b < 64; b++) {
if (JUMP[i] & UINT64_C(1) << b) {
s0 ^= uint64_state[0];
s1 ^= uint64_state[1];
s2 ^= uint64_state[2];
s3 ^= uint64_state[3];
}
xoshiro256_next(state);
}
uint64_state[0] = s0;
uint64_state[1] = s1;
uint64_state[2] = s2;
uint64_state[3] = s3;
}
/* This is the long-jump function for the generator. It is equivalent to
2^192 calls to next(); it can be used to generate 2^64 starting points,
from each of which jump() will generate 2^64 non-overlapping
subsequences for parallel distributed computations. */
void long_jump(xoshiro256_state_t* state) {
uint64_t* uint64_state = state->state;
static const uint64_t LONG_JUMP[] = { 0x76e15d3efefdcbbf, 0xc5004e441c522fb3, 0x77710069854ee241, 0x39109bb02acbe635 };
uint64_t s0 = 0;
uint64_t s1 = 0;
uint64_t s2 = 0;
uint64_t s3 = 0;
for(uint64_t i = 0; i < sizeof LONG_JUMP / sizeof *LONG_JUMP; i++)
for(int b = 0; b < 64; b++) {
if (LONG_JUMP[i] & UINT64_C(1) << b) {
s0 ^= uint64_state[0];
s1 ^= uint64_state[1];
s2 ^= uint64_state[2];
s3 ^= uint64_state[3];
}
xoshiro256_next(state);
}
uint64_state[0] = s0;
uint64_state[1] = s1;
uint64_state[2] = s2;
uint64_state[3] = s3;
}

33
src/rand/xoshiro256.h Normal file
View file

@ -0,0 +1,33 @@
/*
* This code is part of the strategy game operational-space.
* operational-space comes with ABSOLUTELY NO WARRANTY and is licensed under GPL-2.0.
* Copyright (C) 2024 VegOwOtenks, Sleppo04
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef XOSHIRO256_H
#define XOSHIRO256_H
#include <stdint.h>
typedef struct XoshiroState {
uint64_t state[4];
} xoshiro256_state_t;
uint64_t rotate_uint64_left(uint64_t bytes, int degree);
uint64_t xoshiro256_next(xoshiro256_state_t *state);
#endif