Спонсор: Microsoft
Опубликован: 10.04.2009 | Уровень: специалист | Доступ: свободно
Самостоятельная работа 15:

Пространственные преобразования объектов

Аннотация: Эта лабораторная работа посвящена пространственным преобразованиям трехмерных объектов. В частности, здесь мы поговорим о перемещении объектов, об их масштабировании, обсудим настройку перемещения камеры.

Примеры к лабораторной работе

Задачи работы

  • Освоить технику перемещения объектов
  • Освоить технику масштабирования объектов
  • Освоить технику перемещения камеры

Пространственные преобразования объектов

Создадим новый проект P15_1 и на его примере рассмотрим следующие пространственные преобразования объектов

  • Перемещение
  • Вращение
  • Масштабирование

Для выполнения этих операций нам понадобится модификация мировой матрицы. Модификации, соответствующие перемещению объекта мы выполним по клавиатурным командам, остальные модификации будут выполняться автоматически в цикле обновления.

Для этого примера мы создали несколько простых трехмерных моделей в редакторе Blender. В частности – это два разноцветных шара и куб. Вот как выглядит игровой экран проекта P15_1 (рис. 20.1.).

Игровой экран проекта P15_1

увеличить изображение
Рис. 20.1. Игровой экран проекта P15_1

Для упрощения работы с несколькими игровыми объектами мы создадим игровой компонент - modCls, который будет отвечать за хранение параметров, соответствующих этим объектам и за их визуализацию. В листинге 20.1. вы можете видеть код этого объекта.

using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Storage;
using Microsoft.Xna.Framework.Content;

namespace P15_1
{
    public class modCls : Microsoft.Xna.Framework.DrawableGameComponent
    {
        //Модель
        Model myModel;
        //Мировая матрица
        public  Matrix WorldMatrix;
        //Соотношение сторон экрана
        public  float aspectRatio;
        //Для управления графическим устройством
        GraphicsDeviceManager graphics;
        //Конструктор получает на вход 
        //игровой класс, модель, объект для управления графическим устройством
        public modCls(Game game, Model mod, GraphicsDeviceManager grf)
            : base(game)
        {
            myModel = mod;
            graphics = grf;
            aspectRatio = (float)graphics.GraphicsDevice.Viewport.Width /
(float)graphics.GraphicsDevice.Viewport.Height;
        }

        public override void Initialize()
        {
            // TODO: Add your initialization code here
            base.Initialize();
        }

        public override void Update(GameTime gameTime)
        {

            foreach (ModelMesh mesh in myModel.Meshes)
            {
                //Для каждого эффекта в сети
                foreach (BasicEffect effect in mesh.Effects)
                {
                    //Установить освещение по умолчанию
                    effect.LightingEnabled = true;
                    effect.EnableDefaultLighting();
                    //установить матрицы
                    effect.World = WorldMatrix;
                    effect.View = Matrix.CreateLookAt(new Vector3(0.0f, 0.0f, 10.0f), Vector3.Zero, Vector3.Up);
                    effect.Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45.0f),
                         aspectRatio, 1.0f, 1000.0f);
                }
            }

            base.Update(gameTime);
        }
        public override void Draw(GameTime gameTime)
        {
            foreach (ModelMesh mesh in myModel.Meshes)
            {
                mesh.Draw();
            }
            base.Draw(gameTime);
        }
    }
}
Листинг 20.1. Код класса modCls

Управление объектами возложено на основной игровой класс – его метод Update используется для вычисления новых позиций объектов и обновления информации объектов. Код этого класса вы можете видеть в листинге 20.2. Шар, расположенный сверху, автоматически циклически изменяет размер, куб вращается вокруг осей X и Y, шар, расположенный ниже, можно перемещать. Клавиши-стрелки используются для перемещения по осям X и Y (вверх, вниз, влево и вправо), клавиши W и S перемещают объект вперед и назад по оси Z.

using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;

namespace P15_1
{
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        //Мировая матрица
        Matrix WorldMatrixM, WorldMatrixM1, WorldMatrixM2;
        //Направление движения для модели modelCls1
        Vector3 directM1;
        //Модели - 
        //modelCls вращается
        //modelCls1 перемещается по клавиатурным командам
        //modelCls2 изменяет размер
        modCls modelCls, modelCls1, modelCls2;
        //Переменные для текущего размера и 
        //текущего приращения размера модели modelCls2
        float size, sizeDelta;
        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        protected override void Initialize()
        {
            // TODO: Add your initialization logic here

            base.Initialize();
        }

