update jogl scatter render

This commit is contained in:
wyq 2023-01-28 22:57:57 +08:00
parent 788ae3d51f
commit df767d471f
7 changed files with 202 additions and 56 deletions

View File

@ -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:

View File

@ -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);
}
}
}

View File

@ -1326,7 +1326,7 @@ public class LayoutMap extends LayoutElement {
}
/**
* Set grid label positiont
* Set grid label position
*
* @param value Grid label position
*/

View File

@ -1,32 +1,34 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<MeteoInfo File="milconfig.xml" Type="configurefile">
<Path OpenPath="D:\Working\MIScript\Jython\mis\io\dataconvert">
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\annotate"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\arrow"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\bar"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\boxplot"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\toolbox"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\common_math"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\common_math\stats"/>
<Path OpenPath="D:\Working\MIScript\Jython\mis\dataframe">
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\isosurface"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\particles"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\scatter"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\model"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\funny"/>
<RecentFolder Folder="D:\MyProgram\java\MeteoInfoDev\toolbox\EMIPS\emips\gui"/>
<RecentFolder Folder="D:\MyProgram\java\MeteoInfoDev\toolbox\EMIPS\emips"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\toolbox\emips"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\io"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\io\dataconvert"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\surf"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\map"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\map\geoshow"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\3d_earth"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\pie"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\dataframe"/>
</Path>
<File>
<OpenedFiles>
<OpenedFile File="D:\MyProgram\java\MeteoInfoDev\toolbox\EMIPS\emips\gui\main_gui.py"/>
<OpenedFile File="D:\MyProgram\java\MeteoInfoDev\toolbox\EMIPS\emips\gui\_reload.py"/>
<OpenedFile File="D:\MyProgram\java\MeteoInfoDev\toolbox\EMIPS\emips\gui\emission_panel.py"/>
<OpenedFile File="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\scatter\scatter3_4.py"/>
<OpenedFile File="D:\Working\MIScript\Jython\mis\dataframe\dataframe_groupby_3.py"/>
</OpenedFiles>
<RecentFiles>
<RecentFile File="D:\MyProgram\java\MeteoInfoDev\toolbox\EMIPS\emips\gui\main_gui.py"/>
<RecentFile File="D:\MyProgram\java\MeteoInfoDev\toolbox\EMIPS\emips\gui\_reload.py"/>
<RecentFile File="D:\MyProgram\java\MeteoInfoDev\toolbox\EMIPS\emips\gui\emission_panel.py"/>
<RecentFile File="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\scatter\scatter3_4.py"/>
<RecentFile File="D:\Working\MIScript\Jython\mis\dataframe\dataframe_groupby_3.py"/>
</RecentFiles>
</File>
<Font>

View File

@ -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

View File

@ -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