tavli

changeset 6:a0d30f6f20d4

- texture coordinate generation in class Mesh - wood texture
author John Tsiombikas <nuclear@member.fsf.org>
date Fri, 26 Jun 2015 04:22:06 +0300
parents e48b40a3c82a
children f1ecc2439802
files Makefile src/board.cc src/game.cc src/mesh.cc src/mesh.h src/object.cc src/object.h src/pnoise.cc src/pnoise.h
diffstat 9 files changed, 350 insertions(+), 16 deletions(-) [+]
line diff
     1.1 --- a/Makefile	Thu Jun 25 20:43:34 2015 +0300
     1.2 +++ b/Makefile	Fri Jun 26 04:22:06 2015 +0300
     1.3 @@ -2,6 +2,7 @@
     1.4  
     1.5  src = $(wildcard src/*.cc)
     1.6  obj = $(src:.cc=.o)
     1.7 +dep = $(obj:.o=.d)
     1.8  
     1.9  bin = tavli
    1.10  
    1.11 @@ -17,10 +18,19 @@
    1.12  $(bin): $(obj)
    1.13  	$(CXX) -o $@ $(obj) $(LDFLAGS)
    1.14  
    1.15 +-include $(dep)
    1.16 +
    1.17 +%.d: %.cc
    1.18 +	@$(CPP) $(CXXFLAGS) $< -MM -MT $(@:.d=.o) >$@
    1.19 +
    1.20  .PHONY: clean
    1.21  clean:
    1.22  	rm -f $(obj) $(bin)
    1.23  
    1.24 +.PHONY: cleandep
    1.25 +cleandep:
    1.26 +	rm -f $(dep)
    1.27 +
    1.28  .PHONY: install
    1.29  install: $(bin)
    1.30  	mkdir -p $(PREFIX)/bin
     2.1 --- a/src/board.cc	Thu Jun 25 20:43:34 2015 +0300
     2.2 +++ b/src/board.cc	Fri Jun 26 04:22:06 2015 +0300
     2.3 @@ -1,7 +1,7 @@
     2.4  #include "opengl.h"
     2.5  #include "board.h"
     2.6  #include "meshgen.h"
     2.7 -
     2.8 +#include "pnoise.h"
     2.9  
    2.10  Board::Board()
    2.11  {
    2.12 @@ -109,9 +109,15 @@
    2.13  		sides->append(tmp);
    2.14  		tmp.clear();
    2.15  
    2.16 +		// generate texture coordinates
    2.17 +		sides->texcoord_gen_box();
    2.18 +
    2.19  		Object *osides = new Object;
    2.20  		osides->set_mesh(sides);
    2.21  		osides->xform() = obottom->xform();
    2.22 +		osides->set_texture(img_wood.texture());
    2.23 +		osides->tex_xform().set_scaling(Vector3(2, 2, 2));
    2.24 +		osides->tex_xform().rotate(-Vector3(1, 0, 0.5), M_PI / 4.0);
    2.25  		obj.push_back(osides);
    2.26  
    2.27  	}
    2.28 @@ -137,6 +143,17 @@
    2.29  	ohinges->set_mesh(hinges);
    2.30  	obj.push_back(ohinges);
    2.31  
    2.32 +	// debug object
    2.33 +	/*Mesh *dbgmesh = new Mesh;
    2.34 +	gen_box(dbgmesh, 0.5, 0.5, 0.5);
    2.35 +	xform.set_translation(Vector3(0, 0.4, 0));
    2.36 +	xform.set_scaling(Vector3(4, 1, 4));
    2.37 +	dbgmesh->apply_xform(xform);
    2.38 +	Object *dbgobj = new Object;
    2.39 +	dbgobj->set_mesh(dbgmesh);
    2.40 +	dbgobj->set_texture(img_wood.texture());
    2.41 +	dbgobj->tex_xform().set_scaling(Vector3(3, 3, 3));
    2.42 +	obj.push_back(dbgobj);*/
    2.43  
    2.44  	return true;
    2.45  }
    2.46 @@ -157,6 +174,20 @@
    2.47  	return val < 0.0 ? 0.0 : (val > 1.0 ? 1.0 : val);
    2.48  }
    2.49  
    2.50 +static float wood_tile(float x, float y)
    2.51 +{
    2.52 +	float u = x;
    2.53 +	float v = y;
    2.54 +	x *= 10.0;
    2.55 +	y *= 10.0;
    2.56 +
    2.57 +	float val = x + pnoise2(u * 6.0, v, 6, 1) * 3.0 +
    2.58 +		pturbulence2(u * 4, v * 2, 4, 2, 2) * 1.5 + pturbulence2(u * 8, v * 8, 8, 8, 2) * 0.5;
    2.59 +
    2.60 +	val = fmod(val, 1.0);
    2.61 +	return val < 0.0 ? 0.0 : (val > 1.0 ? 1.0 : val);
    2.62 +}
    2.63 +
    2.64  static bool spike(float x, float y)
    2.65  {
    2.66  	x = fmod(x * 5.0, 1.0);
    2.67 @@ -185,20 +216,18 @@
    2.68  
    2.69  bool Board::generate_textures()
    2.70  {
    2.71 +	// ---- board field texture ----
    2.72  	static const Vector3 wcol1 = Vector3(0.6, 0.4, 0.2);
    2.73 -	static const Vector3 wcol2 = Vector3(0.53, 0.32, 0.1);//Vector3(0.38, 0.25, 0.08);
    2.74 +	static const Vector3 wcol2 = Vector3(0.53, 0.32, 0.1);
    2.75 +	static const Vector3 wcol3 = Vector3(0.38, 0.25, 0.08);
    2.76  
    2.77 -	const int xsz = 512;
    2.78 -	const int ysz = 1024;
    2.79 +	img_field.create(512, 1024);
    2.80 +	unsigned char *pptr = img_field.pixels;
    2.81 +	for(int i=0; i<img_field.height; i++) {
    2.82 +		float v = (float)i / (float)img_field.height;
    2.83  
    2.84 -	img_field.create(xsz, ysz);
    2.85 -
    2.86 -	unsigned char *pptr = img_field.pixels;
    2.87 -	for(int i=0; i<ysz; i++) {
    2.88 -		float v = (float)i / (float)ysz;
    2.89 -
    2.90 -		for(int j=0; j<xsz; j++) {
    2.91 -			float u = (float)j / (float)xsz;
    2.92 +		for(int j=0; j<img_field.width; j++) {
    2.93 +			float u = (float)j / (float)img_field.width;
    2.94  
    2.95  			int r = 0, g = 0, b = 0;
    2.96  
    2.97 @@ -231,7 +260,29 @@
    2.98  			pptr += 3;
    2.99  		}
   2.100  	}
   2.101 +	img_field.texture();
   2.102  
   2.103 -	img_field.texture();
   2.104 +	// ---- generic wood texture ----
   2.105 +	img_wood.create(256, 256);
   2.106 +	pptr = img_wood.pixels;
   2.107 +	for(int i=0; i<img_wood.height; i++) {
   2.108 +		float v = (float)i / (float)img_wood.height;
   2.109 +		for(int j=0; j<img_wood.width; j++) {
   2.110 +			float u = (float)j / (float)img_wood.width;
   2.111 +
   2.112 +			float wood_val = wood_tile(u, v);
   2.113 +			Vector3 wood_color = lerp(wcol2, wcol3, wood_val) * 0.7;
   2.114 +
   2.115 +			int r = (int)(wood_color.x * 255.0);
   2.116 +			int g = (int)(wood_color.y * 255.0);
   2.117 +			int b = (int)(wood_color.z * 255.0);
   2.118 +
   2.119 +			pptr[0] = r > 255 ? 255 : r;
   2.120 +			pptr[1] = g > 255 ? 255 : g;
   2.121 +			pptr[2] = b > 255 ? 255 : b;
   2.122 +			pptr += 3;
   2.123 +		}
   2.124 +	}
   2.125 +	img_wood.texture();
   2.126  	return true;
   2.127  }
     3.1 --- a/src/game.cc	Thu Jun 25 20:43:34 2015 +0300
     3.2 +++ b/src/game.cc	Fri Jun 26 04:22:06 2015 +0300
     3.3 @@ -52,8 +52,10 @@
     3.4  	glRotatef(cam_phi, 1, 0, 0);
     3.5  	glRotatef(cam_theta, 0, 1, 0);
     3.6  
     3.7 +	float ldir[] = {-1, 2, 1, 0};
     3.8 +	glLightfv(GL_LIGHT0, GL_POSITION, ldir);
     3.9 +
    3.10  	draw_backdrop();
    3.11 -
    3.12  	board.draw();
    3.13  }
    3.14  
     4.1 --- a/src/mesh.cc	Thu Jun 25 20:43:34 2015 +0300
     4.2 +++ b/src/mesh.cc	Fri Jun 26 04:22:06 2015 +0300
     4.3 @@ -931,6 +931,72 @@
     4.4  }
     4.5  
     4.6  
     4.7 +// texture coordinate manipulation
     4.8 +void Mesh::texcoord_apply_xform(const Matrix4x4 &xform)
     4.9 +{
    4.10 +	if(!has_attrib(MESH_ATTR_TEXCOORD)) {
    4.11 +		return;
    4.12 +	}
    4.13 +
    4.14 +	for(unsigned int i=0; i<nverts; i++) {
    4.15 +		Vector4 tc = get_attrib(MESH_ATTR_TEXCOORD, i);
    4.16 +		set_attrib(MESH_ATTR_TEXCOORD, i, tc.transformed(xform));
    4.17 +	}
    4.18 +}
    4.19 +
    4.20 +void Mesh::texcoord_gen_plane(const Vector3 &norm, const Vector3 &tang)
    4.21 +{
    4.22 +	if(!nverts) return;
    4.23 +
    4.24 +	if(!has_attrib(MESH_ATTR_TEXCOORD)) {
    4.25 +		// allocate texture coordinate attribute array
    4.26 +		set_attrib_data(MESH_ATTR_TEXCOORD, 2, nverts);
    4.27 +	}
    4.28 +
    4.29 +	Vector3 n = norm.normalized();
    4.30 +	Vector3 b = cross_product(n, tang).normalized();
    4.31 +	Vector3 t = cross_product(b, n);
    4.32 +
    4.33 +	for(unsigned int i=0; i<nverts; i++) {
    4.34 +		Vector3 pos = get_attrib(MESH_ATTR_VERTEX, i);
    4.35 +
    4.36 +		// distance along the tangent direction
    4.37 +		float u = dot_product(pos, t);
    4.38 +		// distance along the bitangent direction
    4.39 +		float v = dot_product(pos, b);
    4.40 +
    4.41 +		set_attrib(MESH_ATTR_TEXCOORD, i, Vector4(u, v, 0, 1));
    4.42 +	}
    4.43 +}
    4.44 +
    4.45 +void Mesh::texcoord_gen_box()
    4.46 +{
    4.47 +	if(!nverts || !has_attrib(MESH_ATTR_NORMAL)) return;
    4.48 +
    4.49 +	if(!has_attrib(MESH_ATTR_TEXCOORD)) {
    4.50 +		// allocate texture coordinate attribute array
    4.51 +		set_attrib_data(MESH_ATTR_TEXCOORD, 2, nverts);
    4.52 +	}
    4.53 +
    4.54 +	for(unsigned int i=0; i<nverts; i++) {
    4.55 +		Vector3 pos = Vector3(get_attrib(MESH_ATTR_VERTEX, i)) * 0.5 + Vector3(0.5, 0.5, 0.5);
    4.56 +		Vector3 norm = get_attrib(MESH_ATTR_NORMAL, i);
    4.57 +
    4.58 +		float abs_nx = fabs(norm.x);
    4.59 +		float abs_ny = fabs(norm.y);
    4.60 +		float abs_nz = fabs(norm.z);
    4.61 +		int dom = abs_nx > abs_ny && abs_nx > abs_nz ? 0 : (abs_ny > abs_nz ? 1 : 2);
    4.62 +
    4.63 +		float uv[2], *uvptr = uv;
    4.64 +		for(int j=0; j<3; j++) {
    4.65 +			if(j == dom) continue;	// skip dominant axis
    4.66 +
    4.67 +			*uvptr++ = pos[j];
    4.68 +		}
    4.69 +		set_attrib(MESH_ATTR_TEXCOORD, i, Vector4(uv[0], uv[1], 0, 1));
    4.70 +	}
    4.71 +}
    4.72 +
    4.73  // ------ private member functions ------
    4.74  
    4.75  void Mesh::calc_aabb()
     5.1 --- a/src/mesh.h	Thu Jun 25 20:43:34 2015 +0300
     5.2 +++ b/src/mesh.h	Fri Jun 26 04:22:06 2015 +0300
     5.3 @@ -220,6 +220,11 @@
     5.4  	 *     If you intend to use it in a speed-critical part of the code, you'll *have* to optimize it!
     5.5  	 */
     5.6  	bool intersect(const Ray &ray, HitPoint *hit = 0) const;
     5.7 +
     5.8 +	// texture coordinate manipulation
     5.9 +	void texcoord_apply_xform(const Matrix4x4 &xform);
    5.10 +	void texcoord_gen_plane(const Vector3 &norm, const Vector3 &tang);
    5.11 +	void texcoord_gen_box();
    5.12  };
    5.13  
    5.14  #endif	// MESH_H_
     6.1 --- a/src/object.cc	Thu Jun 25 20:43:34 2015 +0300
     6.2 +++ b/src/object.cc	Fri Jun 26 04:22:06 2015 +0300
     6.3 @@ -5,6 +5,11 @@
     6.4  {
     6.5  	mesh = 0;
     6.6  	tex = 0;
     6.7 +
     6.8 +	mtl.diffuse = Vector3(1, 1, 1);
     6.9 +	mtl.specular = Vector3(0, 0, 0);
    6.10 +	mtl.shininess = 60.0;
    6.11 +	mtl.alpha = 1.0;
    6.12  }
    6.13  
    6.14  Object::~Object()
    6.15 @@ -22,6 +27,16 @@
    6.16  	return matrix;
    6.17  }
    6.18  
    6.19 +Matrix4x4 &Object::tex_xform()
    6.20 +{
    6.21 +	return tex_matrix;
    6.22 +}
    6.23 +
    6.24 +const Matrix4x4 &Object::tex_xform() const
    6.25 +{
    6.26 +	return tex_matrix;
    6.27 +}
    6.28 +
    6.29  void Object::set_mesh(Mesh *m)
    6.30  {
    6.31  	this->mesh = m;
    6.32 @@ -44,6 +59,10 @@
    6.33  	if(tex) {
    6.34  		glBindTexture(GL_TEXTURE_2D, tex);
    6.35  		glEnable(GL_TEXTURE_2D);
    6.36 +
    6.37 +		glMatrixMode(GL_TEXTURE);
    6.38 +		glPushMatrix();
    6.39 +		glLoadTransposeMatrixf(tex_matrix[0]);
    6.40  	} else {
    6.41  		glDisable(GL_TEXTURE_2D);
    6.42  	}
    6.43 @@ -52,13 +71,23 @@
    6.44  	glPushMatrix();
    6.45  	glMultTransposeMatrixf(matrix[0]);
    6.46  
    6.47 +	float dcol[] = {mtl.diffuse.x, mtl.diffuse.y, mtl.diffuse.z, mtl.alpha};
    6.48 +	glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, dcol);
    6.49 +	float scol[] = {mtl.specular.x, mtl.specular.y, mtl.specular.z, 1.0f};
    6.50 +	glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, scol);
    6.51 +	glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, mtl.shininess);
    6.52 +
    6.53  	mesh->draw();
    6.54  
    6.55 -	glPopMatrix();
    6.56 -
    6.57  	if(tex) {
    6.58  		glDisable(GL_TEXTURE_2D);
    6.59 +
    6.60 +		glMatrixMode(GL_TEXTURE);
    6.61 +		glPopMatrix();
    6.62  	}
    6.63 +
    6.64 +	glMatrixMode(GL_MODELVIEW);
    6.65 +	glPopMatrix();
    6.66  }
    6.67  
    6.68  bool Object::intersect(const Ray &ray, HitPoint *hit) const
     7.1 --- a/src/object.h	Thu Jun 25 20:43:34 2015 +0300
     7.2 +++ b/src/object.h	Fri Jun 26 04:22:06 2015 +0300
     7.3 @@ -3,20 +3,34 @@
     7.4  
     7.5  #include "mesh.h"
     7.6  #include "geom.h"
     7.7 +#include "vmath/vmath.h"
     7.8 +
     7.9 +struct Material {
    7.10 +	Vector3 diffuse;
    7.11 +	Vector3 specular;
    7.12 +	float shininess;
    7.13 +	float alpha;
    7.14 +};
    7.15  
    7.16  class Object {
    7.17  private:
    7.18  	Mesh *mesh;
    7.19  	Matrix4x4 matrix;
    7.20  	unsigned int tex;
    7.21 +	Matrix4x4 tex_matrix;
    7.22  
    7.23  public:
    7.24 +	Material mtl;
    7.25 +
    7.26  	Object();
    7.27  	~Object();
    7.28  
    7.29  	Matrix4x4 &xform();
    7.30  	const Matrix4x4 &xform() const;
    7.31  
    7.32 +	Matrix4x4 &tex_xform();
    7.33 +	const Matrix4x4 &tex_xform() const;
    7.34 +
    7.35  	void set_mesh(Mesh *m);
    7.36  	Mesh *get_mesh() const;
    7.37  
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/src/pnoise.cc	Fri Jun 26 04:22:06 2015 +0300
     8.3 @@ -0,0 +1,149 @@
     8.4 +#include <stdlib.h>
     8.5 +#include "pnoise.h"
     8.6 +#include "vmath/vmath.h"
     8.7 +
     8.8 +#define B	0x100
     8.9 +#define BM	0xff
    8.10 +#define N	0x1000
    8.11 +#define NP	12
    8.12 +#define NM	0xfff
    8.13 +
    8.14 +#define s_curve(t)	((t) * (t) * (3.0f - 2.0f * (t)))
    8.15 +#define setup(elem, b0, b1, r0, r1) \
    8.16 +	do {							\
    8.17 +		float t = elem + N;		\
    8.18 +		b0 = ((int)t) & BM;			\
    8.19 +		b1 = (b0 + 1) & BM;			\
    8.20 +		r0 = t - (int)t;			\
    8.21 +		r1 = r0 - 1.0f;				\
    8.22 +	} while(0)
    8.23 +
    8.24 +#define setup_p(elem, b0, b1, r0, r1, p) \
    8.25 +	do {							\
    8.26 +		float t = elem + N;		\
    8.27 +		b0 = (((int)t) & BM) % p;	\
    8.28 +		b1 = ((b0 + 1) & BM) % p;	\
    8.29 +		r0 = t - (int)t;			\
    8.30 +		r1 = r0 - 1.0f;				\
    8.31 +	} while(0)
    8.32 +
    8.33 +static int perm[B + B + 2];
    8.34 +static vec2_t grad2[B + B + 2];
    8.35 +static bool tables_valid;
    8.36 +
    8.37 +static void init_noise()
    8.38 +{
    8.39 +	for(int i=0; i<B; i++) {
    8.40 +		perm[i] = i;
    8.41 +
    8.42 +		grad2[i].x = (float)((rand() % (B + B)) - B) / B;
    8.43 +		grad2[i].y = (float)((rand() % (B + B)) - B) / B;
    8.44 +		grad2[i] = v2_normalize(grad2[i]);
    8.45 +	}
    8.46 +
    8.47 +	for(int i=0; i<B; i++) {
    8.48 +		int rand_idx = rand() % B;
    8.49 +
    8.50 +		int tmp = perm[i];
    8.51 +		perm[i] = perm[rand_idx];
    8.52 +		perm[rand_idx] = tmp;
    8.53 +	}
    8.54 +
    8.55 +	for(int i=0; i<B+2; i++) {
    8.56 +		perm[B + i] = perm[i];
    8.57 +		grad2[B + i] = grad2[i];
    8.58 +	}
    8.59 +}
    8.60 +
    8.61 +#define lerp(a, b, t)	((a) + ((b) - (a)) * t)
    8.62 +
    8.63 +float dbg_noise2(float x, float y)
    8.64 +{
    8.65 +	if(!tables_valid) {
    8.66 +		init_noise();
    8.67 +		tables_valid = true;
    8.68 +	}
    8.69 +
    8.70 +	int bx0, bx1, by0, by1;
    8.71 +	float rx0, rx1, ry0, ry1;
    8.72 +	setup(x, bx0, bx1, rx0, rx1);
    8.73 +	setup(y, by0, by1, ry0, ry1);
    8.74 +
    8.75 +	int i = perm[bx0];
    8.76 +	int j = perm[bx1];
    8.77 +
    8.78 +	int b00 = perm[i + by0];
    8.79 +	int b10 = perm[j + by0];
    8.80 +	int b01 = perm[i + by1];
    8.81 +	int b11 = perm[j + by1];
    8.82 +
    8.83 +	float sx = s_curve(rx0);
    8.84 +	float sy = s_curve(ry0);
    8.85 +
    8.86 +	vec2_t g00 = grad2[b00];
    8.87 +	vec2_t g10 = grad2[b10];
    8.88 +	vec2_t g01 = grad2[b01];
    8.89 +	vec2_t g11 = grad2[b11];
    8.90 +
    8.91 +	float u = g00.x * rx0 + g00.y * ry0;
    8.92 +	float v = g10.x * rx1 + g10.y * ry0;
    8.93 +	float a = lerp(u, v, sx);
    8.94 +
    8.95 +	u = g01.x * rx0 + g01.y * ry1;
    8.96 +	v = g11.x * rx1 + g11.y * ry1;
    8.97 +	float b = lerp(u, v, sx);
    8.98 +
    8.99 +	return lerp(a, b, sy);
   8.100 +}
   8.101 +
   8.102 +float pnoise2(float x, float y, int periodx, int periody)
   8.103 +{
   8.104 +	if(!tables_valid) {
   8.105 +		init_noise();
   8.106 +		tables_valid = true;
   8.107 +	}
   8.108 +
   8.109 +	int bx0, bx1, by0, by1;
   8.110 +	float rx0, rx1, ry0, ry1;
   8.111 +	setup_p(x, bx0, bx1, rx0, rx1, periodx);
   8.112 +	setup_p(y, by0, by1, ry0, ry1, periody);
   8.113 +
   8.114 +	int i = perm[bx0];
   8.115 +	int j = perm[bx1];
   8.116 +
   8.117 +	int b00 = perm[i + by0];
   8.118 +	int b10 = perm[j + by0];
   8.119 +	int b01 = perm[i + by1];
   8.120 +	int b11 = perm[j + by1];
   8.121 +
   8.122 +	float sx = s_curve(rx0);
   8.123 +	float sy = s_curve(ry0);
   8.124 +
   8.125 +	vec2_t g00 = grad2[b00];
   8.126 +	vec2_t g10 = grad2[b10];
   8.127 +	vec2_t g01 = grad2[b01];
   8.128 +	vec2_t g11 = grad2[b11];
   8.129 +
   8.130 +	float u = g00.x * rx0 + g00.y * ry0;
   8.131 +	float v = g10.x * rx1 + g10.y * ry0;
   8.132 +	float a = lerp(u, v, sx);
   8.133 +
   8.134 +	u = g01.x * rx0 + g01.y * ry1;
   8.135 +	v = g11.x * rx1 + g11.y * ry1;
   8.136 +	float b = lerp(u, v, sx);
   8.137 +
   8.138 +	return lerp(a, b, sy);
   8.139 +}
   8.140 +
   8.141 +float pturbulence2(float x, float y, int periodx, int periody, int octaves)
   8.142 +{
   8.143 +	int i;
   8.144 +	float res = 0.0f, freq = 1.0f;
   8.145 +	for(i=0; i<octaves; i++) {
   8.146 +		res += fabs(pnoise2(x * freq, y * freq, periodx, periody) / freq);
   8.147 +		freq *= 2.0f;
   8.148 +		periodx *= 2;
   8.149 +		periody *= 2;
   8.150 +	}
   8.151 +	return res;
   8.152 +}
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/src/pnoise.h	Fri Jun 26 04:22:06 2015 +0300
     9.3 @@ -0,0 +1,8 @@
     9.4 +#ifndef PNOISE_H_
     9.5 +#define PNOISE_H_
     9.6 +
     9.7 +float dbg_noise2(float x, float y);
     9.8 +float pnoise2(float x, float y, int periodx, int periody);
     9.9 +float pturbulence2(float x, float y, int periodx, int periody, int octaves);
    9.10 +
    9.11 +#endif	// PNOISE_H_