support image texture rendering in surf functions

This commit is contained in:
wyq 2021-12-01 23:11:36 +08:00
parent f0b68abe13
commit c08d0b696a
9 changed files with 279 additions and 74 deletions

View File

@ -2850,6 +2850,66 @@ public class GraphicFactory {
return graphics;
}
/**
* Create image
*
* @param gdata Grid data array
* @param ls Legend scheme
* @return Image
*/
public static BufferedImage createImage(Array gdata, LegendScheme ls) {
gdata = gdata.copyIfView();
int width, height, breakNum;
width = gdata.getShape()[1];
height = gdata.getShape()[0];
breakNum = ls.getBreakNum();
double[] breakValue = new double[breakNum];
Color[] breakColor = new Color[breakNum];
Color undefColor = Color.white;
for (int i = 0; i < breakNum; i++) {
breakValue[i] = Double.parseDouble(ls.getLegendBreaks().get(i).getEndValue().toString());
breakColor[i] = ls.getLegendBreaks().get(i).getColor();
if (ls.getLegendBreaks().get(i).isNoData()) {
undefColor = ls.getLegendBreaks().get(i).getColor();
}
}
Color defaultColor = breakColor[breakNum - 1]; //Last color
BufferedImage aImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
double oneValue;
Color oneColor;
Index index = gdata.getIndex();
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
index.set(i, j);
oneValue = gdata.getDouble(index);
if (Double.isNaN(oneValue)) {
oneColor = undefColor;
} else {
oneColor = defaultColor;
if (ls.getLegendType() == LegendType.GRADUATED_COLOR) {
for (int k = 0; k < breakNum - 1; k++) {
if (oneValue < breakValue[k]) {
oneColor = breakColor[k];
break;
}
}
} else {
for (int k = 0; k < breakNum - 1; k++) {
if (oneValue == breakValue[k]) {
oneColor = breakColor[k];
break;
}
}
}
}
aImage.setRGB(j, height - i - 1, oneColor.getRGB());
}
}
return aImage;
}
/**
* Create image
*

View File

@ -5,6 +5,9 @@
*/
package org.meteoinfo.chart.graphic;
import com.jogamp.opengl.GL2;
import com.jogamp.opengl.util.texture.Texture;
import com.jogamp.opengl.util.texture.awt.AWTTextureIO;
import org.joml.Vector3f;
import org.meteoinfo.chart.jogl.Transform;
import org.meteoinfo.chart.jogl.pipe.Pipe;
@ -15,6 +18,7 @@ import org.meteoinfo.geometry.legend.PolygonBreak;
import org.meteoinfo.geometry.shape.PointZ;
import org.meteoinfo.geometry.shape.ShapeTypes;
import java.awt.image.BufferedImage;
import java.util.List;
import java.util.Vector;
@ -31,6 +35,8 @@ public class SurfaceGraphics extends GraphicCollection3D {
private Transform transform;
private Vector3f[][] tVertices;
private Vector3f[][] normals;
private BufferedImage image;
private Texture texture;
/**
* Constructor
@ -43,6 +49,7 @@ public class SurfaceGraphics extends GraphicCollection3D {
this.edgeInterp = false;
this.mesh = false;
this.usingLight = true;
this.image = null;
}
/**
@ -183,6 +190,38 @@ public class SurfaceGraphics extends GraphicCollection3D {
this.updateLegendIndex();
}
/**
* Get image
* @return The image
*/
public BufferedImage getImage() {
return this.image;
}
/**
* Set image
* @param value The image
*/
public void setImage(BufferedImage value) {
this.image = value;
}
/**
* Get texture
* @return Texture
*/
public Texture getTexture() {
return this.texture;
}
/**
* Set texture
* @param value Texture
*/
public void setTexture(Texture value) {
this.texture = value;
}
/**
* Check if the legend has multiple colors
*
@ -296,4 +335,12 @@ public class SurfaceGraphics extends GraphicCollection3D {
}
}
}
/**
* Update texture from image
* @param gl The JOGL GL2 object
*/
public void updateTexture(GL2 gl) {
this.texture = AWTTextureIO.newTexture(gl.getGLProfile(), this.image, true);
}
}

View File

