Как видно из кода в нем нет ничего сложного. Функция evaluteInput() получает и последовательно обрабатывает состояние устройств ввода сначала клавиатуры затем мыши.
Обработка ввода с клавиатуры происходит в цикле. Сначала мы проверяем есть ли что обрабатывает. Если в пуле есть события то программа последовательно извлекает их из него и в соответствии с условиями case устанавливает состояние клавиш. В данном случае нас интересует исключительно нажата ли клавиша "Пробел", т.к. именно она переключает анимацию.
Код
KeyState ks;
//Обработка клавиатуры
while( ( ks = keyMapper.poll() ) != KeyState.NONE )
{
switch (ks.getKeyCode())
{
//пример Обработки ввода цифр на основной клавиатуре
case KeyEvent.VK_0: {numeric_key = 0;continue;}
//обработка пробела
case KeyEvent.VK_SPACE: {space_key = ks.getState(); continue;}
}
}
[code]
Далее мы читаем и обрабатываем события с мышки не забывая про то, что координаты по Y необходимо инвертировать
[code]
//Обработка мыши
//получение координат мыши
mouse_x = Mouse.getX();
//не забываем про инверсию по Y
mouse_y = buffer.getOutputHeight()-Mouse.getY();
//чтение состояния кнопок мыши
if (Mouse.isButtonDown(0))
{
mouse_leftbutton_down = true;
}
else
{
mouse_leftbutton_down = false;
}
if (Mouse.isButtonDown(1))
{
mouse_rigthbutton_down = true;
}
else
{
mouse_rigthbutton_down = false;
}
С обработкой ввода закончили теперь перейдем к анимации.
Анимация в JPCT реализована в классе
Animation . Данный класс позволяет загрузить ключевые кадры на основании которых будет выполнена анимация, а также метод по которому будут интерполироваться координаты сетки объекта. Рассмотрим некоторые из доступных методов интерполяции:
1) LINEAR - метод линейной интерполяции между кадрами. Этот вид интерполяции является самым быстрым.
2) COSINE - метод косинус интерполяции между кадрами. Этот метод интерполяции немного медленнее, чем линейная интерполяция, но все еще очень быстр. Косинус интерполяции, как правило, "генерирует" кадры, так что анимация выглядит как будто движение выполняет робот.
3) BICUBIC - метод использующий бикубическую интерполяцию между кадрами. Это обеспечивает "сглаживаемую" интерполяция, но она медленнее, чем линейная или косинус интерполяции.
4) KEYFRAMESONLY - метод без интерполяции между кадрами. Это самый быстрый метод отображения Анимации, но при этом анимация выглядит очень некрасиво. Данный метод должен быть использован только для создания специальных эффектов или отладки анимации.
А также режимы выполнения интерполяции:
1) USE_WRAPPING - В этом режиме, интерполяция переходит из позиции 1 (последний кадр) в положение 0 (первый кадр) т.е. ходит по кругу. Это значение установлено по умолчанию.
2) USE_CLAMPING - В этом режиме интерполяции не начинается с начала суб-последовательность, если закончится (и наоборот) т.е. не ходит по кругу.
Они устанавливаются методом setInterpolationMethod.
Заканчиваем с теорией и переходим к практике.
Загрузка кадров анимации выглядит следующим образом:
Код
//Загрузка анимации
Animation animation = new Animation(3);
//Меняем метод расчета интерполяции вершин
// animation.setInterpolationMethod(Animation.BICUBIC);
//анимация стояния
animation.createSubSequence("стояние");
animation.addKeyFrame(model.getMesh());
//анимация движения
animation.createSubSequence("движение");
animation.addKeyFrame(loadModelfrom3DS(".\\res\\testanim2_1.3ds", 1.0f).getMesh());
animation.addKeyFrame(loadModelfrom3DS(".\\res\\testanim2_2.3ds", 1.0f).getMesh());
//добавлении анимации к объекту
model.setAnimationSequence(animation);
Как видно из кода с начала мы инициализируем экземпляр класса Animation числом 3 это общее количество кадров анимации затем мы создаем 2 анимационные последовательности. В первой из них только 1 сетка отражающая стоящий объект. Вторая анимационная последовательность состоит из 2-х кадров отражающих крайние точки анимации при движении объекта. Очень важно чтобы количество полигонов в данных ключевых кадрах совпадало иначе вы увидите при анимации артефакты, следите за этим т.к. при создании и выгрузке анимации вы можете случайно удалить один полигон в результате чего вся работа будет испорчена.
Для расчета анимации в данном примере мною была создана специальная функция doAnimation(), вот ее код:
Код
private void doAnimation() {
AFrame+=0.001f;
if (AFrame>1) {AFrame=0;}
model.animate(AFrame, ASequence);
}
Данная функция очень проста, мы за каждый вызов функции увеличиваем счетчик анимации пока он не станет равным единицы и затем его обнуляем. Расчет вершин проходит при вызове функции animate, принимающей 2 параметра счетчик кадров анимации согласно документации он должен быть равен от 0 до 1 при этом 0 это первый кадр анимации а 1 последний (направление счетчика можно управлять установкой флагов изменения режимов интерполяции) и номер последовательности кадров к которой он должен применяться.