2016-03-12 01:20:51 +01:00
|
|
|
/* Copyright (c) 2002-2012 Croteam Ltd.
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of version 2 of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation
|
|
|
|
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License along
|
|
|
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
|
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
|
2016-03-11 14:57:17 +01:00
|
|
|
|
2016-03-29 03:03:54 +02:00
|
|
|
#include "Engine/StdH.h"
|
2016-03-11 14:57:17 +01:00
|
|
|
|
|
|
|
#include <Engine/Math/Projection.h>
|
|
|
|
|
|
|
|
#include <Engine/Math/Clipping.inl>
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
|
// CSimpleProjection3D
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Prepare for projecting.
|
|
|
|
*/
|
|
|
|
void CSimpleProjection3D::Prepare(void)
|
|
|
|
{
|
|
|
|
FLOATmatrix3D t3dObjectStretch; // matrix for object stretch
|
|
|
|
FLOATmatrix3D t3dObjectRotation; // matrix for object angles
|
|
|
|
|
|
|
|
// calc. matrices for viewer and object angles and stretch
|
|
|
|
MakeRotationMatrix(t3dObjectRotation, pr_ObjectPlacement.pl_OrientationAngle); // object normally
|
|
|
|
MakeInverseRotationMatrix(pr_ViewerRotationMatrix, pr_ViewerPlacement.pl_OrientationAngle); // viewer inverse
|
|
|
|
t3dObjectStretch.Diagonal(pr_ObjectStretch);
|
|
|
|
|
|
|
|
// if the object is face-forward
|
|
|
|
if (pr_bFaceForward) {
|
|
|
|
// apply object stretch only
|
|
|
|
pr_RotationMatrix = t3dObjectStretch;
|
|
|
|
} else {
|
|
|
|
// first apply object stretch then object rotation and then viewer rotation
|
|
|
|
pr_RotationMatrix = pr_ViewerRotationMatrix*t3dObjectRotation*t3dObjectStretch;
|
|
|
|
}
|
|
|
|
|
|
|
|
// calc. offset of object from viewer
|
|
|
|
pr_TranslationVector = pr_ObjectPlacement.pl_PositionVector - pr_ViewerPlacement.pl_PositionVector;
|
|
|
|
// rotate offset only by viewer angles
|
|
|
|
pr_TranslationVector = pr_TranslationVector*pr_ViewerRotationMatrix;
|
|
|
|
// transform handle from object space to viewer space and add it to the offset
|
|
|
|
pr_TranslationVector -= pr_vObjectHandle*pr_RotationMatrix;
|
|
|
|
|
|
|
|
// mark as prepared
|
|
|
|
pr_Prepared = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Project 3D object point into 3D view space, before clipping.
|
|
|
|
*/
|
|
|
|
void CSimpleProjection3D::PreClip(const FLOAT3D &v3dObjectPoint,
|
|
|
|
FLOAT3D &v3dTransformedPoint) const
|
|
|
|
{
|
|
|
|
// check that the projection object is prepared for projecting
|
|
|
|
ASSERT(pr_Prepared);
|
|
|
|
|
|
|
|
// rotate and translate the point
|
|
|
|
v3dTransformedPoint = v3dObjectPoint*pr_RotationMatrix + pr_TranslationVector;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Project 3D object point into 3D view space, after clipping.
|
|
|
|
*/
|
|
|
|
void CSimpleProjection3D::PostClip( const FLOAT3D &v3dTransformedPoint,
|
|
|
|
FLOAT3D &v3dViewPoint) const
|
|
|
|
{
|
|
|
|
// check that the projection object is prepared for projecting
|
|
|
|
ASSERT(pr_Prepared);
|
|
|
|
v3dViewPoint = v3dTransformedPoint;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CSimpleProjection3D::PostClip( const FLOAT3D &v3dTransformedPoint, FLOAT fTransformedR,
|
|
|
|
FLOAT3D &v3dViewPoint, FLOAT &fViewR) const
|
|
|
|
{
|
|
|
|
// check that the projection object is prepared for projecting
|
|
|
|
ASSERT(pr_Prepared);
|
|
|
|
v3dViewPoint = v3dTransformedPoint;
|
|
|
|
fViewR = fTransformedR;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Test if a sphere in view space is inside view frustum. */
|
|
|
|
INDEX CSimpleProjection3D::TestSphereToFrustum(const FLOAT3D &vViewPoint, FLOAT fRadius) const
|
|
|
|
{
|
|
|
|
ASSERT(pr_Prepared);
|
|
|
|
ASSERTALWAYS("Function not supported");
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Test if an oriented box in view space is inside view frustum. */
|
|
|
|
INDEX CSimpleProjection3D::TestBoxToFrustum(const FLOATobbox3D &boxView) const
|
|
|
|
{
|
|
|
|
ASSERT(pr_Prepared);
|
|
|
|
ASSERTALWAYS("Function not supported");
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Project 3D object point into 3D view space.
|
|
|
|
*/
|
|
|
|
void CSimpleProjection3D::ProjectCoordinate(const FLOAT3D &v3dObjectPoint,
|
|
|
|
FLOAT3D &v3dViewPoint) const
|
|
|
|
{
|
|
|
|
// rotate and translate the point
|
|
|
|
v3dViewPoint = v3dObjectPoint*pr_RotationMatrix + pr_TranslationVector;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Get a distance of object point from the viewer.
|
|
|
|
*/
|
|
|
|
FLOAT CSimpleProjection3D::GetDistance(const FLOAT3D &v3dObjectPoint) const
|
|
|
|
{
|
|
|
|
// get just the z coordinate of the point in viewer space
|
|
|
|
return
|
|
|
|
v3dObjectPoint(1)*pr_RotationMatrix(3,1)+
|
|
|
|
v3dObjectPoint(2)*pr_RotationMatrix(3,2)+
|
|
|
|
v3dObjectPoint(3)*pr_RotationMatrix(3,3)+
|
|
|
|
pr_TranslationVector(3);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Project 3D object direction vector into 3D view space.
|
|
|
|
*/
|
|
|
|
void CSimpleProjection3D::ProjectDirection(const FLOAT3D &v3dObjectPoint,
|
|
|
|
FLOAT3D &v3dViewPoint) const
|
|
|
|
{
|
|
|
|
// rotate the direction
|
|
|
|
v3dViewPoint = v3dObjectPoint*pr_RotationMatrix;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Project 3D object placement into 3D view space.
|
|
|
|
*/
|
|
|
|
void CSimpleProjection3D::ProjectPlacement(const CPlacement3D &plObject,
|
|
|
|
CPlacement3D &plView) const
|
|
|
|
{
|
|
|
|
// rotate and translate the position vector
|
|
|
|
plView.pl_PositionVector = plObject.pl_PositionVector*pr_RotationMatrix
|
|
|
|
+ pr_TranslationVector;
|
|
|
|
// rotate the orientation
|
|
|
|
FLOATmatrix3D mOrientation;
|
|
|
|
MakeRotationMatrix(mOrientation, plObject.pl_OrientationAngle);
|
|
|
|
DecomposeRotationMatrix(plView.pl_OrientationAngle, pr_RotationMatrix*mOrientation);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Project 3D object placement into 3D view space.
|
|
|
|
*/
|
|
|
|
void CSimpleProjection3D::ProjectPlacementSmooth(const CPlacement3D &plObject,
|
|
|
|
CPlacement3D &plView) const
|
|
|
|
{
|
|
|
|
// rotate and translate the position vector
|
|
|
|
plView.pl_PositionVector = plObject.pl_PositionVector*pr_RotationMatrix
|
|
|
|
+ pr_TranslationVector;
|
|
|
|
// rotate the orientation
|
|
|
|
FLOATmatrix3D mOrientation;
|
|
|
|
MakeRotationMatrixFast(mOrientation, plObject.pl_OrientationAngle);
|
|
|
|
DecomposeRotationMatrixNoSnap(plView.pl_OrientationAngle, pr_RotationMatrix*mOrientation);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Project 3D object axis aligned bounding box into 3D view space.
|
|
|
|
*/
|
|
|
|
void CSimpleProjection3D::ProjectAABBox(const FLOATaabbox3D &boxObject,
|
|
|
|
FLOATaabbox3D &boxView) const
|
|
|
|
{
|
|
|
|
// check that the projection object is prepared for projecting
|
|
|
|
ASSERT(pr_Prepared);
|
|
|
|
|
|
|
|
// get center and max axial extent of object box
|
|
|
|
const FLOAT3D vObjectBoxCenter = boxObject.Center();
|
|
|
|
const FLOAT fObjectBoxMaxExtent = boxObject.Size().MaxNorm();
|
|
|
|
// project the center to view space
|
|
|
|
FLOAT3D vViewBoxCenter;
|
|
|
|
ProjectCoordinate(vObjectBoxCenter, vViewBoxCenter);
|
|
|
|
|
|
|
|
// let the view box have center there and radius of twice max axial extent of object box
|
|
|
|
boxView = FLOATaabbox3D(vViewBoxCenter, 2*fObjectBoxMaxExtent);
|
|
|
|
|
|
|
|
/* // clear view box
|
|
|
|
boxView = FLOATaabbox3D();
|
|
|
|
// create all vertex points of object box
|
|
|
|
FLOAT3D avObjectBoxVertices[8];
|
|
|
|
avObjectBoxVertices[0](1) = boxObject.Min()(1);
|
|
|
|
avObjectBoxVertices[0](2) = boxObject.Min()(2);
|
|
|
|
avObjectBoxVertices[0](3) = boxObject.Min()(3);
|
|
|
|
|
|
|
|
avObjectBoxVertices[0](1) = boxObject.Min()(1);
|
|
|
|
avObjectBoxVertices[0](2) = boxObject.Min()(2);
|
|
|
|
avObjectBoxVertices[0](3) = boxObject.Min()(3);
|
|
|
|
|
|
|
|
avObjectBoxVertices[0](1) = boxObject.Max()(1);
|
|
|
|
// project all vertex points of object box
|
|
|
|
// add all vertex points of object box to view box
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Project 3D object plane into 3D view space.
|
|
|
|
*/
|
|
|
|
void CSimpleProjection3D::Project(const FLOATplane3D &p3dObjectPlane,
|
|
|
|
FLOATplane3D &p3dTransformedPlane) const
|
|
|
|
{
|
|
|
|
// check that the projection object is prepared for projecting
|
|
|
|
ASSERT(pr_Prepared);
|
|
|
|
|
|
|
|
// rotate and translate the plane
|
|
|
|
p3dTransformedPlane = p3dObjectPlane*pr_RotationMatrix + pr_TranslationVector;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Calculate plane gradient for a plane in 3D view space. */
|
|
|
|
void CSimpleProjection3D::MakeOoKGradient(const FLOATplane3D &plViewerPlane, CPlanarGradients &pgOoK) const
|
|
|
|
{
|
|
|
|
ASSERTALWAYS("Function not supported");
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* Clip a line.
|
|
|
|
*/
|
|
|
|
ULONG CSimpleProjection3D::ClipLine(FLOAT3D &v3dPoint0, FLOAT3D &v3dPoint1) const
|
|
|
|
{
|
|
|
|
// check that the projection object is prepared for projecting
|
|
|
|
ASSERT(pr_Prepared);
|
|
|
|
|
|
|
|
// line remains unclipped
|
|
|
|
return LCFVERTEX0(LCF_UNCLIPPED) | LCFVERTEX1(LCF_UNCLIPPED);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Get placement for a ray through a projected point.
|
|
|
|
*/
|
|
|
|
void CSimpleProjection3D::RayThroughPoint(const FLOAT3D &v3dViewPoint,
|
|
|
|
CPlacement3D &plRay) const
|
|
|
|
{
|
|
|
|
// check that the projection object is prepared for projecting
|
|
|
|
ASSERT(pr_Prepared);
|
|
|
|
|
|
|
|
ASSERTALWAYS("Not implemented!");
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check if an object-space plane is visible.
|
|
|
|
*/
|
|
|
|
BOOL CSimpleProjection3D::IsObjectPlaneVisible(const FLOATplane3D &p3dObjectPlane) const
|
|
|
|
{
|
|
|
|
// check that the projection object is prepared for projecting
|
|
|
|
ASSERT(pr_Prepared);
|
|
|
|
|
|
|
|
ASSERTALWAYS("Not implemented!");
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check if a viewer-space plane is visible.
|
|
|
|
*/
|
|
|
|
BOOL CSimpleProjection3D::IsViewerPlaneVisible(const FLOATplane3D &p3dViewerPlane) const
|
|
|
|
{
|
|
|
|
// check that the projection object is prepared for projecting
|
|
|
|
ASSERT(pr_Prepared);
|
|
|
|
// the object plane is visible is it is not heading away from the view plane
|
|
|
|
return p3dViewerPlane(3)>0.0f;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Calculate a mip-factor for a given object.
|
|
|
|
*/
|
|
|
|
// by its distance from viewer
|
|
|
|
FLOAT CSimpleProjection3D::MipFactor(FLOAT fDistance) const
|
|
|
|
{
|
|
|
|
// check that the projection object is prepared for projecting
|
|
|
|
ASSERT(pr_Prepared);
|
|
|
|
|
|
|
|
ASSERTALWAYS("Not implemented!");
|
|
|
|
return 0.0f;
|
|
|
|
}
|
|
|
|
// general mip-factor for target object
|
|
|
|
FLOAT CSimpleProjection3D::MipFactor(void) const
|
|
|
|
{
|
|
|
|
// check that the projection object is prepared for projecting
|
|
|
|
ASSERT(pr_Prepared);
|
|
|
|
|
|
|
|
ASSERTALWAYS("Not implemented!");
|
|
|
|
return 0.0f;
|
|
|
|
}
|
|
|
|
|