Package com.ardor3d.util.geom

Source Code of com.ardor3d.util.geom.Debugger

/**
* Copyright (c) 2008-2012 Ardor Labs, Inc.
*
* This file is part of Ardor3D.
*
* Ardor3D is free software: you can redistribute it and/or modify it
* under the terms of its license which may be found in the accompanying
* LICENSE file or at <http://www.ardor3d.com/LICENSE>.
*/

package com.ardor3d.util.geom;

import java.nio.FloatBuffer;

import com.ardor3d.bounding.BoundingBox;
import com.ardor3d.bounding.BoundingSphere;
import com.ardor3d.bounding.BoundingVolume;
import com.ardor3d.bounding.OrientedBoundingBox;
import com.ardor3d.image.Texture2D;
import com.ardor3d.image.TextureStoreFormat;
import com.ardor3d.math.ColorRGBA;
import com.ardor3d.math.MathUtils;
import com.ardor3d.math.Vector3;
import com.ardor3d.math.type.ReadOnlyColorRGBA;
import com.ardor3d.renderer.Camera;
import com.ardor3d.renderer.ContextManager;
import com.ardor3d.renderer.IndexMode;
import com.ardor3d.renderer.Renderer;
import com.ardor3d.renderer.TextureRenderer;
import com.ardor3d.renderer.TextureRendererFactory;
import com.ardor3d.renderer.queue.RenderBucketType;
import com.ardor3d.renderer.state.BlendState;
import com.ardor3d.renderer.state.RenderState;
import com.ardor3d.renderer.state.TextureState;
import com.ardor3d.renderer.state.WireframeState;
import com.ardor3d.renderer.state.ZBufferState;
import com.ardor3d.scenegraph.IndexBufferData;
import com.ardor3d.scenegraph.Line;
import com.ardor3d.scenegraph.Mesh;
import com.ardor3d.scenegraph.Node;
import com.ardor3d.scenegraph.Spatial;
import com.ardor3d.scenegraph.hint.CullHint;
import com.ardor3d.scenegraph.hint.LightCombineMode;
import com.ardor3d.scenegraph.hint.NormalsMode;
import com.ardor3d.scenegraph.shape.AxisRods;
import com.ardor3d.scenegraph.shape.Box;
import com.ardor3d.scenegraph.shape.OrientedBox;
import com.ardor3d.scenegraph.shape.Quad;
import com.ardor3d.scenegraph.shape.Sphere;
import com.ardor3d.util.ExtendedCamera;

/**
* Debugger provides tools for viewing scene data such as boundings and normals.
*
* Make sure you set the RenderStateFactory before using this class.
*
* @see Debugger#setRenderStateFactory(RenderStateFactory)
*/
public final class Debugger {

    // -- **** METHODS FOR DRAWING BOUNDING VOLUMES **** -- //

    private static final Sphere boundingSphere = new Sphere("bsphere", 10, 10, 1);
    static {
        boundingSphere.getSceneHints().setRenderBucketType(RenderBucketType.Skip);
        boundingSphere.getSceneHints().setNormalsMode(NormalsMode.Off);
        boundingSphere.setRenderState(new WireframeState());
        boundingSphere.setRenderState(new ZBufferState());
        boundingSphere.updateWorldRenderStates(false);
    }
    private static final Box boundingBox = new Box("bbox", new Vector3(), 1, 1, 1);
    static {
        boundingBox.getSceneHints().setRenderBucketType(RenderBucketType.Skip);
        boundingBox.getSceneHints().setNormalsMode(NormalsMode.Off);
        boundingBox.setRenderState(new WireframeState());
        boundingBox.setRenderState(new ZBufferState());
        boundingBox.updateWorldRenderStates(false);
    }
    private static final OrientedBox boundingOB = new OrientedBox("bobox");
    static {
        boundingOB.getSceneHints().setRenderBucketType(RenderBucketType.Skip);
        boundingOB.getSceneHints().setNormalsMode(NormalsMode.Off);
        boundingOB.setRenderState(new WireframeState());
        boundingOB.setRenderState(new ZBufferState());
        boundingOB.updateWorldRenderStates(false);
    }

