All Downloads are FREE. Search and download functionalities are using the official Maven repository.

src.gov.nasa.worldwind.render.airspaces.AirspaceRenderer Maven / Gradle / Ivy

Go to download

World Wind is a collection of components that interactively display 3D geographic information within Java applications or applets.

There is a newer version: 2.0.0-986
Show newest version
/*
 * Copyright (C) 2012 United States Government as represented by the Administrator of the
 * National Aeronautics and Space Administration.
 * All Rights Reserved.
 */
package gov.nasa.worldwind.render.airspaces;

import gov.nasa.worldwind.Locatable;
import gov.nasa.worldwind.layers.Layer;
import gov.nasa.worldwind.pick.PickSupport;
import gov.nasa.worldwind.render.*;
import gov.nasa.worldwind.util.*;

import javax.media.opengl.*;
import java.awt.*;
import java.nio.Buffer;
import java.util.Iterator;

/**
 * @author dcollins
 * @version $Id: AirspaceRenderer.java 1847 2014-02-18 00:32:16Z dcollins $
 */
public class AirspaceRenderer
{
    private static final String EXT_BLEND_FUNC_SEPARATE_STRING = "GL_EXT_blend_func_separate";

    private boolean enableAntialiasing;
    private boolean enableBlending;
    private boolean enableDepthOffset;
    private boolean enableLighting;
    private boolean useEXTBlendFuncSeparate;
    private boolean haveEXTBlendFuncSeparate;
    private boolean drawExtents;
    private boolean drawWireframe;
    private final PickSupport pickSupport = new PickSupport();
    private double linePickWidth;
    private Double depthOffsetFactor; // Initially null, indicating the DrawContext's default is used.
    private Double depthOffsetUnits;  // Initially null, indicating the DrawContext's default is used.
    protected boolean enableBatchRendering = true;
    protected boolean enableBatchPicking = true;

    /** Implements the the interface used by the draw context's outlined-shape renderer. */
    protected OutlinedShape outlineShapeRenderer = new OutlinedShape()
    {
        public boolean isDrawOutline(DrawContext dc, Object shape)
        {
            return ((Airspace) shape).getAttributes().isDrawOutline();
        }

        public boolean isDrawInterior(DrawContext dc, Object shape)
        {
            return ((Airspace) shape).getAttributes().isDrawInterior();
        }

        public boolean isEnableDepthOffset(DrawContext dc, Object shape)
        {
            return AirspaceRenderer.this.isEnableDepthOffset();
        }

        public void drawOutline(DrawContext dc, Object shape)
        {
            AirspaceRenderer.this.drawAirspaceOutline(dc, (Airspace) shape);
        }

        public void drawInterior(DrawContext dc, Object shape)
        {
            AirspaceRenderer.this.drawAirspaceInterior(dc, (Airspace) shape);
        }

        public Double getDepthOffsetFactor(DrawContext dc, Object shape)
        {
            return AirspaceRenderer.this.getDepthOffsetFactor();
        }

        public Double getDepthOffsetUnits(DrawContext dc, Object shape)
        {
            return AirspaceRenderer.this.getDepthOffsetUnits();
        }
    };

    public AirspaceRenderer()
    {
        this.enableAntialiasing = false;
        this.enableBlending = true;
        this.enableDepthOffset = false;
        this.enableLighting = true;
        this.useEXTBlendFuncSeparate = true;
        this.haveEXTBlendFuncSeparate = false;
        this.drawExtents = false;
        this.drawWireframe = false;
        this.linePickWidth = 8.0;
    }

    public boolean isEnableAntialiasing()
    {
        return this.enableAntialiasing;
    }

    public void setEnableAntialiasing(boolean enable)
    {
        this.enableAntialiasing = enable;
    }

    public boolean isEnableBlending()
    {
        return this.enableBlending;
    }

    public void setEnableBlending(boolean enable)
    {
        this.enableBlending = enable;
    }

    public boolean isEnableDepthOffset()
    {
        return this.enableDepthOffset;
    }

    public void setEnableDepthOffset(boolean enable)
    {
        this.enableDepthOffset = enable;
    }

    public boolean isEnableLighting()
    {
        return this.enableLighting;
    }

    public void setEnableLighting(boolean enable)
    {
        this.enableLighting = enable;
    }

