Merge pull request #5 from mq1n/main

fix camera glitch issue
This commit is contained in:
d1str4ught
2025-08-28 18:38:54 +02:00
committed by GitHub

View File

@@ -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 its 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)