    /**
     * <code>drawBounds</code> draws the bounding volume for a given Spatial and its children.
     *
     * @param se
     *            the Spatial to draw boundings for.
     * @param r
     *            the Renderer to use to draw the bounding.
     */
    public static void drawBounds(final Spatial se, final Renderer r) {
        drawBounds(se, r, true);
    }

    /**
     * <code>drawBounds</code> draws the bounding volume for a given Spatial and optionally its children.
     *
     * @param se
     *            the Spatial to draw boundings for.
     * @param r
     *            the Renderer to use to draw the bounding.
     * @param doChildren
     *            if true, boundings for any children will also be drawn
     */
    public static void drawBounds(final Spatial se, final Renderer r, boolean doChildren) {
        if (se == null) {
            return;
        }

        if (se.getWorldBound() != null && se.getSceneHints().getCullHint() != CullHint.Always) {
            final Camera cam = Camera.getCurrentCamera();
            final int state = cam.getPlaneState();
            if (cam.contains(se.getWorldBound()) != Camera.FrustumIntersect.Outside) {
                drawBounds(se.getWorldBound(), r);
            } else {
                doChildren = false;
            }
            cam.setPlaneState(state);
        }
        if (doChildren && se instanceof Node) {
            final Node n = (Node) se;
            if (n.getNumberOfChildren() != 0) {
                for (int i = n.getNumberOfChildren(); --i >= 0;) {
                    drawBounds(n.getChild(i), r, true);
                }
            }
        }
    }

    public static void drawBounds(final BoundingVolume bv, final Renderer r) {

        switch (bv.getType()) {
            case AABB:
                drawBoundingBox((BoundingBox) bv, r);
                break;
            case Sphere:
                drawBoundingSphere((BoundingSphere) bv, r);
                break;
            case OBB:
                drawOBB((OrientedBoundingBox) bv, r);
                break;
            default:
                break;
        }
    }

    public static void setBoundsColor(final ReadOnlyColorRGBA color) {
        boundingBox.setDefaultColor(color);
        boundingOB.setDefaultColor(color);
        boundingSphere.setDefaultColor(color);
    }

    public static void drawBoundingSphere(final BoundingSphere sphere, final Renderer r) {
        boundingSphere.setData(sphere.getCenter(), 10, 10, sphere.getRadius());
        boundingSphere.draw(r);
    }

    public static void drawBoundingBox(final BoundingBox box, final Renderer r) {
        boundingBox.setData(box.getCenter(), box.getXExtent(), box.getYExtent(), box.getZExtent());
        boundingBox.draw(r);
    }

    public static void drawOBB(final OrientedBoundingBox box, final Renderer r) {
        boundingOB.getCenter().set(box.getCenter());
        boundingOB.getxAxis().set(box.getXAxis());
        boundingOB.getYAxis().set(box.getYAxis());
        boundingOB.getZAxis().set(box.getZAxis());
        boundingOB.getExtent().set(box.getExtent());
        boundingOB.computeInformation();
        boundingOB.draw(r);
    }

    // -- **** METHODS FOR DRAWING NORMALS **** -- //

    private static final Line normalLines = new Line("normLine");
    static {
        normalLines.getSceneHints().setRenderBucketType(RenderBucketType.Skip);
        normalLines.setRenderState(new ZBufferState());
        normalLines.setLineWidth(3.0f);
        normalLines.getMeshData().setIndexMode(IndexMode.Lines);
        normalLines.getMeshData().setVertexBuffer(BufferUtils.createVector3Buffer(500));
        normalLines.getMeshData().setColorBuffer(BufferUtils.createColorBuffer(500));
        normalLines.updateWorldRenderStates(false);
    }
    private static final Vector3 _normalVect = new Vector3(), _normalVect2 = new Vector3();
    public static final ColorRGBA NORMAL_COLOR_BASE = new ColorRGBA(ColorRGBA.RED);
    public static final ColorRGBA NORMAL_COLOR_TIP = new ColorRGBA(ColorRGBA.PINK);
    public static final ColorRGBA TANGENT_COLOR_BASE = new ColorRGBA(ColorRGBA.ORANGE);
    public static final ColorRGBA TANGENT_COLOR_TIP = new ColorRGBA(ColorRGBA.YELLOW);
    protected static final BoundingBox measureBox = new BoundingBox();
    public static double AUTO_NORMAL_RATIO = .05;

