Initial commit

This commit is contained in:
2026-02-02 04:50:13 +01:00
commit 5b11698731
22592 changed files with 7677434 additions and 0 deletions

View File

@@ -0,0 +1,572 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 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, see <http://www.gnu.org/licenses/>.
*
*/
/*
* Copyright (C) 2006-2010 - Frictional Games
*
* This file is part of HPL1 Engine.
*/
#include "hpl1/engine/math/BoundingVolume.h"
#include "hpl1/engine/graphics/LowLevelGraphics.h"
#include "hpl1/engine/math/Math.h"
namespace hpl {
static constexpr cTriEdge kvBVEdges[12] = {
cTriEdge(1, 0, 0, 2),
cTriEdge(3, 1, 0, 5),
cTriEdge(2, 3, 0, 3),
cTriEdge(0, 2, 0, 4),
cTriEdge(0, 4, 4, 2),
cTriEdge(4, 6, 4, 1),
cTriEdge(6, 2, 4, 3),
cTriEdge(4, 5, 1, 2),
cTriEdge(5, 7, 1, 5),
cTriEdge(7, 6, 1, 3),
cTriEdge(1, 5, 2, 5),
cTriEdge(3, 7, 5, 3)};
static constexpr cVector3f globalNormals[6] = {
cVector3f(1, 0, 0),
cVector3f(-1, 0, 0),
cVector3f(0, 1, 0),
cVector3f(0, -1, 0),
cVector3f(0, 0, 1),
cVector3f(0, 0, -1)};
static bool globalfacingLight[6] = {false, false, false, false, false, false};
static const int kvFacePoints[6] = {0, 5, 5, 6, 4, 7};
//////////////////////////////////////////////////////////////////////////
// SHADOW VOLUME
//////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------
bool cShadowVolumeBV::CollideBoundingVolume(cBoundingVolume *aBV) {
// Do a simple sphere collide test
if (CollideBVSphere(aBV) == false)
return false;
return CollideBVAABB(aBV);
}
//-----------------------------------------------------------------------
bool cShadowVolumeBV::CollideBVSphere(cBoundingVolume *aBV) {
for (int i = 0; i < mlPlaneCount; ++i) {
float fDist = cMath::PlaneToPointDist(mvPlanes[i], aBV->GetWorldCenter());
if (fDist < -aBV->GetRadius()) {
return false;
}
}
return true;
}
//-----------------------------------------------------------------------
bool cShadowVolumeBV::CollideBVAABB(cBoundingVolume *aBV) {
cVector3f vMax = aBV->GetMax();
cVector3f vMin = aBV->GetMin();
// Get the corners from the AAB
cVector3f vCorners[9] = {
cVector3f(vMax.x, vMax.y, vMax.z),
cVector3f(vMax.x, vMax.y, vMin.z),
cVector3f(vMax.x, vMin.y, vMax.z),
cVector3f(vMax.x, vMin.y, vMin.z),
cVector3f(vMin.x, vMax.y, vMax.z),
cVector3f(vMin.x, vMax.y, vMin.z),
cVector3f(vMin.x, vMin.y, vMax.z),
cVector3f(vMin.x, vMin.y, vMin.z),
// The "fuling", add center as well...
aBV->GetPosition()};
// Go through all the planes
for (int i = 0; i < mlPlaneCount; i++) {
int lInCount = 9;
// bool bIsIn = true;
for (int j = 0; j < 9; j++) {
float fDist = cMath::PlaneToPointDist(mvPlanes[i], vCorners[j]);
if (fDist < 0) {
lInCount--;
// bIsIn = false;
}
}
if (lInCount == 0)
return false;
}
return true;
}
//-----------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////////
// CONSTRUCTORS
//////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------
cBoundingVolume::cBoundingVolume() {
m_mtxTransform = cMatrixf::Identity;
mvLocalMax = 0;
mvLocalMin = 0;
mvPosition = 0;
mvPivot = 0;
mvSize = 0;
mfRadius = 0;
mbPositionUpdated = true;
mbSizeUpdated = true;
mShadowVolume.mvPoints.reserve(8 * 4);
mbShadowPlanesNeedUpdate = true;
}
//-----------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////////
// PUBLIC METHODS
//////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------
cVector3f cBoundingVolume::GetMax() {
UpdateSize();
return mvWorldMax;
}
cVector3f cBoundingVolume::GetMin() {
UpdateSize();
return mvWorldMin;
}
//-----------------------------------------------------------------------
cVector3f cBoundingVolume::GetLocalMax() {
return mvLocalMax;
}
cVector3f cBoundingVolume::GetLocalMin() {
return mvLocalMin;
}
//-----------------------------------------------------------------------
void cBoundingVolume::SetLocalMinMax(const cVector3f &avMin, const cVector3f &avMax) {
mvLocalMax = avMax;
mvLocalMin = avMin;
mbSizeUpdated = true;
}
//-----------------------------------------------------------------------
cVector3f cBoundingVolume::GetLocalCenter() {
return mvPivot;
}
//-----------------------------------------------------------------------
cVector3f cBoundingVolume::GetWorldCenter() {
UpdateSize();
return m_mtxTransform.GetTranslation() + mvPivot;
}
//-----------------------------------------------------------------------
void cBoundingVolume::SetPosition(const cVector3f &avPos) {
m_mtxTransform.SetTranslation(avPos);
mbPositionUpdated = true;
}
//-----------------------------------------------------------------------
cVector3f cBoundingVolume::GetPosition() {
return m_mtxTransform.GetTranslation();
}
//-----------------------------------------------------------------------
void cBoundingVolume::SetTransform(const cMatrixf &a_mtxTransform) {
m_mtxTransform = a_mtxTransform;
mbSizeUpdated = true;
}
const cMatrixf &cBoundingVolume::GetTransform() {
return m_mtxTransform;
}
//-----------------------------------------------------------------------
void cBoundingVolume::SetSize(const cVector3f &avSize) {
mvLocalMax = avSize * 0.5;
mvLocalMin = avSize * -0.5;
mbSizeUpdated = true;
}
//-----------------------------------------------------------------------
cVector3f cBoundingVolume::GetSize() {
UpdateSize();
return mvSize;
}
//-----------------------------------------------------------------------
float cBoundingVolume::GetRadius() {
UpdateSize();
return mfRadius;
}
//-----------------------------------------------------------------------
cShadowVolumeBV *cBoundingVolume::GetShadowVolume(const cVector3f &avLightPos,
float afLightRange, bool abForceUpdate) {
if (cMath::PointBVCollision(avLightPos, *this))
return NULL;
if (!abForceUpdate && !mbShadowPlanesNeedUpdate)
return &mShadowVolume;
// Set size 0.
mShadowVolume.mvPoints.resize(0);
// Get the corners.
cVector3f vMax = GetMax();
cVector3f vMin = GetMin();
cVector3f vCorners[8];
vCorners[0] = cVector3f(vMax.x, vMax.y, vMax.z);
vCorners[1] = cVector3f(vMax.x, vMax.y, vMin.z);
vCorners[2] = cVector3f(vMax.x, vMin.y, vMax.z);
vCorners[3] = cVector3f(vMax.x, vMin.y, vMin.z);
vCorners[4] = cVector3f(vMin.x, vMax.y, vMax.z);
vCorners[5] = cVector3f(vMin.x, vMax.y, vMin.z);
vCorners[6] = cVector3f(vMin.x, vMin.y, vMax.z);
vCorners[7] = cVector3f(vMin.x, vMin.y, vMin.z);
/////////////////////////////////////////////////////////////////////
// Iterate the faces and check which ones are facing the light.
// int lNearPoint = -1;
mShadowVolume.mlPlaneCount = 0;
for (int face = 0; face < 6; face++) {
globalfacingLight[face] = cMath::Vector3Dot(globalNormals[face],
vCorners[kvFacePoints[face]] - avLightPos) < 0;
// Get a point for the near plane. (any edge point will do)
if (globalfacingLight[face]) {
mShadowVolume.mvPlanes[mShadowVolume.mlPlaneCount] = cPlanef(
globalNormals[face] * -1.0f, vCorners[kvFacePoints[face]]);
mShadowVolume.mlPlaneCount++;
}
}
mShadowVolume.mlCapPlanes = mShadowVolume.mlPlaneCount;
// The direction a point is pushed away in
cVector3f vDir;
// The length to push the shadow points.
float fPushLength = afLightRange * kSqrt2f;
//////////////////////////////////////////////////////////
// Iterate the edges and build quads from the silhouette
for (int edge = 0; edge < 12; edge++) {
const cTriEdge &Edge = kvBVEdges[edge];
const bool facingLight1 = globalfacingLight[Edge.tri1];
const bool facingLight2 = globalfacingLight[Edge.tri2];
if ((facingLight1 && !facingLight2) || (facingLight2 && !facingLight1)) {
if (facingLight1) {
mShadowVolume.mvPoints.push_back(vCorners[Edge.point1]);
mShadowVolume.mvPoints.push_back(vCorners[Edge.point2]);
vDir = (vCorners[Edge.point2] - avLightPos);
vDir.Normalise();
mShadowVolume.mvPoints.push_back(vCorners[Edge.point2] + vDir * fPushLength);
vDir = (vCorners[Edge.point1] - avLightPos);
vDir.Normalise();
mShadowVolume.mvPoints.push_back(vCorners[Edge.point1] + vDir * fPushLength);
} else {
mShadowVolume.mvPoints.push_back(vCorners[Edge.point2]);
mShadowVolume.mvPoints.push_back(vCorners[Edge.point1]);
vDir = (vCorners[Edge.point1] - avLightPos);
vDir.Normalise();
mShadowVolume.mvPoints.push_back(vCorners[Edge.point1] + vDir * fPushLength);
vDir = (vCorners[Edge.point2] - avLightPos);
vDir.Normalise();
mShadowVolume.mvPoints.push_back(vCorners[Edge.point2] + vDir * fPushLength);
}
}
}
/////////////////////////////////////
// Create the side planes:
for (int i = 0; i < (int)mShadowVolume.mvPoints.size(); i += 4) {
// Normal should point inwards
cVector3f vNormal = cMath::Vector3Cross(
mShadowVolume.mvPoints[i + 1] - mShadowVolume.mvPoints[i + 0],
mShadowVolume.mvPoints[i + 2] - mShadowVolume.mvPoints[i + 0]);
mShadowVolume.mvPlanes[mShadowVolume.mlPlaneCount].FromNormalPoint(vNormal,
mShadowVolume.mvPoints[i + 0]);
mShadowVolume.mvPlanes[mShadowVolume.mlPlaneCount].Normalise();
mShadowVolume.mlPlaneCount++;
}
return &mShadowVolume;
}
//-----------------------------------------------------------------------
void cBoundingVolume::DrawEdges(const cVector3f &avLightPos, float afLightRange, iLowLevelGraphics *apLowLevelGraphics) {
cShadowVolumeBV *pVolume = GetShadowVolume(avLightPos, afLightRange, false);
apLowLevelGraphics->SetBlendActive(true);
apLowLevelGraphics->SetBlendFunc(eBlendFunc_One, eBlendFunc_One);
apLowLevelGraphics->SetDepthWriteActive(false);
tVertexVec vVtx;
vVtx.resize(4);
for (int capplane = 0; capplane < mShadowVolume.mlCapPlanes; capplane++) {
mShadowVolume.mvPlanes[capplane].CalcNormal();
apLowLevelGraphics->DrawLine(GetWorldCenter(), GetWorldCenter() + mShadowVolume.mvPlanes[capplane].normal * -0.5f, cColor(1, 1, 1, 1));
}
int lPlane = mShadowVolume.mlCapPlanes;
for (int quad = 0; quad < (int)pVolume->mvPoints.size(); quad += 4) {
for (int i = 0; i < 4; i++)
vVtx[i].pos = pVolume->mvPoints[quad + i];
apLowLevelGraphics->DrawQuad(vVtx, cColor(0.2f, 0, 0.2f));
cVector3f vCenter = (vVtx[1].pos + vVtx[0].pos) * 0.5f;
mShadowVolume.mvPlanes[lPlane].CalcNormal();
apLowLevelGraphics->DrawLine(vCenter, vCenter + mShadowVolume.mvPlanes[lPlane].normal * -0.5f, cColor(1, 1, 1, 1));
lPlane++;
}
apLowLevelGraphics->SetBlendActive(false);
apLowLevelGraphics->SetDepthWriteActive(true);
}
//-----------------------------------------------------------------------
void cBoundingVolume::AddArrayPoints(const float *apArray, int alNumOfVectors) {
cBVTempArray temp;
temp.mpArray = apArray;
temp.mlSize = alNumOfVectors;
mlstArrays.push_back(temp);
}
//-----------------------------------------------------------------------
void cBoundingVolume::CreateFromPoints(int alStride) {
mvLocalMax = cVector3f(-100000, -100000, -100000);
mvLocalMin = cVector3f(100000, 100000, 100000);
for (tBVTempArrayListIt it = mlstArrays.begin(); it != mlstArrays.end(); it++) {
// Loop through all the vectors and find min and max
const float *apVec = it->mpArray;
int lNumOfVectors = it->mlSize;
while (lNumOfVectors) {
// Min and max X
if (apVec[0] < mvLocalMin.x)
mvLocalMin.x = apVec[0];
if (apVec[0] > mvLocalMax.x)
mvLocalMax.x = apVec[0];
// Min and max Y
if (apVec[1] < mvLocalMin.y)
mvLocalMin.y = apVec[1];
if (apVec[1] > mvLocalMax.y)
mvLocalMax.y = apVec[1];
// Min and max Z
if (apVec[2] < mvLocalMin.z)
mvLocalMin.z = apVec[2];
if (apVec[2] > mvLocalMax.z)
mvLocalMax.z = apVec[2];
apVec += alStride;
lNumOfVectors--;
}
}
mlstArrays.clear();
// Update the used size
mbPositionUpdated = true;
mbSizeUpdated = true;
}
//-----------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////////
// PRIVATE METHODS
//////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------
void cBoundingVolume::UpdateSize() {
if (mbSizeUpdated) {
cMatrixf mtxRot = m_mtxTransform.GetRotation();
// Transform the local corners
cVector3f vCorners[8];
vCorners[0] = cMath::MatrixMul(mtxRot, cVector3f(mvLocalMax.x, mvLocalMax.y, mvLocalMax.z));
vCorners[1] = cMath::MatrixMul(mtxRot, cVector3f(mvLocalMax.x, mvLocalMax.y, mvLocalMin.z));
vCorners[2] = cMath::MatrixMul(mtxRot, cVector3f(mvLocalMax.x, mvLocalMin.y, mvLocalMax.z));
vCorners[3] = cMath::MatrixMul(mtxRot, cVector3f(mvLocalMax.x, mvLocalMin.y, mvLocalMin.z));
vCorners[4] = cMath::MatrixMul(mtxRot, cVector3f(mvLocalMin.x, mvLocalMax.y, mvLocalMax.z));
vCorners[5] = cMath::MatrixMul(mtxRot, cVector3f(mvLocalMin.x, mvLocalMax.y, mvLocalMin.z));
vCorners[6] = cMath::MatrixMul(mtxRot, cVector3f(mvLocalMin.x, mvLocalMin.y, mvLocalMax.z));
vCorners[7] = cMath::MatrixMul(mtxRot, cVector3f(mvLocalMin.x, mvLocalMin.y, mvLocalMin.z));
mvMax = vCorners[0];
mvMin = vCorners[0];
// Calculate the transformed min and max
for (int i = 1; i < 8; i++) {
// X
if (vCorners[i].x < mvMin.x)
mvMin.x = vCorners[i].x;
else if (vCorners[i].x > mvMax.x)
mvMax.x = vCorners[i].x;
// Y
if (vCorners[i].y < mvMin.y)
mvMin.y = vCorners[i].y;
else if (vCorners[i].y > mvMax.y)
mvMax.y = vCorners[i].y;
// Z
if (vCorners[i].z < mvMin.z)
mvMin.z = vCorners[i].z;
else if (vCorners[i].z > mvMax.z)
mvMax.z = vCorners[i].z;
}
// Get the transformed size.
mvSize = mvMax - mvMin;
// Get the local pivot (or offset from origo).
mvPivot = mvMax - (mvSize * 0.5f);
// Get radius as pivot to localmax
mfRadius = cMath::Vector3Dist(mvPivot, mvMax);
mbSizeUpdated = false;
mbPositionUpdated = true;
}
if (mbPositionUpdated) {
mvWorldMax = m_mtxTransform.GetTranslation() + mvMax;
mvWorldMin = m_mtxTransform.GetTranslation() + mvMin;
mbPositionUpdated = false;
mbShadowPlanesNeedUpdate = true;
}
}
//-----------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////////
// SERIALIZE CLASS
//////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------
kBeginSerializeBase(cBoundingVolume)
kSerializeVar(m_mtxTransform, eSerializeType_Matrixf)
kSerializeVar(mvLocalMax, eSerializeType_Vector3f)
kSerializeVar(mvLocalMin, eSerializeType_Vector3f)
kSerializeVar(mvMax, eSerializeType_Vector3f)
kSerializeVar(mvMin, eSerializeType_Vector3f)
kSerializeVar(mvPivot, eSerializeType_Vector3f)
kSerializeVar(mvWorldMax, eSerializeType_Vector3f)
kSerializeVar(mvWorldMin, eSerializeType_Vector3f)
kSerializeVar(mvPosition, eSerializeType_Vector3f)
kSerializeVar(mvSize, eSerializeType_Vector3f)
kSerializeVar(mfRadius, eSerializeType_Float32)
kEndSerialize()
//-----------------------------------------------------------------------
/* OLD "NEAR PLANE CODE"
int lNearPoint =-1;
for(int face=0; face< 6; face++)
{
gvFaces[face].facingLight = cMath::Vector3Dot(gvFaces[face].normal,
vCorners[kvFacePoints[face]] - avLightPos)<0;
//Get a point for the near plane. (any edge point will do)
if(gvFaces[face].facingLight && lNearPoint<0)
{
lNearPoint = kvFacePoints[face];
}
}
//Build the near plane for the shadow.
cVector3f vLightNormal = GetWorldCenter() - avLightPos;
mShadowVolume.mvPlanes[0] = cPlanef(vLightNormal,vCorners[lNearPoint]);
mShadowVolume.mvPlanes[0].Normalise();
//The direction a point is pushed away in
cVector3f vDir;
float fPushLength = afLightRange*kSqrt2f;
//The number of planes created.
mShadowVolume.mlPlaneCount =1;*/
} // namespace hpl

