Skip to content

Commit 1645e98

Browse files
committed
Add perlin noise functions to flecs script
1 parent e90d9d0 commit 1645e98

File tree

4 files changed

+367
-0
lines changed

4 files changed

+367
-0
lines changed

distr/flecs.c

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50284,6 +50284,15 @@ int flecs_script_apply_annot(
5028450284
ecs_script_entity_t *node,
5028550285
ecs_script_annot_t *annot);
5028650286

50287+
/* Script functions */
50288+
double flecs_lerp(
50289+
double a,
50290+
double b,
50291+
double t);
50292+
50293+
void FlecsScriptMathPerlinImport(
50294+
ecs_world_t *world);
50295+
5028750296
#endif // FLECS_SCRIPT
5028850297
#endif // FLECS_SCRIPT_PRIVATE_H
5028950298

@@ -64705,6 +64714,26 @@ void flecs_script_rng_get_uint(
6470564714
}
6470664715
}
6470764716

64717+
double flecs_lerp(
64718+
double a,
64719+
double b,
64720+
double t)
64721+
{
64722+
return a + t * (b - a);
64723+
}
64724+
64725+
void flecs_script_lerp(
64726+
const ecs_function_ctx_t *ctx,
64727+
int32_t argc,
64728+
const ecs_value_t *argv,
64729+
ecs_value_t *result)
64730+
{
64731+
double a = *(double*)argv[0].ptr;
64732+
double b = *(double*)argv[1].ptr;
64733+
double t = *(double*)argv[2].ptr;
64734+
*(double*)result->ptr = flecs_lerp(a, b, t);
64735+
}
64736+
6470864737
#define FLECS_MATH_FUNC_F64(name, ...)\
6470964738
static\
6471064739
void flecs_math_##name(\
@@ -64929,6 +64958,160 @@ void FlecsScriptMathImport(
6492964958
},
6493064959
.callback = flecs_script_rng_get_uint
6493164960
});
64961+
64962+
ecs_function(world, {
64963+
.name = "lerp",
64964+
.parent = ecs_id(FlecsScriptMath),
64965+
.return_type = ecs_id(ecs_f64_t),
64966+
.params = {
64967+
{ .name = "a", .type = ecs_id(ecs_f64_t) },
64968+
{ .name = "b", .type = ecs_id(ecs_f64_t) },
64969+
{ .name = "t", .type = ecs_id(ecs_f64_t) }
64970+
},
64971+
.callback = flecs_script_lerp
64972+
});
64973+
64974+
FlecsScriptMathPerlinImport(world);
64975+
}
64976+
64977+
#endif
64978+
64979+
/**
64980+
* @file addons/script/functions_math_perlin.c
64981+
* @brief Perlin noise functions for flecs script.
64982+
*
64983+
* - flecs_perlin2(x, y): returns noise in ~[-1, 1]
64984+
* - flecs_perlin_seed(seed): initializes permutation table for repeatable noise
64985+
*/
64986+
64987+
64988+
#ifdef FLECS_SCRIPT_MATH
64989+
#include <math.h>
64990+
64991+
static uint8_t flecs_perlin_perm[512];
64992+
64993+
static
64994+
uint32_t flecs_perlin_xs32(
64995+
uint32_t *state)
64996+
{
64997+
uint32_t x = *state;
64998+
x ^= x << 13;
64999+
x ^= x >> 17;
65000+
x ^= x << 5;
65001+
*state = x;
65002+
return x;
65003+
}
65004+
65005+
void flecs_perlin_seed(
65006+
uint32_t seed)
65007+
{
65008+
uint8_t p[256];
65009+
for (int i = 0; i < 256; i++) p[i] = (uint8_t)i;
65010+
65011+
uint32_t st = (seed ? seed : 0xA341316Cu);
65012+
65013+
for (int i = 255; i > 0; i--) {
65014+
uint32_t r = flecs_perlin_xs32(&st);
65015+
int j = (int)(r % (uint32_t)(i + 1));
65016+
uint8_t tmp = p[i];
65017+
p[i] = p[j];
65018+
p[j] = tmp;
65019+
}
65020+
65021+
for (int i = 0; i < 256; i++) {
65022+
flecs_perlin_perm[i] = p[i];
65023+
flecs_perlin_perm[i + 256] = p[i];
65024+
}
65025+
}
65026+
65027+
static
65028+
double flecs_perlin_fade(
65029+
double t)
65030+
{
65031+
return t * t * t * (t * (t * 6.0 - 15.0) + 10.0);
65032+
}
65033+
65034+
static
65035+
double flecs_perlin_grad2(
65036+
int hash,
65037+
double x,
65038+
double y)
65039+
{
65040+
switch (hash & 7) {
65041+
case 0: return x + y;
65042+
case 1: return -x + y;
65043+
case 2: return x - y;
65044+
case 3: return -x - y;
65045+
case 4: return x;
65046+
case 5: return -x;
65047+
case 6: return y;
65048+
default: return -y;
65049+
}
65050+
}
65051+
65052+
static
65053+
double flecs_perlin2(
65054+
double x,
65055+
double y)
65056+
{
65057+
int X = (int)floor(x) & 255;
65058+
int Y = (int)floor(y) & 255;
65059+
65060+
double xf = x - floor(x);
65061+
double yf = y - floor(y);
65062+
65063+
double u = flecs_perlin_fade(xf);
65064+
double v = flecs_perlin_fade(yf);
65065+
65066+
int aa = flecs_perlin_perm[flecs_perlin_perm[X] + Y];
65067+
int ab = flecs_perlin_perm[flecs_perlin_perm[X] + Y + 1];
65068+
int ba = flecs_perlin_perm[flecs_perlin_perm[X + 1] + Y];
65069+
int bb = flecs_perlin_perm[flecs_perlin_perm[X + 1] + Y + 1];
65070+
65071+
double x1 = flecs_lerp(
65072+
flecs_perlin_grad2(aa, xf, yf),
65073+
flecs_perlin_grad2(ba, xf - 1, yf),
65074+
u);
65075+
65076+
double x2 = flecs_lerp(
65077+
flecs_perlin_grad2(ab, xf, yf - 1),
65078+
flecs_perlin_grad2(bb, xf - 1, yf - 1),
65079+
u);
65080+
65081+
return flecs_lerp(x1, x2, v);
65082+
}
65083+
65084+
static
65085+
void flecs_script_perlin2(
65086+
const ecs_function_ctx_t *ctx,
65087+
int32_t argc,
65088+
const ecs_value_t *argv,
65089+
ecs_value_t *result)
65090+
{
65091+
(void)argc;
65092+
double x = *(double*)argv[0].ptr;
65093+
double y = *(double*)argv[1].ptr;
65094+
*(double*)result->ptr = flecs_perlin2(x, y);
65095+
}
65096+
65097+
void FlecsScriptMathPerlinImport(
65098+
ecs_world_t *world)
65099+
{
65100+
ecs_entity_t FlecsScriptMath = ecs_lookup(world, "flecs.script.math");
65101+
ecs_assert(FlecsScriptMath != 0, ECS_INTERNAL_ERROR, NULL);
65102+
65103+
flecs_perlin_seed(1234);
65104+
65105+
ecs_function(world, {
65106+
.name = "perlin2",
65107+
.parent = FlecsScriptMath,
65108+
.return_type = ecs_id(ecs_f64_t),
65109+
.params = {
65110+
{ .name = "x", .type = ecs_id(ecs_f64_t) },
65111+
{ .name = "y", .type = ecs_id(ecs_f64_t) },
65112+
},
65113+
.callback = flecs_script_perlin2
65114+
});
6493265115
}
6493365116