    /**
     * <code>drawNormals</code> draws lines representing normals for a given Spatial and its children.
     *
     * @param element
     *            the Spatial to draw normals for.
     * @param r
     *            the Renderer to use to draw the normals.
     */
    public static void drawNormals(final Spatial element, final Renderer r) {
        drawNormals(element, r, -1f, true);
    }

    public static void drawTangents(final Spatial element, final Renderer r) {
        drawTangents(element, r, -1f, true);
    }

    /**
     * <code>drawNormals</code> draws the normals for a given Spatial and optionally its children.
     *
     * @param element
     *            the Spatial to draw normals for.
     * @param r
     *            the Renderer to use to draw the normals.
     * @param size
     *            the length of the drawn normal (default is -1.0 which means autocalc based on boundings - if any).
     * @param doChildren
     *            if true, normals for any children will also be drawn
     */
    public static void drawNormals(final Spatial element, final Renderer r, final double size, final boolean doChildren) {
        if (element == null) {
            return;
        }

        final Camera cam = Camera.getCurrentCamera();
        final int state = cam.getPlaneState();
        if (element.getWorldBound() != null && cam.contains(element.getWorldBound()) == Camera.FrustumIntersect.Outside) {
            cam.setPlaneState(state);
            return;
        }
        cam.setPlaneState(state);
        if (element instanceof Mesh && element.getSceneHints().getCullHint() != CullHint.Always) {
            final Mesh mesh = (Mesh) element;

            double rSize = size;
            if (rSize == -1) {
                final BoundingVolume vol = element.getWorldBound();
                if (vol != null) {
                    measureBox.setCenter(vol.getCenter());
                    measureBox.setXExtent(0);
                    measureBox.setYExtent(0);
                    measureBox.setZExtent(0);
                    measureBox.mergeLocal(vol);
                    rSize = AUTO_NORMAL_RATIO
                            * ((measureBox.getXExtent() + measureBox.getYExtent() + measureBox.getZExtent()) / 3);
                } else {
                    rSize = 1.0;
                }

                if (Double.isInfinite(rSize) || Double.isNaN(rSize)) {
                    rSize = 1.0;
                }
            }

            final FloatBuffer norms = mesh.getMeshData().getNormalBuffer();
            final FloatBuffer verts = mesh.getMeshData().getVertexBuffer();
            if (norms != null && verts != null && norms.limit() == verts.limit()) {
                FloatBuffer lineVerts = normalLines.getMeshData().getVertexBuffer();
                if (lineVerts.capacity() < (3 * (2 * mesh.getMeshData().getVertexCount()))) {
                    normalLines.getMeshData().setVertexBuffer(null);
                    lineVerts = BufferUtils.createVector3Buffer(mesh.getMeshData().getVertexCount() * 2);
                    normalLines.getMeshData().setVertexBuffer(lineVerts);
                } else {
                    lineVerts.clear();
                    lineVerts.limit(3 * 2 * mesh.getMeshData().getVertexCount());
                    normalLines.getMeshData().setVertexBuffer(lineVerts);
                }

                FloatBuffer lineColors = normalLines.getMeshData().getColorBuffer();
                if (lineColors.capacity() < (4 * (2 * mesh.getMeshData().getVertexCount()))) {
                    normalLines.getMeshData().setColorBuffer(null);
                    lineColors = BufferUtils.createColorBuffer(mesh.getMeshData().getVertexCount() * 2);
                    normalLines.getMeshData().setColorBuffer(lineColors);
                } else {
                    lineColors.clear();
                }

                IndexBufferData<?> lineInds = normalLines.getMeshData().getIndices();
                if (lineInds == null || lineInds.getBufferCapacity() < (normalLines.getMeshData().getVertexCount())) {
                    normalLines.getMeshData().setIndices(null);
                    lineInds = BufferUtils.createIndexBufferData(mesh.getMeshData().getVertexCount() * 2, normalLines
                            .getMeshData().getVertexCount() - 1);
                    normalLines.getMeshData().setIndices(lineInds);
                } else {
                    lineInds.getBuffer().clear();
                    lineInds.getBuffer().limit(normalLines.getMeshData().getVertexCount());
                }

                verts.rewind();
                norms.rewind();
                lineVerts.rewind();
                lineInds.getBuffer().rewind();

                for (int x = 0; x < mesh.getMeshData().getVertexCount(); x++) {
                    _normalVect.set(verts.get(), verts.get(), verts.get());
                    mesh.getWorldTransform().applyForward(_normalVect);
                    lineVerts.put(_normalVect.getXf());
                    lineVerts.put(_normalVect.getYf());
                    lineVerts.put(_normalVect.getZf());

                    lineColors.put(NORMAL_COLOR_BASE.getRed());
                    lineColors.put(NORMAL_COLOR_BASE.getGreen());
                    lineColors.put(NORMAL_COLOR_BASE.getBlue());
                    lineColors.put(NORMAL_COLOR_BASE.getAlpha());

                    lineInds.put(x * 2);

                    _normalVect2.set(norms.get(), norms.get(), norms.get());
                    mesh.getWorldTransform().applyForwardVector(_normalVect2).normalizeLocal().multiplyLocal(rSize);
                    _normalVect.addLocal(_normalVect2);
                    lineVerts.put(_normalVect.getXf());
                    lineVerts.put(_normalVect.getYf());
                    lineVerts.put(_normalVect.getZf());

                    lineColors.put(NORMAL_COLOR_TIP.getRed());
                    lineColors.put(NORMAL_COLOR_TIP.getGreen());
                    lineColors.put(NORMAL_COLOR_TIP.getBlue());
                    lineColors.put(NORMAL_COLOR_TIP.getAlpha());

                    lineInds.put((x * 2) + 1);
                }

                normalLines.onDraw(r);
            }

        }

        if (doChildren && element instanceof Node) {
            final Node n = (Node) element;
            if (n.getNumberOfChildren() != 0) {
                for (int i = n.getNumberOfChildren(); --i >= 0;) {
                    drawNormals(n.getChild(i), r, size, true);
                }
            }
        }
    }