    public boolean isUseEXTBlendFuncSeparate()
    {
        return this.useEXTBlendFuncSeparate;
    }

    public void setUseEXTBlendFuncSeparate(boolean useEXTBlendFuncSeparate)
    {
        this.useEXTBlendFuncSeparate = useEXTBlendFuncSeparate;
    }

    protected boolean isHaveEXTBlendFuncSeparate()
    {
        return this.haveEXTBlendFuncSeparate;
    }

    protected void setHaveEXTBlendFuncSeparate(boolean haveEXTBlendFuncSeparate)
    {
        this.haveEXTBlendFuncSeparate = haveEXTBlendFuncSeparate;
    }

    public boolean isDrawExtents()
    {
        return this.drawExtents;
    }

    public void setDrawExtents(boolean draw)
    {
        this.drawExtents = draw;
    }

    public boolean isDrawWireframe()
    {
        return this.drawWireframe;
    }

    public void setDrawWireframe(boolean draw)
    {
        this.drawWireframe = draw;
    }

    public double getLinePickWidth()
    {
        return linePickWidth;
    }

    public void setLinePickWidth(double width)
    {
        if (width < 0.0)
        {
            String message = Logging.getMessage("generic.ArgumentOutOfRange", "width < 0");
            Logging.logger().severe(message);
            throw new IllegalArgumentException(message);
        }

        this.linePickWidth = width;
    }

    public Double getDepthOffsetFactor()
    {
        return this.depthOffsetFactor;
    }

    public void setDepthOffsetFactor(Double factor)
    {
        this.depthOffsetFactor = factor;
    }

    public Double getDepthOffsetUnits()
    {
        return depthOffsetUnits;
    }

    public void setDepthOffsetUnits(Double units)
    {
        this.depthOffsetUnits = units;
    }

    public PickSupport getPickSupport()
    {
        return this.pickSupport;
    }

    public boolean isEnableBatchRendering()
    {
        return enableBatchRendering;
    }

    public void setEnableBatchRendering(boolean enableBatchRendering)
    {
        this.enableBatchRendering = enableBatchRendering;
    }

    public boolean isEnableBatchPicking()
    {
        return enableBatchPicking;
    }

    public void setEnableBatchPicking(boolean enableBatchPicking)
    {
        this.enableBatchPicking = enableBatchPicking;
    }

    public void renderOrdered(DrawContext dc, Iterable airspaces)
    {
        if (dc == null)
        {
            String msg = Logging.getMessage("nullValue.DrawContextIsNull");
            Logging.logger().severe(msg);
            throw new IllegalArgumentException(msg);
        }

        if (airspaces == null)
        {
            String msg = Logging.getMessage("nullValue.AirspaceIterableIsNull");
            Logging.logger().severe(msg);
            throw new IllegalArgumentException(msg);
        }

        this.drawOrdered(dc, airspaces);
    }

    public void pickNow(DrawContext dc, Iterable airspaces, java.awt.Point pickPoint, Layer layer)
    {
        if (dc == null)
        {
            String msg = Logging.getMessage("nullValue.DrawContextIsNull");
            Logging.logger().severe(msg);
            throw new IllegalArgumentException(msg);
        }

        if (airspaces == null)
        {
            String msg = Logging.getMessage("nullValue.AirspaceIterableIsNull");
            Logging.logger().severe(msg);
            throw new IllegalArgumentException(msg);
        }

        PickSupport pickSupport = this.getPickSupport();
        pickSupport.clearPickList();
        pickSupport.beginPicking(dc);
        this.beginRendering(dc);
        try
        {
            // The pick method will bind pickable objects to the renderer's PickSupport.
            this.drawNow(dc, airspaces, pickSupport);
        }
        finally
        {
            this.endRendering(dc);
            pickSupport.endPicking(dc);
            pickSupport.resolvePick(dc, pickPoint, layer);
        }
    }

    public void renderNow(DrawContext dc, Iterable airspaces)
    {
        if (dc == null)
        {
            String msg = Logging.getMessage("nullValue.DrawContextIsNull");
            Logging.logger().severe(msg);
            throw new IllegalArgumentException(msg);
        }

        if (airspaces == null)
        {
            String msg = Logging.getMessage("nullValue.AirspaceIterableIsNull");
            Logging.logger().severe(msg);
            throw new IllegalArgumentException(msg);
        }

        this.beginRendering(dc);
        try
        {
            // The render method does not bind any pickable objects.
            this.drawNow(dc, airspaces, null);
        }
        finally
        {
            this.endRendering(dc);
        }
    }

