fix camera glitch issue
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
#include "StdAfx.h"
|
||||
#include "../eterBase/Utils.h"
|
||||
#include "Camera.h"
|
||||
#include <cmath>
|
||||
|
||||
const float c_fDefaultResistance = 0.3f;
|
||||
|
||||
@@ -219,6 +220,10 @@ void CCamera::SetViewParams( const D3DXVECTOR3 &v3Eye, const D3DXVECTOR3& v3Targ
|
||||
m_v3Target = v3Target;
|
||||
m_v3Up = v3Up;
|
||||
|
||||
// Avoid screen flipping with nan values in the view matrix
|
||||
if (!m_v3Eye.y)
|
||||
m_v3Eye.y = 0.1f;
|
||||
|
||||
SetViewMatrix();
|
||||
}
|
||||
|
||||
@@ -252,40 +257,107 @@ void CCamera::SetUp(const D3DXVECTOR3 & v3Up)
|
||||
SetViewMatrix();
|
||||
}
|
||||
|
||||
bool IsNaN(const D3DXVECTOR3& v)
|
||||
{
|
||||
return std::isnan(v.x) || std::isnan(v.y) || std::isnan(v.z);
|
||||
}
|
||||
|
||||
void CCamera::SetViewMatrix()
|
||||
{
|
||||
// Calculate view direction
|
||||
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;
|
||||
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);
|
||||
if (std::isnan(m_fDistance))
|
||||
{
|
||||
m_fDistance = 0.0f;
|
||||
}
|
||||
m_fDistance = std::fmax(0.0f, m_fDistance);
|
||||
assert(m_fDistance >= 0);
|
||||
D3DXVec3Normalize(&m_v3View , &m_v3View);
|
||||
|
||||
D3DXVec3Cross(&m_v3Cross, &m_v3Up, &m_v3View);
|
||||
D3DXVec3Normalize(&m_v3Cross, &m_v3Cross);
|
||||
// Normalize the view vector if possible
|
||||
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);
|
||||
D3DXVec3Normalize(&m_v3Up, &m_v3Up);
|
||||
const auto vv = D3DXVECTOR3(0.0f, 0.0f, 1.0f);
|
||||
m_fPitch = D3DXVec3Dot(&m_v3Up, &vv);// / D3DXVec2Length(&v2ViewYZ);
|
||||
if (m_fPitch >= 1)
|
||||
m_fPitch = 1;
|
||||
else if (m_fPitch <= -1)
|
||||
m_fPitch = -1;
|
||||
// Compute the cross product for the right vector and normalize
|
||||
D3DXVec3Cross(&m_v3Cross, &m_v3Up, &m_v3View);
|
||||
float crossLength = D3DXVec3Length(&m_v3Cross);
|
||||
if (crossLength > FLT_EPSILON)
|
||||
{
|
||||
D3DXVec3Normalize(&m_v3Cross, &m_v3Cross);
|
||||
}
|
||||
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);
|
||||
if (std::isnan(m_fPitch))
|
||||
{
|
||||
m_fPitch = 0.0f;
|
||||
}
|
||||
m_fPitch *= (180.0f / D3DX_PI);
|
||||
if ( 0 < m_v3View.z )
|
||||
if (m_v3View.z > 0)
|
||||
m_fPitch = -m_fPitch;
|
||||
|
||||
// Build the view matrix.
|
||||
D3DXMatrixLookAtRH(&m_matView, &m_v3Eye, &m_v3Target, &m_v3Up);
|
||||
|
||||
// Compute the determinant and check it.
|
||||
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._41 = 0.0f;
|
||||
m_matBillboard._42 = 0.0f;
|
||||
m_matBillboard._43 = 0.0f;
|
||||
m_matBillboard._41 = 0.0f;
|
||||
m_matBillboard._42 = 0.0f;
|
||||
m_matBillboard._43 = 0.0f;
|
||||
|
||||
m_ViewRay.SetStartPoint(m_v3Target);
|
||||
m_ViewRay.SetDirection(v3CenterRay, m_fDistance);
|
||||
@@ -302,21 +374,27 @@ void CCamera::SetViewMatrix()
|
||||
m_kCameraBackToTerrainRay.SetDirection(-m_v3View, m_fTerrainCollisionRadius);
|
||||
m_kCameraLeftToTerrainRay.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_kTopObjectCollisionRay.SetStartPoint(m_v3Target);
|
||||
m_kRightObjectCollisionRay.SetStartPoint(m_v3Target);
|
||||
m_kBottomObjectCollisionRay.SetStartPoint(m_v3Target);
|
||||
const auto vv3 = (v3CenterRay + m_fObjectCollisionRadius * m_v3Cross);
|
||||
const auto vv4 = (v3CenterRay - m_fObjectCollisionRadius * m_v3Cross);
|
||||
const auto vv5 = (v3CenterRay + m_fObjectCollisionRadius * m_v3Up);
|
||||
const auto vv6 = (v3CenterRay + m_fObjectCollisionRadius * m_v3Up);
|
||||
m_kLeftObjectCollisionRay.SetDirection(v3CenterRay + m_fObjectCollisionRadius * m_v3Cross, D3DXVec3Length(&vv3));
|
||||
m_kRightObjectCollisionRay.SetDirection(v3CenterRay - m_fObjectCollisionRadius * m_v3Cross, D3DXVec3Length(&vv4));
|
||||
m_kTopObjectCollisionRay.SetDirection(v3CenterRay + m_fObjectCollisionRadius * m_v3Up, D3DXVec3Length(&vv5));
|
||||
m_kBottomObjectCollisionRay.SetDirection(v3CenterRay - m_fObjectCollisionRadius * m_v3Up, D3DXVec3Length(&vv6));
|
||||
|
||||
D3DXVECTOR3 val1 = (v3CenterRay + m_fObjectCollisionRadius * m_v3Cross);
|
||||
m_kLeftObjectCollisionRay.SetDirection(val1, D3DXVec3Length(&val1));
|
||||
|
||||
D3DXVECTOR3 val2 = (v3CenterRay - m_fObjectCollisionRadius * m_v3Cross);
|
||||
m_kRightObjectCollisionRay.SetDirection(val2, D3DXVec3Length(&val2));
|
||||
|
||||
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)
|
||||
|
||||
Reference in New Issue
Block a user