@@ -5,6 +5,7 @@
|
|||||||
#include "StdAfx.h"
|
#include "StdAfx.h"
|
||||||
#include "../eterBase/Utils.h"
|
#include "../eterBase/Utils.h"
|
||||||
#include "Camera.h"
|
#include "Camera.h"
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
const float c_fDefaultResistance = 0.3f;
|
const float c_fDefaultResistance = 0.3f;
|
||||||
|
|
||||||
@@ -219,6 +220,10 @@ void CCamera::SetViewParams( const D3DXVECTOR3 &v3Eye, const D3DXVECTOR3& v3Targ
|
|||||||
m_v3Target = v3Target;
|
m_v3Target = v3Target;
|
||||||
m_v3Up = v3Up;
|
m_v3Up = v3Up;
|
||||||
|
|
||||||
|
// Avoid screen flipping with nan values in the view matrix
|
||||||
|
if (!m_v3Eye.y)
|
||||||
|
m_v3Eye.y = 0.1f;
|
||||||
|
|
||||||
SetViewMatrix();
|
SetViewMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -252,40 +257,107 @@ void CCamera::SetUp(const D3DXVECTOR3 & v3Up)
|
|||||||
SetViewMatrix();
|
SetViewMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsNaN(const D3DXVECTOR3& v)
|
||||||
|
{
|
||||||
|
return std::isnan(v.x) || std::isnan(v.y) || std::isnan(v.z);
|
||||||
|
}
|
||||||
|
|
||||||
void CCamera::SetViewMatrix()
|
void CCamera::SetViewMatrix()
|
||||||
{
|
{
|
||||||
|
// Calculate view direction
|
||||||
m_v3View = m_v3Target - m_v3Eye;
|
m_v3View = m_v3Target - m_v3Eye;
|
||||||
|
if (IsNaN(m_v3View))
|
||||||
|
{
|
||||||
|
m_v3View = D3DXVECTOR3(0.0f, 0.0f, 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
// v3CenterRay is the reverse of the view vector
|
||||||
D3DXVECTOR3 v3CenterRay = -m_v3View;
|
D3DXVECTOR3 v3CenterRay = -m_v3View;
|
||||||
CalculateRoll();
|
|
||||||
|
// Calculate roll (if this function uses m_v3View, ensure it’s valid)
|
||||||
|
CalculateRoll();
|
||||||
|
|
||||||
|
// Compute the distance from eye to target
|
||||||
m_fDistance = D3DXVec3Length(&m_v3View);
|
m_fDistance = D3DXVec3Length(&m_v3View);
|
||||||
|
if (std::isnan(m_fDistance))
|
||||||
|
{
|
||||||
|
m_fDistance = 0.0f;
|
||||||
|
}
|
||||||
|
m_fDistance = std::fmax(0.0f, m_fDistance);
|
||||||
assert(m_fDistance >= 0);
|
assert(m_fDistance >= 0);
|
||||||
D3DXVec3Normalize(&m_v3View , &m_v3View);
|
|
||||||
|
|
||||||
D3DXVec3Cross(&m_v3Cross, &m_v3Up, &m_v3View);
|
// Normalize the view vector if possible
|
||||||
D3DXVec3Normalize(&m_v3Cross, &m_v3Cross);
|
if (m_fDistance > FLT_EPSILON)
|
||||||
|
{
|
||||||
|
D3DXVec3Normalize(&m_v3View, &m_v3View);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Avoid dividing by zero; set to a default forward direction
|
||||||
|
m_v3View = D3DXVECTOR3(0.0f, 0.0f, 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
D3DXVec3Cross(&m_v3Up, &m_v3View, &m_v3Cross);
|
// Compute the cross product for the right vector and normalize
|
||||||
D3DXVec3Normalize(&m_v3Up, &m_v3Up);
|
D3DXVec3Cross(&m_v3Cross, &m_v3Up, &m_v3View);
|
||||||
const auto vv = D3DXVECTOR3(0.0f, 0.0f, 1.0f);
|
float crossLength = D3DXVec3Length(&m_v3Cross);
|
||||||
m_fPitch = D3DXVec3Dot(&m_v3Up, &vv);// / D3DXVec2Length(&v2ViewYZ);
|
if (crossLength > FLT_EPSILON)
|
||||||
if (m_fPitch >= 1)
|
{
|
||||||
m_fPitch = 1;
|
D3DXVec3Normalize(&m_v3Cross, &m_v3Cross);
|
||||||
else if (m_fPitch <= -1)
|
}
|
||||||
m_fPitch = -1;
|
else
|
||||||
|
{
|
||||||
|
// Use a default right vector if the cross product is near zero
|
||||||
|
m_v3Cross = D3DXVECTOR3(1.0f, 0.0f, 0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recompute the up vector and normalize
|
||||||
|
D3DXVec3Cross(&m_v3Up, &m_v3View, &m_v3Cross);
|
||||||
|
float upLength = D3DXVec3Length(&m_v3Up);
|
||||||
|
if (upLength > FLT_EPSILON)
|
||||||
|
{
|
||||||
|
D3DXVec3Normalize(&m_v3Up, &m_v3Up);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Use a default up vector.
|
||||||
|
m_v3Up = D3DXVECTOR3(0.0f, 1.0f, 0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate the pitch angle from the up vector
|
||||||
|
D3DXVECTOR3 val = D3DXVECTOR3(0.0f, 0.0f, 1.0f);
|
||||||
|
m_fPitch = D3DXVec3Dot(&m_v3Up, &val);
|
||||||
|
// Clamp the dot product so acosf is safe
|
||||||
|
if (m_fPitch >= 1.0f)
|
||||||
|
m_fPitch = 1.0f;
|
||||||
|
else if (m_fPitch <= -1.0f)
|
||||||
|
m_fPitch = -1.0f;
|
||||||
m_fPitch = acosf(m_fPitch);
|
m_fPitch = acosf(m_fPitch);
|
||||||
|
if (std::isnan(m_fPitch))
|
||||||
|
{
|
||||||
|
m_fPitch = 0.0f;
|
||||||
|
}
|
||||||
m_fPitch *= (180.0f / D3DX_PI);
|
m_fPitch *= (180.0f / D3DX_PI);
|
||||||
if ( 0 < m_v3View.z )
|
if (m_v3View.z > 0)
|
||||||
m_fPitch = -m_fPitch;
|
m_fPitch = -m_fPitch;
|
||||||
|
|
||||||
|
// Build the view matrix.
|
||||||
D3DXMatrixLookAtRH(&m_matView, &m_v3Eye, &m_v3Target, &m_v3Up);
|
D3DXMatrixLookAtRH(&m_matView, &m_v3Eye, &m_v3Target, &m_v3Up);
|
||||||
|
|
||||||
|
// Compute the determinant and check it.
|
||||||
float fDeterminantD3DMatView = D3DXMatrixDeterminant(&m_matView);
|
float fDeterminantD3DMatView = D3DXMatrixDeterminant(&m_matView);
|
||||||
D3DXMatrixInverse(&m_matInverseView, &fDeterminantD3DMatView, &m_matView);
|
if (std::isnan(fDeterminantD3DMatView) || fabs(fDeterminantD3DMatView) < FLT_EPSILON)
|
||||||
|
{
|
||||||
|
D3DXMatrixIdentity(&m_matInverseView);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
D3DXMatrixInverse(&m_matInverseView, &fDeterminantD3DMatView, &m_matView);
|
||||||
|
}
|
||||||
|
|
||||||
m_matBillboard = m_matInverseView;
|
m_matBillboard = m_matInverseView;
|
||||||
m_matBillboard._41 = 0.0f;
|
m_matBillboard._41 = 0.0f;
|
||||||
m_matBillboard._42 = 0.0f;
|
m_matBillboard._42 = 0.0f;
|
||||||
m_matBillboard._43 = 0.0f;
|
m_matBillboard._43 = 0.0f;
|
||||||
|
|
||||||
m_ViewRay.SetStartPoint(m_v3Target);
|
m_ViewRay.SetStartPoint(m_v3Target);
|
||||||
m_ViewRay.SetDirection(v3CenterRay, m_fDistance);
|
m_ViewRay.SetDirection(v3CenterRay, m_fDistance);
|
||||||
@@ -302,21 +374,27 @@ void CCamera::SetViewMatrix()
|
|||||||
m_kCameraBackToTerrainRay.SetDirection(-m_v3View, m_fTerrainCollisionRadius);
|
m_kCameraBackToTerrainRay.SetDirection(-m_v3View, m_fTerrainCollisionRadius);
|
||||||
m_kCameraLeftToTerrainRay.SetDirection(-m_v3Cross, 3.0f * m_fTerrainCollisionRadius);
|
m_kCameraLeftToTerrainRay.SetDirection(-m_v3Cross, 3.0f * m_fTerrainCollisionRadius);
|
||||||
m_kCameraRightToTerrainRay.SetDirection(m_v3Cross, 3.0f * m_fTerrainCollisionRadius);
|
m_kCameraRightToTerrainRay.SetDirection(m_v3Cross, 3.0f * m_fTerrainCollisionRadius);
|
||||||
const auto vv2 = (v3CenterRay - m_fTerrainCollisionRadius * m_v3Up);
|
|
||||||
m_kTargetToCameraBottomRay.SetDirection(v3CenterRay - m_fTerrainCollisionRadius * m_v3Up, D3DXVec3Length(&vv2));
|
D3DXVECTOR3 temp = (v3CenterRay - m_fTerrainCollisionRadius * m_v3Up);
|
||||||
|
m_kTargetToCameraBottomRay.SetDirection(v3CenterRay - m_fTerrainCollisionRadius * m_v3Up,
|
||||||
|
D3DXVec3Length(&temp));
|
||||||
|
|
||||||
m_kLeftObjectCollisionRay.SetStartPoint(m_v3Target);
|
m_kLeftObjectCollisionRay.SetStartPoint(m_v3Target);
|
||||||
m_kTopObjectCollisionRay.SetStartPoint(m_v3Target);
|
m_kTopObjectCollisionRay.SetStartPoint(m_v3Target);
|
||||||
m_kRightObjectCollisionRay.SetStartPoint(m_v3Target);
|
m_kRightObjectCollisionRay.SetStartPoint(m_v3Target);
|
||||||
m_kBottomObjectCollisionRay.SetStartPoint(m_v3Target);
|
m_kBottomObjectCollisionRay.SetStartPoint(m_v3Target);
|
||||||
const auto vv3 = (v3CenterRay + m_fObjectCollisionRadius * m_v3Cross);
|
|
||||||
const auto vv4 = (v3CenterRay - m_fObjectCollisionRadius * m_v3Cross);
|
D3DXVECTOR3 val1 = (v3CenterRay + m_fObjectCollisionRadius * m_v3Cross);
|
||||||
const auto vv5 = (v3CenterRay + m_fObjectCollisionRadius * m_v3Up);
|
m_kLeftObjectCollisionRay.SetDirection(val1, D3DXVec3Length(&val1));
|
||||||
const auto vv6 = (v3CenterRay + m_fObjectCollisionRadius * m_v3Up);
|
|
||||||
m_kLeftObjectCollisionRay.SetDirection(v3CenterRay + m_fObjectCollisionRadius * m_v3Cross, D3DXVec3Length(&vv3));
|
D3DXVECTOR3 val2 = (v3CenterRay - m_fObjectCollisionRadius * m_v3Cross);
|
||||||
m_kRightObjectCollisionRay.SetDirection(v3CenterRay - m_fObjectCollisionRadius * m_v3Cross, D3DXVec3Length(&vv4));
|
m_kRightObjectCollisionRay.SetDirection(val2, D3DXVec3Length(&val2));
|
||||||
m_kTopObjectCollisionRay.SetDirection(v3CenterRay + m_fObjectCollisionRadius * m_v3Up, D3DXVec3Length(&vv5));
|
|
||||||
m_kBottomObjectCollisionRay.SetDirection(v3CenterRay - m_fObjectCollisionRadius * m_v3Up, D3DXVec3Length(&vv6));
|
D3DXVECTOR3 val3 = (v3CenterRay + m_fObjectCollisionRadius * m_v3Up);
|
||||||
|
m_kTopObjectCollisionRay.SetDirection(val3, D3DXVec3Length(&val3));
|
||||||
|
|
||||||
|
D3DXVECTOR3 val4 = (v3CenterRay - m_fObjectCollisionRadius * m_v3Up);
|
||||||
|
m_kBottomObjectCollisionRay.SetDirection(val4, D3DXVec3Length(&val4));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CCamera::Move(const D3DXVECTOR3 & v3Displacement)
|
void CCamera::Move(const D3DXVECTOR3 & v3Displacement)
|
||||||
|
|||||||
Reference in New Issue
Block a user