    protected void drawOrdered(DrawContext dc, Iterable airspaces)
    {
        if (dc == null)
        {
            String msg = Logging.getMessage("nullValue.DrawContextIsNull");
            Logging.logger().severe(msg);
            throw new IllegalArgumentException(msg);
        }

        if (airspaces == null)
        {
            String msg = Logging.getMessage("nullValue.AirspaceIterableIsNull");
            Logging.logger().severe(msg);
            throw new IllegalArgumentException(msg);
        }

        for (Airspace airspace : airspaces)
        {
            if (!airspace.isVisible())
                continue;

            if (!airspace.isAirspaceVisible(dc))
                continue;

            airspace.makeOrderedRenderable(dc, this);
        }
    }

    protected void drawNow(DrawContext dc, Iterable airspaces, PickSupport pickSupport)
    {
        if (dc == null)
        {
            String msg = Logging.getMessage("nullValue.DrawContextIsNull");
            Logging.logger().severe(msg);
            throw new IllegalArgumentException(msg);
        }

        if (airspaces == null)
        {
            String msg = Logging.getMessage("nullValue.AirspaceIterableIsNull");
            Logging.logger().severe(msg);
            throw new IllegalArgumentException(msg);
        }

        for (Airspace airspace : airspaces)
        {
            if (airspace == null)
                continue;

            if (!airspace.isVisible())
                continue;

            if (!airspace.isAirspaceVisible(dc))
                continue;

            this.drawAirspace(dc, airspace, pickSupport);
        }
    }

    //**************************************************************//
    //********************  Ordered Airspaces  *********************//
    //**************************************************************//

    public OrderedRenderable createOrderedRenderable(DrawContext dc, Airspace airspace, double eyeDistance,
        Object pickedObject)
    {
        if (dc == null)
        {
            String msg = Logging.getMessage("nullValue.DrawContextIsNull");
            Logging.logger().severe(msg);
            throw new IllegalArgumentException(msg);
        }

        if (airspace == null)
        {
            String msg = Logging.getMessage("nullValue.AirspaceIsNull");
            Logging.logger().severe(msg);
            throw new IllegalArgumentException(msg);
        }

        return new OrderedAirspace(this, airspace, dc.getCurrentLayer(), eyeDistance, pickedObject);
    }

    protected static class OrderedAirspace implements OrderedRenderable
    {
        protected AirspaceRenderer renderer;
        protected Airspace airspace;
        protected Layer layer;
        protected double eyeDistance;
        protected Object pickedObject;

        public OrderedAirspace(AirspaceRenderer renderer, Airspace airspace, Layer layer, double eyeDistance,
            Object pickedObject)
        {
            if (renderer == null)
            {
                String msg = Logging.getMessage("nullValue.RendererIsNull");
                Logging.logger().severe(msg);
                throw new IllegalArgumentException(msg);
            }

            if (airspace == null)
            {
                String msg = Logging.getMessage("nullValue.AirspaceIsNull");
                Logging.logger().severe(msg);
                throw new IllegalArgumentException(msg);
            }

            this.renderer = renderer;
            this.airspace = airspace;
            this.layer = layer;
            this.eyeDistance = eyeDistance;
            this.pickedObject = pickedObject;
        }

        public AirspaceRenderer getRenderer()
        {
            return this.renderer;
        }

        public Airspace getAirspace()
        {
            return this.airspace;
        }

        public Layer getLayer()
        {
            return this.layer;
        }

        public double getDistanceFromEye()
        {
            return this.eyeDistance;
        }

        public Object getPickedObject()
        {
            return this.pickedObject;
        }

        public void render(DrawContext dc)
        {
            if (dc == null)
            {
                String msg = Logging.getMessage("nullValue.DrawContextIsNull");
                Logging.logger().severe(msg);
                throw new IllegalArgumentException(msg);
            }

            // The render method does not bind any pickable objects.
            this.draw(dc, null);
        }

