mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-07-19 09:26:45 +00:00
Moved \pocketmine\math to a separate library
This commit is contained in:
parent
313b224bec
commit
7f6b8ad7c2
@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
38
composer.lock
generated
38
composer.lock
generated
@ -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,
|
||||
|
@ -1,432 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\math;
|
||||
|
||||
class AxisAlignedBB{
|
||||
|
||||
/** @var float */
|
||||
public $minX;
|
||||
/** @var float */
|
||||
public $minY;
|
||||
/** @var float */
|
||||
public $minZ;
|
||||
/** @var float */
|
||||
public $maxX;
|
||||
/** @var float */
|
||||
public $maxY;
|
||||
/** @var float */
|
||||
public $maxZ;
|
||||
|
||||
public function __construct(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;
|
||||
}
|
||||
|
||||
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})";
|
||||
}
|
||||
}
|
@ -1,67 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* Math related classes, like matrices, bounding boxes and vector
|
||||
*/
|
||||
namespace pocketmine\math;
|
||||
|
||||
|
||||
abstract class Math{
|
||||
|
||||
public static function floorFloat($n) : int{
|
||||
$i = (int) $n;
|
||||
return $n >= $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 [];
|
||||
}
|
||||
}
|
||||
}
|
@ -1,202 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\math;
|
||||
|
||||
|
||||
class Matrix implements \ArrayAccess{
|
||||
private $matrix = [];
|
||||
private $rows = 0;
|
||||
private $columns = 0;
|
||||
|
||||
public function offsetExists($offset){
|
||||
return isset($this->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) . ")";
|
||||
}
|
||||
|
||||
}
|
@ -1,75 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\math;
|
||||
|
||||
/**
|
||||
* Class representing a ray trace collision with an AxisAlignedBB
|
||||
*/
|
||||
class RayTraceResult{
|
||||
|
||||
/**
|
||||
* @var AxisAlignedBB
|
||||
*/
|
||||
public $bb;
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
public $hitFace;
|
||||
/**
|
||||
* @var Vector3
|
||||
*/
|
||||
public $hitVector;
|
||||
|
||||
/**
|
||||
* @param AxisAlignedBB $bb
|
||||
* @param int $hitFace one of the Vector3::SIDE_* constants
|
||||
* @param Vector3 $hitVector
|
||||
*/
|
||||
public function __construct(AxisAlignedBB $bb, int $hitFace, Vector3 $hitVector){
|
||||
$this->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;
|
||||
}
|
||||
}
|
@ -1,132 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\math;
|
||||
|
||||
class Vector2{
|
||||
public $x;
|
||||
public $y;
|
||||
|
||||
public function __construct($x = 0, $y = 0){
|
||||
$this->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 . ")";
|
||||
}
|
||||
|
||||
}
|
@ -1,342 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\math;
|
||||
|
||||
class Vector3{
|
||||
|
||||
public const SIDE_DOWN = 0;
|
||||
public const SIDE_UP = 1;
|
||||
public const SIDE_NORTH = 2;
|
||||
public const SIDE_SOUTH = 3;
|
||||
public const SIDE_WEST = 4;
|
||||
public const SIDE_EAST = 5;
|
||||
|
||||
public $x;
|
||||
public $y;
|
||||
public $z;
|
||||
|
||||
public function __construct($x = 0, $y = 0, $z = 0){
|
||||
$this->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 . ")";
|
||||
}
|
||||
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\math;
|
||||
|
||||
|
||||
abstract class VectorMath{
|
||||
|
||||
public static function getDirection2D($azimuth){
|
||||
return new Vector2(cos($azimuth), sin($azimuth));
|
||||
}
|
||||
|
||||
}
|
@ -1,138 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\math;
|
||||
|
||||
abstract class VoxelRayTrace{
|
||||
|
||||
/**
|
||||
* Performs a ray trace from the start position in the given direction, for a distance of $maxDistance. This
|
||||
* returns a Generator which yields Vector3s containing the coordinates of voxels it passes through.
|
||||
*
|
||||
* @param Vector3 $start
|
||||
* @param Vector3 $directionVector
|
||||
* @param float $maxDistance
|
||||
*
|
||||
* @return \Generator|Vector3[]
|
||||
*/
|
||||
public static function inDirection(Vector3 $start, Vector3 $directionVector, float $maxDistance) : \Generator{
|
||||
return self::betweenPoints($start, $start->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;
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user