2012-01-17 4 views
0

Моя проблема касается OpenGL и Normals, я понимаю математику позади них, и у меня есть некоторый успех.OpenGL Calculating Normals (Quads)

Функция, приведенная ниже, принимает перемеженный вершинный массив и вычисляет нормали для каждых четырех вершин. Они представляют собой QUADS, которые имеют одинаковые направления. По моему мнению, эти четыре вершины должны иметь один и тот же Normal. Пока они сталкиваются одинаково.

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

Я рисую свои QUADS в последовательном порядке. 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]; 
    } 
} 
} 
+0

Это C++; вы рассматривали использование математической библиотеки, например [GLM] (http://glm.g-truc.net/)? –

+0

К сожалению, это для задания, и поэтому мы не поощряем использование библиотек. – LBHoward

ответ

2

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

+0

Огромное вам спасибо, у меня было ощущение, что это были несколько небольших проблем, которые смотрели мне в лицо. Крайний срок - в четверг, поэтому я работал без остановок, чтобы сгладить окончательные проблемы. – LBHoward

2

Похоже, что ваш 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 
    ... 
    } 
} 
+0

Хорошо заметили, это вызывает огромную проблему. Благодаря! – LBHoward

2

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

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

И вы использовать индексы , 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]; 

Эти индексы перекрываются (нормаль.x имеет тот же индекс, что и position.z), w это не должно происходить.


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

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

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


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

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

Для calcualting нормальна в четырехъядерных ABCD

A--B 
| | 
C--D 

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

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

ИЛИ

нормальные = нормализуют ((D.position - A.position) Х (C.position - B.position)).

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

В любом случае это будет нормально работать.

+0

Спасибо за ввод, математика была на месте, но, как вы правильно указываете, у меня были нормали, перекрывающие мои Вершины. – LBHoward