@ -191,6 +191,7 @@ public class JOGLUtil {
graphics.setZValue(offset);
TextureShape ishape = new TextureShape();
ishape.setFileName(layer.getFileName());
ishape.setImage(layer.getImage());
Extent extent = layer.getExtent();
Extent3D ex3 = new Extent3D(extent.minX + xshift, extent.maxX + xshift, extent.minY, extent.maxY, offset, offset);
List<PointZ> coords = new ArrayList<>();

View File

@ -2751,6 +2751,8 @@ public class Plot3DGL extends Plot implements GLEventListener {
}
}
BufferedImage image = surface.getImage();
if (image == null) {
if (pgb.isDrawFill()) {
gl.glEnable(GL2.GL_POLYGON_OFFSET_FILL);
gl.glPolygonOffset(1.0f, 1.0f);
@ -2797,6 +2799,55 @@ public class Plot3DGL extends Plot implements GLEventListener {
}
gl.glDisable(GL2.GL_POLYGON_OFFSET_FILL);
}
} else {
Texture texture = surface.getTexture();
if (texture == null) {
surface.updateTexture(gl);
texture = surface.getTexture();
}
int idTexture = texture.getTextureObject();
gl.glColor3f(1f, 1f, 1f);
gl.glBindTexture(GL2.GL_TEXTURE_2D, idTexture);
// Texture parameterization
gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_MIN_FILTER, GL2.GL_NEAREST);
gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_MAG_FILTER, GL2.GL_LINEAR);
// Draw image
gl.glBegin(GL2.GL_QUADS);
// Front Face
float float_x, float_y, float_xb, float_yb;
for (int i = 0; i < dim1 - 1; i++) {
for (int j = 0; j < dim2 - 1; j++) {
float_y = (float) (i) / dim1;
//float_y = 1.0f - (float) (i) / dim1;
float_x = (float) (j) / dim2;
float_yb = (float) (i + 1) / dim1;
//float_yb = 1.0f - (float) (i + 1) / dim1;
float_xb = (float) (j + 1) / dim2;
gl.glNormal3fv(JOGLUtil.toArray(surface.getNormal(i, j)), 0);
gl.glTexCoord2f(float_x, float_y);
gl.glVertex3fv(JOGLUtil.toArray(surface.getTVertex(i, j)), 0);
gl.glNormal3fv(JOGLUtil.toArray(surface.getNormal(i + 1, j)), 0);
gl.glTexCoord2f(float_x, float_yb);
gl.glVertex3fv(JOGLUtil.toArray(surface.getTVertex(i + 1, j)), 0);
gl.glNormal3fv(JOGLUtil.toArray(surface.getNormal(i + 1, j + 1)), 0);
gl.glTexCoord2f(float_xb, float_yb);
gl.glVertex3fv(JOGLUtil.toArray(surface.getTVertex(i + 1, j + 1)), 0);
gl.glNormal3fv(JOGLUtil.toArray(surface.getNormal(i, j + 1)), 0);
gl.glTexCoord2f(float_xb, float_y);
gl.glVertex3fv(JOGLUtil.toArray(surface.getTVertex(i, j + 1)), 0);
}
}
gl.glEnd();
// Unbinding the texture
gl.glBindTexture(GL2.GL_TEXTURE_2D, 0);
}
if (lightEnabled && !surface.isUsingLight()) {
this.lighting.start(gl);
@ -3012,12 +3063,14 @@ public class Plot3DGL extends Plot implements GLEventListener {
TextureShape ishape = (TextureShape) graphic.getShape();
Texture texture = ishape.getTexture();
if (texture == null) {
try {
ishape.updateTexture(gl);
texture = ishape.getTexture();
/*try {
ishape.loadTexture();
texture = ishape.getTexture();
} catch (IOException ex) {
Logger.getLogger(Plot3DGL.class.getName()).log(Level.SEVERE, null, ex);
}
}*/
}
if (texture == null) {
return;
@ -3037,17 +3090,17 @@ public class Plot3DGL extends Plot implements GLEventListener {
// Draw image
gl.glBegin(GL2.GL_QUADS);
// Front Face
gl.glTexCoord2f(0.0f, 0.0f);
//gl.glTexCoord2f(0.0f, 1.0f);
gl.glVertex3f(transform.transform_x((float) coords.get(0).X), transform.transform_y((float) coords.get(0).Y), transform.transform_z((float) coords.get(0).Z));
gl.glTexCoord2f(1.0f, 0.0f);
//gl.glTexCoord2f(1.0f, 1.0f);
gl.glVertex3f(transform.transform_x((float) coords.get(1).X), transform.transform_y((float) coords.get(1).Y), transform.transform_z((float) coords.get(1).Z));
gl.glTexCoord2f(1.0f, 1.0f);
//gl.glTexCoord2f(1.0f, 0.0f);
gl.glVertex3f(transform.transform_x((float) coords.get(2).X), transform.transform_y((float) coords.get(2).Y), transform.transform_z((float) coords.get(2).Z));
gl.glTexCoord2f(0.0f, 1.0f);
//gl.glTexCoord2f(0.0f, 0.0f);
gl.glTexCoord2f(0.0f, 1.0f);
gl.glVertex3f(transform.transform_x((float) coords.get(0).X), transform.transform_y((float) coords.get(0).Y), transform.transform_z((float) coords.get(0).Z));
//gl.glTexCoord2f(1.0f, 0.0f);
gl.glTexCoord2f(1.0f, 1.0f);
gl.glVertex3f(transform.transform_x((float) coords.get(1).X), transform.transform_y((float) coords.get(1).Y), transform.transform_z((float) coords.get(1).Z));
//gl.glTexCoord2f(1.0f, 1.0f);
gl.glTexCoord2f(1.0f, 0.0f);
gl.glVertex3f(transform.transform_x((float) coords.get(2).X), transform.transform_y((float) coords.get(2).Y), transform.transform_z((float) coords.get(2).Z));
//gl.glTexCoord2f(0.0f, 1.0f);
gl.glTexCoord2f(0.0f, 0.0f);
gl.glVertex3f(transform.transform_x((float) coords.get(3).X), transform.transform_y((float) coords.get(3).Y), transform.transform_z((float) coords.get(3).Z));
gl.glEnd();
gl.glFlush();

View File

@ -5,8 +5,10 @@
*/
package org.meteoinfo.chart.shape;
import com.jogamp.opengl.GL2;
import com.jogamp.opengl.util.texture.Texture;
import com.jogamp.opengl.util.texture.TextureIO;
import com.jogamp.opengl.util.texture.awt.AWTTextureIO;
import org.meteoinfo.geometry.shape.ImageShape;
import org.meteoinfo.geometry.shape.ShapeTypes;
@ -81,4 +83,12 @@ public class TextureShape extends ImageShape{
public void loadTexture() throws IOException {
this.texture = TextureIO.newTexture(new File(fileName), true);
}
/**
* Update texture from image
* @param gl The JOGL GL2 object
*/
public void updateTexture(GL2 gl) {
this.texture = AWTTextureIO.newTexture(gl.getGLProfile(), this.image, true);
}
}

View File

@ -16,9 +16,9 @@ import java.util.List;
*/
public class ImageShape extends PointShape {
// <editor-fold desc="Variables">
private BufferedImage image;
private Object interp;
private List<PointZ> coords;
protected BufferedImage image;
protected Object interp;
protected List<PointZ> coords;
// </editor-fold>
// <editor-fold desc="Constructor">
/**

View File

@ -1,34 +1,36 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<MeteoInfo File="milconfig.xml" Type="configurefile">
<Path OpenPath="D:\Working\MIScript\Jython\mis\traj">
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\wind"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types"/>
<Path OpenPath="D:\Working\MIScript\Jython\mis\map\geoshow">
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\common_math"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\map\maskout"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\common_math\interpolate"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\io"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\map"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\image"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\io\geotiff"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\map\geoshow"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\traj\TrajStat"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\traj"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\satellite"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\satellite\calipso"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\image"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\map"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\map\geoshow"/>
</Path>
<File>
<OpenedFiles>
<OpenedFile File="D:\Working\MIScript\Jython\mis\toolbox\miml\deep_learning\classification\saturn.py"/>
<OpenedFile File="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\surf_breather.py"/>
<OpenedFile File="D:\Working\MIScript\Jython\mis\image\imread_3.py"/>
<OpenedFile File="D:\Working\MIScript\Jython\mis\map\geoshow\georead_1.py"/>
<OpenedFile File="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\surf_texturemap_1.py"/>
<OpenedFile File="D:\Working\MIScript\Jython\mis\satellite\calipso\CALIPSO_L2_AOD_3d_1.py"/>
<OpenedFile File="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\geoshow_image_2.py"/>
<OpenedFile File="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\geoshow_image_1.py"/>
</OpenedFiles>
<RecentFiles>
<RecentFile File="D:\Working\MIScript\Jython\mis\toolbox\miml\deep_learning\classification\saturn.py"/>
<RecentFile File="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\surf_breather.py"/>
<RecentFile File="D:\Working\MIScript\Jython\mis\image\imread_3.py"/>
<RecentFile File="D:\Working\MIScript\Jython\mis\map\geoshow\georead_1.py"/>
<RecentFile File="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\surf_texturemap_1.py"/>
<RecentFile File="D:\Working\MIScript\Jython\mis\satellite\calipso\CALIPSO_L2_AOD_3d_1.py"/>
<RecentFile File="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\geoshow_image_2.py"/>
<RecentFile File="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\geoshow_image_1.py"/>
</RecentFiles>
</File>
<Font>
@ -36,5 +38,5 @@
</Font>
<LookFeel DockWindowDecorated="true" LafDecorated="true" Name="FlatDarkLaf"/>
<Figure DoubleBuffering="true"/>
<Startup MainFormLocation="-7,0" MainFormSize="1434,778"/>
<Startup MainFormLocation="-7,-7" MainFormSize="1293,685"/>
</MeteoInfo>

View File

@ -12,10 +12,13 @@ from org.meteoinfo.geometry.legend import BreakTypes, BarBreak
from org.meteoinfo.geo.legend import LegendManage
from org.meteoinfo.geo.layer import LayerTypes
from org.meteoinfo.geometry.shape import ShapeTypes
from org.meteoinfo.geometry.graphic import Graphic, GraphicCollection
from org.meteoinfo.chart.jogl import Plot3DGL, GLForm, JOGLUtil
from org.meteoinfo.math.interpolate import InterpolationMethod
from org.meteoinfo.image import ImageUtil
from javax.swing import WindowConstants
from java.awt import Font, Color
from java.awt.image import BufferedImage
import os
import numbers
@ -91,6 +94,12 @@ class Axes3DGL(Axes3D):
aspect = kwargs.pop('aspect', None)
if not aspect is None:
self.axes.setAspectType(AspectType.valueOf(aspect.upper()))
axis = kwargs.pop('axis', True)
if not axis:
self.axes.setDrawBase(False)
self.axes.setBoxed(False)
self.axes.setDisplayXY(False)
self.axes.setDisplayZ(False)
def _set_plot(self, plot):
'''
@ -568,6 +577,7 @@ class Axes3DGL(Axes3D):
else:
interpolation = kwargs.pop('interpolation', None)
graphics = JOGLUtil.createTexture(layer, offset, xshift, interpolation)
#graphics = GraphicFactory.createImage(layer, offset, xshift, interpolation)
lighting = kwargs.pop('lighting', None)
if not lighting is None:
@ -1027,7 +1037,14 @@ class Axes3DGL(Axes3D):
if len(args) > 1:
level_arg = args[1]
else:
level_arg = C
level_arg = args[0]
facecolor = kwargs.pop('facecolor', None)
if facecolor == 'texturemap':
cdata = kwargs.pop('cdata')
if isinstance(cdata, NDArray) and cdata.ndim == 2:
min = cdata.min()
max = cdata.max()
if not level_arg is None:
if isinstance(level_arg, int):
@ -1044,12 +1061,25 @@ class Axes3DGL(Axes3D):
ls = LegendManage.createLegendScheme(min, max, cn, cmap)
ls = ls.convertTo(ShapeTypes.POLYGON)
facecolor = kwargs.pop('facecolor', None)
face_interp = None
image = None
if not facecolor is None:
face_interp = (facecolor == 'interp')
if not face_interp:
if not facecolor in ['flat','texturemap','none']:
if facecolor == 'texturemap':
if isinstance(cdata, NDArray):
if cdata.ndim == 3:
image = ImageUtil.createImage(cdata._array)
else:
image = GraphicFactory.createImage(cdata._array, ls)
elif isinstance(cdata, BufferedImage):
image = cdata
elif isinstance(cdata, GraphicCollection):
image = cdata.getGraphicN(0).getShape().getImage()
else:
image = cdata.getShape().getImage()
elif not facecolor in ['flat','none']:
facecolor = plotutil.getcolor(facecolor)
ls = LegendManage.createSingleSymbolLegendScheme(ShapeTypes.POLYGON, facecolor, 1)
plotutil.setlegendscheme(ls, **kwargs)
@ -1058,6 +1088,8 @@ class Axes3DGL(Axes3D):
else:
graphics = JOGLUtil.surface(x.asarray(), y.asarray(), z.asarray(), C.asarray(), ls)
if not image is None:
graphics.setImage(image)
if face_interp:
graphics.setFaceInterp(face_interp)
lighting = kwargs.pop('lighting', None)