aboutsummaryrefslogtreecommitdiff
path: root/src/player.h
Commit message (Expand)AuthorAge
* Add ObjectRef.hud_set_hotbar_itemcount and add TOCLIENT_HUD_SET_PARAMKahrl2013-05-26
* Fix nearly all warningskwolekr2013-05-19
* Move player collisionbox to player classsapier2013-04-25
* Added support to disable built-in HUD elementsDiego Martínez2013-04-24
* Split HUD code off to hud.cpp, make into a class, extensive Lua HUD modificationkwolekr2013-04-18
* Lua HUDJonathon Anderson2013-04-18
* Allow modifying movement speed, jump height and gravity per-player via the Lu...MirceaKitsune2013-04-05
* Update Copyright YearsSfan52013-02-24
* Change Minetest-c55 to MinetestPilzAdam2013-02-24
* Improved Player PhysicsMirceaKitsune2013-02-14
* Tilt camera on player damage (tweaked by PilzAdam)Jeija2013-01-03
* Don't send player position from client to server if the player hasn't movedMirceaKitsune2012-12-02
* RealBadAngel's patch which allows the lua api to read pressed player keys. Th...MirceaKitsune2012-11-25
* Remove special handling of creative modePerttu Ahola2012-07-25
* Allow defining player's inventory form in LuaPerttu Ahola2012-07-19
* Optimize headersPerttu Ahola2012-06-17
* Initially split utility.h to multiple files in util/Perttu Ahola2012-06-17
* Switch the license to be LGPLv2/later, with small parts still remaining as GP...Perttu Ahola2012-06-05
* Add 'fly' and 'fast' privileges and the underlying privileges-to-client systemPerttu Ahola2012-03-31
* Simple fix for camera blinking black when jumping into ceiling with current s...Perttu Ahola2012-03-29
* added PlayerSAO and RemotePlayer, removed ServerRemotePlayerKahrl2012-03-29
* LocalPlayer::getStandingNodePos()Perttu Ahola2012-03-24
* Fix some warnings on some compilersGiuseppe Bilotta2012-02-02
* Inventory menu (with dragging) improved. Crafting is now handled via a IACTIO...Kahrl2012-01-22
* The huge item definition and item namespace unification patch (itemdef), see ...Kahrl2012-01-12
* Add get_look_dir(), get_look_pitch() and get_look_yaw() for playersPerttu Ahola2011-12-28
* Move ServerRemotePlayer to a separate filePerttu Ahola2011-12-02
* Make players be again visible from a long distancePerttu Ahola2011-12-02
* Players are more like objects + related stuffPerttu Ahola2011-12-01
* Player-is-SAO WIPPerttu Ahola2011-12-01
* Proper player inventory and hp modification tracking and sending accordinglyPerttu Ahola2011-11-29
* CraftItem rework and Lua interfaceKahrl2011-11-29
* Player movement speed and node access distance checkingPerttu Ahola2011-11-29
* on_newplayer and on_respawnplayer callbacksPerttu Ahola2011-11-29
* Clean mapnode.h and fix other files accordinglyPerttu Ahola2011-11-29
* GameDef compilesPerttu Ahola2011-11-29
* Create framework for getting rid of global definitions of node/tool/item/what...Perttu Ahola2011-11-29
* Scripting WIP: dynamic object stuffPerttu Ahola2011-11-29
* ServerRemotePlayer implements ServerActiveObjectPerttu Ahola2011-11-29
* Better player damage prevention when falling on unloaded blocks, not involvin...Perttu Ahola2011-10-16
* Simplistic wielded tool lighting, added setMeshVerticesColor to utility.h and...Kahrl2011-09-21
* fix a numerical problem, but tool is still jitteryKahrl2011-09-20
* Added sprite extruderKahrl2011-09-19
* Display which tool the player is holdingJacobF2011-09-07
* Pause in unloaded territory instead of collideJacobF2011-09-06
* Keep track of player itemGiuseppe Bilotta2011-08-11
* Refactor player's eye position codingGiuseppe Bilotta2011-08-11
* Introduce Player::getLightPositionGiuseppe Bilotta2011-08-11
* Respect base virtual functions' signaturesGiuseppe Bilotta2011-08-08
* Ladders implemented!Mark Holmquist2011-08-01
49'>449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618
/*
Minetest
Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
Copyright (C) 2010-2013 kwolekr, Ryan Kwolek <kwolekr@minetest.net>

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

#include <math.h>
#include "noise.h"
#include <iostream>
#include "debug.h"
#include "util/numeric.h"

#define NOISE_MAGIC_X    1619
#define NOISE_MAGIC_Y    31337
#define NOISE_MAGIC_Z    52591
#define NOISE_MAGIC_SEED 1013

float cos_lookup[16] = {
	1.0,  0.9238,  0.7071,  0.3826, 0, -0.3826, -0.7071, -0.9238,
	1.0, -0.9238, -0.7071, -0.3826, 0,  0.3826,  0.7071,  0.9238
};


///////////////////////////////////////////////////////////////////////////////


//noise poly:  p(n) = 60493n^3 + 19990303n + 137612589
float noise2d(int x, int y, int seed) {
	int n = (NOISE_MAGIC_X * x + NOISE_MAGIC_Y * y
			+ NOISE_MAGIC_SEED * seed) & 0x7fffffff;
	n = (n >> 13) ^ n;
	n = (n * (n * n * 60493 + 19990303) + 1376312589) & 0x7fffffff;
	return 1.f - (float)n / 0x40000000;
}


float noise3d(int x, int y, int z, int seed) {
	int n = (NOISE_MAGIC_X * x + NOISE_MAGIC_Y * y + NOISE_MAGIC_Z * z
			+ NOISE_MAGIC_SEED * seed) & 0x7fffffff;
	n = (n >> 13) ^ n;
	n = (n * (n * n * 60493 + 19990303) + 1376312589) & 0x7fffffff;
	return 1.f - (float)n / 0x40000000;
}


float dotProduct(float vx, float vy, float wx, float wy) {
	return vx * wx + vy * wy;
}


inline float linearInterpolation(float v0, float v1, float t) {
    return v0 + (v1 - v0) * t;
}


float biLinearInterpolation(float v00, float v10,
							float v01, float v11,
							float x, float y) {
    float tx = easeCurve(x);
    float ty = easeCurve(y);
    float u = linearInterpolation(v00, v10, tx);
    float v = linearInterpolation(v01, v11, tx);
    return linearInterpolation(u, v, ty);
}


float biLinearInterpolationNoEase(float x0y0, float x1y0,
								  float x0y1, float x1y1,
								  float x, float y) {
    float u = linearInterpolation(x0y0, x1y0, x);
    float v = linearInterpolation(x0y1, x1y1, x);
    return linearInterpolation(u, v, y);
}


float triLinearInterpolation(
		float v000, float v100, float v010, float v110,
		float v001, float v101, float v011, float v111,
		float x, float y, float z) {
	float u = biLinearInterpolationNoEase(v000, v100, v010, v110, x, y);
	float v = biLinearInterpolationNoEase(v001, v101, v011, v111, x, y);
	return linearInterpolation(u, v, z);
}


#if 0
float triLinearInterpolation(
		float v000, float v100, float v010, float v110,
		float v001, float v101, float v011, float v111,
		float x, float y, float z)
{
	/*float tx = easeCurve(x);
	float ty = easeCurve(y);
	float tz = easeCurve(z);*/
	float tx = x;
	float ty = y;
	float tz = z;
	return(
		v000 * (1 - tx) * (1 - ty) * (1 - tz) +
		v100 * tx * (1 - ty) * (1 - tz) +
		v010 * (1 - tx) * ty * (1 - tz) +
		v110 * tx * ty * (1 - tz) +
		v001 * (1 - tx) * (1 - ty) * tz +
		v101 * tx * (1 - ty) * tz +
		v011 * (1 - tx) * ty * tz +
		v111 * tx * ty * tz
	);
}
#endif


