Во многих программах 3D-дизайна, таких как Blender и 3D Studio Max, вы можете выбрать, какие поверхности формы вы хотите сгладить, а не твердые и плоские. Это означает усреднение (я полагаю) нормалей вершин, которые находятся в той же позиции, что и конкретная вершина. Я пытаюсь написать что-то в этом роде, но я делаю это впервые, и способ, которым я придумал, должен быть действительно неэффективным, и я считаю, что это не ^ 2 временная сложность. Итак, если у нас есть трехмерная фигура с 99 вершинами, то цикл должен выполняться 99 x 99 раз, почти 10000 раз.
С шариком это легко, так как нормаль каждой вершины - это просто нормализованная позиция вершины (единичный вектор положения). Я могу сделать это легко, как показано ниже:
Мне было интересно, как эти программы делают это и есть ли более эффективный способ, чем этот. Мой метод состоит в том, чтобы пройти через i от 0 до 99 и j от 0 до 99. Я в основном прохожу и проверяю, имеет ли другая вершина такое же положение, если так, я проверяю, есть ли угол между ее нормалью и нормалью другой вершины. находится под желаемым угловым порогом. Если так, я добавляю это к сумме вектора, тогда я делю на число вершин, которые были сопоставлены. Я не уверен, что это правильно.
#include <iostream>
#include <vector>
#include <math.h>
using namespace std;
float thresholdAngle = 60 /*degrees*/ / 180 * 3.14159; // In radians
struct vec3
{
float x, y, z;
bool hasSamePositionAs(vec3& other)
{
if (other.x == this->x &&
other.y == this->y &&
other.z == this->z)
return true;
return false;
}
bool angleIsUnderThresholdWith(vec3& other)
{//THIS SHOULD BE IF DOTPRODUCT > COS(THRESHOLDANGLE)
return dotProductWith(other) < thresholdAngle ? true : false;
}
float dotProductWith(vec3& other)
{
return x * other.x + y * other.y + z * other.z;
}
void operator +=(vec3 other) { x += other.x; y += other.y; z + other.z; }
int main()
{
// 33 triangles, 99 vertices
vector<vec3> vertices(99); // ALL UNIT VECTORS, NORMALS
vector<vec3> newNormals(99);
for (int i = 0; i < 99; i++)
{
vec3 normal = vertices[i];
for (int j = 0; j < 99; j++)
{
if (j == i) continue;
if (vertices[i].hasSamePositionAs(vertices[j]))
{
if (vertices[i].angleIsUnderThresholdWith(vertices[j]))
{
normal += vertices[j];
}
}
}
normalise(normal);
newNormals[i] = normal;
}
}
Редактировать: ОК, поэтому, используя этот код, мне удалось получить то, что мне было нужно, но алгоритм по-прежнему n ^ 2. Вы можете заметить, что синие линии, которые являются нормалями, разделены для каждой грани в виде плоской штриховки и объединены (усреднены) при прохождении через этот код.