Почему выбраковка моего усеченного конуса не происходит на определенных углах?

Моя реализация отбраковки Frustum не работает должным образом; то, что происходит, это отбраковывает, когда я поворачиваю камеру влево, но не вправо. Он также будет «отбракован», если я переместу камеру назад, хотя расстояние, на котором объект исчезает и не отображается, очень мало для этого — о 6.0f единиц при использовании центра объекта (сферы) и положения камеры для вычисления расстояния. Вверх или вниз движения / вращения на самом деле ничего не делают.

Моя проекция на дальнюю плоскость высокая: 500.0fМоё ближнее самолётное существо 0.1f, Конечно, опускание / поднятие дальней плоскости, похоже, не влияет на выбраковку.


Код

Вот код вычисления плоскости:

void Frustum::UpdateCamParams( Camera* camera )
{
vec3 fartl, fartr, farbl, farbr;
vec3 neartl, neartr, nearbl, nearbr;

const vec3& camLook  = camera->GetLook();
const vec3& camUp    = camera->GetUp();
const vec3& camRight = camera->GetRight();
const vec3& camPos   = camera->GetPosition();

const float zFar    = camera->GetFarZ();
const float zNear   = camera->GetNearZ();

float halfFarWidth  = camera->GetFarWindowWidth() * 0.5f;
float halfFarHeight = camera->GetFarWindowHeight() * 0.5f;

float halfNearWidth     = camera->GetNearWindowWidth() * 0.5f;
float halfNearHeight    = camera->GetNearWindowHeight() * 0.5f;

const vec3& farClip = camPos + camLook * zFar;

fartl  = farClip + ( camUp * halfFarHeight ) - ( camRight * halfFarWidth );
fartr = farClip + ( camUp * halfFarHeight ) + ( camRight * halfFarWidth );
farbl  = farClip - ( camUp * halfFarHeight ) - ( camRight * halfFarWidth );
farbr = farClip - ( camUp * halfFarHeight ) + ( camRight * halfFarWidth );

const vec3& nearClip = camPos + camLook * zNear;

neartl  = nearClip + ( camUp * halfNearHeight ) - ( camRight * halfNearWidth );
neartr  = nearClip + ( camUp * halfNearHeight ) + ( camRight * halfNearWidth );
nearbl  = nearClip - ( camUp * halfNearHeight ) - ( camRight * halfNearWidth );
nearbr  = nearClip - ( camUp * halfNearHeight ) + ( camRight * halfNearWidth );

////viewRay = camLook - camPos;

// Points are set in a counter-clockwise order, for each plane

planes[ FRUST_LEFT ].points[ 0 ] = nearbl;
planes[ FRUST_LEFT ].points[ 1 ] = farbl;
planes[ FRUST_LEFT ].points[ 2 ] = fartl;
M_ComputePlane( &planes[ FRUST_LEFT ] );

planes[ FRUST_RIGHT ].points[ 0 ] = nearbr;
planes[ FRUST_RIGHT ].points[ 1 ] = farbr;
planes[ FRUST_RIGHT ].points[ 2 ] = fartr;
M_ComputePlane( &planes[ FRUST_RIGHT ] );

planes[ FRUST_TOP ].points[ 0 ] = neartl;
planes[ FRUST_TOP ].points[ 1 ] = neartr;
planes[ FRUST_TOP ].points[ 2 ] = fartr;
M_ComputePlane( &planes[ FRUST_TOP ] );

planes[ FRUST_BOTTOM ].points[ 0 ] = nearbl;
planes[ FRUST_BOTTOM ].points[ 1 ] = nearbr;
planes[ FRUST_BOTTOM ].points[ 2 ] = farbr;
M_ComputePlane( &planes[ FRUST_BOTTOM ] );

planes[ FRUST_FAR ].points[ 0 ] = farbl;
planes[ FRUST_FAR ].points[ 1 ] = farbr;
planes[ FRUST_FAR ].points[ 2 ] = fartr;
M_ComputePlane( &planes[ FRUST_FAR ] );

planes[ FRUST_NEAR ].points[ 0 ] = nearbl;
planes[ FRUST_NEAR ].points[ 1 ] = nearbr;
planes[ FRUST_NEAR ].points[ 2 ] = neartr;
M_ComputePlane( &planes[ FRUST_NEAR ] );
}

В двух словах, сначала вычисляются центры дальней и ближней плоскости зажима, а затем вычисляются четыре угла обеих сторон усеченного контура, чтобы обеспечить установку точки в пределах planes Массив следующим образом. planes массив используется для обозначения 6 сторон усеченного конуса.

M_ComputePlane вычисляет нормаль плоскости и расстояние до начала координат, d:

void M_ComputePlane( plane_t* p )
{
vec3 e1 = p->points[ 2 ] - p->points[ 1 ];
vec3 e3 = p->points[ 1 ] - p->points[ 0 ];

vec3 normal = glm::cross( e1, e3 );

p->normal = glm::length( normal ) > 1.0f ? glm::normalize( normal ) : normal;
p->d      = glm::dot( p->points[ 0 ], p->normal );
}

Вот тесты пересечения, каждый из которых был протестирован и в основном дает один и тот же результат:

/*
=============================

Frustum::BoundsInSphere

returns true in the event that the given center and radius
are within the view frustum

=============================
*/

bool Frustum::BoundsInSphere( const vec3& center, float radius )
{
for ( uint32_t i = 0; i < 6; ++i )
{
// center dot planes[ i ].normal = magnitude of projecting sphere center position onto plane normal
// plane[ i ].d = distance from origin to plane

float test = glm::dot( center, planes[ i ].normal ) + planes[ i ].d + radius;

if ( test <= 0 )
return false; // object is outside of this plane - reject!
}

return true;
}

/*
=============================

Frustum::BoundsInAABB_AllPoints

Tests each vertex of the AABB and only
returns false if all points are outside of one of
the frustum planes. Otherwise, the object
is considered renderable.

=============================
*/

bool Frustum::BoundsInAABB_AllPoints( const AABB& box )
{
for ( uint32_t i = 0; i < 6; ++i )
{
int out = 0;

for ( uint32_t k = 0; k < 8; ++k )
{
float test = glm::dot( box.Corner( k ), planes[ i ].normal ) + planes[ i ].d;

if ( test < 0 )
++out;
}

if ( out == 8 ) // all points rejected for this plane - bail
return false;
}

return true;
}

/*
=============================

Frustum::BoundsInAABB_Closest

Find the closest boint of the AABB
to frustum plane[ i ]. If that point
has a signed distance less than 0
to the plane, we reject it.
Otherwise, we continue to test with the farthest
point of the AABB to the given plane, and update
our intersection enum accordingly.

=============================
*/

bool Frustum::BoundsInAABB_Closest( const AABB& box, frustumPlane_t* intersection )
{
*intersection = FRUST_NONE;

for ( uint32_t i = 0; i < 6; ++i )
{
const vec3& positive = box.GetPointRelativeToNormal( planes[ i ].normal, true );

if ( M_SignedPlaneDistance( &planes[ i ], positive ) < 0 )
return false; // closest point is outside; reject.

const vec3& negative = box.GetPointRelativeToNormal( planes[ i ].normal, false );

if ( M_SignedPlaneDistance( &planes[ i ], negative ) < 0 )
*intersection = ( frustumPlane_t ) i;
}

return true;
}

2

Решение

Задача ещё не решена.

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]