From 736f0319ab2eac73a90bef5e43761a5cc1f85002 Mon Sep 17 00:00:00 2001 From: pdavidc Date: Fri, 30 Sep 2016 12:12:13 -0700 Subject: [PATCH] Added image display options needed for shape dashed outlines (issue #63) --- .../java/gov/nasa/worldwind/WorldWind.java | 43 +++++++++++++++++++ .../nasa/worldwind/render/ImageOptions.java | 15 +++++++ .../worldwind/render/RenderResourceCache.java | 21 ++++++++- .../java/gov/nasa/worldwind/shape/Path.java | 16 ++++++- 4 files changed, 91 insertions(+), 4 deletions(-) diff --git a/worldwind/src/main/java/gov/nasa/worldwind/WorldWind.java b/worldwind/src/main/java/gov/nasa/worldwind/WorldWind.java index 9bd90b865..6101b32ea 100644 --- a/worldwind/src/main/java/gov/nasa/worldwind/WorldWind.java +++ b/worldwind/src/main/java/gov/nasa/worldwind/WorldWind.java @@ -250,6 +250,49 @@ public class WorldWind { } + /** + * {@link ResamplingMode} constant indicating bilinear image sampling. + */ + public static final int BILINEAR = 0; + + /** + * {@link ResamplingMode} constant indicating nearest neighbor image sampling. + */ + public static final int NEAREST_NEIGHBOR = 1; + + /** + * Resampling mode indicates the image sampling algorithm used by World Wind to display images that appear larger or + * smaller on screen than their native resolution. Accepted values are {@link WorldWind#BILINEAR} and {@link + * WorldWind#NEAREST_NEIGHBOR}. + */ + @IntDef({BILINEAR, NEAREST_NEIGHBOR}) + @Retention(RetentionPolicy.SOURCE) + public @interface ResamplingMode { + + } + + /** + * {@link WrapMode} constant indicating that the image's edge pixels should be displayed outside of the image + * bounds. + */ + public static final int CLAMP = 0; + + /** + * {@link WrapMode} constant indicating that the image should display as a repeating pattern outside of the image + * bounds. + */ + public static final int REPEAT = 1; + + /** + * Wrap mode indicates how World Wind displays the contents of an image when attempting to draw a region outside of + * the image bounds. Accepted values are {@link WorldWind#CLAMP} and {@link WorldWind#REPEAT}. + */ + @IntDef({CLAMP, REPEAT}) + @Retention(RetentionPolicy.SOURCE) + public @interface WrapMode { + + } + /** * Notification constant requesting that World Window instances update their display. */ diff --git a/worldwind/src/main/java/gov/nasa/worldwind/render/ImageOptions.java b/worldwind/src/main/java/gov/nasa/worldwind/render/ImageOptions.java index 11b080634..83e2b8189 100644 --- a/worldwind/src/main/java/gov/nasa/worldwind/render/ImageOptions.java +++ b/worldwind/src/main/java/gov/nasa/worldwind/render/ImageOptions.java @@ -21,6 +21,21 @@ public class ImageOptions { @WorldWind.ImageConfig public int imageConfig = WorldWind.RGBA_8888; + /** + * Indicates the image sampling algorithm used by World Wind to display images that appear larger or smaller on + * screen than their native resolution. Accepted values are {@link WorldWind#BILINEAR} and {@link + * WorldWind#NEAREST_NEIGHBOR}. + */ + @WorldWind.ResamplingMode + public int resamplingMode = WorldWind.BILINEAR; + + /** + * Indicates how World Wind displays the contents of an image when attempting to draw a region outside of the image + * bounds. Accepted values are {@link WorldWind#CLAMP} and {@link WorldWind#REPEAT}. + */ + @WorldWind.WrapMode + public int wrapMode = WorldWind.CLAMP; + /** * Constructs an image options with default values. */ diff --git a/worldwind/src/main/java/gov/nasa/worldwind/render/RenderResourceCache.java b/worldwind/src/main/java/gov/nasa/worldwind/render/RenderResourceCache.java index 5212bf72f..e2c25f2c0 100644 --- a/worldwind/src/main/java/gov/nasa/worldwind/render/RenderResourceCache.java +++ b/worldwind/src/main/java/gov/nasa/worldwind/render/RenderResourceCache.java @@ -9,6 +9,7 @@ import android.content.Context; import android.content.res.Resources; import android.graphics.Bitmap; +import android.opengl.GLES20; import android.os.Handler; import android.os.Message; @@ -132,7 +133,7 @@ public Texture retrieveTexture(ImageSource imageSource, ImageOptions options) { // Bitmap image sources are already in memory, so a texture may be created and put into the cache immediately. if (imageSource.isBitmap()) { - Texture texture = new Texture(imageSource.asBitmap()); + Texture texture = this.createTexture(imageSource, options, imageSource.asBitmap()); this.put(imageSource, texture, texture.getByteCount()); return texture; } @@ -143,7 +144,7 @@ public Texture retrieveTexture(ImageSource imageSource, ImageOptions options) { // corresponding texture if found. Bitmap bitmap = this.imageRetrieverCache.remove(imageSource); if (bitmap != null) { - Texture texture = new Texture(bitmap); + Texture texture = this.createTexture(imageSource, options, bitmap); this.put(imageSource, texture, texture.getByteCount()); return texture; } @@ -160,6 +161,22 @@ public Texture retrieveTexture(ImageSource imageSource, ImageOptions options) { return null; } + protected Texture createTexture(ImageSource imageSource, ImageOptions options, Bitmap bitmap) { + Texture texture = new Texture(bitmap); + + if (options != null && options.resamplingMode == WorldWind.NEAREST_NEIGHBOR) { + texture.setTexParameter(GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST); + texture.setTexParameter(GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST); + } + + if (options != null && options.wrapMode == WorldWind.REPEAT) { + texture.setTexParameter(GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_REPEAT); + texture.setTexParameter(GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_REPEAT); + } + + return texture; + } + @Override public void retrievalSucceeded(Retriever retriever, ImageSource key, ImageOptions options, Bitmap value) { this.imageRetrieverCache.put(key, value, value.getByteCount()); diff --git a/worldwind/src/main/java/gov/nasa/worldwind/shape/Path.java b/worldwind/src/main/java/gov/nasa/worldwind/shape/Path.java index 8e93479d5..035b25b8d 100644 --- a/worldwind/src/main/java/gov/nasa/worldwind/shape/Path.java +++ b/worldwind/src/main/java/gov/nasa/worldwind/shape/Path.java @@ -24,6 +24,7 @@ import gov.nasa.worldwind.geom.Vec3; import gov.nasa.worldwind.render.BasicShaderProgram; import gov.nasa.worldwind.render.BufferObject; +import gov.nasa.worldwind.render.ImageOptions; import gov.nasa.worldwind.render.RenderContext; import gov.nasa.worldwind.render.Texture; import gov.nasa.worldwind.util.FloatArray; @@ -39,6 +40,8 @@ public class Path extends AbstractShape { protected static final double FOLLOW_TERRAIN_SEGMENT_LENGTH = 1000.0; + protected static final ImageOptions defaultOutlineImageOptions = new ImageOptions(); + protected List positions = Collections.emptyList(); protected boolean extrude; @@ -71,6 +74,11 @@ protected static Object nextCacheKey() { return new Object(); } + static { + defaultOutlineImageOptions.resamplingMode = WorldWind.NEAREST_NEIGHBOR; + defaultOutlineImageOptions.wrapMode = WorldWind.REPEAT; + } + public Path() { } @@ -190,7 +198,7 @@ protected void makeDrawable(RenderContext rc) { if (this.activeAttributes.drawOutline && this.activeAttributes.outlineImageSource != null) { Texture texture = rc.getTexture(this.activeAttributes.outlineImageSource); if (texture == null) { - texture = rc.retrieveTexture(this.activeAttributes.outlineImageSource, null); + texture = rc.retrieveTexture(this.activeAttributes.outlineImageSource, defaultOutlineImageOptions); } if (texture != null) { double metersPerPixel = rc.pixelSizeAtDistance(cameraDistance); @@ -234,7 +242,11 @@ protected void makeDrawable(RenderContext rc) { drawState.depthOffset = (this.altitudeMode == WorldWind.CLAMP_TO_GROUND ? CLAMP_TO_GROUND_DEPTH_OFFSET : 0); // Enqueue the drawable for processing on the OpenGL thread. - rc.offerShapeDrawable(drawable, cameraDistance); + if (this.altitudeMode == WorldWind.CLAMP_TO_GROUND) { + rc.offerSurfaceDrawable(drawable, 0 /*zOrder*/); + } else { + rc.offerShapeDrawable(drawable, cameraDistance); + } } protected boolean mustAssembleGeometry(RenderContext rc) {