diff --git a/composer.json b/composer.json index 54756a5cb..d0584c1ca 100644 --- a/composer.json +++ b/composer.json @@ -24,7 +24,8 @@ "pocketmine/raklib": "dev-master#31d6522de71a9c404aff5c23c49c6ea0526793fb", "pocketmine/spl": "dev-master#ee32424c100fd11ae7f7b8df7604623fd475f0ec", "pocketmine/binaryutils": "dev-master#03e6851f814aba96487ec64181a6ae948edd9f7a", - "pocketmine/nbt": "dev-master#e8fb4c11b291e96c2b44220a5d00f97c1692556e" + "pocketmine/nbt": "dev-master#e8fb4c11b291e96c2b44220a5d00f97c1692556e", + "pocketmine/math": "dev-master#e0fe8ab70bcacead007cf11dd5b74adc91d94388" }, "autoload": { "psr-4": { @@ -47,6 +48,10 @@ { "type": "vcs", "url": "https://github.com/pmmp/NBT" + }, + { + "type": "vcs", + "url": "https://github.com/pmmp/Math" } ] } diff --git a/composer.lock b/composer.lock index 0a8e17532..6343462cf 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "3426771a9526fe9ecb4c66b2ec87a3dd", + "content-hash": "e04780cd000c97da7b356dfdf858bf47", "packages": [ { "name": "pocketmine/binaryutils", @@ -39,6 +39,39 @@ }, "time": "2018-03-17T11:57:06+00:00" }, + { + "name": "pocketmine/math", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/pmmp/Math.git", + "reference": "e0fe8ab70bcacead007cf11dd5b74adc91d94388" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/pmmp/Math/zipball/e0fe8ab70bcacead007cf11dd5b74adc91d94388", + "reference": "e0fe8ab70bcacead007cf11dd5b74adc91d94388", + "shasum": "" + }, + "require": { + "php": ">=7.2.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "pocketmine\\math\\": "src/" + } + }, + "license": [ + "LGPL-3.0" + ], + "description": "PHP library containing math related code used in PocketMine-MP", + "support": { + "source": "https://github.com/pmmp/Math/tree/master", + "issues": "https://github.com/pmmp/Math/issues" + }, + "time": "2018-03-17T12:35:50+00:00" + }, { "name": "pocketmine/nbt", "version": "dev-master", @@ -158,7 +191,8 @@ "pocketmine/raklib": 20, "pocketmine/spl": 20, "pocketmine/binaryutils": 20, - "pocketmine/nbt": 20 + "pocketmine/nbt": 20, + "pocketmine/math": 20 }, "prefer-stable": false, "prefer-lowest": false, diff --git a/src/pocketmine/math/AxisAlignedBB.php b/src/pocketmine/math/AxisAlignedBB.php deleted file mode 100644 index a126ff720..000000000 --- a/src/pocketmine/math/AxisAlignedBB.php +++ /dev/null @@ -1,432 +0,0 @@ -minX = $minX; - $this->minY = $minY; - $this->minZ = $minZ; - $this->maxX = $maxX; - $this->maxY = $maxY; - $this->maxZ = $maxZ; - } - - public function setBounds(float $minX, float $minY, float $minZ, float $maxX, float $maxY, float $maxZ){ - $this->minX = $minX; - $this->minY = $minY; - $this->minZ = $minZ; - $this->maxX = $maxX; - $this->maxY = $maxY; - $this->maxZ = $maxZ; - - return $this; - } - - /** - * Returns a new AxisAlignedBB extended by the specified X, Y and Z. - * If each of X, Y and Z are positive, the relevant max bound will be increased. If negative, the relevant min - * bound will be decreased. - * - * @param float $x - * @param float $y - * @param float $z - * - * @return AxisAlignedBB - */ - public function addCoord(float $x, float $y, float $z) : AxisAlignedBB{ - $minX = $this->minX; - $minY = $this->minY; - $minZ = $this->minZ; - $maxX = $this->maxX; - $maxY = $this->maxY; - $maxZ = $this->maxZ; - - if($x < 0){ - $minX += $x; - }elseif($x > 0){ - $maxX += $x; - } - - if($y < 0){ - $minY += $y; - }elseif($y > 0){ - $maxY += $y; - } - - if($z < 0){ - $minZ += $z; - }elseif($z > 0){ - $maxZ += $z; - } - - return new AxisAlignedBB($minX, $minY, $minZ, $maxX, $maxY, $maxZ); - } - - /** - * Returns a new AxisAlignedBB with bounds outset by the specified X, Y and Z. - * - * @param float $x - * @param float $y - * @param float $z - * - * @return AxisAlignedBB - */ - public function grow(float $x, float $y, float $z) : AxisAlignedBB{ - return new AxisAlignedBB($this->minX - $x, $this->minY - $y, $this->minZ - $z, $this->maxX + $x, $this->maxY + $y, $this->maxZ + $z); - } - - /** - * Performs the same operation as grow() but operates on itself instead of returning a new object. - * @param float $x - * @param float $y - * @param float $z - * - * @return $this - */ - public function expand(float $x, float $y, float $z){ - $this->minX -= $x; - $this->minY -= $y; - $this->minZ -= $z; - $this->maxX += $x; - $this->maxY += $y; - $this->maxZ += $z; - - return $this; - } - - /** - * Performs the same operation as getOffsetBoundingBox(), but operates on itself instead of returning a new object. - * - * @param float $x - * @param float $y - * @param float $z - * - * @return $this - */ - public function offset(float $x, float $y, float $z){ - $this->minX += $x; - $this->minY += $y; - $this->minZ += $z; - $this->maxX += $x; - $this->maxY += $y; - $this->maxZ += $z; - - return $this; - } - - /** - * Returns a new AxisAlignedBB with bounds inset by the specified X, Y and Z. - * - * @param float $x - * @param float $y - * @param float $z - * - * @return AxisAlignedBB - */ - public function shrink(float $x, float $y, float $z) : AxisAlignedBB{ - return new AxisAlignedBB($this->minX + $x, $this->minY + $y, $this->minZ + $z, $this->maxX - $x, $this->maxY - $y, $this->maxZ - $z); - } - - /** - * Performs the same operation as shrink(), but operates on itself instead of returning a new object. - * - * @param float $x - * @param float $y - * @param float $z - * - * @return $this - */ - public function contract(float $x, float $y, float $z){ - $this->minX += $x; - $this->minY += $y; - $this->minZ += $z; - $this->maxX -= $x; - $this->maxY -= $y; - $this->maxZ -= $z; - - return $this; - } - - /** - * Sets the bounding box's bounds from another AxisAlignedBB, and returns itself - * - * @param AxisAlignedBB $bb - * @return $this - */ - public function setBB(AxisAlignedBB $bb){ - $this->minX = $bb->minX; - $this->minY = $bb->minY; - $this->minZ = $bb->minZ; - $this->maxX = $bb->maxX; - $this->maxY = $bb->maxY; - $this->maxZ = $bb->maxZ; - return $this; - } - - /** - * Returns a new AxisAlignedBB shifted by the specified X, Y and Z - * - * @param float $x - * @param float $y - * @param float $z - * - * @return AxisAlignedBB - */ - public function getOffsetBoundingBox(float $x, float $y, float $z) : AxisAlignedBB{ - return new AxisAlignedBB($this->minX + $x, $this->minY + $y, $this->minZ + $z, $this->maxX + $x, $this->maxY + $y, $this->maxZ + $z); - } - - public function calculateXOffset(AxisAlignedBB $bb, float $x) : float{ - if($bb->maxY <= $this->minY or $bb->minY >= $this->maxY){ - return $x; - } - if($bb->maxZ <= $this->minZ or $bb->minZ >= $this->maxZ){ - return $x; - } - if($x > 0 and $bb->maxX <= $this->minX){ - $x1 = $this->minX - $bb->maxX; - if($x1 < $x){ - $x = $x1; - } - }elseif($x < 0 and $bb->minX >= $this->maxX){ - $x2 = $this->maxX - $bb->minX; - if($x2 > $x){ - $x = $x2; - } - } - - return $x; - } - - public function calculateYOffset(AxisAlignedBB $bb, float $y) : float{ - if($bb->maxX <= $this->minX or $bb->minX >= $this->maxX){ - return $y; - } - if($bb->maxZ <= $this->minZ or $bb->minZ >= $this->maxZ){ - return $y; - } - if($y > 0 and $bb->maxY <= $this->minY){ - $y1 = $this->minY - $bb->maxY; - if($y1 < $y){ - $y = $y1; - } - }elseif($y < 0 and $bb->minY >= $this->maxY){ - $y2 = $this->maxY - $bb->minY; - if($y2 > $y){ - $y = $y2; - } - } - - return $y; - } - - public function calculateZOffset(AxisAlignedBB $bb, float $z) : float{ - if($bb->maxX <= $this->minX or $bb->minX >= $this->maxX){ - return $z; - } - if($bb->maxY <= $this->minY or $bb->minY >= $this->maxY){ - return $z; - } - if($z > 0 and $bb->maxZ <= $this->minZ){ - $z1 = $this->minZ - $bb->maxZ; - if($z1 < $z){ - $z = $z1; - } - }elseif($z < 0 and $bb->minZ >= $this->maxZ){ - $z2 = $this->maxZ - $bb->minZ; - if($z2 > $z){ - $z = $z2; - } - } - - return $z; - } - - /** - * Returns whether any part of the specified AABB is inside (intersects with) this one. - * - * @param AxisAlignedBB $bb - * @param float $epsilon - * - * @return bool - */ - public function intersectsWith(AxisAlignedBB $bb, float $epsilon = 0.00001) : bool{ - if($bb->maxX - $this->minX > $epsilon and $this->maxX - $bb->minX > $epsilon){ - if($bb->maxY - $this->minY > $epsilon and $this->maxY - $bb->minY > $epsilon){ - return $bb->maxZ - $this->minZ > $epsilon and $this->maxZ - $bb->minZ > $epsilon; - } - } - - return false; - } - - /** - * Returns whether the specified vector is within the bounds of this AABB on all axes. - * - * @param Vector3 $vector - * @return bool - */ - public function isVectorInside(Vector3 $vector) : bool{ - if($vector->x <= $this->minX or $vector->x >= $this->maxX){ - return false; - } - if($vector->y <= $this->minY or $vector->y >= $this->maxY){ - return false; - } - - return $vector->z > $this->minZ and $vector->z < $this->maxZ; - } - - /** - * Returns the mean average of the AABB's X, Y and Z lengths. - * @return float - */ - public function getAverageEdgeLength() : float{ - return ($this->maxX - $this->minX + $this->maxY - $this->minY + $this->maxZ - $this->minZ) / 3; - } - - /** - * Returns whether the specified vector is within the Y and Z bounds of this AABB. - * - * @param Vector3 $vector - * @return bool - */ - public function isVectorInYZ(Vector3 $vector) : bool{ - return $vector->y >= $this->minY and $vector->y <= $this->maxY and $vector->z >= $this->minZ and $vector->z <= $this->maxZ; - } - - /** - * Returns whether the specified vector is within the X and Z bounds of this AABB. - * - * @param Vector3 $vector - * @return bool - */ - public function isVectorInXZ(Vector3 $vector) : bool{ - return $vector->x >= $this->minX and $vector->x <= $this->maxX and $vector->z >= $this->minZ and $vector->z <= $this->maxZ; - } - - /** - * Returns whether the specified vector is within the X and Y bounds of this AABB. - * - * @param Vector3 $vector - * @return bool - */ - public function isVectorInXY(Vector3 $vector) : bool{ - return $vector->x >= $this->minX and $vector->x <= $this->maxX and $vector->y >= $this->minY and $vector->y <= $this->maxY; - } - - /** - * Performs a ray-trace and calculates the point on the AABB's edge nearest the start position that the ray-trace - * collided with. Returns a RayTraceResult with colliding vector closest to the start position. - * Returns null if no colliding point was found. - * - * @param Vector3 $pos1 - * @param Vector3 $pos2 - * - * @return RayTraceResult|null - */ - public function calculateIntercept(Vector3 $pos1, Vector3 $pos2) : ?RayTraceResult{ - $v1 = $pos1->getIntermediateWithXValue($pos2, $this->minX); - $v2 = $pos1->getIntermediateWithXValue($pos2, $this->maxX); - $v3 = $pos1->getIntermediateWithYValue($pos2, $this->minY); - $v4 = $pos1->getIntermediateWithYValue($pos2, $this->maxY); - $v5 = $pos1->getIntermediateWithZValue($pos2, $this->minZ); - $v6 = $pos1->getIntermediateWithZValue($pos2, $this->maxZ); - - if($v1 !== null and !$this->isVectorInYZ($v1)){ - $v1 = null; - } - - if($v2 !== null and !$this->isVectorInYZ($v2)){ - $v2 = null; - } - - if($v3 !== null and !$this->isVectorInXZ($v3)){ - $v3 = null; - } - - if($v4 !== null and !$this->isVectorInXZ($v4)){ - $v4 = null; - } - - if($v5 !== null and !$this->isVectorInXY($v5)){ - $v5 = null; - } - - if($v6 !== null and !$this->isVectorInXY($v6)){ - $v6 = null; - } - - $vector = null; - $distance = PHP_INT_MAX; - - foreach([$v1, $v2, $v3, $v4, $v5, $v6] as $v){ - if($v !== null and ($d = $pos1->distanceSquared($v)) < $distance){ - $vector = $v; - $distance = $d; - } - } - - if($vector === null){ - return null; - } - - $f = -1; - - if($vector === $v1){ - $f = Vector3::SIDE_WEST; - }elseif($vector === $v2){ - $f = Vector3::SIDE_EAST; - }elseif($vector === $v3){ - $f = Vector3::SIDE_DOWN; - }elseif($vector === $v4){ - $f = Vector3::SIDE_UP; - }elseif($vector === $v5){ - $f = Vector3::SIDE_NORTH; - }elseif($vector === $v6){ - $f = Vector3::SIDE_SOUTH; - } - - return new RayTraceResult($this, $f, $vector); - } - - public function __toString(){ - return "AxisAlignedBB({$this->minX}, {$this->minY}, {$this->minZ}, {$this->maxX}, {$this->maxY}, {$this->maxZ})"; - } -} diff --git a/src/pocketmine/math/Math.php b/src/pocketmine/math/Math.php deleted file mode 100644 index 025186c9d..000000000 --- a/src/pocketmine/math/Math.php +++ /dev/null @@ -1,67 +0,0 @@ -= $i ? $i : $i - 1; - } - - public static function ceilFloat($n) : int{ - $i = (int) ($n + 1); - return $n >= $i ? $i : $i - 1; - } - - /** - * Solves a quadratic equation with the given coefficients and returns an array of up to two solutions. - * - * @param float $a - * @param float $b - * @param float $c - * - * @return float[] - */ - public static function solveQuadratic(float $a, float $b, float $c) : array{ - $discriminant = $b ** 2 - 4 * $a * $c; - if($discriminant > 0){ //2 real roots - $sqrtDiscriminant = sqrt($discriminant); - return [ - (-$b + $sqrtDiscriminant) / (2 * $a), - (-$b - $sqrtDiscriminant) / (2 * $a) - ]; - }elseif($discriminant == 0){ //1 real root - return [ - -$b / (2 * $a) - ]; - }else{ //No real roots - return []; - } - } -} diff --git a/src/pocketmine/math/Matrix.php b/src/pocketmine/math/Matrix.php deleted file mode 100644 index 8bbaee0b2..000000000 --- a/src/pocketmine/math/Matrix.php +++ /dev/null @@ -1,202 +0,0 @@ -matrix[(int) $offset]); - } - - public function offsetGet($offset){ - return $this->matrix[(int) $offset]; - } - - public function offsetSet($offset, $value){ - $this->matrix[(int) $offset] = $value; - } - - public function offsetUnset($offset){ - unset($this->matrix[(int) $offset]); - } - - public function __construct($rows, $columns, array $set = []){ - $this->rows = max(1, (int) $rows); - $this->columns = max(1, (int) $columns); - $this->set($set); - } - - public function set(array $m){ - for($r = 0; $r < $this->rows; ++$r){ - $this->matrix[$r] = []; - for($c = 0; $c < $this->columns; ++$c){ - $this->matrix[$r][$c] = $m[$r][$c] ?? 0; - } - } - } - - public function getRows(){ - return $this->rows; - } - - public function getColumns(){ - return $this->columns; - } - - public function setElement($row, $column, $value){ - if($row > $this->rows or $row < 0 or $column > $this->columns or $column < 0){ - return false; - } - $this->matrix[(int) $row][(int) $column] = $value; - - return true; - } - - public function getElement($row, $column){ - if($row > $this->rows or $row < 0 or $column > $this->columns or $column < 0){ - return false; - } - - return $this->matrix[(int) $row][(int) $column]; - } - - public function isSquare(){ - return $this->rows === $this->columns; - } - - public function add(Matrix $matrix){ - if($this->rows !== $matrix->getRows() or $this->columns !== $matrix->getColumns()){ - return false; - } - $result = new Matrix($this->rows, $this->columns); - for($r = 0; $r < $this->rows; ++$r){ - for($c = 0; $c < $this->columns; ++$c){ - $result->setElement($r, $c, $this->matrix[$r][$c] + $matrix->getElement($r, $c)); - } - } - - return $result; - } - - public function subtract(Matrix $matrix){ - if($this->rows !== $matrix->getRows() or $this->columns !== $matrix->getColumns()){ - return false; - } - $result = clone $this; - for($r = 0; $r < $this->rows; ++$r){ - for($c = 0; $c < $this->columns; ++$c){ - $result->setElement($r, $c, $this->matrix[$r][$c] - $matrix->getElement($r, $c)); - } - } - - return $result; - } - - public function multiplyScalar($number){ - $result = clone $this; - for($r = 0; $r < $this->rows; ++$r){ - for($c = 0; $c < $this->columns; ++$c){ - $result->setElement($r, $c, $this->matrix[$r][$c] * $number); - } - } - - return $result; - } - - - public function divideScalar($number){ - $result = clone $this; - for($r = 0; $r < $this->rows; ++$r){ - for($c = 0; $c < $this->columns; ++$c){ - $result->setElement($r, $c, $this->matrix[$r][$c] / $number); - } - } - - return $result; - } - - public function transpose(){ - $result = new Matrix($this->columns, $this->rows); - for($r = 0; $r < $this->rows; ++$r){ - for($c = 0; $c < $this->columns; ++$c){ - $result->setElement($c, $r, $this->matrix[$r][$c]); - } - } - - return $result; - } - - //Naive Matrix product, O(n^3) - public function product(Matrix $matrix){ - if($this->columns !== $matrix->getRows()){ - return false; - } - $c = $matrix->getColumns(); - $result = new Matrix($this->rows, $c); - for($i = 0; $i < $this->rows; ++$i){ - for($j = 0; $j < $c; ++$j){ - $sum = 0; - for($k = 0; $k < $this->columns; ++$k){ - $sum += $this->matrix[$i][$k] * $matrix->getElement($k, $j); - } - $result->setElement($i, $j, $sum); - } - } - - return $result; - } - - - //Computation of the determinant of 2x2 and 3x3 matrices - public function determinant(){ - if($this->isSquare() !== true){ - return false; - } - switch($this->rows){ - case 1: - return 0; - case 2: - return $this->matrix[0][0] * $this->matrix[1][1] - $this->matrix[0][1] * $this->matrix[1][0]; - case 3: - return $this->matrix[0][0] * $this->matrix[1][1] * $this->matrix[2][2] + $this->matrix[0][1] * $this->matrix[1][2] * $this->matrix[2][0] + $this->matrix[0][2] * $this->matrix[1][0] * $this->matrix[2][1] - $this->matrix[2][0] * $this->matrix[1][1] * $this->matrix[0][2] - $this->matrix[2][1] * $this->matrix[1][2] * $this->matrix[0][0] - $this->matrix[2][2] * $this->matrix[1][0] * $this->matrix[0][1]; - } - - return false; - } - - - public function __toString(){ - $s = ""; - for($r = 0; $r < $this->rows; ++$r){ - $s .= implode(",", $this->matrix[$r]) . ";"; - } - - return "Matrix({$this->rows}x{$this->columns};" . substr($s, 0, -1) . ")"; - } - -} diff --git a/src/pocketmine/math/RayTraceResult.php b/src/pocketmine/math/RayTraceResult.php deleted file mode 100644 index b1ca11401..000000000 --- a/src/pocketmine/math/RayTraceResult.php +++ /dev/null @@ -1,75 +0,0 @@ -bb = $bb; - $this->hitFace = $hitFace; - $this->hitVector = $hitVector; - } - - /** - * @return AxisAlignedBB - */ - public function getBoundingBox() : AxisAlignedBB{ - return $this->bb; - } - - /** - * @return int - */ - public function getHitFace() : int{ - return $this->hitFace; - } - - /** - * @return Vector3 - */ - public function getHitVector() : Vector3{ - return $this->hitVector; - } -} diff --git a/src/pocketmine/math/Vector2.php b/src/pocketmine/math/Vector2.php deleted file mode 100644 index 2c3cf0c05..000000000 --- a/src/pocketmine/math/Vector2.php +++ /dev/null @@ -1,132 +0,0 @@ -x = $x; - $this->y = $y; - } - - public function getX(){ - return $this->x; - } - - public function getY(){ - return $this->y; - } - - public function getFloorX(){ - return (int) floor($this->x); - } - - public function getFloorY(){ - return (int) floor($this->y); - } - - public function add($x, $y = 0){ - if($x instanceof Vector2){ - return $this->add($x->x, $x->y); - }else{ - return new Vector2($this->x + $x, $this->y + $y); - } - } - - public function subtract($x, $y = 0){ - if($x instanceof Vector2){ - return $this->add(-$x->x, -$x->y); - }else{ - return $this->add(-$x, -$y); - } - } - - public function ceil(){ - return new Vector2((int) ceil($this->x), (int) ceil($this->y)); - } - - public function floor(){ - return new Vector2((int) floor($this->x), (int) floor($this->y)); - } - - public function round(){ - return new Vector2(round($this->x), round($this->y)); - } - - public function abs(){ - return new Vector2(abs($this->x), abs($this->y)); - } - - public function multiply($number){ - return new Vector2($this->x * $number, $this->y * $number); - } - - public function divide($number){ - return new Vector2($this->x / $number, $this->y / $number); - } - - public function distance($x, $y = 0){ - if($x instanceof Vector2){ - return sqrt($this->distanceSquared($x->x, $x->y)); - }else{ - return sqrt($this->distanceSquared($x, $y)); - } - } - - public function distanceSquared($x, $y = 0){ - if($x instanceof Vector2){ - return $this->distanceSquared($x->x, $x->y); - }else{ - return (($this->x - $x) ** 2) + (($this->y - $y) ** 2); - } - } - - public function length(){ - return sqrt($this->lengthSquared()); - } - - public function lengthSquared(){ - return $this->x * $this->x + $this->y * $this->y; - } - - public function normalize(){ - $len = $this->lengthSquared(); - if($len != 0){ - return $this->divide(sqrt($len)); - } - - return new Vector2(0, 0); - } - - public function dot(Vector2 $v){ - return $this->x * $v->x + $this->y * $v->y; - } - - public function __toString(){ - return "Vector2(x=" . $this->x . ",y=" . $this->y . ")"; - } - -} diff --git a/src/pocketmine/math/Vector3.php b/src/pocketmine/math/Vector3.php deleted file mode 100644 index 0a6a6218f..000000000 --- a/src/pocketmine/math/Vector3.php +++ /dev/null @@ -1,342 +0,0 @@ -x = $x; - $this->y = $y; - $this->z = $z; - } - - public function getX(){ - return $this->x; - } - - public function getY(){ - return $this->y; - } - - public function getZ(){ - return $this->z; - } - - public function getFloorX(){ - return (int) floor($this->x); - } - - public function getFloorY(){ - return (int) floor($this->y); - } - - public function getFloorZ(){ - return (int) floor($this->z); - } - - public function getRight(){ - return $this->x; - } - - public function getUp(){ - return $this->y; - } - - public function getForward(){ - return $this->z; - } - - public function getSouth(){ - return $this->x; - } - - public function getWest(){ - return $this->z; - } - - /** - * @param Vector3|int $x - * @param int $y - * @param int $z - * - * @return Vector3 - */ - public function add($x, $y = 0, $z = 0){ - if($x instanceof Vector3){ - return new Vector3($this->x + $x->x, $this->y + $x->y, $this->z + $x->z); - }else{ - return new Vector3($this->x + $x, $this->y + $y, $this->z + $z); - } - } - - /** - * @param Vector3|int $x - * @param int $y - * @param int $z - * - * @return Vector3 - */ - public function subtract($x = 0, $y = 0, $z = 0){ - if($x instanceof Vector3){ - return $this->add(-$x->x, -$x->y, -$x->z); - }else{ - return $this->add(-$x, -$y, -$z); - } - } - - public function multiply($number){ - return new Vector3($this->x * $number, $this->y * $number, $this->z * $number); - } - - public function divide($number){ - return new Vector3($this->x / $number, $this->y / $number, $this->z / $number); - } - - public function ceil(){ - return new Vector3((int) ceil($this->x), (int) ceil($this->y), (int) ceil($this->z)); - } - - public function floor(){ - return new Vector3((int) floor($this->x), (int) floor($this->y), (int) floor($this->z)); - } - - public function round(int $precision = 0, int $mode = PHP_ROUND_HALF_UP){ - return $precision > 0 ? - new Vector3(round($this->x, $precision, $mode), round($this->y, $precision, $mode), round($this->z, $precision, $mode)) : - new Vector3((int) round($this->x, $precision, $mode), (int) round($this->y, $precision, $mode), (int) round($this->z, $precision, $mode)); - } - - public function abs(){ - return new Vector3(abs($this->x), abs($this->y), abs($this->z)); - } - - public function getSide($side, $step = 1){ - switch((int) $side){ - case Vector3::SIDE_DOWN: - return new Vector3($this->x, $this->y - $step, $this->z); - case Vector3::SIDE_UP: - return new Vector3($this->x, $this->y + $step, $this->z); - case Vector3::SIDE_NORTH: - return new Vector3($this->x, $this->y, $this->z - $step); - case Vector3::SIDE_SOUTH: - return new Vector3($this->x, $this->y, $this->z + $step); - case Vector3::SIDE_WEST: - return new Vector3($this->x - $step, $this->y, $this->z); - case Vector3::SIDE_EAST: - return new Vector3($this->x + $step, $this->y, $this->z); - default: - return $this; - } - } - - /** - * Return a Vector3 instance - * - * @return Vector3 - */ - public function asVector3() : Vector3{ - return new Vector3($this->x, $this->y, $this->z); - } - - /** - * Returns the Vector3 side number opposite the specified one - * - * @param int $side 0-5 one of the Vector3::SIDE_* constants - * @return int - * - * @throws \InvalidArgumentException if an invalid side is supplied - */ - public static function getOppositeSide(int $side) : int{ - if($side >= 0 and $side <= 5){ - return $side ^ 0x01; - } - - throw new \InvalidArgumentException("Invalid side $side given to getOppositeSide"); - } - - public function distance(Vector3 $pos){ - return sqrt($this->distanceSquared($pos)); - } - - public function distanceSquared(Vector3 $pos){ - return (($this->x - $pos->x) ** 2) + (($this->y - $pos->y) ** 2) + (($this->z - $pos->z) ** 2); - } - - public function maxPlainDistance($x = 0, $z = 0){ - if($x instanceof Vector3){ - return $this->maxPlainDistance($x->x, $x->z); - }elseif($x instanceof Vector2){ - return $this->maxPlainDistance($x->x, $x->y); - }else{ - return max(abs($this->x - $x), abs($this->z - $z)); - } - } - - public function length(){ - return sqrt($this->lengthSquared()); - } - - public function lengthSquared(){ - return $this->x * $this->x + $this->y * $this->y + $this->z * $this->z; - } - - /** - * @return Vector3 - */ - public function normalize(){ - $len = $this->lengthSquared(); - if($len > 0){ - return $this->divide(sqrt($len)); - } - - return new Vector3(0, 0, 0); - } - - public function dot(Vector3 $v){ - return $this->x * $v->x + $this->y * $v->y + $this->z * $v->z; - } - - public function cross(Vector3 $v){ - return new Vector3( - $this->y * $v->z - $this->z * $v->y, - $this->z * $v->x - $this->x * $v->z, - $this->x * $v->y - $this->y * $v->x - ); - } - - public function equals(Vector3 $v) : bool{ - return $this->x == $v->x and $this->y == $v->y and $this->z == $v->z; - } - - /** - * Returns a new vector with x value equal to the second parameter, along the line between this vector and the - * passed in vector, or null if not possible. - * - * @param Vector3 $v - * @param float $x - * - * @return Vector3|null - */ - public function getIntermediateWithXValue(Vector3 $v, $x){ - $xDiff = $v->x - $this->x; - $yDiff = $v->y - $this->y; - $zDiff = $v->z - $this->z; - - if(($xDiff * $xDiff) < 0.0000001){ - return null; - } - - $f = ($x - $this->x) / $xDiff; - - if($f < 0 or $f > 1){ - return null; - }else{ - return new Vector3($x, $this->y + $yDiff * $f, $this->z + $zDiff * $f); - } - } - - /** - * Returns a new vector with y value equal to the second parameter, along the line between this vector and the - * passed in vector, or null if not possible. - * - * @param Vector3 $v - * @param float $y - * - * @return Vector3|null - */ - public function getIntermediateWithYValue(Vector3 $v, $y){ - $xDiff = $v->x - $this->x; - $yDiff = $v->y - $this->y; - $zDiff = $v->z - $this->z; - - if(($yDiff * $yDiff) < 0.0000001){ - return null; - } - - $f = ($y - $this->y) / $yDiff; - - if($f < 0 or $f > 1){ - return null; - }else{ - return new Vector3($this->x + $xDiff * $f, $y, $this->z + $zDiff * $f); - } - } - - /** - * Returns a new vector with z value equal to the second parameter, along the line between this vector and the - * passed in vector, or null if not possible. - * - * @param Vector3 $v - * @param float $z - * - * @return Vector3|null - */ - public function getIntermediateWithZValue(Vector3 $v, $z){ - $xDiff = $v->x - $this->x; - $yDiff = $v->y - $this->y; - $zDiff = $v->z - $this->z; - - if(($zDiff * $zDiff) < 0.0000001){ - return null; - } - - $f = ($z - $this->z) / $zDiff; - - if($f < 0 or $f > 1){ - return null; - }else{ - return new Vector3($this->x + $xDiff * $f, $this->y + $yDiff * $f, $z); - } - } - - /** - * @param $x - * @param $y - * @param $z - * - * @return $this - */ - public function setComponents($x, $y, $z){ - $this->x = $x; - $this->y = $y; - $this->z = $z; - return $this; - } - - public function __toString(){ - return "Vector3(x=" . $this->x . ",y=" . $this->y . ",z=" . $this->z . ")"; - } - -} diff --git a/src/pocketmine/math/VectorMath.php b/src/pocketmine/math/VectorMath.php deleted file mode 100644 index 2d1abcd11..000000000 --- a/src/pocketmine/math/VectorMath.php +++ /dev/null @@ -1,33 +0,0 @@ -add($directionVector->multiply($maxDistance))); - } - - /** - * Performs a ray trace between the start and end coordinates. This returns a Generator which yields Vector3s - * containing the coordinates of voxels it passes through. - * - * This is an implementation of the algorithm described in the link below. - * @link http://www.cse.yorku.ca/~amana/research/grid.pdf - * - * @param Vector3 $start - * @param Vector3 $end - * - * @return \Generator|Vector3[] - */ - public static function betweenPoints(Vector3 $start, Vector3 $end) : \Generator{ - $currentBlock = $start->floor(); - - $directionVector = $end->subtract($start)->normalize(); - if($directionVector->lengthSquared() <= 0){ - throw new \InvalidArgumentException("Start and end points are the same, giving a zero direction vector"); - } - - $radius = $start->distance($end); - - $stepX = $directionVector->x <=> 0; - $stepY = $directionVector->y <=> 0; - $stepZ = $directionVector->z <=> 0; - - //Initialize the step accumulation variables depending how far into the current block the start position is. If - //the start position is on the corner of the block, these will be zero. - $tMaxX = self::rayTraceDistanceToBoundary($start->x, $directionVector->x); - $tMaxY = self::rayTraceDistanceToBoundary($start->y, $directionVector->y); - $tMaxZ = self::rayTraceDistanceToBoundary($start->z, $directionVector->z); - - //The change in t on each axis when taking a step on that axis (always positive). - $tDeltaX = $directionVector->x == 0 ? 0 : $stepX / $directionVector->x; - $tDeltaY = $directionVector->y == 0 ? 0 : $stepY / $directionVector->y; - $tDeltaZ = $directionVector->z == 0 ? 0 : $stepZ / $directionVector->z; - - while(true){ - yield $currentBlock; - - // tMaxX stores the t-value at which we cross a cube boundary along the - // X axis, and similarly for Y and Z. Therefore, choosing the least tMax - // chooses the closest cube boundary. - if($tMaxX < $tMaxY and $tMaxX < $tMaxZ){ - if($tMaxX > $radius){ - break; - } - $currentBlock->x += $stepX; - $tMaxX += $tDeltaX; - }elseif($tMaxY < $tMaxZ){ - if($tMaxY > $radius){ - break; - } - $currentBlock->y += $stepY; - $tMaxY += $tDeltaY; - }else{ - if($tMaxZ > $radius){ - break; - } - $currentBlock->z += $stepZ; - $tMaxZ += $tDeltaZ; - } - } - } - - /** - * Returns the distance that must be travelled on an axis from the start point with the direction vector component to - * cross a block boundary. - * - * For example, given an X coordinate inside a block and the X component of a direction vector, will return the distance - * travelled by that direction component to reach a block with a different X coordinate. - * - * Find the smallest positive t such that s+t*ds is an integer. - * - * @param float $s Starting coordinate - * @param float $ds Direction vector component of the relevant axis - * - * @return float Distance along the ray trace that must be travelled to cross a boundary. - */ - private static function rayTraceDistanceToBoundary(float $s, float $ds) : float{ - if($ds == 0){ - return INF; - } - - if($ds < 0){ - $s = -$s; - $ds = -$ds; - - if(floor($s) == $s){ //exactly at coordinate, will leave the coordinate immediately by moving negatively - return 0; - } - } - - // problem is now s+t*ds = 1 - return (1 - ($s - floor($s))) / $ds; - } -}