    public static void drawTangents(final Spatial element, final Renderer r, final double size, final boolean doChildren) {
        if (element == null) {
            return;
        }

        final Camera cam = Camera.getCurrentCamera();
        final int state = cam.getPlaneState();
        if (element.getWorldBound() != null && cam.contains(element.getWorldBound()) == Camera.FrustumIntersect.Outside) {
            cam.setPlaneState(state);
            return;
        }
        cam.setPlaneState(state);
        if (element instanceof Mesh && element.getSceneHints().getCullHint() != CullHint.Always) {
            final Mesh mesh = (Mesh) element;

            double rSize = size;
            if (rSize == -1) {
                final BoundingVolume vol = element.getWorldBound();
                if (vol != null) {
                    measureBox.setCenter(vol.getCenter());
                    measureBox.setXExtent(0);
                    measureBox.setYExtent(0);
                    measureBox.setZExtent(0);
                    measureBox.mergeLocal(vol);
                    rSize = AUTO_NORMAL_RATIO
                            * ((measureBox.getXExtent() + measureBox.getYExtent() + measureBox.getZExtent()) / 3f);
                } else {
                    rSize = 1.0;
                }
            }

            final FloatBuffer norms = mesh.getMeshData().getTangentBuffer();
            final FloatBuffer verts = mesh.getMeshData().getVertexBuffer();
            if (norms != null && verts != null && norms.limit() == verts.limit()) {
                FloatBuffer lineVerts = normalLines.getMeshData().getVertexBuffer();
                if (lineVerts.capacity() < (3 * (2 * mesh.getMeshData().getVertexCount()))) {
                    normalLines.getMeshData().setVertexBuffer(null);
                    lineVerts = BufferUtils.createVector3Buffer(mesh.getMeshData().getVertexCount() * 2);
                    normalLines.getMeshData().setVertexBuffer(lineVerts);
                } else {
                    lineVerts.clear();
                    lineVerts.limit(3 * 2 * mesh.getMeshData().getVertexCount());
                    normalLines.getMeshData().setVertexBuffer(lineVerts);
                }

                FloatBuffer lineColors = normalLines.getMeshData().getColorBuffer();
                if (lineColors.capacity() < (4 * (2 * mesh.getMeshData().getVertexCount()))) {
                    normalLines.getMeshData().setColorBuffer(null);
                    lineColors = BufferUtils.createColorBuffer(mesh.getMeshData().getVertexCount() * 2);
                    normalLines.getMeshData().setColorBuffer(lineColors);
                } else {
                    lineColors.clear();
                }

                IndexBufferData<?> lineInds = normalLines.getMeshData().getIndices();
                if (lineInds == null || lineInds.getBufferCapacity() < (normalLines.getMeshData().getVertexCount())) {
                    normalLines.getMeshData().setIndices(null);
                    lineInds = BufferUtils.createIndexBufferData(mesh.getMeshData().getVertexCount() * 2, normalLines
                            .getMeshData().getVertexCount() - 1);
                    normalLines.getMeshData().setIndices(lineInds);
                } else {
                    lineInds.getBuffer().clear();
                    lineInds.getBuffer().limit(normalLines.getMeshData().getVertexCount());
                }

                verts.rewind();
                norms.rewind();
                lineVerts.rewind();
                lineInds.getBuffer().rewind();

                for (int x = 0; x < mesh.getMeshData().getVertexCount(); x++) {
                    _normalVect.set(verts.get(), verts.get(), verts.get());
                    _normalVect.multiplyLocal(mesh.getWorldScale());
                    lineVerts.put(_normalVect.getXf());
                    lineVerts.put(_normalVect.getYf());
                    lineVerts.put(_normalVect.getZf());

                    lineColors.put(TANGENT_COLOR_BASE.getRed());
                    lineColors.put(TANGENT_COLOR_BASE.getGreen());
                    lineColors.put(TANGENT_COLOR_BASE.getBlue());
                    lineColors.put(TANGENT_COLOR_BASE.getAlpha());

                    lineInds.put(x * 2);

                    _normalVect.addLocal(norms.get() * rSize, norms.get() * rSize, norms.get() * rSize);
                    lineVerts.put(_normalVect.getXf());
                    lineVerts.put(_normalVect.getYf());
                    lineVerts.put(_normalVect.getZf());

                    lineColors.put(TANGENT_COLOR_TIP.getRed());
                    lineColors.put(TANGENT_COLOR_TIP.getGreen());
                    lineColors.put(TANGENT_COLOR_TIP.getBlue());
                    lineColors.put(TANGENT_COLOR_TIP.getAlpha());

                    lineInds.put((x * 2) + 1);
                }

                normalLines.setWorldTranslation(mesh.getWorldTranslation());
                normalLines.setWorldRotation(mesh.getWorldRotation());
                normalLines.onDraw(r);
            }

        }

        if (doChildren && element instanceof Node) {
            final Node n = (Node) element;
            if (n.getNumberOfChildren() != 0) {
                for (int i = n.getNumberOfChildren(); --i >= 0;) {
                    drawTangents(n.getChild(i), r, size, true);
                }
            }
        }
    }

