Issue #28 Changed ResourceList so it can be extended to allow duplicates. Removed deleted files from ISerializableObject files. Made TileSetRenderable properly issue refresh when images were still being requested. Made true color code work by only showing intersecting areas of all bands on screen. Made so shader files would be reread in if edited.

Change-Id: Ib2ce27522c59f25ce1cef65e6d7665e28963f081

Former-commit-id: 1f84ddbddf [formerly 75b2cdff47] [formerly 1f84ddbddf [formerly 75b2cdff47] [formerly c4812b7745 [formerly 291edbc6bd69815e003179e9ce708b6fdad254ad]]]
Former-commit-id: c4812b7745
Former-commit-id: 6f96fa5045 [formerly 7f506ce81d]
Former-commit-id: 8e894dba11
This commit is contained in:
Max Schenkelberg 2012-08-23 17:37:12 -05:00
parent d1801d7942
commit 713f9be08b
11 changed files with 248 additions and 179 deletions

View file

@ -17,7 +17,6 @@ com.raytheon.uf.viz.core.rsc.capabilities.LabelableCapability
com.raytheon.uf.viz.core.rsc.capabilities.DensityCapability
com.raytheon.uf.viz.core.rsc.capabilities.DisplayTypeCapability
com.raytheon.uf.viz.core.rsc.capabilities.MagnificationCapability
com.raytheon.uf.viz.core.rsc.capabilities.MultiChannelCapability
com.raytheon.uf.viz.core.rsc.capabilities.PointCapability
com.raytheon.uf.viz.core.rsc.capabilities.TimeMatchBasisCapability
com.raytheon.uf.viz.core.rsc.GenericResourceData

View file

