Package com.ardor3d.util.stat.graph

Source Code of com.ardor3d.util.stat.graph.LineGrapher$LineEntry

/**
* 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.stat.graph;

import java.nio.FloatBuffer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

import com.ardor3d.math.ColorRGBA;
import com.ardor3d.math.Vector3;
import com.ardor3d.math.type.ReadOnlyVector3;
import com.ardor3d.renderer.ContextCapabilities;
import com.ardor3d.renderer.IndexMode;
import com.ardor3d.renderer.Renderer;
import com.ardor3d.renderer.queue.RenderBucketType;
import com.ardor3d.renderer.state.BlendState;
import com.ardor3d.scenegraph.Line;
import com.ardor3d.scenegraph.Node;
import com.ardor3d.scenegraph.Point;
import com.ardor3d.scenegraph.hint.CullHint;
import com.ardor3d.util.Constants;
import com.ardor3d.util.geom.BufferUtils;
import com.ardor3d.util.stat.MultiStatSample;
import com.ardor3d.util.stat.StatCollector;
import com.ardor3d.util.stat.StatType;

public class LineGrapher extends AbstractStatGrapher implements TableLinkable {

    public static final StatType Vertical = new StatType("_lineGrapher_vert");
    public static final StatType Horizontal = new StatType("_lineGrapher_horiz");

    public enum ConfigKeys {
        ShowPoints, PointSize, PointColor, Antialias, ShowLines, Width, Stipple, Color, FrameAverage,
    }

    protected Node _graphRoot = new Node("root");
    protected Line _horizontals, _verticals;
    protected int _eventCount = 0;
    protected int _threshold = 1;
    protected float _startMarker = 0;
    private float _off;
    private float _vSpan;
    private static final int majorHBar = 20;
    private static final int majorVBar = 10;

    private final HashMap<StatType, LineEntry> _entries = new HashMap<StatType, LineEntry>();

    private BlendState _defBlendState = null;

    public LineGrapher(final int width, final int height, final Renderer renderer, final ContextCapabilities caps) {
        super(width, height, renderer, caps);

        // Setup our static horizontal graph lines
        createHLines();

        _defBlendState = new BlendState();
        _defBlendState.setEnabled(true);
        _defBlendState.setBlendEnabled(true);
        _defBlendState.setSourceFunction(BlendState.SourceFunction.SourceAlpha);
        _defBlendState.setDestinationFunction(BlendState.DestinationFunction.OneMinusSourceAlpha);
        _graphRoot.setRenderState(_defBlendState);
        _graphRoot.getSceneHints().setCullHint(CullHint.Never);
    }

    public void statsUpdated() {
        if (!isEnabled() || !Constants.updateGraphs) {
            return;
        }

        // Turn off stat collection while we draw this graph.
        StatCollector.pause();

        // some basic stats:
        final int texWidth = _gWidth;
        final int texHeight = _gHeight;

        // On stat event:
        // - check if enough events have been triggered to cause an update.
        _eventCount++;
        _off += StatCollector.getStartOffset();
        if (_eventCount < _threshold) {
            return;
        } else {
            _eventCount = 0;
        }

        // - (Re)attach horizontal bars.
        if (!_graphRoot.equals(_horizontals.getParent())) {
            _graphRoot.attachChild(_horizontals);
        }

        // - Check if we have valid vertical bars:
        final float newVSpan = calcVSpan();
        if (_verticals == null || newVSpan != _vSpan) {
            _vSpan = newVSpan;
            createVLines();
        }
        _off %= (StatCollector.getSampleRate() * majorVBar);

        // - (Re)attach vertical bars.
        if (!_graphRoot.equals(_verticals.getParent())) {
            _graphRoot.attachChild(_verticals);
        }

        // - shift verticals based on current time
        shiftVerticals();

        for (final StatType type : _entries.keySet()) {
            _entries.get(type).visited = false;
            _entries.get(type).verts.clear();
        }

        // - For each sample, add points and extend the lines of the
        // corresponding Line objects.
        synchronized (StatCollector.getHistorical()) {
            for (int i = 0; i < StatCollector.getHistorical().size(); i++) {
                final MultiStatSample sample = StatCollector.getHistorical().get(i);
                for (final StatType type : _config.keySet()) {
                    if (sample.containsStat(type)) {
                        LineEntry entry = _entries.get(type);
                        // Prepare our entry object as needed.
                        if (entry == null || entry.maxSamples != StatCollector.getMaxSamples()) {
                            entry = new LineEntry(StatCollector.getMaxSamples(), type);
                            _entries.put(type, entry);
                        }

                        final double value = getBooleanConfig(type, ConfigKeys.FrameAverage.name(), false) ? sample
                                .getStatValue(type).getAverageValue() : sample.getStatValue(type).getAccumulatedValue();

                        final Vector3 point = new Vector3(i, value, 0);
                        // Now, add
                        entry.verts.add(point);

                        // Update min/max
                        if (entry.max < value) {
                            entry.max = value;
                        }

                        entry.visited = true;
                    } else {
                        final LineEntry entry = _entries.get(type);
                        if (entry != null) {
                            entry.verts.add(new Vector3(i, 0, 0));
                        }
                    }
                }
            }
        }

        for (final Iterator<StatType> i = _entries.keySet().iterator(); i.hasNext();) {
            final LineEntry entry = _entries.get(i.next());
            // - Go through the entries list and remove any that were not visited.
            if (!entry.visited) {
                entry.line.removeFromParent();
                entry.point.removeFromParent();
                i.remove();
                continue;
            }

            // - Update the Point and Line params with the verts and count.
            final FloatBuffer fb = BufferUtils.createFloatBuffer(entry.verts.toArray(new Vector3[entry.verts.size()]));
            entry.point.getMeshData().setVertexBuffer(fb);
            final double scaleWidth = texWidth / (StatCollector.getMaxSamples() - 1.0);
            final double scaleHeight = texHeight / (entry.max * 1.02);
            entry.point.setScale(new Vector3(scaleWidth, scaleHeight, 1));
            entry.line.getMeshData().setVertexBuffer(fb);
            entry.line.setScale(new Vector3(scaleWidth, scaleHeight, 1));
            fb.rewind();

            // - attach point/line to root as needed
            if (!_graphRoot.equals(entry.line.getParent())) {
                _graphRoot.attachChild(entry.line);
            }
            if (!_graphRoot.equals(entry.point.getParent())) {
                _graphRoot.attachChild(entry.point);
            }
        }

        // - Now, draw to texture via a TextureRenderer
        _graphRoot.updateGeometricState(0, true);
        _textureRenderer.render(_graphRoot, _texture, Renderer.BUFFER_COLOR_AND_DEPTH);

        // Turn stat collection back on.
        StatCollector.resume();
    }

    private float calcVSpan() {
        return _textureRenderer.getWidth() * majorVBar / StatCollector.getMaxSamples();
    }

    private void shiftVerticals() {
        final int texWidth = _textureRenderer.getWidth();
        final double xOffset = -(_off * texWidth) / (StatCollector.getMaxSamples() * StatCollector.getSampleRate());
        final ReadOnlyVector3 trans = _verticals.getTranslation();
        _verticals.setTranslation(xOffset, trans.getY(), trans.getZ());
    }

    public int getThreshold() {
        return _threshold;
    }

    public void setThreshold(final int threshold) {
        _threshold = threshold;
    }

    // - Setup horizontal bars
    private void createHLines() {
        // some basic stats:
        final int texWidth = _textureRenderer.getWidth();
        final int texHeight = _textureRenderer.getHeight();

        final FloatBuffer verts = BufferUtils.createVector3Buffer((100 / majorHBar) * 2);

        final float div = texHeight * majorHBar / 100f;

        for (int y = 0, i = 0; i < verts.capacity(); i += 6, y += div) {
            verts.put(0).put(y).put(0);
            verts.put(texWidth).put(y).put(0);
        }

        _horizontals = new Line("horiz", verts, null, null, null);
        _horizontals.getMeshData().setIndexMode(IndexMode.Lines);
        _horizontals.getSceneHints().setRenderBucketType(RenderBucketType.Ortho);

        _horizontals.setDefaultColor(getColorConfig(LineGrapher.Horizontal, ConfigKeys.Color.name(), new ColorRGBA(
                ColorRGBA.BLUE)));
        _horizontals.setLineWidth(getIntConfig(LineGrapher.Horizontal, ConfigKeys.Width.name(), 1));
        _horizontals
                .setStipplePattern(getShortConfig(LineGrapher.Horizontal, ConfigKeys.Stipple.name(), (short) 0xFF00));
        _horizontals.setAntialiased(getBooleanConfig(LineGrapher.Horizontal, ConfigKeys.Antialias.name(), true));
    }

    // - Setup enough vertical bars to have one at every (10 X samplerate)
    // secs... we'll need +1 bar.
    private void createVLines() {
        // some basic stats:
        final int texWidth = _textureRenderer.getWidth();
        final int texHeight = _textureRenderer.getHeight();

        final FloatBuffer verts = BufferUtils.createVector3Buffer(((int) (texWidth / _vSpan) + 1) * 2);

        for (float x = _vSpan; x <= texWidth + _vSpan; x += _vSpan) {
            verts.put(x).put(0).put(0);
            verts.put(x).put(texHeight).put(0);
        }

        _verticals = new Line("vert", verts, null, null, null);
        _verticals.getMeshData().setIndexMode(IndexMode.Lines);
        _verticals.getSceneHints().setRenderBucketType(RenderBucketType.Ortho);

        _verticals.setDefaultColor(getColorConfig(LineGrapher.Vertical, ConfigKeys.Color.name(), new ColorRGBA(
                ColorRGBA.RED)));
        _verticals.setLineWidth(getIntConfig(LineGrapher.Vertical, ConfigKeys.Width.name(), 1));
        _verticals.setStipplePattern(getShortConfig(LineGrapher.Vertical, ConfigKeys.Stipple.name(), (short) 0xFF00));
        _verticals.setAntialiased(getBooleanConfig(LineGrapher.Vertical, ConfigKeys.Antialias.name(), true));
    }

    class LineEntry {
        public List<Vector3> verts = new ArrayList<Vector3>();
        public int maxSamples;
        public double min = 0;
        public double max = 10;
        public boolean visited;
        public Point point;
        public Line line;

        public LineEntry(final int maxSamples, final StatType type) {
            this.maxSamples = maxSamples;

            point = new Point("p", BufferUtils.createVector3Buffer(maxSamples), null, null, null);
            point.getSceneHints().setRenderBucketType(RenderBucketType.Ortho);

            point.setDefaultColor(getColorConfig(type, ConfigKeys.PointColor.name(), new ColorRGBA(ColorRGBA.WHITE)));
            point.setPointSize(getIntConfig(type, ConfigKeys.PointSize.name(), 5));
            point.setAntialiased(getBooleanConfig(type, ConfigKeys.Antialias.name(), true));
            if (!getBooleanConfig(type, ConfigKeys.ShowPoints.name(), false)) {
                point.getSceneHints().setCullHint(CullHint.Always);
            }

            line = new Line("l", BufferUtils.createVector3Buffer(maxSamples), null, null, null);
            line.getSceneHints().setRenderBucketType(RenderBucketType.Ortho);
            line.getMeshData().setIndexMode(IndexMode.LineStrip);

            line.setDefaultColor(getColorConfig(type, ConfigKeys.Color.name(), new ColorRGBA(ColorRGBA.LIGHT_GRAY)));
            line.setLineWidth(getIntConfig(type, ConfigKeys.Width.name(), 3));
            line.setStipplePattern(getShortConfig(type, ConfigKeys.Stipple.name(), (short) 0xFFFF));
            line.setAntialiased(getBooleanConfig(type, ConfigKeys.Antialias.name(), true));
            if (!getBooleanConfig(type, ConfigKeys.ShowLines.name(), true)) {
                line.getSceneHints().setCullHint(CullHint.Always);
            }
        }
    }

    public Line updateLineKey(final StatType type, Line lineKey) {
        if (lineKey == null) {
            lineKey = new Line("lk", BufferUtils.createVector3Buffer(2), null, null, null);
            final FloatBuffer fb = BufferUtils.createFloatBuffer(new Vector3[] { new Vector3(0, 0, 0),
                    new Vector3(30, 0, 0) });
            fb.rewind();
            lineKey.getMeshData().setVertexBuffer(fb);
        }

        lineKey.getSceneHints().setRenderBucketType(RenderBucketType.Ortho);
        lineKey.getMeshData().setIndexMode(IndexMode.LineStrip);

        lineKey.setDefaultColor(getColorConfig(type, ConfigKeys.Color.name(), new ColorRGBA(ColorRGBA.LIGHT_GRAY)));
        lineKey.setLineWidth(getIntConfig(type, ConfigKeys.Width.name(), 3));
        lineKey.setStipplePattern(getShortConfig(type, ConfigKeys.Stipple.name(), (short) 0xFFFF));
        lineKey.setAntialiased(getBooleanConfig(type, ConfigKeys.Antialias.name(), true));
        if (!getBooleanConfig(type, ConfigKeys.ShowLines.name(), true)) {
            lineKey.getSceneHints().setCullHint(CullHint.Always);
        }

        return lineKey;
    }

    @Override
    public void reset() {
        synchronized (StatCollector.getHistorical()) {
            for (final Iterator<StatType> i = _entries.keySet().iterator(); i.hasNext();) {
                final LineEntry entry = _entries.get(i.next());
                entry.line.removeFromParent();
                entry.point.removeFromParent();
                i.remove();
            }
        }
    }
}
TOP

Related Classes of com.ardor3d.util.stat.graph.LineGrapher$LineEntry

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.