View File

@@ -0,0 +1,135 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 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, see <http://www.gnu.org/licenses/>.
*
*/
/*
* Copyright (C) 2006-2010 - Frictional Games
*
* This file is part of HPL1 Engine.
*/
#ifndef HPL_BOUNDING_VOLUME_H
#define HPL_BOUNDING_VOLUME_H
#include "hpl1/engine/graphics/GraphicsTypes.h"
#include "hpl1/engine/math/MathTypes.h"
#include "hpl1/engine/system/SerializeClass.h"
#include "hpl1/engine/system/SystemTypes.h"
namespace hpl {
class iLowLevelGraphics;
class cBoundingVolume;
class cBVTempArray {
public:
const float *mpArray;
int mlSize;
};
enum eBVCollision {
eBVCollision_Inside,
eBVCollision_Outside,
eBVCollision_Intersect,
eBVCollision_LastEnum
};
typedef Common::List<cBVTempArray> tBVTempArrayList;
typedef tBVTempArrayList::iterator tBVTempArrayListIt;
class cShadowVolumeBV {
public:
cPlanef mvPlanes[12];
int mlPlaneCount;
tVector3fVec mvPoints;
int mlCapPlanes;
bool CollideBoundingVolume(cBoundingVolume *aBV);
private:
bool CollideBVSphere(cBoundingVolume *aBV);
bool CollideBVAABB(cBoundingVolume *aBV);
};
class cBoundingVolume : public iSerializable {
friend class cMath;
kSerializableClassInit(cBoundingVolume) public : cBoundingVolume();
cVector3f GetMax();
cVector3f GetMin();
cVector3f GetLocalMax();
cVector3f GetLocalMin();
void SetLocalMinMax(const cVector3f &mvMin, const cVector3f &mvMax);
void SetPosition(const cVector3f &avPos);
cVector3f GetPosition();
void SetSize(const cVector3f &avSize);
cVector3f GetSize();
void SetTransform(const cMatrixf &a_mtxTransform);
const cMatrixf &GetTransform();
cVector3f GetLocalCenter();
cVector3f GetWorldCenter();
float GetRadius();
void AddArrayPoints(const float *apArray, int alNumOfVectors);
void CreateFromPoints(int alStride);
cShadowVolumeBV *GetShadowVolume(const cVector3f &avLightPos, float afLightRange, bool abForceUpdate);
// Debug:
void DrawEdges(const cVector3f &avLightPos, float afLightRange, iLowLevelGraphics *apLowLevelGraphics);
void UpdateSize();
cMatrixf m_mtxTransform;
cVector3f mvLocalMax;
cVector3f mvLocalMin;
cVector3f mvMax;
cVector3f mvMin;
cVector3f mvPivot;
cVector3f mvWorldMax;
cVector3f mvWorldMin;
cVector3f mvPosition;
cVector3f mvSize;
float mfRadius;
private:
bool mbPositionUpdated;
bool mbSizeUpdated;
tBVTempArrayList mlstArrays;
cShadowVolumeBV mShadowVolume;
bool mbShadowPlanesNeedUpdate;
};
} // namespace hpl
#endif // HPL_BOUNDING_VOLUME_H

View File