6493465117
#endif

src/addons/script/functions_math.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,26 @@ void flecs_script_rng_get_uint(
137137
}
138138
}
139139

140+
double flecs_lerp(
141+
double a,
142+
double b,
143+
double t)
144+
{
145+
return a + t * (b - a);
146+
}
147+
148+
void flecs_script_lerp(
149+
const ecs_function_ctx_t *ctx,
150+
int32_t argc,
151+
const ecs_value_t *argv,
152+
ecs_value_t *result)
153+
{
154+
double a = *(double*)argv[0].ptr;
155+
double b = *(double*)argv[1].ptr;
156+
double t = *(double*)argv[2].ptr;
157+
*(double*)result->ptr = flecs_lerp(a, b, t);
158+
}
159+
140160
#define FLECS_MATH_FUNC_F64(name, ...)\
141161
static\
142162
void flecs_math_##name(\
@@ -361,6 +381,20 @@ void FlecsScriptMathImport(
361381
},
362382
.callback = flecs_script_rng_get_uint
363383
});
384+
385+
ecs_function(world, {
386+
.name = "lerp",
387+
.parent = ecs_id(FlecsScriptMath),
388+
.return_type = ecs_id(ecs_f64_t),
389+
.params = {
390+
{ .name = "a", .type = ecs_id(ecs_f64_t) },
391+
{ .name = "b", .type = ecs_id(ecs_f64_t) },
392+
{ .name = "t", .type = ecs_id(ecs_f64_t) }
393+
},
394+
.callback = flecs_script_lerp
395+
});
396+
397+
FlecsScriptMathPerlinImport(world);
364398
}
365399

