Отсекатель Кохена-Сазерленда в 3Д
От: Wordex  
Дата: 30.11.10 21:33
Оценка:
Добрый всем день. Переписываю такие колеса как вивод линии (за Брезенхемом), проекцию и др. — среди них — отсекатель Кохена-Сазерленда. Сперва сделал отсекатель уже проецированной линии (тоесть 2Д-отсекатель), который работает прекрасно. Теперь делаю отсекатель в каноническом обьеме. С етим как рас и проблемы, поетому надеюсь на читателей книги Френсис Хил — програмирование компютерной графики в OpenGl. Вопшем суть: в алгоритме из книги предлагается делать отсекание после преобразования в кан. обьем, которое будет выглядеть так: x <= 1 && x >= -1 && y <= 1 && y >= -1 && z <= 1 && z >= -1. (Пример грубый, но пока хватит). Так вот,проблема в том, что точки фигур у меня в програме имееют кооординаты куда больше |1|, например 600, 800, и т. п. Я все сделал так, как в книжке было написано, но сделать нормальний 3Д отсекатель пока не получилось. В чем может быть проблема? Привожу код моих функций вичисления проекции точки и ее текущего преобразования:

void Perspective(int viewAngle, float aspect, float N, float F) //функция для установки значений матрицы перспективной проекции
{
    float top = N * TanTable[viewAngle >> 1]; // TanTable у меня есть протабулированная фия Tan в районе 0..360 градусов с шагом 1 градус
    float bot = -top;
    float right = top * aspect;
    float left = -right;
    PR[0][0] = 2 * N * (right - left); // PR[4][4] - моя матрица проецирования
    PR[1][1] = 2 * N * (top - bot);
    PR[0][2] = (right + left) / (right - left);
    PR[1][2] = (top + bot) / (top - bot);
    PR[2][2] = - (F + N) / (F - N);
    PR[2][3] = - 2 * F * N / (F - N);
}
//теперь к каждой точке моей полигональной сетки я применяю матрицы VM, Projection, ViewPort
inline int TransformProject(COORDINATE &x1, COORDINATE &y1, COORDINATE &z1)
{
    float x = x1 * CT[tp][0][0] + y1 * CT[tp][0][1] + z1 * CT[tp][0][2] + CT[tp][0][3]; //Current transformation - CT[4][4] - совокупность афинних
    float y = x1 * CT[tp][1][0] + y1 * CT[tp][1][1] + z1 * CT[tp][1][2] + CT[tp][1][3]; //преобразований + преобразование камеры - я использую преобразования системы координат, как в OpenGl, точка * Матрицу преобразования
    float z = x1 * CT[tp][2][0] + y1 * CT[tp][2][1] + z1 * CT[tp][2][2] + CT[tp][2][3]; //Ошибка ТОЧНО НЕ ТУТ, 

    x = -(PR[0][0] * x + PR[0][2] * z) / z;
    y = -(PR[1][1] * y + PR[1][2] * z) / z; //<---перспективное преобразование, проблема гдето-тут..?
    z = -(PR[2][2] * z + PR[2][3]) / z;  <-|    //<--- z - ето псевдоглубина
        //использовал формулу:                 |----------------------------<-----------
        (  2 * N                      right + left                  )      (       )   |
        |------------     0           -------------     0           |      |   x   |   |
        |right - left                 right - left                  |      |       |   ^
        |                                                           |      |       |   |
        |                2 * N        top + bot                     |      |       |   |
        |      0       ---------      ----------        0           |      |   y   |   |
        |              top - left     top - bot                     | *    |       | = |
        |                                                           |      |       |
        |                              F + N            2 * F * N   |      |       |
        |      0           0        - --------       - -----------  |      |   z   |
        |                              F - N              F - N     |      |       |
        |                                                           |      |       |
        (      0           0            -1                  0       )      (   1   )
    
        //пройдясь дебагером, в етом месте вияснил, что первая координата х имеет значение 4000.0

        x1 = VP.A * x + VP.C; //в порт просмотра, тут ТОЖЕ 100% проблем нет.
    y1 = VP.B * y + VP.D;
}

Perspective(90, 1.25, 10.0, 100.0); - так вызываю ее в коде, а для дальнейшего постоянно использования запихаю ее в стек - Push().



Если у моей проге использовать формулу x <= 1 && x >= -1 && y <= 1 && y >= -1 && z <= 1 && z >= -1 — то врядли увидим мзображение, но если использовать x <= 100 && x >= -100 && y <= 100 && y >= -100 && z <= 100 && z >= -100 — то получим малий квадрат в центе екрана.

Почему точки не имеють коодринат от -1 до 1? Где я ошибся?

В своей програме я рисую домик из книги Френсис Хил, где координата по х некоторой вершыны равна 10. Если я применю к ней перспективное преобразование, значит ли ето, что ета координата сожметься в диапазон -1..1? Почему тогда производиться отсекание границами -1..1? Где суть?
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.