Опубликован: 13.07.2010 | Уровень: специалист | Доступ: платный
Самостоятельная работа 14:

Использование Mesh-объектов в DirectX

Создание Mesh-объекта

  • Добавьте в класс создание ссылки на Mesh -объект. Ее можно разместить сразу после создания ссылки устройства
private Device device = null;
    private Mesh mesh=null;
  
    public void InitializeGraphics()
    {
    ...........................................
    }
Листинг 14.8. Объявление ссылки на Mesh-объект

Имеются три метода создания самого объекта Mesh, но на данном этапе нам не понадобится ни один из них. Мы воспользуемся статическим методом создания куба Mesh.Box. Кроме этого метода класс Mesh содержит еще ряд перегружаемых методов для создания примитивных объектов:

  1. Microsoft.DirectX.Direct3D.Mesh.Box() - создание куба
  2. Microsoft.DirectX.Direct3D.Mesh.Cylinder() - создание цилиндра
  3. Microsoft.DirectX.Direct3D.Mesh.Polygon() - создание полигона
  4. Microsoft.DirectX.Direct3D.Mesh.Sphere() - создание сферы
  5. Microsoft.DirectX.Direct3D.Mesh.Torus() - создание тора
  6. Microsoft.DirectX.Direct3D.Mesh.Teapot() - создание изображения заварочного чайника

Этими методами мы воспользуемся в лабораторной работе №17 для создания препятствий на дороге.

  • Добавьте в конец функции InitializeGraphics() после кода создания устройства следующую строку генерации куба
public void InitializeGraphics()
        {
            // Создание объекта и настройка параметров представления
            // Создать объект параметров представления
            PresentParameters presentParams = new PresentParameters();
            // Установить оконный режим
            presentParams.Windowed = true;
            // Сбрасывать содержимое буфера, если он не готов к представлению
            presentParams.SwapEffect = SwapEffect.Discard;
    
            // Создать объект устройства и сохранить ссылку на него
            device = new Device(0, DeviceType.Hardware, this,
                CreateFlags.SoftwareVertexProcessing, presentParams);
    
            // Генерация и подключение к устройству куба 
            // с помощью статического метода класса Mesh
            mesh = Mesh.Box(device, 2.0F, 2.0F, 2.0F);
        }
Листинг 14.9. Загрузка в устройство Mesh-объекта куба

Статический метод Mesh.Box() имеет две перегрузки и мы воспользовались первой из них:

  1. public static Microsoft.DirectX.Direct3D.Mesh Box(Microsoft.DirectX.Direct3D.Device device, float width, float height, float depth)
  2. public static Microsoft.DirectX.Direct3D.Mesh Box(Microsoft.DirectX.Direct3D.Device device, float width, float height, float depth, out Microsoft.DirectX.Direct3D.GraphicsStream adjacency)

Он создает новый Mesh-объект, который содержит вершины и индексы, необходимые для рендеринга куба с заданной шириной, высотой и глубиной (значение 2.0F ). Этот куб того же размера, что и созданный нами вручную в Form3 лабораторной работы №13.

Теперь нужно отобразить Mesh -объект на экране с помощью функции DrawSubset() экземплярного объекта mesh.

  • Измените в функции DrawCubes() все вызовы метода DrawIndexedPrimitives() устройства на вызовы метода DrawSubset(0) объекта mesh
private void DrawCubes()
        {
            //
            // Средний ряд
            //
            device.Transform.World = Matrix.RotationYawPitchRoll(
                angle / (float)Math.PI,
                angle / (float)Math.PI * 2.0f,
                angle / (float)Math.PI / 4.0f) *
                Matrix.Translation(0.0f, 0.0f, 0.0f);   // По центру
            mesh.DrawSubset(0);
    
            //
            // .......................................................
            //
    
            if (flagRotate)
                angle += 0.02F;
        }
Листинг 14.10. Изменение функции DrawCubes()

Обратите внимание на то, сколько много кода мы удалили, а добавили совсем чуть-чуть. Прямая выгода в использовании Mesh -технологии налицо!

  • Запустите приложение - должен получиться такой результат


Итак, мы получили девять вращающихся кубов, но все они оказались бесцветными. Это происходит потому, что цвета Mesh -объекта не были определены и, поскольку у нас выключена подсветка сцены, кубы остались неокрашенными и неосвещенными. Давайте будем это исправлять. Освещение в устройстве device установлено по умолчанию, поэтому можно удалить код выключения освещения или задать соответствующему параметру значение true.

  • Найдите в классе функцию SetupCamera() и замените в секции выключения освещения значение false на true
// Установка камеры в сцену
        private void SetupCamera()
        {
            //Создание перспективы 
            device.Transform.Projection = Matrix.PerspectiveFovLH(
                (float)Math.PI / 4, // Угол зрения равен 45 градусов
                                    // Форматное соотношение сторон
                (float)this.ClientSize.Width / (float)this.ClientSize.Height, 
                1.0F,               // Ближний план
                100.0F);            // Дальний план
    
            //Добавление камеры 
            device.Transform.View = Matrix.LookAtLH(
                new Vector3(0, 0, 15.0F),    // Положение камеры
                new Vector3(),              // Положение объекта текущее
                new Vector3(0, 1, 0));      // Направление камеры
    
            // Освещение
            device.RenderState.Lighting = true;
        }
Листинг 14.11. Включить освещение сцены
  • Запустите приложение, получится такой результат


Теперь наши вращающиеся кубы превратились в черные. В конце лабораторной работы №10 говорилось о том, что Direct3D не может освещать объект, не имея нормали к каждой его поверхности. Нормаль представляет собой вектор, перпендикулярный передней стороне объекта.

Познакомимся с термином " общее освещение " или " общий свет ". Общий свет обеспечивается постоянным источником света для сцены. При этом все объекты на сцене будут освещены равномерно, поскольку общее освещение не зависит ни от местоположения источника, его направленности, ослабления и др. Но несмотря на свою эффективность, такой свет не позволяет добиться реалистичности картины. Но на данном этапе мы воспользуемся общим освещением.

  • Добавьте в конец функции SetupCamera() строку, описывающую состояние рендера подсветки
// Установка камеры в сцену
        private void SetupCamera()
        {
            //Создание перспективы 
            device.Transform.Projection = Matrix.PerspectiveFovLH(
                (float)Math.PI / 4, // Угол зрения равен 45 градусов
                                    // Форматное соотношение сторон
                (float)this.ClientSize.Width / (float)this.ClientSize.Height, 
                1.0F,               // Ближний план
                100.0F);            // Дальний план
    
            //Добавление камеры 
            device.Transform.View = Matrix.LookAtLH(
                new Vector3(0, 0, 15.0F),    // Положение камеры
                new Vector3(),              // Положение объекта текущее
                new Vector3(0, 1, 0));      // Направление камеры
    
            // Освещение
            device.RenderState.Lighting = true;
    
            // Установить красный свет
            device.RenderState.Ambient = Color.Red;
        }
Листинг 14.12. Включаем красный свет

Общий свет и расцветка в сцене определяются состоянием рендера общего освещения. Здесь мы хотим, чтобы наш общий свет стал красным. Если сейчас запустить приложение, то ничего не изменится - кубы будут черными.

Иван Циферблат
Иван Циферблат
Россия, Таганрог, 36, 2000