/*
Copyright (C) 2001, 2006 United States Government
as represented by the Administrator of the
National Aeronautics and Space Administration.
All Rights Reserved.
*/
package gov.nasa.worldwind.render;
import gov.nasa.worldwind.geom.*;
import gov.nasa.worldwind.tracks.TrackPoint;
import gov.nasa.worldwind.layers.Layer;
import gov.nasa.worldwind.Disposable;
import gov.nasa.worldwind.pick.*;
import javax.media.opengl.glu.*;
import javax.media.opengl.*;
import java.util.Iterator;
/**
* @author tag
* @version $Id: LocationRenderer.java 4513 2008-02-16 05:50:01Z tgaskins $
*/
public abstract class LocationRenderer implements Disposable
{
protected int lowerLimit = 0;
protected int upperLimit = Integer.MAX_VALUE;
protected final Shape SPHERE = new Sphere();
protected final Shape CONE = new Cone();
protected final Shape CYLINDER = new Cylinder();
protected PickSupport pickSupport = new PickSupport();
private double elevation = 10d;
private boolean overrideMarkerElevation = false;
private Object client;
public void dispose()
{
this.CONE.dispose();
this.CYLINDER.dispose();
this.SPHERE.dispose();
}
public int getLowerLimit()
{
return this.lowerLimit;
}
public void setLowerLimit(int lowerLimit)
{
this.lowerLimit = lowerLimit;
}
public int getUpperLimit()
{
return this.upperLimit;
}
public void setUpperLimit(int upperLimit)
{
this.upperLimit = upperLimit;
}
public double getElevation()
{
return elevation;
}
public void setElevation(double elevation)
{
this.elevation = elevation;
}
public boolean isOverrideElevation()
{
return overrideMarkerElevation;
}
public Object getClient()
{
return client;
}
public void setClient(Object client)
{
this.client = client;
}
public void setOverrideElevation(boolean overrideMarkerElevation)
{
this.overrideMarkerElevation = overrideMarkerElevation;
}
protected Vec4 computeSurfacePoint(DrawContext dc, TrackPoint tp)
{
Position pos = tp.getPosition();
if (!this.overrideMarkerElevation)
return dc.getGlobe().computePointFromPosition(pos);
// Compute points that are at the track-specified elevation
Vec4 point = dc.getSurfaceGeometry().getSurfacePoint(pos.getLatitude(), pos.getLongitude(), this.elevation);
if (point != null)
return point;
// Point is outside the current sector geometry, so compute it from the globe.
return dc.getGlobe().computePointFromPosition(pos.getLatitude(), pos.getLongitude(), this.elevation);
}
protected void begin(DrawContext dc)
{
GL gl = dc.getGL();
Vec4 cameraPosition = dc.getView().getEyePoint();
if (dc.isPickingMode())
{
this.pickSupport.beginPicking(dc);
gl.glPushAttrib(GL.GL_ENABLE_BIT | GL.GL_CURRENT_BIT | GL.GL_TRANSFORM_BIT);
gl.glDisable(GL.GL_TEXTURE_2D);
gl.glDisable(GL.GL_COLOR_MATERIAL);
}
else
{
gl.glPushAttrib(
GL.GL_TEXTURE_BIT | GL.GL_ENABLE_BIT | GL.GL_CURRENT_BIT | GL.GL_LIGHTING_BIT | GL.GL_TRANSFORM_BIT);
gl.glDisable(GL.GL_TEXTURE_2D);
float[] lightPosition =
{(float) (cameraPosition.x * 2), (float) (cameraPosition.y / 2), (float) (cameraPosition.z), 0.0f};
float[] lightDiffuse = {1.0f, 1.0f, 1.0f, 1.0f};
float[] lightAmbient = {1.0f, 1.0f, 1.0f, 1.0f};
float[] lightSpecular = {1.0f, 1.0f, 1.0f, 1.0f};
gl.glDisable(GL.GL_COLOR_MATERIAL);
gl.glLightfv(GL.GL_LIGHT1, GL.GL_POSITION, lightPosition, 0);
gl.glLightfv(GL.GL_LIGHT1, GL.GL_DIFFUSE, lightDiffuse, 0);
gl.glLightfv(GL.GL_LIGHT1, GL.GL_AMBIENT, lightAmbient, 0);
gl.glLightfv(GL.GL_LIGHT1, GL.GL_SPECULAR, lightSpecular, 0);
gl.glDisable(GL.GL_LIGHT0);
gl.glEnable(GL.GL_LIGHT1);
gl.glEnable(GL.GL_LIGHTING);
gl.glEnable(GL.GL_NORMALIZE);
}
gl.glMatrixMode(GL.GL_MODELVIEW);
gl.glPushMatrix();
}
protected void end(DrawContext dc)
{
GL gl = dc.getGL();
gl.glMatrixMode(GL.GL_MODELVIEW);
gl.glPopMatrix();
if (dc.isPickingMode())
{
this.pickSupport.endPicking(dc);
}
else
{
gl.glDisable(GL.GL_LIGHT1);
gl.glEnable(GL.GL_LIGHT0);
gl.glDisable(GL.GL_LIGHTING);
gl.glDisable(GL.GL_NORMALIZE);
}
gl.glPopAttrib();
}
public Vec4 pick(DrawContext dc, Iterator<TrackPoint> trackPositions, java.awt.Point pickPoint, Layer layer)
{
this.pickSupport.clearPickList();
Vec4 lastPointDrawn = this.draw(dc, trackPositions);
this.pickSupport.resolvePick(dc, pickPoint, layer);
this.pickSupport.clearPickList(); // to ensure entries can be garbage collected
return lastPointDrawn;
}
public Vec4 render(DrawContext dc, Iterator<TrackPoint> trackPositions)
{
return this.draw(dc, trackPositions);
}
protected abstract Vec4 draw(DrawContext dc, Iterator<TrackPoint> trackPositions);
protected static abstract class Shape
{
protected String name;
protected int glListId;
protected GLUquadric quadric;
protected boolean isInitialized = false;
abstract protected void doRender(DrawContext dc, Vec4 point, double radius);
protected void initialize(DrawContext dc)
{
this.glListId = dc.getGL().glGenLists(1);
this.quadric = dc.getGLU().gluNewQuadric();
dc.getGLU().gluQuadricDrawStyle(quadric, GLU.GLU_FILL);
dc.getGLU().gluQuadricNormals(quadric, GLU.GLU_SMOOTH);
dc.getGLU().gluQuadricOrientation(quadric, GLU.GLU_OUTSIDE);
dc.getGLU().gluQuadricTexture(quadric, false);
}
private void dispose()
{
if (this.isInitialized)
{
GLU glu = new GLU();
glu.gluDeleteQuadric(this.quadric);
this.isInitialized = false;
GLContext glc = GLContext.getCurrent();
if (glc == null)
return;
glc.getGL().glDeleteLists(this.glListId, 1);
this.glListId = -1;
}
}
protected void render(DrawContext dc, Vec4 point, double radius)
{
dc.getView().pushReferenceCenter(dc, point);
this.doRender(dc, point, radius);
dc.getView().popReferenceCenter(dc);
}
}
private static class Sphere extends Shape
{
protected void initialize(DrawContext dc)
{
super.initialize(dc);
this.name = "Sphere";
double radius = 1;
int slices = 36;
int stacks = 18;
dc.getGL().glNewList(this.glListId, GL.GL_COMPILE);
dc.getGLU().gluSphere(this.quadric, radius, slices, stacks);
dc.getGL().glEndList();
this.isInitialized = true;
}
protected void doRender(DrawContext dc, Vec4 point, double radius)
{
dc.getGL().glScaled(radius, radius, radius);
dc.getGL().glCallList(this.glListId);
}
}
private static class Cone extends Shape
{
protected void initialize(DrawContext dc)
{
super.initialize(dc);
this.name = "Cone";
int slices = 30;
int stacks = 30;
int loops = 2;
dc.getGL().glNewList(this.glListId, GL.GL_COMPILE);
dc.getGLU().gluQuadricOrientation(quadric, GLU.GLU_OUTSIDE);
dc.getGLU().gluCylinder(quadric, 1d, 0d, 2d, slices, (int) (2 * (Math.sqrt(stacks)) + 1));
dc.getGLU().gluDisk(quadric, 0d, 1d, slices, loops);
dc.getGL().glEndList();
this.isInitialized = true;
}
protected void doRender(DrawContext dc, Vec4 point, double size)
{
PolarPoint p = PolarPoint.fromCartesian(point);
dc.getGL().glScaled(size, size, size);
dc.getGL().glRotated(p.getLongitude().getDegrees(), 0, 1, 0);
dc.getGL().glRotated(Math.abs(p.getLatitude().getDegrees()), Math.signum(p.getLatitude().getDegrees()) * -1,
0, 0);
dc.getGL().glCallList(this.glListId);
}
}
protected static class Cylinder extends Shape
{
protected void initialize(DrawContext dc)
{
super.initialize(dc);
this.name = "Cylinder";
int slices = 30;
int stacks = 1;
int loops = 1;
dc.getGL().glNewList(this.glListId, GL.GL_COMPILE);
dc.getGLU().gluCylinder(quadric, 1d, 1d, 2d, slices, (int) (2 * (Math.sqrt(stacks)) + 1));
dc.getGLU().gluDisk(quadric, 0d, 1d, slices, loops);
dc.getGL().glTranslated(0, 0, 2);
dc.getGLU().gluDisk(quadric, 0d, 1d, slices, loops);
dc.getGL().glTranslated(0, 0, -2);
dc.getGL().glEndList();
this.isInitialized = true;
}
protected void doRender(DrawContext dc, Vec4 point, double size)
{
PolarPoint p = PolarPoint.fromCartesian(point);
dc.getGL().glScaled(size, size, size);
dc.getGL().glRotated(p.getLongitude().getDegrees(), 0, 1, 0);
dc.getGL().glRotated(Math.abs(p.getLatitude().getDegrees()), Math.signum(p.getLatitude().getDegrees()) * -1,
0, 0);
dc.getGL().glCallList(this.glListId);
}
}
}