Докуметация Cтарт Статьи Форум Лента Вход
Не официальное русскоязычное сообщество

Отладка

Опубликованно: 03.06.2017, 16:31
Последняя редакция, Andry: 01.01.2018 19:08

Когда вы имеете дело со сложными функциями игрового движка, такими как анимация или физика, полезно получить обратную связь от движка, как он интерпретирует текущее состояние. Является ли форма столкновения физического объекта на самом деле такой, как вы думаете? Является ли скелет анимированного персонажа движущимся так, как вы думаете, это должно быть? В этом документе показано, как активировать визуальные помощники отладки.

Что делать, если вы просто хотите быстро написать код, который загружает модели и помещает их в исходное положение? Возможно, вам не захочется искать образец модели, конвертировать ее, добавлять источники света и загружать материалы. Вместо этого вы можете «без проблем» использовать простые фигуры и незатеняемый материал или каркас: нет модели, нет источника света, нет материалов, необходимых для их просмотра на тестовой сцене.

Если у вас когда-либо возникли проблемы с объектами, появляющимися в неправильном месте, с неправильным масштабом или неправильной ориентацией, просто присоедините фигуры отладки к вашей сцене, чтобы иметь точку отсчета в 3D-пространстве — точно так же, как гигантская линейка. Если ваш код правильно размещает фигуры отладки, но модели остаются невидимыми, когда вы применяете к ним один и тот же код, вы понимаете, что проблема должна быть либо в модели (где расположена ее координата?), Либо в свете (слишком темный? Слишком яркий ? Отсутствует?), Или материал модели (отсутствует?), А не размещающий код.

Вот несколько разных фигур отладки:

debug-shapes

Отладочные фигуры

Координатные оси(Coordinate Axes)

Координатные оси (com.jme3.scene.debug.Arrow) помогут вам увидеть основные направления (X, Y, Z) из их центральной точки. Масштабируйте стрелки, чтобы использовать их как «линейку» на определенную длину.

private void attachCoordinateAxes(Vector3f pos) {
    Arrow arrow = new Arrow(Vector3f.UNIT_X);
    putShape(arrow, ColorRGBA.Red).setLocalTranslation(pos);

    arrow = new Arrow(Vector3f.UNIT_Y);
    putShape(arrow, ColorRGBA.Green).setLocalTranslation(pos);

    arrow = new Arrow(Vector3f.UNIT_Z);
    putShape(arrow, ColorRGBA.Blue).setLocalTranslation(pos);
}

private Geometry putShape(Mesh shape, ColorRGBA color) {
    Geometry g = new Geometry("coordinate axis", shape);
    Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
    mat.getAdditionalRenderState().setWireframe(true);
    mat.getAdditionalRenderState().setLineWidth(4);
    mat.setColor("Color", color);
    g.setMaterial(mat);
    rootNode.attachChild(g);
    return g;
}

Каркас Сетки(Wireframe Grid)

Используйте каркас сетки (com.jme3.scene.debug.Grid) как линейку или простой пол.

private Geometry attachGrid(Vector3f pos, int size, ColorRGBA color) {
    Geometry g = new Geometry("wireframe grid", new Grid(size, size, 0.2f));
    Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
    mat.getAdditionalRenderState().setWireframe(true);
    mat.setColor("Color", color);
    g.setMaterial(mat);
    g.center().move(pos);
    rootNode.attachChild(g);
    return g;
}

Каркас Куба(Wireframe Cube)

Используйте каркас куба (com.jme3.scene.debug.WireBox) в качестве объекта ожидания, чтобы проверить, правильно ли загружаются ваши модели, местоположение или ориентация загружаемых моделей.

public Geometry attachWireBox(Vector3f pos, float size, ColorRGBA color) {
    Geometry g = new Geometry("wireframe cube", new WireBox(size, size, size));
    Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
    mat.getAdditionalRenderState().setWireframe(true);
    mat.setColor("Color", color);
    g.setMaterial(mat);
    g.setLocalTranslation(pos);
    rootNode.attachChild(g);
    return g;
}

Каркас Сферы(Wireframe Sphere)

Используйте каркас сферы (com.jme3.scene.debug.WireSphere) в качестве объекта ожидания, чтобы проверить, правильно ли загружаются ваши модели, местоположение или ориентация загружаемых моделей.

private Geometry attachWireSphere(Vector3f pos, float size, ColorRGBA color) {
    Geometry g = new Geometry("wireframe sphere", new WireSphere(size));
    Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
    mat.getAdditionalRenderState().setWireframe(true);
    mat.setColor("Color", color);
    g.setMaterial(mat);
    g.setLocalTranslation(pos);
    rootNode.attachChild(g);
    return g;
}

Каркас для Физики

Вы можете отображать каркасы (обычно невидимой) фигур столкновения вокруг всех объектов с физикой. Используйте это для отладки при анализе неожиданного поведения. Не работает с физикой DETACHED, пожалуйста, переключитесь на PARALLEL или SEQUENTIAL для отладки.

//Создадим пространство с физикой.
bulletAppState = new BulletAppState();
bulletAppState.setDebugEnabled(true);
getStateManager().attach(bulletAppState);

