Обзор Graphics3DControl¶
Контрол Graphics3DControl
позволяет встраивать 3D-модели в ваше приложение Avalonia. Контрол поддерживает операции поворота, панорамирования и масштабирования с помощью мыши и клавиатуры, позволяя пользователю взаимодействовать с моделями во время выполнения программы.
Любая 3D-модель состоит из сеток, рисованных с использованием определенных материалов. Graphics3DControl
предоставляет API для определения сеток, материалов, свойств камеры и освещения. Вы также можете использовать сторонние библиотеки для загрузки моделей в форматах OBJ и STL в контрол Graphics3DControl
.
Основные характеристики¶
- API для задания 3D-моделей
- Одновременное отображение нескольких 3D-моделей
- Перспективные и изометрические камеры
- Поддерживаемые типы сеток: треугольные, линии и точки
- Простые и текстурированные материалы
- Преобразования 3D-моделей
- Отбраковка спереди и сзади
- Поддержка шаблона проектирования MVVM для определения 3D-моделей
- Отображение осей и сеток
Взаимодействие с пользователем¶
- Поворачивайте, перемещайте и масштабируйте модели с помощью мыши и клавиатуры
- Подсказки
- Выделение элементов
Смотрите раздел Взаимодействие пользователя с 3D-моделями
Начало работы¶
- Начало работы с Graphics3DControl — Демонстрирует, как создать 3D-модель с нуля.
Демонстрации¶
Ознакомьтесь с приложением Eremex Avalonia Controls Demo, которое содержит примеры, демонстрирующие различные возможности Graphics3DControl
:
- Загрузка моделей Wavefront (Obj) и Stl из внешних файлов с использованием сторонних библиотек и создание 3D-моделей на основе загруженных данных.
- Создание 3D-моделей с нуля.
- Демонстрация поддерживаемых типов сеток: треугольных, линий и точек.
- Использование шаблона проектирования MVVM для определения 3D-моделей и многого другого.
Система координат, оси и сетки¶
Graphics3DControl
поддерживает правостороннюю (по умолчанию) и левостороннюю системы координат. Вы можете использовать свойство Graphics3DControl.CoordinateSystem
, чтобы включить требуемую опцию.
Правосторонняя система координат¶
Положительные оси X, Y и Z направлены вправо, вверх и в сторону зрителя соответственно.
Левосторонняя система координат¶
Положительные оси X, Y и Z направлены вправо, вверх и в сторону от наблюдателя соответственно.
Оси¶
Включите свойство Graphics3DControl.ShowAxes
для отображения осей X, Y и Z в контроле.
Связанные опции¶
- Свойство
Graphics3DControl.AxisThickness
— определяет толщину осей.
Gizmo¶
Graphics3DControl
может отображать какую-либо штуковину. Это виджет, который визуально указывает текущую ориентацию осей.
Чтобы включить Gizmo, инициализируйте свойство Graphics3DControl.Gizmo
экземпляром класса Eremex.AvaloniaUI.Controls3D.Gizmo
.
<mx3d:Graphics3DControl Name="g3DControl" >
<!-- ... -->
<mx3d:Graphics3DControl.Gizmo>
<mx3d:Gizmo Name="gizmo" />
</mx3d:Graphics3DControl.Gizmo>
</mx3d:Graphics3DControl>
Сетки¶
Свойство Graphics3DControl.ShowGrid
позволяет отображать сетки на плоскостях XY, XZ и YZ.
Связанные опции¶
- Свойство
Graphics3DControl.GridThickness
— определяет толщину линий сетки.
Модели¶
Чтобы определить 3D-модели для Graphics3DControl
, используйте API Graphics3DControl
для создания объектов, представляющих модели, сетки, вершины, материалы, камеры и т.д.
Определение 3D-моделей¶
Класс GeometryModel3D
инкапсулирует единую 3D-модель в Graphics3DControl
.
Используйте одно из следующих свойств, чтобы добавить 3D-модели в контрол:
Graphics3DControl.Models
— Коллекция объектовGeometryModel3D
.Graphics3DControl.ModelsSource
— Источник бизнес-объектов, используемых для создания 3D-моделей (объектовGeometryModel3D
) в соответствии с шаблоном проектирования MVVM.
xmlns:mx3d="https://schemas.eremexcontrols.net/avalonia/controls3d"
<mx3d:Graphics3DControl Name="g3DControl" ShowAxes="True"/>
using Eremex.AvaloniaUI.Controls3D;
GeometryModel3D model = new GeometryModel3D();
g3DControl.Models.Add(model);
Сетки¶
3D-модель представляет собой набор сеток, отрисованных с использованием определенных материалов. Сетки определяют форму и структуру 3D-объекта.
Класс MeshGeometry3D
представляет сетку в Graphics3DControl
. Следующие свойства позволяют задавать сетки для модели:
GeometryModel3D.Meshes
— Коллекция объектовMeshGeometry3D
.GeometryModel3D.MeshesSource
— Источник бизнес-объектов, используемых для создания сеток (объектыMeshGeometry3D
) в соответствии с шаблоном проектирования MVVM.
Контрол поддерживает три типа сетки, которые вы можете выбрать с помощью свойства MeshGeometry3D.FillType
.
MeshFillType.Triangles
(по умолчанию) — Треугольная сетка. Состоит из треугольных граней (плоских областей, ограниченных тремя ребрами).
MeshFillType.Lines
— сетка линии. Вершины соединяются линиями, образуя каркас.
MeshFillType.Points
— Точечная сетка (облако точек). Состоит из вершин, которые не соединены линиями.
using DynamicData;
MeshGeometry3D meshTriangle1 = new MeshGeometry3D();
MeshGeometry3D meshSquare = new MeshGeometry3D();
MeshGeometry3D meshPoints = new MeshGeometry3D() { FillType = MeshFillType.Points };
//Define the meshes
//...
model.Meshes.AddRange(new[] { meshTriangle1, meshSquare, meshPoints });
При создании сетки используйте следующие свойства для определения вершин и граней/линий:
- Массив
MeshGeometry3D.Vertices
— определяет массив всех вершин, составляющих сетку. - Массив
MeshGeometry3D.Indices
— определяет треугольные грани (для треугольной сетки) или линии (для сетки линий).
Вершины¶
Вершина - это точка в трехмерном пространстве, определяемая ее координатами (x, y, z).
Тип Vertex3D
инкапсулирует единственную вершину в Graphics3DControl
. Используйте массив MeshGeometry3D.Vertices
для добавления вершин в сетку.
Тип Vertex3D
предоставляет следующие основные свойства, которые необходимо инициализировать.
Vertex3D.Position
— значениеVector3
, которое определяет координаты вершины (x, y, z).Vertex3D.Normal
— ЗначениеVector3
, задающее нормаль к вершине. Нормаль к вершине - это вектор, перпендикулярный поверхности 3D-модели в этой вершине. В 3D-графике нормали к вершинам используются для расчета освещения и затенения сетки. Нормали соседних треугольников должны быть выровнены для обеспечения плавного затенения (ребер).
Vertex3D.TextureCoord
— значениеVector2
, задающее координаты (x, y) точки в текстурированном материале, которая сопоставлена с текущей вершиной.
Определяем треугольную сетку¶
Чтобы создать треугольную сетку, вам нужно разделить фигуру на треугольники. Вершины задают углы треугольников. Для свойства MeshGeometry3D.FillType
необходимо установить значение по умолчанию (MeshFillType.Triangles
).
Рассмотрим пример, в котором сетка имеет форму четырехугольника. Ее можно триангулировать, добавив одну диагональ.
Сначала добавьте все вершины в массив MeshGeometry3D.Vertices
.
using DynamicData;
GeometryModel3D model = new GeometryModel3D();
g3DControl.Models.Add(model);
Vector3 pt1 = new(2f, 0, 0);
Vector3 pt2 = new(0, 0, 0);
Vector3 pt3 = new(0, 0, 1);
Vector3 pt4 = new(2f, 0, 1);
MeshGeometry3D meshSquare = new MeshGeometry3D();
meshSquare.FillType = MeshFillType.Triangles;
Vertex3D[] meshSquareVertices = new Vertex3D[]
{
new Vertex3D() { Position = pt1, Normal = new Vector3(0, 1, 0) },
new Vertex3D() { Position = pt2, Normal = new Vector3(0, 1, 0) },
new Vertex3D() { Position = pt3, Normal = new Vector3(0, 1, 0) },
new Vertex3D() { Position = pt4, Normal = new Vector3(0, 1, 0) }
};
meshSquare.Vertices = meshSquareVertices;
//...
model.Meshes.AddRange(new[] { meshSquare });
Затем используйте свойство MeshGeometry3D.Indices
для формирования граней треугольника.
Для треугольной сетки свойство MeshGeometry3D.Indices
представляет собой массив индексов вершин в массиве MeshGeometry3D.Vertices
, которые определяют отдельные треугольники сетки. Этот массив содержит группы индексов three в каждой. Первые три индекса в массиве относятся к вершинам первого сетчатого треугольника. Следующие три индекса относятся к вершинам второго сетчатого треугольника и так далее.
Порядок расположения индексов для каждого треугольника важен, поскольку он определяет нормаль к поверхности. Нормаль к поверхности, в свою очередь, определяет переднюю и заднюю стороны треугольника, что важно для таких операций, как отбраковка обратной и фронтальной сторон.
Для приведенной выше четырехъядерной сетки массив MeshGeometry3D.Indices
должен содержать шесть индексов. Первые три индекса относятся к вершинам первого треугольника. Вторые три индекса относятся к вершинам второго треугольника.
Определите сетку линий¶
В сетке с линиями вершины соединены линиями. Чтобы определить сетку линий, создайте объект MeshGeometry3D
и установите для его свойства MeshGeometry3D.FillType
значение MeshFillType.Lines
. Затем используйте свойство MeshGeometry3D.Vertices
, чтобы указать все вершины, и свойство MeshGeometry3D.Indices
, чтобы соединить вершины линиями.
Рассмотрим следующую 3D-модель, состоящую из линий, соединяющих шесть точек.
Сначала добавьте все вершины в массив MeshGeometry3D.Vertices
.
GeometryModel3D model = new GeometryModel3D();
g3DControl.Models.Add(model);
Vector3 p0 = new(1, 0, 0);
Vector3 p1 = new(1, 1, 0);
Vector3 p2 = new(1, 1, 2);
Vector3 p3 = new(2, 1, 2);
Vector3 p4 = new(2, 1, 0);
Vector3 p5 = new(2, 2, 0);
MeshGeometry3D meshLines = new MeshGeometry3D();
meshLines.PrimitiveSize = 3;
meshLines.FillType = MeshFillType.Lines;
Vertex3D[] meshLinesVertices = new Vertex3D[]
{
new Vertex3D() { Position = p0, Normal = new Vector3(0, 1, 0) },
new Vertex3D() { Position = p1, Normal = new Vector3(0, 1, 0) },
new Vertex3D() { Position = p2, Normal = new Vector3(0, 1, 0) },
new Vertex3D() { Position = p3, Normal = new Vector3(0, 1, 0) },
new Vertex3D() { Position = p4, Normal = new Vector3(0, 1, 0) },
new Vertex3D() { Position = p5, Normal = new Vector3(0, 1, 0) }
};
meshLines.Vertices = meshLinesVertices;
//...
model.Meshes.Add(meshLines);
Используйте свойство MeshGeometry3D.Indices
, чтобы соединить вершины линиями. Для сетки линий свойство MeshGeometry3D.Indices
представляет собой массив индексов вершин в массиве MeshGeometry3D.Vertices
, которые определяют отдельные линии.
Этот массив содержит пары индексов. Первые два индекса в массиве относятся к вершинам первой линии. Следующие два индекса относятся к вершинам второй линии и так далее.
В приведенном выше примере массив MeshGeometry3D.Indices
должен содержать 10 индексов. Первая пара индексов относится к точкам, которые определяют первую линию. Вторая пара индексов относится к вершинам второй линии и так далее.
uint[] meshLinesIndices = new uint[] { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5 };
meshLines.Indices = meshLinesIndices;
Толщина линий¶
В сетке линий используйте свойство PrimitiveSize
, чтобы изменить толщину линий.
Определение точечной сетки¶
В точечной сетке вершины отображаются как отдельные точки.
Чтобы определить точечную сетку, создайте объект MeshGeometry3D
и задайте его свойству MeshGeometry3D.FillType
значение MeshFillType.Points
. Затем используйте свойство MeshGeometry3D.Vertices
, чтобы указать все вершины, и свойство MeshGeometry3D.Indices
, чтобы указать, какие вершины отображать.
Давайте создадим точечную сетку, образующую спираль, в которой точки расположены в размещении в плоскости XY.
int pointCount = 500;
GeometryModel3D model = new GeometryModel3D();
g3DControl.Models.Add(model);
var vertices = new Vertex3D[pointCount];
var indices = new uint[pointCount];
MeshGeometry3D meshPoints = new MeshGeometry3D();
meshPoints.PrimitiveSize = 3;
meshPoints.MaterialKey = "pointsMaterial";
meshPoints.FillType = MeshFillType.Points;
double radius = 0;
double angle = 0;
double radiusStep = 0.1;
double angleStep = 0.1;
for (uint i = 0; i < pointCount; i++)
{
double x = radius * Math.Cos(angle);
double y = radius * Math.Sin(angle);
vertices[i] = new Vertex3D() {
// Vertex coordinates:
Position = new Vector3((float)x, (float)y, 0),
// Normalized coordinates of a position in the texture mapped to the current vertex:
TextureCoord= new Vector2((float)i/pointCount, 0)
};
radius += radiusStep;
angle += angleStep;
indices[i] = i;
}
meshPoints.Vertices = vertices;
meshPoints.Indices = indices;
model.Meshes.Add(meshPoints);
Вы можете раскрасить вершины в точечной сетке разными цветами. Например, вершины можно рисовать цветами, определяемыми их позициями или координатами.
Приведенный ниже код показывает, как использовать текстурированный материал для раскрашивания вершин. Индекс вершины определяет ее цвет (позицию в следующем цветовом градиенте).
-
Добавьте текстурированный материал (
TexturedPbrMaterial
) в коллекциюGraphics3DControl.Materials
. Текстурированный материал представляет собой набор растровых изображений, которые задают следующие свойства текстуры:Albedo
— Базовый цветAlpha
— ПрозрачностьEmission
— Интенсивность света, излучаемого поверхностьюAmbientOcclusion
— Уровень затемнения, вызванного объектами, блокирующими окружающий светRoughness
— Гладкость поверхностиMetallic
— свойства отражательной способности поверхности
Вершины позже сопоставляются с определенными позициями в этих текстурных растровых изображениях.
Чтобы убедиться, что вершины отображают реалистичные цвета из целевого цветового градиента, настройте текстурные растровые изображения следующим образом:
- Установите для
TexturedPbrMaterial.Emission
значение градиентного растрового изображения, которое определяет реальный цвет вершин. - Установите для
TexturedPbrMaterial.Albedo
значение растрового изображения, заполненного черным цветом. - Установите для
TexturedPbrMaterial.Roughness
иTexturedPbrMaterial.AmbientOcclusion
значения растровых изображений, которые будут заполнены белым цветом.
using DynamicData; using Avalonia.Media; public void InitG3DControlMaterials() { g3DControl.Materials.AddRange( new[] { new TexturedPbrMaterial(){ Albedo = getSolidColorBitmap(Colors.Black), Roughness = getSolidColorBitmap(Colors.White), AmbientOcclusion = getSolidColorBitmap(Colors.White), Emission = getGradientColorBitmap(Colors.DodgerBlue, Colors.Red), Key= "pointsMaterial" } } ); } Bitmap getSolidColorBitmap(Color fillColor) { var bitmap = new RenderTargetBitmap(new PixelSize(pointCount, 1)); using (var context = bitmap.CreateDrawingContext()) { Brush brush = new SolidColorBrush(fillColor); context.FillRectangle(brush, new Rect(0, 0, pointCount, 1)); } return bitmap; } Bitmap getGradientColorBitmap(Color fillColor1, Color fillColor2) { var bitmap = new RenderTargetBitmap(new PixelSize(pointCount, 1)); using (var context = bitmap.CreateDrawingContext()) { var gradientBrush = new LinearGradientBrush { StartPoint = new RelativePoint(0, 0, RelativeUnit.Relative), EndPoint = new RelativePoint(1, 1, RelativeUnit.Relative), GradientStops = { new GradientStop(fillColor1, 0.0), new GradientStop(fillColor2, 1.0) } }; context.FillRectangle(gradientBrush, new Rect(0, 0, pointCount, 1)); } return bitmap; }
Свойству материала
TexturedPbrMaterial.Key
присвоено значение уникального ключа (строки). Уникальные ключи позволяют идентифицировать материалы из коллекцииGraphics3DControl.Materials
. -
Назначьте созданный материал сетке, используя свойство
MeshGeometry3D.MaterialKey
. СвойствоMeshGeometry3D.MaterialKey
должно соответствовать значению свойстваTexturedPbrMaterial.Key
. -
Используйте свойство
Vertex3D.TextureCoord
для сопоставления вершин с определенными позициями в текстуре. Это свойство должно указывать нормализованные координаты. Значения TextureCoord.X и TextureCoord.Y должны находиться в диапазоне от 0 до 1, где 0 соответствует левому или верхнему краю текстурного растрового изображения, а 1 соответствует правому или нижнему краю текстурного растрового изображения.Когда вершины будут созданы, укажите свойство
Vertex3D.TextureCoord
для обращения к целевым позициям в текстуре.vertices[i] = new Vertex3D() { // Vertex coordinates: Position = new Vector3((float)x, (float)y, 0), // Normalized coordinates of a position in the texture mapped to the current vertex: TextureCoord= new Vector2((float)i/pointCount, 0) };
Теперь вершины раскрашиваются с использованием указанного градиента.
Количество точек¶
В точечной сетке используйте свойство PrimitiveSize
, чтобы изменить толщину точек.
Видимость модели¶
Используйте свойство GeometryModel3D.Visible
, чтобы временно скрыть, а затем восстановить модель.
GeometryModel3D model = new GeometryModel3D();
g3DControl.Models.Add(model);
//...
model.Visible = !model.Visible;
Преобразования моделей¶
Graphics3DControl
позволяет выполнять преобразования моделей. Для этой цели создайте матрицу преобразования, которая поворачивает, масштабирует и/или преобразует модель. После создания присвойте этой матрице свойство GeometryModel3D.Transform
.
Чтобы отменить текущее преобразование, присвойте свойству GeometryModel3D.Transform
значение объекта Matrix4x4.Identity
.
Класс Matrix4x4
предоставляет методы для генерации матриц преобразований для различных типов преобразований. Некоторые из этих методов включают:
Matrix4x4.CreateRotationX
— Генерирует матрицу преобразования, которая представляет поворот вокруг оси X на заданный угол.Matrix4x4.CreateRotationY
— Генерирует матрицу преобразования, которая представляет поворот вокруг оси Y на заданный угол.Matrix4x4.CreateRotationZ
— Генерирует матрицу преобразования, которая представляет поворот вокруг оси Z на заданный угол.Matrix4x4.CreateTranslation
— Генерирует матрицу преобразования, которая перемещает объект на заданное смещение вдоль осей X, Y и Z.Matrix4x4.CreateScale
— Генерирует матрицу преобразования, которая масштабирует объект по осям X, Y и Z.
Чтобы применить несколько преобразований одновременно, вы можете умножить матрицы, которые выполняют отдельные преобразования.
Пример - Поворот модели¶
В следующем примере создается анимация, которая вращает 3D-модель (спираль, состоящую из точек). Метод Matrix4x4.CreateRotationZ
вызывается для генерации матрицы преобразования, которая поворачивает модель на заданный угол вокруг оси Z.
Чтобы применить преобразование, этой матрице присваивается свойство GeometryModel3D.Transform
.
GeometryModel3D model;
//Init the model
//...
float angleStep = MathF.PI / 180;
float angle = 0;
private void BtnRotate_Click(object? sender, Avalonia.Interactivity.RoutedEventArgs e)
{
for (int i = 0; i < 180; i++)
{
angle += angleStep;
Matrix4x4 rotationMatrix = Matrix4x4.CreateRotationZ(angle);
model.Transform = rotationMatrix;
// Update the UI
Dispatcher.UIThread.RunJobs();
Thread.Sleep(12);
}
}
Пример - Выполнение нескольких преобразований¶
В следующем примере создается 3D-модель, которая отображает треугольник, и показано, как выполнить несколько преобразований над моделью.
В примере операции масштабирования, поворота и перемещения объединены в единую матрицу преобразования, а затем для применения преобразований этой матрице присваивается свойство GeometryModel3D.Transform
.
В этом примере к матрицам преобразования применяются небольшие постепенные изменения, создающие плавный анимационный эффект.
xmlns:mx3d="https://schemas.eremexcontrols.net/avalonia/controls3d"
<mx3d:Graphics3DControl Name="g3DControl" ShowAxes="True" Grid.Row="1"/>
using DynamicData;
public MainWindow()
{
InitG3dControl();
}
private void InitG3dControl()
{
// Create a 3D model that renders a triangle.
GeometryModel3D model = new GeometryModel3D();
g3DControl.Models.Add(model);
Vector3 pt1 = new(1f, 0, 0);
Vector3 pt2 = new(0, 0, 0);
Vector3 pt3 = new(0, 0, 1);
MeshGeometry3D meshSquare = new MeshGeometry3D();
meshSquare.FillType = MeshFillType.Triangles;
Vertex3D[] meshSquareVertices = new Vertex3D[]
{
new Vertex3D() { Position = pt1, Normal = new Vector3(0, 1, 0) },
new Vertex3D() { Position = pt2, Normal = new Vector3(0, 1, 0) },
new Vertex3D() { Position = pt3, Normal = new Vector3(0, 1, 0) }
};
uint[] meshSquareIndices = new uint[] { 0, 1, 2 };
meshSquare.Indices = meshSquareIndices;
meshSquare.Vertices = meshSquareVertices;
model.Meshes.AddRange(new[] { meshSquare });
this.model = model;
}
//Transform the model
private void BtnRotate_Click(object? sender, Avalonia.Interactivity.RoutedEventArgs e)
{
int steps = 100;
Vector3 stepTranslationVector = new Vector3(-0.5f, 0, 0)/steps;
Vector3 stepScaleVector = new Vector3(-0.5f, 0, 0.1f)/steps;
float stepRotationAngle = (MathF.PI/2)/steps;
Vector3 translationVector = new Vector3(0,0,0),
scaleVector = new Vector3(1, 1, 1);
float rotationAngle = 0;
for (int i = 0; i < steps; i++)
{
rotationAngle += stepRotationAngle;
translationVector += stepTranslationVector;
scaleVector += stepScaleVector;
// Translation Matrix (move by)
Matrix4x4 translationMatrix = Matrix4x4.CreateTranslation(translationVector);
// Scaling Matrix
Matrix4x4 scalingMatrix = Matrix4x4.CreateScale(scaleVector);
// Rotation Matrix
Matrix4x4 rotationMatrix = Matrix4x4.CreateRotationY(rotationAngle);
rotationMatrix *= Matrix4x4.CreateRotationX(rotationAngle);
Matrix4x4 combinedMatrix = Matrix4x4.Identity;
combinedMatrix *= scalingMatrix;
combinedMatrix *= rotationMatrix;
combinedMatrix *= translationMatrix;
model.Transform = combinedMatrix;
// Update the UI
Dispatcher.UIThread.RunJobs();
Thread.Sleep(12);
}
}
Мультисэмплинг (сглаживание)¶
Graphics3DControl.MultisamplingMode
— Активирует сглаживание с несколькими выборками (MSAA) или отключает его.
Функция сглаживания используется для уменьшения визуальных искажений, таких как неровные края (сглаживание псевдонимов), в визуализируемой графике, обеспечивая более плавные и точные результаты.
Свойству MultisamplingMode
можно присвоить следующие значения: None
, X2
, X4
, X8
, X16
, X32
, X64
. X2
...Значения X64
определяют количество точек выборки на пиксель для расчета конечного цвета пикселя. Большее количество выборок приводит к лучшим результатам, однако это также требует больших вычислительных затрат.
- Значением свойства
MultisamplingMode
по умолчанию являетсяX8
. - Возможно, ваш графический процессор поддерживает не все режимы MSAA. Если выбран неподдерживаемый режим MSAA, система возвращается к более низкому доступному режиму. Вы можете использовать свойство
Graphics3DControl.AvailableMultisamplingModes
, чтобы вернуть список режимов MSAA, поддерживаемых вашим графическим драйвером. - Мультисэмплинг для больших 3D-моделей увеличивает использование памяти и вычислительные затраты. Чтобы повысить производительность приложения в таких случаях, рассмотрите возможность установки для свойства
MultisamplingMode
меньшего значения или отключения MSAA.
Материалы¶
Каждая сетка в контроле Graphics3DControl
может быть рисована своим собственным материалом. Материал определяет, как поверхности взаимодействуют со светом, придавая объектам их визуальный вид.
Контрол Graphics3DControl
поддерживает два типа материалов:
-
SimplePbrMaterial
— Материал, который определяет визуальные свойства поверхности с помощью числовых значений, таких как цвета (например, альбедо и излучение) и свойства взаимодействия света (например, металлический оттенок и шероховатость). Для получения дополнительной информации смотрите Простые материалы (SimplePbrMaterial) -
TexturedPbrMaterial
— Текстурированный материал в формате PBR. Этот материал определяет визуальные свойства поверхности с помощью текстур (растровых изображений). Дополнительную информацию смотрите в разделе Текстурированные материалы (TexturedPbrMaterial)
Чтобы нанести материалы на сетки, выполните следующие действия:
- Создавайте и инициализируйте материалы.
- Присвойте свойству
Key
для материалов значение уникальных строк. Ключи позволяют идентифицировать материал при назначении материалов сеткам. - Добавьте материалы в коллекцию
Graphics3DControl.Materials
. - Используйте свойство
MeshGeometry3D.MaterialKey
, чтобы привязать сетку к определенному материалу. Для этой цели установите для свойстваMeshGeometry3D.MaterialKey
значение свойстваKey
целевого материала.
Пример - Назначение материала для сетки¶
В следующем примере создаются три материала (объекты SimplePbrMaterial
) и один из этих материалов применяется к сетке. Созданные материалы идентифицируются с помощью уникальных строковых ключей ("BrownColor", "TomatoColor" и "VioletColor").
using DynamicData;
g3DControl.Materials.AddRange(
new[] {
new SimplePbrMaterial(Color.FromUInt32(0xFF822c2e), "BrownColor"),
new SimplePbrMaterial(Color.FromUInt32(0xffeb523f), "TomatoColor"),
new SimplePbrMaterial(Color.FromUInt32(0xFFea3699), "VioletColor")
}
);
//...
mesh1.MaterialKey = "VioletColor";
Простые материалы (SimplePbrMaterial
)¶
SimplePbrMaterial
- это материал, который описывает визуальные свойства поверхности в виде числовых значений. Он предоставляет следующие элементы для указания визуальных свойств:
-
Albedo
— Базовый цвет.Значением свойства является объект Vector3, элементы X, Y и Z которого задают нормализованные значения для компонентов красного, зеленого и синего цветов. Нормализованные значения находятся в диапазоне [0;1]. Чтобы преобразовать стандартную цветовую составляющую (0-255) в нормализованное значение, разделите ее на 255. Вы также можете использовать конструктор
SimplePbrMaterial
для инициализации свойствAlbedo
иAlpha
из указанного объектаColor
. Этот конструктор автоматически нормализует цветовые компоненты. -
Alpha
— Уровень прозрачности.Значение свойства должно находиться в диапазоне [0;1], где
0
означает полностью прозрачный, а1
означает полностью непрозрачный. -
Emission
— Интенсивность света, излучаемого поверхностью.Значением свойства является объект Vector3, элементы X, Y и Z которого задают нормализованные значения для компонентов красного, зеленого и синего цветов. Нормализованные значения находятся в диапазоне [0;1]. Чтобы преобразовать стандартную цветовую составляющую (0-255) в нормализованное значение, разделите ее на 255.
-
AmbientOcclusion
— Уровень затемнения, вызванного объектами, блокирующими окружающий свет.Значение свойства должно находиться в диапазоне [0;1], где
0
означает, что применяется максимальный эффект внешней окклюзии, а1
означает, что внешняя окклюзия не применяется. -
Roughness
— Гладкость поверхности.Значение свойства должно находиться в диапазоне [0;1], где
0
означает идеально гладкую и глянцевую поверхность, а1
означает полностью шероховатую и матовую поверхность. -
Metallic
— Отражательная способность поверхности.Значение свойства должно находиться в диапазоне [0;1], где
0
означает неметаллическую поверхность, а1
означает полностью металлический материал.
Демонстрация¶
Пример Simple Materials
в демонстрационном приложении демонстрирует 3D-модель, рисованную с использованием простого материала. Демонстрация позволяет вам настраивать свойства материала в режиме реального времени и мгновенно видеть последствия ваших изменений.
Пример - Применение простого материала к модели¶
Следующий код создает простой материал (объект SimplePbrMaterial
) и применяет его к первой сетке 3D-модели.
Свойству SimplePbrMaterial.Albedo
присваивается значение базового цвета (бирюзовый) с использованием нормализованных цветовых координат.
SimplePbrMaterial material = new SimplePbrMaterial();
material.Albedo = ToNormalizedVector3(Colors.Teal);
material.Emission = ToNormalizedVector3(Colors.Black);
material.Metallic = 0;
material.Roughness = 0.5f;
material.AmbientOcclusion = 1;
material.Key = "myFavMaterial";
g3DControl.Materials.Add(material);
// Apply the material to the first mesh of the model
g3DControl.Models[0].Meshes[0].MaterialKey = "myFavMaterial";
public static Vector3 ToNormalizedVector3(Color color)
{
return new Vector3(color.R/255f, color.G/255f, color.B/255f);
}
Этот материал, нанесенный на образец 3D-модели, показан ниже:
Текстурированные материалы (TexturedPbrMaterial
)¶
TexturedPbrMaterial
- это материал, который использует PBR-текстуры (растровые изображения) для определения визуальных свойств поверхности. Класс TexturedPbrMaterial
предоставляет следующие элементы для настройки свойств материала:
-
Albedo
— Растровое изображение, задающее базовый цвет материала. -
Alpha
— Растровое изображение, задающее уровень прозрачности. -
Emission
— Растровое изображение, которое определяет интенсивность света, излучаемого поверхностью. -
AmbientOcclusion
— Растровое изображение, которое определяет уровень затенения, вызванного объектами, блокирующими окружающий свет. -
Roughness
— Растровое изображение, которое определяет гладкость поверхности. -
Metallic
— Растровое изображение, определяющее отражательную способность поверхности. -
Normal
— Растровое изображение, которое определяет карту нормалей.
Демо¶
Пример Textured Materials
в демонстрационном приложении демонстрирует 3D-модель, отрисованную с использованием текстур PBR. Текстуры загружаются из графических файлов, хранящихся в ресурсах приложения.
Следующий фрагмент кода из демонстрации Textured Materials
заполняет коллекцию Materials
модели представления материалами (объектами TexturedPbrMaterial
). Эти материалы созданы для всех текстур, которые хранятся в виде ZIP-файлов в ресурсах приложения, найденных в папке DemoCenter.Resources.Graphics3D.Materials
. Для каждого материала, если ZIP-файл с текстурой содержит растровые изображения для свойств Albedo
, AmbientOcclusion
, Metallic
, Roughness
, Normal
и Emission
, эти растровые изображения загружаются и применяются к материалу.
public partial class Graphics3DControlTexturedMaterialsViewModel : Graphics3DControlViewModel
{
[ObservableProperty] ObservableCollection<TexturedPbrMaterial> materials = new();
[ObservableProperty] TexturedPbrMaterial selectedMaterial;
public Graphics3DControlTexturedMaterialsViewModel()
{
var assembly = Assembly.GetAssembly(typeof(Graphics3DControlViewModel));
var textureNames = assembly!.GetManifestResourceNames().Where(name => name.StartsWith("DemoCenter.Resources.Graphics3D.Materials."));
foreach (var textureName in textureNames)
materials.Add(LoadMaterial(assembly, textureName));
selectedMaterial = Materials.First();
//...
}
static TexturedPbrMaterial LoadMaterial(Assembly assembly, string resourceName)
{
var stream = assembly!.GetManifestResourceStream(resourceName);
using var archive = new ZipArchive(stream!, ZipArchiveMode.Read);
var material = new TexturedPbrMaterial { Key = resourceName.Split('.')[^2] };
foreach (var entry in archive.Entries)
{
using var entryStream = entry.Open();
using var memoryStream = new MemoryStream();
entryStream.CopyTo(memoryStream);
memoryStream.Seek(0, SeekOrigin.Begin);
var bitmap = new Bitmap(memoryStream);
if (entry.Name.StartsWith("Albedo"))
material.Albedo = bitmap;
else if (entry.Name.StartsWith("AO"))
material.AmbientOcclusion = bitmap;
else if (entry.Name.StartsWith("Metallic"))
material.Metallic = bitmap;
else if (entry.Name.StartsWith("Roughness"))
material.Roughness = bitmap;
else if (entry.Name.StartsWith("Normal"))
material.Normal = bitmap;
else if (entry.Name.StartsWith("Emissive"))
material.Emission = bitmap;
}
return material;
}
}
Приведенный ниже XAML-код из демонстрационной версии Textured Materials
привязывает контрол Graphics3DControl
к коллекции материалов в модели представления (Graphics3DControlTexturedMaterialsViewModel.Materials
). Применяемый в данный момент материал определяется свойством Graphics3DControlTexturedMaterialsViewModel.SelectedMaterial
.
<mx3d:Graphics3DControl x:Name="DemoControl" MaterialsSource="{Binding Materials}">
<mx3d:GeometryModel3D>
<mx3d:MeshGeometry3D Vertices="{Binding Vertices}" Indices="{Binding Indices}" MaterialKey="{Binding SelectedMaterial.Key}" />
</mx3d:GeometryModel3D>
</mx3d:Graphics3DControl>
Координаты текстуры¶
Когда вы используете текстурированный материал, вам необходимо сопоставить текстуру с поверхностью. Для этого инициализируйте свойство Vertex3D.TextureCoord
для вершин в вашей сетке. Это свойство определяет координаты текстуры (часто называемые координатами UV).
Координаты текстуры - это двумерные координаты (x, y)
, к которым привязана вершина.
-
x
представляет собой горизонтальную координату в текстуре в диапазоне [0; 1], где0
представляет левый край, а1
представляет правый край картинки. -
y
представляет вертикальную координату текстуры в диапазоне [0; 1], где0
представляет верхний край, а1
представляет нижний край картинки.
Например, координата (x, y)
вместо координаты (0.5, 0.5)
будет выборкой пикселя в центре текстуры.
Примеры¶
Примеры, демонстрирующие использование свойства Vertex3D.TextureCoord
:
-
Демонстрационная версия
Textured Materials
. -
Пример приведен в разделе Определение точечной сетки в текущей документации.
Отбраковка обратной и лицевой сторон¶
Свойство Graphics3DControl.CullMode
позволяет вам включить отбраковку задней и передней граней для треугольных сеток . Режим отбраковки определяет, какие грани 3D-модели следует нарисовать, а какие следует отбросить. Вы можете присвоить свойству Graphics3DControl.CullMode
следующие значения:
-
CullMode.Back
— Позволяет выполнять выбраковку обратной стороны, при которой не отображаются задние грани треугольников. -
CullMode.Front
— Позволяет выполнять выбраковку передних граней, при которой передние грани треугольников не отображаются. -
CullMode.None
— Нарисованы передняя и задняя грани.
Определение лицевой и оборотной сторон¶
Когда вы определяете треугольные грани для сетки, вы используете свойство MeshGeometry3D.Indices
, чтобы указать индексы вершин, которые образуют каждый треугольник.
Порядок индексов для каждого треугольника сетки важен, поскольку он определяет направление нормали к поверхности и, следовательно, переднюю и заднюю части треугольника:
-
Если индексы треугольника пронумерованы против часовой стрелки, нормаль к поверхности направлена в сторону наблюдателя, и наблюдатель видит переднюю часть треугольника.
-
Если индексы треугольника пронумерованы по часовой стрелке, нормаль поверхности направлена в сторону от наблюдателя, и наблюдатель видит обратную сторону треугольника.
Пример¶
В этом примере демонстрируется функция отбраковки лиц. В этом примере создается модель, состоящая из двух треугольников. При отображении зритель видит переднюю часть первого (левого) треугольника и заднюю часть второго (правого) треугольника.
xmlns:mx3d="https://schemas.eremexcontrols.net/avalonia/controls3d"
<mx3d:Graphics3DControl Name="g3DControl" ShowAxes="True"/>
using Avalonia.Media;
using DynamicData;
GeometryModel3D model = new GeometryModel3D();
g3DControl.Models.Add(model);
Vector3 pt1 = new(-1f, 0, 0);
Vector3 pt2 = new(-0.5f, 0.5f, 0);
Vector3 pt3 = new(0, 0, 0);
Vector3 pt4 = new(0, 0, 0);
Vector3 pt5 = new(0.5f, 0.5f, 0);
Vector3 pt6 = new(1f, 0, 0);
MeshGeometry3D mesh1 = new MeshGeometry3D();
mesh1.FillType = MeshFillType.Triangles;
Vertex3D[] meshVertices = new Vertex3D[]
{
new Vertex3D() { Position = pt1, Normal = new Vector3(0, 0, 1) },
new Vertex3D() { Position = pt2, Normal = new Vector3(0, 0, 1) },
new Vertex3D() { Position = pt3, Normal = new Vector3(0, 0, 1) },
new Vertex3D() { Position = pt4, Normal = new Vector3(0, 0, -1) },
new Vertex3D() { Position = pt5, Normal = new Vector3(0, 0, -1) },
new Vertex3D() { Position = pt6, Normal = new Vector3(0, 0, -1) }
};
mesh1.Vertices = meshVertices;
// Vertices of the first triangle are enumerated counter-clockwise (pt3->pt2->pt1),
// while vertices of the second triangle are enumerated clockwise (pt4->pt5->pt6):
uint[] meshIndices = new uint[] { 2, 1, 0, 3, 4, 5 };
mesh1.Indices = meshIndices;
model.Meshes.AddRange(new MeshGeometry3D[] { mesh1 });
g3DControl.Materials.Add(new SimplePbrMaterial(Colors.SeaGreen, "myMaterial"));
mesh1.MaterialKey = "myMaterial";
При установке для свойства Graphics3DControl.CullMode
значения CullMode.Back
задние грани не отображаются. Второй (правый) треугольник обращен в сторону от камеры, поэтому он не отображается.
Когда значение Graphics3DControl.CullMode
равно значению CullMode.Front
, передние грани не отображаются. Первый (левый) треугольник обращен к камере, поэтому он скрыт:
Гамма-коррекция и коррекция экспозиции¶
Graphics3DControl.Exposure
— контролирует уровень коррекции экспозиции, который регулирует яркость отрисованного изображения. Значение по умолчанию равно 4.5. Свойству может быть присвоено неотрицательное значение.Graphics3DControl.Gamma
— контролирует гамма-коррекцию. Значение по умолчанию равно 2,2, что является стандартным значением гаммы для большинства дисплеев. Этому свойству можно присвоить неотрицательное значение.
* Эта страница была создана автоматически с помощью сервиса машинного перевода Яндекс Переводчик.