struct plane { float a,b,c,d; }; struct point { float x,y,z; }; int main (void) { plane p = { 1.0, 0.0, 0.0, -20.0 }; point v = { 25.0, 0.0, 0.0 }; float distance = p.a * v.x + p.b * v.y + p.c * v.z + p.d; //distance = 5 return 0; }
Правило. Если нормаль плоскости смотрит в сторону начала координат, то дистанция до плоскости пложительная, иначе дистанция до плоскости отрицательная.
Пусть у нас есть плоскость, нормаль направлена вдоль положительного направления оси X, плосокость расположена на 20 единиц по оси X в положительном направлении, это значит начало координат с обратной стороны плоскости, за плоскостью, дистанция отрицательное значение -20. Если бы нормаль была направлена в строну начала координат, то дистанция в этом случае была бы положительной - значение 20 единиц.
Пусть у нас есть точка- точка лежит по оси X на расстоянии 25 единиц от начала координат.
Вполне логично- расстояние от точки до плоскости 5 единиц, что подтверждаеться формулой.
float distance = 1.0 * 25.0 + 0 * 0 + 0 * 0 + (-20.0) = 25.0 - 20.0 = 5.0;
Пусть у нас есть нормаль n и вектор v, и плоскость проходит через центр координатной системы, тогда дистанция до плоскости 0, а следующая формула покажет расстояние от точки v до плоскости:
float distance = n.x * v.x + n.y * v.y + n.z * v.z;
Формулу определения расстояния от точки до полоскости можно использовать в тех случаях когда нужно определить- точка расположена перед плоскостью, или за плоскостью. В нашем случае расстояние от точки до полоскости положительное число 5 единиц, то есть точка расположена перед плосокстью. Если бы дистанция была отрицательной- это значит что точка расположена с обратной стороны плоскости. Если дистанция равна 0 то точка лежит на плоскости. Обратная сторона плоскости это та которая расположена в обратном направлении нормали к плоскости. То есть нормаль показывает в одну сторону, а обратная сторона плоскости (отрицательная дистацния) с другой стороны.
Если мы хотим поменять знак дистацнию плоскости от начала координат мы должны инвертировать ее нормаль, то есть нормаль умножить на -1. Например эти две плоскости p1 и p2 аналогичны, расположены на 20 единиц от начала координат, отличаються только направлением нормали. Эти две плоскости лежат в одной плоскости.
plane p1 = { 1.0, 0.0, 0.0, -20.0 }; plane p2 = { -1.0, 0.0, 0.0, 20.0 };
Следует раличать такие понятия как- расстояние плоскости от начала координат, расстояние точки от плоскости, и расстояние точки от начала координат.
Уравнение плоскости: Ax + By + Cz + D = 0
Любая точка пространства либо принадлежит плоскости, либо «спереди» от плоскости, либо «за» плоскостью. Плоскость определяется четырьмя числами: A,B,C и D, где {A,B,C} – вектор нормали к этой плоскости, а D – расстояние до начала координат. Что бы понять находится ли точка перед плоскостью или нет надо вычислить расстояние от точки плоскости. Если расстояние положительно, значит, точка лежит перед плоскостью, отрицательна – значит за плоскостью. Вот формула для вычисления расстояния точки до плоскости:
distance = A * X + B * Y + C * Z + D
Где A, B, C, и D - четыре числа, которые определяют плоскость и X, Y, и Z - координаты точки.
Предположим мы извлекли 6 плоскостей области просмотра из матриц World, View, Projection.
float frustum[6][4];
Теперь мы можем написать функцию для проверки - видима точка или нет.
bool PointInFrustum( float x, float y, float z ) { int p; for( p = 0; p < 6; p++ ) if( frustum[p][0] * x + frustum[p][1] * y + frustum[p][2] * z + frustum[p][3] <= 0 ) return false; return true; } bool PolygonInFrustum( int numpoints, vertex* pointlist ) { int f, p; for( f = 0; f < 6; f++ ) { for( p = 0; p < numpoints; p++ ) { if( frustum[f][0] * pointlist[p].x + frustum[f][1] * pointlist[p].y + frustum[f][2] * pointlist[p].z + frustum[f][3] > 0 ) break; } if( p == numpoints ) return false; } return true; }