2013-07-07 1 views
1

Я пытаюсь реализовать импортер .3ds в соответствии с this documentation, и я подошел к этапу, когда мне нужно вычислить нормали вершин, потому что файлы .3ds не предоставляют таких. Вот код Java:Расчет нормалей модели .3ds

/* Sctructure of vertex array is {x0, y0, z0, x1, y1, z1...} 
* 
* Basically, MathUtils.generateNormal_f(x0,y0,z0, x1,y1,z1, x2,y2,z2) is cross 
* product between (x1-x0, y1-y0, z1-z0) and (x2-x0, y2-y0, z2-z0) */ 

normals = new float[this.vertex.length]; //every vertex has it's own normal 
int n = 0; 
for (int i=0; i<this.index.length; i++){ 
    float[] Normal = MathUtils.generateNormal_f(//getting xyz coords of 1 normal 
      vertex[index[i]*3], vertex[index[i]*3+1], vertex[index[i]*3+2], 
      vertex[index[++i]*3], vertex[index[i]*3+1], vertex[index[i]*3+2], 
      vertex[index[++i]*3], vertex[index[i]*3+1], vertex[index[i]*3+2]); 

    normals[n++] = Normal[0]; 
    normals[n++] = Normal[1]; 
    normals[n++] = Normal[2]; 
} 

Метод MathUtils.generateNormal_f(...) протестирована и работает отлично. Результат этого кода можно увидеть ниже (первое изображение). Например, во втором изображении каждая нормальная модель одинакова и указывает на источник света.

Вопрос: как правильно рассчитать нормали?

Generated normals Every vertex has (1,0,0) normal

ответ

1

Ваши нормалей может быть обращена.

Я не очень хорошо помню формат 3ds, но проверьте, можете ли вы экспортировать и импортировать нормали из файла, а не вычислять их.

P.S. также не используйте магию следующим образом:

vertex[index[i]*3], vertex[index[i]*3+1], vertex[index[i]*3+2], 
vertex[index[++i]*3], vertex[index[i]*3+1], vertex[index[i]*3+2], 
vertex[index[++i]*3], vertex[index[i]*3+1], vertex[index[i]*3+2] 

Вы получите разные результаты, основанные на последовательности оценки аргументов. лучше явно использовать [i], [i + 1], [i + 2] при вызове вычисления нормального ...

+0

3ds действительно не имеет нормалей, все приложение было построено вокруг идеи, что нормали вычисляются сглаживанием групп. Который работает отлично, я вас точка дать пользователям любые другие варианты. – joojaa

+0

1. Нет, нормали не инвертируются. Они просто случайно указывают везде. 2. Формат 3ds вообще не поддерживает нормали. 3. Не могу понять, о каких волшебниках и магах вы говорите :) – TomatoMato

0

Эта информация верна, насколько я знаю, и это сработало для меня. Для любых 3 точек А, В и С на плоскости, нормальной, если мы начинаем в точке А, то В, и, наконец, C, будет:

Где (В - А) и (C - B) каждый вычитает два вектора, а знак X представляет собой взаимное произведение двух векторов. Порядок точек весьма важен и определяет наше нормальное направление. Если A, B и C организованы против часовой стрелки, то их нормаль будет направлена ​​за пределы твердого тела. Если вы хотите знать, что крест продукт, то для любой точки P и Q, то их векторное произведение будет:

Другое дело, что часто делается для нормального вектора является то, что она нормализуется. Это означает, что величина нормального вектора равна 1, так что с ней легче работать. вот уравнение:

Если точка представляет собой скалярное произведение. Если вы не знаете, что такое точечный продукт, позвольте мне проиллюстрировать следующее. Для любых точек P и Q, то их скалярное произведение, которое является скалярным значением, является:

Теперь, когда у вас есть нормали поверхности, вы можете правильно рассчитать вершинные нормали для каждой вершины путем усреднения нормали любой поверхности, разделяющей эту вершину. У меня нет этой формулы на мне, но я знаю, что есть два подхода, чтобы найти верхую нормальную: взвешенную и не взвешенную. Весовой подход включает расчет площади каждой поверхности, а не взвешенный подход - нет.

Надеюсь, эта информация поможет вам.Я оставляю остальных вам или кому-либо еще, так как оставшаяся информация выходит за рамки моего царства. Возможно, я вернусь и исследую еще кое-что по этому вопросу.