Вторник, 12.12.2017, 09:20
Поиск
Никнэйм
Сертификат на никнейм Olelucoye, зарегистрирован на Тимофеев Константин Михайлович
Зарегистрируй свой никнейм
Обратная связь
olelucoye.tk@yandex.ru
Реклама AdSense
Реклама
Друзья сайта
  • Лига медицинского права
  • Гостиница "Зай"
  • FAQ по системе
  • Инструкции для uCoz
  • Главная » Статьи » libGDX

    3D модель для libGDX. Пишем код.

    3D модель  для libGDX. Пишем код.

    Используем созданную модель в коде. Создаем libGDX проект - я назвал его Model3D. В качестве заготовки используем код из этой статьи, удалив из него создание и отрисовку модели куба.

    Объявим объект AssetManager - он используется для загрузки внешних файлов в память. Мы используем его для загрузки модели.

        public AssetManager assets;
        boolean loading;
                        
        @Override
        public void create () {
            assets = new AssetManager();
            assets.load("data/gumanoid.g3db", Model.class);
            loading = true;
            ....
       }

    Поскольку для загрузки модели необходимо какое-то время, нам нужно сообщить в метод render() о том, что загрузка модели завершена. Если этого не сделать, рендер попытается нарисовать еще не загруженную модель. что вызовет ошибку. Для этого используем булеву переменную loading. Саму загрузку модели вынесем в отдельный метод:

    public void doneLoading(){
            model = assets.get("data/gumanoid.g3db", Model.class);
            modelInstance = new ModelInstance(model);
            loading = false;
        }

    Я использую двоичную версию модели, но таким же способом можно загружать и json-модель. Теперь рассмотрим внутренности метода render(). Сначала проверим загружена ли наша модель. Если нет вызываем метод загрузки. Дальше снова проверяем загружена ли модель и если да начинаем отрисовку.

    @Override
        public void render () {
            if(loading&&assets.update()){
                doneLoading();
            }
            ......
            if(!loading){
            modelBatch.begin(cam);
            modelBatch.render(modelInstance, environment);
            modelBatch.end();
            }
        }

    Можно запустить и посмотреть, что получилось. 

    Модель загрузилась и отобразилась. Попробуем оживить её. Как я писал в предыдущей статье, для этой модели я создал две анимации - Stay и Walk. Запустим одну из них при запуске приложения. Для этого понадобится контролер анимации AnimationController. Объявим его и немного изменим метод загрузки модели.

        AnimationController animController;
        
        public void doneLoading(){
            model = assets.get("data/gumanoid.g3db", Model.class);
            modelInstance = new ModelInstance(model);
            animController = new AnimationController(modelInstance);
            animController.setAnimation("Skelet|Stay", -1);
            loading = false;
        }

    После загрузки модели и создания экземпляра, инициализируем контролер анимации, передав ему экземпляр модели. Затем ставим на воспроизведение анимацию Stay. Первый параметр метода - это id анимации, его можно увидеть, если открыть json-версию модели в блокноте. Почему id именно "Skelet|Stay" наверняка сказать не могу (так создает Blender), но предполагаю, что у модели может быть несколько скелетов и здесь указывается анимацию какого именно скелета мы запускаем. Второй параметр устанавливает количество повторов анимации. Если его не указывать анимация воспроизведется один раз. Я указал минус один, что означает бесконечное повторение. Также нам нужно обновить контроллер анимации в render(). 

           if(!loading){
            modelBatch.begin(cam);
            modelBatch.render(modelInstance, environment);
            modelBatch.end();
            animController.update(Gdx.graphics.getDeltaTime());
            }

    Запускаем и смотрим - человечек шевелится. Если нужно изменить скорость воспроизведения анимации, нужно увеличить или уменьшить параметр передаваемый в update. Например, такой код animController.update(2f * Gdx.graphics.getDeltaTime()) увеличит скорость воспроизведения анимации в 2 раза.

    Теперь воспроизведем вторую анимацию - при нажатии стрелки вверх модель будет шагать. Для этого нам нужно реализовать интерфейс ввода InputProcessor, в котором мы будем отлавливать нажатия клавиш. Добавим этот интерфейс в главный класс и добавим все его методы.

    public class Model3D extends ApplicationAdapter implements InputProcessor {
        .......
        @Override
        public boolean keyDown(int keycode) {
            // TODO Auto-generated method stub
            return false;
        }
        @Override
        public boolean keyUp(int keycode) {
            // TODO Auto-generated method stub
            return false;
        }
        @Override
        public boolean keyTyped(char character) {
            // TODO Auto-generated method stub
            return false;
        }
        @Override
        public boolean touchDown(int screenX, int screenY, int pointer, int button) {
            // TODO Auto-generated method stub
            return false;
        }
        @Override
        public boolean touchUp(int screenX, int screenY, int pointer, int button) {
            // TODO Auto-generated method stub
            return false;
        }
        @Override
        public boolean touchDragged(int screenX, int screenY, int pointer) {
            // TODO Auto-generated method stub
            return false;
        }
        @Override
        public boolean mouseMoved(int screenX, int screenY) {
            // TODO Auto-generated method stub
            return false;
        }
        @Override
        public boolean scrolled(int amount) {
            // TODO Auto-generated method stub
            return false;
        }
    }

    Все методы возвращают false. Нам нужно переопределить необходимые нам методы и вернуть true. Нас интересуют методы keyDown и keyUp. При нажатии кнопки "стрелка вверх" установим анимацию Walk, при отпускании возвращаем анимацию Stay.

    @Override
        public boolean keyDown(int keycode) {
            if(keycode == Keys.UP){
                animController.setAnimation("Skelet|Walk", -1);
           }
            return true;
        }
        @Override
        public boolean keyUp(int keycode) {
            if(keycode == Keys.UP){
                animController.setAnimation("Skelet|Stay", -1);
           }
            return true;
        }

    Для того, чтобы приложение реагировало на нажатия нужно указать движку контроллер для обработки ввода. Делается это методом Gdx.input.setInputProcessor(controller). Смотрим метод create() и видим, что у нас уже используется контроллер камеры в этом методе (вспоминаем тут). Как же указать еще один контроллер ввода? Для этого используется класс InputMultiplexer. С помощью него мы собираем все имеющиеся у нас контроллеры, а в методе Gdx.input.setInputProcessor(controller) указываем сам мультиплексор в качестве параметра.

        InputMultiplexer multiplexer;
                        
        @Override
        public void create () {
            .....        
            multiplexer = new InputMultiplexer();
            camController = new CameraInputController(cam);
            multiplexer.addProcessor(camController);
            multiplexer.addProcessor(this);
            Gdx.input.setInputProcessor(multiplexer);
        }

    Заметьте, что поскольку мы реализовали интерфейс InputProcessor прямо в главном классе, передаем в мультиплексор в качестве параметра this.

    Запускаем. Человек шевелится. Нажимаем стрелку вверх - человек шагает на месте. Нам этого не достаточно - сделаем так, чтобы модель меняла положение в пространстве при шагании. Для этого объявим еще две переменные - z-координату и флаг движения:

        float z_coord = 0f;
        boolean moving = false;

    При загрузке модели установим экземпляр в начало координат.

        public void doneLoading(){
            .....
            modelInstance = new ModelInstance(model);
            modelInstance.transform.setToTranslation(0, 0, z_coord);
            .....
        }

    Добавим в keyDown и keyUp изменение состояния флага движения.

        @Override
        public boolean keyDown(int keycode) {
            if(keycode == Keys.UP){
                animController.setAnimation("Skelet|Walk", -1);
                moving = true;
            }
            return true;
        }
        @Override
        public boolean keyUp(int keycode) {
            if(keycode == Keys.UP){
                animController.setAnimation("Skelet|Stay", -1);
                moving = false;
            }
            return true;
        }

    В render() отслеживаем состояние флага движения и если он равен true, изменяем координату z  и перемещаем модель в новую точку.

        @Override
        public void render () {
            ....
            if(moving){
                z_coord += 0.02;
                modelInstance.transform.setToTranslation(0, 0, z_coord);
            }
            .....
        }

    Готово! Запускаем и наслаждаемся!

    Полный листинг главного класса.

    import com.badlogic.gdx.ApplicationAdapter;
    import com.badlogic.gdx.Gdx;
    import com.badlogic.gdx.Input.Keys;
    import com.badlogic.gdx.InputMultiplexer;
    import com.badlogic.gdx.InputProcessor;
    import com.badlogic.gdx.assets.AssetManager;
    import com.badlogic.gdx.graphics.GL20;
    import com.badlogic.gdx.graphics.PerspectiveCamera;
    import com.badlogic.gdx.graphics.g3d.Environment;
    import com.badlogic.gdx.graphics.g3d.Model;
    import com.badlogic.gdx.graphics.g3d.ModelBatch;
    import com.badlogic.gdx.graphics.g3d.ModelInstance;
    import com.badlogic.gdx.graphics.g3d.attributes.ColorAttribute;
    import com.badlogic.gdx.graphics.g3d.environment.DirectionalLight;
    import com.badlogic.gdx.graphics.g3d.utils.AnimationController;
    import com.badlogic.gdx.graphics.g3d.utils.CameraInputController;
    public class Model3D extends ApplicationAdapter implements InputProcessor {
        public PerspectiveCamera cam;
        public Model model;
        public ModelInstance modelInstance;
        public ModelBatch modelBatch;
        public Environment environment;
        public CameraInputController camController;
        AnimationController animController;
        public AssetManager assets;
        boolean loading;
        InputMultiplexer multiplexer;
        float z_coord = 0f;
        boolean moving = false;
                    
        @Override
        public void create () {
            assets = new AssetManager();
            assets.load("data/gumanoid.g3db", Model.class);
            loading = true;
            modelBatch = new ModelBatch();
            environment = new Environment();
            environment.set(new ColorAttribute(ColorAttribute.AmbientLight, 0.4f, 0.4f, 0.4f, 1f));
            environment.add(new DirectionalLight().set(0.8f, 0.8f, 0.8f, -1f, -0.8f, -0.2f));
                            
            cam = new PerspectiveCamera(67, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
            cam.position.set(10f, 10f, 10f);
            cam.lookAt(0f, 0f, 0f);
            cam.near = 1f;
            cam.far = 300f;
            cam.update();
            
            multiplexer = new InputMultiplexer();
            camController = new CameraInputController(cam);
            multiplexer.addProcessor(camController);
            multiplexer.addProcessor(this);
            Gdx.input.setInputProcessor(multiplexer);
            
        }
        public void doneLoading(){
            model = assets.get("data/gumanoid.g3db", Model.class);
            modelInstance = new ModelInstance(model);
            modelInstance.transform.setToTranslation(0, 0, z_coord);
            animController = new AnimationController(modelInstance);
            animController.setAnimation("Skelet|Stay", -1);
            loading = false;
        }
        @Override
        public void render () {
            if(loading&&assets.update()){
                doneLoading();
            }
            if(moving){
                z_coord += 0.02;
                modelInstance.transform.setToTranslation(0, 0, z_coord);
            }
            camController.update();
            
            Gdx.gl.glViewport ( 0 , 0 , Gdx.graphics.getWidth (), Gdx.graphics.getHeight ());
            Gdx.gl.glClearColor(0, 0, 1, 1);
            Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT|GL20.GL_DEPTH_BUFFER_BIT);
            
            if(!loading){
            modelBatch.begin(cam);
            modelBatch.render(modelInstance, environment);
            modelBatch.end();
            animController.update(Gdx.graphics.getDeltaTime());
            }
        }
        
        @Override
        public void dispose(){
            modelBatch.dispose();
            model.dispose();
        }
        
        @Override
        public boolean keyDown(int keycode) {
            if(keycode == Keys.UP){
                animController.setAnimation("Skelet|Walk", -1);
                moving = true;
            }
            return true;
        }
        
        @Override
        public boolean keyUp(int keycode) {
            if(keycode == Keys.UP){
                animController.setAnimation("Skelet|Stay", -1);
                moving = false;
            }
            return true;
        }
        
        @Override
        public boolean keyTyped(char character) {
            return false;
        }
        
        @Override
        public boolean touchDown(int screenX, int screenY, int pointer, int button) {
            return false;
        }
        
        @Override
        public boolean touchUp(int screenX, int screenY, int pointer, int button) {
            return false;
        }
        
        @Override
        public boolean touchDragged(int screenX, int screenY, int pointer) {
            return false;
        }
        
        @Override
        public boolean mouseMoved(int screenX, int screenY) {
            return false;
        }
        
        @Override
        public boolean scrolled(int amount) {
            return false;
        }
    }

    3D модель для движка libGDX
    Строим модель с помощью ModelBuilder
    libGDX. Основы 3D программирования.
    Игра Flower. Ловим капли.
    TexturePacker.Создаем атлас текстур.
    Создаем проект на движке libGDX
    Кастомизация EditText
    Кастомизация SeekBar'а
    9-patch изображения для Андроид
    Кастомный ползунок в виде дуги (аналог SeekBar)
    Анимация в Андроид
    Кастомизация элементов управления в Android
    Создание кастомного View-элемента интерфейса.
    Создание виджета - электронные часы с кастомным шрифтом
    Программируем калькулятор на андроид. Урок 1

    Категория: libGDX | Добавил: Olelucoye (11.04.2015)
    Просмотров: 2481
    | Теги: анимация модели, AssetManager, InputProcessor, 3d модель, java, libGDX | Рейтинг: 0.0/0
    Всего комментариев: 0
    Добавлять комментарии могут только зарегистрированные пользователи.
    [ Регистрация | Вход ]
    Меню сайта
    Категории раздела
    Андроид разработка [23]
    libGDX [24]
    Мои андроид проекты [6]
    Excel [7]
    Железяки [5]
    Скрипты в блокноте [4]
    Разное [1]
    Форма входа
    Статистика

    Онлайн всего: 1
    Гостей: 1
    Пользователей: 0
    Яндекс Метрика
    Яндекс.Метрика