Попробуем ещё разок - я
подумал.
smt005 писал(а):
class C_Vector2
{
public:
float u;
float v;
};
class C_Vector3
{
public:
GLfloat x;
GLfloat y;
GLfloat z;
};
class C_Face
{
public:
unsigned short a;
unsigned short b;
unsigned short c;
};
class C_Mesh
{
public:
unsigned short int iVertex;
C_Vector3 * pVertex;
unsigned short int iNormal;
C_Vector3 * pNormal; // Надо рассчитать
unsigned short int iTangent;
C_Vector3 * pTangent; // Надо рассчитать
unsigned short int iTextCoord;
C_Vector2 * pTextCoord;
unsigned short int iFace;
C_Face * pFace;
};
Тангента, бинормаль и нормаль рассчитываются не для каждой отдельной вершины, а для всего треугольника на основе координат его вершин и их текстурных координат. Т.е. первоначально эти три вектора одинаковы у всех трёх вершин каждого треуга. Это значит, что тебе нужно временно создать ещё три массива C_Vector3 (vec3) для нормалей, бинормалей и тангент каждого фэйса (треуга).
1) Три массива той же размерности, что и массив треугов (их число у тебя == iFace, да?).
Во:
unsigned short int iFace;
C_Face * pFace;
C_Vector3 * pFaceNormal;
C_Vector3 * pFaceTangent;
C_Vector3 * pFaceBinormal;
Эти три массива тебе понадобятся лишь на стадии рассчёта ТБН, т.е. это временные массивы. Так что имеет смысл НЕ держать их в классе модели.
2) Дальше ты циклом проходишь все треуги и вычисляешь для каждого из них нормаль, тангенту и бинормаль, заполняя вышеуказанные массивы. Если ты всё ещё не втыкнул, как вычисляются эти три вектора, распишу подробнее. А так - лень.
3) Сперва обращу внимание на неувязочку:
smt005 писал(а):
unsigned short int iVertex;
...
unsigned short int iNormal;
...
unsigned short int iTangent;
...
unsigned short int iTextCoord;
Вопрос: а разве все четыре счётчика могут быть не равны?
Думаю, ты очепятался. Так что я предположу, что количество вершинных аттрибутов равно количеству вершин и оно есть iVertex. Оки?
Вычисляешь ТБН для каждой вершины:
Код:
//Берёшь по-порядку каждую вершину...
for(int v=0;v<iVertex;v++){
//Создаёшь "контейнеры" для вычисляемых аттрибутов:
C_Vector3 normal(0,0,0), binormal(0,0,0), tangent(0,0,0);
//Ищешь эту вершину в каждом треуге...
for(int f=0;f<iFace;f++)if(pFace[f].a==v||pFace[f].b==v||pFace[f].c==v){
//Нашлась? Суммируем векторочки, "сливая" треуги...
normal+=pFaceNormal[f];
tangent+=pFaceTangent[f];
binormal+=pFaceBinormal[f];
}
//Нормализуем полученные вектора и можно переходить к следующей вершине:
pNormal[v]=normalize(normal);
pTangent[v]=normalize(tangent);
pBinormal[v]=normalize(binormal);
}
Добавлено спустя 59 минут 31 секунду:Победю лень и допишу алгоритм вычисления нормали, тангенты и бинормали для каждого треуга:
Код:
//Берёшь по-порядку каждый треуг...
for(int f=0;f<iFace;f++){
//Вычисляешь два вектора, этот треуг образующих (в вершинном и текстурном пространствах):
C_Vector3 av = pVertex[pFace[f].a] - pVertex[pFace[f].c];
C_Vector3 bv = pVertex[pFace[f].b] - pVertex[pFace[f].c];
C_Vector2 at = pTextCoord[pFace[f].a] - pTextCoord[pFace[f].c];
C_Vector2 bt = pTextCoord[pFace[f].b] - pTextCoord[pFace[f].c];
//Ещё понадобится кое-что:
double div = 1.0/(at.x*bt.y - at.y*bt.x);
//Теперь можно вычислить нормаль, тангенту и бинормаль для треуга:
pFaceNormal[f]=normalize(cross(av,bv));
pFaceTangent[f]=normalize((av*bt.y - bv*at.y)*div);
pFaceBinormal[f]=normalize((bv*at.x - av*bt.x)*div);
}//Следующий треуг гоу!