unmath.h
来自「虚幻的再开发程序包源代码」· C头文件 代码 · 共 1,604 行 · 第 1/3 页
H
1,604 行
ASMTransformVector( Coords, *this, Temp);
return Temp;
#endif
}
//
// Mirror a vector about a normal vector.
//
inline FVector FVector::MirrorByVector( const FVector& MirrorNormal ) const
{
return *this - MirrorNormal * (2.0 * (*this | MirrorNormal));
}
//
// Mirror a vector about a plane.
//
inline FVector FVector::MirrorByPlane( const FPlane& Plane ) const
{
return *this - Plane * (2.0 * Plane.PlaneDot(*this) );
}
/*-----------------------------------------------------------------------------
FVector friends.
-----------------------------------------------------------------------------*/
//
// Compare two points and see if they're the same, using a threshold.
// Returns 1=yes, 0=no. Uses fast distance approximation.
//
inline int FPointsAreSame( const FVector &P, const FVector &Q )
{
FLOAT Temp;
Temp=P.X-Q.X;
if( (Temp > -THRESH_POINTS_ARE_SAME) && (Temp < THRESH_POINTS_ARE_SAME) )
{
Temp=P.Y-Q.Y;
if( (Temp > -THRESH_POINTS_ARE_SAME) && (Temp < THRESH_POINTS_ARE_SAME) )
{
Temp=P.Z-Q.Z;
if( (Temp > -THRESH_POINTS_ARE_SAME) && (Temp < THRESH_POINTS_ARE_SAME) )
{
return 1;
}
}
}
return 0;
}
//
// Compare two points and see if they're the same, using a threshold.
// Returns 1=yes, 0=no. Uses fast distance approximation.
//
inline int FPointsAreNear( const FVector &Point1, const FVector &Point2, FLOAT Dist )
{
FLOAT Temp;
Temp=(Point1.X - Point2.X); if (Abs(Temp)>=Dist) return 0;
Temp=(Point1.Y - Point2.Y); if (Abs(Temp)>=Dist) return 0;
Temp=(Point1.Z - Point2.Z); if (Abs(Temp)>=Dist) return 0;
return 1;
}
//
// Calculate the signed distance (in the direction of the normal) between
// a point and a plane.
//
inline FLOAT FPointPlaneDist
(
const FVector &Point,
const FVector &PlaneBase,
const FVector &PlaneNormal
)
{
return (Point - PlaneBase) | PlaneNormal;
}
//
// Euclidean distance between two points.
//
inline FLOAT FDist( const FVector &V1, const FVector &V2 )
{
return appSqrt( Square(V2.X-V1.X) + Square(V2.Y-V1.Y) + Square(V2.Z-V1.Z) );
}
//
// Squared distance between two points.
//
inline FLOAT FDistSquared( const FVector &V1, const FVector &V2 )
{
return Square(V2.X-V1.X) + Square(V2.Y-V1.Y) + Square(V2.Z-V1.Z);
}
//
// See if two normal vectors (or plane normals) are nearly parallel.
//
inline int FParallel( const FVector &Normal1, const FVector &Normal2 )
{
FLOAT NormalDot = Normal1 | Normal2;
return (Abs (NormalDot - 1.0) <= THRESH_VECTORS_ARE_PARALLEL);
}
//
// See if two planes are coplanar.
//
inline int FCoplanar( const FVector &Base1, const FVector &Normal1, const FVector &Base2, const FVector &Normal2 )
{
if (!FParallel(Normal1,Normal2)) return 0;
else if (FPointPlaneDist (Base2,Base1,Normal1) > THRESH_POINT_ON_PLANE) return 0;
else return 1;
}
//
// Triple product of three vectors.
//
inline FLOAT FTriple( const FVector& X, const FVector& Y, const FVector& Z )
{
return
( (X.X * (Y.Y * Z.Z - Y.Z * Z.Y))
+ (X.Y * (Y.Z * Z.X - Y.X * Z.Z))
+ (X.Z * (Y.X * Z.Y - Y.Y * Z.X)) );
}
/*-----------------------------------------------------------------------------
FPlane implementation.
-----------------------------------------------------------------------------*/
//
// Transform a point by a coordinate system, moving
// it by the coordinate system's origin if nonzero.
//
inline FPlane FPlane::TransformPlaneByOrtho( const FCoords &Coords ) const
{
FVector Normal( *this | Coords.XAxis, *this | Coords.YAxis, *this | Coords.ZAxis );
return FPlane( Normal, W - (Coords.Origin.TransformVectorBy(Coords) | Normal) );
}
/*-----------------------------------------------------------------------------
FCoords functions.
-----------------------------------------------------------------------------*/
//
// Return this coordinate system's transpose.
// If the coordinate system is orthogonal, this is equivalent to its inverse.
//
inline FCoords FCoords::Transpose() const
{
return FCoords
(
-Origin.TransformVectorBy(*this),
FVector( XAxis.X, YAxis.X, ZAxis.X ),
FVector( XAxis.Y, YAxis.Y, ZAxis.Y ),
FVector( XAxis.Z, YAxis.Z, ZAxis.Z )
);
}
//
// Mirror the coordinates about a normal vector.
//
inline FCoords FCoords::MirrorByVector( const FVector& MirrorNormal ) const
{
return FCoords
(
Origin.MirrorByVector( MirrorNormal ),
XAxis .MirrorByVector( MirrorNormal ),
YAxis .MirrorByVector( MirrorNormal ),
ZAxis .MirrorByVector( MirrorNormal )
);
}
//
// Mirror the coordinates about a plane.
//
inline FCoords FCoords::MirrorByPlane( const FPlane& Plane ) const
{
return FCoords
(
Origin.MirrorByPlane ( Plane ),
XAxis .MirrorByVector( Plane ),
YAxis .MirrorByVector( Plane ),
ZAxis .MirrorByVector( Plane )
);
}
/*-----------------------------------------------------------------------------
FCoords operators.
-----------------------------------------------------------------------------*/
//
// Transform this coordinate system by another coordinate system.
//
inline FCoords& FCoords::operator*=( const FCoords& TransformCoords )
{
//!! Proper solution:
//Origin = Origin.TransformPointBy( TransformCoords.Inverse().Transpose() );
// Fast solution assuming orthogonal coordinate system:
Origin = Origin.TransformPointBy ( TransformCoords );
XAxis = XAxis .TransformVectorBy( TransformCoords );
YAxis = YAxis .TransformVectorBy( TransformCoords );
ZAxis = ZAxis .TransformVectorBy( TransformCoords );
return *this;
}
inline FCoords FCoords::operator*( const FCoords &TransformCoords ) const
{
return FCoords(*this) *= TransformCoords;
}
//
// Transform this coordinate system by a pitch-yaw-roll rotation.
//
inline FCoords& FCoords::operator*=( const FRotator &Rot )
{
// Apply yaw rotation.
*this *= FCoords
(
FVector( 0.0, 0.0, 0.0 ),
FVector( +GMath.CosTab(Rot.Yaw), +GMath.SinTab(Rot.Yaw), +0.0 ),
FVector( -GMath.SinTab(Rot.Yaw), +GMath.CosTab(Rot.Yaw), +0.0 ),
FVector( +0.0, +0.0, +1.0 )
);
// Apply pitch rotation.
*this *= FCoords
(
FVector( 0.0, 0.0, 0.0 ),
FVector( +GMath.CosTab(Rot.Pitch), +0.0, +GMath.SinTab(Rot.Pitch) ),
FVector( +0.0, +1.0, +0.0 ),
FVector( -GMath.SinTab(Rot.Pitch), +0.0, +GMath.CosTab(Rot.Pitch) )
);
// Apply roll rotation.
*this *= FCoords
(
FVector( 0.0, 0.0, 0.0 ),
FVector( +1.0, +0.0, +0.0 ),
FVector( +0.0, +GMath.CosTab(Rot.Roll), -GMath.SinTab(Rot.Roll) ),
FVector( +0.0, +GMath.SinTab(Rot.Roll), +GMath.CosTab(Rot.Roll) )
);
return *this;
}
inline FCoords FCoords::operator*( const FRotator &Rot ) const
{
return FCoords(*this) *= Rot;
}
inline FCoords& FCoords::operator*=( const FVector &Point )
{
Origin -= Point;
return *this;
}
inline FCoords FCoords::operator*( const FVector &Point ) const
{
return FCoords(*this) *= Point;
}
//
// Detransform this coordinate system by a pitch-yaw-roll rotation.
//
inline FCoords& FCoords::operator/=( const FRotator &Rot )
{
// Apply inverse roll rotation.
*this *= FCoords
(
FVector( 0.0, 0.0, 0.0 ),
FVector( +1.0, -0.0, +0.0 ),
FVector( -0.0, +GMath.CosTab(Rot.Roll), +GMath.SinTab(Rot.Roll) ),
FVector( +0.0, -GMath.SinTab(Rot.Roll), +GMath.CosTab(Rot.Roll) )
);
// Apply inverse pitch rotation.
*this *= FCoords
(
FVector( 0.0, 0.0, 0.0 ),
FVector( +GMath.CosTab(Rot.Pitch), +0.0, -GMath.SinTab(Rot.Pitch) ),
FVector( +0.0, +1.0, -0.0 ),
FVector( +GMath.SinTab(Rot.Pitch), +0.0, +GMath.CosTab(Rot.Pitch) )
);
// Apply inverse yaw rotation.
*this *= FCoords
(
FVector( 0.0, 0.0, 0.0 ),
FVector( +GMath.CosTab(Rot.Yaw), -GMath.SinTab(Rot.Yaw), -0.0 ),
FVector( +GMath.SinTab(Rot.Yaw), +GMath.CosTab(Rot.Yaw), +0.0 ),
FVector( -0.0, +0.0, +1.0 )
);
return *this;
}
inline FCoords FCoords::operator/( const FRotator &Rot ) const
{
return FCoords(*this) /= Rot;
}
inline FCoords& FCoords::operator/=( const FVector &Point )
{
Origin += Point;
return *this;
}
inline FCoords FCoords::operator/( const FVector &Point ) const
{
return FCoords(*this) /= Point;
}
//
// Transform this coordinate system by a scale.
// Note: Will return coordinate system of opposite handedness if
// Scale.X*Scale.Y*Scale.Z is negative.
//
inline FCoords& FCoords::operator*=( const FScale &Scale )
{
// Apply sheering.
FLOAT Sheer = FSheerSnap( Scale.SheerRate );
FCoords TempCoords = GMath.UnitCoords;
switch( Scale.SheerAxis )
{
case SHEER_XY:
TempCoords.XAxis.Y = Sheer;
break;
case SHEER_XZ:
TempCoords.XAxis.Z = Sheer;
break;
case SHEER_YX:
TempCoords.YAxis.X = Sheer;
break;
case SHEER_YZ:
TempCoords.YAxis.Z = Sheer;
break;
case SHEER_ZX:
TempCoords.ZAxis.X = Sheer;
break;
case SHEER_ZY:
TempCoords.ZAxis.Y = Sheer;
break;
default:
break;
}
*this *= TempCoords;
// Apply scaling.
XAxis *= Scale.Scale;
YAxis *= Scale.Scale;
ZAxis *= Scale.Scale;
Origin.X /= Scale.Scale.X;
Origin.Y /= Scale.Scale.Y;
Origin.Z /= Scale.Scale.Z;
return *this;
}
inline FCoords FCoords::operator*( const FScale &Scale ) const
{
return FCoords(*this) *= Scale;
}
//
// Detransform a coordinate system by a scale.
//
inline FCoords& FCoords::operator/=( const FScale &Scale )
{
// Deapply scaling.
XAxis /= Scale.Scale;
YAxis /= Scale.Scale;
ZAxis /= Scale.Scale;
Origin.X *= Scale.Scale.X;
Origin.Y *= Scale.Scale.Y;
Origin.Z *= Scale.Scale.Z;
// Deapply sheering.
FCoords TempCoords(GMath.UnitCoords);
FLOAT Sheer = FSheerSnap( Scale.SheerRate );
switch( Scale.SheerAxis )
{
case SHEER_XY:
TempCoords.XAxis.Y = -Sheer;
break;
case SHEER_XZ:
TempCoords.XAxis.Z = -Sheer;
break;
case SHEER_YX:
TempCoords.YAxis.X = -Sheer;
break;
case SHEER_YZ:
TempCoords.YAxis.Z = -Sheer;
break;
case SHEER_ZX:
TempCoords.ZAxis.X = -Sheer;
break;
case SHEER_ZY:
TempCoords.ZAxis.Y = -Sheer;
break;
default: // SHEER_NONE
break;
}
*this *= TempCoords;
return *this;
}
inline FCoords FCoords::operator/( const FScale &Scale ) const
{
return FCoords(*this) /= Scale;
}
/*-----------------------------------------------------------------------------
Random numbers.
-----------------------------------------------------------------------------*/
//
// Compute pushout of a box from a plane.
//
inline FLOAT FBoxPushOut( FVector Normal, FVector Size )
{
return Abs(Normal.X*Size.X) + Abs(Normal.Y*Size.Y) + Abs(Normal.Z*Size.Z);
}
//
// Return a uniformly distributed random unit vector.
//
inline FVector VRand()
{
FVector Result;
do
{
// Check random vectors in the unit sphere so result is statistically uniform.
Result.X = appFrand()*2 - 1;
Result.Y = appFrand()*2 - 1;
Result.Z = appFrand()*2 - 1;
} while( Result.SizeSquared() > 1.0 );
return Result.UnsafeNormal();
}
/*-----------------------------------------------------------------------------
Advanced geometry.
-----------------------------------------------------------------------------*/
//
// Find the intersection of an infinite line (defined by two points) and
// a plane. Assumes that the line and plane do indeed intersect; you must
// make sure they're not parallel before calling.
//
inline FVector FLinePlaneIntersection
(
const FVector &Point1,
const FVector &Point2,
const FVector &PlaneOrigin,
const FVector &PlaneNormal
)
{
return
Point1
+ (Point2-Point1)
* (((PlaneOrigin - Point1)|PlaneNormal) / ((Point2 - Point1)|PlaneNormal));
}
inline FVector FLinePlaneIntersection
(
const FVector &Point1,
const FVector &Point2,
const FPlane &Plane
)
{
return
Point1
+ (Point2-Point1)
* ((Plane.W - (Point1|Plane))/((Point2 - Point1)|Plane));
}
/*-----------------------------------------------------------------------------
FPlane functions.
-----------------------------------------------------------------------------*/
//
// Compute intersection point of three planes.
// Return 1 if valid, 0 if infinite.
//
inline UBOOL FIntersectPlanes3( FVector& I, const FPlane& P1, const FPlane& P2, const FPlane& P3 )
{
guard(FIntersectPlanes3);
// Compute determinant, the triple product P1|(P2^P3)==(P1^P2)|P3.
FLOAT Det = (P1 ^ P2) | P3;
if( Square(Det) < Square(0.001) )
{
// Degenerate.
I = FVector(0,0,0);
return 0;
}
else
{
// Compute the intersection point, guaranteed valid if determinant is nonzero.
I = (P1.W*(P2^P3) + P2.W*(P3^P1) + P3.W*(P1^P2)) / Det;
}
return 1;
unguard;
}
//
// Compute intersection point and direction of line joining two planes.
// Return 1 if valid, 0 if infinite.
//
inline FIntersectPlanes2( FVector& I, FVector& D, const FPlane& P1, const FPlane& P2 )
{
guard(FIntersectPlanes2);
// Compute line direction, perpendicular to both plane normals.
D = P1 ^ P2;
FLOAT DD = D.SizeSquared();
if( DD < Square(0.001) )
{
// Parallel or nearly parallel planes.
D = I = FVector(0,0,0);
return 0;
}
else
{
// Compute intersection.
I = (P1.W*(P2^D) + P2.W*(D^P1)) / DD;
D.Normalize();
return 1;
}
unguard;
}
/*-----------------------------------------------------------------------------
FRotator functions.
-----------------------------------------------------------------------------*/
//
// Convert a rotation into a vector facing in its direction.
//
inline FVector FRotator::Vector()
{
return (GMath.UnitCoords / *this).XAxis;
}
/*-----------------------------------------------------------------------------
The End.
-----------------------------------------------------------------------------*/
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?