unmath.h
来自「虚幻的再开发程序包源代码」· C头文件 代码 · 共 1,604 行 · 第 1/3 页
H
1,604 行
return Sgn(Scale.X * Scale.Y * Scale.Z);
}
};
/*-----------------------------------------------------------------------------
FCoords.
-----------------------------------------------------------------------------*/
//
// A coordinate system matrix.
//
class CORE_API FCoords
{
public:
FVector Origin;
FVector XAxis;
FVector YAxis;
FVector ZAxis;
// Constructors.
FCoords() {}
FCoords( const FVector &InOrigin )
: Origin(InOrigin), XAxis(1,0,0), YAxis(0,1,0), ZAxis(0,0,1) {}
FCoords( const FVector &InOrigin, const FVector &InX, const FVector &InY, const FVector &InZ )
: Origin(InOrigin), XAxis(InX), YAxis(InY), ZAxis(InZ) {}
// Functions.
FCoords MirrorByVector( const FVector& MirrorNormal ) const;
FCoords MirrorByPlane( const FPlane& MirrorPlane ) const;
FCoords Transpose() const;
FCoords Inverse() const;
FRotator OrthoRotation() const;
// Operators.
FCoords& operator*= (const FCoords &TransformCoords);
FCoords operator* (const FCoords &TransformCoords) const;
FCoords& operator*= (const FVector &Point);
FCoords operator* (const FVector &Point) const;
FCoords& operator*= (const FRotator &Rot);
FCoords operator* (const FRotator &Rot) const;
FCoords& operator*= (const FScale &Scale);
FCoords operator* (const FScale &Scale) const;
FCoords& operator/= (const FVector &Point);
FCoords operator/ (const FVector &Point) const;
FCoords& operator/= (const FRotator &Rot);
FCoords operator/ (const FRotator &Rot) const;
FCoords& operator/= (const FScale &Scale);
FCoords operator/ (const FScale &Scale) const;
};
/*-----------------------------------------------------------------------------
FModelCoords.
-----------------------------------------------------------------------------*/
//
// A model coordinate system, describing both the covariant and contravariant
// transformation matrices to transform points and normals by.
//
class CORE_API FModelCoords
{
public:
// Variables.
FCoords PointXform; // Coordinates to transform points by (covariant).
FCoords VectorXform; // Coordinates to transform normals by (contravariant).
// Constructors.
FModelCoords()
{}
FModelCoords( const FCoords& InCovariant, const FCoords& InContravariant )
: PointXform(InCovariant), VectorXform(InContravariant)
{}
// Functions.
FModelCoords Inverse()
{
return FModelCoords( VectorXform.Transpose(), PointXform.Transpose() );
}
};
/*-----------------------------------------------------------------------------
FRotator.
-----------------------------------------------------------------------------*/
//
// Rotation.
//
class CORE_API FRotator
{
public:
// Variables.
INT Pitch; // Looking up and down (0=Straight Ahead, +Up, -Down).
INT Yaw; // Rotating around (running in circles), 0=East, +North, -South.
INT Roll; // Rotation about axis of screen, 0=Straight, +Clockwise, -CCW.
// Serializer.
friend FArchive& operator<<( FArchive& Ar, FRotator& R )
{
return Ar << R.Pitch << R.Yaw << R.Roll;
}
// Constructors.
FRotator() {}
FRotator( INT InPitch, INT InYaw, INT InRoll )
: Pitch(InPitch), Yaw(InYaw), Roll(InRoll) {}
// Binary arithmetic operators.
FRotator operator+( const FRotator &R ) const
{
return FRotator( Pitch+R.Pitch, Yaw+R.Yaw, Roll+R.Roll );
}
FRotator operator-( const FRotator &R ) const
{
return FRotator( Pitch-R.Pitch, Yaw-R.Yaw, Roll-R.Roll );
}
FRotator operator*( FLOAT Scale ) const
{
return FRotator( Pitch*Scale, Yaw*Scale, Roll*Scale );
}
friend FRotator operator*( FLOAT Scale, const FRotator &R )
{
return FRotator( R.Pitch*Scale, R.Yaw*Scale, R.Roll*Scale );
}
FRotator operator*= (FLOAT Scale)
{
Pitch = (INT)(Pitch*Scale); Yaw = (INT)(Yaw*Scale); Roll = (INT)(Roll*Scale);
return *this;
}
// Binary comparison operators.
UBOOL operator==( const FRotator &R ) const
{
return Pitch==R.Pitch && Yaw==R.Yaw && Roll==R.Roll;
}
UBOOL operator!=( const FRotator &V ) const
{
return Pitch!=V.Pitch || Yaw!=V.Yaw || Roll!=V.Roll;
}
// Assignment operators.
FRotator operator+=( const FRotator &R )
{
Pitch += R.Pitch; Yaw += R.Yaw; Roll += R.Roll;
return *this;
}
FRotator operator-=( const FRotator &R )
{
Pitch -= R.Pitch; Yaw -= R.Yaw; Roll -= R.Roll;
return *this;
}
// Functions.
FRotator Reduce() const
{
return FRotator( ReduceAngle(Pitch), ReduceAngle(Yaw), ReduceAngle(Roll) );
}
int IsZero() const
{
return ((Pitch&65535)==0) && ((Yaw&65535)==0) && ((Roll&65535)==0);
}
FRotator Add( INT DeltaPitch, INT DeltaYaw, INT DeltaRoll )
{
Yaw += DeltaYaw;
Pitch += DeltaPitch;
Roll += DeltaRoll;
return *this;
}
FRotator AddBounded( INT DeltaPitch, INT DeltaYaw, INT DeltaRoll )
{
Yaw += DeltaYaw;
Pitch = FAddAngleConfined(Pitch,DeltaPitch,192*0x100,64*0x100);
Roll = FAddAngleConfined(Roll, DeltaRoll, 192*0x100,64*0x100);
return *this;
}
FRotator GridSnap( const FRotator &RotGrid )
{
return FRotator
(
FSnap(Pitch,RotGrid.Pitch),
FSnap(Yaw, RotGrid.Yaw),
FSnap(Roll, RotGrid.Roll)
);
}
FVector Vector();
};
/*-----------------------------------------------------------------------------
Bounds.
-----------------------------------------------------------------------------*/
//
// A rectangular minimum bounding volume.
//
class CORE_API FBox
{
public:
// Variables.
FVector Min;
FVector Max;
BYTE IsValid;
// Constructors.
FBox() {}
FBox(INT) : Min(0,0,0), Max(0,0,0), IsValid(0) {}
FBox( const FVector& InMin, const FVector& InMax ) : Min(InMin), Max(InMax), IsValid(1) {}
FBox( const FVector* Points, INT Count );
// Accessors.
FVector& GetExtrema( int i )
{
return (&Min)[i];
}
const FVector& GetExtrema( int i ) const
{
return (&Min)[i];
}
// Functions.
FBox& operator+=( const FVector &Other )
{
if( IsValid )
{
Min.X = ::Min( Min.X, Other.X );
Min.Y = ::Min( Min.Y, Other.Y );
Min.Z = ::Min( Min.Z, Other.Z );
Max.X = ::Max( Max.X, Other.X );
Max.Y = ::Max( Max.Y, Other.Y );
Max.Z = ::Max( Max.Z, Other.Z );
}
else
{
Min = Max = Other;
IsValid = 1;
}
return *this;
}
FBox operator+( const FVector& Other ) const
{
return FBox(*this) += Other;
}
FBox& operator+=( const FBox& Other )
{
if( IsValid && Other.IsValid )
{
Min.X = ::Min( Min.X, Other.Min.X );
Min.Y = ::Min( Min.Y, Other.Min.Y );
Min.Z = ::Min( Min.Z, Other.Min.Z );
Max.X = ::Max( Max.X, Other.Max.X );
Max.Y = ::Max( Max.Y, Other.Max.Y );
Max.Z = ::Max( Max.Z, Other.Max.Z );
}
else *this = Other;
return *this;
}
FBox operator+( const FBox& Other ) const
{
return FBox(*this) += Other;
}
FBox TransformBy( const FCoords& Coords ) const
{
FBox NewBox(0);
for( int i=0; i<2; i++ )
for( int j=0; j<2; j++ )
for( int k=0; k<2; k++ )
NewBox += FVector( GetExtrema(i).X, GetExtrema(j).Y, GetExtrema(k).Z ).TransformPointBy( Coords );
return NewBox;
}
FBox ExpandBy( FLOAT W ) const
{
return FBox( Min - FVector(W,W,W), Max + FVector(W,W,W) );
}
// Serializer.
friend FArchive& operator<<( FArchive& Ar, FBox& Bound )
{
return Ar << Bound.Min << Bound.Max << Bound.IsValid;
}
};
/*-----------------------------------------------------------------------------
FGlobalMath.
-----------------------------------------------------------------------------*/
//
// Global mathematics info.
//
class CORE_API FGlobalMath
{
public:
// Constants.
enum {ANGLE_SHIFT = 2}; // Bits to right-shift to get lookup value.
enum {ANGLE_BITS = 14}; // Number of valid bits in angles.
enum {NUM_ANGLES = 16384}; // Number of angles that are in lookup table.
enum {NUM_SQRTS = 16384}; // Number of square roots in lookup table.
enum {ANGLE_MASK = (((1<<ANGLE_BITS)-1)<<(16-ANGLE_BITS))};
// Class constants.
const FVector WorldMin;
const FVector WorldMax;
const FCoords UnitCoords;
const FScale UnitScale;
const FCoords ViewCoords;
// Basic math functions.
FLOAT Sqrt( int i )
{
return SqrtFLOAT[i];
}
FLOAT SinTab( int i )
{
return TrigFLOAT[((i>>ANGLE_SHIFT)&(NUM_ANGLES-1))];
}
FLOAT CosTab( int i )
{
return TrigFLOAT[(((i+16384)>>ANGLE_SHIFT)&(NUM_ANGLES-1))];
}
FLOAT SinFloat( FLOAT F )
{
return SinTab((F*65536)/(2.0*PI));
}
FLOAT CosFloat( FLOAT F )
{
return CosTab((F*65536)/(2.0*PI));
}
// Constructor.
FGlobalMath();
private:
// Tables.
FLOAT TrigFLOAT [NUM_ANGLES];
FLOAT SqrtFLOAT [NUM_SQRTS];
FLOAT LightSqrtFLOAT [NUM_SQRTS];
};
inline INT ReduceAngle( INT Angle )
{
return Angle & FGlobalMath::ANGLE_MASK;
};
/*-----------------------------------------------------------------------------
Floating point constants.
-----------------------------------------------------------------------------*/
//
// Lengths of normalized vectors (These are half their maximum values
// to assure that dot products with normalized vectors don't overflow).
//
#define FLOAT_NORMAL_THRESH (0.0001)
//
// Magic numbers for numerical precision.
//
#define THRESH_POINT_ON_PLANE (0.10) /* Thickness of plane for front/back/inside test */
#define THRESH_POINT_ON_SIDE (0.20) /* Thickness of polygon side's side-plane for point-inside/outside/on side test */
#define THRESH_POINTS_ARE_SAME (0.002) /* Two points are same if within this distance */
#define THRESH_POINTS_ARE_NEAR (0.015) /* Two points are near if within this distance and can be combined if imprecise math is ok */
#define THRESH_NORMALS_ARE_SAME (0.00002) /* Two normal points are same if within this distance */
/* Making this too large results in incorrect CSG classification and disaster */
#define THRESH_VECTORS_ARE_NEAR (0.0004) /* Two vectors are near if within this distance and can be combined if imprecise math is ok */
/* Making this too large results in lighting problems due to inaccurate texture coordinates */
#define THRESH_SPLIT_POLY_WITH_PLANE (0.25) /* A plane splits a polygon in half */
#define THRESH_SPLIT_POLY_PRECISELY (0.01) /* A plane exactly splits a polygon */
#define THRESH_ZERO_NORM_SQUARED (0.01*0.01) /* Size of a unit normal that is considered "zero", squared */
#define THRESH_VECTORS_ARE_PARALLEL (0.02) /* Vectors are parallel if dot product varies less than this */
/*-----------------------------------------------------------------------------
FVector transformation.
-----------------------------------------------------------------------------*/
//
// Transformations in optimized assembler format.
// An adaption of Michael Abrash' optimal transformation code.
//
#if ASM
inline void ASMTransformPoint(const FCoords &Coords, const FVector &InVector, FVector &OutVector)
{
// FCoords is a structure of 4 vectors: Origin, X, Y, Z
// x y z
// FVector Origin; 0 4 8
// FVector XAxis; 12 16 20
// FVector YAxis; 24 28 32
// FVector ZAxis; 36 40 44
//
// task: Temp = ( InVector - Coords.Origin );
// Outvector.X = (Temp | Coords.XAxis);
// Outvector.Y = (Temp | Coords.YAxis);
// Outvector.Z = (Temp | Coords.ZAxis);
//
// About 33 cycles on a Pentium.
//
__asm
{
mov esi,[InVector]
mov edx,[Coords]
mov edi,[OutVector]
// get source
fld dword ptr [esi+0]
fld dword ptr [esi+4]
fld dword ptr [esi+8] // z y x
fxch st(2) // xyz
// subtract origin
fsub dword ptr [edx + 0] // xyz
fxch st(1)
fsub dword ptr [edx + 4] // yxz
fxch st(2)
fsub dword ptr [edx + 8] // zxy
fxch st(1) // X Z Y
// triplicate X for transforming
fld st(0) // X X Z Y
fmul dword ptr [edx+12] // Xx X Z Y
fld st(1) // X Xx X Z Y
fmul dword ptr [edx+24] // Xy Xx X Z Y
fxch st(2)
fmul dword ptr [edx+36] // Xz Xx Xy Z Y
fxch st(4) // Y Xx Xy Z Xz
fld st(0) // Y Y Xx Xy Z Xz
fmul dword ptr [edx+16]
fld st(1) // Y Yx Y Xx Xy Z Xz
fmul dword ptr [edx+28]
fxch st(2) // Y Yx Yy Xx Xy Z Xz
fmul dword ptr [edx+40] // Yz Yx Yy Xx Xy Z Xz
fxch st(1) // Yx Yz Yy Xx Xy Z Xz
faddp st(3),st(0) // Yz Yy XxYx Xy Z Xz
faddp st(5),st(0) // Yy XxYx Xy Z XzYz
faddp st(2),st(0) // XxYx XyYy Z XzYz
fxch st(2) // Z XyYy XxYx XzYz
fld st(0) // Z Z XyYy XxYx XzYz
fmul dword ptr [edx+20]
fld st(1) // Z Zx Z XyYy XxYx XzYz
fmul dword ptr [edx+32]
fxch st(2) // Z Zx Zy
fmul dword ptr [edx+44] // Zz Zx Zy XyYy XxYx XzYz
fxch st(1) // Zx Zz Zy XyYy XxYx XzYz
faddp st(4),st(0) // Zz Zy XyYy XxYxZx XzYz
faddp st(4),st(0) // Zy XyYy XxYxZx XzYzZz
faddp st(1),st(0) // XyYyZy XxYxZx XzYzZz
fxch st(1) // Xx+Xx+Zx Xy+Yy+Zy Xz+Yz+Zz
fstp dword ptr [edi+0]
fstp dword ptr [edi+4]
fstp dword ptr [edi+8]
}
}
#endif
#if ASM
inline void ASMTransformVector(const FCoords &Coords, const FVector &InVector, FVector &OutVector)
{
__asm
{
mov esi,[InVector]
mov edx,[Coords]
mov edi,[OutVector]
// get source
fld dword ptr [esi+0]
fld dword ptr [esi+4]
fxch st(1)
fld dword ptr [esi+8] // z x y
fxch st(1) // x z y
// triplicate X for transforming
fld st(0) // X X Z Y
fmul dword ptr [edx+12] // Xx X Z Y
fld st(1) // X Xx X Z Y
fmul dword ptr [edx+24] // Xy Xx X Z Y
fxch st(2)
fmul dword ptr [edx+36] // Xz Xx Xy Z Y
fxch st(4) // Y Xx Xy Z Xz
fld st(0) // Y Y Xx Xy Z Xz
fmul dword ptr [edx+16]
fld st(1) // Y Yx Y Xx Xy Z Xz
fmul dword ptr [edx+28]
fxch st(2) // Y Yx Yy Xx Xy Z Xz
fmul dword ptr [edx+40] // Yz Yx Yy Xx Xy Z Xz
fxch st(1) // Yx Yz Yy Xx Xy Z Xz
faddp st(3),st(0) // Yz Yy XxYx Xy Z Xz
faddp st(5),st(0) // Yy XxYx Xy Z XzYz
faddp st(2),st(0) // XxYx XyYy Z XzYz
fxch st(2) // Z XyYy XxYx XzYz
fld st(0) // Z Z XyYy XxYx XzYz
fmul dword ptr [edx+20]
fld st(1) // Z Zx Z XyYy XxYx XzYz
fmul dword ptr [edx+32]
fxch st(2) // Z Zx Zy
fmul dword ptr [edx+44] // Zz Zx Zy XyYy XxYx XzYz
fxch st(1) // Zx Zz Zy XyYy XxYx XzYz
faddp st(4),st(0) // Zz Zy XyYy XxYxZx XzYz
faddp st(4),st(0) // Zy XyYy XxYxZx XzYzZz
faddp st(1),st(0) // XyYyZy XxYxZx XzYzZz
fxch st(1) // Xx+Xx+Zx Xy+Yy+Zy Xz+Yz+Zz
fstp dword ptr [edi+0]
fstp dword ptr [edi+4]
fstp dword ptr [edi+8]
}
}
#endif
//
// Transform a point by a coordinate system, moving
// it by the coordinate system's origin if nonzero.
//
inline FVector FVector::TransformPointBy( const FCoords &Coords ) const
{
#if !ASM
FVector Temp = *this - Coords.Origin;
return FVector( Temp | Coords.XAxis, Temp | Coords.YAxis, Temp | Coords.ZAxis );
#else
FVector Temp;
ASMTransformPoint( Coords, *this, Temp);
return Temp;
#endif
}
//
// Transform a directional vector by a coordinate system.
// Ignore's the coordinate system's origin.
//
inline FVector FVector::TransformVectorBy( const FCoords &Coords ) const
{
#if !ASM
return FVector( *this | Coords.XAxis, *this | Coords.YAxis, *this | Coords.ZAxis );
#else
FVector Temp;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?