К основному контенту

XNA: Первое 3D

Создаю первое 3D - базовый минимум, чтобы понять как отрисовывать. Объяснений минимум - в коде комментарии. За базу брал http://msdn.microsoft.com/en-us/library/bb197293.aspx Модельку взял с http://www.turbosquid.com/3d-models/free-max-mode-old-wood-crate/473045 .
Среда: Microsoft Visual C# 2008, XNA 3.1
Код:
using System;
using System.Collections.Generic;
using System.Linq;
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.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;

namespace _3dtest
{
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;

        /// 
        /// 3Д Модель (включая текстуры)
        /// 
        Model myModel;
        /// 
        /// Соотношение сторон
        /// 
        float aspectRatio;
        /// 
        /// Начальная позиция 3д модели
        /// 
        Vector3 modelPosition = Vector3.Zero;
        /// 
        /// Вращение зд модели
        /// 
        float modelRotation = 0.0f;
        /// 
        /// Начальная позиция камеры
        /// 
        Vector3 cameraPosition = new Vector3(0.0f, 5.0f, 5.3f);
        
        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
            graphics.PreferMultiSampling = true;//Включить антиальясинг (сглаживание линий)
        }

        protected override void Initialize()
        {
            base.Initialize();
        }

        protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);
            //Загружаем 3д модель
            myModel = Content.Load("Crate1");
            //Читаем соотношение сторон (текущее видимое соотношение сторон)
            aspectRatio = graphics.GraphicsDevice.Viewport.AspectRatio;
        }

        protected override void UnloadContent()
        {

        }

        protected override void Update(GameTime gameTime)
        {
            KeyboardState kb = Keyboard.GetState();
            //Клавиша вверх - приближение
            if (kb.IsKeyDown(Keys.Up)) cameraPosition.Z-=1;
            //Клавиша вниз отдаление
            if (kb.IsKeyDown(Keys.Down)) cameraPosition.Z+=1;
            //Эскейп - выход
            if (kb.IsKeyDown(Keys.Escape)) this.Exit();
            //С течением времени (прошедшие милисекунды) 3д модель вращаеться
            modelRotation += (float)gameTime.ElapsedGameTime.TotalMilliseconds*0.1f * MathHelper.ToRadians(0.1f);

            base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            //Предварительно копируем все трансформации
            Matrix[] transforms = new Matrix[myModel.Bones.Count];
            myModel.CopyAbsoluteBoneTransformsTo(transforms);
            //В модели может быть несколько мэшей - перебираем все
            foreach (ModelMesh mesh in myModel.Meshes)
            {
                //Перебараем все составляющие мэша
                foreach (BasicEffect effect in mesh.Effects)
                {
                    //Стандартное освещение
                    effect.EnableDefaultLighting();
                    //Формирование матрицы позиции (мировая координата)
                    effect.World = transforms[mesh.ParentBone.Index] * Matrix.CreateRotationY(modelRotation) * Matrix.CreateTranslation(modelPosition);
                    //Формирование матрицы вида
                    effect.View = Matrix.CreateLookAt(cameraPosition, Vector3.Zero, Vector3.Up);
                    //Формирование матрицы проэкции
                    effect.Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45.0f), aspectRatio, 1.0f, 10000.0f);
                }
                //Рисуем мэш
                mesh.Draw();
            }
            base.Draw(gameTime);
        }
    }
}

Файл примера выкладывать не буду - из-за мэша занимает 16Мб, - помойму тут и так все прозрачно.

Комментарии