Serious-Engine/Sources/Engine/Math/Placement.cpp
Ryan C. Gordon 24cb244d43 First attempt to hand-merge Ryan's Linux and Mac OS X port.
This was a _ton_ of changes, made 15 years ago, so there are probably some
problems to work out still.

Among others: Engine/Base/Stream.* was mostly abandoned and will need to be
re-ported.

Still, this is a pretty good start, and probably holds a world record for
lines of changes or something.  :)
2016-03-28 23:46:13 -04:00

216 lines
7.1 KiB
C++

/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */
#include "Engine/StdH.h"
#include <Engine/Math/Placement.h>
#include <Engine/Base/Stream.h>
#include <Engine/Math/Geometry.h>
#include <Engine/Math/Projection.h>
// Stream operations
CTStream &operator>>(CTStream &strm, CPlacement3D &p3d)
{
strm>>p3d.pl_PositionVector;
strm>>p3d.pl_OrientationAngle;
return strm;
}
CTStream &operator<<(CTStream &strm, const CPlacement3D &p3d)
{
strm<<p3d.pl_PositionVector;
strm<<p3d.pl_OrientationAngle;
return strm;
}
/////////////////////////////////////////////////////////////////////
// transformations from between coordinate systems
/*
* Project this placement from absolute system to coordinate system of another placement.
*/
void CPlacement3D::AbsoluteToRelative(const CPlacement3D &plSystem)
{
// create a simple projection
CSimpleProjection3D prSimple;
// set the relative system as the viewer
prSimple.ViewerPlacementL() = plSystem;
// set the absolute system as object
prSimple.ObjectPlacementL().pl_PositionVector = FLOAT3D(0.0f, 0.0f, 0.0f);
prSimple.ObjectPlacementL().pl_OrientationAngle = ANGLE3D(0, 0, 0);
// prepare the projection
prSimple.Prepare();
// project this placement using the projection
prSimple.ProjectPlacement(*this, *this);
}
void CPlacement3D::AbsoluteToRelativeSmooth(const CPlacement3D &plSystem)
{
// create a simple projection
CSimpleProjection3D prSimple;
// set the relative system as the viewer
prSimple.ViewerPlacementL() = plSystem;
// set the absolute system as object
prSimple.ObjectPlacementL().pl_PositionVector = FLOAT3D(0.0f, 0.0f, 0.0f);
prSimple.ObjectPlacementL().pl_OrientationAngle = ANGLE3D(0, 0, 0);
// prepare the projection
prSimple.Prepare();
// project this placement using the projection
prSimple.ProjectPlacementSmooth(*this, *this);
}
/*
* Project this placement from coordinate system of another placement to absolute system.
*/
void CPlacement3D::RelativeToAbsolute(const CPlacement3D &plSystem)
{
// create a simple projection
CSimpleProjection3D prSimple;
// set the absolute system as the viewer
prSimple.ViewerPlacementL().pl_PositionVector = FLOAT3D(0.0f, 0.0f, 0.0f);
prSimple.ViewerPlacementL().pl_OrientationAngle = ANGLE3D(0, 0, 0);
// set the relative system as object
prSimple.ObjectPlacementL() = plSystem;
// prepare the projection
prSimple.Prepare();
// project this placement using the projection
prSimple.ProjectPlacement(*this, *this);
}
void CPlacement3D::RelativeToAbsoluteSmooth(const CPlacement3D &plSystem)
{
// create a simple projection
CSimpleProjection3D prSimple;
// set the absolute system as the viewer
prSimple.ViewerPlacementL().pl_PositionVector = FLOAT3D(0.0f, 0.0f, 0.0f);
prSimple.ViewerPlacementL().pl_OrientationAngle = ANGLE3D(0, 0, 0);
// set the relative system as object
prSimple.ObjectPlacementL() = plSystem;
// prepare the projection
prSimple.Prepare();
// project this placement using the projection
prSimple.ProjectPlacementSmooth(*this, *this);
}
/*
* Project this placement from system of one placement to system of another placement.
*/
void CPlacement3D::RelativeToRelative(const CPlacement3D &plSource,
const CPlacement3D &plTarget)
{
// create a simple projection
CSimpleProjection3D prSimple;
// set the target system as the viewer
prSimple.ViewerPlacementL() = plTarget;
// set the source system as object
prSimple.ObjectPlacementL() = plSource;
// prepare the projection
prSimple.Prepare();
// project this placement using the projection
prSimple.ProjectPlacement(*this, *this);
}
void CPlacement3D::RelativeToRelativeSmooth(const CPlacement3D &plSource,
const CPlacement3D &plTarget)
{
// create a simple projection
CSimpleProjection3D prSimple;
// set the target system as the viewer
prSimple.ViewerPlacementL() = plTarget;
// set the source system as object
prSimple.ObjectPlacementL() = plSource;
// prepare the projection
prSimple.Prepare();
// project this placement using the projection
prSimple.ProjectPlacementSmooth(*this, *this);
}
/* Make this placement be a linear interpolation between given two placements. */
void CPlacement3D::Lerp(const CPlacement3D &pl0, const CPlacement3D &pl1, FLOAT fFactor)
{
// lerp the position
pl_PositionVector(1) =
LerpFLOAT(pl0.pl_PositionVector(1), pl1.pl_PositionVector(1), fFactor);
pl_PositionVector(2) =
LerpFLOAT(pl0.pl_PositionVector(2), pl1.pl_PositionVector(2), fFactor);
pl_PositionVector(3) =
LerpFLOAT(pl0.pl_PositionVector(3), pl1.pl_PositionVector(3), fFactor);
// lerp the orientation
pl_OrientationAngle(1) =
LerpANGLE(pl0.pl_OrientationAngle(1), pl1.pl_OrientationAngle(1), fFactor);
pl_OrientationAngle(2) =
LerpANGLE(pl0.pl_OrientationAngle(2), pl1.pl_OrientationAngle(2), fFactor);
pl_OrientationAngle(3) =
LerpANGLE(pl0.pl_OrientationAngle(3), pl1.pl_OrientationAngle(3), fFactor);
}
/////////////////////////////////////////////////////////////////////
// translations and rotations
/*
* Rotate using trackball method.
*/
void CPlacement3D::Rotate_TrackBall(const ANGLE3D &a3dRotation)
{
FLOATmatrix3D t3dRotation; // matrix for the rotation angles
FLOATmatrix3D t3dOriginal; // matrix for the original angles
// create matrices from angles
MakeRotationMatrix(t3dRotation, a3dRotation);
MakeRotationMatrix(t3dOriginal, pl_OrientationAngle);
// make composed matrix
t3dOriginal = t3dRotation*t3dOriginal; // rotate first by original, then by rotation angles
// recreate angles from composed matrix
DecomposeRotationMatrix(pl_OrientationAngle, t3dOriginal);
}
/*
* Rotate using airplane method.
*/
void CPlacement3D::Rotate_Airplane(const ANGLE3D &a3dRotation)
{
FLOATmatrix3D t3dRotation; // matrix for the rotation angles
FLOATmatrix3D t3dOriginal; // matrix for the original angles
// create matrices from angles
MakeRotationMatrixFast(t3dRotation, a3dRotation);
MakeRotationMatrixFast(t3dOriginal, pl_OrientationAngle);
// make composed matrix
t3dOriginal = t3dOriginal*t3dRotation; // rotate first by rotation, then by original angles
// recreate angles from composed matrix
DecomposeRotationMatrixNoSnap(pl_OrientationAngle, t3dOriginal);
}
/*
* Rotate using HPB method.
*/
void CPlacement3D::Rotate_HPB(const ANGLE3D &a3dRotation)
{
// just add the rotation angles to original angles
pl_OrientationAngle += a3dRotation;
}
/*
* Translate in own coordinate system.
*/
void CPlacement3D::Translate_OwnSystem(const FLOAT3D &f3dRelativeTranslation)
{
FLOATmatrix3D t3dOwnAngles; // matrix for own angles
// make matrix from own angles
MakeRotationMatrix(t3dOwnAngles, pl_OrientationAngle);
// make absolute translation from relative by rotating for your own angles
pl_PositionVector += f3dRelativeTranslation*t3dOwnAngles;
}
/*
* Translate in absolute coordinate system.
*/
void CPlacement3D::Translate_AbsoluteSystem(const FLOAT3D &f3dAbsoluteTranslation)
{
// just add the translation to the position vector
pl_PositionVector += f3dAbsoluteTranslation;
}