Unreal Math: FVector(1)

struct FVector 
{
public:

	/** Vector's X component. */
	float X;

	/** Vector's Y component. */
	float Y;

	/** Vector's Z component. */
	float Z;
}

最基本也是最重要的向量类了,包含了大量的变换和操作,涉及到很多的数学内容。

一些基本的常量向量:

	/** A zero vector (0,0,0) */
	static CORE_API const FVector ZeroVector;

	/** One vector (1,1,1) */
	static CORE_API const FVector OneVector;

	/** Unreal up vector (0,0,1) */
	static CORE_API const FVector UpVector;

	/** Unreal down vector (0,0,-1) */
	static CORE_API const FVector DownVector;

	/** Unreal forward vector (1,0,0) */
	static CORE_API const FVector ForwardVector;

	/** Unreal backward vector (-1,0,0) */
	static CORE_API const FVector BackwardVector;

	/** Unreal right vector (0,1,0) */
	static CORE_API const FVector RightVector;

	/** Unreal left vector (0,-1,0) */
	static CORE_API const FVector LeftVector;

基本操作

/**
 * Calculate the cross product of two vectors.
 *
 * @param A The first vector.
 * @param B The second vector.
 * @return The cross product.
 */
FORCEINLINE FVector FVector::operator^(const FVector& V) const
{
	return FVector
		(
		Y * V.Z - Z * V.Y,
		Z * V.X - X * V.Z,
		X * V.Y - Y * V.X
		);
}

向量叉乘,[latex]\begin{bmatrix} x1\\y1\\ z1 \end{bmatrix}\times \begin{bmatrix} x2 \\ y2 \\ z2 \end{bmatrix}= \begin{bmatrix} y1z2-z1y2 \\ z1x2-x1z2 \\ x1y2-y1x2 \end{bmatrix}[/latex]

基本的向量操作都有了,比如数乘,点乘,叉乘之类的。需要注意的是,向量点乘重写的运算符是|,叉乘重写的运算符是^,运算符*/是分量的/。不过为了避免失误,还是用DotProduct,CrossProduct最好。

FVector v1(2, 4, 6), v2(-1, -2, -3);
float dotProduct = v1 | v2;//-28
FVector crossProduct = v1 ^ v2;// (0,0,0)
FVector componentDivide = v1 / v2;//(-2,-2,-2)
FVector componentProduct = v1 * v2;//(-2,-8,-18)

归一化

向量的归一化函数有两个,一个是Safe的,一个是UnSafe的,这种形式在其他的向量类里面也有。区别在于,UnSafe的是直接计算的,而Safe的会先计算向量的模(平方),然后把零向量和单位向量先处理了。

	/**
	 * Calculates normalized version of vector without checking for zero length.
	 *
	 * @return Normalized version of vector.
	 * @see GetSafeNormal()
	 */
	FORCEINLINE FVector GetUnsafeNormal() const;

	/**
	 * Gets a normalized copy of the vector, checking it is safe to do so based on the length.
	 * Returns zero vector if vector length is too small to safely normalize.
	 *
	 * @param Tolerance Minimum squared vector length.
	 * @return A normalized copy if safe, (0,0,0) otherwise.
	 */
	FVector GetSafeNormal(float Tolerance=SMALL_NUMBER) const;

另外,还有GetSafeNormal2D的函数,仅仅针对x,y分量操作。

void ToDirectionAndLength(FVector &OutDir, float &OutLength) const;

获取当前向量的长度及单位方向向量。

平面投影

将向量投影到z=1的平面,各分量除以z。

	/**
	 * Projects 2D components of vector based on Z.
	 *
	 * @return Projected version of vector based on Z.
	 */
	FVector Projection() const;

FVector GridSnap(const float& GridSz) const;

按Gridsz将空间划分网格,获取离网格最近的那个点。实现方式是逐个计算每一个分量最近的点。这个函数主要用于计算对齐到网格。

/** Snaps a value to the nearest grid multiple */
static FORCEINLINE float GridSnap( float Location, float Grid )
{
	if( Grid==0.f )	return Location;
	else			
	{
		return FloorToFloat((Location + 0.5*Grid)/Grid)*Grid;
	}
}

关键函数是FloorToFloat((Location + 0.5Grid)/Grid)*Grid;

考虑在数轴上的整数x,如果Location在x的(0.5,0.5)范围内,那么floor(x+0.5)操作会返回x,从而可以计算离Location最近的整数点。上述操作类似。