#if 0
float noise2d_gradient(float x, float y, int seed)
{
	// Calculate the integer coordinates
	int x0 = (x > 0.0 ? (int)x : (int)x - 1);
	int y0 = (y > 0.0 ? (int)y : (int)y - 1);
	// Calculate the remaining part of the coordinates
	float xl = x - (float)x0;
	float yl = y - (float)y0;
	// Calculate random cosine lookup table indices for the integer corners.
	// They are looked up as unit vector gradients from the lookup table.
	int n00 = (int)((noise2d(x0, y0, seed)+1)*8);
	int n10 = (int)((noise2d(x0+1, y0, seed)+1)*8);
	int n01 = (int)((noise2d(x0, y0+1, seed)+1)*8);
	int n11 = (int)((noise2d(x0+1, y0+1, seed)+1)*8);
	// Make a dot product for the gradients and the positions, to get the values
	float s = dotProduct(cos_lookup[n00], cos_lookup[(n00+12)%16], xl, yl);
	float u = dotProduct(-cos_lookup[n10], cos_lookup[(n10+12)%16], 1.-xl, yl);
	float v = dotProduct(cos_lookup[n01], -cos_lookup[(n01+12)%16], xl, 1.-yl);
	float w = dotProduct(-cos_lookup[n11], -cos_lookup[(n11+12)%16], 1.-xl, 1.-yl);
	// Interpolate between the values
	return biLinearInterpolation(s,u,v,w,xl,yl);
}
#endif


