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

osm.map.worldwind.gl.GLRenderable Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (C) 2017 United States Government as represented by the Administrator of the
 * National Aeronautics and Space Administration.
 * All Rights Reserved.
 */

/*
 * this code was published by user 'robotfire' on the WorldWind forum thread
 *   https://forum.worldwindcentral.com/forum/world-wind-java-forums/development-help/17605-collada-models-with-lighting
 * By permission of its creator it is put under the same license and copyright as WorldWind.
 */
package osm.map.worldwind.gl;

import gov.nasa.worldwind.Movable;
import gov.nasa.worldwind.Movable2;
import gov.nasa.worldwind.geom.Angle;
import gov.nasa.worldwind.geom.LatLon;
import gov.nasa.worldwind.geom.Position;
import gov.nasa.worldwind.geom.Vec4;
import gov.nasa.worldwind.globes.Globe;
import gov.nasa.worldwind.layers.Layer;
import gov.nasa.worldwind.pick.PickSupport;

import gov.nasa.worldwind.render.DrawContext;
import gov.nasa.worldwind.render.Highlightable;
import gov.nasa.worldwind.render.OrderedRenderable;
import gov.nasa.worldwind.render.PreRenderable;
import gov.nasa.worldwind.render.Renderable;
import java.awt.Color;
import java.awt.Point;
import com.jogamp.opengl.GL2;

public abstract class GLRenderable implements Renderable, PreRenderable, Highlightable, Movable, Movable2 {

	protected Layer pickLayer;

	protected Position position;
	protected double azimuth = 0.0;
	protected double roll = 0.0;
	protected double elevation = 0.0;
	protected double renderDistance = 50000; //do not draw if object is this far from eye
	protected boolean keepConstantSize = true;
	protected double size = 1;
	protected boolean clamp = false;
	protected boolean useLighting = true;
	protected boolean visible = true;
	protected Vec4 lightSource = new Vec4(1.0, 0.5, 1.0);
	protected double eyeDistance;
	protected double eyeDistanceOffset = 0;
	boolean drawnOnce = false;

	protected PickSupport pickSupport = new PickSupport();
	private boolean highlighted;

	public GLRenderable(Position position) {
		this.position = position;
	}

	public void clamp() {
		this.clamp = true;
	}

	@Override
	public void render(DrawContext dc) {
		if (!this.visible) {
			return;
		}

		dc.addOrderedRenderable(new OrderedGLRenderable());
	}

	protected void updateEyeDistance(DrawContext dc) {
		eyeDistance = dc.getGlobe().computePointFromPosition(position).distanceTo3(dc.getView().getEyePoint()) + eyeDistanceOffset;
	}

	public void myRender(DrawContext dc) {

		updateEyeDistance(dc);

		// If far away, don't render it
		if (eyeDistance > renderDistance) {
			return;
		}

		try {
			if (dc.isPickingMode()) {
				if (dc.getCurrentLayer() != null) {
					this.pickLayer = dc.getCurrentLayer();
				}
			}
			beginDraw(dc);
			if (dc.isPickingMode()) {
				GL2 gl = dc.getGL().getGL2();
				Color pickColor = dc.getUniquePickColor();
				pickSupport.addPickableObject(pickColor.getRGB(), this, this.position);
				gl.glColor3ub((byte) pickColor.getRed(), (byte) pickColor.getGreen(), (byte) pickColor.getBlue());
			}
			draw(dc);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			endDraw(dc);
		}
	}

	protected void draw(DrawContext dc) {
		GL2 gl = dc.getGL().getGL2();

		Vec4 loc;
		if (clamp) {
			loc = dc.computeTerrainPoint(position.latitude, position.longitude, 0);
		} else {
			loc = dc.getGlobe().computePointFromPosition(position, position.elevation * dc.getVerticalExaggeration());
		}
		double localSize = this.computeSize(dc, loc);

		if (dc.getView().getFrustumInModelCoordinates().contains(loc)) {
			dc.getView().pushReferenceCenter(dc, loc);
			gl.glRotated(position.getLongitude().degrees, 0, 1, 0);
			gl.glRotated(-position.getLatitude().degrees, 1, 0, 0);
			gl.glRotated(-azimuth, 0, 0, 1);
			gl.glRotated(elevation, 1, 0, 0);
			gl.glRotated(roll, 0, 1, 0);
			gl.glScaled(localSize, localSize, localSize);
			drawGL(dc);
			dc.getView().popReferenceCenter(dc);
		}
	}

	protected abstract void drawGL(DrawContext dc);

