| Home Page | Recent Changes | Preferences

Official UnMath Page

Introduction

The UnMath.h Header File (from, [Unreal Tournament 432 C++ Publicly Released Headers]) might more properly belong in the Unreal Engine Core section, since it is integral to every critical process that the Engine performs.

The Official UnMath Page is derived from that Header File Released from Epic Games and coded in C++. The following is just a section from the file, that describes FVectors. It appears in the original Tim Sweeney code; an uncompiled text file.

The complete UnMath.h file contains all the mathematical routines used by the Unreal Engine for collision detection, the Artificial Intelligence of Bots, and the physics (yes, even the Quaternion Rotations), and, ultimately, the rendering of the scene. It's WAY l33t?,...but, unfortunately, WAY humungeous.

We should have an analysis page to acompany it.

It will take you at least 5 years to read it all,...and by that time the Engine hierarchy will have evolved into something incomprehensible and extremely highly advanced.

Preface: The acronym API stands for Application Programming Interface. Just to give you an idea of the insane complexity of the UnMath routines, I have included a snippet of code for an important function FuzzVectors:

/*-----------------------------------------------------------------------------
    FVector.
 -----------------------------------------------------------------------------*/
 // Information associated with a floating point vector, describing its
 // status as a point in a rendering context.
 enum EVectorFlags
 {
    FVF_OutXMin     = 0x04, // Outcode rejection, off left hand side of screen.
    FVF_OutXMax     = 0x08, // Outcode rejection, off right hand side of screen.
    FVF_OutYMin     = 0x10, // Outcode rejection, off top of screen.
    FVF_OutYMax     = 0x20, // Outcode rejection, off bottom of screen.
    FVF_OutNear     = 0x40, // Near clipping plane.
    FVF_OutFar      = 0x80, // Far clipping plane.
    FVF_OutReject   = (FVF_OutXMin | FVF_OutXMax | FVF_OutYMin | FVF_OutYMax), //  Outcode rejectable.
    FVF_OutSkip     = (FVF_OutXMin | FVF_OutXMax | FVF_OutYMin | FVF_OutYMax), // Outcode clippable.
 };

 //
 // Floating point vector.
 // Playstation2 vectors are 16 bytes.
 //
 #if __PSX2_EE__
 #define FVECTOR_ALIGNMENT 16
 class CORE_API FVector 
 {
 public:
    // Variables.
    FLOAT X, Y, Z, W;

    // Constructors.
    FVector()
    {}

    FVector( FLOAT InX, FLOAT InY, FLOAT InZ )
    :   X(InX), Y(InY), Z(InZ), W(1.f)
    {}

    // Binary math operators.
    inline FVector operator^( const FVector& V ) const
    {
        FVector r;
        asm volatile ("
            lqc2        vf2, 0x00(%1)
            lqc2        vf3, 0x00(%2)
            vopmula.xyz ACCxyz, vf2xyz, vf3xyz
            vopmsub.xyz vf1xyz, vf3xyz, vf2xyz
            sqc2        vf1, 0x00(%0)
        "
        :
        : "r" (&r), "r" (this), "r" (&V)
        : "memory"
        );
        return r;
    }
    inline FLOAT operator|( const FVector& V ) const
    {
        FVector r;
        asm volatile ("
            lqc2        vf2, 0x00(%1)
            lqc2        vf3, 0x00(%2)
            vmul.xyz    vf1, vf2, vf3
            sqc2        vf1, 0x00(%0)
        "
        :
        : "r" (&r), "r" (this), "r" (&V)
        : "memory"
        );
        return r.X + r.Y + r.Z;
    }
    friend FVector operator*( FLOAT Scale, const FVector& V )
    {
        return FVector( V.X * Scale, V.Y * Scale, V.Z * Scale );
    }
    inline FVector operator+( const FVector& V ) const
    {
        FVector r;
        asm volatile ("
            lqc2        vf2, 0x00(%1)
            lqc2        vf3, 0x00(%2)
            vadd.xyz    vf1, vf2, vf3
            sqc2        vf1, 0x00(%0)
        "
        :
        : "r" (&r), "r" (this), "r" (&V)
        : "memory"
        );
        return r;
    }
    inline FVector operator-( const FVector& V ) const
    {
        FVector r;
        asm volatile ("
            lqc2        vf2, 0x00(%1)
            lqc2        vf3, 0x00(%2)
            vsub.xyz    vf1, vf2, vf3
            sqc2        vf1, 0x00(%0)
        "
        :
        : "r" (&r), "r" (this), "r" (&V)
        : "memory"
        );
        return r;
    }
    inline FVector operator*( FLOAT Scale ) const
    {
        FVector r;
        asm volatile ("
            ctc2        %2,  $21
            lqc2        vf2, 0x00(%1)
            vmuli.xyz   vf1, vf2, I
            sqc2        vf1, 0x00(%0)
        "
        :
        : "r" (&r), "r" (this), "r" (Scale)
        : "memory"
        );
        return r;
    }
    inline FVector operator/( FLOAT Scale ) const
    {
        FLOAT RScale = 1.f/Scale;
        FVector r;
        asm volatile ("
            ctc2        %2,  $21
            lqc2        vf2, 0x00(%1)
            vmuli.xyz   vf1, vf2, I
            sqc2        vf1, 0x00(%0)
        "
        :
        : "r" (&r), "r" (this), "r" (RScale)
        : "memory"
        );
        return r;
    }
    inline FVector operator*( const FVector& V ) const
    {
        FVector r;
        asm volatile ("
            lqc2        vf2, 0x00(%1)
            lqc2        vf3, 0x00(%2)
            vmul.xyz    vf1, vf2, vf3
            sqc2        vf1, 0x00(%0)
        "
        :
        : "r" (&r), "r" (this), "r" (&V)
        : "memory"
        );
        return r;
    }

    // Binary comparison operators.
    UBOOL operator==( const FVector& V ) const
    {
        return X==V.X && Y==V.Y && Z==V.Z;
    }
    UBOOL operator!=( const FVector& V ) const
    {
        return X!=V.X || Y!=V.Y || Z!=V.Z;
    }

    // Unary operators.
    FVector operator-() const
    {
        return FVector( -X, -Y, -Z );
    }

    // Assignment operators.
    inline FVector operator+=( const FVector& V )
    {
        asm volatile ("
            lqc2        vf2, 0x00(%0)
            lqc2        vf3, 0x00(%1)
            vadd.xyz    vf1, vf2, vf3
            sqc2        vf1, 0x00(%0)
        "
        : 
        : "r" (this), "r" (&V)
        : "memory"
        );
        return *this;
    }
    inline FVector operator-=( const FVector& V )
    {
        asm volatile ("
            lqc2        vf2, 0x00(%0)
            lqc2        vf3, 0x00(%1)
            vsub.xyz    vf1, vf2, vf3
            sqc2        vf1, 0x00(%0)
        "
        : 
        : "r" (this), "r" (&V)
        : "memory"
        );
        return *this;
    }
    inline FVector operator*=( FLOAT Scale )
    {
        asm volatile ("
            ctc2        %1,  $21
            lqc2        vf2, 0x00(%0)
            vmuli.xyz   vf1, vf2, I
            sqc2        vf1, 0x00(%0)
        "
        :
        : "r" (this), "r" (Scale)
        : "memory"
        );
        return *this;
    }
    inline FVector operator/=( FLOAT V )
    {
        FLOAT RScale = 1.f/V;
        asm volatile ("
            ctc2        %1,  $21
            lqc2        vf2, 0x00(%0)
            vmuli.xyz   vf1, vf2, I
            sqc2        vf1, 0x00(%0)
        "
        :
        : "r" (this), "r" (RScale)
        : "memory"
        );
        return *this;
    }
    inline FVector operator*=( const FVector& V )
    {
        asm volatile ("
            lqc2        vf2, 0x00(%0)
            lqc2        vf3, 0x00(%1)
            vmul.xyz    vf1, vf2, vf3
            sqc2        vf1, 0x00(%0)
        "
        :
        : "r" (this), "r" (&V)
        : "memory"
        );
        return *this;
    }
    FVector operator/=( const FVector& V )
    {
        X /= V.X; Y /= V.Y; Z /= V.Z;
        return *this;
    }

    // Simple functions.
    FLOAT Size() const
    {
        return appSqrt( X*X + Y*Y + Z*Z );
    }
    FLOAT SizeSquared() const
    {
        return X*X + Y*Y + Z*Z;
    }
    FLOAT Size2D() const 
    {
        return appSqrt( X*X + Y*Y );
    }
    FLOAT SizeSquared2D() const 
    {
        return X*X + Y*Y;
    }
    int IsNearlyZero() const
    {
        return
                Abs(X)<KINDA_SMALL_NUMBER
            &&  Abs(Y)<KINDA_SMALL_NUMBER
            &&  Abs(Z)<KINDA_SMALL_NUMBER;
    }
    UBOOL IsZero() const
    {
        return X==0.f && Y==0.f && Z==0.f;
    }
    UBOOL Normalize()
    {
        FLOAT SquareSum = X*X+Y*Y+Z*Z;
        if( SquareSum >= SMALL_NUMBER )
        {
            FLOAT Scale = 1.f/appSqrt(SquareSum);
            X *= Scale; Y *= Scale; Z *= Scale;
            return 1;
        }
        else return 0;
    }
    FVector Projection() const
    {
        FLOAT RZ = 1.f/Z;
        return FVector( X*RZ, Y*RZ, 1 );
    }
    FVector UnsafeNormal() const
    {
        FLOAT Scale = 1.f/appSqrt(X*X+Y*Y+Z*Z);
        return FVector( X*Scale, Y*Scale, Z*Scale );
    }
    FVector GridSnap( const FVector& Grid )
    {
        return FVector( FSnap(X, Grid.X),FSnap(Y, Grid.Y),FSnap(Z, Grid.Z) );
    }
    FVector BoundToCube( FLOAT Radius )
    {
        return FVector
        (
            Clamp(X,-Radius,Radius),
            Clamp(Y,-Radius,Radius),
            Clamp(Z,-Radius,Radius)
        );
    }
    void AddBounded( const FVector& V, FLOAT Radius=MAXSWORD )
    {
        *this = (*this + V).BoundToCube(Radius);
    }
    FLOAT& Component( INT Index )
    {
        return (&X)[Index];
    }

    // Return a boolean that is based on the vector's direction.
    // When      V==(0,0,0) Booleanize(0)=1.
    // Otherwise Booleanize(V) <-> !Booleanize(!B).
    UBOOL Booleanize()
    {
        return
            X >  0.f ? 1 :
            X <  0.f ? 0 :
            Y >  0.f ? 1 :
            Y <  0.f ? 0 :
            Z >= 0.f ? 1 : 0;
    }

    // Transformation.
    FVector TransformVectorBy( const FCoords& Coords ) const;
    FVector TransformPointBy( const FCoords& Coords ) const;
    FVector MirrorByVector( const FVector& MirrorNormal ) const;
    FVector MirrorByPlane( const FPlane& MirrorPlane ) const;
    FVector PivotTransform(const FCoords& Coords) const;

    // Complicated functions.
    FRotator Rotation();
    void FindBestAxisVectors( FVector& Axis1, FVector& Axis2 );
    FVector SafeNormal() const; //warning: Not inline because of compiler bug.

    // Friends.
    friend FLOAT FDist( const FVector& V1, const FVector& V2 );
    friend FLOAT FDistSquared( const FVector& V1, const FVector& V2 );
    friend UBOOL FPointsAreSame( const FVector& P, const FVector& Q );
    friend UBOOL FPointsAreNear( const FVector& Point1, const FVector& Point2, FLOAT Dist);
    friend FLOAT FPointPlaneDist( const FVector& Point, const FVector& PlaneBase, const FVector& PlaneNormal );
    friend FVector FLinePlaneIntersection( const FVector& Point1, const FVector& Point2, const FVector& PlaneOrigin, const FVector& PlaneNormal );
    friend FVector FLinePlaneIntersection( const FVector& Point1, const FVector& Point2, const FPlane& Plane );
    friend UBOOL FParallel( const FVector& Normal1, const FVector& Normal2 );
    friend UBOOL FCoplanar( const FVector& Base1, const FVector& Normal1, const FVector& Base2, const FVector& Normal2 );

    // Serializer.
    friend FArchive& operator<<( FArchive& Ar, FVector& V )
    {
        return Ar << V.X << V.Y << V.Z;
    }
 } GCC_ALIGN(16);



 #else



 #define FVECTOR_ALIGNMENT DEFAULT_ALIGNMENT
 class CORE_API FVector 
 {
 public:
    // Variables.
    FLOAT X,Y,Z;

    // Constructors.
    FVector()
    {}

    FVector( FLOAT InX, FLOAT InY, FLOAT InZ )
    :   X(InX), Y(InY), Z(InZ)
    {}

    // Binary math operators.
    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
        );
    }
    FLOAT operator|( const FVector& V ) const
    {
        return X*V.X + Y*V.Y + Z*V.Z;
    }
    friend FVector operator*( FLOAT Scale, const FVector& V )
    {
        return FVector( V.X * Scale, V.Y * Scale, V.Z * Scale );
    }
    FVector operator+( const FVector& V ) const
    {
        return FVector( X + V.X, Y + V.Y, Z + V.Z );
    }
    FVector operator-( const FVector& V ) const
    {
        return FVector( X - V.X, Y - V.Y, Z - V.Z );
    }
    FVector operator*( FLOAT Scale ) const
    {
        return FVector( X * Scale, Y * Scale, Z * Scale );
    }
    FVector operator/( FLOAT Scale ) const
    {
        FLOAT RScale = 1.f/Scale;
        return FVector( X * RScale, Y * RScale, Z * RScale );
    }
    FVector operator*( const FVector& V ) const
    {
        return FVector( X * V.X, Y * V.Y, Z * V.Z );
    }

    // Binary comparison operators.
    UBOOL operator==( const FVector& V ) const
    {
        return X==V.X && Y==V.Y && Z==V.Z;
    }
    UBOOL operator!=( const FVector& V ) const
    {
        return X!=V.X || Y!=V.Y || Z!=V.Z;
    }

    // Unary operators.
    FVector operator-() const
    {
        return FVector( -X, -Y, -Z );
    }

    // Assignment operators.
    FVector operator+=( const FVector& V )
    {
        X += V.X; Y += V.Y; Z += V.Z;
        return *this;
    }
    FVector operator-=( const FVector& V )
    {
        X -= V.X; Y -= V.Y; Z -= V.Z;
        return *this;
    }
    FVector operator*=( FLOAT Scale )
    {
        X *= Scale; Y *= Scale; Z *= Scale;
        return *this;
    }
    FVector operator/=( FLOAT V )
    {
        FLOAT RV = 1.f/V;
        X *= RV; Y *= RV; Z *= RV;
        return *this;
    }
    FVector operator*=( const FVector& V )
    {
        X *= V.X; Y *= V.Y; Z *= V.Z;
        return *this;
    }
    FVector operator/=( const FVector& V )
    {
        X /= V.X; Y /= V.Y; Z /= V.Z;
        return *this;
    }

    // Simple functions.
    FLOAT Size() const
    {
        return appSqrt( X*X + Y*Y + Z*Z );
    }
    FLOAT SizeSquared() const
    {
        return X*X + Y*Y + Z*Z;
    }
    FLOAT Size2D() const 
    {
        return appSqrt( X*X + Y*Y );
    }
    FLOAT SizeSquared2D() const 
    {
        return X*X + Y*Y;
    }
    int IsNearlyZero() const
    {
        return
                Abs(X)<KINDA_SMALL_NUMBER
            &&  Abs(Y)<KINDA_SMALL_NUMBER
            &&  Abs(Z)<KINDA_SMALL_NUMBER;
    }
    UBOOL IsZero() const
    {
        return X==0.f && Y==0.f && Z==0.f;
    }
    UBOOL Normalize()
    {
        FLOAT SquareSum = X*X+Y*Y+Z*Z;
        if( SquareSum >= SMALL_NUMBER )
        {
            FLOAT Scale = 1.f/appSqrt(SquareSum);
            X *= Scale; Y *= Scale; Z *= Scale;
            return 1;
        }
        else return 0;
    }
    FVector Projection() const
    {
        FLOAT RZ = 1.f/Z;
        return FVector( X*RZ, Y*RZ, 1 );
    }
    FVector UnsafeNormal() const
    {
        FLOAT Scale = 1.f/appSqrt(X*X+Y*Y+Z*Z);
        return FVector( X*Scale, Y*Scale, Z*Scale );
    }
    FVector GridSnap( const FVector& Grid )
    {
        return FVector( FSnap(X, Grid.X),FSnap(Y, Grid.Y),FSnap(Z, Grid.Z) );
    }
    FVector BoundToCube( FLOAT Radius )
    {
        return FVector
        (
            Clamp(X,-Radius,Radius),
            Clamp(Y,-Radius,Radius),
            Clamp(Z,-Radius,Radius)
        );
    }
    void AddBounded( const FVector& V, FLOAT Radius=MAXSWORD )
    {
        *this = (*this + V).BoundToCube(Radius);
    }
    FLOAT& Component( INT Index )
    {
        return (&X)[Index];
    }

    // Return a boolean that is based on the vector's direction.
    // When      V==(0,0,0) Booleanize(0)=1.
    // Otherwise Booleanize(V) <-> !Booleanize(!B).
    UBOOL Booleanize()
    {
        return
            X >  0.f ? 1 :
            X <  0.f ? 0 :
            Y >  0.f ? 1 :
            Y <  0.f ? 0 :
            Z >= 0.f ? 1 : 0;
    }

    // Transformation.
    FVector TransformVectorBy( const FCoords& Coords ) const;
    FVector TransformPointBy( const FCoords& Coords ) const;
    FVector MirrorByVector( const FVector& MirrorNormal ) const;
    FVector MirrorByPlane( const FPlane& MirrorPlane ) const;
    FVector PivotTransform(const FCoords& Coords) const;

    // Complicated functions.
    FRotator Rotation();
    void FindBestAxisVectors( FVector& Axis1, FVector& Axis2 );
    FVector SafeNormal() const; //warning: Not inline because of compiler bug.

    // Friends.
    friend FLOAT FDist( const FVector& V1, const FVector& V2 );
    friend FLOAT FDistSquared( const FVector& V1, const FVector& V2 );
    friend UBOOL FPointsAreSame( const FVector& P, const FVector& Q );
    friend UBOOL FPointsAreNear( const FVector& Point1, const FVector& Point2, FLOAT Dist);
    friend FLOAT FPointPlaneDist( const FVector& Point, const FVector& PlaneBase, const FVector& PlaneNormal );
    friend FVector FLinePlaneIntersection( const FVector& Point1, const FVector& Point2, const FVector& PlaneOrigin, const FVector& PlaneNormal );
    friend FVector FLinePlaneIntersection( const FVector& Point1, const FVector& Point2, const FPlane& Plane );
    friend UBOOL FParallel( const FVector& Normal1, const FVector& Normal2 );
    friend UBOOL FCoplanar( const FVector& Base1, const FVector& Normal1, const FVector& Base2, const FVector& Normal2 );

    // Serializer.
    friend FArchive& operator<<( FArchive& Ar, FVector& V )
    {
        return Ar << V.X << V.Y << V.Z;
    }
 };
 #endif

DJPaul: Interesting page, rubbish on itself. What about we make a new page that we can put this - and other notes about the Unreal Engine's Native Classes we've gotten out of Epic? Perhaps hack0rz Native Coding around a bit.

That way we can link to this, the few UT2003 native classes we've gotten out of epic via ut2003mods, the Deus Ex native sources, etc.

Tarquin: What is this page?

The Unreal Engine Documentation Site

Wiki Community

Topic Categories

Image Uploads

Random Page

Recent Changes

Offline Wiki

Unreal Engine

Console Commands

Terminology

FAQs

Help Desk

Mapping Topics

Mapping Lessons

UnrealEd Interface

UnrealScript Topics

UnrealScript Lessons

Making Mods

Class Tree

Modeling Topics

Chongqing Page

Log In