Forked from
tome / Tales of MajEyal
11850 commits behind the upstream repository.
-
dg authored
git-svn-id: http://svn.net-core.org/repos/t-engine4@3087 51575b47-30f0-44d4-a5cc-537603b46e54
dg authoredgit-svn-id: http://svn.net-core.org/repos/t-engine4@3087 51575b47-30f0-44d4-a5cc-537603b46e54
noise.c 10.85 KiB
/*
TE4 - T-Engine 4
Copyright (C) 2009, 2010, 2011 Nicolas Casalini
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 3 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, see <http://www.gnu.org/licenses/>.
Nicolas Casalini "DarkGod"
darkgod@te4.org
*/
#include "display.h"
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
#include "auxiliar.h"
#include "types.h"
#include "script.h"
#include <math.h>
#include <stdlib.h>
#include "libtcod.h"
#include "noise.h"
extern bool shaders_active;
typedef struct
{
TCOD_noise_t noise;
int ndim;
} noise_t;
static int noise_new(lua_State *L)
{
int ndim = luaL_checknumber(L, 1);
float hurst = lua_isnumber(L, 2) ? luaL_checknumber(L, 2) : TCOD_NOISE_DEFAULT_HURST;
float lacunarity = lua_isnumber(L, 3) ? luaL_checknumber(L, 3) : TCOD_NOISE_DEFAULT_LACUNARITY;
noise_t *n = (noise_t*)lua_newuserdata(L, sizeof(noise_t));
auxiliar_setclass(L, "noise{core}", -1);
n->noise = TCOD_noise_new(ndim, hurst, lacunarity);
n->ndim = ndim;
return 1;
}
static int noise_free(lua_State *L)
{
noise_t *n = (noise_t*)auxiliar_checkclass(L, "noise{core}", 1);
TCOD_noise_delete(n->noise);
lua_pushnumber(L, 1);
return 1;
}
static int noise_simplex(lua_State *L)
{
noise_t *n = (noise_t*)auxiliar_checkclass(L, "noise{core}", 1);
float p[4];
int i;
for (i = 0; i < n->ndim; i++) p[i] = luaL_checknumber(L, 2 + i);
lua_pushnumber(L, TCOD_noise_simplex(n->noise, p));
return 1;
}
static int noise_fbm_simplex(lua_State *L)
{
noise_t *n = (noise_t*)auxiliar_checkclass(L, "noise{core}", 1);
float p[4];
int i;
for (i = 0; i < n->ndim; i++) p[i] = luaL_checknumber(L, 2 + i);
float octave = luaL_checknumber(L, 2 + i);
lua_pushnumber(L, TCOD_noise_fbm_simplex(n->noise, p, octave));
return 1;
}
static int noise_turbulence_simplex(lua_State *L)
{
noise_t *n = (noise_t*)auxiliar_checkclass(L, "noise{core}", 1);
float p[4];
int i;
for (i = 0; i < n->ndim; i++) p[i] = luaL_checknumber(L, 2 + i);
float octave = luaL_checknumber(L, 2 + i);
lua_pushnumber(L, TCOD_noise_turbulence_simplex(n->noise, p, octave));
return 1;
}
static int noise_perlin(lua_State *L)
{
noise_t *n = (noise_t*)auxiliar_checkclass(L, "noise{core}", 1);
float p[4];
int i;
for (i = 0; i < n->ndim; i++) p[i] = luaL_checknumber(L, 2 + i);
lua_pushnumber(L, TCOD_noise_perlin(n->noise, p));
return 1;
}
static int noise_fbm_perlin(lua_State *L)
{
noise_t *n = (noise_t*)auxiliar_checkclass(L, "noise{core}", 1);
float p[4];
int i;
for (i = 0; i < n->ndim; i++) p[i] = luaL_checknumber(L, 2 + i);
float octave = luaL_checknumber(L, 2 + i);
lua_pushnumber(L, TCOD_noise_fbm_perlin(n->noise, p, octave));
return 1;
}
static int noise_turbulence_perlin(lua_State *L)
{
noise_t *n = (noise_t*)auxiliar_checkclass(L, "noise{core}", 1);
float p[4];
int i;
for (i = 0; i < n->ndim; i++) p[i] = luaL_checknumber(L, 2 + i);
float octave = luaL_checknumber(L, 2 + i);
lua_pushnumber(L, TCOD_noise_turbulence_perlin(n->noise, p, octave));
return 1;
}
static int noise_wavelet(lua_State *L)
{
noise_t *n = (noise_t*)auxiliar_checkclass(L, "noise{core}", 1);
float p[4];
int i;
for (i = 0; i < n->ndim; i++) p[i] = luaL_checknumber(L, 2 + i);
lua_pushnumber(L, TCOD_noise_wavelet(n->noise, p));
return 1;
}
static int noise_fbm_wavelet(lua_State *L)
{
noise_t *n = (noise_t*)auxiliar_checkclass(L, "noise{core}", 1);
float p[4];
int i;
for (i = 0; i < n->ndim; i++) p[i] = luaL_checknumber(L, 2 + i);
float octave = luaL_checknumber(L, 2 + i);
lua_pushnumber(L, TCOD_noise_fbm_wavelet(n->noise, p, octave));
return 1;
}
static int noise_turbulence_wavelet(lua_State *L)
{
noise_t *n = (noise_t*)auxiliar_checkclass(L, "noise{core}", 1);
float p[4];
int i;
for (i = 0; i < n->ndim; i++) p[i] = luaL_checknumber(L, 2 + i);
float octave = luaL_checknumber(L, 2 + i);
lua_pushnumber(L, TCOD_noise_turbulence_wavelet(n->noise, p, octave));
return 1;
}
#define BYTES_PER_TEXEL 3
#define LAYER(r) (w * h * r * BYTES_PER_TEXEL)
// 2->1 dimension mapping function
#define TEXEL2(s, t) (BYTES_PER_TEXEL * (s * w + t))
// 3->1 dimension mapping function
#define TEXEL3(s, t, r) (TEXEL2(s, t) + LAYER(r))
/*
static int noise_texture2d(lua_State *L)
{
noise_t *n = (noise_t*)auxiliar_checkclass(L, "noise{core}", 1);
int w = luaL_checknumber(L, 2);
int h = luaL_checknumber(L, 3);
float zoom = luaL_checknumber(L, 4);
float x = luaL_checknumber(L, 5);
float y = luaL_checknumber(L, 6);
GLubyte *map = malloc(w * h * 3 * sizeof(GLubyte));
float p[2];
int i, j;
for (i = 0; i < w; i++)
{
for (j = 0; j < h; j++)
{
p[0] = zoom * ((float)(i+x)) / w;
p[1] = zoom * ((float)(j+y)) / h;
float v = ((TCOD_noise_simplex(n->noise, p) + 1) / 2) * 255;
map[TEXEL2(i, j)] = (GLubyte)v;
map[TEXEL2(i, j)+1] = (GLubyte)v;
map[TEXEL2(i, j)+2] = (GLubyte)v;
}
}
GLuint *t = (GLuint*)lua_newuserdata(L, sizeof(GLuint));
auxiliar_setclass(L, "gl{texture}", -1);
glGenTextures(1, t);
glBindTexture(GL_TEXTURE_2D, *t);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, map);
free(map);
return 1;
}
*/
inline static float noise3d(noise_t *n, float x, float y, float z) ALWAYS_INLINE;
static float noise3d(noise_t *n, float x, float y, float z)
{
float p[3];
p[0] = x;
p[1] = y;
p[2] = z;
return (TCOD_noise_simplex(n->noise, p) + 1) / 2;
}
// Source: http://web.archive.org/web/20070706003038/http://www.cs.cmu.edu/~mzucker/code/perlin-noise-math-faq.html
static float tilablenoise3d(noise_t *n, double ix, double iy, double iz, double w, double h, double d)
{
double x = fmod(ix,w);
double y = fmod(iy,h);
double z = fmod(iz,d);
return(( noise3d(n, x, y, z) * (w-x) * (h-y) * (d-z) +
noise3d(n, x-w, y, z) * (x) * (h-y) * (d-z) +
noise3d(n, x-w, y-h, z) * (x) * (y) * (d-z) +
noise3d(n, x, y-h, z) * (w-x) * (y) * (d-z) +
noise3d(n, x, y, z-d) * (w-x) * (h-y) * (z) +
noise3d(n, x-w, y, z-d) * (x) * (h-y) * (z) +
noise3d(n, x-w, y-h, z-d) * (x) * (y) * (z) +
noise3d(n, x, y-h, z-d) * (w-x) * (y) * (z))/(w*h*d));
}
static int noise_texture3d(lua_State *L)
{
if (!shaders_active) return 0;
noise_t *n = (noise_t*)auxiliar_checkclass(L, "noise{core}", 1);
int w = luaL_checknumber(L, 2);
int h = luaL_checknumber(L, 3);
int d = luaL_checknumber(L, 4);
GLubyte *map = malloc(w * h * d * 3 * sizeof(GLubyte));
int i, j, k;
for (i = 0; i < w; i++)
{
for (j = 0; j < h; j++)
{
for (k = 0; k < d; k++)
{
float v = tilablenoise3d(n, i*4, j*4, k*4, w*4, h*4, d*4) * 255;
map[TEXEL3(i, j, k)] = (GLubyte)v;
map[TEXEL3(i, j, k)+1] = (GLubyte)v;
map[TEXEL3(i, j, k)+2] = (GLubyte)v;
}
}
}
GLuint *t = (GLuint*)lua_newuserdata(L, sizeof(GLuint));
auxiliar_setclass(L, "gl{texture}", -1);
glGenTextures(1, t);
glBindTexture(GL_TEXTURE_3D, *t);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_REPEAT);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB8, w, h, d, 0, GL_RGB, GL_UNSIGNED_BYTE, map);
free(map);
return 1;
}
static int noise_texture2d(lua_State *L)
{
if (!shaders_active) return 0;
noise_t *n = (noise_t*)auxiliar_checkclass(L, "noise{core}", 1);
int w = luaL_checknumber(L, 2);
int h = luaL_checknumber(L, 3);
GLubyte *map = malloc(w * h * 3 * sizeof(GLubyte));
int i, j;
for (i = 0; i < w; i++)
{
for (j = 0; j < h; j++)
{
float v = tilablenoise3d(n, i*4, j*4, 0*4, w*4, h*4, 1*4) * 255;
map[TEXEL2(i, j)] = (GLubyte)v;
map[TEXEL2(i, j)+1] = (GLubyte)v;
map[TEXEL2(i, j)+2] = (GLubyte)v;
}
}
GLuint *t = (GLuint*)lua_newuserdata(L, sizeof(GLuint));
auxiliar_setclass(L, "gl{texture}", -1);
glGenTextures(1, t);
glBindTexture(GL_TEXTURE_2D, *t);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, map);
free(map);
return 1;
}
static int noise_texture2dstack(lua_State *L)
{
if (!shaders_active) return 0;
noise_t *n = (noise_t*)auxiliar_checkclass(L, "noise{core}", 1);
int w = luaL_checknumber(L, 2);
int h = luaL_checknumber(L, 3);
int d = luaL_checknumber(L, 4);
GLubyte *map = malloc(w * h * 3 * sizeof(GLubyte));
int k;
lua_newtable(L);
for (k = 0; k < d; k++)
{
int i, j;
for (i = 0; i < w; i++)
{
for (j = 0; j < h; j++)
{
float v = tilablenoise3d(n, i*4, j*4, k*4, w*4, h*4, d*4) * 255;
map[TEXEL2(i, j)] = (GLubyte)v;
map[TEXEL2(i, j)+1] = (GLubyte)v;
map[TEXEL2(i, j)+2] = (GLubyte)v;
}
}
lua_pushnumber(L, k+1);
GLuint *t = (GLuint*)lua_newuserdata(L, sizeof(GLuint));
auxiliar_setclass(L, "gl{texture}", -1);
lua_settable(L, -3);
glGenTextures(1, t);
glBindTexture(GL_TEXTURE_2D, *t);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, map);
}
free(map);
return 1;
}
static const struct luaL_reg noiselib[] =
{
{"new", noise_new},
{NULL, NULL},
};
static const struct luaL_reg noise_reg[] =
{
{"__gc", noise_free},
{"simplex", noise_simplex},
{"fbm_simplex", noise_fbm_simplex},
{"turbulence_simplex", noise_turbulence_simplex},
{"perlin", noise_perlin},
{"fbm_perlin", noise_fbm_perlin},
{"turbulence_perlin", noise_turbulence_perlin},
{"wavelet", noise_wavelet},
{"fbm_wavelet", noise_fbm_wavelet},
{"turbulence_wavelet", noise_turbulence_wavelet},
{"makeTexture2DStack", noise_texture2dstack},
{"makeTexture2D", noise_texture2d},
{"makeTexture3D", noise_texture3d},
{NULL, NULL},
};
int luaopen_noise(lua_State *L)
{
auxiliar_newclass(L, "noise{core}", noise_reg);
luaL_openlib(L, "core.noise", noiselib, 0);
lua_pop(L, 1);
return 1;
}