/**
* Copyright (c) Lambda Innovation, 2013-2015
* 本作品版权由Lambda Innovation所有。
* http://www.li-dev.cn/
*
* This project is open-source, and it is distributed under
* the terms of GNU General Public License. You can modify
* and distribute freely as long as you follow the license.
* 本项目是一个开源项目,且遵循GNU通用公共授权协议。
* 在遵照该协议的情况下,您可以自由传播和修改。
* http://www.gnu.org/licenses/gpl.html
*/
package cn.liutils.util.generic;
import java.util.Random;
import net.minecraft.entity.Entity;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.util.MathHelper;
import net.minecraft.util.Vec3;
/**
* Some commonly used vector calculation & generations.
* @author WeAthFolD
*/
public class VecUtils {
private static Random rand = new Random();
public static Vec3 vec(double x, double y, double z) {
return Vec3.createVectorHelper(x, y, z);
}
public static Vec3 random() {
return vec(-1 + 2 * rand.nextDouble(), -1 + 2 * rand.nextDouble(), -1 + 2 * rand.nextDouble());
}
/**
* Convert the yaw and pitch angle to the looking direction vector
* @param yaw in mc entity angle space
* @param pitch in mc entity angle space
* @return the looking direction vec, normalized
*/
public static Vec3 toDirVector(float yaw, float pitch) {
float var3 = 1.0f;
float vx, vy, vz;
vx = MathHelper.sin(yaw / 180.0F
* (float) Math.PI)
* MathHelper.cos(yaw / 180.0F
* (float) Math.PI) * var3;
vz = MathHelper.cos(yaw / 180.0F
* (float) Math.PI)
* MathHelper.cos(pitch / 180.0F
* (float) Math.PI) * var3;
vy = -MathHelper.sin((pitch)
/ 180.0F * (float) Math.PI)
* var3;
return vec(vx, vy, vz);
}
/**
* <b>Currently BUGGY.</b><br>
* Get the closest point on line AB to point P. Calc is based on fact that vecPH*vecAB=0, along with linear interploation.
* @param p Targe point
* @param a One point in line segment
* @param b Another point in line segment, must not equal to a
* @return The closest point on AB.
*
*/
public static Vec3 getClosestPointOn(Vec3 p, Vec3 a, Vec3 b) {
double x0 = a.xCoord, y0 = a.yCoord, z0 = a.zCoord,
x1 = b.xCoord, y1 = b.yCoord, z1 = b.zCoord;
double X = p.xCoord, Y = p.yCoord, Z = p.zCoord;
double dx = x1 - x0, dy = y1 - y0, dz = z1 - z0;
double mid1 = dx * dx + dy * dy + dz * dz;
double mid2 = dx * (x1 - X) + dy * (y1 - Y) + dz * (z1 - Z);
double lambda = mid2 / mid1;
return lerp(a, b, lambda);
}
public static Vec3 multiply(Vec3 v, double scale) {
return Vec3.createVectorHelper(v.xCoord * scale, v.yCoord * scale, v.zCoord * scale);
}
public static Vec3 lerp(Vec3 a, Vec3 b, double lambda) {
double ml = 1 - lambda;
return Vec3.createVectorHelper(
a.xCoord * ml + b.xCoord * lambda,
a.yCoord * ml + b.yCoord * lambda,
a.zCoord * ml + b.zCoord * lambda);
}
public static Vec3 neg(Vec3 v) {
return Vec3.createVectorHelper(-v.xCoord, -v.yCoord, -v.zCoord);
}
public static Vec3 add(Vec3 a, Vec3 b) {
return Vec3.createVectorHelper(a.xCoord + b.xCoord, a.yCoord + b.yCoord, a.zCoord + b.zCoord);
}
public static Vec3 subtract(Vec3 a, Vec3 b) {
return add(a, neg(b));
}
public static double magnitudeSq(Vec3 a) {
return a.xCoord * a.xCoord + a.yCoord * a.yCoord + a.zCoord * a.zCoord;
}
public static double magnitude(Vec3 a) {
return Math.sqrt(magnitudeSq(a));
}
public static Vec3 copy(Vec3 v) {
return Vec3.createVectorHelper(v.xCoord, v.yCoord, v.zCoord);
}
public static void copy(Vec3 from, Vec3 to) {
to.xCoord = from.xCoord;
to.yCoord = from.yCoord;
to.zCoord = from.zCoord;
}
public static Vec3 crossProduct(Vec3 a, Vec3 b) {
double
x0 = a.xCoord, y0 = a.yCoord, z0 = a.zCoord,
x1 = b.xCoord, y1 = b.yCoord, z1 = b.zCoord;
return Vec3.createVectorHelper(
y0 * z1 - y1 * z0,
x1 * z0 - x0 * z1,
x0 * y1 - x1 * y0);
}
// CREDITS TO Greg S for the original code.
private static Vec3 getIntersection(double fDst1, double fDst2, Vec3 P1, Vec3 P2) {
if ( (fDst1 * fDst2) >= 0.0f) return null;
if ( fDst1 == fDst2) return null;
return add(P1, multiply(subtract(P2, P1), ( -fDst1 / (fDst2-fDst1) )));
}
private static boolean inBox(Vec3 Hit, Vec3 B1, Vec3 B2, int Axis) {
if ( Axis==1 && Hit.zCoord > B1.zCoord && Hit.zCoord < B2.zCoord && Hit.yCoord > B1.yCoord && Hit.yCoord < B2.yCoord) return true;
if ( Axis==2 && Hit.zCoord > B1.zCoord && Hit.zCoord < B2.zCoord && Hit.xCoord > B1.xCoord && Hit.xCoord < B2.xCoord) return true;
if ( Axis==3 && Hit.xCoord > B1.xCoord && Hit.xCoord < B2.xCoord && Hit.yCoord > B1.yCoord && Hit.yCoord < B2.yCoord) return true;
return false;
}
public static Vec3 checkLineAABB(Vec3 L1, Vec3 L2, AxisAlignedBB aabb) {
return checkLineBox(vec(aabb.minX, aabb.minY, aabb.minZ),
vec(aabb.maxX, aabb.maxY, aabb.maxZ),
L1, L2);
}
/**
* Check if the line segment (L1, L2) intersects with AABB represented by (B1, B2).
* If intersected, return the a hit point of the segment to the line.
* Else, return null.
* @param B1 smallest point for AABB
* @param B2 largest point for AABB
* @param L1 start point of the line
* @param L2 end point of the line
*/
public static Vec3 checkLineBox(Vec3 B1, Vec3 B2, Vec3 L1, Vec3 L2) {
if (L2.xCoord < B1.xCoord && L1.xCoord < B1.xCoord) return null;
if (L2.xCoord > B2.xCoord && L1.xCoord > B2.xCoord) return null;
if (L2.yCoord < B1.yCoord && L1.yCoord < B1.yCoord) return null;
if (L2.yCoord > B2.yCoord && L1.yCoord > B2.yCoord) return null;
if (L2.zCoord < B1.zCoord && L1.zCoord < B1.zCoord) return null;
if (L2.zCoord > B2.zCoord && L1.zCoord > B2.zCoord) return null;
if (L1.xCoord > B1.xCoord && L1.xCoord < B2.xCoord &&
L1.yCoord > B1.yCoord && L1.yCoord < B2.yCoord &&
L1.zCoord > B1.zCoord && L1.zCoord < B2.zCoord)
return L1;
Vec3 Hit;
if ( ((Hit = getIntersection(L1.xCoord-B1.xCoord, L2.xCoord-B1.xCoord, L1, L2)) != null && inBox( Hit, B1, B2, 1 ))
|| ((Hit = getIntersection( L1.yCoord-B1.yCoord, L2.yCoord-B1.yCoord, L1, L2)) != null && inBox( Hit, B1, B2, 2 ))
|| ((Hit = getIntersection( L1.zCoord-B1.zCoord, L2.zCoord-B1.zCoord, L1, L2)) != null && inBox( Hit, B1, B2, 3 ))
|| ((Hit = getIntersection( L1.xCoord-B2.xCoord, L2.xCoord-B2.xCoord, L1, L2)) != null && inBox( Hit, B1, B2, 1 ))
|| ((Hit = getIntersection( L1.yCoord-B2.yCoord, L2.yCoord-B2.yCoord, L1, L2)) != null && inBox( Hit, B1, B2, 2 ))
|| ((Hit = getIntersection( L1.zCoord-B2.zCoord, L2.zCoord-B2.zCoord, L1, L2)) != null && inBox( Hit, B1, B2, 3 )))
return Hit;
return null;
}
public static Vec3 entityPos(Entity e) {
return vec(e.posX, e.posY, e.posZ);
}
public static Vec3 entityMotion(Entity e) {
return vec(e.motionX, e.motionY, e.motionZ);
}
}