    // -- **** METHODS FOR DRAWING AXIS **** -- //

    private static final AxisRods rods = new AxisRods("debug_rods", true, 1);
    static {
        rods.getSceneHints().setRenderBucketType(RenderBucketType.Skip);
    }
    private static boolean axisInited = false;

    public static void drawAxis(final Spatial spat, final Renderer r) {
        drawAxis(spat, r, true, false);
    }

    public static void drawAxis(final Spatial spat, final Renderer r, final boolean drawChildren, final boolean drawAll) {
        if (!axisInited) {
            final BlendState blendState = new BlendState();
            blendState.setBlendEnabled(true);
            blendState.setSourceFunction(BlendState.SourceFunction.SourceAlpha);
            blendState.setDestinationFunction(BlendState.DestinationFunction.OneMinusSourceAlpha);
            rods.setRenderState(blendState);
            rods.updateGeometricState(0, false);
            axisInited = true;
        }

        if (drawAll || (spat instanceof Mesh)) {
            if (spat.getWorldBound() != null) {
                double rSize;
                final BoundingVolume vol = spat.getWorldBound();
                if (vol != null) {
                    measureBox.setCenter(vol.getCenter());
                    measureBox.setXExtent(0);
                    measureBox.setYExtent(0);
                    measureBox.setZExtent(0);
                    measureBox.mergeLocal(vol);
                    rSize = 1 * ((measureBox.getXExtent() + measureBox.getYExtent() + measureBox.getZExtent()) / 3);
                } else {
                    rSize = 1.0;
                }

                rods.setTranslation(spat.getWorldBound().getCenter());
                rods.setScale(rSize);
            } else {
                rods.setTranslation(spat.getWorldTranslation());
                rods.setScale(spat.getWorldScale());
            }
            rods.setRotation(spat.getWorldRotation());
            rods.updateGeometricState(0, false);

            rods.draw(r);
        }

        if ((spat instanceof Node) && drawChildren) {
            final Node n = (Node) spat;
            if (n.getNumberOfChildren() == 0) {
                return;
            }
            for (int x = 0, count = n.getNumberOfChildren(); x < count; x++) {
                drawAxis(n.getChild(x), r, drawChildren, drawAll);
            }
        }
    }