        public void pick(DrawContext dc, Point pickPoint)
        {
            if (dc == null)
            {
                String msg = Logging.getMessage("nullValue.DrawContextIsNull");
                Logging.logger().severe(msg);
                throw new IllegalArgumentException(msg);
            }

            PickSupport pickSupport = this.getRenderer().getPickSupport();
            pickSupport.clearPickList();
            try
            {
                pickSupport.beginPicking(dc);
                // The pick method will bind pickable objects to the renderer's PickSupport.
                this.draw(dc, pickSupport);
            }
            finally
            {
                pickSupport.endPicking(dc);
                pickSupport.resolvePick(dc, pickPoint, this.getLayer());
            }
        }

        protected void draw(DrawContext dc, PickSupport pickSupport)
        {
            AirspaceRenderer renderer = this.getRenderer();
            renderer.drawOrderedAirspace(dc, this, pickSupport);
        }
    }

    protected void drawOrderedAirspace(DrawContext dc, OrderedAirspace oa, PickSupport pickSupport)
    {
        if (dc == null)
        {
            String msg = Logging.getMessage("nullValue.DrawContextIsNull");
            Logging.logger().severe(msg);
            throw new IllegalArgumentException(msg);
        }

        if (oa == null)
        {
            String msg = Logging.getMessage("nullValue.OrderedAirspace");
            Logging.logger().severe(msg);
            throw new IllegalArgumentException(msg);
        }

        this.beginRendering(dc);
        try
        {
            this.drawAirspace(dc, oa.getAirspace(), oa.getPickedObject(), pickSupport);
            this.drawOrderedAirspaces(dc, pickSupport);
        }
        finally
        {
            this.endRendering(dc);
        }
    }

    protected void drawOrderedAirspaces(DrawContext dc, PickSupport pickSupport)
    {
        if (dc == null)
        {
            String msg = Logging.getMessage("nullValue.DrawContextIsNull");
            Logging.logger().severe(msg);
            throw new IllegalArgumentException(msg);
        }

        if (!this.isEnableBatchRendering())
            return;

        if (dc.isPickingMode() && !this.isEnableBatchPicking())
            return;

        // Batch render as many Airspaces as we can to save OpenGL state switching.
        OrderedRenderable top = dc.peekOrderedRenderables();
        while (top != null && top instanceof OrderedAirspace)
        {
            OrderedAirspace oa = (OrderedAirspace) top;

            // If the next OrderedAirspace's renderer is different, then we must stop batching. Otherwise, we would
            // render an airspace with a renderer with potentially different properties or behavior.
            if (this != oa.getRenderer())
                return;

            this.drawAirspace(dc, oa.getAirspace(), oa.getPickedObject(), pickSupport);

            // Take the ordered airspace off the queue, then peek at the next item in the queue (but do not remove it).
            dc.pollOrderedRenderables();
            top = dc.peekOrderedRenderables();
        }
    }

    //**************************************************************//
    //********************  Airspace Rendering  ********************//
    //**************************************************************//

    protected void drawAirspace(DrawContext dc, Airspace airspace, PickSupport pickSupport)
    {
        this.drawAirspace(dc, airspace, airspace, pickSupport); // Use the airspace as the picked object.
    }

    protected void drawAirspace(DrawContext dc, Airspace airspace, Object pickedObject, PickSupport pickSupport)
    {
        if (dc == null)
        {
            String message = Logging.getMessage("nullValue.DrawContextIsNull");
            Logging.logger().severe(message);
            throw new IllegalArgumentException(message);
        }

        if (airspace == null)
        {
            String message = Logging.getMessage("nullValue.AirspaceIsNull");
            Logging.logger().severe(message);
            throw new IllegalArgumentException(message);
        }

        try
        {
            if (pickSupport != null)
            {
                this.bindPickableObject(dc, pickedObject, pickSupport);
            }

            this.doDrawAirspace(dc, airspace);
        }
        catch (Exception e)
        {
            String message = Logging.getMessage("generic.ExceptionWhileRenderingAirspace");
            Logging.logger().log(java.util.logging.Level.SEVERE, message, e);
        }
    }

    protected void doDrawAirspace(DrawContext dc, Airspace airspace)
    {
        dc.drawOutlinedShape(this.outlineShapeRenderer, airspace);

        if (!dc.isPickingMode())
        {
            if (this.isDrawExtents())
                airspace.renderExtent(dc);
        }
    }