@@ -0,0 +1,412 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 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, see <http://www.gnu.org/licenses/>.
*
*/
/*
* Copyright (C) 2006-2010 - Frictional Games
*
* This file is part of HPL1 Engine.
*/
#include "hpl1/engine/math/Frustum.h"
#include "hpl1/engine/graphics/LowLevelGraphics.h"
#include "hpl1/engine/math/Math.h"
#include "hpl1/engine/system/low_level_system.h"
namespace hpl {
//////////////////////////////////////////////////////////////////////////
// CONSTRUCTORS
//////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------
cFrustum::cFrustum() {
}
//-----------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////////
// PUBLIC METHODS
//////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------
void cFrustum::SetViewProjMatrix(const cMatrixf &a_mtxProj, const cMatrixf &a_mtxView,
float afFarPlane, float afNearPlane, float afFOV, float afAspect,
const cVector3f &avOrigin, bool abInfFarPlane) {
m_mtxViewProj = cMath::MatrixMul(a_mtxProj, a_mtxView);
m_mtxModelView = a_mtxView;
mfFarPlane = afFarPlane;
mfNearPlane = afNearPlane;
mfFOV = afFOV;
mfAspect = afAspect;
mvOrigin = avOrigin;
mbInfFarPlane = abInfFarPlane;
// This could be made more accurate.
mOriginBV.SetSize(afNearPlane * 2);
mOriginBV.SetPosition(mvOrigin);
UpdatePlanes();
UpdateSphere();
UpdateEndPoints();
UpdateBV();
}
//-----------------------------------------------------------------------
cPlanef cFrustum::GetPlane(eFrustumPlane aType) {
return mPlane[aType];
}
//-----------------------------------------------------------------------
eFrustumCollision cFrustum::CollideBoundingVolume(cBoundingVolume *aBV) {
// Check if the BV is in the Frustum sphere.
if (CollideFustrumSphere(aBV) == eFrustumCollision_Outside) {
return eFrustumCollision_Outside;
}
// Do a simple sphere collide test
eFrustumCollision ret = CollideBVSphere(aBV);
// If there was an intersection, collide with the AABB
if (ret == eFrustumCollision_Intersect) {
return CollideBVAABB(aBV);
}
return ret;
}
//-----------------------------------------------------------------------
bool cFrustum::CheckLineIntersection(const cVector3f &avPoint1, const cVector3f &avPoint2) {
return cMath::CheckFrustumLineIntersection(&mPlane[0], avPoint1, avPoint2, 3);
}
//-----------------------------------------------------------------------
bool cFrustum::CheckQuadMeshIntersection(tVector3fVec *apPoints) {
return cMath::CheckFrustumQuadMeshIntersection(&mPlane[0], apPoints, 3);
}
//-----------------------------------------------------------------------
bool cFrustum::CheckVolumeIntersection(cShadowVolumeBV *apVolume) {
if (CheckQuadMeshIntersection(&apVolume->mvPoints)) {
return true;
}
// The first shadow plane is the near plane which we can skip.
int lPairNum = (apVolume->mlPlaneCount - 1) / 2;
// Check with volume planes.
for (int i = 0; i < 4; ++i) {
if (cMath::CheckFrustumLineIntersection(&apVolume->mvPlanes[1], mvOrigin, mvEndPoints[i],
lPairNum)) {
return true;
}
}
return false;
}
//-----------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////////
// PRIVATE METHODS
//////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------
eFrustumCollision cFrustum::CollideFustrumSphere(cBoundingVolume *aBV) {
float fRadiusSum = mBoundingSphere.r + aBV->GetRadius();
cVector3f vSepAxis = mBoundingSphere.center - aBV->GetWorldCenter();
if (vSepAxis.SqrLength() > (fRadiusSum * fRadiusSum)) {
return eFrustumCollision_Outside;
}
return eFrustumCollision_Intersect;
}
//-----------------------------------------------------------------------
eFrustumCollision cFrustum::CollideBVSphere(cBoundingVolume *aBV) {
int lPlanes = 6;
if (mbInfFarPlane)
lPlanes = 5;
for (int i = 0; i < lPlanes; i++) {
float fDist = cMath::PlaneToPointDist(mPlane[i], aBV->GetWorldCenter());
if (fDist < -aBV->GetRadius()) {
return eFrustumCollision_Outside;
}
if (ABS(fDist) < aBV->GetRadius()) {
return eFrustumCollision_Intersect;
}
}
return eFrustumCollision_Inside;
}
//-----------------------------------------------------------------------
eFrustumCollision cFrustum::CollideBVAABB(cBoundingVolume *aBV) {
cVector3f vMax = aBV->GetMax();
cVector3f vMin = aBV->GetMin();
// Get the corners from the AAB
cVector3f vCorners[9] = {
cVector3f(vMax.x, vMax.y, vMax.z),
cVector3f(vMax.x, vMax.y, vMin.z),
cVector3f(vMax.x, vMin.y, vMax.z),
cVector3f(vMax.x, vMin.y, vMin.z),
cVector3f(vMin.x, vMax.y, vMax.z),
cVector3f(vMin.x, vMax.y, vMin.z),
cVector3f(vMin.x, vMin.y, vMax.z),
cVector3f(vMin.x, vMin.y, vMin.z),
// The "fuling", add center as well...
aBV->GetPosition()};
int lTotalIn = 0;
int lPlanes = 6;
if (mbInfFarPlane)
lPlanes = 5;
// Go through all the planes
for (int i = 0; i < lPlanes; i++) {
int lInCount = 9;
bool bIsIn = true;
for (int j = 0; j < 9; j++) {
float fDist = cMath::PlaneToPointDist(mPlane[i], vCorners[j]);
if (fDist < 0) {
lInCount--;
bIsIn = false;
}
}
if (lInCount == 0)
return eFrustumCollision_Outside;
if (bIsIn)
lTotalIn++;
}
if (lTotalIn == lPlanes)
return eFrustumCollision_Inside;
return eFrustumCollision_Intersect;
}
//-----------------------------------------------------------------------
void cFrustum::UpdateSphere() {
// calculate the radius of the frustum sphere
float fViewLen = mfFarPlane - mfNearPlane;
float fHeight = fViewLen * tan(mfFOV * 0.5f);
float fWidth = fHeight * mfAspect;
// halfway point between near/far planes starting at the origin and extending along the z axis
cVector3f P(0.0f, 0.0f, mfNearPlane + fViewLen * 0.5f);
// the calculate far corner of the frustum
cVector3f Q(fWidth, fHeight, fViewLen);
// the vector between P and Q
cVector3f vDiff = P - Q;
// the radius becomes the length of this vector
float fRadius = vDiff.Length();
// get the look vector of the camera from the view matrix
cVector3f vLookVector = m_mtxModelView.GetForward() * -1;
// calculate the center of the sphere
cVector3f vCenter = (mvOrigin) + (vLookVector * (fViewLen * 0.5f + mfNearPlane));
mBoundingSphere = cSpheref(vCenter, fRadius);
}
//-----------------------------------------------------------------------
void cFrustum::UpdatePlanes() {
// Left
mPlane[eFrustumPlane_Left] = cPlanef(m_mtxViewProj.m[3][0] + m_mtxViewProj.m[0][0],
m_mtxViewProj.m[3][1] + m_mtxViewProj.m[0][1],
m_mtxViewProj.m[3][2] + m_mtxViewProj.m[0][2],
m_mtxViewProj.m[3][3] + m_mtxViewProj.m[0][3]);
// Right
mPlane[eFrustumPlane_Right] = cPlanef(m_mtxViewProj.m[3][0] - m_mtxViewProj.m[0][0],
m_mtxViewProj.m[3][1] - m_mtxViewProj.m[0][1],
m_mtxViewProj.m[3][2] - m_mtxViewProj.m[0][2],
m_mtxViewProj.m[3][3] - m_mtxViewProj.m[0][3]);
// Bottom
mPlane[eFrustumPlane_Bottom] = cPlanef(m_mtxViewProj.m[3][0] + m_mtxViewProj.m[1][0],
m_mtxViewProj.m[3][1] + m_mtxViewProj.m[1][1],
m_mtxViewProj.m[3][2] + m_mtxViewProj.m[1][2],
m_mtxViewProj.m[3][3] + m_mtxViewProj.m[1][3]);
// Top
mPlane[eFrustumPlane_Top] = cPlanef(m_mtxViewProj.m[3][0] - m_mtxViewProj.m[1][0],
m_mtxViewProj.m[3][1] - m_mtxViewProj.m[1][1],
m_mtxViewProj.m[3][2] - m_mtxViewProj.m[1][2],
m_mtxViewProj.m[3][3] - m_mtxViewProj.m[1][3]);
// Near
mPlane[eFrustumPlane_Near] = cPlanef(m_mtxViewProj.m[3][0] + m_mtxViewProj.m[2][0],
m_mtxViewProj.m[3][1] + m_mtxViewProj.m[2][1],
m_mtxViewProj.m[3][2] + m_mtxViewProj.m[2][2],
m_mtxViewProj.m[3][3] + m_mtxViewProj.m[2][3]);
// Far
mPlane[eFrustumPlane_Far] = cPlanef(m_mtxViewProj.m[3][0] - m_mtxViewProj.m[2][0],
m_mtxViewProj.m[3][1] - m_mtxViewProj.m[2][1],
m_mtxViewProj.m[3][2] - m_mtxViewProj.m[2][2],
m_mtxViewProj.m[3][3] - m_mtxViewProj.m[2][3]);
for (int i = 0; i < 6; i++) {
mPlane[i].Normalise();
mPlane[i].CalcNormal();
}
}
//-----------------------------------------------------------------------
void cFrustum::UpdateEndPoints() {
float fXAngle = mfFOV * 0.5f;
float fYAngle = mfFOV * 0.5f * mfAspect;
cVector3f vForward = m_mtxModelView.GetForward();
// cVector3f vUp = m_mtxModelView.GetUp();
cVector3f vRight = m_mtxModelView.GetRight();
// Point the forward vec in different dirs.
cVector3f vUpDir = cMath::MatrixMul(cMath::MatrixQuaternion(cQuaternion(fXAngle, vRight)), vForward);
cVector3f vDownDir = cMath::MatrixMul(cMath::MatrixQuaternion(cQuaternion(-fXAngle, vRight)), vForward);
// cVector3f vRightDir = cMath::MatrixMul(cMath::MatrixQuaternion(cQuaternion(fYAngle,vUp)), vForward);
// cVector3f vLeftDir = cMath::MatrixMul(cMath::MatrixQuaternion(cQuaternion(-fYAngle,vUp)), vForward);
vForward = vForward * -1;
float fRightAdd = sin(fYAngle);
// float fUpAdd = sin(fXAngle);
cVector3f vVec0 = vUpDir + vRight * fRightAdd;
cVector3f vVec2 = vDownDir + vRight * fRightAdd;
cVector3f vVec3 = vDownDir + vRight * -fRightAdd;
cVector3f vVec1 = vUpDir + vRight * -fRightAdd;
/*cVector3f vVec0 = vUpDir;//cMath::Vector3Normalize(vUpDir+vRightDir);
cVector3f vVec1 = vRightDir;//cMath::Vector3Normalize(vUpDir+vLeftDir);
cVector3f vVec2 = vDownDir;//cMath::Vector3Normalize(vDownDir+vLeftDir);
cVector3f vVec3 = vLeftDir;//cMath::Vector3Normalize(vDownDir+vRightDir);*/
// angles between forward and the vectors
float fAngle0 = cMath::Vector3Angle(vVec0, vForward);
float fAngle1 = cMath::Vector3Angle(vVec1, vForward);
float fAngle2 = cMath::Vector3Angle(vVec2, vForward);
float fAngle3 = cMath::Vector3Angle(vVec3, vForward);
// create end points.
mvEndPoints[0] = mvOrigin + vVec0 * (mfFarPlane / cos(fAngle0));
mvEndPoints[1] = mvOrigin + vVec1 * (mfFarPlane / cos(fAngle1));
mvEndPoints[2] = mvOrigin + vVec2 * (mfFarPlane / cos(fAngle2));
mvEndPoints[3] = mvOrigin + vVec3 * (mfFarPlane / cos(fAngle3));
/*mvEndPoints[0] = mvOrigin + (vUpDir+vRightDir) * mfFarPlane *-1;
mvEndPoints[1] = mvOrigin + (vUpDir+vLeftDir) * mfFarPlane*-1;
mvEndPoints[2] = mvOrigin + (vDownDir+vRightDir)* mfFarPlane*-1;
mvEndPoints[3] = mvOrigin + (vDownDir+vLeftDir) * mfFarPlane*-1;*/
}
//-----------------------------------------------------------------------
void cFrustum::UpdateBV() {
cVector3f vMin = mvOrigin;
cVector3f vMax = mvOrigin;
for (int i = 0; i < 4; i++) {
if (vMax.x < mvEndPoints[i].x)
vMax.x = mvEndPoints[i].x;
else if (vMin.x > mvEndPoints[i].x)
vMin.x = mvEndPoints[i].x;
if (vMax.y < mvEndPoints[i].y)
vMax.y = mvEndPoints[i].y;
else if (vMin.y > mvEndPoints[i].y)
vMin.y = mvEndPoints[i].y;
if (vMax.z < mvEndPoints[i].z)
vMax.z = mvEndPoints[i].z;
else if (vMin.z > mvEndPoints[i].z)
vMin.z = mvEndPoints[i].z;
}
mBoundingVolume.SetLocalMinMax(vMin, vMax);
}
//-----------------------------------------------------------------------
const cVector3f &cFrustum::GetOrigin() {
return mvOrigin;
}
//-----------------------------------------------------------------------
cBoundingVolume *cFrustum::GetOriginBV() {
return &mOriginBV;
}
//-----------------------------------------------------------------------
cVector3f cFrustum::GetForward() {
return m_mtxModelView.GetForward();
}
//-----------------------------------------------------------------------
void cFrustum::Draw(iLowLevelGraphics *apLowLevelGraphics) {
apLowLevelGraphics->DrawLine(mvOrigin, mvEndPoints[0], cColor(1, 1, 1, 1));
apLowLevelGraphics->DrawLine(mvOrigin, mvEndPoints[1], cColor(1, 1, 1, 1));
apLowLevelGraphics->DrawLine(mvOrigin, mvEndPoints[2], cColor(1, 1, 1, 1));
apLowLevelGraphics->DrawLine(mvOrigin, mvEndPoints[3], cColor(1, 1, 1, 1));
apLowLevelGraphics->DrawLine(mvEndPoints[0], mvEndPoints[1], cColor(1, 1, 1, 1));
apLowLevelGraphics->DrawLine(mvEndPoints[1], mvEndPoints[2], cColor(1, 1, 1, 1));
apLowLevelGraphics->DrawLine(mvEndPoints[2], mvEndPoints[3], cColor(1, 1, 1, 1));
apLowLevelGraphics->DrawLine(mvEndPoints[3], mvEndPoints[0], cColor(1, 1, 1, 1));
apLowLevelGraphics->DrawLine(mvEndPoints[0], mvEndPoints[2], cColor(1, 1, 1, 1));
apLowLevelGraphics->DrawLine(mvEndPoints[1], mvEndPoints[3], cColor(1, 1, 1, 1));
}
//-----------------------------------------------------------------------
} // namespace hpl