FVector BoundToBox(const FVector& Min, const FVector Max) const;

Unreal Math: FVector(1)

获取Vector限制在Box中的向量,如果Vector的某些分量越界,则限制为边界值,用过Clamp系列函数的人应该不会陌生。类似的函数还有一些。

/**
 * Get a copy of this vector, clamped inside of a cube.
 *
 * @param Radius Half size of the cube.
 * @return A copy of this vector, bound by cube.
 */
FVector BoundToCube(float Radius) const;

/** Get a copy of this vector, clamped inside of a cube. */
FVector BoundToBox(const FVector& Min, const FVector Max) const;

/** Create a copy of this vector, with its magnitude clamped between Min and Max. */
FVector GetClampedToSize(float Min, float Max) const;

/** Create a copy of this vector, with the 2D magnitude clamped between Min and Max. Z is unchanged. */
FVector GetClampedToSize2D(float Min, float Max) const;

/** Create a copy of this vector, with its maximum magnitude clamped to MaxSize. */
FVector GetClampedToMaxSize(float MaxSize) const;

/** Create a copy of this vector, with the maximum 2D magnitude clamped to MaxSize. Z is unchanged. */
FVector GetClampedToMaxSize2D(float MaxSize) const;

/**
 * Add a vector to this and clamp the result in a cube.
 *
 * @param V Vector to add.
 * @param Radius Half size of the cube.
 */
void AddBounded(const FVector& V, float Radius=MAX_int16);

FVector Reciprocal() const;

各分量求倒数

镜像和反射

FVector MirrorByVector(const FVector& MirrorNormal) const;

这个函数的名字起的很奇怪,一开始我以为是计算被单位向量映射后的向量,然后推算出来的结果和代码的结果方向相反,查阅代码后发现这个函数主要是用来计算碰撞后的速度,其实就是入射角=反射角,mirrorNormal为碰撞点的法向量。如果BO是入射速度,那么OC为反射后的速度。

推算过程:OB在单位向量mirror上的投影OD=mirror*|OB|*cosα = mirror*|OB|*OB●mirror/|OB|/|mirror|=mirror*(OB ● mirror),然后BD=OD-OB,BC=2BD,OC=OB+BC, 化简后为OC = -OB + 2mirror(OB ● mirror)

FORCEINLINE FVector FVector::MirrorByVector(const FVector& MirrorNormal) const
{
	return *this - MirrorNormal * (2.f * (*this | MirrorNormal));
}
Unreal Math: FVector(1)

FVector MirrorByPlane(const FPlane& Plane) const;

和上一个类似,只不过在单位向量(平面单位法向量)上的投影为点到平面的距离,这个距离为PlaneDot。

inline FVector FVector::MirrorByPlane( const FPlane& Plane ) const
{
	return *this - Plane * (2.f * Plane.PlaneDot(*this) );
}

旋转

/**
 * Rotates around Axis (assumes Axis.Size() == 1).
 *
 * @param Angle Angle to rotate (in degrees).
 * @param Axis Axis to rotate around.
 * @return Rotated Vector.
 */
FVector RotateAngleAxis(const float AngleDeg, const FVector& Axis) const;

将向量围绕向量Axis旋转一个角度后的向量,详细推算过程可见3D数学8.2.3(P91),UE的实现基本一致。

投影

/**
 * Gets a copy of this vector projected onto the input vector.
 *
 * @param A	Vector to project onto, does not assume it is normalized.
 * @return Projected vector.
 */
FORCEINLINE FVector FVector::ProjectOnTo(const FVector& A) const 
{ 
	return (A * ((*this | A) / (A | A))); 
}

/**
 * Gets a copy of this vector projected onto the input vector, which is assumed to be unit length.
 * 
 * @param  Normal Vector to project onto (assumed to be unit length).
 * @return Projected vector.
 */
FORCEINLINE FVector ProjectOnToNormal(const FVector& Normal) const;

计算一个向量在另外一个向量上面的投影。比如要将b投影到a,投影向量 c = a / |a| * |b| * cos α = a / |a| * |b| * (ab/|a||b|) = a * (ab) / (|a| * |a|)。如果是单位向量,则结果是 a * (ab)

Unreal Math: FVector(1)

上一篇:Unreal日志窗口乱码????


下一篇:Unreal Math: 坐标系