com.mygdx.game.debugdrawers.NavMeshDebugDrawer.java Source code

Java tutorial

Introduction

Here is the source code for com.mygdx.game.debugdrawers.NavMeshDebugDrawer.java

Source

/*******************************************************************************
 * Copyright 2015 See AUTHORS file.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ******************************************************************************/

package com.mygdx.game.debugdrawers;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.ai.pfa.Connection;
import com.badlogic.gdx.graphics.Camera;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.Matrix4;
import com.badlogic.gdx.math.Quaternion;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.utils.Bits;
import com.mygdx.game.objects.GameCharacter;
import com.mygdx.game.pathfinding.*;
import com.mygdx.game.steerers.FollowPathSteerer;
import com.mygdx.game.utilities.MyShapeRenderer;

/**
 * @author jsjolund
 */
public class NavMeshDebugDrawer {

    private final Vector3 tmp1 = new Vector3();
    private final Vector3 tmp2 = new Vector3();
    private final Vector3 tmp3 = new Vector3();
    private final Vector3 tmp4 = new Vector3();
    private final Matrix4 tmpMatrix = new Matrix4();
    private final Quaternion tmpQuat = new Quaternion();
    private Bits visibleLayers;
    private MyShapeRenderer shapeRenderer;
    private NavMesh navMesh;

    private boolean triangleIsVisible(Triangle t) {
        return (visibleLayers.nextSetBit(t.meshPartIndex) != -1);
    }

    private void drawVertex(Vector3 pos, float size, Color color) {
        shapeRenderer.setColor(color);
        float offset = size / 2;
        shapeRenderer.box(pos.x - offset, pos.y - offset, pos.z + offset, size, size, size);
    }

    private void drawNavMeshTriangles() {
        shapeRenderer.set(MyShapeRenderer.ShapeType.Line);
        for (int i = 0; i < navMesh.graph.getNodeCount(); i++) {
            Triangle t = navMesh.graph.getTriangleFromGraphIndex(i);
            if (triangleIsVisible(t)) {
                drawTriangle(t, Color.LIGHT_GRAY, 1);
            }
        }
    }

    private void drawNavMeshIndices(SpriteBatch spriteBatch, Camera camera, BitmapFont font) {
        // TODO: Get rid of all the transform matrix setting
        if (spriteBatch.isDrawing()) {
            spriteBatch.end();
        }
        spriteBatch.begin();
        spriteBatch.setProjectionMatrix(camera.combined);
        for (int i = 0; i < navMesh.graph.getNodeCount(); i++) {
            Triangle t = navMesh.graph.getTriangleFromGraphIndex(i);
            if (triangleIsVisible(t)) {
                tmpMatrix.set(camera.view).inv().getRotation(tmpQuat);
                tmpMatrix.setToTranslation(t.centroid).rotate(tmpQuat);
                spriteBatch.setTransformMatrix(tmpMatrix);
                font.draw(spriteBatch, Integer.toString(t.triIndex), 0, 0);
            }
        }
        spriteBatch.end();
    }

    private void drawTriangle(Triangle tri, Color color, float alpha) {
        shapeRenderer.setColor(color.r, color.g, color.b, alpha);
        shapeRenderer.triangle(tri.a, tri.b, tri.c);
    }

    private void drawPathTriangles(NavMeshGraphPath navMeshGraphPath, Triangle currentTriangle) {
        shapeRenderer.set(MyShapeRenderer.ShapeType.Filled);

        if (navMeshGraphPath != null && navMeshGraphPath.getCount() > 0) {

            for (int i = 0; i < navMeshGraphPath.getCount(); i++) {
                Edge e = (Edge) navMeshGraphPath.get(i);
                if (triangleIsVisible(e.fromNode)) {
                    if (currentTriangle.getIndex() == e.fromNode.getIndex()) {
                        drawTriangle(e.fromNode, Color.RED, 0.2f);
                    } else {
                        drawTriangle(e.fromNode, Color.YELLOW, 0.2f);
                    }
                }
                if (i == navMeshGraphPath.getCount() - 1) {
                    if (triangleIsVisible(e.toNode)) {
                        if (currentTriangle.getIndex() == e.toNode.getIndex()) {
                            drawTriangle(e.toNode, Color.RED, 0.2f);
                        } else {
                            drawTriangle(e.toNode, Color.YELLOW, 0.2f);
                        }
                    }
                }
            }
            // Shared triangle edges
            shapeRenderer.set(MyShapeRenderer.ShapeType.Line);
            for (Connection<Triangle> connection : navMeshGraphPath) {
                Edge e = (Edge) connection;
                if (triangleIsVisible(e.fromNode) || triangleIsVisible(e.toNode)) {
                    shapeRenderer.line(e.rightVertex, e.leftVertex, Color.GREEN, Color.RED);
                }
            }
        } else if (currentTriangle != null) {
            drawTriangle(currentTriangle, Color.RED, 0.2f);
        }

    }

    private void drawPathPoints(NavMeshPointPath navMeshPointPath) {
        shapeRenderer.set(MyShapeRenderer.ShapeType.Line);
        Vector3 q;
        Vector3 p = navMeshPointPath.getVector(navMeshPointPath.getSize() - 1);
        shapeRenderer.setColor(Color.WHITE);
        for (int i = navMeshPointPath.getSize() - 1; i >= 0; i--) {
            q = navMeshPointPath.getVector(i);
            shapeRenderer.setColor(Color.CYAN);
            shapeRenderer.line(p, q);
            p = q;
            drawVertex(p, 0.02f, Color.WHITE);
        }
    }

    public void drawClosestPointDebug(GameCharacter character) {
        Vector3 position = tmp1;
        Vector3 direction = tmp2;
        Vector3 closestPoint = tmp3;
        Vector3 aimPoint = tmp4;
        float radius = 2;
        character.getDirection(direction);
        character.getGroundPosition(position);
        aimPoint.set(direction).scl(radius).add(position);
        Triangle closest = navMesh.getClosestValidPointAt(position, direction, radius, closestPoint,
                character.visibleOnLayers);

        shapeRenderer.set(MyShapeRenderer.ShapeType.Filled);
        shapeRenderer.setColor(0, 0, 1, 0.2f);
        shapeRenderer.triangle(closest.a, closest.b, closest.c);
        drawVertex(aimPoint, 0.05f, Color.GREEN);
        drawVertex(closestPoint, 0.05f, Color.WHITE);

    }

    public void drawNavMesh(MyShapeRenderer shapeRenderer, SpriteBatch spriteBatch, NavMesh navMesh,
            GameCharacter character, Bits visibleLayers, Camera camera, BitmapFont font) {

        this.visibleLayers = visibleLayers;
        this.shapeRenderer = shapeRenderer;
        this.navMesh = navMesh;

        if (shapeRenderer.isDrawing()) {
            shapeRenderer.end();
        }

        Gdx.gl.glEnable(GL20.GL_BLEND);
        Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);
        shapeRenderer.begin(MyShapeRenderer.ShapeType.Line);
        drawNavMeshTriangles();
        if (character != null && character.steerer instanceof FollowPathSteerer) {
            FollowPathSteerer fpSteerer = (FollowPathSteerer) character.steerer;
            drawPathTriangles(fpSteerer.navMeshGraphPath, character.getCurrentTriangle());
            if (fpSteerer.navMeshPointPath.getSize() > 0) {
                drawPathPoints(fpSteerer.navMeshPointPath);
            }
            drawClosestPointDebug(character);
        }
        shapeRenderer.end();
        Gdx.gl.glDisable(GL20.GL_BLEND);

        drawNavMeshIndices(spriteBatch, camera, font);
    }

}