View File

@@ -0,0 +1,125 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 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, see <http://www.gnu.org/licenses/>.
*
*/
/*
* Copyright (C) 2006-2010 - Frictional Games
*
* This file is part of HPL1 Engine.
*/
#ifndef HPL_FRUSTUM_H
#define HPL_FRUSTUM_H
#include "hpl1/engine/graphics/GraphicsTypes.h"
#include "hpl1/engine/math/BoundingVolume.h"
#include "hpl1/engine/math/MathTypes.h"
#include "hpl1/engine/system/SystemTypes.h"
namespace hpl {
class iLowLevelGraphics;
enum eFrustumPlane {
eFrustumPlane_Left = 0,
eFrustumPlane_Right = 1,
eFrustumPlane_Bottom = 2,
eFrustumPlane_Top = 3,
eFrustumPlane_Near = 4,
eFrustumPlane_Far = 5,
eFrustumPlane_LastEnum = 7,
};
enum eFrustumCollision {
eFrustumCollision_Inside,
eFrustumCollision_Outside,
eFrustumCollision_Intersect,
eFrustumCollision_LastEnum
};
class cFrustum {
public:
cFrustum();
void SetViewProjMatrix(const cMatrixf &a_mtxProj, const cMatrixf &a_mtxView,
float afFarPlane, float afNearPlane, float afFOV, float afAspect,
const cVector3f &avOrigin, bool abInfFarPlane = false);
cPlanef GetPlane(eFrustumPlane aType);
eFrustumCollision CollideBoundingVolume(cBoundingVolume *aBV);
eFrustumCollision CollideFustrumSphere(cBoundingVolume *aBV);
eFrustumCollision CollideBVSphere(cBoundingVolume *aBV);
eFrustumCollision CollideBVAABB(cBoundingVolume *aBV);
/**
* Checks intersection with a line
*/
bool CheckLineIntersection(const cVector3f &avPoint1, const cVector3f &avPoint2);
/**
* Checks intersection with a quad mesh.
* \param apPoints the points of the quad mesh, every 4 points is a face.
*/
bool CheckQuadMeshIntersection(tVector3fVec *apPoints);
bool CheckVolumeIntersection(cShadowVolumeBV *apVolume);
cSpheref GetBoundingSphere() { return mBoundingSphere; }
const cBoundingVolume &GetBoundingVolume() { return mBoundingVolume; }
const cVector3f &GetOrigin();
cBoundingVolume *GetOriginBV();
cVector3f GetForward();
void Draw(iLowLevelGraphics *apLowLevelGraphics);
private:
void UpdatePlanes();
void UpdateSphere();
void UpdateEndPoints();
void UpdateBV();
float mfFarPlane;
float mfNearPlane;
float mfAspect;
float mfFOV;
bool mbInfFarPlane;
cVector3f mvOrigin;
cBoundingVolume mOriginBV;
cMatrixf m_mtxViewProj;
cMatrixf m_mtxModelView;
cPlanef mPlane[6];
cSpheref mBoundingSphere;
cBoundingVolume mBoundingVolume;
cVector3f mvEndPoints[4];
tVector3fVec mvPoints;
};
} // namespace hpl
#endif // HPL_FRUSTUM_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,501 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 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, see <http://www.gnu.org/licenses/>.
*
*/
/*
* Copyright (C) 2006-2010 - Frictional Games
*
* This file is part of HPL1 Engine.
*/
#ifndef HPL_MATH_H
#define HPL_MATH_H
#include "hpl1/engine/math/BoundingVolume.h"
#include "hpl1/engine/math/MathTypes.h"
#include "hpl1/engine/math/MeshTypes.h"
#include "hpl1/engine/graphics/Color.h"
namespace hpl {
class cMath {
public:
//////////////////////////////////////////////////////
////////// RANDOM GENERATION ////////////////////////
//////////////////////////////////////////////////////
/**
* Generates a random integer from min to max
* \param alMin
* \param alMax
* \return
*/
static int RandRectl(int alMin, int alMax);
/**
* Generates a random float from min to max
* \param alMin
* \param alMax
* \return
*/
static float RandRectf(float alMin, float alMax);
/**
* Generates a random float from min to max
*/
static cVector2f RandRectVector2f(const cVector3f &avMin, const cVector3f &avMax);
/**
* Generates a random float from min to max
*/
static cVector3f RandRectVector3f(const cVector3f &avMin, const cVector3f &avMax);
/**
* Generates a random float from min to max
*/
static cColor RandRectColor(const cColor &aMin, const cColor &aMax);
/**
* Randomize the rand funcs.
* \param alSeed the seed, -1 = random seed.
*/
static void Randomize(int alSeed = -1);
//////////////////////////////////////////////////////
////////// COLLSION //////////////////////////////////
//////////////////////////////////////////////////////
static bool BoxCollision(cRect2l aRect1, cRect2l aRect2);
static bool BoxCollision(cRect2f aRect1, cRect2f aRect2);
static bool PointBoxCollision(cVector2f avPoint, cRect2f aRect);
static bool BoxFit(cRect2l aRectSrc, cRect2l aRectDest);
static bool BoxFit(cRect2f aRectSrc, cRect2f aRectDest);
static float Dist2D(const cVector2f &avPosA, const cVector2f &avPosB);
static float Dist2D(const cVector3f &avPosA, const cVector3f &avPosB);
static float SqrDist2D(const cVector2f &avPosA, const cVector2f &avPosB);
static float SqrDist2D(const cVector3f &avPosA, const cVector3f &avPosB);
static cRect2f &ClipRect(cRect2f &aRectSrc, const cRect2f &aRectDest);
/**
* Checks collison between two bounding volumes.
* \return true if collision, else false.
*/
static bool CheckCollisionBV(cBoundingVolume &aBV1, cBoundingVolume &aBV2);
static bool PointBVCollision(const cVector3f &avPoint, cBoundingVolume &aBV2);
/**
* Creates a clip rect for a bounding volume in screen space.
* \return false if behind near clip.
*/
static bool GetClipRectFromBV(cRect2l &aDestRect, cBoundingVolume &aBV,
const cMatrixf &a_mtxView, const cMatrixf &a_mtxProj,
float afNearClipPlane, const cVector2l &avScreenSize);
static bool CheckSphereInPlanes(const cVector3f &avCenter, float afRadius,
const cPlanef *apPlanes, int alPlaneCount);
//////////////////////////////////////////////////////
////////// FLOAT OPERATIONS ////////////////////////
//////////////////////////////////////////////////////
/**
* Get fraction part of a float
* \param afVal
* \return
*/
static float GetFraction(float afVal);
/**
* Moldus (%) of a float
* \param afDividend
* \param afDivisor
* \return
*/
static float Modulus(float afDividend, float afDivisor);
static float ToRad(float afAngle);
static float ToDeg(float afAngle);
/**
* Get the Log 2 of an int.
*/
static int Log2ToInt(int alX);
/**
* Checks if the number is a power of two.
*/
static bool IsPow2(int alX);
/**
* Wraps a value (afX) between min and max. Example: Wrap(-1, 0,10) returns 9.
* \param afMin The minimum value. Must be lower than max.
* \param afMax The maximum value. Must be higher than min and NOT 0.
*/
static float Wrap(float afX, float afMin, float afMax);
/**
* Clamps a value between min and max. Example Clamp(-1, 0,1) return 0.
*/
static float Clamp(float afX, float afMin, float afMax);
inline static float Max(float afX, float afY) {
if (afX > afY)
return afX;
return afY;
}
inline static float Min(float afX, float afY) {
if (afX < afY)
return afX;
return afY;
}
inline static int Max(int alX, int alY) {
if (alX > alY)
return alX;
return alY;
}
inline static int Min(int alX, int alY) {
if (alX < alY)
return alX;
return alY;
}
inline static float Abs(float afX) { return afX < 0 ? -afX : afX; }
inline static int Abs(int alX) { return alX < 0 ? -alX : alX; }
static float GetAngleDistance(float afAngle1, float afAngle2, float afMaxAngle);
static float GetAngleDistanceRad(float afAngle1, float afAngle2);
static float GetAngleDistanceDeg(float afAngle1, float afAngle2);
static float TurnAngle(float afAngle, float afFinalAngle, float afSpeed, float afMaxAngle);
static float TurnAngleRad(float afAngle, float afFinalAngle, float afSpeed);
static float TurnAngleDeg(float afAngle, float afFinalAngle, float afSpeed);
static float InterpolateFloat(float afA, float afB, float afT);
template<typename Vector>
static decltype(Vector::x) & GetVectorX(Vector &v) {
return v.x;
}
template<typename Vector>
static decltype(Vector::y) & GetVectorY(Vector &v) {
return v.y;
}
template<typename Vector>
static decltype(Vector::z) & GetVectorZ(Vector &v) {
return v.z;
}
//////////////////////////////////////////////////////
////////// VECTOR 2D ///////////////////////////////
//////////////////////////////////////////////////////
/**
* Get the angle a vector at aStartPos has to have to look at aGoalPos
* \param &aStartPos
* \param &avGoalPos
* \return
*/
static float GetAngleFromPoints2D(const cVector2f &aStartPos, const cVector2f &avGoalPos);
/**
* Get a vector from an angle and a length
* \param afAngle
* \param afLength
* \return
*/
static cVector2f GetVectorFromAngle2D(float afAngle, float afLength);
/**
* Get angle and length of a vector
* \param &avVec
* \param *apAngle
* \param *apLength
*/
static void GetAngleFromVector(const cVector2f &avVec, float *apAngle, float *apLength);
/**
* Project Src on Dest
* \param &avSrcVec
* \param &avDestVec
* \return
*/
static cVector2f ProjectVector2D(const cVector2f &avSrcVec, const cVector2f &avDestVec);
//////////////////////////////////////////////////////
////////// VECTOR 3D ///////////////////////////////
//////////////////////////////////////////////////////
static inline cVector3f Vector3ToRad(const cVector3f &avVec) {
return cVector3f(ToRad(avVec.x), ToRad(avVec.y), ToRad(avVec.z));
}
static inline cVector3f Vector3ToDeg(const cVector3f &avVec) {
return cVector3f(ToDeg(avVec.x), ToDeg(avVec.y), ToDeg(avVec.z));
}
static inline cVector3f Vector3Normalize(const cVector3f &avVec) {
cVector3f vNorm = avVec;
vNorm.Normalise();
return vNorm;
}
static inline float Vector3DistSqr(const cVector3f &avStartPos, const cVector3f &avEndPos) {
float fDX = avEndPos.x - avStartPos.x;
float fDY = avEndPos.y - avStartPos.y;
float fDZ = avEndPos.z - avStartPos.z;
return fDX * fDX + fDY * fDY + fDZ * fDZ;
}
static inline float Vector3Dist(const cVector3f &avStartPos, const cVector3f &avEndPos) {
return sqrt(Vector3DistSqr(avStartPos, avEndPos));
}
static cVector3f GetAngleFromPoints3D(const cVector3f &avStartPos, const cVector3f &avGoalPos);
/**
* Vector cross product, A x B = R
* \param avVecA
* \param avVecB
* \return
*/
static cVector3f Vector3Cross(const cVector3f &avVecA, const cVector3f &avVecB);
/**
* Vector dot product, A * B = R
* \param avVecA
* \param avVecB
* \return
*/
static float Vector3Dot(const cVector3f &avVecA, const cVector3f &avVecB);
/**
* Project Src on Dest
* \param &avSrcVec, must be normalized
* \param &avDestVec, must be normalized
* \return
*/
static cVector3f ProjectVector3D(const cVector3f &avSrcVec, const cVector3f &avDestVec);
/**
* Calculates the angle between two vectors.
* \param avVecA
* \param avVecB
* \return
*/
static float Vector3Angle(const cVector3f &avVecA, const cVector3f &avVecB);
/**
* Unprojects a vector from screen size and coords.
*/
static cVector3f Vector3UnProject(const cVector3f &avVec, const cRect2f &aScreenRect,
cMatrixf a_mtxViewProj);
/**
* Calculates distance from a point to a plane
* \param aPlane The plane must be normalised!
* \param avVec
* \return >0 if in front of plane, 0 if on plane and <0 if behind plane
*/
static float PlaneToPointDist(const cPlanef &aPlane, const cVector3f &avVec);
/**
* Get the line defining the intersection of 2 planes.
* \param aPA
* \param aPB
* \param avDir The direction of the line will be placed here
* \param avPoint A point on the line will be placed here.
*/
static void PlaneIntersectionLine(const cPlanef &aPA, const cPlanef &aPB,
cVector3f &avDir, cVector3f &avPoint);
/**
* Checks intersection with a frustum, an array of alPairNum plane pairs(alPairNum*2 planes), and a line,
*/
static bool CheckFrustumLineIntersection(const cPlanef *apPlanePairs, const cVector3f &avPoint1,
const cVector3f &avPoint2, int alPairNum);
/**
* Checks intersection with a a frustum, an array of alPairNum plane pairs(alPairNum * 2 planes), and a quad mesh.
* \param apPoints the points of the quad mesh, every 4 points is a face.
*/
static bool CheckFrustumQuadMeshIntersection(const cPlanef *apPlanePairs, tVector3fVec *apPoints,
int alPairNum);
//////////////////////////////////////////////////////
////////// QUATERNIONS ///////////////////////////////
//////////////////////////////////////////////////////
/**
* Spherical Linear Interpolation between quaternions A and B
* \param afT The amount in-between the quaternions. 0.0 is A and 1 is B.
* \param abShortestPath Move the the shortest path.
* \return
*/
static cQuaternion QuaternionSlerp(float afT, const cQuaternion &aqA, const cQuaternion &aqB,
bool abShortestPath);
static float QuaternionDot(const cQuaternion &aqA, const cQuaternion &aqB);
//////////////////////////////////////////////////////
////////// MATRIX ////////////////////////////////////
//////////////////////////////////////////////////////
/**
* Spherical Linear Interpolation between matrix A and B
* \param afT The amount in-between the quaternions. 0.0 is A and 1 is B.
* \param abShortestPath Move the the shortest path.
* \return
*/
static cMatrixf MatrixSlerp(float afT, const cMatrixf &a_mtxA, const cMatrixf &a_mtxB,
bool abShortestPath);
/**
* Matrix mulitplication, A * B = R. This means that B is applied BEFORE A.
*/
static cMatrixf MatrixMul(const cMatrixf &a_mtxA, const cMatrixf &a_mtxB);
/**
* Multiply and matrix and a 3d vector
*/
static cVector3f MatrixMul(const cMatrixf &a_mtxA, const cVector3f &avB);
/**
* Multiply and matrix and a 3d vector and divide the result with W.
*/
static cVector3f MatrixMulDivideW(const cMatrixf &a_mtxA, const cVector3f &avB);
/**
* Multiply matrix and a float.
*/
static cMatrixf MatrixMulScalar(const cMatrixf &a_mtxA, float afB);
/**
* Creates a rotation matrix along all axes according to order.
*/
static cMatrixf MatrixRotate(cVector3f avRot, eEulerRotationOrder aOrder);
/**
* Create a rotation matrix around the X-axis according to the right hand rule
*/
static cMatrixf MatrixRotateX(float afAngle);
/**
* Create a rotation matrix around the Y-axis according to the right hand rule
*/
static cMatrixf MatrixRotateY(float afAngle);
/**
* Create a rotation matrix around the Z-axis according to the right hand rule
*/
static cMatrixf MatrixRotateZ(float afAngle);
static cMatrixf MatrixScale(cVector3f avScale);
static cMatrixf MatrixTranslate(cVector3f avTrans);
/**
* Creates a matrix from a quaternion.
* \return
*/
static cMatrixf MatrixQuaternion(const cQuaternion &aqRot);
/**
* Get the minor of a matrix.
*/
static inline float MatrixMinor(const cMatrixf &a_mtxA,
const size_t r0, const size_t r1, const size_t r2,
const size_t c0, const size_t c1, const size_t c2);
/**
* Get the adjoint of a matrix.
*/
static inline cMatrixf MatrixAdjoint(const cMatrixf &a_mtxA);
/**
* Get the determinant of a matrix.
*/
static inline float MatrixDeterminant(const cMatrixf &a_mtxA);
/**
* Gets the inverse of a matrix.
*/
static cMatrixf MatrixInverse(const cMatrixf &a_mtxA);
/**
* Converts the matrix into Euler angles, XYZ only supported at the moment.
* \param &a_mtxA
* \param aOrder
*/
static cVector3f MatrixToEulerAngles(const cMatrixf &a_mtxA, eEulerRotationOrder aOrder);
/**
* Create a char string from the matrix
*/
static const char *MatrixToChar(const cMatrixf &a_mtxA);
//////////////////////////////////////////////////////
////////// POLYGONS //////////////////////////////////
//////////////////////////////////////////////////////
/**
* Creates an array with 4d tangent vectors for triangles. alIndexNum % 3 must be 0.
* \param apDestArray The destination array, must be 4 * number of vertices large
* \param apIndexArray The indices
* \param alIndexNum Number of indices
* \param apVertexArray Vertices indexed by the indices
* \param apTexArray The texture coords
* \param apNormalArray The normals
* \param alVertexNum Number of vertex, normals and texcoords.
* \return true if success, else false
*/
static bool CreateTriTangentVectors(float *apDestArray,
const unsigned int *apIndexArray, int alIndexNum,
const float *apVertexArray, int alVtxStride,
const float *apTexArray,
const float *apNormalArray, int alVertexNum);
/**
* Creates triangle data for a triangle mesh. alIndexNum % 3 must be 0.
* \param avTriangles Where the data will be stored. If empty, this function resizes it.
* \param apIndexArray The indices
* \param alIndexNum Number of indices
* \param apVertexArray Vertices indexed by the indices
* \param alVertexNum Number of vertices
* \return true if success, else false
*/
static bool CreateTriangleData(tTriangleDataVec &avTriangles,
const unsigned int *apIndexArray, int alIndexNum,
const float *apVertexArray, int alVtxStride, int alVertexNum);
/**
* Creates edges for a triangle mesh. alIndexNum % 3 must be 0.
* \param avEdges An empty edge vector, this is where the edges will be stored.
* \param apIndexArray The indices
* \param alIndexNum Number of indices
* \param apVertexArray Vertices indexed by the indices
* \param alVertexNum Number of vertices
* \return true if success, else false
*/
static bool CreateEdges(tTriEdgeVec &avEdges,
const unsigned int *apIndexArray, int alIndexNum,
const float *apVertexArray, int alVtxStride, int alVertexNum,
bool *apIsDoubleSided);
};
} // namespace hpl
#endif // HPL_MATH_H