    protected void drawAirspaceInterior(DrawContext dc, Airspace airspace)
    {
        if (!dc.isPickingMode())
        {
            airspace.getAttributes().applyInterior(dc, this.isEnableLighting());
        }

        airspace.renderGeometry(dc, Airspace.DRAW_STYLE_FILL);
    }

    protected void drawAirspaceOutline(DrawContext dc, Airspace airspace)
    {
        int[] lightEnabledState = new int[1];

        if (dc.isPickingMode())
        {
            double lineWidth = airspace.getAttributes().getOutlineWidth();

            // If the airspace interior isn't drawn, make the outline wider during picking.
            if (!airspace.getAttributes().isDrawInterior())
            {
                if (lineWidth != 0.0)
                    lineWidth += this.getLinePickWidth();
            }

            dc.getGL().glLineWidth((float) lineWidth);
        }
        else
        {
            if (this.isEnableLighting())
            {
                dc.getGL().glGetIntegerv(GL2.GL_LIGHTING, lightEnabledState, 0);
                if (lightEnabledState[0] == GL.GL_TRUE)
                    dc.getGL().glDisable(GL2.GL_LIGHTING);
            }

            airspace.getAttributes().applyOutline(dc, false);
        }

        airspace.renderGeometry(dc, Airspace.DRAW_STYLE_OUTLINE);

        if (!dc.isPickingMode() && this.isEnableLighting() && lightEnabledState[0] == GL.GL_TRUE)
        {
            dc.getGL().glEnable(GL2.GL_LIGHTING);
        }
    }

    protected void beginRendering(DrawContext dc)
    {
        GL2 gl = dc.getGL().getGL2(); // GL initialization checks for GL2 compatibility.

        gl.glEnableClientState(GL2.GL_VERTEX_ARRAY);

        if (!dc.isPickingMode())
        {
            int attribMask =
                GL2.GL_COLOR_BUFFER_BIT
                    // For color write mask. If blending is enabled: for blending src and func, and alpha func.
                    | GL2.GL_CURRENT_BIT // For current color.
                    | GL2.GL_LINE_BIT // For line width, line smoothing.
                    | GL2.GL_POLYGON_BIT // For polygon mode, polygon offset.
                    | GL2.GL_TRANSFORM_BIT; // For matrix mode.
            gl.glPushAttrib(attribMask);

            if (this.isDrawWireframe())
                gl.glPolygonMode(GL2.GL_FRONT_AND_BACK, GL2.GL_LINE);

            if (this.isEnableBlending())
                this.setBlending(dc);

            if (this.isEnableLighting())
            {
                gl.glEnableClientState(GL2.GL_NORMAL_ARRAY);
                dc.beginStandardLighting();
            }

            if (this.isEnableAntialiasing())
                gl.glEnable(GL.GL_LINE_SMOOTH);
        }
        else
        {
            int attribMask =
                GL2.GL_CURRENT_BIT // For current color.
//                    | GL2.GL_DEPTH_BUFFER_BIT // For depth test and depth func.
                    | GL2.GL_LINE_BIT; // For line width.
            gl.glPushAttrib(attribMask);
        }
    }

    protected void endRendering(DrawContext dc)
    {
        GL2 gl = dc.getGL().getGL2(); // GL initialization checks for GL2 compatibility.

        gl.glDisableClientState(GL2.GL_VERTEX_ARRAY);

        if (!dc.isPickingMode() && this.isEnableLighting())
        {
            gl.glDisableClientState(GL2.GL_NORMAL_ARRAY);
            dc.endStandardLighting();
        }

        gl.glPopAttrib();
    }

    protected void bindPickableObject(DrawContext dc, Object pickedObject, PickSupport pickSupport)
    {
        java.awt.Color pickColor = dc.getUniquePickColor();
        GL2 gl = dc.getGL().getGL2(); // GL initialization checks for GL2 compatibility.
        gl.glColor3ub((byte) pickColor.getRed(), (byte) pickColor.getGreen(), (byte) pickColor.getBlue());

        if (pickedObject instanceof Locatable)
        {
            pickSupport.addPickableObject(pickColor.getRGB(), pickedObject, ((Locatable) pickedObject).getPosition());
        }
        else
        {
            pickSupport.addPickableObject(pickColor.getRGB(), pickedObject);
        }
    }