366400
#endif
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
/**
2+
* @file addons/script/functions_math_perlin.c
3+
* @brief Perlin noise functions for flecs script.
4+
*
5+
* - flecs_perlin2(x, y): returns noise in ~[-1, 1]
6+
* - flecs_perlin_seed(seed): initializes permutation table for repeatable noise
7+
*/
8+
9+
#include "flecs.h"
10+
11+
#ifdef FLECS_SCRIPT_MATH
12+
#include "script.h"
13+
#include <math.h>
14+
15+
static uint8_t flecs_perlin_perm[512];
16+
17+
static
18+
uint32_t flecs_perlin_xs32(
19+
uint32_t *state)
20+
{
21+
uint32_t x = *state;
22+
x ^= x << 13;
23+
x ^= x >> 17;
24+
x ^= x << 5;
25+
*state = x;
26+
return x;
27+
}
28+
29+
void flecs_perlin_seed(
30+
uint32_t seed)
31+
{
32+
uint8_t p[256];
33+
for (int i = 0; i < 256; i++) p[i] = (uint8_t)i;
34+
35+
uint32_t st = (seed ? seed : 0xA341316Cu);
36+
37+
for (int i = 255; i > 0; i--) {
38+
uint32_t r = flecs_perlin_xs32(&st);
39+
int j = (int)(r % (uint32_t)(i + 1));
40+
uint8_t tmp = p[i];
41+
p[i] = p[j];
42+
p[j] = tmp;
43+
}
44+
45+
for (int i = 0; i < 256; i++) {
46+
flecs_perlin_perm[i] = p[i];
47+
flecs_perlin_perm[i + 256] = p[i];
48+
}
49+
}
50+
51+
static
52+
double flecs_perlin_fade(
53+
double t)
54+
{
55+
return t * t * t * (t * (t * 6.0 - 15.0) + 10.0);
56+
}
57+
58+
static
59+
double flecs_perlin_grad2(
60+
int hash,
61+
double x,
62+
double y)
63+
{
64+
switch (hash & 7) {
65+
case 0: return x + y;
66+
case 1: return -x + y;
67+
case 2: return x - y;
68+
case 3: return -x - y;
69+
case 4: return x;
70+
case 5: return -x;
71+
case 6: return y;
72+
default: return -y;
73+
}
74+
}
75+
76+
static
77+
double flecs_perlin2(
78+
double x,
79+
double y)
80+
{
81+
int X = (int)floor(x) & 255;
82+
int Y = (int)floor(y) & 255;
83+
84+
double xf = x - floor(x);
85+
double yf = y - floor(y);
86+
87+
double u = flecs_perlin_fade(xf);
88+
double v = flecs_perlin_fade(yf);
89+
90+
int aa = flecs_perlin_perm[flecs_perlin_perm[X] + Y];
91+
int ab = flecs_perlin_perm[flecs_perlin_perm[X] + Y + 1];
92+
int ba = flecs_perlin_perm[flecs_perlin_perm[X + 1] + Y];
93+
int bb = flecs_perlin_perm[flecs_perlin_perm[X + 1] + Y + 1];
94+
95+
double x1 = flecs_lerp(
96+
flecs_perlin_grad2(aa, xf, yf),
97+
flecs_perlin_grad2(ba, xf - 1, yf),
98+
u);
99+
100+
double x2 = flecs_lerp(
101+
flecs_perlin_grad2(ab, xf, yf - 1),
102+
flecs_perlin_grad2(bb, xf - 1, yf - 1),
103+
u);
104+
105+
return flecs_lerp(x1, x2, v);
106+
}
107+
108+
static
109+
void flecs_script_perlin2(
110+
const ecs_function_ctx_t *ctx,
111+
int32_t argc,
112+
const ecs_value_t *argv,
113+
ecs_value_t *result)
114+
{
115+
(void)argc;
116+
double x = *(double*)argv[0].ptr;
117+
double y = *(double*)argv[1].ptr;
118+
*(double*)result->ptr = flecs_perlin2(x, y);
119+
}
120+
121+
void FlecsScriptMathPerlinImport(
122+
ecs_world_t *world)
123+
{
124+
ecs_entity_t FlecsScriptMath = ecs_lookup(world, "flecs.script.math");
125+
ecs_assert(FlecsScriptMath != 0, ECS_INTERNAL_ERROR, NULL);
126+
127+
flecs_perlin_seed(1234);
128+
129+
ecs_function(world, {
130+
.name = "perlin2",
131+
.parent = FlecsScriptMath,
132+
.return_type = ecs_id(ecs_f64_t),
133+
.params = {
134+
{ .name = "x", .type = ecs_id(ecs_f64_t) },
135+
{ .name = "y", .type = ecs_id(ecs_f64_t) },
136+
},
137+
.callback = flecs_script_perlin2
138+
});
139+
}
140+
141+
#endif

0 commit comments

Comments
 (0)