Три дня бился об стол, но разобрался. Все-таки для моего уровня пока не разобраться с трехмерной анимации без сторонних библиотек, разбираем XNAnimatinon.
Результат
Нам понадобиться
Что делаем?
Создаем программку, которая будет отображать трехмерную анимацию персонажа. Модель имеет несколько анимаций, - по нажатию на пробел воспроизводиться следующая анимация персонажа и так по кругу.
Как это реализовать?
К сожалению, стандартными методами данную задачу не реализовать, в XNA отсутствует свой обработчик анимации, базовый пример как это реализовать находиться по адресу http://creators.xna.com/en-US/sample/skinnedmodel. В XNA есть реализация чтения модели из fbx файла, но не более, исключение составляет ситуация, если вы будете управлять анимацией посредством костей в модельке - что приемлемо для не сложных анимаций (пример http://creators.xna.com/sample/simpleanimation). Чтобы прочитать анимацию из fbx нужно подставить вместо стандартного загрузчика модельки свой.
Подготавливаем надстройки.
Из XNAnimatinon, вытягиваем две библиотеки: XNAnimation.dll, XNAnimationPipeline.dll
На XNAnimation ссылаемся в общем проекте, а на XNAnimationPipeline ссылаемся в загрузчике (Content).
Так же в Content создаем 2-е папки Models и Textures, куда указываем модельку fbx и текстуры, соответственно.
Теперь нужно указать явно - через что загружать модельку. Указываем в свойствах модельки загрузчик
Content Processor = Model XNAnimation, Generate TangentFrame = true, путь к текстурам Texture Path = ..\Textures\
Теперь мы готовы к коду, привожу с комментариями.
Результат
Нам понадобиться
- Библиотека XNAnimatinon http://xnanimation.codeplex.com/,
- Microsoft Visual C# 2008 Express Edition,
- XNA 3.1
- моделька с анимацией и текстурами формата fbx (я взял с примеров XNAnimation).
Что делаем?
Создаем программку, которая будет отображать трехмерную анимацию персонажа. Модель имеет несколько анимаций, - по нажатию на пробел воспроизводиться следующая анимация персонажа и так по кругу.
Как это реализовать?
К сожалению, стандартными методами данную задачу не реализовать, в XNA отсутствует свой обработчик анимации, базовый пример как это реализовать находиться по адресу http://creators.xna.com/en-US/sample/skinnedmodel. В XNA есть реализация чтения модели из fbx файла, но не более, исключение составляет ситуация, если вы будете управлять анимацией посредством костей в модельке - что приемлемо для не сложных анимаций (пример http://creators.xna.com/sample/simpleanimation). Чтобы прочитать анимацию из fbx нужно подставить вместо стандартного загрузчика модельки свой.
Подготавливаем надстройки.
Из XNAnimatinon, вытягиваем две библиотеки: XNAnimation.dll, XNAnimationPipeline.dll
На XNAnimation ссылаемся в общем проекте, а на XNAnimationPipeline ссылаемся в загрузчике (Content).
Так же в Content создаем 2-е папки Models и Textures, куда указываем модельку fbx и текстуры, соответственно.
Теперь нужно указать явно - через что загружать модельку. Указываем в свойствах модельки загрузчик
Content Processor = Model XNAnimation, Generate TangentFrame = true, путь к текстурам Texture Path = ..\Textures\
Теперь мы готовы к коду, привожу с комментариями.
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; //Подключаем области из библиотеки анимации using XNAnimation; using XNAnimation.Controllers; using XNAnimation.Effects; namespace _3dAnimationTest { public class Game1 : Microsoft.Xna.Framework.Game { GraphicsDeviceManager graphics; SpriteBatch spriteBatch; ///Архив файла проекта (перед компиляцией переподключите билиотеки из корня)./// Модель /// SkinnedModel skinnedModel; ////// Контроллер анимации /// AnimationController animationController; ////// Матрица вида /// Matrix cameraView; ////// Матрица проекции /// Matrix cameraProjection; ////// Индекс анимации /// int animationIndex = 0; ////// Состояние нажатых клавиш /// KeyboardState kb; ////// Старое состояние нажатых клавищ /// KeyboardState Oldkb; ////// Конструктор /// 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); //Загрузка модели skinnedModel = Content.Load("Models\\PlayerMarine"); //Присвоение контроллера анимации animationController = new AnimationController(skinnedModel.SkeletonBones); //Воспроизводить анимацию по индексу animationController.StartClip(skinnedModel.AnimationClips.Values[animationIndex]); //Матрицы вида и проекции встраиваються cameraView = Matrix.CreateLookAt(new Vector3(10, 15, 30), new Vector3(0, 14, 0), Vector3.Up); cameraProjection = Matrix.CreatePerspectiveFieldOfView(1, 1, 1, 1000); } /// /// Выгрузка данных /// protected override void UnloadContent() { } ////// Обновление данных /// /// Игровое время protected override void Update(GameTime gameTime) { //Вычисляем нажатые клавиши, по нажатию пробел - анимация меняеться на следующую (всего 3 анимации) //Опознаем нажатые клавиши kb = Keyboard.GetState(); //Если нажат пробел и он был отпущен ранее if (kb.IsKeyDown(Keys.Space) && kb!=Oldkb) { //Анимационный индекс = следующему из трех animationIndex = ++animationIndex % 3; //Крутим анимацию уже следующего индекса animationController.StartClip(skinnedModel.AnimationClips.Values[animationIndex]); } //Запоминаем нажатые клавиши Oldkb = kb; //Обновляем анимацию animationController.Update(gameTime.ElapsedGameTime, Matrix.Identity); base.Update(gameTime); } ////// Отображаем данные /// /// Игровое время protected override void Draw(GameTime gameTime) { //Очищаем GraphicsDevice.Clear(Color.CornflowerBlue); //Каждый меш модели foreach (ModelMesh modelMesh in skinnedModel.Model.Meshes) { //Каждый элемент меша foreach (SkinnedModelBasicEffect effect in modelMesh.Effects) { // Устанавливаем камеру effect.View = cameraView; effect.Projection = cameraProjection; // Устанавливаем анимацию (транфрмацию) костей к модели effect.Bones = animationController.SkinnedBoneTransforms; // Настраиваем материал (если надо) effect.Material.DiffuseColor = new Vector3(0.8f); effect.Material.SpecularColor = new Vector3(0.3f); effect.Material.SpecularPower = 8; // Настраиваем свет (если надо) effect.AmbientLightColor = new Vector3(0.1f); effect.LightEnabled = true; effect.EnabledLights = EnabledLights.One; effect.PointLights[0].Color = Vector3.One; effect.PointLights[0].Position = new Vector3(100); } // Рисуем меш modelMesh.Draw(); } base.Draw(gameTime); } } }
Этот комментарий был удален автором.
ОтветитьУдалить