    //**************************************************************//
    //********************  Geometry Rendering  ********************//
    //**************************************************************//

    public void drawGeometry(DrawContext dc, int mode, int count, int type, Buffer elementBuffer, Geometry geom)
    {
        if (dc == null)
        {
            String message = Logging.getMessage("nullValue.DrawContextIsNull");
            Logging.logger().severe(message);
            throw new IllegalArgumentException(message);
        }
        if (elementBuffer == null)
        {
            String message = "nullValue.ElementBufferIsNull";
            Logging.logger().severe(message);
            throw new IllegalArgumentException(message);
        }
        if (geom == null)
        {
            String message = "nullValue.AirspaceGeometryIsNull";
            Logging.logger().severe(message);
            throw new IllegalArgumentException(message);
        }
        if (geom.getBuffer(Geometry.VERTEX) == null)
        {
            String message = "nullValue.VertexBufferIsNull";
            Logging.logger().severe(message);
            throw new IllegalArgumentException(message);
        }

        GL2 gl = dc.getGL().getGL2(); // GL initialization checks for GL2 compatibility.

        int minElementIndex, maxElementIndex;
        int size, glType, stride;
        Buffer vertexBuffer, normalBuffer;

        size = geom.getSize(Geometry.VERTEX);
        glType = geom.getGLType(Geometry.VERTEX);
        stride = geom.getStride(Geometry.VERTEX);
        vertexBuffer = geom.getBuffer(Geometry.VERTEX);
        gl.glVertexPointer(size, glType, stride, vertexBuffer);

        normalBuffer = null;
        if (!dc.isPickingMode())
        {
            if (this.isEnableLighting())
            {
                normalBuffer = geom.getBuffer(Geometry.NORMAL);
                if (normalBuffer == null)
                {
                    gl.glDisableClientState(GL2.GL_NORMAL_ARRAY);
                }
                else
                {
                    glType = geom.getGLType(Geometry.NORMAL);
                    stride = geom.getStride(Geometry.NORMAL);
                    gl.glNormalPointer(glType, stride, normalBuffer);
                }
            }
        }

        // On some hardware, using glDrawRangeElements allows vertex data to be prefetched. We know the minimum and
        // maximum index values that are valid in elementBuffer (they are 0 and vertexCount-1), so it's harmless
        // to use this approach and allow the hardware to optimize.
        minElementIndex = 0;
        maxElementIndex = geom.getCount(Geometry.VERTEX) - 1;
        gl.glDrawRangeElements(mode, minElementIndex, maxElementIndex, count, type, elementBuffer);

        if (!dc.isPickingMode())
        {
            if (this.isEnableLighting())
            {
                if (normalBuffer == null)
                    gl.glEnableClientState(GL2.GL_NORMAL_ARRAY);
            }
            this.logGeometryStatistics(dc, geom);
        }
    }

    public void drawGeometry(DrawContext dc, Geometry geom)
    {
        if (dc == null)
        {
            String message = Logging.getMessage("nullValue.DrawContextIsNull");
            Logging.logger().severe(message);
            throw new IllegalArgumentException(message);
        }
        if (geom == null)
        {
            String message = "nullValue.AirspaceGeometryIsNull";
            Logging.logger().severe(message);
            throw new IllegalArgumentException(message);
        }
        if (geom.getBuffer(Geometry.ELEMENT) == null)
        {
            String message = "nullValue.ElementBufferIsNull";
            Logging.logger().severe(message);
            throw new IllegalArgumentException(message);
        }

        int mode, count, type;
        Buffer elementBuffer;

        mode = geom.getMode(Geometry.ELEMENT);
        count = geom.getCount(Geometry.ELEMENT);
        type = geom.getGLType(Geometry.ELEMENT);
        elementBuffer = geom.getBuffer(Geometry.ELEMENT);

        this.drawGeometry(dc, mode, count, type, elementBuffer, geom);
    }