View File

@@ -0,0 +1,41 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 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, see <http://www.gnu.org/licenses/>.
*
*/
/*
* Copyright (C) 2006-2010 - Frictional Games
*
* This file is part of HPL1 Engine.
*/
#include "hpl1/engine/math/MathTypes.h"
namespace hpl {
template<>
const cMatrixf cMatrixf::Identity(1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1);
template<>
const cMatrixf cMatrixf::Zero(0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0);
} // namespace hpl

View File

@@ -0,0 +1,299 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 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, see <http://www.gnu.org/licenses/>.
*
*/
/*
* Copyright (C) 2006-2010 - Frictional Games
*
* This file is part of HPL1 Engine.
*/
#ifndef HPL_MATHTYPES_H
#define HPL_MATHTYPES_H
#include "common/array.h"
#include "common/list.h"
#include "hpl1/engine/math/Vector2.h"
#include "hpl1/engine/math/Vector3.h"
#include "hpl1/engine/math/hplMatrix.h"
#include "hpl1/engine/system/SystemTypes.h"
namespace hpl {
#define kPif (3.141592654f)
#define kPi2f (1.570796327f)
#define kPi4f (0.7853981634f)
#define k2Pif (6.283185307f)
#define kEpsilonf (0.0001f)
#define kSqrt2f (1.414213562f)
enum eEulerRotationOrder {
eEulerRotationOrder_XYZ,
eEulerRotationOrder_XZY,
eEulerRotationOrder_YXZ,
eEulerRotationOrder_YZX,
eEulerRotationOrder_ZXY,
eEulerRotationOrder_ZYX,
eEulerRotationOrder_LastEnum,
};
//-------------------------------------------
class cLinearOscillation {
public:
float max, min, val, up_speed, down_speed;
cLinearOscillation() {}
cLinearOscillation(float afMin, float afMax, float afVal, float afUpSpeed, float afDownSpeed) {
SetUp(afMin, afMax, afVal, afUpSpeed, afDownSpeed);
}
void SetUp(float afMin, float afMax, float afVal, float afUpSpeed, float afDownSpeed) {
min = afMin;
max = afMax;
val = afVal;
up_speed = ABS(afUpSpeed);
down_speed = -ABS(afDownSpeed);
add = up_speed;
}
void Update(float afTimeStep) {
val += add * afTimeStep;
if (add > 0) {
if (val >= max) {
val = max;
add = down_speed;
}
} else {
if (val <= min) {
val = min;
add = up_speed;
}
}
}
private:
float add;
};
//-------------------------------------------
template<class T>
class cPlane {
public:
T a, b, c, d;
cVector3<T> normal;
/////////////////
cPlane(T aA, T aB, T aC, T aD) {
a = aA;
b = aB;
c = aC;
d = aD;
}
cPlane() {
a = 0;
b = 0;
c = 0;
d = 0;
}
/////////////////
cPlane(const cVector3<T> &avNormal, const cVector3<T> &avPoint) {
FromNormalPoint(avNormal, avPoint);
}
/////////////////
cPlane(const cVector3<T> &avPoint0, const cVector3<T> &avPoint1,
const cVector3<T> &avPoint2) {
FromPoints(avPoint0, avPoint1, avPoint2);
}
/////////////////
inline void FromNormalPoint(const cVector3<T> &avNormal, const cVector3<T> &avPoint) {
a = avNormal.x;
b = avNormal.y;
c = avNormal.z;
// Dot product
d = -(avNormal.x * avPoint.x + avNormal.y * avPoint.y + avNormal.z * avPoint.z);
}
/////////////////
inline void FromPoints(const cVector3<T> &avPoint0, const cVector3<T> &avPoint1,
const cVector3<T> &avPoint2) {
cVector3<T> vEdge1 = avPoint1 - avPoint0;
cVector3<T> vEdge2 = avPoint2 - avPoint0;
// Cross product
normal.x = vEdge1.y * vEdge2.z - vEdge1.z * vEdge2.y;
normal.y = vEdge1.z * vEdge2.x - vEdge1.x * vEdge2.z;
normal.z = vEdge1.x * vEdge2.y - vEdge1.y * vEdge2.x;
normal.Normalise();
a = normal.x;
b = normal.y;
c = normal.z;
// Dot product
d = -(normal.x * avPoint0.x + normal.y * avPoint0.y + normal.z * avPoint0.z);
}
/////////////////
inline void Normalise() {
T fMag = sqrt(a * a + b * b + c * c);
a = a / fMag;
b = b / fMag;
c = c / fMag;
d = d / fMag;
}
/////////////////
inline void CalcNormal() {
normal = cVector3<T>(a, b, c);
normal.Normalise();
}
/////////////////
void FromVec(T *apV) {
a = apV[0];
b = apV[1];
c = apV[2];
d = apV[3];
CalcNormal();
}
};
typedef cPlane<float> cPlanef;
typedef Common::Array<cPlanef> tPlanefVec;
typedef tPlanefVec tPlanefVecIt;
//-------------------------------------------
template<class T>
class cSphere {
public:
T r;
cVector3<T> center;
cSphere() {
}
cSphere(cVector3<T> aV, T aR) {
center = aV;
r = aR;
}
};
typedef cSphere<float> cSpheref;
//-------------------------------------------
template<class T>
class cRect2 {
public:
T x, y, w, h;
cRect2(T aX, T aY, T aW, T aH) {
x = aX;
y = aY;
w = aW;
h = aH;
}
cRect2(T aX, T aY) {
x = aX;
y = aY;
w = 0;
h = 0;
}
cRect2() {
x = 0;
y = 0;
w = 0;
h = 0;
}
cRect2(cVector2<T> aPos, cVector2<T> aSize) {
x = aPos.x;
y = aPos.y;
w = aSize.x;
h = aSize.y;
}
void FromVec(T *apV) {
x = apV[0];
y = apV[1];
w = apV[2];
h = apV[3];
}
};
typedef cRect2<float> cRect2f;
typedef cRect2<int> cRect2l;
typedef Common::List<cRect2f> tRect2lList;
typedef tRect2lList tRect2lListIt;
//-------------------------------------------
typedef cVector2<float> cVector2f;
typedef cVector2<int> cVector2l;
typedef cMatrix<float> cMatrixf;
typedef Common::Array<cMatrixf> tMatrixfVec;
typedef tMatrixfVec::iterator tMatrixfVecIt;
typedef Common::List<cMatrixf> tMatrixfList;
typedef tMatrixfList::iterator tMatrixfListIt;
typedef Common::List<cVector2f> tVector2fList;
typedef tVector2fList::iterator tVector2fListIt;
typedef cVector3<float> cVector3f;
typedef cVector3<int> cVector3l;
typedef Common::List<cVector3f> tVector3fList;
typedef tVector3fList::iterator tVector3fListIt;
typedef Common::Array<cVector2f> tVector2fVec;
typedef tVector2fVec::iterator tVector2fVecIt;
typedef Common::Array<cVector3f> tVector3fVec;
typedef tVector3fList::iterator tVector3fVecIt;
//-------------------------------------------
} // namespace hpl
#include "hpl1/engine/math/Quaternion.h"
#endif // HPL_MATHTYPES_H