При отладке включаются цвета используемые для обозначения различных типов физических объектов:

  • Пурпурная проволочная сетка указывает на активное твердое тело.
  • Синяя проволочная сетка указывает на твердое тело, которое является новым или неактивным.
  • Желтая проволочная сетка указывает на призрак.
  • Две зеленые стрелки указывают на соединение.
  • Розовая сетка указывает персонажа.

Каркас для анимации

Создание скелета, видимого внутри анимированных моделей, может быть удобно для отладки анимации. Объектом control является AnimControl, player — загруженная модель.

Известно что AnimControl находится в главном узле

     SkeletonDebugger skeletonDebug =
         new SkeletonDebugger("skeleton", control.getSkeleton());
     Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
     mat.setColor("Color", ColorRGBA.Green);
     mat.getAdditionalRenderState().setDepthTest(false);
     skeletonDebug.setMaterial(mat);
     player.attachChild(skeletonDebug);

AnimControl вставьте где нибудь

private void debugSkeleton(Node player) {
    player.depthFirstTraversal(new SceneGraphVisitorAdapter() {
        @Override
        public void visit(Node node) {
            if (node.getControl(AnimControl.class) != null) {
                AnimControl control = node.getControl(AnimControl.class);
                SkeletonDebugger skeletonDebug = new SkeletonDebugger("skeleton",
                        control.getSkeleton());
                Material mat = new Material(getApplication().getAssetManager(),
                        "Common/MatDefs/Misc/Unshaded.j3md");
                mat.setColor("Color", ColorRGBA.Green);
                mat.getAdditionalRenderState().setDepthTest(false);
                skeletonDebug.setMaterial(mat);
                player.attachChild(skeletonDebug);
            }
        }
    });
}

Пример: переключение каркаса на модель

Мы предполагаем, что вы загрузили модель с материалом mat.

Затем вы можете добавить переключатель для включения и выключения каркаса модели, например:

  1. Создайте триггер клавиши ввода, который будет переключается между двумя материалами: например. Мы переключаемся при нажатии клавиши Т.
    inputManager.addMapping("toggle wireframe", new KeyTrigger(KeyInput.KEY_T));
    inputManager.addListener(actionListener, "toggle wireframe");
  2. Теперь добавьте действие toggle к слушателю действий.
    private ActionListener actionListener = new ActionListener() {
        @Override
        public void onAction(String name, boolean pressed, float tpf) {
            // toggle каркаса
            if (name.equals("toggle wireframe") && !pressed) {
                wireframe = !wireframe; // toggle boolean
                mat.getAdditionalRenderState().setWireframe(wireframe);
            }
            // иначе ... другие тесты ввода.
        }
    };
  3. Кроме того, вы можете перемещаться по всей сцене и переключаться так для всех объектов геометрий там, если вы не хотите создавать новый SceneProcessor
    private ActionListener actionListener = new ActionListener() {
        boolean wireframe = false;
    
        @Override
        public void onAction(String name, boolean pressed, float tpf) {
            // toggle каркаса
            if (name.equals("toggle wireframe") && !pressed) {
                wireframe = !wireframe; // toggle boolean
                rootNode.depthFirstTraversal(new SceneGraphVisitor() {
                    @Override
                    public void visit(Spatial spatial) {
                        if (spatial instanceof Geometry) {
                            ((Geometry) spatial).getMaterial()
                                    .getAdditionalRenderState().setWireframe(wireframe);
                        }
                    }
                });
            }
            // иначе ... другие тесты ввода.
        }
    };
    
Чтобы установить ширину линии отображения каркаса, используйте mesh.setLineWidth(lineWidth). Ширина линии по умолчанию — 1.

Пример: переключение каркаса сцены

Чтобы отображать каркас всей сцены вместо одного материала за раз, сначала создайте следующий Scene Processor

public class WireProcessor implements SceneProcessor {

    RenderManager renderManager;
    Material wireMaterial;

    public WireProcessor(AssetManager assetManager) {
        wireMaterial = new Material(assetManager, "/Common/MatDefs/Misc/Unshaded.j3md");
        wireMaterial.setColor("Color", ColorRGBA.Blue);
        wireMaterial.getAdditionalRenderState().setWireframe(true);
    }

    @Override
    public void initialize(RenderManager rm, ViewPort vp) {
        renderManager = rm;
    }

    @Override
    public void reshape(ViewPort vp, int w, int h) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public boolean isInitialized() {
        return renderManager != null;
    }

    @Override
    public void preFrame(float tpf) {
    }

    @Override
    public void postQueue(RenderQueue rq) {
        renderManager.setForcedMaterial(wireMaterial);
    }

    @Override
    public void postFrame(FrameBuffer out) {
        renderManager.setForcedMaterial(null);
    }

    @Override
    public void cleanup() {
        renderManager.setForcedMaterial(null);
    }
}

Затем присоедините Scene Processor к GUI Viewport.

getViewPort().addProcessor(new WireProcessor());

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

  • Spatial— если вы не видите некоторые spatial, вы можете изменить поведение отсечения, чтобы идентифицировать проблемы (например, пользовательские сетки отображаемые с внутренней стороны)

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

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

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