Докуметация Cтарт Статьи Форум Лента Вход
Не официальное русскоязычное сообщество
Главная
    Документация jMonkeyEngine
        jMonkeyEngine Уроки и Документация
            Вклады
                Лемур GUI
                    Lemur Джемы #4 : Простая деформация сетки

Lemur Джемы #4 : Простая деформация сетки

Опубликованно: 27.08.2017, 19:09
Последняя редакция, Andry: 16.09.2017 18:00

В этом Lemur Джеме я покажу пример использования класса DMesh для деформирования стандартной Mesh(Сетки) на лету. Lemur Джем # 3 показал, как легко превратить обычные объекты 3D-сцены в интерактивные вещи. Я продолжу это, чтобы превратить эти кубы в искривляющееся балки.

Некоторое сумбурное введение….

Сначала встречаем MBox. MBox ведет себя аналогично кубу из JME, за исключением того, что он может быть «разделен» вдоль любой из основных осей, чтобы предоставить простой под-отдел. Я заменяю старый код инициализации куба(Box) на MBox, чтобы было больше треугольников для морфинга.

Затем есть DMesh и Deformation. DMesh является правильным расширением JME Mesh, которое обертывает любой JME-Mesh и модифицирует его с помощью заданной функции Деформирования. Функция деформации передается каждой позиции и вектору нормали Vector3fs для каждой вершины и вы можете изменять их по вашему желанию.

Класс утилиты Deformations предоставляет некоторые деформирующие функции по умолчанию. (Пока только две) Из них я буду использовать цилиндрическую деформацию в этой демонстрации. Цилиндрическая деформация концептуально искажает пространство вокруг некоторого центра в некотором радиусе. Например, плоская плоскость/сетка может быть деформирована на определенную кривую, помещая начало где-то вне плоскости и обеспечивая соответствующий радиус кривой.

Я думаю, что это, наверное, лучше всего, увидеть. Объяснения трудны без картинки.

В последнем демо я создал 5 обычных сеток JME Box. В этом я создам 5 MBox-сеток следующим образом:

    // MBox похож на JME box за исключением того что он может быть
    // разделен по 3 осям.  В этом примере у нас не будет разделений по x или z
    // и будет 5 разделений по y. Это означает, что каждая длинная вертикальная сторона
    // будет состоять из 6 квадратов.   
    MBox b = new MBox(0.5f, 3, 0.5f, 0, 5, 0);

Для этого применяется деформация следующим образом:

    // Создадим функцию деформации из стандартных.
    // встроенных деформаций. 
    // "цилиндрическая" деформация искажает пространство, так что
    // сетка будет искривляться относительно некоторого «центра» и радиуса.
    //    cylindrical( int majorAxis, int minorAxis,
    //                 Vector3f origin, float radius,
    //                 float start, float limit )  
    // Начало и ограничение контролируют диапазон эффекта вдоль основной
    // оси. 
    final Vector3f curveOrigin = new Vector3f(3, -3, 0) ;
    final float radius = 3;
    final Cylindrical cylDeform = Deformations.cylindrical( 1, 0, curveOrigin, radius, 0, 0 );
            
    // DMesh принимает любую исходную сетку и применяет функцию деформации, создающую
    // сетку с новыми данными. Параметры функции могут быть обновлены позже, чтобы оживить её.
    final DMesh mesh = new DMesh(b, cylDeform);

… и этот DMesh передается в Геометрию вместо box в версии джем 3. После этого у нас есть немного другая настройка слушателя мыши:

    MouseEventControl.addListenersToSpatial(geom,
            new DefaultMouseListener() {
 
                private boolean dragging;       
                private float xLast;
                private float limit = 0;
 
                @Override
                public void mouseButtonEvent( MouseButtonEvent event, Spatial target, Spatial capture ) {
                    event.setConsumed();

                    if( event.isPressed() ) {
                        xLast = event.getX();
                        dragging = true;
                    } else {
                        dragging = false;
                        mesh.createCollisionData();
                        geom.updateModelBound();                                
                    }
                }

                @Override
                public void mouseMoved( MouseMotionEvent event, Spatial target, Spatial capture ) {
                    if( !dragging ) {
                        return;
                    }
                    event.setConsumed();
                            
                    float xDelta = event.getX() - xLast;
                    xLast = event.getX();
                            
                    // Предел устанавливает «диапазон» эффекта от центра.
                    // Таким образом, предел 6 будет максимальным, потому что наши кубы
                    // состоят всего из 6 единиц, а центр, у основания.
                    // Однако ограничение начинает иметь небольшой эффект при 5 или около того.
                    // В этот момент мы переключаемся на перемещение радиуса кривой в.
                    limit += xDelta / 100;
                            
                    // Когда предел равен 7 или более, радиус кривой становится равным
                    // 1.0.  Все, что меньше этого, иначе объект начинает
                    // обертывать сам себя. Таким образом, мы сжимаем максимальный
                    // предел до 7.
                    if( limit > 7 ) {
                        limit = 7;
                    }
                                                        
                    if( limit > 5 ) {
                        // Сдвиньте центр кривой ближе к основе кубов...
                        // т.е: более аккуратная кривая
                        // Радиус меньше 1 начинает обертывать
                        // себя.                            
                        curveOrigin.x = 3 - (limit - 5);
                        cylDeform.setRadius(curveOrigin.x);
                    } else {
                        // Сбросьте центр кривой и радиус обратно в нормальное состояние.
                        curveOrigin.x = 3;
                        cylDeform.setRadius(curveOrigin.x);
                    }
                    cylDeform.setLimit(Math.min(6, limit)); 
                    mesh.updateMesh();                            
                }
                   
                @Override
                public void mouseEntered( MouseMotionEvent event, Spatial target, Spatial capture ) {
                    Material m = ((Geometry)target).getMaterial();
                    m.setColor("Color", ColorRGBA.Yellow);
                }

                @Override
                public void mouseExited( MouseMotionEvent event, Spatial target, Spatial capture ) {
                    Material m = ((Geometry)target).getMaterial();
                    m.setColor("Color", ColorRGBA.Blue);
                }                        
            });

Здесь мы сохранили существующее поведение ввода/выхода устанавливающее сетке желтый/синий цвет. Для этого мы добавили кнопки вниз и вверх для в качестве настройки обнаружения перетаскивания. Дельта х от одного движения перетаскивания мышью к следующему отслеживается и используется для настройки параметров Цилиндрической деформации. Цилиндрическая деформация — это своего рода сложный морфинг, но он дает хорошие результаты, поэтому я использовал его. Однако, как следствие, он имеет множество параметров.

Это та же самая деформация, которую я использую для анимированния кривизны страниц моих пользовательских интерфейсов с 3D-книгами.

Вот полный демо-класс: DeformationDemo.java

И видео …

Смотрите так же:


Переведено для jmonkeyengine.ru, оригинал
Автор перевода: Andry

Добавить комментарий

jMonkeyEngine.ru © 2017. Все права сохранены.