View File

@@ -0,0 +1,26 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 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, see <http://www.gnu.org/licenses/>.
*
*/
/*
* Copyright (C) 2006-2010 - Frictional Games
*
* This file is part of HPL1 Engine.
*/

View File

@@ -0,0 +1,74 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 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, see <http://www.gnu.org/licenses/>.
*
*/
/*
* Copyright (C) 2006-2010 - Frictional Games
*
* This file is part of HPL1 Engine.
*/
#ifndef HPL_MESH_TYPES_H
#define HPL_MESH_TYPES_H
#include "hpl1/engine/math/BoundingVolume.h"
#include "hpl1/engine/math/MathTypes.h"
namespace hpl {
//----------------------------------------------
class cTriangleData {
public:
cVector3f normal;
bool facingLight;
cTriangleData() {}
cTriangleData(const cVector3f &avNormal) {
normal = avNormal;
}
};
typedef Common::Array<cTriangleData> tTriangleDataVec;
typedef tTriangleDataVec::iterator tTriangleDataVecIt;
//----------------------------------------------
class cTriEdge {
public:
int point1 = 0;
int point2 = 0;
mutable int tri1 = 0;
mutable int tri2 = 0;
bool invert_tri2 = false;
cTriEdge() = default;
constexpr cTriEdge(int alPoint1, int alPoint2, int alTri1, int alTri2) : point1(alPoint1), point2(alPoint2), tri1(alTri1), tri2(alTri2), invert_tri2(false) {
}
};
typedef Common::Array<cTriEdge> tTriEdgeVec;
typedef tTriEdgeVec::iterator tTriEdgeVecIt;
//----------------------------------------------
} // namespace hpl
#endif // HPL_MESH_TYPES_H

View File

@@ -0,0 +1,135 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 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, see <http://www.gnu.org/licenses/>.
*
*/
/*
* Copyright (C) 2006-2010 - Frictional Games
*
* This file is part of HPL1 Engine.
*/
#ifndef HPL_PID_CONTROLLER_H
#define HPL_PID_CONTROLLER_H
#include "hpl1/algorithms.h"
#include "hpl1/engine/math/MathTypes.h"
namespace hpl {
template<class T>
class cPidController {
public:
float p, i, d;
//////////////////////////////////////////
// Constructors
/////////////////////////////////////////
cPidController() {
Reset();
}
cPidController(float afP, float afI, float afD, int alErrorNum) {
p = afP;
i = afI;
d = afD;
SetErrorNum(alErrorNum);
Reset();
}
//////////////////////////////////////////
// Public
/////////////////////////////////////////
//------------------------------------
T Output(T aError, float afTimeStep) {
mvErrors[mlErrorNum] = aError;
mvTimeSteps[mlErrorNum] = afTimeStep;
integral = 0;
size_t lCount = mvErrors.size();
for (size_t error = 0; error < lCount; ++error) {
integral += mvErrors[error] * mvTimeSteps[error];
}
derivative = 0.0f;
if (mlLastNum >= 0) {
derivative = (mvErrors[mlErrorNum] - mvErrors[mlLastNum]) / afTimeStep;
}
mlLastNum = mlErrorNum;
mlErrorNum++;
if (mlErrorNum >= (int)mvErrors.size())
mlErrorNum = 0;
return mvErrors[mlLastNum] * p + integral * i + derivative * d;
}
//------------------------------------
void SetErrorNum(int alErrorNum) {
mvErrors.resize(alErrorNum);
Hpl1::resizeAndFill(mvTimeSteps, alErrorNum, 0.f);
}
//------------------------------------
void Reset() {
mlErrorNum = 0;
mlLastNum = -1;
Common::fill(mvTimeSteps.begin(), mvTimeSteps.end(), 0);
integral = 0;
derivative = 0;
}
//------------------------------------
T GetLastError() {
if (mlLastNum >= 0)
return mvErrors[mlLastNum];
return 0;
}
T GetLastDerivative() {
return derivative;
}
T GetLastIntegral() {
return integral;
}
//------------------------------------
private:
Common::Array<T> mvErrors;
Common::Array<float> mvTimeSteps;
T integral, derivative;
int mlErrorNum;
int mlLastNum;
};
//---------------------------------
typedef cPidController<float> cPidControllerf;
typedef cPidController<cVector3f> cPidControllerVec3;
} // namespace hpl
#endif // HPL_PID_CONTROLLER_H

View File

@@ -0,0 +1,186 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 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, see <http://www.gnu.org/licenses/>.
*
*/
/*
* Copyright (C) 2006-2010 - Frictional Games
*
* This file is part of HPL1 Engine.
*/
#include "hpl1/engine/math/Quaternion.h"
#include "hpl1/engine/math/Math.h"
#include "hpl1/engine/system/low_level_system.h"
namespace hpl {
//////////////////////////////////////////////////////////////////////////
// CONSTRUCTORS
//////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------
cQuaternion::cQuaternion() {
}
//-----------------------------------------------------------------------
cQuaternion::cQuaternion(float afAngle, const cVector3f &avAxis) {
FromAngleAxis(afAngle, avAxis);
}
//-----------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////////
// PUBLIC METHODS
//////////////////////////////////////////////////////////////////////////
const cQuaternion cQuaternion::Identity = cQuaternion(1.0f, 0.0f, 0.0f, 0.0f);
//-----------------------------------------------------------------------
void cQuaternion::Normalise() {
float fLen = w * w + v.x * v.x + v.y * v.y + v.z * v.z;
float fFactor = 1.0f / sqrt(fLen);
v = v * fFactor;
w = w * fFactor;
}
//-----------------------------------------------------------------------
void cQuaternion::ToRotationMatrix(cMatrixf &a_mtxDest) const {
cMatrixf mtxA;
float fTx = 2.0f * v.x;
float fTy = 2.0f * v.y;
float fTz = 2.0f * v.z;
float fTwx = fTx * w;
float fTwy = fTy * w;
float fTwz = fTz * w;
float fTxx = fTx * v.x;
float fTxy = fTy * v.x;
float fTxz = fTz * v.x;
float fTyy = fTy * v.y;
float fTyz = fTz * v.y;
float fTzz = fTz * v.z;
a_mtxDest.m[0][0] = 1.0f - (fTyy + fTzz);
a_mtxDest.m[0][1] = fTxy - fTwz;
a_mtxDest.m[0][2] = fTxz + fTwy;
a_mtxDest.m[1][0] = fTxy + fTwz;
a_mtxDest.m[1][1] = 1.0f - (fTxx + fTzz);
a_mtxDest.m[1][2] = fTyz - fTwx;
a_mtxDest.m[2][0] = fTxz - fTwy;
a_mtxDest.m[2][1] = fTyz + fTwx;
a_mtxDest.m[2][2] = 1.0f - (fTxx + fTyy);
}
//-----------------------------------------------------------------------
void cQuaternion::FromRotationMatrix(const cMatrix<float> &a_mtxRot) {
float fTrace = a_mtxRot.m[0][0] + a_mtxRot.m[1][1] + a_mtxRot.m[2][2];
float fRoot;
if (fTrace > 0.0) {
// |w| > 1/2, may as well choose w > 1/2
fRoot = sqrt(fTrace + 1.0f); // 2w
w = 0.5f * fRoot;
fRoot = 0.5f / fRoot; // 1/(4w)
v.x = (a_mtxRot.m[2][1] - a_mtxRot.m[1][2]) * fRoot;
v.y = (a_mtxRot.m[0][2] - a_mtxRot.m[2][0]) * fRoot;
v.z = (a_mtxRot.m[1][0] - a_mtxRot.m[0][1]) * fRoot;
} else {
// |w| <= 1/2
static size_t s_iNext[3] = {1, 2, 0};
size_t i = 0;
if (a_mtxRot.m[1][1] > a_mtxRot.m[0][0])
i = 1;
if (a_mtxRot.m[2][2] > a_mtxRot.m[i][i])
i = 2;
size_t j = s_iNext[i];
size_t k = s_iNext[j];
fRoot = sqrt(a_mtxRot.m[i][i] - a_mtxRot.m[j][j] - a_mtxRot.m[k][k] + 1.0f);
float *apkQuat[3] = {&v.x, &v.y, &v.z};
*apkQuat[i] = 0.5f * fRoot;
fRoot = 0.5f / fRoot;
w = (a_mtxRot.m[k][j] - a_mtxRot.m[j][k]) * fRoot;
*apkQuat[j] = (a_mtxRot.m[j][i] + a_mtxRot.m[i][j]) * fRoot;
*apkQuat[k] = (a_mtxRot.m[k][i] + a_mtxRot.m[i][k]) * fRoot;
}
}
//-----------------------------------------------------------------------
void cQuaternion::FromAngleAxis(float afAngle, const cVector3f &avAxis) {
// assert: axis[] is unit length
//
// The quaternion representing the rotation is
// q = cos(A/2)+sin(A/2)*(x*i+y*j+z*k)
float fHalfAngle = 0.5f * afAngle;
float fSin = sin(fHalfAngle);
w = cos(fHalfAngle);
v.x = fSin * avAxis.x;
v.y = fSin * avAxis.y;
v.z = fSin * avAxis.z;
}
//-----------------------------------------------------------------------
cQuaternion cQuaternion::operator+(const cQuaternion &aqB) const {
cQuaternion qOut;
qOut.v = v + aqB.v;
qOut.w = w + aqB.w;
return qOut;
}
//-----------------------------------------------------------------------
cQuaternion cQuaternion::operator-(const cQuaternion &aqB) const {
cQuaternion qOut;
qOut.v = v - aqB.v;
qOut.w = w - aqB.w;
return qOut;
}
//-----------------------------------------------------------------------
cQuaternion cQuaternion::operator*(const cQuaternion &aqB) const {
cQuaternion qOut;
qOut.w = w * aqB.w - v.x * aqB.v.x - v.y * aqB.v.y - v.z * aqB.v.z;
qOut.v.x = w * aqB.v.x + v.x * aqB.w + v.y * aqB.v.z - v.z * aqB.v.y;
qOut.v.y = w * aqB.v.y + v.y * aqB.w + v.z * aqB.v.x - v.x * aqB.v.z;
qOut.v.z = w * aqB.v.z + v.z * aqB.w + v.x * aqB.v.y - v.y * aqB.v.x;
return qOut;
}
//-----------------------------------------------------------------------
cQuaternion cQuaternion::operator*(float afScalar) const {
cQuaternion qOut;
qOut.v = v * afScalar;
qOut.w = w * afScalar;
return qOut;
}
//-----------------------------------------------------------------------
} // namespace hpl

