WorldWind Java中的闪烁注释
我试图在美国宇航局的Worldwind中实现自己的杂波滤波器,它引起了一个奇怪的问题 - 杂波滤波器还没有做很多,但我会用它来移动东西当我通过了“闪烁”的问题。每当鼠标移动时,GlobeAnnotation渲染器都会闪烁。当我将杂波滤镜设置为空时,闪烁似乎不会发生。WorldWind Java中的闪烁注释
这里是一个GIF图片,展示了我的意思:https://media.giphy.com/media/xT9IgFiZwYZ3VJHQU8/giphy.gif
我从这里克隆NASA世界风代码:https://github.com/NASAWorldWind/WorldWindJava。我做了一些改变,使我的最终过滤器的工作。需要注意的是,我希望GlobeAnnotations显示为始终位于其他位置之上。
我该如何让GlobeAnnotations不会互相争斗并且闪烁,但仍然会出现在其他任何事物的顶部 - 同时开启杂波滤波器?
请注意,以下代码仅仅是一个示例,我将它们放在一起以显示我在“真实”应用程序中看到的问题。我希望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);
}
}
这里是我的(基本上没有-OP)杂波滤除:
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;
}
}
首先;
在setupAnnotations
方法,设置alwaysOnTop两个GlobeAnnotation对象为真。这可能是原因。
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);
}
取而代之的是,将要始终在最前面成单独的层和其余的到另一个层可以通过使用上面的链接是解决方案的注释。
我希望它们都是真实的 - 因为我希望注释能够在其他任何东西之上 - 但不会互相争斗。这只是我放在一起展示问题的一个例子。我会在我的帖子中澄清。 – systemoutprintln
有一个'顶部',所以在这两个GlobeAnnotation之间竞速,并且由于闪烁的发生对我来说是预期的行为。 –
是的,这可能是正确的 - 但为什么当Clutter Filter设置为null时不会发生? – systemoutprintln
看起来像z缓冲渲染闪烁,这发生在多个对象呈现与摄像机相同的距离时。难道你不能手动设置距离(高度边际差异),以摆脱这一点? – Caramiriel
我认为既然我想“永远在上面”设置,眼睛的距离可能会被worldwind逻辑忽略? – systemoutprintln