Complete disaster-recovery snapshot: engine/game source, game data assets, VC6 toolchain + DX SDKs, build outputs, deployed game, and _UNUSED archive. Large binaries in Git LFS; text preserved byte-for-byte (core.autocrlf=false, no eol attributes). See RECOVERY.md for the one-clone rebuild procedure.
507 lines
12 KiB
C++
507 lines
12 KiB
C++
//===========================================================================//
|
|
// File: vector3d.hh //
|
|
// Project: MUNGA Brick: Math Library //
|
|
// Contents: Interface specification for vector classes //
|
|
//---------------------------------------------------------------------------//
|
|
// Date Who Modification //
|
|
// -------- --- ---------------------------------------------------------- //
|
|
// 11/19/94 JMA Initial coding. //
|
|
//---------------------------------------------------------------------------//
|
|
// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. //
|
|
// All Rights reserved worldwide //
|
|
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
|
|
//===========================================================================//
|
|
|
|
#pragma once
|
|
|
|
#include "Stuff.hpp"
|
|
#include "MemoryStream.hpp"
|
|
#include "Scalar.hpp"
|
|
|
|
namespace Stuff {class Vector3D;}
|
|
|
|
#if !defined(Spew)
|
|
void
|
|
Spew(
|
|
const char* group,
|
|
const Stuff::Vector3D &vector
|
|
);
|
|
#endif
|
|
|
|
namespace Stuff {
|
|
|
|
class AffineMatrix4D;
|
|
class LinearMatrix4D;
|
|
class Matrix4D;
|
|
class Point3D;
|
|
class UnitQuaternion;
|
|
class YawPitchRange;
|
|
|
|
enum Axes {
|
|
X_Axis,
|
|
Y_Axis,
|
|
Z_Axis,
|
|
W_Axis
|
|
};
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// The following macros define MUNGAs base coordinate system
|
|
//
|
|
// Note that Yaw is always about the up/down axis, pitch is always about
|
|
// the left/right axis, and Roll is always about the forward/back axis. In
|
|
// order to rotate about negative axes, the appropriate macros should be
|
|
// uncommented
|
|
//
|
|
// #define LEFT_HANDED_COORDINATES
|
|
|
|
#define UP_AXIS Stuff::Y_Axis
|
|
#define DOWN_AXIS Stuff::Y_Axis
|
|
#define FORWARD_AXIS Stuff::Z_Axis
|
|
#define BACKWARD_AXIS Stuff::Z_Axis
|
|
#define RIGHT_AXIS Stuff::X_Axis
|
|
#define LEFT_AXIS Stuff::X_Axis
|
|
|
|
#define PRIMARY_AXIS LEFT_AXIS
|
|
#define SECONDARY_AXIS UP_AXIS
|
|
#define TERTIARY_AXIS FORWARD_AXIS
|
|
|
|
// #define YAW_ABOUT_DOWN // Default Yaw is about Up
|
|
// #define PITCH_ABOUT_LEFT // Default Pitch is about Right
|
|
// #define ROLL_ABOUT_BACKWARD // Default Roll is about Forward
|
|
|
|
#define APPLY_UP_SIGN(y) (y)
|
|
#define UP_X (0.0f)
|
|
#define UP_Y (1.0f)
|
|
#define UP_Z (0.0f)
|
|
|
|
#define APPLY_FORWARD_SIGN(z) (z)
|
|
#define FORWARD_X (0.0f)
|
|
#define FORWARD_Y (0.0f)
|
|
#define FORWARD_Z (1.0f)
|
|
|
|
#define APPLY_RIGHT_SIGN(x) (-(x))
|
|
#define RIGHT_X (-1.0f)
|
|
#define RIGHT_Y (0.0f)
|
|
#define RIGHT_Z (0.0f)
|
|
|
|
#define APPLY_DOWN_SIGN(y) (-(y))
|
|
#define DOWN_X (-UP_X)
|
|
#define DOWN_Y (-UP_Y)
|
|
#define DOWN_Z (-UP_Z)
|
|
|
|
#define APPLY_BACKWARD_SIGN(z) (-(z))
|
|
#define BACKWARD_X (-FORWARD_X)
|
|
#define BACKWARD_Y (-FORWARD_Y)
|
|
#define BACKWARD_Z (-FORWARD_Z)
|
|
|
|
#define APPLY_LEFT_SIGN(x) (x)
|
|
#define LEFT_X (-RIGHT_X)
|
|
#define LEFT_Y (-RIGHT_Y)
|
|
#define LEFT_Z (-RIGHT_Z)
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Vector3D ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
class Vector3D
|
|
{
|
|
public:
|
|
Scalar
|
|
x,
|
|
y,
|
|
z;
|
|
|
|
static const Vector3D
|
|
Identity;
|
|
static const Vector3D
|
|
Forward;
|
|
static const Vector3D
|
|
Backward;
|
|
static const Vector3D
|
|
Up;
|
|
static const Vector3D
|
|
Down;
|
|
static const Vector3D
|
|
Left;
|
|
static const Vector3D
|
|
Right;
|
|
|
|
//
|
|
// Constructors
|
|
//
|
|
Vector3D()
|
|
{}
|
|
Vector3D(
|
|
Scalar x,
|
|
Scalar y,
|
|
Scalar z
|
|
):
|
|
x(x),
|
|
y(y),
|
|
z(z)
|
|
{}
|
|
Vector3D(const Vector3D &v):
|
|
x(v.x),
|
|
y(v.y),
|
|
z(v.z)
|
|
{}
|
|
explicit Vector3D(const UnitQuaternion &q)
|
|
{*this = q;}
|
|
explicit Vector3D(const YawPitchRange &p)
|
|
{*this = p;}
|
|
|
|
//
|
|
// Assignment operators
|
|
//
|
|
Vector3D&
|
|
operator=(const Vector3D &vector)
|
|
{
|
|
Check_Pointer(this); Check_Object(&vector);
|
|
x = vector.x; y = vector.y; z = vector.z;
|
|
return *this;
|
|
}
|
|
Vector3D&
|
|
operator=(const UnitQuaternion &q);
|
|
Vector3D&
|
|
operator=(const YawPitchRange &p);
|
|
|
|
//
|
|
// "Close-enough" comparators
|
|
//
|
|
friend bool
|
|
Small_Enough(
|
|
const Vector3D &v,
|
|
Scalar e=SMALL
|
|
)
|
|
{Check_Object(&v); return v.GetLengthSquared() <= e;}
|
|
bool
|
|
operator!() const
|
|
{return Small_Enough(*this, SMALL);}
|
|
|
|
friend bool
|
|
Close_Enough(
|
|
const Vector3D &v1,
|
|
const Vector3D &v2,
|
|
Scalar e=SMALL
|
|
);
|
|
bool
|
|
operator==(const Vector3D& v) const
|
|
{return Close_Enough(*this,v,SMALL);}
|
|
bool
|
|
operator!=(const Vector3D& v) const
|
|
{return !Close_Enough(*this,v,SMALL);}
|
|
|
|
void
|
|
TestInstance() const
|
|
{}
|
|
|
|
//
|
|
// Indexing operations
|
|
//
|
|
|
|
static int GetMemberCount(void)
|
|
{
|
|
return 3;
|
|
}
|
|
|
|
const Scalar&
|
|
operator[](size_t index) const
|
|
{
|
|
Check_Pointer(this);
|
|
Verify(static_cast<unsigned>(index) <= Z_Axis);
|
|
return (&x)[index];
|
|
}
|
|
Scalar&
|
|
operator[](size_t index)
|
|
{
|
|
Check_Pointer(this);
|
|
Verify(static_cast<unsigned>(index) <= Z_Axis);
|
|
return (&x)[index];
|
|
}
|
|
|
|
Scalar
|
|
GetForwardComponent()
|
|
{Check_Object(this); return APPLY_FORWARD_SIGN((*this)[FORWARD_AXIS]);}
|
|
Scalar
|
|
GetBackwardComponent()
|
|
{Check_Object(this); return APPLY_BACKWARD_SIGN((*this)[BACKWARD_AXIS]);}
|
|
Scalar
|
|
GetUpComponent()
|
|
{Check_Object(this); return APPLY_UP_SIGN((*this)[UP_AXIS]);}
|
|
Scalar
|
|
GetDownComponent()
|
|
{Check_Object(this); return APPLY_DOWN_SIGN((*this)[DOWN_AXIS]);}
|
|
Scalar
|
|
GetRightComponent()
|
|
{Check_Object(this); return APPLY_RIGHT_SIGN((*this)[RIGHT_AXIS]);}
|
|
Scalar
|
|
GetLeftComponent()
|
|
{Check_Object(this); return APPLY_LEFT_SIGN((*this)[LEFT_AXIS]);}
|
|
|
|
//
|
|
// The following operators all assume that this points to the destination
|
|
// of the operation results
|
|
//
|
|
Vector3D&
|
|
Negate(const Vector3D &v)
|
|
{
|
|
Check_Pointer(this); Check_Object(&v);
|
|
x = -v.x; y = -v.y; z = -v.z; return *this;
|
|
}
|
|
|
|
Vector3D&
|
|
Add(
|
|
const Vector3D& v1,
|
|
const Vector3D& v2
|
|
)
|
|
{
|
|
Check_Pointer(this); Check_Object(&v1); Check_Object(&v2);
|
|
x = v1.x + v2.x; y = v1.y + v2.y; z = v1.z + v2.z; return *this;
|
|
}
|
|
Vector3D&
|
|
AddScaled(
|
|
const Vector3D& v1,
|
|
const Vector3D& v2,
|
|
Scalar scale
|
|
)
|
|
{
|
|
Check_Pointer(this); Check_Object(&v1); Check_Object(&v2);
|
|
x = v1.x + v2.x*scale; y = v1.y + v2.y*scale;
|
|
z = v1.z + v2.z*scale; return *this;
|
|
}
|
|
Vector3D&
|
|
operator+=(const Vector3D& v)
|
|
{return Add(*this,v);}
|
|
|
|
Vector3D&
|
|
Subtract(
|
|
const Vector3D& v1,
|
|
const Vector3D& v2
|
|
)
|
|
{
|
|
Check_Pointer(this); Check_Object(&v1); Check_Object(&v2);
|
|
x = v1.x - v2.x; y = v1.y - v2.y; z = v1.z - v2.z; return *this;
|
|
}
|
|
Vector3D&
|
|
operator-=(const Vector3D& v)
|
|
{return Subtract(*this,v);}
|
|
|
|
Scalar
|
|
operator*(const Vector3D& v) const
|
|
{
|
|
Check_Object(this); Check_Object(&v);
|
|
return x*v.x + y*v.y + z*v.z;
|
|
}
|
|
|
|
Vector3D&
|
|
Cross(
|
|
const Vector3D& v1,
|
|
const Vector3D& v2
|
|
)
|
|
{
|
|
Check_Pointer(this); Check_Object(&v1); Check_Object(&v2);
|
|
Verify(this != &v1); Verify(this != &v2);
|
|
#if defined(LEFT_HANDED_COORDINATES)
|
|
x = v2.y*v1.z - v2.z*v1.y; y = v2.z*v1.x - v2.x*v1.z;
|
|
z = v2.x*v1.y - v2.y*v1.x; return *this;
|
|
#else
|
|
x = v1.y*v2.z - v1.z*v2.y; y = v1.z*v2.x - v1.x*v2.z;
|
|
z = v1.x*v2.y - v1.y*v2.x; return *this;
|
|
#endif
|
|
}
|
|
|
|
Vector3D&
|
|
Cross(
|
|
const Vector3D& p1, // v1 = p1 - p2
|
|
const Vector3D& p2, // v2 = p3 - p2
|
|
const Vector3D& p3
|
|
)
|
|
{
|
|
Check_Pointer(this);
|
|
Check_Object(&p1); Check_Object(&p2); Check_Object(&p3);
|
|
Verify(this != &p1); Verify(this != &p2); Verify(this != &p3);
|
|
#if defined(LEFT_HANDED_COORDINATES)
|
|
x = (p3.y - p2.y)*(p1.z - p2.z) - (p3.z - p2.z)*(p1.y - p2.y);
|
|
y = (p3.z - p2.z)*(p1.x - p2.x) - (p3.x - p2.x)*(p1.z - p2.z);
|
|
z = (p3.x - p2.x)*(p1.y - p2.y) - (p3.y - p2.y)*(p1.x - p2.x);
|
|
return *this;
|
|
#else
|
|
x = (p1.y - p2.y)*(p3.z - p2.z) - (p1.z - p2.z)*(p3.y - p2.y);
|
|
y = (p1.z - p2.z)*(p3.x - p2.x) - (p1.x - p2.x)*(p3.z - p2.z);
|
|
z = (p1.x - p2.x)*(p3.y - p2.y) - (p1.y - p2.y)*(p3.x - p2.x);
|
|
return *this;
|
|
#endif
|
|
}
|
|
|
|
Vector3D&
|
|
Multiply(
|
|
const Vector3D& v,
|
|
Scalar scale
|
|
)
|
|
{
|
|
Check_Pointer(this); Check_Object(&v);
|
|
x = v.x*scale; y = v.y*scale; z = v.z*scale; return *this;
|
|
}
|
|
Vector3D&
|
|
operator*=(Scalar v)
|
|
{return Multiply(*this,v);}
|
|
|
|
Vector3D&
|
|
Multiply(
|
|
const Vector3D& v1,
|
|
const Vector3D& v2
|
|
)
|
|
{
|
|
Check_Pointer(this); Check_Object(&v1); Check_Object(&v2);
|
|
x = v1.x*v2.x; y = v1.y*v2.y; z = v1.z*v2.z; return *this;
|
|
}
|
|
Vector3D&
|
|
operator*=(const Vector3D &v)
|
|
{return Multiply(*this,v);}
|
|
|
|
Vector3D&
|
|
Divide(
|
|
const Vector3D& v,
|
|
Scalar scale
|
|
)
|
|
{
|
|
Check_Pointer(this); Check_Object(&v);
|
|
Verify(!Small_Enough(scale));
|
|
scale = 1.0f / scale;
|
|
x = v.x*scale; y = v.y*scale; z = v.z*scale; return *this;
|
|
}
|
|
Vector3D&
|
|
operator/=(Scalar v)
|
|
{return Divide(*this,v);}
|
|
|
|
Vector3D&
|
|
Divide(
|
|
const Vector3D& v1,
|
|
const Vector3D& v2
|
|
)
|
|
{
|
|
Check_Pointer(this); Check_Object(&v1); Check_Object(&v2);
|
|
Verify(!Small_Enough(v2.x)); Verify(!Small_Enough(v2.y));
|
|
Verify(!Small_Enough(v2.z));
|
|
x = v1.x/v2.x; y = v1.y/v2.y; z = v1.z/v2.z; return *this;
|
|
}
|
|
Vector3D&
|
|
operator/=(const Vector3D &v)
|
|
{return Divide(*this,v);}
|
|
|
|
//
|
|
// Transform operators
|
|
//
|
|
Vector3D&
|
|
Multiply(
|
|
const Vector3D &v,
|
|
const AffineMatrix4D &m
|
|
);
|
|
Vector3D&
|
|
operator*=(const AffineMatrix4D &m)
|
|
{Vector3D src(*this); return Multiply(src,m);}
|
|
Vector3D&
|
|
MultiplyByInverse(
|
|
const Vector3D &v,
|
|
const LinearMatrix4D &m
|
|
);
|
|
|
|
//
|
|
// Miscellaneous functions
|
|
//
|
|
Scalar
|
|
GetLengthSquared() const
|
|
{Check_Object(this); return x*x + y*y + z*z;}
|
|
Scalar
|
|
GetLength() const
|
|
{return Sqrt(GetLengthSquared());}
|
|
|
|
Scalar
|
|
GetApproximateLength() const
|
|
{return SqrtApproximate(GetLengthSquared());}
|
|
|
|
Vector3D&
|
|
Normalize(const Vector3D &v)
|
|
{
|
|
Check_Object(this); Check_Object(&v);
|
|
Scalar len = v.GetLength();
|
|
Verify(!Small_Enough(len)); len = 1.0f / len;
|
|
x = v.x*len; y = v.y*len; z = v.z*len; return *this;
|
|
}
|
|
|
|
Vector3D&
|
|
NormalizeApproximate(const Vector3D &v)
|
|
{
|
|
Check_Object(this); Check_Object(&v);
|
|
Scalar len = v.GetApproximateLength();
|
|
Verify(!Small_Enough(len)); len = OneOverApproximate(len);
|
|
x = v.x*len; y = v.y*len; z = v.z*len; return *this;
|
|
}
|
|
|
|
|
|
Vector3D&
|
|
Combine(
|
|
const Vector3D& v1,
|
|
Scalar t1,
|
|
const Vector3D& v2,
|
|
Scalar t2
|
|
)
|
|
{
|
|
Check_Pointer(this); Check_Object(&v1); Check_Object(&v2);
|
|
x = t1*v1.x + t2*v2.x; y = t1*v1.y + t2*v2.y;
|
|
z = t1*v1.z + t2*v2.z; return *this;
|
|
}
|
|
|
|
void Zero (void)
|
|
{
|
|
x = y = z = 0.0;
|
|
}
|
|
|
|
//
|
|
// Template support
|
|
//
|
|
Vector3D&
|
|
Lerp(
|
|
const Vector3D& v1,
|
|
const Vector3D& v2,
|
|
Scalar t
|
|
)
|
|
{
|
|
Check_Pointer(this); Check_Object(&v1); Check_Object(&v2);
|
|
x = v1.x + t*(v2.x-v1.x); y = v1.y + t*(v2.y-v1.y);
|
|
z = v1.z + t*(v2.z-v1.z); return *this;
|
|
}
|
|
|
|
//
|
|
// Support functions
|
|
//
|
|
#if !defined(Spew)
|
|
friend void
|
|
::Spew(
|
|
const char* group,
|
|
const Vector3D &vector
|
|
);
|
|
#endif
|
|
static bool
|
|
TestClass();
|
|
};
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~ Vector3D functions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
}
|
|
|
|
namespace MemoryStreamIO {
|
|
|
|
inline Stuff::MemoryStream&
|
|
Read(
|
|
Stuff::MemoryStream* stream,
|
|
Stuff::Vector3D *output
|
|
)
|
|
{return stream->ReadBytes(output, sizeof(*output));}
|
|
inline Stuff::MemoryStream&
|
|
Write(
|
|
Stuff::MemoryStream* stream,
|
|
const Stuff::Vector3D *input
|
|
)
|
|
{return stream->WriteBytes(input, sizeof(*input));}
|
|
|
|
}
|