simplex, particles
This commit is contained in:
parent
1d776855be
commit
dbf4b668bb
5
docs/particles.md
Normal file
5
docs/particles.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
# Particle system
|
||||||
|
|
||||||
|
The particle system works in conjunction with script.
|
||||||
|
|
||||||
|
They are CPU-based particles, which enable a greater amount of particle interactivity thando GPU-based particles.
|
|
@ -5,4 +5,5 @@ The core tenents of Primum are as follows. When choosing features for Primum, th
|
||||||
- Dynamic first. Video games are dynamic, so as much as possible should be dynamically generated. For example, signed distance fields for particle system collision will not be used, as it requires baking sometimes false geometry. We include midi playback, which can be changed in real time far easier than wavs or mp3s.
|
- Dynamic first. Video games are dynamic, so as much as possible should be dynamically generated. For example, signed distance fields for particle system collision will not be used, as it requires baking sometimes false geometry. We include midi playback, which can be changed in real time far easier than wavs or mp3s.
|
||||||
- Marriage of code and editor. Neither completely replaces the other. What is easier to do in code should be done in code, and what should be done in editor should be done in editor. No solutions try to step on the toes of the other solution.
|
- Marriage of code and editor. Neither completely replaces the other. What is easier to do in code should be done in code, and what should be done in editor should be done in editor. No solutions try to step on the toes of the other solution.
|
||||||
- Uniformity. There should not be a specific wind system that interacts with a specific tree system, for example. If there is a "wind" system, it will affect trees, grass, particles, potentially objects, the clouds in the sky, and everything else.
|
- Uniformity. There should not be a specific wind system that interacts with a specific tree system, for example. If there is a "wind" system, it will affect trees, grass, particles, potentially objects, the clouds in the sky, and everything else.
|
||||||
- Mathematics.
|
- Mathematics.
|
||||||
|
- Fast. 240 frames per second on modest hardware.
|
|
@ -57,6 +57,32 @@ cpShape *phys2d_query_pos(cpVect pos) {
|
||||||
return find;
|
return find;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int qhit;
|
||||||
|
void qpoint(cpShape *shape, cpFloat dist, cpVect point, int *data)
|
||||||
|
{
|
||||||
|
qhit++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bbhit(cpShape *shape, int *data)
|
||||||
|
{
|
||||||
|
qhit++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static cpShapeFilter ff = {
|
||||||
|
.group = CP_NO_GROUP,
|
||||||
|
.mask = CP_ALL_CATEGORIES,
|
||||||
|
.categories = CP_ALL_CATEGORIES,
|
||||||
|
};
|
||||||
|
|
||||||
|
int query_point(HMM_Vec2 pos)
|
||||||
|
{
|
||||||
|
qhit = 0;
|
||||||
|
// cpSpacePointQuery(space, pos.cp, 0, filter, qpoint, &qhit);
|
||||||
|
cpSpaceBBQuery(space, cpBBNewForCircle(pos.cp, 2), ff, bbhit, &qhit);
|
||||||
|
return qhit;
|
||||||
|
}
|
||||||
|
|
||||||
int p_compare(void *a, void *b)
|
int p_compare(void *a, void *b)
|
||||||
{
|
{
|
||||||
if (a > b) return 1;
|
if (a > b) return 1;
|
||||||
|
|
|
@ -112,6 +112,7 @@ void shape_gui(struct phys2d_shape *shape);
|
||||||
void phys2d_setup_handlers(gameobject *go);
|
void phys2d_setup_handlers(gameobject *go);
|
||||||
gameobject **phys2d_query_shape(struct phys2d_shape *shape);
|
gameobject **phys2d_query_shape(struct phys2d_shape *shape);
|
||||||
int *phys2d_query_box_points(HMM_Vec2 pos, HMM_Vec2 wh, HMM_Vec2 *points, int n);
|
int *phys2d_query_box_points(HMM_Vec2 pos, HMM_Vec2 wh, HMM_Vec2 *points, int n);
|
||||||
|
int query_point(HMM_Vec2 pos);
|
||||||
|
|
||||||
void flush_collide_cbs();
|
void flush_collide_cbs();
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include "particle.sglsl.h"
|
#include "particle.sglsl.h"
|
||||||
#include "2dphysics.h"
|
#include "2dphysics.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "simplex.h"
|
||||||
|
|
||||||
static emitter **emitters;
|
static emitter **emitters;
|
||||||
|
|
||||||
|
@ -12,6 +13,8 @@ static sg_pipeline par_pipe;
|
||||||
static sg_bindings par_bind;
|
static sg_bindings par_bind;
|
||||||
static int draw_count;
|
static int draw_count;
|
||||||
|
|
||||||
|
#define MAX_PARTICLES 500000
|
||||||
|
|
||||||
struct par_vert {
|
struct par_vert {
|
||||||
HMM_Vec2 pos;
|
HMM_Vec2 pos;
|
||||||
float angle;
|
float angle;
|
||||||
|
@ -50,7 +53,7 @@ void particle_init()
|
||||||
});
|
});
|
||||||
|
|
||||||
par_bind.vertex_buffers[0] = sg_make_buffer(&(sg_buffer_desc){
|
par_bind.vertex_buffers[0] = sg_make_buffer(&(sg_buffer_desc){
|
||||||
.size = sizeof(par_vert)*500,
|
.size = sizeof(par_vert)*MAX_PARTICLES,
|
||||||
.type = SG_BUFFERTYPE_VERTEXBUFFER,
|
.type = SG_BUFFERTYPE_VERTEXBUFFER,
|
||||||
.usage = SG_USAGE_STREAM,
|
.usage = SG_USAGE_STREAM,
|
||||||
.label = "particle buffer"
|
.label = "particle buffer"
|
||||||
|
@ -82,7 +85,7 @@ emitter *make_emitter() {
|
||||||
|
|
||||||
e->life = 10;
|
e->life = 10;
|
||||||
e->explosiveness = 0;
|
e->explosiveness = 0;
|
||||||
e->tte = lerp(e->life/e->max, 0, e->explosiveness);
|
e->tte = lerp(e->explosiveness, e->life/e->max, 0);
|
||||||
e->color.times = NULL;
|
e->color.times = NULL;
|
||||||
e->color.data = NULL;
|
e->color.data = NULL;
|
||||||
e->color.type = LINEAR;
|
e->color.type = LINEAR;
|
||||||
|
@ -134,25 +137,25 @@ void emitters_step(double dt)
|
||||||
emitter_step(emitters[i], dt);
|
emitter_step(emitters[i], dt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct par_vert pv[MAX_PARTICLES];
|
||||||
|
|
||||||
void emitters_draw()
|
void emitters_draw()
|
||||||
{
|
{
|
||||||
draw_count = 0;
|
int draw_count = 0;
|
||||||
|
|
||||||
for (int i = 0; i < arrlen(emitters); i++) {
|
for (int i = 0; i < arrlen(emitters); i++) {
|
||||||
emitter *e = emitters[i];
|
emitter *e = emitters[i];
|
||||||
par_bind.fs.images[0] = e->texture->id;
|
par_bind.fs.images[0] = e->texture->id;
|
||||||
for (int j = 0; j < arrlen(e->particles); j++) {
|
for (int j = 0; j < arrlen(e->particles); j++) {
|
||||||
particle *p = &e->particles[j];
|
particle *p = &e->particles[j];
|
||||||
struct par_vert pv;
|
pv[j].pos = p->pos.xy;
|
||||||
pv.pos = p->pos.xy;
|
pv[j].angle = p->angle;
|
||||||
pv.angle = p->angle;
|
pv[j].scale = HMM_ScaleV2(tex_get_dimensions(e->texture), p->scale);
|
||||||
pv.scale = HMM_ScaleV2(tex_get_dimensions(e->texture), p->scale);
|
pv[j].color = vec2rgba(p->color);
|
||||||
pv.color = vec2rgba(p->color);
|
|
||||||
sg_append_buffer(par_bind.vertex_buffers[0], &(sg_range){.ptr=&pv, .size=sizeof(struct par_vert)});
|
|
||||||
draw_count++;
|
|
||||||
}
|
}
|
||||||
|
sg_append_buffer(par_bind.vertex_buffers[0], &(sg_range){.ptr=&pv, .size=sizeof(struct par_vert)*arrlen(e->particles)});
|
||||||
|
draw_count += arrlen(e->particles);
|
||||||
}
|
}
|
||||||
if (draw_count == 0) return;
|
|
||||||
sg_apply_pipeline(par_pipe);
|
sg_apply_pipeline(par_pipe);
|
||||||
sg_apply_uniforms(SG_SHADERSTAGE_VS, 0, SG_RANGE_REF(projection));
|
sg_apply_uniforms(SG_SHADERSTAGE_VS, 0, SG_RANGE_REF(projection));
|
||||||
sg_apply_bindings(&par_bind);
|
sg_apply_bindings(&par_bind);
|
||||||
|
@ -161,16 +164,25 @@ void emitters_draw()
|
||||||
|
|
||||||
void emitter_step(emitter *e, double dt) {
|
void emitter_step(emitter *e, double dt) {
|
||||||
for (int i = arrlen(e->particles)-1; i >= 0; i--) {
|
for (int i = arrlen(e->particles)-1; i >= 0; i--) {
|
||||||
|
particle p = e->particles[i];
|
||||||
if (e->gravity)
|
if (e->gravity)
|
||||||
e->particles[i].v = HMM_AddV3(e->particles[i].v, HMM_MulV3F((HMM_Vec3){cpSpaceGetGravity(space).x, cpSpaceGetGravity(space).y, 0}, dt));
|
p.v = HMM_AddV3(p.v, HMM_MulV3F((HMM_Vec3){cpSpaceGetGravity(space).x, cpSpaceGetGravity(space).y, 0}, dt));
|
||||||
|
|
||||||
e->particles[i].pos = HMM_AddV3(e->particles[i].pos, HMM_MulV3F(e->particles[i].v, dt));
|
|
||||||
e->particles[i].angle += e->particles[i].av*dt;
|
|
||||||
e->particles[i].life -= dt;
|
|
||||||
e->particles[i].color = sample_sampler(&e->color, (e->life-e->particles[i].life)/e->life);
|
|
||||||
e->particles[i].scale = e->scale;
|
|
||||||
|
|
||||||
if (e->particles[i].life <= 0)
|
// float freq = 1;
|
||||||
|
// p.v = HMM_AddV3(p.v, HMM_MulV3F((HMM_Vec3){Noise2D(p.pos.x*freq, p.pos.y*freq), Noise2D(p.pos.x*freq+5,p.pos.y*freq+5), 0}, 1000*dt));
|
||||||
|
p.v = HMM_AddV3(p.v, HMM_MulV3F((HMM_Vec3){frand(2)-1, frand(2)-1, 0}, 1000*dt));
|
||||||
|
|
||||||
|
p.pos = HMM_AddV3(p.pos, HMM_MulV3F(p.v, dt));
|
||||||
|
p.angle += p.av*dt;
|
||||||
|
p.life -= dt;
|
||||||
|
p.color = sample_sampler(&e->color, (e->life-p.life)/e->life);
|
||||||
|
p.scale = e->scale;
|
||||||
|
e->particles[i] = p;
|
||||||
|
|
||||||
|
if (p.life <= 0)
|
||||||
|
arrdelswap(e->particles,i);
|
||||||
|
|
||||||
|
if (query_point(p.pos.xy))
|
||||||
arrdelswap(e->particles,i);
|
arrdelswap(e->particles,i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,6 +190,6 @@ void emitter_step(emitter *e, double dt) {
|
||||||
e->tte-=dt;
|
e->tte-=dt;
|
||||||
if (e->tte <= 0) {
|
if (e->tte <= 0) {
|
||||||
emitter_spawn(e);
|
emitter_spawn(e);
|
||||||
e->tte = lerp(e->life/e->max,0,e->explosiveness);
|
e->tte = lerp(e->explosiveness, e->life/e->max,0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -120,7 +120,7 @@ struct boundingbox cwh2bb(HMM_Vec2 c, HMM_Vec2 wh);
|
||||||
float *rgba2floats(float *r, struct rgba c);
|
float *rgba2floats(float *r, struct rgba c);
|
||||||
extern sg_blend_state blend_trans;
|
extern sg_blend_state blend_trans;
|
||||||
|
|
||||||
static inline float lerp(float a, float b, float f)
|
static inline float lerp(float f, float a, float b)
|
||||||
{
|
{
|
||||||
return a * (1.0-f)+(b*f);
|
return a * (1.0-f)+(b*f);
|
||||||
}
|
}
|
||||||
|
|
529
source/engine/simplex.c
Normal file
529
source/engine/simplex.c
Normal file
|
@ -0,0 +1,529 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
C source for simplex noise generation,
|
||||||
|
Original Java Source from: http://staffwww.itn.liu.se/~stegu/simplexnoise/simplexnoise.pdf
|
||||||
|
Published originally as a Garrysmod Lua Extension under the pseudonym Levybreak
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
#include "simplex.h"
|
||||||
|
|
||||||
|
double Noise(genericNoise func, int len, double inputs[])
|
||||||
|
{
|
||||||
|
switch (len){
|
||||||
|
case 2:
|
||||||
|
return func.p2(inputs[0], inputs[1]);
|
||||||
|
case 3:
|
||||||
|
return func.p3(inputs[0], inputs[1], inputs[2]);
|
||||||
|
case 4:
|
||||||
|
return func.p4(inputs[0], inputs[1], inputs[2], inputs[3]);
|
||||||
|
default:
|
||||||
|
return func.pn(len, inputs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
double TurbulentNoise(genericNoise func, int dir, int iter, int len, double inputs[])
|
||||||
|
{
|
||||||
|
double ret = fabs(Noise(func, len, inputs));
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
for (i = 0 ; i < iter ; i++){
|
||||||
|
double num = pow(2,iter);
|
||||||
|
double scaled[len];
|
||||||
|
int j = 0;
|
||||||
|
for (j = 0; j < len; j++) {
|
||||||
|
scaled[j] = inputs[len]*(num/i);
|
||||||
|
}
|
||||||
|
ret = ret + (i/num)*fabs(Noise(func, len, scaled));
|
||||||
|
}
|
||||||
|
|
||||||
|
return (double)sin(inputs[dir]+ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
double FractalSumNoise(genericNoise func, int iter, int len, double inputs[])
|
||||||
|
{
|
||||||
|
double ret = Noise(func, len, inputs);
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
for (i = 0 ; i < iter ; i++){
|
||||||
|
double num = pow(2,iter);
|
||||||
|
double scaled[len];
|
||||||
|
int j = 0;
|
||||||
|
for (j = 0; j < len; j++) {
|
||||||
|
scaled[j] = inputs[len]*(num/i);
|
||||||
|
}
|
||||||
|
ret = ret + (i/num)*(Noise(func, len, scaled));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
double FractalSumAbsNoise(genericNoise func, int iter, int len, double inputs[])
|
||||||
|
{
|
||||||
|
double ret = fabs(Noise(func, len, inputs));
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
for (i = 0 ; i < iter ; i++){
|
||||||
|
double num = pow(2,iter);
|
||||||
|
double scaled[len];
|
||||||
|
int j = 0;
|
||||||
|
for (j = 0; j < len; j++) {
|
||||||
|
scaled[j] = inputs[len]*(num/i);
|
||||||
|
}
|
||||||
|
ret = ret + (i/num)*fabs(Noise(func, len, scaled));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int gradients3d[12][3] = {{1,1,0},{-1,1,0},{1,-1,0},{-1,-1,0},
|
||||||
|
{1,0,1},{-1,0,1},{1,0,-1},{-1,0,-1},
|
||||||
|
{0,1,1},{0,-1,1},{0,1,-1},{0,-1,-1}};
|
||||||
|
int gradients4d[32][4] = {{0,1,1,1}, {0,1,1,-1}, {0,1,-1,1}, {0,1,-1,-1},
|
||||||
|
{0,-1,1,1}, {0,-1,1,-1}, {0,-1,-1,1}, {0,-1,-1,-1},
|
||||||
|
{1,0,1,1}, {1,0,1,-1}, {1,0,-1,1}, {1,0,-1,-1},
|
||||||
|
{-1,0,1,1}, {-1,0,1,-1}, {-1,0,-1,1}, {-1,0,-1,-1},
|
||||||
|
{1,1,0,1}, {1,1,0,-1}, {1,-1,0,1}, {1,-1,0,-1},
|
||||||
|
{-1,1,0,1}, {-1,1,0,-1}, {-1,-1,0,1}, {-1,-1,0,-1},
|
||||||
|
{1,1,1,0}, {1,1,-1,0}, {1,-1,1,0}, {1,-1,-1,0},
|
||||||
|
{-1,1,1,0}, {-1,1,-1,0}, {-1,-1,1,0}, {-1,-1,-1,0}};
|
||||||
|
int p[256] = {151,160,137,91,90,15,
|
||||||
|
131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,
|
||||||
|
190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,
|
||||||
|
88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166,
|
||||||
|
77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,
|
||||||
|
102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196,
|
||||||
|
135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123,
|
||||||
|
5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,
|
||||||
|
223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9,
|
||||||
|
129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228,
|
||||||
|
251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107,
|
||||||
|
49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,
|
||||||
|
138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180};
|
||||||
|
|
||||||
|
int perm[512];
|
||||||
|
|
||||||
|
static void con() __attribute__((constructor));
|
||||||
|
|
||||||
|
void con() {
|
||||||
|
int i = 0;
|
||||||
|
for (i = 0 ; i < 255 ; i++) {
|
||||||
|
perm[i] = p[i];
|
||||||
|
perm[i+256] = p[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int simplex[64][4] = {
|
||||||
|
{0,1,2,3},{0,1,3,2},{0,0,0,0},{0,2,3,1},{0,0,0,0},{0,0,0,0},{0,0,0,0},{1,2,3,0},
|
||||||
|
{0,2,1,3},{0,0,0,0},{0,3,1,2},{0,3,2,1},{0,0,0,0},{0,0,0,0},{0,0,0,0},{1,3,2,0},
|
||||||
|
{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},
|
||||||
|
{1,2,0,3},{0,0,0,0},{1,3,0,2},{0,0,0,0},{0,0,0,0},{0,0,0,0},{2,3,0,1},{2,3,1,0},
|
||||||
|
{1,0,2,3},{1,0,3,2},{0,0,0,0},{0,0,0,0},{0,0,0,0},{2,0,3,1},{0,0,0,0},{2,1,3,0},
|
||||||
|
{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},
|
||||||
|
{2,0,1,3},{0,0,0,0},{0,0,0,0},{0,0,0,0},{3,0,1,2},{3,0,2,1},{0,0,0,0},{3,1,2,0},
|
||||||
|
{2,1,0,3},{0,0,0,0},{0,0,0,0},{0,0,0,0},{3,1,0,2},{0,0,0,0},{3,2,0,1},{3,2,1,0}};
|
||||||
|
|
||||||
|
const double e = 2.71828182845904523536;
|
||||||
|
const double PI = 3.14159265358979323846;
|
||||||
|
|
||||||
|
double Dot2D(int tbl[],double x,double y)
|
||||||
|
{
|
||||||
|
return tbl[0]*x + tbl[1]*y;
|
||||||
|
}
|
||||||
|
|
||||||
|
double Dot3D(int tbl[],double x,double y,double z)
|
||||||
|
{
|
||||||
|
return tbl[0]*x + tbl[1]*y + tbl[2]*z;
|
||||||
|
}
|
||||||
|
|
||||||
|
double Dot4D(int tbl[],double x,double y,double z,double w)
|
||||||
|
{
|
||||||
|
return tbl[0]*x + tbl[1]*y + tbl[2]*z + tbl[3]*w;
|
||||||
|
}
|
||||||
|
|
||||||
|
double Noise2D(double xin, double yin)
|
||||||
|
{
|
||||||
|
double n0, n1, n2; // Noise contributions from the three corners
|
||||||
|
// Skew the input space to determine which simplex cell we're in
|
||||||
|
double F2 = 0.5*(sqrt(3.0)-1.0);
|
||||||
|
double s = (xin+yin)*F2; // Hairy factor for 2D
|
||||||
|
int i = floor(xin+s);
|
||||||
|
int j = floor(yin+s);
|
||||||
|
double G2 = (3.0-sqrt(3.0))/6.0;
|
||||||
|
|
||||||
|
double t = (i+j)*G2;
|
||||||
|
double X0 = i-t; // Unskew the cell origin back to (x,y) space
|
||||||
|
double Y0 = j-t;
|
||||||
|
double x0 = xin-X0; // The x,y distances from the cell origin
|
||||||
|
double y0 = yin-Y0;
|
||||||
|
|
||||||
|
// For the 2D case, the simplex shape is an equilateral triangle.
|
||||||
|
// Determine which simplex we are in.
|
||||||
|
int i1, j1; // Offsets for second (middle) corner of simplex in (i,j) coords
|
||||||
|
if(x0>y0){
|
||||||
|
i1=1;
|
||||||
|
j1=0; // lower triangle, XY order: (0,0)->(1,0)->(1,1)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
i1=0;
|
||||||
|
j1=1; // upper triangle, YX order: (0,0)->(0,1)->(1,1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// A step of (1,0) in (i,j) means a step of (1-c,-c) in (x,y), and
|
||||||
|
// a step of (0,1) in (i,j) means a step of (-c,1-c) in (x,y), where
|
||||||
|
// c = (3-sqrt(3))/6
|
||||||
|
|
||||||
|
double x1 = x0 - i1 + G2; // Offsets for middle corner in (x,y) unskewed coords
|
||||||
|
double y1 = y0 - j1 + G2;
|
||||||
|
double x2 = x0 - 1.0 + 2.0 * G2; // Offsets for last corner in (x,y) unskewed coords
|
||||||
|
double y2 = y0 - 1.0 + 2.0 * G2;
|
||||||
|
|
||||||
|
// Work out the hashed gradient indices of the three simplex corners
|
||||||
|
int ii = i & 255;
|
||||||
|
int jj = j & 255;
|
||||||
|
int gi0 = perm[ii+perm[jj]] % 12;
|
||||||
|
int gi1 = perm[ii+i1+perm[jj+j1]] % 12;
|
||||||
|
int gi2 = perm[ii+1+perm[jj+1]] % 12;
|
||||||
|
|
||||||
|
// Calculate the contribution from the three corners
|
||||||
|
double t0 = 0.5 - x0*x0-y0*y0;
|
||||||
|
if (t0<0){
|
||||||
|
n0 = 0.0;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
t0 = t0 * t0;
|
||||||
|
n0 = t0 * t0 * Dot2D(gradients3d[gi0], x0, y0); // (x,y) of Gradients3D used for 2D gradient
|
||||||
|
}
|
||||||
|
|
||||||
|
double t1 = 0.5 - x1*x1-y1*y1;
|
||||||
|
if (t1<0){
|
||||||
|
n1 = 0.0;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
t1 = t1*t1;
|
||||||
|
n1 = t1 * t1 * Dot2D(gradients3d[gi1], x1, y1);
|
||||||
|
}
|
||||||
|
|
||||||
|
double t2 = 0.5 - x2*x2-y2*y2;
|
||||||
|
if (t2<0){
|
||||||
|
n2 = 0.0;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
t2 = t2*t2;
|
||||||
|
n2 = t2 * t2 * Dot2D(gradients3d[gi2], x2, y2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add contributions from each corner to get the final noise value.
|
||||||
|
// The result is scaled to return values in the localerval [-1,1].
|
||||||
|
double ret = (70.0 * (n0 + n1 + n2));
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
double Noise3D(double xin, double yin,double zin)
|
||||||
|
{
|
||||||
|
double n0, n1, n2, n3; // Noise contributions from the four corners
|
||||||
|
|
||||||
|
// Skew the input space to determine which simplex cell we're in
|
||||||
|
double F3 = 1.0/3.0;
|
||||||
|
double s = (xin+yin+zin)*F3; // Very nice and simple skew factor for 3D
|
||||||
|
int i = floor(xin+s);
|
||||||
|
int j = floor(yin+s);
|
||||||
|
int k = floor(zin+s);
|
||||||
|
|
||||||
|
double G3 = 1.0/6.0; // Very nice and simple unskew factor, too
|
||||||
|
double t = (i+j+k)*G3;
|
||||||
|
|
||||||
|
double X0 = i-t; // Unskew the cell origin back to (x,y,z) space
|
||||||
|
double Y0 = j-t;
|
||||||
|
double Z0 = k-t;
|
||||||
|
|
||||||
|
double x0 = xin-X0; // The x,y,z distances from the cell origin
|
||||||
|
double y0 = yin-Y0;
|
||||||
|
double z0 = zin-Z0;
|
||||||
|
|
||||||
|
// For the 3D case, the simplex shape is a slightly irregular tetrahedron.
|
||||||
|
// Determine which simplex we are in.
|
||||||
|
int i1, j1, k1; // Offsets for second corner of simplex in (i,j,k) coords
|
||||||
|
int i2, j2, k2; // Offsets for third corner of simplex in (i,j,k) coords
|
||||||
|
|
||||||
|
if (x0>=y0){
|
||||||
|
if (y0>=z0){
|
||||||
|
i1=1; j1=0; k1=0; i2=1; j2=1; k2=0; // X Y Z order
|
||||||
|
}
|
||||||
|
else if (x0>=z0){
|
||||||
|
i1=1; j1=0; k1=0; i2=1; j2=0; k2=1; // X Z Y order
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
i1=0; j1=0; k1=1; i2=1; j2=0; k2=1; // Z X Y order
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{ // x0<y0
|
||||||
|
if (y0<z0){
|
||||||
|
i1=0; j1=0; k1=1; i2=0; j2=1; k2=1; // Z Y X order
|
||||||
|
}
|
||||||
|
else if (x0<z0){
|
||||||
|
i1=0; j1=1; k1=0; i2=0; j2=1; k2=1; // Y Z X order
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
i1=0; j1=1; k1=0; i2=1; j2=1; k2=0; // Y X Z order
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// A step of (1,0,0) in (i,j,k) means a step of (1-c,-c,-c) in (x,y,z),
|
||||||
|
// a step of (0,1,0) in (i,j,k) means a step of (-c,1-c,-c) in (x,y,z), and
|
||||||
|
// a step of (0,0,1) in (i,j,k) means a step of (-c,-c,1-c) in (x,y,z), where
|
||||||
|
// c = 1/6.
|
||||||
|
|
||||||
|
double x1 = x0 - i1 + G3; // Offsets for second corner in (x,y,z) coords
|
||||||
|
double y1 = y0 - j1 + G3;
|
||||||
|
double z1 = z0 - k1 + G3;
|
||||||
|
|
||||||
|
double x2 = x0 - i2 + 2.0*G3; // Offsets for third corner in (x,y,z) coords
|
||||||
|
double y2 = y0 - j2 + 2.0*G3;
|
||||||
|
double z2 = z0 - k2 + 2.0*G3;
|
||||||
|
|
||||||
|
double x3 = x0 - 1.0 + 3.0*G3; // Offsets for last corner in (x,y,z) coords
|
||||||
|
double y3 = y0 - 1.0 + 3.0*G3;
|
||||||
|
double z3 = z0 - 1.0 + 3.0*G3;
|
||||||
|
|
||||||
|
// Work out the hashed gradient indices of the four simplex corners
|
||||||
|
int ii = i & 255;
|
||||||
|
int jj = j & 255;
|
||||||
|
int kk = k & 255;
|
||||||
|
|
||||||
|
int gi0 = perm[ii+perm[jj+perm[kk]]] % 12;
|
||||||
|
int gi1 = perm[ii+i1+perm[jj+j1+perm[kk+k1]]] % 12;
|
||||||
|
int gi2 = perm[ii+i2+perm[jj+j2+perm[kk+k2]]] % 12;
|
||||||
|
int gi3 = perm[ii+1+perm[jj+1+perm[kk+1]]] % 12;
|
||||||
|
|
||||||
|
// Calculate the contribution from the four corners
|
||||||
|
double t0 = 0.5 - x0*x0 - y0*y0 - z0*z0;
|
||||||
|
|
||||||
|
if (t0<0){
|
||||||
|
n0 = 0.0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
t0 = t0*t0;
|
||||||
|
n0 = t0 * t0 * Dot3D(gradients3d[gi0], x0, y0, z0);
|
||||||
|
}
|
||||||
|
|
||||||
|
double t1 = 0.5 - x1*x1 - y1*y1 - z1*z1;
|
||||||
|
|
||||||
|
if (t1<0){
|
||||||
|
n1 = 0.0;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
t1 = t1*t1;
|
||||||
|
n1 = t1 * t1 * Dot3D(gradients3d[gi1], x1, y1, z1);
|
||||||
|
}
|
||||||
|
|
||||||
|
double t2 = 0.5 - x2*x2 - y2*y2 - z2*z2;
|
||||||
|
|
||||||
|
if (t2<0){
|
||||||
|
n2 = 0.0;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
t2 = t2*t2;
|
||||||
|
n2 = t2 * t2 * Dot3D(gradients3d[gi2], x2, y2, z2);
|
||||||
|
}
|
||||||
|
|
||||||
|
double t3 = 0.5 - x3*x3 - y3*y3 - z3*z3;
|
||||||
|
|
||||||
|
if (t3<0){
|
||||||
|
n3 = 0.0;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
t3 = t3*t3;
|
||||||
|
n3 = t3 * t3 * Dot3D(gradients3d[gi3], x3, y3, z3);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Add contributions from each corner to get the final noise value.
|
||||||
|
// The result is scaled to stay just inside [-1,1]
|
||||||
|
double retval = 32.0*(n0 + n1 + n2 + n3);
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
double Noise4D(double x,double y,double z,double w)
|
||||||
|
{
|
||||||
|
// The skewing and unskewing factors are hairy again for the 4D case
|
||||||
|
double F4 = (sqrt(5.0)-1.0)/4.0;
|
||||||
|
double G4 = (5.0-sqrt(5.0))/20.0;
|
||||||
|
double n0, n1, n2, n3, n4; // Noise contributions from the five corners
|
||||||
|
// Skew the (x,y,z,w) space to determine which cell of 24 simplices we're in
|
||||||
|
double s = (x + y + z + w) * F4; // Factor for 4D skewing
|
||||||
|
int i = floor(x + s);
|
||||||
|
int j = floor(y + s);
|
||||||
|
int k = floor(z + s);
|
||||||
|
int l = floor(w + s);
|
||||||
|
double t = (i + j + k + l) * G4; // Factor for 4D unskewing
|
||||||
|
double X0 = i - t; // Unskew the cell origin back to (x,y,z,w) space
|
||||||
|
double Y0 = j - t;
|
||||||
|
double Z0 = k - t;
|
||||||
|
double W0 = l - t;
|
||||||
|
double x0 = x - X0; // The x,y,z,w distances from the cell origin
|
||||||
|
double y0 = y - Y0;
|
||||||
|
double z0 = z - Z0;
|
||||||
|
double w0 = w - W0;
|
||||||
|
// For the 4D case, the simplex is a 4D shape I won't even try to describe.
|
||||||
|
// To find out which of the 24 possible simplices we're in, we need to
|
||||||
|
// determine the magnitude ordering of x0, y0, z0 and w0.
|
||||||
|
// The method below is a good way of finding the ordering of x,y,z,w and
|
||||||
|
// then find the correct traversal order for the simplex we’re in.
|
||||||
|
// First, six pair-wise comparisons are performed between each possible pair
|
||||||
|
// of the four coordinates, and the results are used to add up binary bits
|
||||||
|
// for an localeger index.
|
||||||
|
int c1 = (x0 > y0) ? 32 : 1;
|
||||||
|
int c2 = (x0 > z0) ? 16 : 1;
|
||||||
|
int c3 = (y0 > z0) ? 8 : 1;
|
||||||
|
int c4 = (x0 > w0) ? 4 : 1;
|
||||||
|
int c5 = (y0 > w0) ? 2 : 1;
|
||||||
|
int c6 = (z0 > w0) ? 1 : 1;
|
||||||
|
int c = c1 + c2 + c3 + c4 + c5 + c6;
|
||||||
|
int i1, j1, k1, l1; // The localeger offsets for the second simplex corner
|
||||||
|
int i2, j2, k2, l2; // The localeger offsets for the third simplex corner
|
||||||
|
int i3, j3, k3, l3; // The localeger offsets for the fourth simplex corner
|
||||||
|
|
||||||
|
// simplex[c] is a 4-vector with the numbers 0, 1, 2 and 3 in some order.
|
||||||
|
// Many values of c will never occur, since e.g. x>y>z>w makes x<z, y<w and x<w
|
||||||
|
// impossible. Only the 24 indices which have non-zero entries make any sense.
|
||||||
|
// We use a thresholding to set the coordinates in turn from the largest magnitude.
|
||||||
|
// The number 3 in the "simplex" array is at the position of the largest coordinate.
|
||||||
|
|
||||||
|
i1 = simplex[c][0]>=3 ? 1 : 0;
|
||||||
|
j1 = simplex[c][1]>=3 ? 1 : 0;
|
||||||
|
k1 = simplex[c][2]>=3 ? 1 : 0;
|
||||||
|
l1 = simplex[c][3]>=3 ? 1 : 0;
|
||||||
|
// The number 2 in the "simplex" array is at the second largest co:dinate.
|
||||||
|
i2 = simplex[c][0]>=2 ? 1 : 0;
|
||||||
|
j2 = simplex[c][1]>=2 ? 1 : 0;
|
||||||
|
k2 = simplex[c][2]>=2 ? 1 : 0;
|
||||||
|
l2 = simplex[c][3]>=2 ? 1 : 0;
|
||||||
|
// The number 1 in the "simplex" array is at the second smallest co:dinate.
|
||||||
|
i3 = simplex[c][0]>=1 ? 1 : 0;
|
||||||
|
j3 = simplex[c][1]>=1 ? 1 : 0;
|
||||||
|
k3 = simplex[c][2]>=1 ? 1 : 0;
|
||||||
|
l3 = simplex[c][3]>=1 ? 1 : 0;
|
||||||
|
// The fifth corner has all coordinate offsets = 1, so no need to look that up.
|
||||||
|
double x1 = x0 - i1 + G4; // Offsets for second corner in (x,y,z,w) coords
|
||||||
|
double y1 = y0 - j1 + G4;
|
||||||
|
double z1 = z0 - k1 + G4;
|
||||||
|
double w1 = w0 - l1 + G4;
|
||||||
|
double x2 = x0 - i2 + 2.0*G4; // Offsets for third corner in (x,y,z,w) coords
|
||||||
|
double y2 = y0 - j2 + 2.0*G4;
|
||||||
|
double z2 = z0 - k2 + 2.0*G4;
|
||||||
|
double w2 = w0 - l2 + 2.0*G4;
|
||||||
|
double x3 = x0 - i3 + 3.0*G4; // Offsets for fourth corner in (x,y,z,w) coords
|
||||||
|
double y3 = y0 - j3 + 3.0*G4;
|
||||||
|
double z3 = z0 - k3 + 3.0*G4;
|
||||||
|
double w3 = w0 - l3 + 3.0*G4;
|
||||||
|
double x4 = x0 - 1.0 + 4.0*G4; // Offsets for last corner in (x,y,z,w) coords
|
||||||
|
double y4 = y0 - 1.0 + 4.0*G4;
|
||||||
|
double z4 = z0 - 1.0 + 4.0*G4;
|
||||||
|
double w4 = w0 - 1.0 + 4.0*G4;
|
||||||
|
|
||||||
|
// Work out the hashed gradient indices of the five simplex corners
|
||||||
|
int ii = i & 255;
|
||||||
|
int jj = j & 255;
|
||||||
|
int kk = k & 255;
|
||||||
|
int ll = l & 255;
|
||||||
|
int gi0 = perm[ii+perm[jj+perm[kk+perm[ll]]]] % 32;
|
||||||
|
int gi1 = perm[ii+i1+perm[jj+j1+perm[kk+k1+perm[ll+l1]]]] % 32;
|
||||||
|
int gi2 = perm[ii+i2+perm[jj+j2+perm[kk+k2+perm[ll+l2]]]] % 32;
|
||||||
|
int gi3 = perm[ii+i3+perm[jj+j3+perm[kk+k3+perm[ll+l3]]]] % 32;
|
||||||
|
int gi4 = perm[ii+1+perm[jj+1+perm[kk+1+perm[ll+1]]]] % 32;
|
||||||
|
|
||||||
|
|
||||||
|
// Calculate the contribution from the five corners
|
||||||
|
double t0 = 0.5 - x0*x0 - y0*y0 - z0*z0 - w0*w0;
|
||||||
|
if (t0<0){
|
||||||
|
n0 = 0.0;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
t0 = t0*t0;
|
||||||
|
n0 = t0 * t0 * Dot4D(gradients4d[gi0], x0, y0, z0, w0);
|
||||||
|
}
|
||||||
|
|
||||||
|
double t1 = 0.5 - x1*x1 - y1*y1 - z1*z1 - w1*w1;
|
||||||
|
if (t1<0){
|
||||||
|
n1 = 0.0;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
t1 = t1*t1;
|
||||||
|
n1 = t1 * t1 * Dot4D(gradients4d[gi1], x1, y1, z1, w1);
|
||||||
|
}
|
||||||
|
|
||||||
|
double t2 = 0.5 - x2*x2 - y2*y2 - z2*z2 - w2*w2;
|
||||||
|
if (t2<0){
|
||||||
|
n2 = 0.0;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
t2 = t2*t2;
|
||||||
|
n2 = t2 * t2 * Dot4D(gradients4d[gi2], x2, y2, z2, w2);
|
||||||
|
}
|
||||||
|
|
||||||
|
double t3 = 0.5 - x3*x3 - y3*y3 - z3*z3 - w3*w3;
|
||||||
|
if (t3<0){
|
||||||
|
n3 = 0.0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
t3 = t3*t3;
|
||||||
|
n3 = t3 * t3 * Dot4D(gradients4d[gi3], x3, y3, z3, w3);
|
||||||
|
}
|
||||||
|
|
||||||
|
double t4 = 0.5 - x4*x4 - y4*y4 - z4*z4 - w4*w4;
|
||||||
|
if (t4<0){
|
||||||
|
n4 = 0.0;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
t4 = t4*t4;
|
||||||
|
n4 = t4 * t4 * Dot4D(gradients4d[gi4], x4, y4, z4, w4);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sum up and scale the result to cover the range [-1,1]
|
||||||
|
|
||||||
|
double retval = 27.0 * (n0 + n1 + n2 + n3 + n4);
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
double GBlur2D(double stdDev, double x, double y)
|
||||||
|
{
|
||||||
|
if (fabs(stdDev)<=0.0) { return 0; }
|
||||||
|
|
||||||
|
double pwr = ((pow(x,2)+pow(y,2))/(2*pow(stdDev,2)))*-1;
|
||||||
|
double ret = (1/(2*PI*pow(stdDev,2)))*pow(e, pwr);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
double GBlur1D(double stdDev, double x)
|
||||||
|
{
|
||||||
|
if (fabs(stdDev)<=0.0) { return 0; }
|
||||||
|
|
||||||
|
double pwr = (pow(x,2)/(2*pow(stdDev,2)))*-1;
|
||||||
|
double ret = (1/(sqrt(2*PI)*stdDev))*pow(e, pwr);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
double octave_3d(double x, double y, double z, int octaves, double persistence)
|
||||||
|
{
|
||||||
|
double total = 0;
|
||||||
|
double frequency = 1;
|
||||||
|
double amplitude = 1;
|
||||||
|
double max = 0;
|
||||||
|
for (int i = 0; i < octaves; i++) {
|
||||||
|
total += Noise3D(x*frequency, y*frequency, z*frequency) * amplitude;
|
||||||
|
max += amplitude;
|
||||||
|
amplitude *= persistence;
|
||||||
|
frequency *= 2;
|
||||||
|
}
|
||||||
|
return total/max;
|
||||||
|
}
|
39
source/engine/simplex.h
Normal file
39
source/engine/simplex.h
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
//externs made available by simplex.c
|
||||||
|
|
||||||
|
#ifndef SIMPLEX_H_INCLUDED
|
||||||
|
#define SIMPLEX_H_INCLUDED
|
||||||
|
|
||||||
|
#define SIMPLEX_X 0
|
||||||
|
#define SIMPLEX_Y 1
|
||||||
|
#define SIMPLEX_Z 2
|
||||||
|
#define SIMPLEX_W 3
|
||||||
|
|
||||||
|
typedef double (*noise2Dptr)(double, double);
|
||||||
|
typedef double (*noise3Dptr)(double, double, double);
|
||||||
|
typedef double (*noise4Dptr)(double, double, double, double);
|
||||||
|
|
||||||
|
typedef double (*noiseNDptr)(int, double[]);
|
||||||
|
|
||||||
|
typedef union NoiseUnion {
|
||||||
|
noise2Dptr p2;
|
||||||
|
noise3Dptr p3;
|
||||||
|
noise4Dptr p4;
|
||||||
|
noiseNDptr pn;
|
||||||
|
} genericNoise;
|
||||||
|
|
||||||
|
extern double Noise2D(double x, double y);
|
||||||
|
extern double Noise3D(double x, double y, double z);
|
||||||
|
extern double Noise4D(double x, double y, double z, double w);
|
||||||
|
|
||||||
|
extern double GBlur1D(double stdDev, double x);
|
||||||
|
extern double GBlur2D(double stdDev, double x, double y);
|
||||||
|
|
||||||
|
extern double Noise(genericNoise func, int len, double args[]);
|
||||||
|
|
||||||
|
extern double TurbulentNoise(genericNoise func, int direction, int iterations, int len, double args[]);
|
||||||
|
extern double FractalSumNoise(genericNoise func, int iterations, int len, double args[]);
|
||||||
|
extern double FractalSumAbsNoise(genericNoise func, int iterations, int len, double args[]);
|
||||||
|
|
||||||
|
double octave_3d(double x, double y, double z, int octaves, double persistence);
|
||||||
|
|
||||||
|
#endif
|
|
@ -306,3 +306,85 @@ HMM_Vec2 tex_get_dimensions(struct Texture *tex) {
|
||||||
float st_s_w(struct glrect st) { return (st.s1 - st.s0); }
|
float st_s_w(struct glrect st) { return (st.s1 - st.s0); }
|
||||||
|
|
||||||
float st_s_h(struct glrect st) { return (st.t1 - st.t0); }
|
float st_s_h(struct glrect st) { return (st.t1 - st.t0); }
|
||||||
|
|
||||||
|
static double fade (double t) { return t*t*t*(t*(t*6-15)+10); }
|
||||||
|
double grad (int hash, double x, double y, double z)
|
||||||
|
{
|
||||||
|
int h = hash&15;
|
||||||
|
double u = h<8 ? x : y;
|
||||||
|
double v = h<4 ? y : h==12||h==14 ? x : z;
|
||||||
|
return ((h&1) == 0 ? u : -u) + ((h&2) == 0 ? v : -v);
|
||||||
|
/* alt */
|
||||||
|
/* switch(hash & 0xF)
|
||||||
|
{
|
||||||
|
case 0x0: return x + y;
|
||||||
|
case 0x1: return -x + y;
|
||||||
|
case 0x2: return x - y;
|
||||||
|
case 0x3: return -x - y;
|
||||||
|
case 0x4: return x + z;
|
||||||
|
case 0x5: return -x + z;
|
||||||
|
case 0x6: return x - z;
|
||||||
|
case 0x7: return -x - z;
|
||||||
|
case 0x8: return y + z;
|
||||||
|
case 0x9: return -y + z;
|
||||||
|
case 0xA: return y - z;
|
||||||
|
case 0xB: return -y - z;
|
||||||
|
case 0xC: return y + x;
|
||||||
|
case 0xD: return -y + z;
|
||||||
|
case 0xE: return y - x;
|
||||||
|
case 0xF: return -y - z;
|
||||||
|
default: return 0; // never happens
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
|
||||||
|
static int p[512] = {151,160,137,91,90,15,
|
||||||
|
131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,
|
||||||
|
190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,
|
||||||
|
88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166,
|
||||||
|
77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,
|
||||||
|
102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196,
|
||||||
|
135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123,
|
||||||
|
5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,
|
||||||
|
223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9,
|
||||||
|
129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228,
|
||||||
|
251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107,
|
||||||
|
49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,
|
||||||
|
138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180,
|
||||||
|
151,160,137,91,90,15,
|
||||||
|
131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,
|
||||||
|
190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,
|
||||||
|
88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166,
|
||||||
|
77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,
|
||||||
|
102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196,
|
||||||
|
135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123,
|
||||||
|
5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,
|
||||||
|
223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9,
|
||||||
|
129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228,
|
||||||
|
251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107,
|
||||||
|
49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,
|
||||||
|
138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180
|
||||||
|
};
|
||||||
|
|
||||||
|
double perlin(double x, double y, double z)
|
||||||
|
{
|
||||||
|
int X = (int)floor(x)&255;
|
||||||
|
int Y = (int)floor(y)&255;
|
||||||
|
int Z = (int)floor(z)&255;
|
||||||
|
x -= floor(x);
|
||||||
|
y -= floor(y);
|
||||||
|
z -= floor(z);
|
||||||
|
double u = fade(x),
|
||||||
|
v = fade(y),
|
||||||
|
w = fade(z);
|
||||||
|
int A = p[X ]+Y, AA = p[A]+Z, AB = p[A+1]+Z,
|
||||||
|
B = p[X+1]+Y, BA = p[B]+Z, BB = p[B+1]+Z;
|
||||||
|
|
||||||
|
return lerp(w, lerp(v, lerp(u, grad(p[AA ], x , y , z ),
|
||||||
|
grad(p[BA ], x-1, y , z )),
|
||||||
|
lerp(u, grad(p[AB ], x , y-1, z ),
|
||||||
|
grad(p[BB ], x-1, y-1, z ))),
|
||||||
|
lerp(v, lerp(u, grad(p[AA+1], x , y , z-1 ),
|
||||||
|
grad(p[BA+1], x-1, y , z-1 )),
|
||||||
|
lerp(u, grad(p[AB+1], x , y-1, z-1 ),
|
||||||
|
grad(p[BB+1], x-1, y-1, z-1 ))));
|
||||||
|
}
|
||||||
|
|
|
@ -55,4 +55,6 @@ int *gif_delays(const char *path);
|
||||||
struct glrect tex_get_rect(struct Texture *tex);
|
struct glrect tex_get_rect(struct Texture *tex);
|
||||||
HMM_Vec2 tex_get_dimensions(struct Texture *tex);
|
HMM_Vec2 tex_get_dimensions(struct Texture *tex);
|
||||||
|
|
||||||
|
double perlin(double x, double y, double z);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -10,6 +10,10 @@
|
||||||
#include "spline.h"
|
#include "spline.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include "particle.h"
|
#include "particle.h"
|
||||||
|
#include "simplex.h"
|
||||||
|
|
||||||
|
#define FNL_IMPL
|
||||||
|
#include "FastNoiseLite.h"
|
||||||
|
|
||||||
#include "datastream.h"
|
#include "datastream.h"
|
||||||
|
|
||||||
|
@ -104,6 +108,8 @@ void c_init() {
|
||||||
script_evalf("Game.init();");
|
script_evalf("Game.init();");
|
||||||
|
|
||||||
particle_init();
|
particle_init();
|
||||||
|
|
||||||
|
YughWarn("simplex %.17lf", Noise3D(3.14,42,7.001));
|
||||||
}
|
}
|
||||||
|
|
||||||
int frame_fps() { return 1.0/sapp_frame_duration(); }
|
int frame_fps() { return 1.0/sapp_frame_duration(); }
|
||||||
|
|
Loading…
Reference in a new issue