        protected override void LoadContent()
        {
            //загрузка моделей и создание объектов, используемых для 
            //хранения информации о моделях и их вывода на экран
            modelCls = new modCls(this, Content.Load<Model>("cube"), graphics);
            modelCls1 = new modCls(this, Content.Load<Model>("ball"), graphics);
            modelCls2 = new modCls(this, Content.Load<Model>("ball2"), graphics);
            //Добавляем объекты в коллекцию Components - для их 
            //автоматического вывода на экран
            Components.Add(modelCls);
            Components.Add(modelCls1);
            Components.Add(modelCls2);
            //Значения для приращения размера и текущего размера
            sizeDelta = 0.01f;
            size = 0.5f;
            //Установка исходного положения для модели modelCls1
            directM1 = new Vector3(2.0f, -1.0f, 1.0f);
            //Установка матриц, которые используются для управления объектами
            WorldMatrixM = Matrix.Identity;
            WorldMatrixM1 = Matrix.CreateTranslation(directM1);
            WorldMatrixM2 = Matrix.CreateScale(size);
        }

        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        protected override void Update(GameTime gameTime)
        {


            KeyboardState kb = Keyboard.GetState();
            //По нажатии клавиши-стрелки "вверх" перемещаем модель
            //modelCls1 вверх
            if (kb.IsKeyDown(Keys.Up))
            {
                directM1.Y=directM1 .Y +0.1f;
                WorldMatrixM1 = Matrix.CreateTranslation(directM1);
            }
            //Нажатие клавиши "вниз" - перемещение вниз
            if (kb.IsKeyDown(Keys.Down))
            {
                directM1.Y = directM1.Y - 0.1f;
                WorldMatrixM1 = Matrix.CreateTranslation(directM1);
            }
            //Нажатие клавиши "влево" - перемещение влево
            if (kb.IsKeyDown(Keys.Left))
            {
                directM1.X = directM1.X - 0.1f;
                WorldMatrixM1 = Matrix.CreateTranslation(directM1);
            }
            //Нажатие клавиши "вправо" - перемещение вправо
            if (kb.IsKeyDown(Keys.Right))
            {
                directM1.X = directM1.X + 0.1f;
                WorldMatrixM1 = Matrix.CreateTranslation(directM1);
            }
            //Нажатие клавиши "W" - перемещение вперед
            if (kb.IsKeyDown(Keys.W))
            {
                directM1.Z = directM1.Z - 0.1f;
                WorldMatrixM1 = Matrix.CreateTranslation(directM1);
            }
            //Нажатие клавиши "S" - перемещение назад
            if (kb.IsKeyDown(Keys.S))
            {
                directM1.Z = directM1.Z + 0.1f;
                WorldMatrixM1 = Matrix.CreateTranslation(directM1);
            }
            
            //Если текущий размер меньше 0.5 - 
            //устанавливаем приращение, равное 0.01
            //Если текущий размер больше 1.5 -
            //устанавливаем приращение -0.01
            if (size < 0.5) sizeDelta = 0.01f;
            if (size > 1.5) sizeDelta = -0.01f;
            size += sizeDelta;

            //Матрица для объекта modelCls1 устанавливается для поворота его вокруг
            //осей X и Y на один градус
            WorldMatrixM = WorldMatrixM * Matrix.CreateRotationY(MathHelper.ToRadians(1))*
                Matrix .CreateRotationX (MathHelper .ToRadians (1));
            //Установка матрицы для объекта modelCls2
            WorldMatrixM2 = Matrix.CreateScale(size) * Matrix.CreateTranslation(new Vector3(-5.0f, 2.0f, -3.0f));
            //Передаем матрицы объектам
            modelCls.WorldMatrix = WorldMatrixM;
            modelCls1.WorldMatrix = WorldMatrixM1;
            modelCls2.WorldMatrix = WorldMatrixM2;
            base.Update(gameTime);
        }

   
        protected override void Draw(GameTime gameTime)
        {
            graphics.GraphicsDevice.Clear(Color.CornflowerBlue);
            
            base.Draw(gameTime);
        }
    }
}
Листинг 20.2. Код класса Game1

Рассмотрев способы модификации объектов, поговорим об особенностях настройки камеры.

Alina Lasskaja
Alina Lasskaja

Быть может кто-то из Вас знает игру Sims, к какому жанру она относиться? Жизненная симуляция, ролевая игра, там можно и дома строить.....