From ed1e5a8c4571cfd7bdba42a1ec8eb1972b805073 Mon Sep 17 00:00:00 2001 From: sam Date: Fri, 12 Apr 2024 03:30:10 +1200 Subject: [PATCH] add textures and test out perlin noise --- .gitignore | 4 + Makefile | 10 +- atlas.png | Bin 0 -> 3466 bytes samcraft/chunk.c | 7 +- samcraft/chunk.h | 9 +- samcraft/faces.c | 155 +++++++++++++++ samcraft/faces.h | 171 ++--------------- samcraft/main.c | 86 ++++----- samcraft/stb_perlin.h | 428 ++++++++++++++++++++++++++++++++++++++++++ samcraft/vector.h | 15 ++ samcraft/vector3.h | 10 - 11 files changed, 682 insertions(+), 213 deletions(-) create mode 100644 .gitignore create mode 100644 atlas.png create mode 100644 samcraft/faces.c create mode 100644 samcraft/stb_perlin.h create mode 100644 samcraft/vector.h delete mode 100644 samcraft/vector3.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..90a5915 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +x64/ +x86/ +samcraft/x64 +samcraft/x86 diff --git a/Makefile b/Makefile index b2388ea..973f15e 100644 --- a/Makefile +++ b/Makefile @@ -6,20 +6,22 @@ BINARY=$(OUTDIR)/$(NAME) OBJDIR=$(NAME)/$(OUTDIR) CC=gcc -LD=ld -CFLAGS=-O3 -LDFLAGS=-lraylib +CFLAGS=-O3 -g +LDFLAGS=-lraylib -lGL -lm CFILES=$(shell cd $(NAME) && find -L * -type f -name '*.c') OBJ=$(addprefix $(OBJDIR)/, $(CFILES:.c=.obj)) $(BINARY): $(OBJ) Makefile mkdir -p $(OUTDIR) - $(LD) $(LDFLAGS) $(OBJ) -o $@ + $(CC) $(OBJ) $(LDFLAGS) -o $@ $(OBJDIR)/%.obj: $(NAME)/%.c mkdir -p $(OBJDIR) $(CC) $(CFLAGS) -c $< -o $@ +run: $(BINARY) + $(BINARY) + clean: rm -rf $(OBJ) $(BINARY) diff --git a/atlas.png b/atlas.png new file mode 100644 index 0000000000000000000000000000000000000000..51e2fda97e61016e43006b299367983419721a95 GIT binary patch literal 3466 zcmeH~`%hD67{}jpdgv*I(lRKNTU%maEHbHGxeO*fg^q#_td1xV#Dd(S)gXib|!l!?peD41rzcHG3^VB2A^uH&-6K!z?MIJpd&$OOWjuI^vhul?nHpFGK%JkRs} zKA+^RlE=sxbXPh6fDsibJqZA04k19Jny-W`eVRFcB1$TW%}YF=qGkQ9tlhf0u@yqR zr9M{-#_gy_ZU0JUCibSwHLS8BUU#M%YF&11JX~!PTDVEBtS_A=IDvtIpX|*IIa9e@ zZa3#^mBA2Ey+;b@5#fq56>w3T8Tq^vgE8MIGcX@4>TolRLn#=89Rh|sO>19?S zzY1~Tdo*#;b^~;4OX9*Slel8{ySsxZl~gw3ckcT#XBJVCEL#6qMP|@6&aiI-)!iq% zln%*X*bPota}BmLVNd7MGHaRj6^|){Yy5x&4-I9|s2ygsFDALTJ)B1uAvR)ME@!`? zs}sAzI!^&+1@sS0zLy7P4sJo8{v#=j%jQk8HEd@E$YEk4<89+vgvD#9Yin!k3k6*; zf*@okqzS5I+yGVmy+LPI)!rLpENu);aH5|x-MBy&70V4&|DB|fqP68df2tReqYZ;6 zkKn0kae-g}%|S7`L>Xs5*@(dQpeQ09=pHLXh>s0a-2=2u9PP!V+onOST|@ zLZ;6St!%otn3!2k$^o81m1B)r8BW_-cMq9M(*U3Geqm6@P0(bGarx3^ry6g3jKyI< zzlGy}!eDY3eKgNsdKr3Tm}I_KEuF<~drZ*rXq%D=z8b|h2?;hz6Z_QnU-(Gw35HgP zFd$V2?8)l4GidTR5uZaKWlR{7HLuE{D9*#gDcHEEJq+Z5*ps8K%MP;;rr~E@2X}I1 zC`I;7pZSdw9P2^>Y}mL26w0YQkY%Xoa#VDdHuCt_D@J8Ib?=x^k-x4k^gq=i&j3L> zNnOVZI zM?f3`#&?NfM*J@2hQnkoHO79L(&H2xN#3;03G%06`5iri zCYIUABE-mqzKEujY;O_!Vm%*c!@af(9PWXK$Dv>bZHaD{hr|5qN#aPTE5bYAIZ>1pwSzB!cd-ViBS@FUW+D-Y`~ov1pXv3=_@ji~GC>CGwG98ldPW}fV|L2*EFb?C| zYw<0IWd;@>Sk}OT0t*Q(B(#vwLc;$+!q44dun^%H@MG= WIDTH || pos.z < 0 || pos.z >= WIDTH || pos.y < 0 || pos.y >= HEIGHT) return 0; + return chunk[coord_to_index(pos)]; +} diff --git a/samcraft/chunk.h b/samcraft/chunk.h index 93f47c1..46b2e39 100644 --- a/samcraft/chunk.h +++ b/samcraft/chunk.h @@ -1,12 +1,13 @@ #ifndef __CHUNK_H__ #define __CHUNK_H__ -#include "vector3.h" +#include "vector.h" -#define WIDTH 5 -#define HEIGHT 10 +#define WIDTH 320 +#define HEIGHT 256 vector3 index_to_coord(int i); int coord_to_index(vector3 pos); +int get_block_at(int* chunk, vector3 pos); -#endif \ No newline at end of file +#endif diff --git a/samcraft/faces.c b/samcraft/faces.c new file mode 100644 index 0000000..9a07bc3 --- /dev/null +++ b/samcraft/faces.c @@ -0,0 +1,155 @@ +#include "faces.h" +#include + +#define TOP_LEFT { 0.0f, 0.0f } +#define TOP_RIGHT { 1.0f, 0.0f } +#define BOTTOM_LEFT { 0.0f, 1.0f } +#define BOTTOM_RIGHT { 1.0f, 1.0f } + +void add_face(Mesh* mesh, vector3* face, vector2* tex, int block_id, vector3 pos) { + int vert_start = mesh->vertexCount * 3; + int tex_start = mesh->vertexCount * 2; + + mesh->vertexCount += 6; + mesh->triangleCount += 2; + + mesh->vertices = realloc(mesh->vertices, (mesh->vertexCount * 3) * sizeof(float)); + mesh->texcoords = realloc(mesh->texcoords, (mesh->vertexCount * 2) * sizeof(float)); + + for (int i = 0; i < 18; i += 3) { + int v = i / 3; + mesh->vertices[vert_start + i + 0] = face[v].x + pos.x; + mesh->vertices[vert_start + i + 1] = face[v].y + pos.y; + mesh->vertices[vert_start + i + 2] = face[v].z + pos.z; + } + + for (int i = 0; i < 12; i += 2) { + int v = i / 2; + + int block_x = block_id % ATLAS_FIT; + int block_y = block_id / ATLAS_FIT; + + mesh->texcoords[tex_start + i + 0] = ((block_x + tex[v].x) * TEXTURE_SIZE) / ATLAS_SIZE; + mesh->texcoords[tex_start + i + 1] = ((block_y + tex[v].y) * TEXTURE_SIZE) / ATLAS_SIZE; + } +} + +vector3 bottom[] = { + { -0.5f, -0.5f, -0.5f }, + { 0.5f, -0.5f, -0.5f }, + { -0.5f, -0.5f, 0.5f }, + + { 0.5f, -0.5f, -0.5f }, + { 0.5f, -0.5f, 0.5f }, + { -0.5f, -0.5f, 0.5f } +}; + +vector2 bottom_tex[] = { + BOTTOM_LEFT, + BOTTOM_RIGHT, + TOP_LEFT, + + BOTTOM_RIGHT, + TOP_RIGHT, + TOP_LEFT +}; + +vector3 top[] = { + { -0.5f, 0.5f, -0.5f }, + { -0.5f, 0.5f, 0.5f }, + { 0.5f, 0.5f, -0.5f }, + + { 0.5f, 0.5f, -0.5f }, + { -0.5f, 0.5f, 0.5f }, + { 0.5f, 0.5f, 0.5f } +}; + +vector2 top_tex[] = { + BOTTOM_LEFT, + TOP_LEFT, + BOTTOM_RIGHT, + + BOTTOM_RIGHT, + TOP_LEFT, + TOP_RIGHT +}; + +vector3 front[] = { + { -0.5f, -0.5f, 0.5f }, + { 0.5f, -0.5f, 0.5f }, + { -0.5f, 0.5f, 0.5f }, + + { 0.5f, -0.5f, 0.5f }, + { 0.5f, 0.5f, 0.5f }, + { -0.5f, 0.5f, 0.5f } +}; + +vector2 front_tex[] = { + BOTTOM_LEFT, + BOTTOM_RIGHT, + TOP_LEFT, + + BOTTOM_RIGHT, + TOP_RIGHT, + TOP_LEFT +}; + +vector3 back[] = { + { -0.5f, -0.5f, -0.5f }, + { -0.5f, 0.5f, -0.5f }, + { 0.5f, -0.5f, -0.5f }, + + { 0.5f, -0.5f, -0.5f }, + { -0.5f, 0.5f, -0.5f }, + { 0.5f, 0.5f, -0.5f } +}; + +vector2 back_tex[] = { + BOTTOM_LEFT, + TOP_LEFT, + BOTTOM_RIGHT, + + BOTTOM_RIGHT, + TOP_LEFT, + TOP_RIGHT +}; + +vector3 right[] = { + { 0.5f, -0.5f, -0.5f }, + { 0.5f, 0.5f, 0.5f }, + { 0.5f, -0.5f, 0.5f }, + + { 0.5f, -0.5f, -0.5f }, + { 0.5f, 0.5f, -0.5f }, + { 0.5f, 0.5f, 0.5f } +}; + +vector2 right_tex[] = { + BOTTOM_LEFT, + TOP_RIGHT, + TOP_LEFT, + + BOTTOM_LEFT, + BOTTOM_RIGHT, + TOP_RIGHT +}; + +vector3 left[] = { + { -0.5f, -0.5f, -0.5f }, + { -0.5f, -0.5f, 0.5f }, + { -0.5f, 0.5f, 0.5f }, + + { -0.5f, -0.5f, -0.5f }, + { -0.5f, 0.5f, 0.5f }, + { -0.5f, 0.5f, -0.5f } +}; + +vector2 left_tex[] = { + BOTTOM_LEFT, + TOP_LEFT, + TOP_RIGHT, + + BOTTOM_LEFT, + TOP_RIGHT, + BOTTOM_RIGHT +}; diff --git a/samcraft/faces.h b/samcraft/faces.h index f8c009d..29bf92f 100644 --- a/samcraft/faces.h +++ b/samcraft/faces.h @@ -1,160 +1,27 @@ #ifndef __FACES_H__ #define __FACES_H__ -float bottom[] = { - -0.5f, - -0.5f, - -0.5f, +#include +#include "vector.h" - 0.5f, - -0.5f, - -0.5f, +#define ATLAS_SIZE 256 +#define TEXTURE_SIZE 16 +#define ATLAS_FIT (ATLAS_SIZE / TEXTURE_SIZE) - -0.5f, - -0.5f, - 0.5f, +void add_face(Mesh* mesh, vector3* face, vector2* tex, int block_id, vector3 pos); - 0.5f, - -0.5f, - -0.5f, +extern vector3 left[]; +extern vector3 right[]; +extern vector3 top[]; +extern vector3 bottom[]; +extern vector3 back[]; +extern vector3 front[]; - 0.5f, - -0.5f, - 0.5f, +extern vector2 left_tex[]; +extern vector2 right_tex[]; +extern vector2 top_tex[]; +extern vector2 bottom_tex[]; +extern vector2 back_tex[]; +extern vector2 front_tex[]; - -0.5f, - -0.5f, - 0.5f, -}; - -float top[] = { - -0.5f, - 0.5f, - -0.5f, - - -0.5f, - 0.5f, - 0.5f, - - 0.5f, - 0.5f, - -0.5f, - - 0.5f, - 0.5f, - -0.5f, - - -0.5f, - 0.5f, - 0.5f, - - 0.5f, - 0.5f, - 0.5f, -}; - -float front[] = { - -0.5f, - -0.5f, - 0.5f, - - 0.5f, - -0.5f, - 0.5f, - - -0.5f, - 0.5f, - 0.5f, - - 0.5f, - -0.5f, - 0.5f, - - 0.5f, - 0.5f, - 0.5f, - - -0.5f, - 0.5f, - 0.5f, -}; - -float back[] = { - -0.5f, - -0.5f, - -0.5f, - - -0.5f, - 0.5f, - -0.5f, - - 0.5f, - -0.5f, - -0.5f, - - 0.5f, - -0.5f, - -0.5f, - - -0.5f, - 0.5f, - -0.5f, - - 0.5f, - 0.5f, - -0.5f, -}; - -float right[] = { - 0.5f, - -0.5f, - -0.5f, - - 0.5f, - 0.5f, - 0.5f, - - 0.5f, - -0.5f, - 0.5f, - - 0.5f, - -0.5f, - -0.5f, - - 0.5f, - 0.5f, - -0.5f, - - 0.5f, - 0.5f, - 0.5f, -}; - -float left[] = { - -0.5f, - -0.5f, - -0.5f, - - -0.5f, - -0.5f, - 0.5f, - - -0.5f, - 0.5f, - 0.5f, - - -0.5f, - -0.5f, - -0.5f, - - -0.5f, - 0.5f, - 0.5f, - - -0.5f, - 0.5f, - -0.5f, -}; - -#endif \ No newline at end of file +#endif diff --git a/samcraft/main.c b/samcraft/main.c index e3c64ff..6459d36 100644 --- a/samcraft/main.c +++ b/samcraft/main.c @@ -3,54 +3,40 @@ #include #include #include -#include #include "faces.h" #include "chunk.h" -#include "vector3.h" - -void add_face(Mesh* mesh, float* face, vector3 pos) { - int start = mesh->vertexCount * 3; - mesh->vertexCount += 6; - mesh->triangleCount += 2; - - Mesh* ptr = realloc(mesh->vertices, (mesh->vertexCount * 3) * sizeof(float)); - assert(ptr != NULL); - mesh->vertices = ptr; - - for (int i = 0; i < 18; i += 3) { - mesh->vertices[start + i] = face[i] + pos.x; - mesh->vertices[start + i + 1] = face[i + 1] + pos.y; - mesh->vertices[start + i + 2] = face[i + 2] + pos.z; - } -} - -int get_block_at(int* chunk, vector3 pos) { - if (pos.x < 0 || pos.x >= WIDTH || pos.z < 0 || pos.z >= WIDTH || pos.y < 0 || pos.y >= HEIGHT) return 0; - return chunk[coord_to_index(pos)]; -} +#include "vector.h" +#include "stb_perlin.h" Mesh gen_mesh(int* chunk) { Mesh mesh = { 0 }; mesh.vertices = malloc(0); mesh.vertexCount = 0; + mesh.texcoords = malloc(0); for (int i = 0; i < WIDTH * WIDTH * HEIGHT; i++) { - if (chunk[i] == 0) continue; + int block_id = chunk[i]; + if(block_id == 0) continue; vector3 pos = index_to_coord(i); if(get_block_at(chunk, (vector3){ pos.x, pos.y - 1, pos.z }) == 0) - add_face(&mesh, bottom, pos); - if (get_block_at(chunk, (vector3) { pos.x, pos.y + 1, pos.z }) == 0) - add_face(&mesh, top, pos); - if (get_block_at(chunk, (vector3) { pos.x - 1, pos.y, pos.z }) == 0) - add_face(&mesh, left, pos); - if (get_block_at(chunk, (vector3) { pos.x + 1, pos.y, pos.z }) == 0) - add_face(&mesh, right, pos); - if (get_block_at(chunk, (vector3) { pos.x, pos.y, pos.z - 1 }) == 0) - add_face(&mesh, back, pos); - if (get_block_at(chunk, (vector3) { pos.x, pos.y, pos.z + 1 }) == 0) - add_face(&mesh, front, pos); + add_face(&mesh, bottom, bottom_tex, block_id, pos); + + if(get_block_at(chunk, (vector3){ pos.x, pos.y + 1, pos.z }) == 0) + add_face(&mesh, top, top_tex, block_id, pos); + + if(get_block_at(chunk, (vector3){ pos.x - 1, pos.y, pos.z }) == 0) + add_face(&mesh, left, left_tex, block_id, pos); + + if(get_block_at(chunk, (vector3){ pos.x + 1, pos.y, pos.z }) == 0) + add_face(&mesh, right, right_tex, block_id, pos); + + if(get_block_at(chunk, (vector3){ pos.x, pos.y, pos.z - 1 }) == 0) + add_face(&mesh, back, back_tex, block_id, pos); + + if(get_block_at(chunk, (vector3){ pos.x, pos.y, pos.z + 1 }) == 0) + add_face(&mesh, front, front_tex, block_id, pos); } UploadMesh(&mesh, false); @@ -61,21 +47,35 @@ Mesh gen_mesh(int* chunk) { } int main() { + for(float x = 0.0f; x < WIDTH; x++) { + for(float z = 0.0f; z < WIDTH; z++) { + printf("%f, %f: %f\n", x, z, stb_perlin_noise3(x, z, z, 0, 0, 0)); + } + } + InitWindow(800, 600, "samcraft"); - SetTargetFPS(60); + //SetTargetFPS(60); int* chunk = malloc(WIDTH * WIDTH * HEIGHT * sizeof(int)); - assert(chunk != NULL); - - for (int i = 0; i < WIDTH * WIDTH * HEIGHT; i++) { - chunk[i] = GetRandomValue(0, 1); + for(int i = 0; i < WIDTH * WIDTH * HEIGHT; i++) { + chunk[i] = 0; } + for(int x = 0; x < WIDTH; x++) { + for(int z = 0; z < WIDTH; z++) { + for(int y = 0; y < (10 + stb_perlin_fbm_noise3(x / 40.0f, x / 40.0f, z / 40.0f, 2.0f, 0.5f, 6) * 10.0f); y++) { + chunk[coord_to_index((vector3){ x, y, z })] = GetRandomValue(1, 2); + } + } + } Mesh chunk_mesh = gen_mesh(chunk); Material mat = LoadMaterialDefault(); Matrix matrix = MatrixIdentity(); + Texture atlas = LoadTexture("atlas.png"); + mat.maps[MATERIAL_MAP_DIFFUSE].texture = atlas; + Camera camera = { 0 }; camera.position = (Vector3){ 10.0f, 10.0f, 10.0f }; camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; @@ -84,7 +84,7 @@ int main() { camera.fovy = 70.0f; while (!WindowShouldClose()) { - UpdateCamera(&camera, CAMERA_THIRD_PERSON); + UpdateCamera(&camera, CAMERA_FREE); DisableCursor(); @@ -98,6 +98,8 @@ int main() { DrawGrid(10, 10); } EndMode3D(); + + DrawFPS(10, 10); } EndDrawing(); } @@ -105,4 +107,4 @@ int main() { CloseWindow(); return 0; -} \ No newline at end of file +} diff --git a/samcraft/stb_perlin.h b/samcraft/stb_perlin.h new file mode 100644 index 0000000..47cb9a4 --- /dev/null +++ b/samcraft/stb_perlin.h @@ -0,0 +1,428 @@ +// stb_perlin.h - v0.5 - perlin noise +// public domain single-file C implementation by Sean Barrett +// +// LICENSE +// +// See end of file. +// +// +// to create the implementation, +// #define STB_PERLIN_IMPLEMENTATION +// in *one* C/CPP file that includes this file. +// +// +// Documentation: +// +// float stb_perlin_noise3( float x, +// float y, +// float z, +// int x_wrap=0, +// int y_wrap=0, +// int z_wrap=0) +// +// This function computes a random value at the coordinate (x,y,z). +// Adjacent random values are continuous but the noise fluctuates +// its randomness with period 1, i.e. takes on wholly unrelated values +// at integer points. Specifically, this implements Ken Perlin's +// revised noise function from 2002. +// +// The "wrap" parameters can be used to create wraparound noise that +// wraps at powers of two. The numbers MUST be powers of two. Specify +// 0 to mean "don't care". (The noise always wraps every 256 due +// details of the implementation, even if you ask for larger or no +// wrapping.) +// +// float stb_perlin_noise3_seed( float x, +// float y, +// float z, +// int x_wrap=0, +// int y_wrap=0, +// int z_wrap=0, +// int seed) +// +// As above, but 'seed' selects from multiple different variations of the +// noise function. The current implementation only uses the bottom 8 bits +// of 'seed', but possibly in the future more bits will be used. +// +// +// Fractal Noise: +// +// Three common fractal noise functions are included, which produce +// a wide variety of nice effects depending on the parameters +// provided. Note that each function will call stb_perlin_noise3 +// 'octaves' times, so this parameter will affect runtime. +// +// float stb_perlin_ridge_noise3(float x, float y, float z, +// float lacunarity, float gain, float offset, int octaves) +// +// float stb_perlin_fbm_noise3(float x, float y, float z, +// float lacunarity, float gain, int octaves) +// +// float stb_perlin_turbulence_noise3(float x, float y, float z, +// float lacunarity, float gain, int octaves) +// +// Typical values to start playing with: +// octaves = 6 -- number of "octaves" of noise3() to sum +// lacunarity = ~ 2.0 -- spacing between successive octaves (use exactly 2.0 for wrapping output) +// gain = 0.5 -- relative weighting applied to each successive octave +// offset = 1.0? -- used to invert the ridges, may need to be larger, not sure +// +// +// Contributors: +// Jack Mott - additional noise functions +// Jordan Peck - seeded noise +// + + +#ifdef __cplusplus +extern "C" { +#endif +extern float stb_perlin_noise3(float x, float y, float z, int x_wrap, int y_wrap, int z_wrap); +extern float stb_perlin_noise3_seed(float x, float y, float z, int x_wrap, int y_wrap, int z_wrap, int seed); +extern float stb_perlin_ridge_noise3(float x, float y, float z, float lacunarity, float gain, float offset, int octaves); +extern float stb_perlin_fbm_noise3(float x, float y, float z, float lacunarity, float gain, int octaves); +extern float stb_perlin_turbulence_noise3(float x, float y, float z, float lacunarity, float gain, int octaves); +extern float stb_perlin_noise3_wrap_nonpow2(float x, float y, float z, int x_wrap, int y_wrap, int z_wrap, unsigned char seed); +#ifdef __cplusplus +} +#endif + +#ifdef STB_PERLIN_IMPLEMENTATION + +#include // fabs() + +// not same permutation table as Perlin's reference to avoid copyright issues; +// Perlin's table can be found at http://mrl.nyu.edu/~perlin/noise/ +static unsigned char stb__perlin_randtab[512] = +{ + 23, 125, 161, 52, 103, 117, 70, 37, 247, 101, 203, 169, 124, 126, 44, 123, + 152, 238, 145, 45, 171, 114, 253, 10, 192, 136, 4, 157, 249, 30, 35, 72, + 175, 63, 77, 90, 181, 16, 96, 111, 133, 104, 75, 162, 93, 56, 66, 240, + 8, 50, 84, 229, 49, 210, 173, 239, 141, 1, 87, 18, 2, 198, 143, 57, + 225, 160, 58, 217, 168, 206, 245, 204, 199, 6, 73, 60, 20, 230, 211, 233, + 94, 200, 88, 9, 74, 155, 33, 15, 219, 130, 226, 202, 83, 236, 42, 172, + 165, 218, 55, 222, 46, 107, 98, 154, 109, 67, 196, 178, 127, 158, 13, 243, + 65, 79, 166, 248, 25, 224, 115, 80, 68, 51, 184, 128, 232, 208, 151, 122, + 26, 212, 105, 43, 179, 213, 235, 148, 146, 89, 14, 195, 28, 78, 112, 76, + 250, 47, 24, 251, 140, 108, 186, 190, 228, 170, 183, 139, 39, 188, 244, 246, + 132, 48, 119, 144, 180, 138, 134, 193, 82, 182, 120, 121, 86, 220, 209, 3, + 91, 241, 149, 85, 205, 150, 113, 216, 31, 100, 41, 164, 177, 214, 153, 231, + 38, 71, 185, 174, 97, 201, 29, 95, 7, 92, 54, 254, 191, 118, 34, 221, + 131, 11, 163, 99, 234, 81, 227, 147, 156, 176, 17, 142, 69, 12, 110, 62, + 27, 255, 0, 194, 59, 116, 242, 252, 19, 21, 187, 53, 207, 129, 64, 135, + 61, 40, 167, 237, 102, 223, 106, 159, 197, 189, 215, 137, 36, 32, 22, 5, + + // and a second copy so we don't need an extra mask or static initializer + 23, 125, 161, 52, 103, 117, 70, 37, 247, 101, 203, 169, 124, 126, 44, 123, + 152, 238, 145, 45, 171, 114, 253, 10, 192, 136, 4, 157, 249, 30, 35, 72, + 175, 63, 77, 90, 181, 16, 96, 111, 133, 104, 75, 162, 93, 56, 66, 240, + 8, 50, 84, 229, 49, 210, 173, 239, 141, 1, 87, 18, 2, 198, 143, 57, + 225, 160, 58, 217, 168, 206, 245, 204, 199, 6, 73, 60, 20, 230, 211, 233, + 94, 200, 88, 9, 74, 155, 33, 15, 219, 130, 226, 202, 83, 236, 42, 172, + 165, 218, 55, 222, 46, 107, 98, 154, 109, 67, 196, 178, 127, 158, 13, 243, + 65, 79, 166, 248, 25, 224, 115, 80, 68, 51, 184, 128, 232, 208, 151, 122, + 26, 212, 105, 43, 179, 213, 235, 148, 146, 89, 14, 195, 28, 78, 112, 76, + 250, 47, 24, 251, 140, 108, 186, 190, 228, 170, 183, 139, 39, 188, 244, 246, + 132, 48, 119, 144, 180, 138, 134, 193, 82, 182, 120, 121, 86, 220, 209, 3, + 91, 241, 149, 85, 205, 150, 113, 216, 31, 100, 41, 164, 177, 214, 153, 231, + 38, 71, 185, 174, 97, 201, 29, 95, 7, 92, 54, 254, 191, 118, 34, 221, + 131, 11, 163, 99, 234, 81, 227, 147, 156, 176, 17, 142, 69, 12, 110, 62, + 27, 255, 0, 194, 59, 116, 242, 252, 19, 21, 187, 53, 207, 129, 64, 135, + 61, 40, 167, 237, 102, 223, 106, 159, 197, 189, 215, 137, 36, 32, 22, 5, +}; + + +// perlin's gradient has 12 cases so some get used 1/16th of the time +// and some 2/16ths. We reduce bias by changing those fractions +// to 5/64ths and 6/64ths + +// this array is designed to match the previous implementation +// of gradient hash: indices[stb__perlin_randtab[i]&63] +static unsigned char stb__perlin_randtab_grad_idx[512] = +{ + 7, 9, 5, 0, 11, 1, 6, 9, 3, 9, 11, 1, 8, 10, 4, 7, + 8, 6, 1, 5, 3, 10, 9, 10, 0, 8, 4, 1, 5, 2, 7, 8, + 7, 11, 9, 10, 1, 0, 4, 7, 5, 0, 11, 6, 1, 4, 2, 8, + 8, 10, 4, 9, 9, 2, 5, 7, 9, 1, 7, 2, 2, 6, 11, 5, + 5, 4, 6, 9, 0, 1, 1, 0, 7, 6, 9, 8, 4, 10, 3, 1, + 2, 8, 8, 9, 10, 11, 5, 11, 11, 2, 6, 10, 3, 4, 2, 4, + 9, 10, 3, 2, 6, 3, 6, 10, 5, 3, 4, 10, 11, 2, 9, 11, + 1, 11, 10, 4, 9, 4, 11, 0, 4, 11, 4, 0, 0, 0, 7, 6, + 10, 4, 1, 3, 11, 5, 3, 4, 2, 9, 1, 3, 0, 1, 8, 0, + 6, 7, 8, 7, 0, 4, 6, 10, 8, 2, 3, 11, 11, 8, 0, 2, + 4, 8, 3, 0, 0, 10, 6, 1, 2, 2, 4, 5, 6, 0, 1, 3, + 11, 9, 5, 5, 9, 6, 9, 8, 3, 8, 1, 8, 9, 6, 9, 11, + 10, 7, 5, 6, 5, 9, 1, 3, 7, 0, 2, 10, 11, 2, 6, 1, + 3, 11, 7, 7, 2, 1, 7, 3, 0, 8, 1, 1, 5, 0, 6, 10, + 11, 11, 0, 2, 7, 0, 10, 8, 3, 5, 7, 1, 11, 1, 0, 7, + 9, 0, 11, 5, 10, 3, 2, 3, 5, 9, 7, 9, 8, 4, 6, 5, + + // and a second copy so we don't need an extra mask or static initializer + 7, 9, 5, 0, 11, 1, 6, 9, 3, 9, 11, 1, 8, 10, 4, 7, + 8, 6, 1, 5, 3, 10, 9, 10, 0, 8, 4, 1, 5, 2, 7, 8, + 7, 11, 9, 10, 1, 0, 4, 7, 5, 0, 11, 6, 1, 4, 2, 8, + 8, 10, 4, 9, 9, 2, 5, 7, 9, 1, 7, 2, 2, 6, 11, 5, + 5, 4, 6, 9, 0, 1, 1, 0, 7, 6, 9, 8, 4, 10, 3, 1, + 2, 8, 8, 9, 10, 11, 5, 11, 11, 2, 6, 10, 3, 4, 2, 4, + 9, 10, 3, 2, 6, 3, 6, 10, 5, 3, 4, 10, 11, 2, 9, 11, + 1, 11, 10, 4, 9, 4, 11, 0, 4, 11, 4, 0, 0, 0, 7, 6, + 10, 4, 1, 3, 11, 5, 3, 4, 2, 9, 1, 3, 0, 1, 8, 0, + 6, 7, 8, 7, 0, 4, 6, 10, 8, 2, 3, 11, 11, 8, 0, 2, + 4, 8, 3, 0, 0, 10, 6, 1, 2, 2, 4, 5, 6, 0, 1, 3, + 11, 9, 5, 5, 9, 6, 9, 8, 3, 8, 1, 8, 9, 6, 9, 11, + 10, 7, 5, 6, 5, 9, 1, 3, 7, 0, 2, 10, 11, 2, 6, 1, + 3, 11, 7, 7, 2, 1, 7, 3, 0, 8, 1, 1, 5, 0, 6, 10, + 11, 11, 0, 2, 7, 0, 10, 8, 3, 5, 7, 1, 11, 1, 0, 7, + 9, 0, 11, 5, 10, 3, 2, 3, 5, 9, 7, 9, 8, 4, 6, 5, +}; + +static float stb__perlin_lerp(float a, float b, float t) +{ + return a + (b-a) * t; +} + +static int stb__perlin_fastfloor(float a) +{ + int ai = (int) a; + return (a < ai) ? ai-1 : ai; +} + +// different grad function from Perlin's, but easy to modify to match reference +static float stb__perlin_grad(int grad_idx, float x, float y, float z) +{ + static float basis[12][4] = + { + { 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 }, + }; + + float *grad = basis[grad_idx]; + return grad[0]*x + grad[1]*y + grad[2]*z; +} + +float stb_perlin_noise3_internal(float x, float y, float z, int x_wrap, int y_wrap, int z_wrap, unsigned char seed) +{ + float u,v,w; + float n000,n001,n010,n011,n100,n101,n110,n111; + float n00,n01,n10,n11; + float n0,n1; + + unsigned int x_mask = (x_wrap-1) & 255; + unsigned int y_mask = (y_wrap-1) & 255; + unsigned int z_mask = (z_wrap-1) & 255; + int px = stb__perlin_fastfloor(x); + int py = stb__perlin_fastfloor(y); + int pz = stb__perlin_fastfloor(z); + int x0 = px & x_mask, x1 = (px+1) & x_mask; + int y0 = py & y_mask, y1 = (py+1) & y_mask; + int z0 = pz & z_mask, z1 = (pz+1) & z_mask; + int r0,r1, r00,r01,r10,r11; + + #define stb__perlin_ease(a) (((a*6-15)*a + 10) * a * a * a) + + x -= px; u = stb__perlin_ease(x); + y -= py; v = stb__perlin_ease(y); + z -= pz; w = stb__perlin_ease(z); + + r0 = stb__perlin_randtab[x0+seed]; + r1 = stb__perlin_randtab[x1+seed]; + + r00 = stb__perlin_randtab[r0+y0]; + r01 = stb__perlin_randtab[r0+y1]; + r10 = stb__perlin_randtab[r1+y0]; + r11 = stb__perlin_randtab[r1+y1]; + + n000 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r00+z0], x , y , z ); + n001 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r00+z1], x , y , z-1 ); + n010 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r01+z0], x , y-1, z ); + n011 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r01+z1], x , y-1, z-1 ); + n100 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r10+z0], x-1, y , z ); + n101 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r10+z1], x-1, y , z-1 ); + n110 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r11+z0], x-1, y-1, z ); + n111 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r11+z1], x-1, y-1, z-1 ); + + n00 = stb__perlin_lerp(n000,n001,w); + n01 = stb__perlin_lerp(n010,n011,w); + n10 = stb__perlin_lerp(n100,n101,w); + n11 = stb__perlin_lerp(n110,n111,w); + + n0 = stb__perlin_lerp(n00,n01,v); + n1 = stb__perlin_lerp(n10,n11,v); + + return stb__perlin_lerp(n0,n1,u); +} + +float stb_perlin_noise3(float x, float y, float z, int x_wrap, int y_wrap, int z_wrap) +{ + return stb_perlin_noise3_internal(x,y,z,x_wrap,y_wrap,z_wrap,0); +} + +float stb_perlin_noise3_seed(float x, float y, float z, int x_wrap, int y_wrap, int z_wrap, int seed) +{ + return stb_perlin_noise3_internal(x,y,z,x_wrap,y_wrap,z_wrap, (unsigned char) seed); +} + +float stb_perlin_ridge_noise3(float x, float y, float z, float lacunarity, float gain, float offset, int octaves) +{ + int i; + float frequency = 1.0f; + float prev = 1.0f; + float amplitude = 0.5f; + float sum = 0.0f; + + for (i = 0; i < octaves; i++) { + float r = stb_perlin_noise3_internal(x*frequency,y*frequency,z*frequency,0,0,0,(unsigned char)i); + r = offset - (float) fabs(r); + r = r*r; + sum += r*amplitude*prev; + prev = r; + frequency *= lacunarity; + amplitude *= gain; + } + return sum; +} + +float stb_perlin_fbm_noise3(float x, float y, float z, float lacunarity, float gain, int octaves) +{ + int i; + float frequency = 1.0f; + float amplitude = 1.0f; + float sum = 0.0f; + + for (i = 0; i < octaves; i++) { + sum += stb_perlin_noise3_internal(x*frequency,y*frequency,z*frequency,0,0,0,(unsigned char)i)*amplitude; + frequency *= lacunarity; + amplitude *= gain; + } + return sum; +} + +float stb_perlin_turbulence_noise3(float x, float y, float z, float lacunarity, float gain, int octaves) +{ + int i; + float frequency = 1.0f; + float amplitude = 1.0f; + float sum = 0.0f; + + for (i = 0; i < octaves; i++) { + float r = stb_perlin_noise3_internal(x*frequency,y*frequency,z*frequency,0,0,0,(unsigned char)i)*amplitude; + sum += (float) fabs(r); + frequency *= lacunarity; + amplitude *= gain; + } + return sum; +} + +float stb_perlin_noise3_wrap_nonpow2(float x, float y, float z, int x_wrap, int y_wrap, int z_wrap, unsigned char seed) +{ + float u,v,w; + float n000,n001,n010,n011,n100,n101,n110,n111; + float n00,n01,n10,n11; + float n0,n1; + + int px = stb__perlin_fastfloor(x); + int py = stb__perlin_fastfloor(y); + int pz = stb__perlin_fastfloor(z); + int x_wrap2 = (x_wrap ? x_wrap : 256); + int y_wrap2 = (y_wrap ? y_wrap : 256); + int z_wrap2 = (z_wrap ? z_wrap : 256); + int x0 = px % x_wrap2, x1; + int y0 = py % y_wrap2, y1; + int z0 = pz % z_wrap2, z1; + int r0,r1, r00,r01,r10,r11; + + if (x0 < 0) x0 += x_wrap2; + if (y0 < 0) y0 += y_wrap2; + if (z0 < 0) z0 += z_wrap2; + x1 = (x0+1) % x_wrap2; + y1 = (y0+1) % y_wrap2; + z1 = (z0+1) % z_wrap2; + + #define stb__perlin_ease(a) (((a*6-15)*a + 10) * a * a * a) + + x -= px; u = stb__perlin_ease(x); + y -= py; v = stb__perlin_ease(y); + z -= pz; w = stb__perlin_ease(z); + + r0 = stb__perlin_randtab[x0]; + r0 = stb__perlin_randtab[r0+seed]; + r1 = stb__perlin_randtab[x1]; + r1 = stb__perlin_randtab[r1+seed]; + + r00 = stb__perlin_randtab[r0+y0]; + r01 = stb__perlin_randtab[r0+y1]; + r10 = stb__perlin_randtab[r1+y0]; + r11 = stb__perlin_randtab[r1+y1]; + + n000 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r00+z0], x , y , z ); + n001 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r00+z1], x , y , z-1 ); + n010 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r01+z0], x , y-1, z ); + n011 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r01+z1], x , y-1, z-1 ); + n100 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r10+z0], x-1, y , z ); + n101 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r10+z1], x-1, y , z-1 ); + n110 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r11+z0], x-1, y-1, z ); + n111 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r11+z1], x-1, y-1, z-1 ); + + n00 = stb__perlin_lerp(n000,n001,w); + n01 = stb__perlin_lerp(n010,n011,w); + n10 = stb__perlin_lerp(n100,n101,w); + n11 = stb__perlin_lerp(n110,n111,w); + + n0 = stb__perlin_lerp(n00,n01,v); + n1 = stb__perlin_lerp(n10,n11,v); + + return stb__perlin_lerp(n0,n1,u); +} +#endif // STB_PERLIN_IMPLEMENTATION + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ diff --git a/samcraft/vector.h b/samcraft/vector.h new file mode 100644 index 0000000..63a4183 --- /dev/null +++ b/samcraft/vector.h @@ -0,0 +1,15 @@ +#ifndef __VECTOR_H__ +#define __VECTOR_H__ + +typedef struct { + float x; + float y; + float z; +} vector3; + +typedef struct { + float x; + float y; +} vector2; + +#endif diff --git a/samcraft/vector3.h b/samcraft/vector3.h deleted file mode 100644 index 8ff6400..0000000 --- a/samcraft/vector3.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef __VECTOR3_H__ -#define __VECTOR3_H__ - -typedef struct { - float x; - float y; - float z; -} vector3; - -#endif \ No newline at end of file