From df767d471f982101fbc9af7d8c64268efde39994 Mon Sep 17 00:00:00 2001 From: wyq Date: Sat, 28 Jan 2023 22:57:57 +0800 Subject: [PATCH] update jogl scatter render --- .../java/org/meteoinfo/chart/jogl/GLPlot.java | 11 +- .../chart/render/jogl/PointRender.java | 140 +++++++++++++++++- .../org/meteoinfo/geo/layout/LayoutMap.java | 2 +- meteoinfo-lab/milconfig.xml | 36 ++--- .../pylib/mipylib/dataframe/index.py | 59 ++++---- .../pylib/mipylib/plotlib/_axes3dgl$py.class | Bin 90257 -> 90293 bytes .../pylib/mipylib/plotlib/_axes3dgl.py | 10 +- 7 files changed, 202 insertions(+), 56 deletions(-) diff --git a/meteoinfo-chart/src/main/java/org/meteoinfo/chart/jogl/GLPlot.java b/meteoinfo-chart/src/main/java/org/meteoinfo/chart/jogl/GLPlot.java index b8da5456..6300fc5b 100644 --- a/meteoinfo-chart/src/main/java/org/meteoinfo/chart/jogl/GLPlot.java +++ b/meteoinfo-chart/src/main/java/org/meteoinfo/chart/jogl/GLPlot.java @@ -2504,7 +2504,16 @@ public class GLPlot extends Plot { if (((GraphicCollection3D) graphic).isSphere()) { this.drawSpheres(gl, graphic); } else { - this.drawPoints(gl, graphic); + //this.drawPoints(gl, graphic); + if (!this.renderMap.containsKey(graphic)) { + renderMap.put(graphic, new PointRender(gl, (GraphicCollection3D) graphic)); + } + PointRender pointRender = (PointRender) renderMap.get(graphic); + pointRender.setTransform(this.transform, this.alwaysUpdateBuffers); + pointRender.setOrthographic(this.orthographic); + pointRender.setLighting(this.lighting); + pointRender.updateMatrix(); + pointRender.draw(); } break; case POLYLINE_Z: diff --git a/meteoinfo-chart/src/main/java/org/meteoinfo/chart/render/jogl/PointRender.java b/meteoinfo-chart/src/main/java/org/meteoinfo/chart/render/jogl/PointRender.java index d6f5c1eb..e45d5804 100644 --- a/meteoinfo-chart/src/main/java/org/meteoinfo/chart/render/jogl/PointRender.java +++ b/meteoinfo-chart/src/main/java/org/meteoinfo/chart/render/jogl/PointRender.java @@ -1,11 +1,35 @@ package org.meteoinfo.chart.render.jogl; +import com.jogamp.opengl.GL; import com.jogamp.opengl.GL2; +import com.jogamp.opengl.util.GLBuffers; import org.meteoinfo.chart.graphic.GraphicCollection3D; +import org.meteoinfo.chart.jogl.Program; +import org.meteoinfo.chart.jogl.Transform; +import org.meteoinfo.chart.jogl.Utils; +import org.meteoinfo.geometry.graphic.Graphic; +import org.meteoinfo.geometry.legend.*; +import org.meteoinfo.geometry.shape.PointZ; +import org.meteoinfo.geometry.shape.PointZShape; +import org.meteoinfo.geometry.shape.Polyline; +import org.meteoinfo.geometry.shape.PolylineZShape; + +import java.nio.FloatBuffer; +import java.nio.IntBuffer; +import java.util.ArrayList; +import java.util.List; public class PointRender extends JOGLGraphicRender { - private GraphicCollection3D pointGraphics; + private GraphicCollection3D graphics; + private IntBuffer vbo; + private Program program; + private int vertexNum; + private int sizePosition; + private int sizeColor; + private int sizeNormal; + private float[] vertexColor; + private float pointSize; /** * Constructor @@ -14,6 +38,15 @@ public class PointRender extends JOGLGraphicRender { */ public PointRender(GL2 gl) { super(gl); + + if (useShader) { + try { + this.compileShaders(); + } catch (Exception e) { + e.printStackTrace(); + } + } + initVertexBuffer(); } /** @@ -23,12 +56,113 @@ public class PointRender extends JOGLGraphicRender { * @param pointGraphics 3D point graphics */ public PointRender(GL2 gl, GraphicCollection3D pointGraphics) { - super(gl); - this.pointGraphics = pointGraphics; + this(gl); + + this.graphics = pointGraphics; + this.vertexNum = pointGraphics.getNumGraphics(); + PointBreak pb = (PointBreak) this.graphics.getGraphicN(0).getLegend(); + this.pointSize = pb.getSize(); + this.updateVertexColor(); + } + + void compileShaders() throws Exception { + String vertexShaderCode = Utils.loadResource("/shaders/surface/vertex.vert"); + String fragmentShaderCode = Utils.loadResource("/shaders/surface/surface.frag"); + program = new Program("surface", vertexShaderCode, fragmentShaderCode); + } + + private void initVertexBuffer() { + vbo = GLBuffers.newDirectIntBuffer(1); + } + + private void updateVertexColor() { + this.vertexColor = new float[this.vertexNum * 4]; + int i = 0; + float[] color; + for (Graphic graphic : this.graphics.getGraphics()) { + PointBreak pb = (PointBreak) graphic.getLegend(); + color = pb.getColor().getRGBComponents(null); + System.arraycopy(color, 0, vertexColor, i * 4, 4); + i++; + } + } + + private float[] getVertexPosition() { + float[] vertexData = new float[this.vertexNum * 3]; + int i = 0; + for (Graphic graphic : this.graphics.getGraphics()) { + PointZShape shape = (PointZShape) graphic.getShape(); + PointZ p = (PointZ) shape.getPoint(); + vertexData[i] = transform.transform_x((float) p.X); + vertexData[i + 1] = transform.transform_y((float) p.Y); + vertexData[i + 2] = transform.transform_z((float) p.Z); + i += 3; + } + + return vertexData; + } + + @Override + public void setTransform(Transform transform, boolean alwaysUpdateBuffers) { + boolean updateBuffer = true; + if (!alwaysUpdateBuffers && this.transform != null && this.transform.equals(transform)) + updateBuffer = false; + + super.setTransform((Transform) transform.clone()); + + if (updateBuffer) { + float[] vertexData = this.getVertexPosition(); + FloatBuffer vertexBuffer = GLBuffers.newDirectFloatBuffer(vertexData); + sizePosition = vertexBuffer.capacity() * Float.BYTES; + + FloatBuffer colorBuffer = GLBuffers.newDirectFloatBuffer(vertexColor); + sizeColor = colorBuffer.capacity() * Float.BYTES; + int totalSize = sizePosition + sizeColor; + + gl.glGenBuffers(1, vbo); + gl.glBindBuffer(GL.GL_ARRAY_BUFFER, vbo.get(0)); + gl.glBufferData(GL.GL_ARRAY_BUFFER, totalSize, null, GL.GL_STATIC_DRAW); + gl.glBufferSubData(GL.GL_ARRAY_BUFFER, 0, sizePosition, vertexBuffer); + gl.glBufferSubData(GL.GL_ARRAY_BUFFER, sizePosition, sizeColor, colorBuffer); + gl.glBindBuffer(GL.GL_ARRAY_BUFFER, 0); + } + } + + void setUniforms() { + } @Override public void draw() { + if (useShader) { // not working now + program.use(gl); + setUniforms(); + gl.glUseProgram(0); + } else { + gl.glBindBuffer(GL.GL_ARRAY_BUFFER, vbo.get(0)); + + // enable vertex arrays + gl.glEnableClientState(GL2.GL_VERTEX_ARRAY); + gl.glVertexPointer(3, GL.GL_FLOAT, 0, 0); + gl.glEnableClientState(GL2.GL_COLOR_ARRAY); + gl.glColorPointer(4, GL.GL_FLOAT, 0, sizePosition); + + boolean lightEnabled = this.lighting.isEnable(); + if (lightEnabled) { + this.lighting.stop(gl); + } + gl.glPointSize(this.pointSize * this.dpiScale); + gl.glDrawArrays(GL.GL_POINTS, 0, this.vertexNum); + + if (lightEnabled) { + this.lighting.start(gl); + } + + gl.glDisableClientState(GL2.GL_VERTEX_ARRAY); + gl.glDisableClientState(GL2.GL_COLOR_ARRAY); + + gl.glBindBuffer(GL.GL_ARRAY_BUFFER, 0); + } } } diff --git a/meteoinfo-geo/src/main/java/org/meteoinfo/geo/layout/LayoutMap.java b/meteoinfo-geo/src/main/java/org/meteoinfo/geo/layout/LayoutMap.java index 038930f6..7b2e2f5b 100644 --- a/meteoinfo-geo/src/main/java/org/meteoinfo/geo/layout/LayoutMap.java +++ b/meteoinfo-geo/src/main/java/org/meteoinfo/geo/layout/LayoutMap.java @@ -1326,7 +1326,7 @@ public class LayoutMap extends LayoutElement { } /** - * Set grid label positiont + * Set grid label position * * @param value Grid label position */ diff --git a/meteoinfo-lab/milconfig.xml b/meteoinfo-lab/milconfig.xml index 10f92a7d..a4155e49 100644 --- a/meteoinfo-lab/milconfig.xml +++ b/meteoinfo-lab/milconfig.xml @@ -1,32 +1,34 @@ - - - - - - - - - - + + + + + - - - - - + + + + + + + + + + - + + - + + diff --git a/meteoinfo-lab/pylib/mipylib/dataframe/index.py b/meteoinfo-lab/pylib/mipylib/dataframe/index.py index 075cf9fb..c324d6ff 100644 --- a/meteoinfo-lab/pylib/mipylib/dataframe/index.py +++ b/meteoinfo-lab/pylib/mipylib/dataframe/index.py @@ -1,9 +1,9 @@ -#----------------------------------------------------- +# ----------------------------------------------------- # Author: Yaqiang Wang # Date: 2018-7-18 # Purpose: MeteoInfo index module # Note: Jython -#----------------------------------------------------- +# ----------------------------------------------------- from org.meteoinfo.dataframe import Index as MIIndex from org.meteoinfo.dataframe import DateTimeIndex as MIDateTimeIndex @@ -15,8 +15,9 @@ import numbers import mipylib.numeric as np import mipylib.miutil as miutil + class Index(object): - + @staticmethod def factory(data=None, name='Index', index=None): """ @@ -32,7 +33,7 @@ class Index(object): return DateTimeIndex(index=index) else: return Index(index=index) - + def __init__(self, data=None, name='Index', index=None): """ Index @@ -57,22 +58,22 @@ class Index(object): @name.setter def name(self, value): self._index.setName(value) - + def __len__(self): return self._index.size() - + def __iter__(self): """ provide iteration over the values of the Index """ return iter(self._index) - + def __str__(self): return self.__repr__() - + def __repr__(self): return self._index.toString() - + def __getitem__(self, k): if isinstance(k, int): return self.data[k] @@ -82,17 +83,17 @@ class Index(object): sidx = self.__len__() + sidx eidx = self.__len__() if k.stop is None else k.stop if eidx < 0: - eidx = self.__len__() + eidx + eidx = self.__len__() + eidx step = 1 if k.step is None else k.step r = self._index.subIndex(sidx, eidx, step) return Index.factory(index=r) - + def __eq__(self, other): if isinstance(other, numbers.Number): return np.NDArray(self._index.equal(other)) else: return False - + def index(self, v): """ Get index of a value. @@ -120,14 +121,14 @@ class Index(object): r = self._index.getIndices(key.asarray()) else: r = self._index.getIndices(key) - if outkeys: + if outkeys: return list(r[0]), list(r[1]) else: return list(r[0]) - + def fill_keylist(self, rdata, rfdata): return self._index.fillKeyList(rdata.asarray(), rfdata) - + def get_format(self): """ Get value to string format. @@ -135,7 +136,7 @@ class Index(object): :returns: (*string*) Format string. """ return self._index.getFormat() - + def set_format(self, format): """ Set value to string format. @@ -143,10 +144,11 @@ class Index(object): :param format: (*string*) Format string. """ self._index.setFormat(format) - + + ############################################ class DateTimeIndex(Index): - + def __init__(self, data=None, name='Index', start=None, end=None, periods=None, freq='D', index=None): if index is None: if not data is None: @@ -169,7 +171,7 @@ class DateTimeIndex(Index): self._index = index self.data = miutil.pydate(list(self._index.getData())) self._index.setName(name) - + def index(self, v): """ Get index of a value. @@ -183,7 +185,7 @@ class DateTimeIndex(Index): else: v = miutil.str2jdate(v) return self._index.indexOf(v) - + def get_loc(self, key, outkeys=False): """ Get integer location, slice or boolean mask for requested label. @@ -201,11 +203,11 @@ class DateTimeIndex(Index): elif isinstance(key, (list, tuple, np.NDArray)) and isinstance(key[0], datetime.datetime): key = miutil.jdatetime(key) r = self._index.getIndices(key) - if outkeys: + if outkeys: return list(r[0]), list(r[1]) else: return list(r[0]) - + @property def year(self): """ @@ -213,7 +215,7 @@ class DateTimeIndex(Index): """ r = self._index.getYear() return Index(index=r) - + @property def month(self): """ @@ -221,7 +223,7 @@ class DateTimeIndex(Index): """ r = self._index.getMonth() return Index(index=r) - + @property def day(self): """ @@ -229,7 +231,7 @@ class DateTimeIndex(Index): """ r = self._index.getDay() return Index(index=r) - + @property def hour(self): """ @@ -237,7 +239,7 @@ class DateTimeIndex(Index): """ r = self._index.getHour() return Index(index=r) - + @property def minute(self): """ @@ -245,7 +247,7 @@ class DateTimeIndex(Index): """ r = self._index.getMinute() return Index(index=r) - + @property def second(self): """ @@ -254,7 +256,7 @@ class DateTimeIndex(Index): r = self._index.getSecond() return Index(index=r) - + ############################################# def date_range(start=None, end=None, periods=None, freq='D'): """ @@ -269,4 +271,3 @@ def date_range(start=None, end=None, periods=None, freq='D'): """ r = DateTimeIndex(start=start, end=end, periods=periods, freq=freq) return r - \ No newline at end of file diff --git a/meteoinfo-lab/pylib/mipylib/plotlib/_axes3dgl$py.class b/meteoinfo-lab/pylib/mipylib/plotlib/_axes3dgl$py.class index 8938f832fd4cc047d1aca8f2baefb9622e90fa52..babb2550acd071efcc3dadefb5a6a0bf445167ca 100644 GIT binary patch delta 10779 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 b{G_jUnWme18cT=tJ-w@rn^*5rr(6F7=c}vM delta 10803 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 Kv=dWRhV|c@D4rq! diff --git a/meteoinfo-lab/pylib/mipylib/plotlib/_axes3dgl.py b/meteoinfo-lab/pylib/mipylib/plotlib/_axes3dgl.py index 4bcdb2ff..9f310913 100644 --- a/meteoinfo-lab/pylib/mipylib/plotlib/_axes3dgl.py +++ b/meteoinfo-lab/pylib/mipylib/plotlib/_axes3dgl.py @@ -1599,16 +1599,16 @@ class EarthAxes3D(Axes3DGL): def __init__(self, *args, **kwargs): kwargs['aspect'] = 'equal' - if not kwargs.has_key('bgcolor'): + if 'bgcolor' not in kwargs.keys(): kwargs['bgcolor'] = 'k' kwargs['clip_plane'] = False kwargs['axis'] = False - if not kwargs.has_key('distance'): + if 'distance' not in kwargs.keys(): kwargs['distance'] = 500 super(EarthAxes3D, self).__init__(*args, **kwargs) image = kwargs.pop('image', 'world_topo.jpg') - if not image is None: + if image is not None: if not os.path.exists(image): image = os.path.join(migl.get_map_folder(), image) if os.path.exists(image): @@ -1650,7 +1650,7 @@ class EarthAxes3D(Axes3DGL): :return: Longitude and latitude lines. """ - nlon = (int)(360. / lon_delta) + nlon = int(360. / lon_delta) lons = np.zeros([nlon, npoints]) lats = np.zeros([nlon, npoints]) alts = np.zeros([nlon, npoints]) + offset @@ -1662,7 +1662,7 @@ class EarthAxes3D(Axes3DGL): idx += 1 self.plot(lons, lats, alts, **kwargs) - nlat = (int)(180. / lat_delta) + nlat = int(180. / lat_delta) lons = np.zeros([nlat, npoints]) lats = np.zeros([nlat, npoints]) alts = np.zeros([nlat, npoints]) + offset