@ -158,6 +158,18 @@ public class ResourceList extends CopyOnWriteArrayList<ResourcePair> implements
return add(rp);
}
/**
* Function for determining if the {@link ResourcePair} can be added to the
* list. Default checks if the pair is already in the list and returns false
* if so
*
* @param e
* @return
*/
protected boolean canAdd(ResourcePair e) {
return contains(e) == false;
}
/*
* (non-Javadoc)
*
@ -165,7 +177,7 @@ public class ResourceList extends CopyOnWriteArrayList<ResourcePair> implements
*/
@Override
public boolean add(ResourcePair e) {
if (e == null || contains(e)) {
if (e == null || canAdd(e) == false) {
return false;
}
@ -263,7 +275,7 @@ public class ResourceList extends CopyOnWriteArrayList<ResourcePair> implements
}
synchronized (this) {
if (contains(e)) {
if (canAdd(e) == false) {
return false;
}
@ -276,9 +288,7 @@ public class ResourceList extends CopyOnWriteArrayList<ResourcePair> implements
super.add(i >= 0 ? (i + 1) : 0, e);
synchronized (resourcesToInstantiate) {
if (resourcesToInstantiate.contains(e) == false) {
resourcesToInstantiate.add(e);
}
resourcesToInstantiate.add(e);
}
}
@ -300,7 +310,7 @@ public class ResourceList extends CopyOnWriteArrayList<ResourcePair> implements
if (rp.getResource() == null) {
Validate.notNull(rp.getResourceData());
}
if (contains(rp) == false) {
if (canAdd(rp)) {
toAdd.add(rp);
}
}
@ -400,7 +410,13 @@ public class ResourceList extends CopyOnWriteArrayList<ResourcePair> implements
super.remove(index);
synchronized (resourcesToInstantiate) {
resourcesToInstantiate.remove(rp);
// Ensure rp is removed from list entirely
Iterator<ResourcePair> iter = resourcesToInstantiate.iterator();
while (iter.hasNext()) {
if (iter.next() == rp) {
iter.remove();
}
}
}
try {

View file

@ -371,6 +371,7 @@ public class TileSetRenderable implements IRenderable {
}
jobMap.clear();
} else {
target.setNeedsRefresh(true);
// Create tiles needing images
createTileImages(target, tilesNeedingImage);
}

View file

@ -1,6 +1,9 @@
#include <colorUtil>
#include <indexing>
// Multiplier used to store bit mask safely between 0-1
const float maskMultiplier = 8.0;
uniform sampler2D rawTex;
uniform float naturalMin;
uniform float naturalMax;
@ -16,7 +19,11 @@ uniform int width;
uniform float noDataValue;
uniform float alphaStep;
uniform int checkAlpha;
uniform int expectedMask;
int toBitMask(float alpha) {
return int((alpha * maskMultiplier) + 0.5);
}
float getIndex(sampler2D rawTex, float cmapMin, float cmapMax, float naturalMin, float naturalMax, int isFloat) {
vec4 textureValue = texture2D(rawTex, gl_TexCoord[0].st);
@ -25,7 +32,7 @@ float getIndex(sampler2D rawTex, float cmapMin, float cmapMax, float naturalMin,
naturalVal = ((naturalVal * (naturalMax - naturalMin)) + naturalMin);
}
float index = 0.0;
float index = -1.0;
if (naturalVal != noDataValue && naturalVal == naturalVal) {
index = findIndex(naturalVal, cmapMin, cmapMax);
}
@ -34,28 +41,50 @@ float getIndex(sampler2D rawTex, float cmapMin, float cmapMax, float naturalMin,
void main(void)
{
vec2 xy = gl_FragCoord.xy;
vec4 imageVal = texture2D(rawTex,gl_TexCoord[0].st);
vec4 curVal = texture2D(trueColorTexture, vec2((xy.x / float(width)), (xy.y / float(height))));
float r = curVal.r;
float g = curVal.g;
float b = curVal.b;
float a = curVal.a;
float index = getIndex(rawTex, cmapMin, cmapMax, naturalMin, naturalMax, isFloat);
if ( band == 0 && index > r ) {
r = index;
} else if ( band == 1 && index > g ) {
g = index;
} else if ( band == 2 && index > b ) {
b = index;
if ( band == -1 ) {
vec4 imageVal = texture2D(rawTex,gl_TexCoord[0].st);
float r = imageVal.r;
float g = imageVal.g;
float b = imageVal.b;
float a = imageVal.a;
// Round because of 8-bit floating point precision
int bitMask = toBitMask(a);
if (expectedMask > 0 && bitMask == expectedMask ) {
a = 1.0;
} else {
a = 0.0;
}
gl_FragColor = vec4(r,g,b,a);
} else {
vec2 xy = gl_FragCoord.xy;
vec4 imageVal = texture2D(rawTex,gl_TexCoord[0].st);
vec4 curVal = texture2D(trueColorTexture, vec2((xy.x / float(width)), (xy.y / float(height))));
float r = curVal.r;
float g = curVal.g;
float b = curVal.b;
float a = curVal.a;
float index = getIndex(rawTex, cmapMin, cmapMax, naturalMin, naturalMax, isFloat);
if ( index != -1.0 ) {
int currentMask = toBitMask(a);
int bitValue = (1 << band);
if ( band == 0 && index > r ) {
r = index;
} else if ( band == 1 && index > g ) {
g = index;
} else if ( band == 2 && index > b ) {
b = index;
}
if ( (currentMask & bitValue) == 0 ) {
// alpha does not contain this bit yet!
a = (currentMask | bitValue) / maskMultiplier;
}
}
gl_FragColor = vec4(r,g,b,a);
}
a = a + alphaStep;
if (checkAlpha == 1 && a < 1.0) {
a = 0.0;
}
gl_FragColor = vec4(r,g,b,a);
}

View file

@ -64,20 +64,11 @@ public class GLTrueColorImagingExtension extends AbstractGLSLImagingExtension
private Channel renderingChannel;
/** The current rendering bit mask, specifies what bands we rendered */
private int currentMask = 0;
private Map<ColorMapParameters, Object> parameters = new IdentityHashMap<ColorMapParameters, Object>();
/**
* Alpha value to add to current alpha. When all 3 passes occur, alpha
* should be >= 1.0
*/
private float alphaStep;
/**
* Flag if alpha check should be performed in shader. Alpha vals less than
* one will be set to 0
*/
private boolean checkAlpha;
/*
* (non-Javadoc)
*
@ -119,6 +110,8 @@ public class GLTrueColorImagingExtension extends AbstractGLSLImagingExtension
if (image instanceof GLTrueColorImage) {
GLTrueColorImage trueColorImage = (GLTrueColorImage) image;
if (trueColorImage.isRepaint()) {
// Reset current bit mask
currentMask = 0;
parameters.clear();
writeToImage = trueColorImage;
GLOffscreenRenderingExtension extension = target
@ -127,18 +120,14 @@ public class GLTrueColorImagingExtension extends AbstractGLSLImagingExtension
extension.renderOffscreen(trueColorImage,
trueColorImage.getImageExtent());
boolean allPainted = true;
int channels = trueColorImage.getNumberOfChannels();
// Calculate our alpha step, ensure channels * alphaStep >=
// 1.0
alphaStep = 1.0f / (channels - 0.1f);
int i = 1;
for (Channel channel : Channel.values()) {
renderingChannel = channel;
DrawableImage[] imagesToDraw = trueColorImage
.getImages(channel);
if (imagesToDraw != null && imagesToDraw.length > 0) {
// Perform alpha check on last pass
checkAlpha = i == channels;
// Mark the channel bit in the current bit mask
currentMask |= (1 << channel.ordinal());
// Make sure images are staged before we mosaic them
ImagingSupport.prepareImages(target, imagesToDraw);
@ -153,22 +142,23 @@ public class GLTrueColorImagingExtension extends AbstractGLSLImagingExtension
// Need to set repaint based on if drawing
// completed.
trueColorImage.setRepaint(allPainted == false);
++i;
}
}
} finally {
} catch (VizException e) {
extension.renderOnscreen();
throw e;
}
renderingChannel = null;
writeToImage = null;
trueColorImage.setImageParameters(parameters.keySet());
trueColorImage.bind(target.getGl());
return imageCoverage;
} else {
target.drawRasters(paintProps,
new DrawableImage(trueColorImage.getWrappedImage(),
imageCoverage));
return null;
}
trueColorImage.setImageParameters(parameters.keySet());
target.drawRasters(paintProps,
new DrawableImage(trueColorImage.getWrappedImage(),
imageCoverage));
// Don't actually render this image now since we just did it
return null;
} else {
GL gl = target.getGl();
// bind on GL_TEXTURE1 as 0 is channel image
@ -188,10 +178,18 @@ public class GLTrueColorImagingExtension extends AbstractGLSLImagingExtension
@Override
public void postImageRender(PaintProperties paintProps,
AbstractGLImage image, Object data) throws VizException {
GL gl = target.getGl();
// Unbind the writeToImage from GL_TEXTURE1
gl.glActiveTexture(GL.GL_TEXTURE1);
gl.glBindTexture(writeToImage.getTextureStorageType(), 0);
if (image instanceof GLTrueColorImage) {
target.getExtension(GLOffscreenRenderingExtension.class)
.renderOnscreen();
target.drawRasters(paintProps, new DrawableImage(
((GLTrueColorImage) image).getWrappedImage(),
(PixelCoverage) data));
} else if (writeToImage != null) {
GL gl = target.getGl();
// Unbind the writeToImage from GL_TEXTURE1
gl.glActiveTexture(GL.GL_TEXTURE1);
gl.glBindTexture(writeToImage.getTextureStorageType(), 0);
}
}
/*
@ -206,36 +204,41 @@ public class GLTrueColorImagingExtension extends AbstractGLSLImagingExtension
@Override
public void loadShaderData(GLShaderProgram program, IImage image,
PaintProperties paintProps) throws VizException {
if (image instanceof GLColormappedImage == false) {
throw new VizException(
"Can only render colormapped images in true color");
if (image instanceof GLTrueColorImage) {
program.setUniform("band", -1);
program.setUniform("rawTex", 0);
program.setUniform("expectedMask", currentMask);
} else {
if (image instanceof GLColormappedImage == false) {
throw new VizException(
"Can only render colormapped images in true color");
}
GLColormappedImage cmapImage = (GLColormappedImage) image;
ColorMapParameters colorMapParameters = cmapImage
.getColorMapParameters();
parameters.put(colorMapParameters, null);
int textureType = cmapImage.getTextureType();
// Set the band image data
program.setUniform("rawTex", 0);
program.setUniform("naturalMin", colorMapParameters.getDataMin());
program.setUniform("naturalMax", colorMapParameters.getDataMax());
program.setUniform("cmapMin", colorMapParameters.getColorMapMin());
program.setUniform("cmapMax", colorMapParameters.getColorMapMax());
program.setUniform("isFloat", textureType == GL.GL_FLOAT
|| textureType == GL.GL_HALF_FLOAT_ARB ? 1 : 0);
program.setUniform("noDataValue",
colorMapParameters.getNoDataValue());
// Set the composite image data
program.setUniform("trueColorTexture", 1);
program.setUniform("width", writeToImage.getWidth());
program.setUniform("height", writeToImage.getHeight());
// Set the band we are rendering to
program.setUniform("band", renderingChannel.ordinal());
}
GLColormappedImage cmapImage = (GLColormappedImage) image;
ColorMapParameters colorMapParameters = cmapImage
.getColorMapParameters();
parameters.put(colorMapParameters, null);
int textureType = cmapImage.getTextureType();
// Set the band image data
program.setUniform("rawTex", 0);
program.setUniform("naturalMin", colorMapParameters.getDataMin());
program.setUniform("naturalMax", colorMapParameters.getDataMax());
program.setUniform("cmapMin", colorMapParameters.getColorMapMin());
program.setUniform("cmapMax", colorMapParameters.getColorMapMax());
program.setUniform("isFloat", textureType == GL.GL_FLOAT
|| textureType == GL.GL_HALF_FLOAT_ARB ? 1 : 0);
program.setUniform("noDataValue", colorMapParameters.getNoDataValue());
// Set the composite image data
program.setUniform("trueColorTexture", 1);
program.setUniform("width", writeToImage.getWidth());
program.setUniform("height", writeToImage.getHeight());
// Set the band we are rendering to
program.setUniform("band", renderingChannel.ordinal());
program.setUniform("checkAlpha", checkAlpha);
program.setUniform("alphaStep", alphaStep);
}
/*

View file

@ -232,22 +232,6 @@ public class GLTrueColorImage extends GLDelegateImage<GLImage> implements
}
}
/**
* Returns the number of channels the image is currently using
*
* @return
*/
public int getNumberOfChannels() {
int channels = 0;
for (Channel c : Channel.values()) {
DrawableImage[] images = getImages(c);
if (images != null && images.length > 0) {
++channels;
}
}
return channels;
}
/*
* (non-Javadoc)
*

View file

@ -19,18 +19,16 @@
**/
package com.raytheon.uf.viz.truecolor.rsc;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.swt.graphics.Rectangle;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.common.time.DataTime;
import com.raytheon.uf.viz.core.DrawableImage;
import com.raytheon.uf.viz.core.IExtent;
import com.raytheon.uf.viz.core.IGraphicsTarget;
@ -127,13 +125,18 @@ public class TrueColorResourceGroup extends
private static final String DEFAULT_NAME = "RGB Composite";
private List<DisplayedChannelResource> displayedResources;
private Map<Channel, DisplayedChannelResource> displayedResources;
private ITrueColorImage image;
private boolean timeAgnostic = true;
/** Mapping to keep colormap parameters in sync with ChannelInfo in resourceData */
private String baseName;
/**
* Mapping to keep colormap parameters in sync with ChannelInfo in
* resourceData
*/
private Map<ColorMapParameters, ChannelInfo> channelInfoMap = new IdentityHashMap<ColorMapParameters, ChannelInfo>();
/**
@ -187,16 +190,22 @@ public class TrueColorResourceGroup extends
FramesInfo fi = paintProps.getFramesInfo();
for (Channel c : Channel.values()) {
List<DrawableImage> images = new ArrayList<DrawableImage>();
for (DisplayedChannelResource dcr : displayedResources) {
if (dcr.isChannel(c)) {
DrawableImage[] images = null;
DisplayedChannelResource dcr = displayedResources.get(c);
if (dcr != null) {
DataTime dcrTime = fi.getTimeForResource(dcr.resource);
if (dcrTime != null) {
paintProps.setDataTime(fi.getTimeForResource(dcr.resource));
images.addAll(dcr.resource
Collection<DrawableImage> dcrImages = dcr.resource
.getCapability(ImagingCapability.class)
.getProvider().getImages(target, paintProps));
.getProvider().getImages(target, paintProps);
if (dcrImages != null) {
images = dcrImages.toArray(new DrawableImage[dcrImages
.size()]);
}
}
}
image.setImages(c, images.toArray(new DrawableImage[images.size()]));
image.setImages(c, images);
}
Coordinate ul = new Coordinate(extent.getMinX(), extent.getMaxY());
@ -229,10 +238,8 @@ public class TrueColorResourceGroup extends
// We will name the composite
getCapability(GroupNamingCapability.class);
displayedResources = new ArrayList<DisplayedChannelResource>();
displayedResources = new HashMap<Channel, DisplayedChannelResource>();
ResourceList resources = getResourceList();
// Make sure multiple resources are not assinged to same channel
Set<Channel> usedChannels = new HashSet<Channel>();
for (ChannelResource cr : resourceData.getChannelResources()) {
for (ResourcePair rp : resources) {
if (cr.getResourceData() == rp.getResourceData()) {
@ -263,7 +270,7 @@ public class TrueColorResourceGroup extends
}
if (cr.getChannel() == null) {
error = "is not tied to any channel";
} else if (usedChannels.contains(cr.getChannel())) {
} else if (displayedResources.containsKey(cr.getChannel())) {
error = "is tied to a channel already in use";
}
@ -308,14 +315,19 @@ public class TrueColorResourceGroup extends
resources.remove(rp);
} else {
resource.getResourceData().addChangeListener(this);
usedChannels.add(displayedResource.getChannel());
displayedResources.add(displayedResource);
displayedResources.put(displayedResource.getChannel(),
displayedResource);
}
break;
}
}
}
if (displayedResources.size() == 0) {
throw new VizException(
"No resources to draw in true color composite");
}
ITrueColorImagingExtension ext = target
.getExtension(ITrueColorImagingExtension.class);
image = ext.initializeRaster(new int[] { 0, 0 }, null);
@ -326,9 +338,22 @@ public class TrueColorResourceGroup extends
// Every resource has to be time agnostic for us to be as well
timeAgnostic = true;
for (DisplayedChannelResource dr : displayedResources) {
for (DisplayedChannelResource dr : displayedResources.values()) {
timeAgnostic &= dr.resource.isTimeAgnostic();
}
String groupName = resourceData.getGroupName();
if (groupName == null) {
groupName = "True Color Composite";
}
String channels = " (";
for (Channel c : Channel.values()) {
if (displayedResources.containsKey(c)) {
channels += c.name().substring(0, 1);
}
}
channels += "): ";
baseName = groupName + channels;
}
/*
@ -338,37 +363,28 @@ public class TrueColorResourceGroup extends
*/
@Override
public String getName() {
String name = resourceData.getGroupName();
if (name != null) {
name += " ";
}
String name = baseName;
boolean first = true;
for (Channel c : Channel.values()) {
DisplayedChannelResource dcr = displayedResources.get(c);
if (dcr != null) {
if (!first) {
name += "/";
}
first = false;
if (image != null) {
String productNames = "";
boolean first = true;
for (Channel c : Channel.values()) {
DrawableImage[] images = image.getImages(c);
if (images != null && images.length > 0) {
name += c.name().substring(0, 1);
if (!first) {
productNames += "/";
}
for (DisplayedChannelResource rsc : displayedResources) {
if (rsc.isChannel(c)) {
productNames += rsc.getDisplayName();
break;
}
}
first = false;
boolean has = true;
if (image != null && image.getImages(c) == null) {
has = false;
}
if (has) {
name += dcr.getDisplayName();
} else {
String channelName = c.name();
name += "No " + channelName.substring(0, 1)
+ channelName.substring(1).toLowerCase();
}
}
if (first == true) {
name += DEFAULT_NAME;
} else {
name += ": " + productNames;
}
} else {
name += DEFAULT_NAME;
}
return name;
}
@ -420,6 +436,6 @@ public class TrueColorResourceGroup extends
}
public Collection<DisplayedChannelResource> getChannelResources() {
return displayedResources;
return displayedResources.values();
}
}

View file

@ -19,8 +19,8 @@
**/
package com.raytheon.uf.viz.truecolor.rsc;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@ -41,8 +41,7 @@ import com.raytheon.uf.viz.truecolor.extension.ITrueColorImagingExtension.Channe
/**
* {@link TrueColorResourceGroup} resource data. Contains a red/blue/green
* channel resource and a name. Sub resources that .equal each other will be
* replaced with the first reference to save time
* channel resource and a name.
*
* <pre>
*
@ -79,26 +78,34 @@ public class TrueColorResourceGroupData extends AbstractResourceData implements
@Override
public ResourceList getResourceList() {
if (resourceList == null) {
resourceList = new ResourceList();
// Removes duplicate resources
List<ChannelResource> added = new ArrayList<ChannelResource>(
channelResources.size());
for (ChannelResource resource : channelResources) {
if (addResource(resource.getResourceData())) {
added.add(resource);
resourceList = new ResourceList() {
private static final long serialVersionUID = 1L;
@Override
protected boolean canAdd(ResourcePair e) {
// Don't allow a ResourcePair that == another in the list
Iterator<ResourcePair> iter = iterator();
while (iter.hasNext()) {
if (iter.next() == e) {
return false;
}
}
return true;
}
channelResources = added;
};
for (ChannelResource resource : channelResources) {
addResource(resource.getResourceData());
}
}
return resourceList;
}
private boolean addResource(AbstractResourceData resourceData) {
private void addResource(AbstractResourceData resourceData) {
ResourcePair rp = new ResourcePair();
rp.setResourceData(resourceData);
rp.setLoadProperties(new LoadProperties());
rp.setProperties(new ResourceProperties());
return resourceList.add(rp);
resourceList.add(rp);
}
/*

View file

@ -90,7 +90,6 @@ public abstract class AbstractGLImagingExtension extends
try {
gl.glPolygonMode(GL.GL_FRONT_AND_BACK, GL.GL_FILL);
rval = drawRastersInternal(paintProps, images);
gl.glPolygonMode(GL.GL_BACK, GL.GL_LINE);
disableBlending(gl);
} finally {
target.popGLState();

View file

@ -74,6 +74,8 @@ public class GLProgramManager {
private final Map<String, File> programFiles = new HashMap<String, File>();
private final Map<String, Long> programFileModTimes = new HashMap<String, Long>();
private final IPathManager pm;
private GLProgramManager() {
@ -86,6 +88,7 @@ public class GLProgramManager {
File fileObj = file.getFile();
String name = fileObj.getName();
programFiles.put(name, fileObj);
programFileModTimes.put(name, fileObj.lastModified());
programsCode.put(name, readProgramContents(fileObj));
}
}
@ -107,9 +110,15 @@ public class GLProgramManager {
* @throws VizException
*/
public String getProgramCode(String aProgramName) throws VizException {
String fileName = aProgramName + GLSL_EXTENSION;
hasBeenModified(aProgramName);
return programsCode.get(fileName);
if (aProgramName.endsWith(GLSL_EXTENSION) == false) {
aProgramName += GLSL_EXTENSION;
}
if (hasBeenModified(aProgramName)) {
File programFile = programFiles.get(aProgramName);
programsCode.put(aProgramName, readProgramContents(programFile));
programFileModTimes.put(aProgramName, programFile.lastModified());
}
return programsCode.get(aProgramName);
}
/**
@ -119,9 +128,16 @@ public class GLProgramManager {
* @return
*/
public boolean hasBeenModified(String programName) {
// TODO: Check file modification time and reload contents. Should also
// check modification times of files depends on and reload if any
// changes
if (programName.endsWith(GLSL_EXTENSION) == false) {
programName += GLSL_EXTENSION;
}
File programFile = programFiles.get(programName);
if (programFile != null) {
long lastMod = programFileModTimes.get(programName);
if (lastMod != programFile.lastModified()) {
return true;
}
}
return false;
}

View file

@ -1,5 +1,4 @@
com.raytheon.viz.satellite.rsc.SatResourceData
com.raytheon.viz.satellite.rsc.SatBlendedResourceData
com.raytheon.viz.satellite.rsc.SatBestResResourceData
com.raytheon.viz.satellite.rsc.SatTrueColorResourceData
com.raytheon.viz.satellite.SatelliteProductBrowserDataDefinition