    public void drawGeometry(DrawContext dc, Geometry elementGeom, Geometry vertexGeom)
    {
        if (dc == null)
        {
            String message = Logging.getMessage("nullValue.DrawContextIsNull");
            Logging.logger().severe(message);
            throw new IllegalArgumentException(message);
        }
        if (elementGeom == null)
        {
            String message = "nullValue.ElementGeometryIsNull";
            Logging.logger().severe(message);
            throw new IllegalArgumentException(message);
        }
        if (elementGeom.getBuffer(Geometry.ELEMENT) == null)
        {
            String message = "nullValue.ElementBufferIsNull";
            Logging.logger().severe(message);
            throw new IllegalArgumentException(message);
        }
        if (vertexGeom == null)
        {
            String message = "nullValue.VertexGeometryIsNull";
            Logging.logger().severe(message);
            throw new IllegalArgumentException(message);
        }

        int mode, count, type;
        Buffer elementBuffer;

        mode = elementGeom.getMode(Geometry.ELEMENT);
        count = elementGeom.getCount(Geometry.ELEMENT);
        type = elementGeom.getGLType(Geometry.ELEMENT);
        elementBuffer = elementGeom.getBuffer(Geometry.ELEMENT);

        this.drawGeometry(dc, mode, count, type, elementBuffer, vertexGeom);
    }

    //**************************************************************//
    //********************  Rendering Support  *********************//
    //**************************************************************//

    public void setBlending(DrawContext dc)
    {
        if (dc == null)
        {
            String message = Logging.getMessage("nullValue.DrawContextIsNull");
            Logging.logger().severe(message);
            throw new IllegalStateException(message);
        }
        if (dc.getGL() == null)
        {
            String message = Logging.getMessage("nullValue.DrawingContextGLIsNull");
            Logging.logger().severe(message);
            throw new IllegalStateException(message);
        }

        GL2 gl = dc.getGL().getGL2(); // GL initialization checks for GL2 compatibility.

        if (this.isUseEXTBlendFuncSeparate())
            this.setHaveEXTBlendFuncSeparate(gl.isExtensionAvailable(EXT_BLEND_FUNC_SEPARATE_STRING));

        gl.glEnable(GL2.GL_ALPHA_TEST);
        gl.glAlphaFunc(GL2.GL_GREATER, 0.0f);

        gl.glEnable(GL.GL_BLEND);
        // The separate blend function correctly handles regular (non-premultiplied) colors. We want
        //     Cd = Cs*As + Cf*(1-As)
        //     Ad = As    + Af*(1-As)
        // So we use GL_EXT_blend_func_separate to specify different blending factors for source color and source
        // alpha.
        if (this.isUseEXTBlendFuncSeparate() && this.isHaveEXTBlendFuncSeparate())
        {
            gl.glBlendFuncSeparate(
                GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA,             // rgb   blending factors
                GL.GL_ONE, GL.GL_ONE_MINUS_SRC_ALPHA);                  // alpha blending factors
        }
        // Fallback to a single blending factor for source color and source alpha. The destination alpha will be
        // incorrect.
        else
        {
            gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA); // rgba  blending factors
        }
    }

    protected void logGeometryStatistics(DrawContext dc, Geometry geom)
    {
        if (dc == null)
        {
            String message = Logging.getMessage("nullValue.DrawContextIsNull");
            Logging.logger().severe(message);
            throw new IllegalArgumentException(message);
        }
        if (geom == null)
        {
            String message = Logging.getMessage("nullValue.GeometryIsNull");
            Logging.logger().severe(message);
            throw new IllegalArgumentException(message);
        }

        int geomCount = 0;
        int vertexCount = 0;

        Iterator iter = dc.getPerFrameStatistics().iterator();
        while (iter.hasNext())
        {
            PerformanceStatistic stat = iter.next();
            if (PerformanceStatistic.AIRSPACE_GEOMETRY_COUNT.equals(stat.getKey()))
            {
                geomCount += (Integer) stat.getValue();
                iter.remove();
            }
            if (PerformanceStatistic.AIRSPACE_VERTEX_COUNT.equals(stat.getKey()))
            {
                vertexCount += (Integer) stat.getValue();
                iter.remove();
            }
        }

        geomCount += 1;
        vertexCount += geom.getCount(Geometry.VERTEX);
        dc.setPerFrameStatistic(PerformanceStatistic.AIRSPACE_GEOMETRY_COUNT, "Airspace Geometry Count", geomCount);
        dc.setPerFrameStatistic(PerformanceStatistic.AIRSPACE_VERTEX_COUNT, "Airspace Vertex Count", vertexCount);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy