Три дня бился об стол, но разобрался. Все-таки для моего уровня пока не разобраться с трехмерной анимации без сторонних библиотек, разбираем 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);
}
}
}
Архив файла проекта (перед компиляцией переподключите билиотеки из корня).



Этот комментарий был удален автором.
ОтветитьУдалить