	// puts opengl in the correct state for this layer
	protected void beginDraw(DrawContext dc) {
		GL2 gl = dc.getGL().getGL2();
		gl.glPushAttrib(
			GL2.GL_TEXTURE_BIT
			| GL2.GL_DEPTH_BUFFER_BIT
			| GL2.GL_COLOR_BUFFER_BIT
			| GL2.GL_HINT_BIT
			| GL2.GL_POLYGON_BIT
			| GL2.GL_ENABLE_BIT
			| GL2.GL_CURRENT_BIT
			| GL2.GL_LIGHTING_BIT
			| GL2.GL_TRANSFORM_BIT
			| GL2.GL_CLIENT_VERTEX_ARRAY_BIT);

		if (useLighting && !dc.isPickingMode()) {
			gl.glEnable(GL2.GL_CULL_FACE);
			gl.glEnable(GL2.GL_SMOOTH);
			gl.glEnable(GL2.GL_LIGHTING);
			gl.glLightModeli(GL2.GL_LIGHT_MODEL_LOCAL_VIEWER, GL2.GL_TRUE);
			gl.glLightModeli(GL2.GL_LIGHT_MODEL_TWO_SIDE, GL2.GL_FALSE);

			gl.glEnable(GL2.GL_LIGHT0);

			Vec4 vec = lightSource.normalize3();
			float[] params = new float[]{(float) vec.x, (float) vec.y, (float) vec.z, 0f};
			gl.glMatrixMode(GL2.GL_MODELVIEW);
			gl.glPushMatrix();
			gl.glLoadIdentity();
			gl.glLightfv(GL2.GL_LIGHT0, GL2.GL_POSITION, params, 0);
			gl.glPopMatrix();
		}

		gl.glEnable(GL2.GL_NORMALIZE);
		gl.glMatrixMode(GL2.GL_MODELVIEW);
		gl.glPushMatrix();
	}

	// resets opengl state
	protected void endDraw(DrawContext dc) {
		GL2 gl = dc.getGL().getGL2();
		gl.glMatrixMode(GL2.GL_MODELVIEW);
		gl.glPopMatrix();
		gl.glPopAttrib();
	}

	protected double computeSize(DrawContext dc, Vec4 loc) {
		if (this.keepConstantSize) {
			return size;
		}
		if (loc == null) {
			System.err.println("Null location when computing size");
			return 1;
		}
		double d = loc.distanceTo3(dc.getView().getEyePoint());
		double newSize = 60 * dc.getView().computePixelSizeAtDistance(d);
		if (newSize < 2) {
			newSize = 2;
		}
		return newSize;
	}

	protected final Vec4 computeTerrainPoint(DrawContext dc, Angle lat, Angle lon) {
		Vec4 p = dc.getSurfaceGeometry().getSurfacePoint(lat, lon);
		if (p == null) {
			p = dc.getGlobe().computePointFromPosition(lat, lon,
				dc.getGlobe().getElevation(lat, lon) * dc.getVerticalExaggeration());
		}
		return p;
	}

	public boolean isConstantSize() {
		return keepConstantSize;
	}

	public void setKeepConstantSize(boolean val) {
		this.keepConstantSize = val;
	}

	public double getSize() {
		return size;
	}

	public void setSize(double size) {
		this.size = size;
	}

	public Position getPosition() {
		return position;
	}

	public void setPosition(Position position) {
		this.position = position;
	}

	public double getAzimuth() {
		return azimuth;
	}

	public void setAzimuth(double val) {
		this.azimuth = val;
	}

	public double getRoll() {
		return roll;
	}

	public void setRoll(double val) {
		this.roll = val;
	}

	public double getElevation() {
		return elevation;
	}

	public void setElevation(double val) {
		this.elevation = val;
	}

	public boolean isVisible() {
		return this.visible;
	}

	public void setVisible(boolean visible) {
		this.visible = visible;
	}

	public void setRenderDistance(double renderDistance) {
		this.renderDistance = renderDistance;
	}

	public class OrderedGLRenderable implements OrderedRenderable {

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

		@Override
		public void pick(DrawContext dc, Point pickPoint) {
			pickSupport.clearPickList();
			try {
				pickSupport.beginPicking(dc);
				GLRenderable.this.myRender(dc);
			} finally {
				pickSupport.endPicking(dc);
				pickSupport.resolvePick(dc, pickPoint, pickLayer);
			}
		}

		@Override
		public void render(DrawContext dc) {

			GLRenderable.this.myRender(dc);
		}

	}

	@Override
	public void preRender(DrawContext dc) {
		if (dc.getCurrentLayer() != null) {
			this.pickLayer = dc.getCurrentLayer();
		}

	}

	@Override
	public boolean isHighlighted() {
		return this.highlighted;
	}

	@Override
	public void setHighlighted(boolean highlighted) {
		this.highlighted = highlighted;
	}

	@Override
	public Position getReferencePosition() {
		return this.position;
	}

	@Override
	public void move(Position position) {
        Angle heading = LatLon.greatCircleAzimuth(this.getReferencePosition(),position);
        Angle pathLength = LatLon.greatCircleDistance(this.getReferencePosition(), position);
        this.position = new Position(LatLon.greatCircleEndPosition(this.position, heading, pathLength),this.position.elevation);
    }

    protected void doMoveTo(Globe globe, Position oldReferencePosition, Position newReferencePosition) {
//        List locations = new ArrayList(1);
//        locations.add(this.getCenter());
//        List newLocations = LatLon.computeShiftedLocations(globe, oldReferencePosition, newReferencePosition,locations); 
//        this.setCenter(newLocations.get(0));
		this.position = new Position(newReferencePosition,this.position.getElevation());
	}

	@Override
	public void moveTo(Position position) {
		this.position = position;
	}

	@Override
	public void moveTo(Globe globe, Position position) {
		this.position = new Position(position,this.position.getElevation());
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy