WorldWind Java

时间:2017-10-05 20:23:16

标签: java jogl worldwind

我正在尝试在NASA Worldwind for Java中实现我自己的混乱过滤器,这会产生一个奇怪的问题 - 杂乱的过滤器还没有做太多的事情,但是当我通过它时我会用它来移动东西“闪烁”问题。无论何时移动鼠标,GlobeAnnotation可渲染都会闪烁。当我将杂波滤波器设置为空时,似乎不会发生闪烁。

这是一个显示我的意思的GIF:https://media.giphy.com/media/xT9IgFiZwYZ3VJHQU8/giphy.gif

我从这里克隆了NASA世界代码:https://github.com/NASAWorldWind/WorldWindJava。我做了一些改动,让事情适合我的最终过滤器。需要注意的是,我希望GlobeAnnotations显示为Always On Top of everything。

如何使GlobeAnnotations不会相互争斗并闪烁,但仍然会出现在其他所有内容之上 - 同时打开Clutter Filter?

请注意,以下代码只是我放在一起的示例,以显示我在“真实”应用程序中看到的问题。我希望GlobeAnnotations始终处于其他一切之上 - 但不要互相闪烁和争斗。

这是我的测试驱动程序:

package gov.nasa.worldwindx.examples;

import java.awt.Color;

import gov.nasa.worldwind.geom.LatLon;
import gov.nasa.worldwind.geom.Position;
import gov.nasa.worldwind.layers.AnnotationLayer;
import gov.nasa.worldwind.layers.RenderableLayer;
import gov.nasa.worldwind.render.GlobeAnnotation;
import gov.nasa.worldwind.render.Material;
import gov.nasa.worldwind.render.airspaces.CappedCylinder;

public class FlashyAnnotations extends ApplicationTemplate {
    @SuppressWarnings("unchecked")
    private static class AppFrame extends ApplicationTemplate.AppFrame {

        private AnnotationLayer layer;

        public AppFrame() {

            this.getWwd().getSceneController().setClutterFilter(new SimpleClutterFilter());

            CappedCylinder cappedCyl = new CappedCylinder(LatLon.fromDegrees(27, -100), 3000000);
            cappedCyl.getAttributes().setDrawInterior(true);
            cappedCyl.getAttributes().setInteriorMaterial(Material.GREEN);
            cappedCyl.getAttributes().setInteriorOpacity(.75f);
            cappedCyl.setAltitudes(10, 100000);
            RenderableLayer renderLayer = new RenderableLayer();

            renderLayer.addRenderable(cappedCyl);
            insertBeforeCompass(this.getWwd(), renderLayer);

            // Create example annotations
            this.setupAnnotations();

        }

        private void setupAnnotations() {

            // Create an AnnotationLayer with lots of annotations
            this.layer = new AnnotationLayer();

            GlobeAnnotation ga = new GlobeAnnotation("Annotation", Position.fromDegrees(20, -100.9, 1000));
            ga.getAttributes().setTextColor(Color.white);
            ga.getAttributes().setBackgroundColor(Color.BLACK);
            ga.getAttributes().setOpacity(.75f);
            ga.setAlwaysOnTop(true);
            layer.addAnnotation(ga);

            ga = new GlobeAnnotation("Annotation", Position.fromDegrees(25, -100.9, 1000));
            ga.getAttributes().setTextColor(Color.white);
            ga.getAttributes().setBackgroundColor(Color.BLACK);
            ga.getAttributes().setOpacity(.75f);
            ga.setAlwaysOnTop(true);
            layer.addAnnotation(ga);

            // Add layer to the layer list and update the layer panel
            insertBeforeCompass(this.getWwd(), layer);
        }

    }

    public static void main(String[] args) {
        ApplicationTemplate.start("WorldWind Annotations", AppFrame.class);
    }
}

这是我的(基本上是无操作的)Clutter Filter:

package gov.nasa.worldwindx.examples;

import java.util.List;

import gov.nasa.worldwind.render.Declutterable;
import gov.nasa.worldwind.render.DrawContext;
import gov.nasa.worldwind.util.ClutterFilter;

public class SimpleClutterFilter implements ClutterFilter{

    @Override
    public void apply(DrawContext dc, List<Declutterable> shapes) {
        for(Declutterable shape: shapes) {
            dc.addOrderedRenderable(shape);
        }

    }

}

我还必须更新gov.nasa.worldwind.render.BasicAnnotationRenderer,让它创建的OrderedAnnotations实现Declutterable。 (这个内部类的唯一变化是添加isEnableDecluttering和getBounds):