View File

@@ -0,0 +1,69 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 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, see <http://www.gnu.org/licenses/>.
*
*/
/*
* Copyright (C) 2006-2010 - Frictional Games
*
* This file is part of HPL1 Engine.
*/
#ifndef HPL_QUATERNION_H
#define HPL_QUATERNION_H
#include "hpl1/engine/math/Vector3.h"
#include "hpl1/engine/math/hplMatrix.h"
namespace hpl {
class cQuaternion {
public:
cVector3<float> v;
float w;
cQuaternion();
cQuaternion(float afAngle, const cVector3<float> &avAxis);
constexpr cQuaternion(float afW, float afX, float afY, float afZ) : v(afX, afY, afZ), w(afW) {
}
void Normalise();
void ToRotationMatrix(cMatrix<float> &a_mtxDest) const;
void FromRotationMatrix(const cMatrix<float> &a_mtxRot);
/**
* Set the quaternion from and angle and axis.
* \param afAngle
* \param &avAxis MUST be unit length!
*/
void FromAngleAxis(float afAngle, const cVector3<float> &avAxis);
cQuaternion operator+(const cQuaternion &aqB) const;
cQuaternion operator-(const cQuaternion &aqB) const;
cQuaternion operator*(const cQuaternion &aqB) const;
cQuaternion operator*(float afScalar) const;
static const cQuaternion Identity;
private:
};
} // namespace hpl
#endif // HPL_QUATERNION_H

View File

@@ -0,0 +1,28 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 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, see <http://www.gnu.org/licenses/>.
*
*/
/*
* Copyright (C) 2006-2010 - Frictional Games
*
* This file is part of HPL1 Engine.
*/
#include "hpl1/engine/math/Spring.h"

View File

@@ -0,0 +1,67 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 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, see <http://www.gnu.org/licenses/>.
*
*/
/*
* Copyright (C) 2006-2010 - Frictional Games
*
* This file is part of HPL1 Engine.
*/
#ifndef HPL_SPRING_H
#define HPL_SPRING_H
#include "hpl1/engine/math/MathTypes.h"
namespace hpl {
template<class T>
class cSpring {
public:
float k;
float b;
//////////////////////////////////////////
// Constructors
/////////////////////////////////////////
cSpring() {}
cSpring(float afK, float afB) {
k = afK;
b = afB;
}
//////////////////////////////////////////
// Public
/////////////////////////////////////////
T Output(T aError, T aV) {
return aError * k - aV * b;
}
};
//---------------------------------
typedef cSpring<float> cSpringf;
typedef cSpring<cVector3f> cSpringVec3;
} // namespace hpl
#endif // HPL_SPRING_H

View File

@@ -0,0 +1,231 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 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, see <http://www.gnu.org/licenses/>.
*
*/
/*
* Copyright (C) 2006-2010 - Frictional Games
*
* This file is part of HPL1 Engine.
*/
#ifndef HPL_VECTOR2_H
#define HPL_VECTOR2_H
#include "hpl1/engine/system/SystemTypes.h"
namespace hpl {
template<class T>
class cVector2 {
public:
T x, y;
#if 0
union{
struct {
T x,y;
};
T v[2];
};
#endif
//////////////////////////////////////////
// Constructors
/////////////////////////////////////////
constexpr cVector2() : x(0), y(0) {
}
constexpr cVector2(T aVal) : x(aVal), y(aVal) {
}
constexpr cVector2(T aX, T aY) : x(aX), y(aY) {
}
constexpr cVector2(cVector2<T> const &aVec) : x(aVec.x), y(aVec.y) {
}
//////////////////////////////////////////
// Copy
/////////////////////////////////////////
inline cVector2<T> &operator=(const cVector2<T> &aVec) {
x = aVec.x;
y = aVec.y;
return *this;
}
inline cVector2<T> &operator=(const T aVal) {
x = aVal;
y = aVal;
return *this;
}
//////////////////////////////////////////
// Boolean
/////////////////////////////////////////
inline bool operator==(const cVector2<T> &aVec) const {
if (x == aVec.x && y == aVec.y)
return true;
else
return false;
}
inline bool operator!=(const cVector2<T> &aVec) const {
if (x == aVec.x && y == aVec.y)
return false;
else
return true;
}
//////////////////////////////////////////
// Vector Arithmetic
/////////////////////////////////////////
inline cVector2<T> operator+(const cVector2<T> &aVec) const {
cVector2<T> vec;
vec.x = x + aVec.x;
vec.y = y + aVec.y;
return vec;
}
inline cVector2<T> operator-(const cVector2<T> &aVec) const {
cVector2<T> vec;
vec.x = x - aVec.x;
vec.y = y - aVec.y;
return vec;
}
inline cVector2<T> operator*(const cVector2<T> &aVec) const {
cVector2<T> vec;
vec.x = x * aVec.x;
vec.y = y * aVec.y;
return vec;
}
inline cVector2<T> operator/(const cVector2<T> &aVec) const {
cVector2<T> vec;
vec.x = x / aVec.x;
vec.y = y / aVec.y;
return vec;
}
inline cVector2<T> &operator-=(const cVector2<T> &aVec) {
x -= aVec.x;
y -= aVec.y;
return *this;
}
inline cVector2<T> &operator+=(const cVector2<T> &aVec) {
x += aVec.x;
y += aVec.y;
return *this;
}
inline cVector2<T> &operator*=(const cVector2<T> &aVec) {
x *= aVec.x;
y *= aVec.y;
return *this;
}
inline cVector2<T> &operator/=(const cVector2<T> &aVec) {
x /= aVec.x;
y /= aVec.y;
return *this;
}
//////////////////////////////////////////
// Real Arithmetic
/////////////////////////////////////////
inline cVector2<T> operator/(const T &aVal) const {
cVector2<T> vec;
vec.x = x / aVal;
vec.y = y / aVal;
return vec;
}
inline cVector2<T> operator*(const T &aVal) const {
cVector2<T> vec;
vec.x = x * aVal;
vec.y = y * aVal;
return vec;
}
inline cVector2<T> operator+(const T &aVal) const {
cVector2<T> vec;
vec.x = x + aVal;
vec.y = y + aVal;
return vec;
}
cVector2<T> operator-(const T &aVal) const {
cVector2<T> vec;
vec.x = x - aVal;
vec.y = y - aVal;
return vec;
}
//////////////////////////////////////////
// Methods
/////////////////////////////////////////
inline void FromVec(const T *apVec) {
x = apVec[0];
y = apVec[1];
}
/**
* Only use this on double or float vectors
* \return Length of Vector
*/
T Normalise() {
T length = sqrt(x * x + y * y);
if (length > 1e-08) {
T InvLength = 1.0f / length;
x *= InvLength;
y *= InvLength;
}
return length;
}
//////////////////////////////////////////
// Printing
/////////////////////////////////////////
tString ToString() const {
char buf[512];
snprintf(buf, 512, "%f : %f", x, y);
tString str = buf;
return str;
}
tString ToFileString() const {
char buf[512];
snprintf(buf, 512, "%g %g", x, y);
tString str = buf;
return str;
}
};
} // namespace hpl
#endif // HPL_VECTOR2_H

View File

