OpenGL Расчет нормалей (квадраторов) - PullRequest
0 голосов
/ 17 января 2012

Моя проблема касается OpenGL и нормалей, я понимаю математику, стоящую за ними, и у меня есть некоторый успех.

Функция, которую я прикрепил ниже, принимает чередованный массив вершин и вычисляет нормали для каждых 4 вершин. Они представляют КВАДЫ, имеющие одинаковые направления. Насколько я понимаю, эти 4 вершины должны иметь одинаковую Нормаль. Пока они сталкиваются одинаково.

Проблема, с которой я столкнулся, заключается в том, что мои квадро-карты рендеринга с диагональным градиентом, примерно так: Световой эффект - За исключением того, что тень находится посередине, а свет в углах.

Я рисую свои квады последовательно. TopLeft, TopRight, BottomRight, BottomLeft и вершины, которые я использую для вычисления моих нормалей: TopRight - TopLeft и BottomRight - TopLeft.

Надеюсь, кто-то увидит что-то, на чем я допустил ошибку, но я занимался этим часами, чтобы не победить.

Для записи я отрисовываю куб, а чайник рядом с моими объектами, чтобы проверить, работает ли мое освещение, поэтому я совершенно уверен, что нет проблем с положением света.

void CalculateNormals(point8 toCalc[], int toCalcLength)
{
    GLfloat N[3], U[3], V[3];//N will be our final calculated normal, U and V will be the subjects of cross-product
    float length;

for (int i = 0; i < toCalcLength; i+=4) //Starting with every first corner QUAD vertice
{
    U[0] = toCalc[i+1][5] - toCalc[i][5]; U[1] = toCalc[i+1][6] - toCalc[i][6]; U[2] = toCalc[i+1][7] - toCalc[i][7]; //Calculate Ux Uy Uz 
    V[0] = toCalc[i+3][5] - toCalc[i][5]; V[1] = toCalc[i+3][6] - toCalc[i][6]; V[2] = toCalc[i+3][7] - toCalc[i][7]; //Calculate Vx Vy Vz

    N[0] = (U[1]*V[2]) - (U[2] * V[1]);
    N[1] = (U[2]*V[0]) - (U[0] * V[2]);
    N[2] = (U[0]*V[1]) - (U[1] * V[0]);

    //Calculate length for normalising
    length = (float)sqrt((pow(N[0],2)) + (pow(N[1],2)) + (pow(N[2],2)));

    for (int a = 0; a < 3; a++)
    {
        N[a]/=length;
    }

    for (int j = 0; i < 4; i++)
    {
                    //Apply normals to QUAD vertices (3,4,5 index position of normals in interleaved array)
        toCalc[i+j][3] = N[0]; toCalc[i+j][4] = N[1]; toCalc[i+j][5] = N[2];
    }
}
}

Ответы [ 3 ]

2 голосов
/ 17 января 2012

Похоже, ваши for-loops кусают вас.

for (int i = 0; i < toCalcLength; i+=4) //Starting with every first corner QUAD vertice
{
  ...
  for (int j = 0; i < 4; i++)
  { //            ^      ^
    // Should you be using 'j' instead of 'i' here?
    // j will never increment
    // This loop won't be called at all after the first time through the outer loop
    ...
  }
}
2 голосов
/ 17 января 2012

Вы используете индексы 3, 4 и 5 для нормального хранения:

toCalc[i+j][3] = N[0]; toCalc[i+j][4] = N[1]; toCalc[i+j][5] = N[2];

И вы используете индексы 5 , 6и 7 для получения координат точки:

U[0] = toCalc[i+1][5] - toCalc[i][5]; U[1] = toCalc[i+1][6] - toCalc[i][6]; U[2] = toCalc[i+1][7] - toCalc[i][7];

Эти индексы перекрываются (общий индекс normal.x совпадает с индексом position.z), чего не должно быть.


Рекомендации:

  1. Поместите все в структуры.
  2. Либо:
    1. Использовать библиотеку математики.
    2. ИЛИ помещать векторную арифметику в отдельные подпрограммы с соответствующим именем.
  3. Вместо этого использовать именованные переменныеиндексов.

Тем самым вы уменьшите количество ошибок в своем коде.a.position.x легче читать, чем quad[0][5], и легче исправить опечатку в векторной операции, когда код не был скопирован.


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

struct Vector3{
    union{
        struct{
            float x, y, z;
        };
        float v[3];
    };
};    

Для вычисления нормалей в квадрате ABCD

A--B
|  |
C--D

Используйте формулу:

normal = normalize ((B.положение - A.position) X (C.position - A.position)).

ИЛИ

normal = normalize ((D.position - A.position) X (C.position -B.position)).

Где «X» означает «перекрестное произведение».

В любом случае все будет хорошо.

2 голосов
/ 17 января 2012

Кажется, что вы берете значения положения вершины для использования в вычислениях из индексов 5, 6 и 7, а затем записываете нормали в индексах 3, 4 и 5. Обратите внимание, как индекс 5 используется в обоих. Я полагаю, один из них не правильный.

...