float noise2d_gradient(float x, float y, int seed)
{
	// Calculate the integer coordinates
	int x0 = myfloor(x);
	int y0 = myfloor(y);
	// Calculate the remaining part of the coordinates
	float xl = x - (float)x0;
	float yl = y - (float)y0;
	// Get values for corners of square
	float v00 = noise2d(x0, y0, seed);
	float v10 = noise2d(x0+1, y0, seed);
	float v01 = noise2d(x0, y0+1, seed);
	float v11 = noise2d(x0+1, y0+1, seed);
	// Interpolate
	return biLinearInterpolation(v00,v10,v01,v11,xl,yl);
}


float noise3d_gradient(float x, float y, float z, int seed)
{
	// Calculate the integer coordinates
	int x0 = myfloor(x);
	int y0 = myfloor(y);
	int z0 = myfloor(z);
	// Calculate the remaining part of the coordinates
	float xl = x - (float)x0;
	float yl = y - (float)y0;
	float zl = z - (float)z0;
	// Get values for corners of cube
	float v000 = noise3d(x0,     y0,     z0,     seed);
	float v100 = noise3d(x0 + 1, y0,     z0,     seed);
	float v010 = noise3d(x0,     y0 + 1, z0,     seed);
	float v110 = noise3d(x0 + 1, y0 + 1, z0,     seed);
	float v001 = noise3d(x0,     y0,     z0 + 1, seed);
	float v101 = noise3d(x0 + 1, y0,     z0 + 1, seed);
	float v011 = noise3d(x0,     y0 + 1, z0 + 1, seed);
	float v111 = noise3d(x0 + 1, y0 + 1, z0 + 1, seed);
	// Interpolate
	return triLinearInterpolation(v000, v100, v010, v110,
								  v001, v101, v011, v111,
								  xl, yl, zl);
}


float noise2d_perlin(float x, float y, int seed,
		int octaves, float persistence)
{
	float a = 0;
	float f = 1.0;
	float g = 1.0;
	for (int i = 0; i < octaves; i++)
	{
		a += g * noise2d_gradient(x * f, y * f, seed + i);
		f *= 2.0;
		g *= persistence;
	}
	return a;
}


float noise2d_perlin_abs(float x, float y, int seed,
		int octaves, float persistence)
{
	float a = 0;
	float f = 1.0;
	float g = 1.0;
	for (int i = 0; i < octaves; i++)
	{
		a += g * fabs(noise2d_gradient(x * f, y * f, seed + i));
		f *= 2.0;
		g *= persistence;
	}
	return a;
}


float noise3d_perlin(float x, float y, float z, int seed,
		int octaves, float persistence)
{
	float a = 0;
	float f = 1.0;
	float g = 1.0;
	for (int i = 0; i < octaves; i++)
	{
		a += g * noise3d_gradient(x * f, y * f, z * f, seed + i);
		f *= 2.0;
		g *= persistence;
	}
	return a;
}


float noise3d_perlin_abs(float x, float y, float z, int seed,
		int octaves, float persistence)
{
	float a = 0;
	float f = 1.0;
	float g = 1.0;
	for (int i = 0; i < octaves; i++)
	{
		a += g * fabs(noise3d_gradient(x * f, y * f, z * f, seed + i));
		f *= 2.0;
		g *= persistence;
	}
	return a;
}


// -1->0, 0->1, 1->0
float contour(float v)
{
	v = fabs(v);
	if(v >= 1.0)
		return 0.0;
	return (1.0-v);
}


///////////////////////// [ New perlin stuff ] ////////////////////////////


Noise::Noise(NoiseParams *np, int seed, int sx, int sy) {
	init(np, seed, sx, sy, 1);
}


Noise::Noise(NoiseParams *np, int seed, int sx, int sy, int sz) {
	init(np, seed, sx, sy, sz);
}


void Noise::init(NoiseParams *np, int seed, int sx, int sy, int sz) {
	this->np   = np;
	this->seed = seed;
	this->sx   = sx;
	this->sy   = sy;
	this->sz   = sz;

	this->noisebuf = NULL;
	resizeNoiseBuf(sz > 1);

	this->buf    = new float[sx * sy * sz];
	this->result = new float[sx * sy * sz];
}


Noise::~Noise() {
	delete[] buf;
	delete[] result;
	delete[] noisebuf;
}


void Noise::setSize(int sx, int sy) {
	setSize(sx, sy, 1);
}