    // -- **** METHODS FOR DISPLAYING BUFFERS **** -- //
    public static final int NORTHWEST = 0;
    public static final int NORTHEAST = 1;
    public static final int SOUTHEAST = 2;
    public static final int SOUTHWEST = 3;

    private static final Quad bQuad = new Quad("", 128, 128);
    private static Texture2D bufTexture;
    private static TextureRenderer bufTexRend;

    static {
        bQuad.getSceneHints().setRenderBucketType(RenderBucketType.Ortho);
        bQuad.getSceneHints().setCullHint(CullHint.Never);
    }

    public static void drawBuffer(final TextureStoreFormat rttFormat, final int location, final Renderer r) {
        final Camera cam = Camera.getCurrentCamera();
        drawBuffer(rttFormat, location, r, cam.getWidth() / 6.25);
    }

    public static void drawBuffer(final TextureStoreFormat rttFormat, final int location, final Renderer r,
            final double size) {
        final Camera cam = Camera.getCurrentCamera();
        r.flushGraphics();
        double locationX = cam.getWidth(), locationY = cam.getHeight();
        bQuad.resize(size, (cam.getHeight() / (double) cam.getWidth()) * size);
        if (bQuad.getLocalRenderState(RenderState.StateType.Texture) == null) {
            final TextureState ts = new TextureState();
            bufTexture = new Texture2D();
            ts.setTexture(bufTexture);
            bQuad.setRenderState(ts);
        }

        int width = cam.getWidth();
        if (!MathUtils.isPowerOfTwo(width)) {
            int newWidth = 2;
            do {
                newWidth <<= 1;

            } while (newWidth < width);
            bQuad.getMeshData().getTextureBuffer(0).put(4, width / (float) newWidth);
            bQuad.getMeshData().getTextureBuffer(0).put(6, width / (float) newWidth);
            width = newWidth;
        }

        int height = cam.getHeight();
        if (!MathUtils.isPowerOfTwo(height)) {
            int newHeight = 2;
            do {
                newHeight <<= 1;

            } while (newHeight < height);
            bQuad.getMeshData().getTextureBuffer(0).put(1, height / (float) newHeight);
            bQuad.getMeshData().getTextureBuffer(0).put(7, height / (float) newHeight);
            height = newHeight;
        }
        if (bufTexRend == null) {
            bufTexRend = TextureRendererFactory.INSTANCE.createTextureRenderer(width, height, r, ContextManager
                    .getCurrentContext().getCapabilities());
            bufTexRend.setupTexture(bufTexture);
        }
        bufTexRend.copyToTexture(bufTexture, 0, 0, width, height, 0, 0);

        final double loc = size * .75;
        switch (location) {
            case NORTHWEST:
                locationX = loc;
                locationY -= loc;
                break;
            case NORTHEAST:
                locationX -= loc;
                locationY -= loc;
                break;
            case SOUTHEAST:
                locationX -= loc;
                locationY = loc;
                break;
            case SOUTHWEST:
            default:
                locationX = loc;
                locationY = loc;
                break;
        }

        bQuad.setWorldTranslation(locationX, locationY, 0);

        bQuad.updateGeometricState(0);
        bQuad.onDraw(r);
        r.flushGraphics();
    }

    // -- **** METHODS FOR DISPLAYING CAMERAS **** -- //
    private static Line lineFrustum;
    private static final ExtendedCamera extendedCamera = new ExtendedCamera();

    public static void drawCameraFrustum(final Renderer r, final Camera camera, final ReadOnlyColorRGBA color,
            final short pattern, final boolean drawOriginConnector) {
        drawCameraFrustum(r, camera, camera.getFrustumNear(), camera.getFrustumFar(), color, pattern,
                drawOriginConnector);
    }

