/*******************************************************************************
* Copyright 2016 Geoscience Australia
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package au.gov.ga.earthsci.worldwind.common.render;
import gov.nasa.worldwind.avlist.AVKey;
import gov.nasa.worldwind.geom.Position;
import gov.nasa.worldwind.geom.Vec4;
import gov.nasa.worldwind.layers.Layer;
import gov.nasa.worldwind.pick.PickedObject;
import gov.nasa.worldwind.render.DrawContext;
import gov.nasa.worldwind.render.markers.Marker;
import gov.nasa.worldwind.render.markers.MarkerAttributes;
import gov.nasa.worldwind.render.markers.MarkerRenderer;
import java.util.Iterator;
import javax.media.opengl.GL2;
/**
* {@link MarkerRenderer} that supports picking of subsurface markers.
*
* @author Michael de Hoog
*/
public class DeepPickingMarkerRenderer extends MarkerRenderer
{
private boolean oldDeepPicking;
private boolean drawImmediately;
private MarkerAttributes previousAttributes;
@Override
protected boolean intersectsFrustum(DrawContext dc, Vec4 point, double radius)
{
//use the same test for drawing and picking (see superclass' method)
return dc.getView().getFrustumInModelCoordinates().contains(point);
}
@Override
protected void begin(DrawContext dc)
{
if (dc.isPickingMode())
{
oldDeepPicking = dc.isDeepPickingEnabled();
dc.setDeepPickingEnabled(true);
}
super.begin(dc);
}
@Override
protected void end(DrawContext dc)
{
super.end(dc);
if (dc.isPickingMode())
{
dc.setDeepPickingEnabled(oldDeepPicking);
}
}
public boolean isDrawImmediately()
{
return drawImmediately;
}
public void setDrawImmediately(boolean drawImmediately)
{
this.drawImmediately = drawImmediately;
}
@Override
protected void draw(final DrawContext dc, Iterable<Marker> markers)
{
if (isDrawImmediately())
{
drawImmediately(dc, markers);
}
else
{
super.draw(dc, markers);
}
}
protected void drawImmediately(DrawContext dc, Iterable<Marker> markers)
{
Layer parentLayer = dc.getCurrentLayer();
try
{
begin(dc);
Iterator<Marker> markerIterator = markers.iterator();
for (int index = 0; markerIterator.hasNext(); index++)
{
Marker marker = markerIterator.next();
Position pos = marker.getPosition();
Vec4 point = this.computeSurfacePoint(dc, pos);
double radius = this.computeMarkerRadius(dc, point, marker);
if (!intersectsFrustum(dc, point, radius))
{
continue;
}
drawMarker(dc, index, marker, point, radius);
}
}
finally
{
end(dc);
if (dc.isPickingMode())
{
this.pickSupport.resolvePick(dc, dc.getPickPoint(), parentLayer); // Also clears the pick list.
}
}
}
/*
* Same as superclass' method (copied because private)
*/
private void drawMarker(DrawContext dc, int index, Marker marker, Vec4 point, double radius)
{
// This method is called from OrderedMarker's render and pick methods. We don't perform culling here, because
// the marker has already been culled against the appropriate frustum prior adding OrderedMarker to the draw
// context.
if (dc.isPickingMode())
{
java.awt.Color color = dc.getUniquePickColor();
int colorCode = color.getRGB();
PickedObject po = new PickedObject(colorCode, marker, marker.getPosition(), false);
po.setValue(AVKey.PICKED_OBJECT_ID, index);
if (this.isEnablePickSizeReturn())
{
po.setValue(AVKey.PICKED_OBJECT_SIZE, 2 * radius);
}
this.pickSupport.addPickableObject(po);
GL2 gl = dc.getGL().getGL2(); // GL initialization checks for GL2 compatibility.
gl.glColor3ub((byte) color.getRed(), (byte) color.getGreen(), (byte) color.getBlue());
}
MarkerAttributes attrs = marker.getAttributes();
if (attrs != this.previousAttributes) // equality is intentional to avoid constant equals() calls
{
attrs.apply(dc);
this.previousAttributes = attrs;
}
marker.render(dc, point, radius);
}
}