@@ -0,0 +1,334 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 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, see <http://www.gnu.org/licenses/>.
*
*/
/*
* Copyright (C) 2006-2010 - Frictional Games
*
* This file is part of HPL1 Engine.
*/
#ifndef HPL_VECTOR3_H
#define HPL_VECTOR3_H
#include "hpl1/engine/math/Vector2.h"
#define VEC3_CONST_ARRAY(name, vec) const float name[] = {vec.x, vec.y, vec.z}
namespace hpl {
template<class T>
class cVector3 {
public:
T x, y, z;
constexpr cVector3() : x(0), y(0), z(0) {
}
constexpr cVector3(T aVal) : x(aVal), y(aVal), z(aVal) {
}
constexpr cVector3(T aX, T aY, T aZ) : x(aX), y(aY), z(aZ) {
}
constexpr cVector3(cVector3<T> const &aVec) : x(aVec.x), y(aVec.y), z(aVec.z) {
}
constexpr cVector3(cVector2<T> const &aVec) : x(aVec.x), y(aVec.y), z(0) {
}
static cVector3 fromArray(const float vec[3]) {
return cVector3<T>(vec[0], vec[1], vec[2]);
}
//////////////////////////////////////////
// Copy
/////////////////////////////////////////
inline cVector3<T> &operator=(const cVector3<T> &aVec) {
x = aVec.x;
y = aVec.y;
z = aVec.z;
return *this;
}
inline cVector3<T> &operator=(const cVector2<T> &aVec) {
x = aVec.x;
y = aVec.y;
return *this;
}
inline cVector3<T> &operator=(const T aVal) {
x = aVal;
y = aVal;
z = aVal;
return *this;
}
//////////////////////////////////////////
// Boolean
/////////////////////////////////////////
inline bool operator==(const cVector3<T> &aVec) const {
if (x == aVec.x && y == aVec.y && z == aVec.z)
return true;
else
return false;
}
inline bool operator!=(const cVector3<T> &aVec) const {
if (x == aVec.x && y == aVec.y && z == aVec.z)
return false;
else
return true;
}
inline bool operator<(const cVector3<T> &aVec) const {
if (x != aVec.x)
return x < aVec.x;
if (y != aVec.y)
return y < aVec.y;
return z < aVec.z;
}
inline bool operator>(const cVector3<T> &aVec) const {
if (x != aVec.x)
return x > aVec.x;
if (y != aVec.y)
return y > aVec.y;
return z > aVec.z;
}
//////////////////////////////////////////
// Vector3 Arithmetic
/////////////////////////////////////////
inline cVector3<T> operator+(const cVector3<T> &aVec) const {
cVector3<T> vec;
vec.x = x + aVec.x;
vec.y = y + aVec.y;
vec.z = z + aVec.z;
return vec;
}
inline cVector3<T> operator-(const cVector3<T> &aVec) const {
cVector3<T> vec;
vec.x = x - aVec.x;
vec.y = y - aVec.y;
vec.z = z - aVec.z;
return vec;
}
inline cVector3<T> operator*(const cVector3<T> &aVec) const {
cVector3<T> vec;
vec.x = x * aVec.x;
vec.y = y * aVec.y;
vec.z = z * aVec.z;
return vec;
}
inline cVector3<T> operator/(const cVector3<T> &aVec) const {
cVector3<T> vec;
vec.x = x / aVec.x;
vec.y = y / aVec.y;
vec.z = z / aVec.z;
return vec;
}
inline cVector3<T> &operator-=(const cVector3<T> &aVec) {
x -= aVec.x;
y -= aVec.y;
z -= aVec.z;
return *this;
}
inline cVector3<T> &operator+=(const cVector3<T> &aVec) {
x += aVec.x;
y += aVec.y;
z += aVec.z;
return *this;
}
inline cVector3<T> &operator*=(const cVector3<T> &aVec) {
x *= aVec.x;
y *= aVec.y;
z *= aVec.z;
return *this;
}
inline cVector3<T> &operator/=(const cVector3<T> &aVec) {
x /= aVec.x;
y /= aVec.y;
z /= aVec.z;
return *this;
}
//////////////////////////////////////////
// Vector2 Arithmetic
/////////////////////////////////////////
inline cVector3<T> operator+(const cVector2<T> &aVec) const {
cVector3<T> vec;
vec.x = x + aVec.x;
vec.y = y + aVec.y;
vec.z = z;
return vec;
}
inline cVector3<T> operator-(const cVector2<T> &aVec) const {
cVector3<T> vec;
vec.x = x - aVec.x;
vec.y = y - aVec.y;
vec.z = z;
return vec;
}
inline cVector3<T> operator*(const cVector2<T> &aVec) const {
cVector3<T> vec;
vec.x = x * aVec.x;
vec.y = y * aVec.y;
vec.z = z;
return vec;
}
inline cVector3<T> operator/(const cVector2<T> &aVec) const {
cVector3<T> vec;
vec.x = x / aVec.x;
vec.y = y / aVec.y;
vec.z = z;
return vec;
}
inline cVector3<T> &operator-=(const cVector2<T> &aVec) {
x -= aVec.x;
y -= aVec.y;
return *this;
}
inline cVector3<T> &operator+=(const cVector2<T> &aVec) {
x += aVec.x;
y += aVec.y;
return *this;
}
inline cVector3<T> &operator*=(const cVector2<T> &aVec) {
x *= aVec.x;
y *= aVec.y;
return *this;
}
inline cVector3<T> &operator/=(const cVector2<T> &aVec) {
x /= aVec.x;
y /= aVec.y;
return *this;
}
//////////////////////////////////////////
// Single Float Arithmetic
/////////////////////////////////////////
inline cVector3<T> operator/(const T &aVal) const {
cVector3<T> vec;
vec.x = x / aVal;
vec.y = y / aVal;
vec.z = z / aVal;
return vec;
}
inline cVector3<T> operator*(const T &aVal) const {
cVector3<T> vec;
vec.x = x * aVal;
vec.y = y * aVal;
vec.z = z * aVal;
return vec;
}
inline cVector3<T> operator+(const T &aVal) const {
cVector3<T> vec;
vec.x = x + aVal;
vec.y = y + aVal;
vec.z = z + aVal;
return vec;
}
cVector3<T> operator-(const T &aVal) const {
cVector3<T> vec;
vec.x = x - aVal;
vec.y = y - aVal;
vec.z = z - aVal;
return vec;
}
//////////////////////////////////////////
// Methods
/////////////////////////////////////////
inline void FromVec(const T *apVec) {
x = apVec[0];
y = apVec[1];
z = apVec[2];
}
inline T Length() {
return sqrt(x * x + y * y + z * z);
}
inline T SqrLength() {
return x * x + y * y + z * z;
}
/**
* Only use this on double or float vectors
* \return Length of Vector
*/
T Normalise() {
T length = sqrt(x * x + y * y + z * z);
// Will also work for zero-sized vectors, but will change nothing
if (length > 1e-08) {
T InvLength = 1.0f / length;
x *= InvLength;
y *= InvLength;
z *= InvLength;
}
return length;
}
//////////////////////////////////////////
// Printing
/////////////////////////////////////////
tString ToString() const {
char buf[512];
snprintf(buf, 512, "%f : %f : %f", x, y, z);
tString str = buf;
return str;
}
tString ToFileString() const {
char buf[512];
snprintf(buf, 512, "%g %g %g", x, y, z);
tString str = buf;
return str;
}
};
} // namespace hpl
#endif // HPL_VECTOR3_H

View File

@@ -0,0 +1,266 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 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, see <http://www.gnu.org/licenses/>.
*
*/
/*
* Copyright (C) 2006-2010 - Frictional Games
*
* This file is part of HPL1 Engine.
*/
#ifndef HPL_MATRIX_H
#define HPL_MATRIX_H
#include "hpl1/engine/math/Vector3.h"
namespace hpl {
template<class T>
class cMatrix {
public:
// The ways to reference the matrix
// format is [row][col]
union {
T m[4][4];
T v[16];
};
//////////////////////////////////////////
// Constructors
/////////////////////////////////////////
inline cMatrix() {
}
//-----------------------------------------------------------------------
inline cMatrix(T *pA) {
FromVec(pA);
}
//-----------------------------------------------------------------------
inline cMatrix(double *pA) {
m[0][0] = (T)pA[0];
m[0][1] = (T)pA[1];
m[0][2] = (T)pA[2];
m[0][3] = (T)pA[3];
m[1][0] = (T)pA[4];
m[1][1] = (T)pA[5];
m[1][2] = (T)pA[6];
m[1][3] = (T)pA[7];
m[2][0] = (T)pA[8];
m[2][1] = (T)pA[9];
m[2][2] = (T)pA[10];
m[2][3] = (T)pA[11];
m[3][0] = (T)pA[12];
m[3][1] = (T)pA[13];
m[3][2] = (T)pA[14];
m[3][3] = (T)pA[15];
}
//-----------------------------------------------------------------------
inline constexpr cMatrix(
T a00, T a01, T a02, T a03,
T a10, T a11, T a12, T a13,
T a20, T a21, T a22, T a23,
T a30, T a31, T a32, T a33) : m{
{a00, a01, a02, a03},
{a10, a11, a12, a13},
{a20, a21, a22, a23},
{a30, a31, a32, a33}} {
}
static const cMatrix<T> Identity;
static const cMatrix<T> Zero;
//-----------------------------------------------------------------------
inline bool operator==(const cMatrix<T> &aMtx) const {
if (m[0][0] == aMtx.m[0][0] &&
m[0][1] == aMtx.m[0][1] &&
m[0][2] == aMtx.m[0][2] &&
m[0][3] == aMtx.m[0][3] &&
m[1][0] == aMtx.m[1][0] &&
m[1][1] == aMtx.m[1][1] &&
m[1][2] == aMtx.m[1][2] &&
m[1][3] == aMtx.m[1][3] &&
m[2][0] == aMtx.m[2][0] &&
m[2][1] == aMtx.m[2][1] &&
m[2][2] == aMtx.m[2][2] &&
m[2][3] == aMtx.m[2][3] &&
m[3][0] == aMtx.m[3][0] &&
m[3][1] == aMtx.m[3][1] &&
m[3][2] == aMtx.m[3][2] &&
m[3][3] == aMtx.m[3][3]) {
return true;
}
return false;
}
//-----------------------------------------------------------------------
inline bool operator!=(const cMatrix<T> &aMtx) {
return !(*this == aMtx);
}
//-----------------------------------------------------------------------
inline void FromVec(const T *pA) {
m[0][0] = pA[0];
m[0][1] = pA[1];
m[0][2] = pA[2];
m[0][3] = pA[3];
m[1][0] = pA[4];
m[1][1] = pA[5];
m[1][2] = pA[6];
m[1][3] = pA[7];
m[2][0] = pA[8];
m[2][1] = pA[9];
m[2][2] = pA[10];
m[2][3] = pA[11];
m[3][0] = pA[12];
m[3][1] = pA[13];
m[3][2] = pA[14];
m[3][3] = pA[15];
}
//-----------------------------------------------------------------------
inline void FromTranspose(const T *pA) {
m[0][0] = pA[0];
m[1][0] = pA[1];
m[2][0] = pA[2];
m[3][0] = pA[3];
m[0][1] = pA[4];
m[1][1] = pA[5];
m[2][1] = pA[6];
m[3][1] = pA[7];
m[0][2] = pA[8];
m[1][2] = pA[9];
m[2][2] = pA[10];
m[3][2] = pA[11];
m[0][3] = pA[12];
m[1][3] = pA[13];
m[2][3] = pA[14];
m[3][3] = pA[15];
}
//-----------------------------------------------------------------------
inline cVector3<T> GetRight() const {
/* @todo ??? */
return cVector3<T>(m[0][0], m[0][1], m[0][2]);
}
inline void SetRight(const cVector3<T> &avVec) {
m[0][0] = avVec.x;
m[0][1] = avVec.y;
m[0][2] = avVec.z;
}
//-----------------------------------------------------------------------
inline cVector3<T> GetUp() const {
/* @todo ??? */
return cVector3<T>(m[1][0], m[1][1], m[1][2]);
}
inline void SetUp(const cVector3<T> &avVec) {
m[1][0] = avVec.x;
m[1][1] = avVec.y;
m[1][2] = avVec.z;
}
//-----------------------------------------------------------------------
inline cVector3<T> GetForward() const {
/* @todo ??? */
return cVector3<T>(m[2][0], m[2][1], m[2][2]);
}
inline void SetForward(const cVector3<T> &avVec) {
m[2][0] = avVec.x;
m[2][1] = avVec.y;
m[2][2] = avVec.z;
}
//-----------------------------------------------------------------------
inline cVector3<T> GetTranslation() const {
/* @todo ??? */
return cVector3<T>(m[0][3], m[1][3], m[2][3]);
}
inline void SetTranslation(const cVector3<T> &avTrans) {
m[0][3] = avTrans.x;
m[1][3] = avTrans.y;
m[2][3] = avTrans.z;
}
//-----------------------------------------------------------------------
inline cMatrix<T> GetRotation() const {
return cMatrix<T>(m[0][0], m[0][1], m[0][2], 0,
m[1][0], m[1][1], m[1][2], 0,
m[2][0], m[2][1], m[2][2], 0,
0, 0, 0, 1);
}
//-----------------------------------------------------------------------
inline cMatrix<T> GetTranspose() const {
return cMatrix<T>(m[0][0], m[1][0], m[2][0], m[3][0],
m[0][1], m[1][1], m[2][1], m[3][1],
m[0][2], m[1][2], m[2][2], m[3][2],
m[0][3], m[1][3], m[2][3], m[3][3]);
}
//-----------------------------------------------------------------------
tString ToString() {
char buf[512];
snprintf(buf, 512, "[%f : %f : %f : %f] [%f : %f : %f : %f] [%f : %f : %f : %f] [%f : %f : %f : %f]",
m[0][0], m[0][1], m[0][2], m[0][3],
m[1][0], m[1][1], m[1][2], m[1][3],
m[2][0], m[2][1], m[2][2], m[2][3],
m[3][0], m[3][1], m[3][2], m[3][3]);
return buf;
}
tString ToFileString() {
char buf[512];
snprintf(buf, 512, "%g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g",
m[0][0], m[0][1], m[0][2], m[0][3],
m[1][0], m[1][1], m[1][2], m[1][3],
m[2][0], m[2][1], m[2][2], m[2][3],
m[3][0], m[3][1], m[3][2], m[3][3]);
return buf;
}
};
} // namespace hpl
#endif // HPL_MATRIX_H