Новичок
Профиль
Группа: Участник
Сообщений: 9
Регистрация: 31.5.2006
Репутация: нет Всего: нет
|
Проблема с вычислениями нормалей в OpenGL. Задача состоит в вычислении нормалей для вершин только один раз и в занисении полученных данных в массив. Затем при каждой новой отрисовке модели мы будем брать данные о нормали для каждой вершины уже из полученного массива, а не вычислять их каждый раз при перересовке модели. Код реализации данной задачи: | Код | // init == true : идёт инициализация // init == false : инициализация уже была, и нормали не высчитываем if(init) { for(int j = 0; j < qualTr; j++) { u = detour[j * 3] - 1; // первая вершина i = detour[j * 3 + 1] - 1; // вторая вершина o = detour[j * 3 + 2] - 1; // третья вершина
// вычисление вектора перпендикулярного грани треугольника float r1[ 3 ], r2[ 3 ]; for (int k = 0; k < 3; k++) { r1[ k ] = locvec[i * 3 + k + 3] - locvec[u * 3 + k + 3]; r2[ k ] = locvec[o * 3 + k + 3] - locvec[u * 3 + k + 3]; } // векторное произведение 2-x векторов // x, y, z - координаты нормали x = r1[ 1 ] * r2[ 2 ] - r1[ 2 ] * r2[ 1 ]; y = r1[ 2 ] * r2[ 0 ] - r1[ 0 ] * r2[ 2 ]; z = r1[ 0 ] * r2[ 1 ] - r1[ 1 ] * r2[ 0 ]; // нормализуем нормаль - т.е. приводим к единичному вектору d = sqrt( x * x + y * y + z * z ); if(d == 0) d = 1; x /= d; y /= d; z /= d;
// заносим вычисленные нормали в массив for(int k = 0; k < 3; k++) mechanism->setNormal(numpart, numgener, k, 0);
mechanism->setNormal(numpart, numgener, u * 3 + 3, x); mechanism->setNormal(numpart, numgener, u * 3 + 1 + 3, y); mechanism->setNormal(numpart, numgener, u * 3 + 2 + 3, z);
mechanism->setNormal(numpart, numgener, i * 3 + 3, x); mechanism->setNormal(numpart, numgener, i * 3 + 1 + 3, y); mechanism->setNormal(numpart, numgener, i * 3 + 2 + 3, z);
mechanism->setNormal(numpart, numgener, o * 3 + 3, x); mechanism->setNormal(numpart, numgener, o * 3 + 1 + 3, y); mechanism->setNormal(numpart, numgener, o * 3 + 2 + 3, z); } } // отрисовываем модель for(int j = 0; j < qualTr; j++) { u = detour[j * 3] - 1; i = detour[j * 3 + 1] - 1; o = detour[j * 3 + 2] - 1;
glBegin( GL_TRIANGLES ); // достаём нормаль для 1-ой вершины glNormal3f(locnorm[u * 3 + 3], locnorm[u * 3 + 3 + 1], locnorm[u * 3 + 3 + 2]); float v[ 3 ]; for( int k = 0; k < 3; k++ ) v[ k ] = locvec[u * 3 + k + 3]; glVertex3fv( v );
// достаём нормаль для 2-ой вершины glNormal3f(locnorm[i*3 +3], locnorm[i * 3 + 3 + 1], locnorm[i * 3 + 3 + 2]); for( int k = 0; k < 3; k++ ) v[ k ] = locvec[i * 3 + k + 3]; glVertex3fv( v );
// достаём нормаль для 3-ей вершины glNormal3f(locnorm[o*3 +3], locnorm[o * 3 + 3 + 1], locnorm[o * 3 + 3 + 2]); for( int k = 0; k < 3; k++ ) v[ k ] = locvec[o * 3 + k + 3]; glVertex3fv( v ); glEnd(); }
|
И полученное изображение получается изломанным:  Теперь же если заставить программу во время каждой отрисовки модели вычислять нормаль (комментируем несколько строк) для треугольника, который мы рисуем в текущий момент, то получаем "по красивее" изображение (падение FPS в 15 раз, т.к. нормали вычисляются каждый раз). Код: | Код | // init == true : идёт инициализация // init == false : инициализация уже была, и нормали не высчитываем //if(init) //{ for(int j = 0; j < qualTr; j++) { u = detour[j * 3] - 1; // первая вершина i = detour[j * 3 + 1] - 1; // вторая вершина o = detour[j * 3 + 2] - 1; // третья вершина
// вычисление вектора перпендикулярного грани треугольника float r1[ 3 ], r2[ 3 ]; for (int k = 0; k < 3; k++) { r1[ k ] = locvec[i * 3 + k + 3] - locvec[u * 3 + k + 3]; r2[ k ] = locvec[o * 3 + k + 3] - locvec[u * 3 + k + 3]; } // векторное произведение 2-x векторов // x, y, z - координаты нормали x = r1[ 1 ] * r2[ 2 ] - r1[ 2 ] * r2[ 1 ]; y = r1[ 2 ] * r2[ 0 ] - r1[ 0 ] * r2[ 2 ]; z = r1[ 0 ] * r2[ 1 ] - r1[ 1 ] * r2[ 0 ]; // нормализуем нормаль - т.е. приводим к единичному вектору d = sqrt( x * x + y * y + z * z ); if(d == 0) d = 1; x /= d; y /= d; z /= d;
// заносим вычисленные нормали в массив for(int k = 0; k < 3; k++) mechanism->setNormal(numpart, numgener, k, 0);
mechanism->setNormal(numpart, numgener, u * 3 + 3, x); mechanism->setNormal(numpart, numgener, u * 3 + 1 + 3, y); mechanism->setNormal(numpart, numgener, u * 3 + 2 + 3, z);
mechanism->setNormal(numpart, numgener, i * 3 + 3, x); mechanism->setNormal(numpart, numgener, i * 3 + 1 + 3, y); mechanism->setNormal(numpart, numgener, i * 3 + 2 + 3, z);
mechanism->setNormal(numpart, numgener, o * 3 + 3, x); mechanism->setNormal(numpart, numgener, o * 3 + 1 + 3, y); mechanism->setNormal(numpart, numgener, o * 3 + 2 + 3, z); //} //} // отрисовываем модель //for(int j = 0; j < qualTr; j++) //{ u = detour[j * 3] - 1; i = detour[j * 3 + 1] - 1; o = detour[j * 3 + 2] - 1;
glBegin( GL_TRIANGLES ); // достаём нормаль для 1-ой вершины glNormal3f(locnorm[u * 3 + 3], locnorm[u * 3 + 3 + 1], locnorm[u * 3 + 3 + 2]); float v[ 3 ]; for( int k = 0; k < 3; k++ ) v[ k ] = locvec[u * 3 + k + 3]; glVertex3fv( v );
// достаём нормаль для 2-ой вершины glNormal3f(locnorm[i*3 +3], locnorm[i * 3 + 3 + 1], locnorm[i * 3 + 3 + 2]); for( int k = 0; k < 3; k++ ) v[ k ] = locvec[i * 3 + k + 3]; glVertex3fv( v );
// достаём нормаль для 3-ей вершины glNormal3f(locnorm[o*3 +3], locnorm[o * 3 + 3 + 1], locnorm[o * 3 + 3 + 2]); for( int k = 0; k < 3; k++ ) v[ k ] = locvec[o * 3 + k + 3]; glVertex3fv( v ); glEnd(); }
|
Изображение теперь выглядит так:  Теперь же решил дальше поэкспериментировать и заставить программу во время каждой отрисовки вычислить вначале все нормали для каждой вершины, а уже только потом отрисовать треугольники (падение FPS в 15 раз, т.к. нормали вычисляются каждый раз): | Код | // init == true : идёт инициализация // init == false : инициализация уже была, и нормали не высчитываем //if(init) //{ for(int j = 0; j < qualTr; j++) { u = detour[j * 3] - 1; // первая вершина i = detour[j * 3 + 1] - 1; // вторая вершина o = detour[j * 3 + 2] - 1; // третья вершина
// вычисление вектора перпендикулярного грани треугольника float r1[ 3 ], r2[ 3 ]; for (int k = 0; k < 3; k++) { r1[ k ] = locvec[i * 3 + k + 3] - locvec[u * 3 + k + 3]; r2[ k ] = locvec[o * 3 + k + 3] - locvec[u * 3 + k + 3]; } // векторное произведение 2-x векторов // x, y, z - координаты нормали x = r1[ 1 ] * r2[ 2 ] - r1[ 2 ] * r2[ 1 ]; y = r1[ 2 ] * r2[ 0 ] - r1[ 0 ] * r2[ 2 ]; z = r1[ 0 ] * r2[ 1 ] - r1[ 1 ] * r2[ 0 ]; // нормализуем нормаль - т.е. приводим к единичному вектору d = sqrt( x * x + y * y + z * z ); if(d == 0) d = 1; x /= d; y /= d; z /= d;
// заносим вычисленные нормали в массив for(int k = 0; k < 3; k++) mechanism->setNormal(numpart, numgener, k, 0);
mechanism->setNormal(numpart, numgener, u * 3 + 3, x); mechanism->setNormal(numpart, numgener, u * 3 + 1 + 3, y); mechanism->setNormal(numpart, numgener, u * 3 + 2 + 3, z);
mechanism->setNormal(numpart, numgener, i * 3 + 3, x); mechanism->setNormal(numpart, numgener, i * 3 + 1 + 3, y); mechanism->setNormal(numpart, numgener, i * 3 + 2 + 3, z);
mechanism->setNormal(numpart, numgener, o * 3 + 3, x); mechanism->setNormal(numpart, numgener, o * 3 + 1 + 3, y); mechanism->setNormal(numpart, numgener, o * 3 + 2 + 3, z); } //} // отрисовываем модель for(int j = 0; j < qualTr; j++) { u = detour[j * 3] - 1; i = detour[j * 3 + 1] - 1; o = detour[j * 3 + 2] - 1;
glBegin( GL_TRIANGLES ); // достаём нормаль для 1-ой вершины glNormal3f(locnorm[u * 3 + 3], locnorm[u * 3 + 3 + 1], locnorm[u * 3 + 3 + 2]); float v[ 3 ]; for( int k = 0; k < 3; k++ ) v[ k ] = locvec[u * 3 + k + 3]; glVertex3fv( v );
// достаём нормаль для 2-ой вершины glNormal3f(locnorm[i*3 +3], locnorm[i * 3 + 3 + 1], locnorm[i * 3 + 3 + 2]); for( int k = 0; k < 3; k++ ) v[ k ] = locvec[i * 3 + k + 3]; glVertex3fv( v );
// достаём нормаль для 3-ей вершины glNormal3f(locnorm[o*3 +3], locnorm[o * 3 + 3 + 1], locnorm[o * 3 + 3 + 2]); for( int k = 0; k < 3; k++ ) v[ k ] = locvec[o * 3 + k + 3]; glVertex3fv( v ); glEnd(); }
|
И изображение как в первом варианте с "ломаным" светом. Чертовщина какая-то: ведь во всех трёх случаях данные о нормалях одинаковые, просто каждый раз по-разному идёт отрисовка модели, но и изображение каждый раз разное. Помогите кто уже сталкивался с вычислениями нормалей, м.б. уже были подобные трудности. Если нет, то прошу просто помочь разобраться, проект уже третий день стоит из-за этой проблемы.
|