void Noise::setSize(int sx, int sy, int sz) {
	this->sx = sx;
	this->sy = sy;
	this->sz = sz;

	this->noisebuf = NULL;
	resizeNoiseBuf(sz > 1);

	delete[] buf;
	delete[] result;
	this->buf    = new float[sx * sy * sz];
	this->result = new float[sx * sy * sz];
}


void Noise::setSpreadFactor(v3f spread) {
	this->np->spread = spread;

	resizeNoiseBuf(sz > 1);
}


void Noise::setOctaves(int octaves) {
	this->np->octaves = octaves;

	resizeNoiseBuf(sz > 1);
}


void Noise::resizeNoiseBuf(bool is3d) {
	int nlx, nly, nlz;
	float ofactor;

	//maximum possible spread value factor
	ofactor = (float)(1 << (np->octaves - 1));

	//noise lattice point count
	//(int)(sz * spread * ofactor) is # of lattice points crossed due to length
	// + 2 for the two initial endpoints
	// + 1 for potentially crossing a boundary due to offset
	nlx = (int)(sx * ofactor / np->spread.X) + 3;
	nly = (int)(sy * ofactor / np->spread.Y) + 3;
	nlz = is3d ? (int)(sz * ofactor / np->spread.Z) + 3 : 1;

	if (noisebuf)
		delete[] noisebuf;
	noisebuf = new float[nlx * nly * nlz];
}


/*
 * NB:  This algorithm is not optimal in terms of space complexity.  The entire
 * integer lattice of noise points could be done as 2 lines instead, and for 3D,
 * 2 lines + 2 planes.
 * However, this would require the noise calls to be interposed with the
 * interpolation loops, which may trash the icache, leading to lower overall
 * performance.
 * Another optimization that could save half as many noise calls is to carry over
 * values from the previous noise lattice as midpoints in the new lattice for the
 * next octave.
 */
#define idx(x, y) ((y) * nlx + (x))
void Noise::gradientMap2D(float x, float y, float step_x, float step_y, int seed) {
	float v00, v01, v10, v11, u, v, orig_u;
	int index, i, j, x0, y0, noisex, noisey;
	int nlx, nly;

	x0 = floor(x);
	y0 = floor(y);
	u = x - (float)x0;
	v = y - (float)y0;
	orig_u = u;

	//calculate noise point lattice
	nlx = (int)(u + sx * step_x) + 2;
	nly = (int)(v + sy * step_y) + 2;
	index = 0;
	for (j = 0; j != nly; j++)
		for (i = 0; i != nlx; i++)
			noisebuf[index++] = noise2d(x0 + i, y0 + j, seed);

	//calculate interpolations
	index  = 0;
	noisey = 0;
	for (j = 0; j != sy; j++) {
		v00 = noisebuf[idx(0, noisey)];
		v10 = noisebuf[idx(1, noisey)];
		v01 = noisebuf[idx(0, noisey + 1)];
		v11 = noisebuf[idx(1, noisey + 1)];

		u = orig_u;
		noisex = 0;
		for (i = 0; i != sx; i++) {
			buf[index++] = biLinearInterpolation(v00, v10, v01, v11, u, v);
			u += step_x;
			if (u >= 1.0) {
				u -= 1.0;
				noisex++;
				v00 = v10;
				v01 = v11;
				v10 = noisebuf[idx(noisex + 1, noisey)];
				v11 = noisebuf[idx(noisex + 1, noisey + 1)];
			}
		}

		v += step_y;
		if (v >= 1.0) {
			v -= 1.0;
			noisey++;
		}
	}
}
#undef idx