    public static void drawCameraFrustum(final Renderer r, final Camera camera, final double fNear, final double fFar,
            final ReadOnlyColorRGBA color, final short pattern, final boolean drawOriginConnector) {
        if (lineFrustum == null) {
            final FloatBuffer verts = BufferUtils.createVector3Buffer(24);
            final FloatBuffer colors = BufferUtils.createColorBuffer(24);

            lineFrustum = new Line("Lines", verts, null, colors, null);
            lineFrustum.getMeshData().setIndexModes(
                    new IndexMode[] { IndexMode.LineLoop, IndexMode.LineLoop, IndexMode.Lines, IndexMode.Lines });
            lineFrustum.getMeshData().setIndexLengths(new int[] { 4, 4, 8, 8 });
            lineFrustum.setLineWidth(2);
            lineFrustum.getSceneHints().setLightCombineMode(LightCombineMode.Off);

            final BlendState lineBlendState = new BlendState();
            lineBlendState.setEnabled(true);
            lineBlendState.setBlendEnabled(true);
            lineBlendState.setTestEnabled(true);
            lineBlendState.setSourceFunction(BlendState.SourceFunction.SourceAlpha);
            lineBlendState.setDestinationFunction(BlendState.DestinationFunction.OneMinusSourceAlpha);
            lineFrustum.setRenderState(lineBlendState);

            final ZBufferState zstate = new ZBufferState();
            lineFrustum.setRenderState(zstate);
            lineFrustum.updateGeometricState(0.0);

            lineFrustum.getSceneHints().setRenderBucketType(RenderBucketType.Skip);
        }

        lineFrustum.setDefaultColor(color);
        lineFrustum.setStipplePattern(pattern);

        extendedCamera.set(camera);
        extendedCamera.calculateFrustum(fNear, fFar);

        final FloatBuffer colors = lineFrustum.getMeshData().getColorBuffer();
        for (int i = 0; i < 16; i++) {
            BufferUtils.setInBuffer(color, colors, i);
        }
        final float alpha = drawOriginConnector ? 0.4f : 0.0f;
        for (int i = 16; i < 24; i++) {
            colors.position(i * 4);
            colors.put(color.getRed());
            colors.put(color.getGreen());
            colors.put(color.getBlue());
            colors.put(alpha);
        }

        final Vector3[] corners = extendedCamera.getCorners();

        final FloatBuffer verts = lineFrustum.getMeshData().getVertexBuffer();
        BufferUtils.setInBuffer(corners[0], verts, 0);
        BufferUtils.setInBuffer(corners[1], verts, 1);
        BufferUtils.setInBuffer(corners[2], verts, 2);
        BufferUtils.setInBuffer(corners[3], verts, 3);

        BufferUtils.setInBuffer(corners[4], verts, 4);
        BufferUtils.setInBuffer(corners[5], verts, 5);
        BufferUtils.setInBuffer(corners[6], verts, 6);
        BufferUtils.setInBuffer(corners[7], verts, 7);

        BufferUtils.setInBuffer(corners[0], verts, 8);
        BufferUtils.setInBuffer(corners[4], verts, 9);
        BufferUtils.setInBuffer(corners[1], verts, 10);
        BufferUtils.setInBuffer(corners[5], verts, 11);
        BufferUtils.setInBuffer(corners[2], verts, 12);
        BufferUtils.setInBuffer(corners[6], verts, 13);
        BufferUtils.setInBuffer(corners[3], verts, 14);
        BufferUtils.setInBuffer(corners[7], verts, 15);

        BufferUtils.setInBuffer(extendedCamera.getLocation(), verts, 16);
        BufferUtils.setInBuffer(corners[0], verts, 17);
        BufferUtils.setInBuffer(extendedCamera.getLocation(), verts, 18);
        BufferUtils.setInBuffer(corners[1], verts, 19);
        BufferUtils.setInBuffer(extendedCamera.getLocation(), verts, 20);
        BufferUtils.setInBuffer(corners[2], verts, 21);
        BufferUtils.setInBuffer(extendedCamera.getLocation(), verts, 22);
        BufferUtils.setInBuffer(corners[3], verts, 23);

        lineFrustum.draw(r);
    }

}
TOP

Related Classes of com.ardor3d.util.geom.Debugger

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.