public class OrderedAnnotation implements OrderedRenderable, Declutterable
{
protected Annotation annotation;


protected double eyeDistance;
protected Layer layer;

public OrderedAnnotation(Annotation annotation, double eyeDistance)
{
    this.annotation = annotation;
    this.eyeDistance = eyeDistance;
}

public OrderedAnnotation(Annotation annotation, Layer layer, double eyeDistance)
{
    this.annotation = annotation;
    this.eyeDistance = eyeDistance;
    this.layer = layer;
}

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

public void render(DrawContext dc)
{
    OGLStackHandler stackHandler = new OGLStackHandler();
    BasicAnnotationRenderer.this.beginDrawAnnotations(dc, stackHandler);
    try
    {
        this.doRender(dc, this);
        // Draw as many as we can in a batch to save ogl state switching.
        while (dc.peekOrderedRenderables() instanceof OrderedAnnotation)
        {
            OrderedAnnotation oa = (OrderedAnnotation) dc.pollOrderedRenderables();
            this.doRender(dc, oa);
        }
    }
    catch (WWRuntimeException e)
    {
        Logging.logger().log(Level.SEVERE, "generic.ExceptionWhileRenderingAnnotation", e);
    }
    catch (Exception e)
    {
        Logging.logger().log(Level.SEVERE, "generic.ExceptionWhileRenderingAnnotation", e);
    }
    finally
    {
        BasicAnnotationRenderer.this.endDrawAnnotations(dc, stackHandler);
    }
}

public void pick(DrawContext dc, java.awt.Point pickPoint)
{
    OGLStackHandler stackHandler = new OGLStackHandler();
    BasicAnnotationRenderer.this.pickSupport.clearPickList();
    BasicAnnotationRenderer.this.beginDrawAnnotations(dc, stackHandler);
    try
    {
        this.annotation.setPickSupport(BasicAnnotationRenderer.this.pickSupport);
        this.doRender(dc, this);
        // Draw as many as we can in a batch to save ogl state switching.
        while (dc.peekOrderedRenderables() instanceof OrderedAnnotation)
        {
            OrderedAnnotation oa = (OrderedAnnotation) dc.pollOrderedRenderables();
            oa.annotation.setPickSupport(BasicAnnotationRenderer.this.pickSupport);
            this.doRender(dc, oa);
        }
    }
    catch (WWRuntimeException e)
    {
        Logging.logger().log(Level.SEVERE, "generic.ExceptionWhilePickingAnnotation", e);
    }
    catch (Exception e)
    {
        Logging.logger().log(Level.SEVERE, "generic.ExceptionWhilePickingAnnotation", e);
    }
    finally
    {
        BasicAnnotationRenderer.this.endDrawAnnotations(dc, stackHandler);
        BasicAnnotationRenderer.this.pickSupport.resolvePick(dc, pickPoint, this.layer);
        BasicAnnotationRenderer.this.pickSupport.clearPickList(); // to ensure entries can be garbage collected
    }
}

protected void doRender(DrawContext dc, OrderedAnnotation oa)
{
    // Swap the draw context's current layer with that of the ordered annotation
    Layer previousCurrentLayer = dc.getCurrentLayer();
    try
    {
        dc.setCurrentLayer(oa.layer);
        oa.annotation.renderNow(dc);
    }
    finally
    {
        dc.setCurrentLayer(previousCurrentLayer); // restore the original layer
    }
}

@Override
public boolean isEnableDecluttering() {
    return (annotation instanceof GlobeAnnotation);
}

@Override
public Rectangle2D getBounds(DrawContext dc) {
    if(annotation instanceof GlobeAnnotation) {
        return ((GlobeAnnotation) annotation).computeBounds(dc);
    }
    return null;
}

}

1 个答案:

答案 0 :(得分:1)

首先;

Draw order of PointPlacemarks

https://forum.worldwindcentral.com/forum/world-wind-java-forums/development-help/13263-layer-priority-order

setupAnnotations方法中,将GlobeOnTop对象的alwaysOnTop设置为true。这可能是原因。

private void setupAnnotations() {

            // Create an AnnotationLayer with lots of annotations
            this.layer = new AnnotationLayer();

            GlobeAnnotation ga = new GlobeAnnotation("Annotation", Position.fromDegrees(20, -100.9, 1000));
            ga.getAttributes().setTextColor(Color.white);
            ga.getAttributes().setBackgroundColor(Color.BLACK);
            ga.getAttributes().setOpacity(.75f);
            **ga.setAlwaysOnTop(true);**
            layer.addAnnotation(ga);

            ga = new GlobeAnnotation("Annotation", Position.fromDegrees(25, -100.9, 1000));
            ga.getAttributes().setTextColor(Color.white);
            ga.getAttributes().setBackgroundColor(Color.BLACK);
            ga.getAttributes().setOpacity(.75f);
            **ga.setAlwaysOnTop(true);**
            layer.addAnnotation(ga);

            // Add layer to the layer list and update the layer panel
            insertBeforeCompass(this.getWwd(), layer);
        }

除此之外,使用上面的链接可以解决您希望始终位于单独层中的注释以及将剩余注释放在另一层中的注释。