Отсечение невидимой геометрии (13 стр)
slava_mib
Ладно, буду перепроверять, но всё нормализуется. Пробовал пример для не нормализованных плоскостей, результат лучше, но чёт не то...
P.S. Нет, всё перепроверил, именно проверка на сферу работает косячно!
А теперь вопрос ко всем: где можно покурить пример реализации Ray Casting? Хочется ещё его добавить и убить эту тему, чтоб сделать универсальное решение для большинства задач и без надобности не заморачиваться на всяких порталах и прочих вещах.
Daniil Petrov, покажи реализацию (код).
> где можно покурить пример реализации Ray Casting?
Рейкастинг - оно не совсем по теме куллинга, если что ) По крайней мере рилтайм-куллинга.
slava_mib
> Рейкастинг - оно не совсем по теме куллинга, если что ) По крайней мере рилтайм-куллинга.
Бля :)))
Расчёт фрастама:
+ Показать
− Скрыть
void CFrustum::ExtractFrustum(const glm::mat4 mProjMatrix, const glm::mat4 mModelView)
{
glm::mat4 ClippingPlane = mProjMatrix * mModelView;
FrustumPyramid[RIGHT].x = ClippingPlane[0].w - ClippingPlane[0].x;
FrustumPyramid[RIGHT].y = ClippingPlane[1].w - ClippingPlane[1].x;
FrustumPyramid[RIGHT].z = ClippingPlane[2].w - ClippingPlane[2].x;
FrustumPyramid[RIGHT].w = ClippingPlane[3].w - ClippingPlane[3].x;
FrustumPyramid[RIGHT] = glm::normalize(FrustumPyramid[RIGHT]);
FrustumPyramid[LEFT].x = ClippingPlane[0].w + ClippingPlane[0].x;
FrustumPyramid[LEFT].y = ClippingPlane[1].w + ClippingPlane[1].x;
FrustumPyramid[LEFT].z = ClippingPlane[2].w + ClippingPlane[2].x;
FrustumPyramid[LEFT].w = ClippingPlane[3].w + ClippingPlane[3].x;
FrustumPyramid[LEFT] = glm::normalize(FrustumPyramid[LEFT]);
FrustumPyramid[BOTTOM].x = ClippingPlane[0].w + ClippingPlane[0].y;
FrustumPyramid[BOTTOM].y = ClippingPlane[1].w + ClippingPlane[1].y;
FrustumPyramid[BOTTOM].z = ClippingPlane[2].w + ClippingPlane[2].y;
FrustumPyramid[BOTTOM].w = ClippingPlane[3].w + ClippingPlane[3].y;
FrustumPyramid[BOTTOM] = glm::normalize(FrustumPyramid[BOTTOM]);
FrustumPyramid[TOP].x = ClippingPlane[0].w - ClippingPlane[0].y;
FrustumPyramid[TOP].y = ClippingPlane[1].w - ClippingPlane[1].y;
FrustumPyramid[TOP].z = ClippingPlane[2].w - ClippingPlane[2].y;
FrustumPyramid[TOP].w = ClippingPlane[3].w - ClippingPlane[3].y;
FrustumPyramid[TOP] = glm::normalize(FrustumPyramid[TOP]);
FrustumPyramid[BACK].x = ClippingPlane[0].w - ClippingPlane[0].z;
FrustumPyramid[BACK].y = ClippingPlane[1].w - ClippingPlane[1].z;
FrustumPyramid[BACK].z = ClippingPlane[2].w - ClippingPlane[2].z;
FrustumPyramid[BACK].w = ClippingPlane[3].w - ClippingPlane[3].z;
FrustumPyramid[BACK] = glm::normalize(FrustumPyramid[BACK]);
FrustumPyramid[FRONT].x = ClippingPlane[0].w + ClippingPlane[0].z;
FrustumPyramid[FRONT].y = ClippingPlane[1].w + ClippingPlane[1].z;
FrustumPyramid[FRONT].z = ClippingPlane[2].w + ClippingPlane[2].z;
FrustumPyramid[FRONT].w = ClippingPlane[3].w + ClippingPlane[3].z;
FrustumPyramid[FRONT] = glm::normalize(FrustumPyramid[FRONT]);
}
Каждая плоскость нормализуется, всё по урокам NeHe :)
Проверка сферы:
+ Показать
− Скрыть
bool CFrustum::SphereInFrustum(glm::vec3 Center, float Radius)
{
for (int i = 0; i < 6; i++)
{
if (FrustumPyramid[i].x * Center.x + FrustumPyramid[i].y * Center.y + FrustumPyramid[i].z * Center.z + FrustumPyramid[i].w <= -Radius)
return false;
}
return true;
}
> FrustumPyramid[RIGHT] = glm::normalize(FrustumPyramid[RIGHT]);
Daniil Petrov, может проблема тут? Ты 4хмерный вектор нормализуешь? Нормализовать-то надо только нормаль - т.е. x/y/z, но не w...
> А здесь разве не так?
Daniil Petrov, нет, там не так, обрати внимание на строки
t = sqrt( frustum[0][0] * frustum[0][0] + frustum[0][1] * frustum[0][1] + frustum[0][2] * frustum[0][2] );
Тут при расчёте t берутся только x/y/z , а делятся на это значение - x/y/z/w
Т.е. это совершенно не то же самое, что normalize(vec4)
На всякий случай тебе код из моего двига:
void Culler::normalizePlanes()
{
for (int i=0; i<m_planesCount; i++)
{
const float l = sqrtf(getPlaneVar(i, 0)*getPlaneVar(i, 0) + getPlaneVar(i, 1)*getPlaneVar(i, 1) + getPlaneVar(i, 2)*getPlaneVar(i, 2));
plane_var(i, 0) = plane_var(i, 0)/l;
plane_var(i, 1) = plane_var(i, 1)/l;
plane_var(i, 2) = plane_var(i, 2)/l;
plane_var(i, 3) = plane_var(i, 3)/l;
}
}
slava_mib
Я уже взял отсюда: http://masandilov.ru/opengl/opengl-frustum, но за подсказку благодарю :))) я в тригонометрии не силён, а тут она ещё и на программировании основана, так что мне вдвойне сложнее грызть этот гранит науки!
Но вот с радиусом маленько что-то не то, но буду разбираться!
if( dot( sphere->center, plane->normal ) - plane->dist <= -sphere->radius )
return true; // sphere culled
Как можно накосячить в одной строчке?
А, всё дошло. У тебя плоскости стандартные, а не позитивные.
Center.z + FrustumPyramid[i].w
плюс на минус поменяй.
g-cont
> плюс на минус поменяй.
Таки неправильно - всё исчезает!
Да всё уже, разобрался, там только несрастушки с радиусом были :) теперь оформить обработку параллелепипеда и всё!
Интересное дело - после того, как нормализацию плоскостей исправил на верную и сфера стала отсекаться верно, куб стал отсекаться по точке Center, словно выполняется функция PointInFrustum :)))
Вот код куба, взятый из уроков NeHe:
+ Показать
− Скрыть
bool CFrustum::CubeInFrustum(const glm::vec3 Center, const float Size)
{
for (int i = 0; i < 6; i++)
{
if (FrustumPyramid[i].x * (Center.x - Size) + FrustumPyramid[i].y * (Center.y - Size) + FrustumPyramid[i].z * (Center.z - Size) + FrustumPyramid[i].w > 0)
continue;
if (FrustumPyramid[i].x * (Center.x + Size) + FrustumPyramid[i].y * (Center.y - Size) + FrustumPyramid[i].z * (Center.z - Size) + FrustumPyramid[i].w > 0)
continue;
if (FrustumPyramid[i].x * (Center.x - Size) + FrustumPyramid[i].y * (Center.y + Size) + FrustumPyramid[i].z * (Center.z - Size) + FrustumPyramid[i].w > 0)
continue;
if (FrustumPyramid[i].x * (Center.x + Size) + FrustumPyramid[i].y * (Center.y + Size) + FrustumPyramid[i].z * (Center.z - Size) + FrustumPyramid[i].w > 0)
continue;
if (FrustumPyramid[i].x * (Center.x - Size) + FrustumPyramid[i].y * (Center.y - Size) + FrustumPyramid[i].z * (Center.z + Size) + FrustumPyramid[i].w > 0)
continue;
if (FrustumPyramid[i].x * (Center.x + Size) + FrustumPyramid[i].y * (Center.y - Size) + FrustumPyramid[i].z * (Center.z + Size) + FrustumPyramid[i].w > 0)
continue;
if (FrustumPyramid[i].x * (Center.x - Size) + FrustumPyramid[i].y * (Center.y + Size) + FrustumPyramid[i].z * (Center.z + Size) + FrustumPyramid[i].w > 0)
continue;
if (FrustumPyramid[i].x * (Center.x + Size) + FrustumPyramid[i].y * (Center.y + Size) + FrustumPyramid[i].z * (Center.z + Size) + FrustumPyramid[i].w > 0)
continue;
return false;
}
return true;
}
ну, решение очевидно - пора начинать разбираться в том, что ты делаешь, вместо того, что бы просто копипастить :)))
slava_mib
В коде бы я ещё разобрался, но тут ещё и математика :) придётся, конечно!
Box in frustum.) у Кармака погляди, там более ясно все
> там более ясно все
barnes, да уж куда там ещё более ясно, чем расстояние от точки до плоскости )))