Основы 3D – Векторной Графики
Когда мы говорим о 3D, то практически всегда имеем в виду 3D- Векторную Графику. 3D- Растровая Графика существует только в экзотических приложениях для медицины, исследований материалов и геологии, но не используется в Играх и прочих визуальных Развлечениях. Соответственно название лекции "3D-Векторная Графика" можно легко сократить до - "3D-Графика".
Расширение 2D-x,y-координат через z-координату
Каждая вершина Полигона получает дополнительно к его x- и y-координатам еще одну z-координату. В этом смысле, 2D-Векторная Графика - это частный случай 3D-Векторной Графики, при котором все z-координаты равны 0.0f.
Пример расширения функций Scroll, Zoom и Rotate из 2D в 3D:
double arcus = alpha * 2.0 * Math.PI / 360.0;
float cosinus = (float)Math.Cos( arcus );
float sinus = (float)Math.Sin( arcus );
for ( i=0; i<n; i++ )
{ p[i].X += dx;
p[i].Y += dy;
p[i].Z += dz; //новое измерение
p[i].X *= zoomx;
p[i].Y *= zoomy;
p[i].Z *= zoomz; //новое измерение
float help = p[i].X * cosinus - p[i].Y * sinus;
p[i].Y = p[i].X * sinus + p[i].Y * cosinus;
p[i].X = help; //Rot-operation around the z-axis doesn't change
}
Scroll и Zoom приобретают в 3D по одной строке Z-строке, 2D-Rotation остается идентична в 3D без Z-строки. Причина: вращение в x,y-Плоскости - это вращение вокруг оси параллельно оси-Z. При таком вращении, все вершины сохраняют свои z-координаты, а меняются только их x- и y- координаты.
Направление оси Z может указывать относительно плоскости x,y, как вперед, так и назад. Таким образом определяются две координатные системы, что создает много путаницы. По умолчанию в DirectX и OpenGL ось Z указывает вперед относительно x,y-плоскости монитора = Лева рукая декартова система координат = x-ось слева направо, y-ось снизу вверх, z-ось спереди назад. Больше информации тут - 3-D Coordinate Systems |
Вращение в трех осях: Roll (Крен), Pitch (Тангаж), Yaw (Рыскание)
В 3D появляются новые, в 2D неизвестные вращения, - вокруг оси-x и оси-y. Таким образом, в 3D известно не один способ вращения, а три способа - каждый со своим именным углом, названным по морской/авиационной традиции: | см: roll-pitch-yaw |
Vertex и Vektor
Определения Vertex и Vektor близки по значению. Оба используют аналогичную структуру данных типа { float X; float Y; float Z; }. Однако, существуют определенные интуитивные различия между этими понятиями.
Интуитивная интерпретация Вертекса (Вершины) - это точка в пространстве, похожая на звезду в космосе. Массив Вертксов соответственно можно представить, как облако звёзд.
Плюс - простота. Минус - нет возможности использовать векторные вычисления.
Интуитивная интерпретация Вектора - это стрела с началом в нулевой точке координат (0,0,0), указывающая своим острием на точку (x,y,z) в пространстве. Массив Векторов можно представить, как букет из стрел, имеющих одно начало (0,0,0) и указывающих на различные точки в пространстве. Каждая стрела умеет пространственный угол и длину.
Плюс - Вектора можно складывать, вычитать и умножать. Минус - сложнее для понимания, чем Вертекс.
1) Векторное сложение : v0 + v1 = { v0.X+v1.X, v0.Y+v1.Y, v0.Z+v1.Z } v1 садится на острие (вершину) v0 а результирующий вектор указывает от начала v0 на острие (вершину) v1.
2) Векторное вычитание : v1 - v0 = { v1.X-v0.X, v1.Y-v0.Y, v1.Z-v0.Z } результирующий Вектор указывает от острия v0 на острие v1.
3) Скалярное умножение : v0 * v1 = v0.X*v1.X +v0.Y*v1.Y +v0.Z*v1.Z = cos(alpha) - получается косинус угла между v0 и v1, в случае, когда v0 и v1 имеют длину, равную 1.0.
4) Векторное умножение : получается Вектор, перпендикулярный плоскости, в которой лежат v0 и v1.
v0 x v1 = { v0.Y*v1.Z - v0.Z*v1.Y,
v0.Z*v1.X - v0.X*v1.Z,
v0.X*v1.Y - v0.Y*v1.X }
5) Длина v : Length = Math.Sqrt( v.X2 + v.Y2 + v.Z2 ).
Применения:
Для 1) существует немного вариантов применения в области 3D-Графики (в отличии от Физики).
Через 2) рассчитывается соединительный вектор между вершинами.
Через 3) рассчитывается угол падения света на плоскость = Face = как правило треугольник.
Через 4) рассчитывается нормаль к плоскости = Face = обычно треугольник.
Через 5) рассчитывается длина, а если длина не играет роли, то она приравнивается к 1.0 = нормированный Вектор v = { v.X/Length, v.Y/Length, v.Z/Length}
Вывод: используйте простое определение Вертекса, а когда вам нужны углы, нормали и нормировки, переключайтесь на Векторные понятия.
Нормаль
2D-поверхности имеют только лицевую сторону, но в 3D нужно также различать тыльную сторону и общую ориентацию.
3D-поверхности = Faces обычно нуждаются в рассчете нормали = "Face Normal" = перпендикулярный к плоскости вектор. Направление наружу. См: Face and Vertex Normal Vectors.
Расчет нормали треугольника p0,p1,p2:
1) v0 = p0 - p1 // Вектор из p1 в p0
2) v1 = p2 - p1 // Вектор из p1 в p2
3) n0 = векторное произведение v0 и v1 // Нормаль без нормировки
4) Length = Math.Sqrt( n0.X2 + n0.Y2 + n0.Z2 ) // Длина вектора n0
5) n = { n0.X/Length, n0.Y/Length, n0.Z/Length } // Нормированная нормаль
см: Cross Product Applet www.phy.syr.edu/courses/java-suite/crosspro.html |
Нормаль определяет, где внешняя и где внутренняя сторона треугольника и под каким углом alpha находится поверхность относительно источника света. Из скалярного произведения нормированной нормали треугольника (Face) и нормированного вектора Света вычисляется cos(alpha), что определяет интенсивность освещенности (яркость отображения). Face наиболее освещен, когда направление Света совпадает с направлением нормали Фейса (треугольника).
Примеры:
alpha [Grad] | 0 | 30 | 45 | 60 | 90 | 120 | 180 | 360 |
cos(alpha) | 1.0 | 0.87 | 0.71 | 0.5 | 0.0 | -0.5 | -1.0 | 1.0 |
Освещенность (Яркость) | 100% | 87% | 71% | 50% | 0% | 0% | 0% | 100% |
Для определения направления нормали вручную можно использовать метод левой руки - находясь на второй вершине (Вертексе) p[1], направляем большой палец левой руки на первый Вертекс p[0], а указательный на Вертекс p[2]. Нормаль Фейса будет совпадать с отогнутым перпендикулярно ладони средним пальцем.
В DirectX3D и в OpenGL у каждого Фейса, принято работать не с одной нормалью, а тремя Вертексными нормалями = "Vertex Normal". То есть один треугольник содержит три параллельные "Vertex Normals", что на первый взгляд - избыточно и бессмысленно для одного треугольника.
Однако, когда несколько треугольников образуют объемную фигуру, сводя свои вершины в одну, например на вершине пирамиды, то можно в этой точке посчитать среднюю нормаль, которая будет хорошо представлять данную вершину.
Преимущество такого подхода видно на краях поверхностей, где треугольники резко сталкиваются друг с другом - вместо резкого скачка цвета (Flat Shading), сглаженные нормали дают мягкий переход - Gouraud-Shading.
Shading (затенение) - это метод симуляции глубины сцены через эффект комбинации света и тени.
Gouraud-Shading опубликован в 1971-м году и назван по имени студента Henri Gouraud (произносится: Гуро).
Близкие методы: Phong-Shading, Metal Shading