#define idx(x, y, z) ((z) * nly * nlx + (y) * nlx + (x))
void Noise::gradientMap3D(float x, float y, float z,
						  float step_x, float step_y, float step_z,
						  int seed) {
	float v000, v010, v100, v110;
	float v001, v011, v101, v111;
	float u, v, w, orig_u, orig_v;
	int index, i, j, k, x0, y0, z0, noisex, noisey, noisez;
	int nlx, nly, nlz;

	x0 = floor(x);
	y0 = floor(y);
	z0 = floor(z);
	u = x - (float)x0;
	v = y - (float)y0;
	w = z - (float)z0;
	orig_u = u;
	orig_v = v;

	//calculate noise point lattice
	nlx = (int)(u + sx * step_x) + 2;
	nly = (int)(v + sy * step_y) + 2;
	nlz = (int)(w + sz * step_z) + 2;
	index = 0;
	for (k = 0; k != nlz; k++)
		for (j = 0; j != nly; j++)
			for (i = 0; i != nlx; i++)
				noisebuf[index++] = noise3d(x0 + i, y0 + j, z0 + k, seed);

	//calculate interpolations
	index  = 0;
	noisey = 0;
	noisez = 0;
	for (k = 0; k != sz; k++) {
		v = orig_v;
		noisey = 0;
		for (j = 0; j != sy; j++) {
			v000 = noisebuf[idx(0, noisey,     noisez)];
			v100 = noisebuf[idx(1, noisey,     noisez)];
			v010 = noisebuf[idx(0, noisey + 1, noisez)];
			v110 = noisebuf[idx(1, noisey + 1, noisez)];
			v001 = noisebuf[idx(0, noisey,     noisez + 1)];
			v101 = noisebuf[idx(1, noisey,     noisez + 1)];
			v011 = noisebuf[idx(0, noisey + 1, noisez + 1)];
			v111 = noisebuf[idx(1, noisey + 1, noisez + 1)];

			u = orig_u;
			noisex = 0;
			for (i = 0; i != sx; i++) {
				buf[index++] = triLinearInterpolation(
									v000, v100, v010, v110,
									v001, v101, v011, v111,
									u, v, w);
				u += step_x;
				if (u >= 1.0) {
					u -= 1.0;
					noisex++;
					v000 = v100;
					v010 = v110;
					v100 = noisebuf[idx(noisex + 1, noisey,     noisez)];
					v110 = noisebuf[idx(noisex + 1, noisey + 1, noisez)];
					v001 = v101;
					v011 = v111;
					v101 = noisebuf[idx(noisex + 1, noisey,     noisez + 1)];
					v111 = noisebuf[idx(noisex + 1, noisey + 1, noisez + 1)];
				}
			}

			v += step_y;
			if (v >= 1.0) {
				v -= 1.0;
				noisey++;
			}
		}

		w += step_z;
		if (w >= 1.0) {
			w -= 1.0;
			noisez++;
		}
	}
}
#undef idx


float *Noise::perlinMap2D(float x, float y) {
	float f = 1.0, g = 1.0;
	int i, j, index, oct;

	x /= np->spread.X;
	y /= np->spread.Y;

	memset(result, 0, sizeof(float) * sx * sy);

	for (oct = 0; oct < np->octaves; oct++) {
		gradientMap2D(x * f, y * f,
			f / np->spread.X, f / np->spread.Y,
			seed + np->seed + oct);

		index = 0;
		for (j = 0; j != sy; j++) {
			for (i = 0; i != sx; i++) {
				result[index] += g * buf[index];
				index++;
			}
		}

		f *= 2.0;
		g *= np->persist;
	}

	return result;
}


float *Noise::perlinMap2DModulated(float x, float y, float *persist_map) {
	float f = 1.0;
	int i, j, index, oct;

	x /= np->spread.X;
	y /= np->spread.Y;

	memset(result, 0, sizeof(float) * sx * sy);
	
	float *g = new float[sx * sy];
	for (index = 0; index != sx * sy; index++)
		g[index] = 1.0;

	for (oct = 0; oct < np->octaves; oct++) {
		gradientMap2D(x * f, y * f,
			f / np->spread.X, f / np->spread.Y,
			seed + np->seed + oct);

		index = 0;
		for (j = 0; j != sy; j++) {
			for (i = 0; i != sx; i++) {
				result[index] += g[index] * buf[index];
				g[index] *= persist_map[index];
				index++;
			}
		}

		f *= 2.0;
	}
	
	delete[] g;
	return result;
}


float *Noise::perlinMap3D(float x, float y, float z) {
	float f = 1.0, g = 1.0;
	int i, j, k, index, oct;

	x /= np->spread.X;
	y /= np->spread.Y;
	z /= np->spread.Z;

	memset(result, 0, sizeof(float) * sx * sy * sz);

	for (oct = 0; oct < np->octaves; oct++) {
		gradientMap3D(x * f, y * f, z * f,
			f / np->spread.X, f / np->spread.Y, f / np->spread.Z,
			seed + np->seed + oct);

		index = 0;
		for (k = 0; k != sz; k++) {
			for (j = 0; j != sy; j++) {
				for (i = 0; i != sx; i++) {
					result[index] += g * buf[index];
					index++;
				}
			}
		}

		f *= 2.0;
		g *= np->persist;
	}

	return result;
}


void Noise::transformNoiseMap() {
	int i = 0;
	for (int z = 0; z != sz; z++) {
		for (int y = 0; y != sy; y++) {
			for (int x = 0; x != sx; x++) {
				result[i] = result[i] * np->scale + np->offset;
				i++;
			}
		}
	}
}