mirror of
https://github.com/meteoinfo/MeteoInfo.git
synced 2025-12-08 20:36:05 +00:00
add ModelRender class
This commit is contained in:
parent
376df7f35d
commit
5c84f06d89
@ -8137,6 +8137,49 @@ public class GraphicFactory {
|
||||
return meshGraphic;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create model graphic
|
||||
*
|
||||
* @param faceIndices Vertex indices array
|
||||
* @param x X coordinates array
|
||||
* @param y Y coordinates array
|
||||
* @param z Z coordinates array
|
||||
* @param ls Legend scheme
|
||||
* @return
|
||||
*/
|
||||
public static Model model(Array faceIndices, Array x, Array y,
|
||||
Array z, LegendScheme ls) {
|
||||
Model model = new Model();
|
||||
model.setTriangles(faceIndices, x, y, z);
|
||||
model.setLegendScheme(ls);
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create model graphic
|
||||
*
|
||||
* @param faceIndices Vertex indices array
|
||||
* @param x X coordinates array
|
||||
* @param y Y coordinates array
|
||||
* @param z Z coordinates array
|
||||
* @param normal Normal array
|
||||
* @param ls Legend scheme
|
||||
* @return
|
||||
*/
|
||||
public static Model model(Array faceIndices, Array x, Array y,
|
||||
Array z, Array normal, LegendScheme ls) {
|
||||
if (normal == null) {
|
||||
return model(faceIndices, x, y, z, ls);
|
||||
}
|
||||
|
||||
Model model = new Model();
|
||||
model.setTriangles(faceIndices, x, y, z, normal);
|
||||
model.setLegendScheme(ls);
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create volume graphics
|
||||
*
|
||||
|
||||
@ -1,7 +1,13 @@
|
||||
package org.meteoinfo.chart.graphic;
|
||||
|
||||
public class Model {
|
||||
protected TriMeshGraphic triMeshGraphic;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class Model extends TriMeshGraphic {
|
||||
|
||||
protected Vector3f angle = new Vector3f();
|
||||
protected float scale = 1;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
@ -11,28 +17,43 @@ public class Model {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param triMeshGraphic Triangle mesh graphic
|
||||
* Get angle
|
||||
* @return The angle
|
||||
*/
|
||||
public Model(TriMeshGraphic triMeshGraphic) {
|
||||
this.triMeshGraphic = triMeshGraphic;
|
||||
public Vector3f getAngle() {
|
||||
return angle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get triangle mesh graphic
|
||||
* @return Triangle mesh graphic
|
||||
* Set angle
|
||||
* @param value Then angle
|
||||
*/
|
||||
public TriMeshGraphic getTriMeshGraphic() {
|
||||
return this.triMeshGraphic;
|
||||
public void setAngle(Vector3f value) {
|
||||
angle = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set triangle mesh graphic
|
||||
* @param value Triangle mesh graphic
|
||||
* Set angle
|
||||
* @param value The angle
|
||||
*/
|
||||
public void setTriMeshGraphic(TriMeshGraphic value) {
|
||||
this.triMeshGraphic = value;
|
||||
public void setAngle(List<Float> value) {
|
||||
angle = new Vector3f(value.get(0), value.get(1), value.get(2));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get scale
|
||||
* @return The scale
|
||||
*/
|
||||
public float getScale() {
|
||||
return scale;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set value
|
||||
* @param value The value
|
||||
*/
|
||||
public void setScale(float value) {
|
||||
scale = value;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -20,16 +20,16 @@ import java.util.logging.Logger;
|
||||
public class TriMeshGraphic extends GraphicCollection3D {
|
||||
|
||||
private Logger logger = Logger.getLogger("TriMeshGraphic");
|
||||
private float[] vertexPosition;
|
||||
private float[] vertexValue;
|
||||
private float[] vertexColor;
|
||||
private float[] vertexNormal;
|
||||
private int[] vertexIndices;
|
||||
protected float[] vertexPosition;
|
||||
protected float[] vertexValue;
|
||||
protected float[] vertexColor;
|
||||
protected float[] vertexNormal;
|
||||
protected int[] vertexIndices;
|
||||
//private LinkedHashMap<Integer, List<Integer>> triangleMap;
|
||||
private boolean faceInterp;
|
||||
private boolean edgeInterp;
|
||||
private boolean mesh;
|
||||
private boolean normalLoaded = false;
|
||||
protected boolean faceInterp;
|
||||
protected boolean edgeInterp;
|
||||
protected boolean mesh;
|
||||
protected boolean normalLoaded = false;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
|
||||
@ -9,7 +9,7 @@ import org.meteoinfo.chart.graphic.TriMeshGraphic;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class Cylinder extends Model {
|
||||
public class Cylinder {
|
||||
private float baseRadius;
|
||||
private float topRadius;
|
||||
private float height;
|
||||
@ -64,9 +64,9 @@ public class Cylinder extends Model {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void buildTriMeshGraphic() {
|
||||
this.triMeshGraphic = new TriMeshGraphic();
|
||||
|
||||
protected TriMeshGraphic buildTriMeshGraphic() {
|
||||
TriMeshGraphic triMeshGraphic = new TriMeshGraphic();
|
||||
int n = this.vertices.size();
|
||||
float[] vertexPosition = new float[n * 3];
|
||||
float[] vertexNormal = new float[n * 3];
|
||||
@ -82,9 +82,11 @@ public class Cylinder extends Model {
|
||||
vertexNormal[j + 2] = v.z;
|
||||
}
|
||||
int[] vertexIndices = this.indices.stream().mapToInt(Integer::intValue).toArray();
|
||||
this.triMeshGraphic.setVertexPosition(vertexPosition);
|
||||
this.triMeshGraphic.setVertexNormal(vertexNormal);
|
||||
this.triMeshGraphic.setVertexIndices(vertexIndices);
|
||||
triMeshGraphic.setVertexPosition(vertexPosition);
|
||||
triMeshGraphic.setVertexNormal(vertexNormal);
|
||||
triMeshGraphic.setVertexIndices(vertexIndices);
|
||||
|
||||
return triMeshGraphic;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -2518,6 +2518,18 @@ public class GLPlot extends Plot {
|
||||
pointRender.updateMatrix();
|
||||
pointRender.draw();
|
||||
} else if (graphic instanceof TriMeshGraphic) {
|
||||
if (graphic instanceof Model) {
|
||||
if (!this.renderMap.containsKey(graphic)) {
|
||||
renderMap.put(graphic, new ModelRender(gl, (Model) graphic));
|
||||
}
|
||||
ModelRender modelRender = (ModelRender) renderMap.get(graphic);
|
||||
modelRender.setTransform(this.transform, this.alwaysUpdateBuffers);
|
||||
modelRender.setOrthographic(this.orthographic);
|
||||
modelRender.setLighting(this.lighting);
|
||||
modelRender.updateMatrix();
|
||||
modelRender.setRotateModelView(this.modelViewMatrixR);
|
||||
modelRender.draw();
|
||||
} else {
|
||||
if (!this.renderMap.containsKey(graphic)) {
|
||||
renderMap.put(graphic, new TriMeshRender(gl, (TriMeshGraphic) graphic));
|
||||
}
|
||||
@ -2527,6 +2539,7 @@ public class GLPlot extends Plot {
|
||||
triMeshRender.setLighting(this.lighting);
|
||||
triMeshRender.updateMatrix();
|
||||
triMeshRender.draw();
|
||||
}
|
||||
} else if (graphic instanceof VolumeGraphic) {
|
||||
try {
|
||||
if (this.clipPlane)
|
||||
|
||||
@ -0,0 +1,245 @@
|
||||
package org.meteoinfo.chart.render.jogl;
|
||||
|
||||
import com.jogamp.common.nio.Buffers;
|
||||
import com.jogamp.opengl.GL;
|
||||
import com.jogamp.opengl.GL2;
|
||||
import com.jogamp.opengl.util.GLBuffers;
|
||||
import org.joml.Matrix4f;
|
||||
import org.joml.Vector3f;
|
||||
import org.joml.Vector4f;
|
||||
import org.meteoinfo.chart.graphic.Model;
|
||||
import org.meteoinfo.chart.graphic.TriMeshGraphic;
|
||||
import org.meteoinfo.chart.jogl.Program;
|
||||
import org.meteoinfo.chart.jogl.Transform;
|
||||
import org.meteoinfo.chart.jogl.Utils;
|
||||
import org.meteoinfo.geometry.legend.PolygonBreak;
|
||||
|
||||
import java.nio.FloatBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
|
||||
public class ModelRender extends JOGLGraphicRender {
|
||||
|
||||
private Model model;
|
||||
private IntBuffer vbo;
|
||||
//private IntBuffer vboNormal;
|
||||
private Program program;
|
||||
private float[] vertexPosition;
|
||||
private int sizePosition;
|
||||
private int sizeNormal;
|
||||
private int sizeColor;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param gl The JOGL GL2 object
|
||||
*/
|
||||
public ModelRender(GL2 gl) {
|
||||
super(gl);
|
||||
|
||||
useShader = false;
|
||||
if (useShader) {
|
||||
try {
|
||||
this.compileShaders();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
initVertexBuffer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param gl The opengl pipeline
|
||||
* @param model The model
|
||||
*/
|
||||
public ModelRender(GL2 gl, Model model) {
|
||||
this(gl);
|
||||
|
||||
this.model = model;
|
||||
this.setBufferData();
|
||||
}
|
||||
|
||||
private void initVertexBuffer() {
|
||||
vbo = GLBuffers.newDirectIntBuffer(2);
|
||||
}
|
||||
|
||||
private void setBufferData() {
|
||||
if (vertexPosition == null) {
|
||||
vertexPosition = model.getVertexPosition();
|
||||
}
|
||||
FloatBuffer vertexBuffer = GLBuffers.newDirectFloatBuffer(vertexPosition);
|
||||
if (model.getVertexNormal() == null) {
|
||||
model.calculateNormalVectors(vertexPosition);
|
||||
}
|
||||
FloatBuffer normalBuffer = GLBuffers.newDirectFloatBuffer(model.getVertexNormal());
|
||||
FloatBuffer colorBuffer = GLBuffers.newDirectFloatBuffer(model.getVertexColor());
|
||||
sizePosition = vertexBuffer.capacity() * Float.BYTES;
|
||||
sizeNormal = normalBuffer.capacity() * Float.BYTES;
|
||||
sizeColor = colorBuffer.capacity() * Float.BYTES;
|
||||
|
||||
gl.glGenBuffers(2, vbo);
|
||||
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, vbo.get(0));
|
||||
gl.glBufferData(GL.GL_ARRAY_BUFFER, sizePosition + sizeNormal + sizeColor, null, GL.GL_STATIC_DRAW);
|
||||
gl.glBufferSubData(GL.GL_ARRAY_BUFFER, 0, sizePosition, vertexBuffer);
|
||||
gl.glBufferSubData(GL.GL_ARRAY_BUFFER, sizePosition, sizeNormal, normalBuffer);
|
||||
gl.glBufferSubData(GL.GL_ARRAY_BUFFER, sizePosition + sizeNormal, sizeColor, colorBuffer);
|
||||
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, 0);
|
||||
|
||||
IntBuffer indexBuffer = GLBuffers.newDirectIntBuffer(model.getVertexIndices());
|
||||
gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, vbo.get(1));
|
||||
gl.glBufferData(GL.GL_ELEMENT_ARRAY_BUFFER, indexBuffer.capacity() * Integer.BYTES, indexBuffer, GL.GL_STATIC_DRAW);
|
||||
gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
@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 (alwaysUpdateBuffers) {
|
||||
setBufferData();
|
||||
}
|
||||
}
|
||||
|
||||
void compileShaders() throws Exception {
|
||||
String vertexShaderCode = Utils.loadResource("/shaders/mesh/vertex.vert");
|
||||
String fragmentShaderCode = Utils.loadResource("/shaders/mesh/mesh.frag");
|
||||
program = new Program("mesh", vertexShaderCode, fragmentShaderCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update shaders
|
||||
*/
|
||||
public void updateShaders() {
|
||||
if (program == null) {
|
||||
try {
|
||||
compileShaders();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setUniforms() {
|
||||
program.allocateUniform(gl, "matrixModelViewProjection", (gl2, loc) -> {
|
||||
gl2.glUniformMatrix4fv(loc, 1, false, this.viewProjMatrix.get(Buffers.newDirectFloatBuffer(16)));
|
||||
});
|
||||
program.allocateUniform(gl, "matrixModelView", (gl2, loc) -> {
|
||||
gl2.glUniformMatrix4fv(loc, 1, false, toMatrix(this.mvmatrix).get(Buffers.newDirectFloatBuffer(16)));
|
||||
});
|
||||
Matrix4f matrixNormal = toMatrix(this.mvmatrix);
|
||||
matrixNormal.setColumn(3, new Vector4f(0,0,0,1));
|
||||
program.allocateUniform(gl, "matrixNormal", (gl2, loc) -> {
|
||||
gl2.glUniformMatrix4fv(loc, 1, false, matrixNormal.get(Buffers.newDirectFloatBuffer(16)));
|
||||
});
|
||||
float[] rgba = model.getColor().getRGBComponents(null);
|
||||
program.allocateUniform(gl, "color", (gl2, loc) -> {
|
||||
gl2.glUniform4fv(loc, 1, rgba, 0);
|
||||
});
|
||||
program.allocateUniform(gl, "lightPosition", (gl2, loc) -> {
|
||||
gl2.glUniform4fv(loc, 1, lighting.getPosition(), 0);
|
||||
});
|
||||
program.allocateUniform(gl, "lightAmbient", (gl2, loc) -> {
|
||||
gl2.glUniform4fv(loc, 1, lighting.getAmbient(), 0);
|
||||
});
|
||||
program.allocateUniform(gl, "lightDiffuse", (gl2, loc) -> {
|
||||
gl2.glUniform4fv(loc, 1, lighting.getDiffuse(), 0);
|
||||
});
|
||||
program.allocateUniform(gl, "lightSpecular", (gl2, loc) -> {
|
||||
gl2.glUniform4fv(loc, 1, lighting.getSpecular(), 0);
|
||||
});
|
||||
|
||||
program.setUniforms(gl);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw() {
|
||||
gl.glPushMatrix();
|
||||
FloatBuffer fb = Buffers.newDirectFloatBuffer(16);
|
||||
Matrix4f modelView = new Matrix4f(this.modelViewMatrixR);
|
||||
modelView.scale(this.model.getScale());
|
||||
modelView.rotateXYZ(model.getAngle());
|
||||
gl.glLoadMatrixf(modelView.get(fb));
|
||||
|
||||
if (useShader) {
|
||||
program.use(gl);
|
||||
setUniforms();
|
||||
|
||||
int attribVertexPosition = gl.glGetAttribLocation(program.getProgramId(), "vertexPosition");
|
||||
int attribVertexNormal = gl.glGetAttribLocation(program.getProgramId(), "vertexNormal");
|
||||
|
||||
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, vbo.get(0));
|
||||
|
||||
gl.glEnableVertexAttribArray(attribVertexPosition);
|
||||
gl.glEnableVertexAttribArray(attribVertexNormal);
|
||||
|
||||
gl.glVertexAttribPointer(attribVertexPosition, 3, GL.GL_FLOAT, false, 0, 0);
|
||||
gl.glVertexAttribPointer(attribVertexNormal, 3, GL.GL_FLOAT, false, 0, vertexPosition.length * Float.BYTES);
|
||||
|
||||
gl.glDrawArrays(GL.GL_TRIANGLES, 0, model.getVertexNumber());
|
||||
|
||||
gl.glDisableVertexAttribArray(attribVertexPosition);
|
||||
gl.glDisableVertexAttribArray(attribVertexNormal);
|
||||
|
||||
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, 0);
|
||||
|
||||
gl.glUseProgram(0);
|
||||
} else {
|
||||
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, vbo.get(0));
|
||||
gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, vbo.get(1));
|
||||
|
||||
// enable vertex arrays
|
||||
gl.glEnableClientState(GL2.GL_NORMAL_ARRAY);
|
||||
gl.glEnableClientState(GL2.GL_VERTEX_ARRAY);
|
||||
gl.glNormalPointer(GL.GL_FLOAT, 0, sizePosition);
|
||||
gl.glVertexPointer(3, GL.GL_FLOAT, 0, 0);
|
||||
gl.glEnableClientState(GL2.GL_COLOR_ARRAY);
|
||||
gl.glColorPointer(4, GL.GL_FLOAT, 0, sizePosition + sizeNormal);
|
||||
|
||||
PolygonBreak pb = (PolygonBreak) model.getLegendScheme().getLegendBreak(0);
|
||||
if (pb.isDrawFill()) {
|
||||
gl.glEnable(GL2.GL_POLYGON_OFFSET_FILL);
|
||||
gl.glPolygonOffset(1.0f, 1.0f);
|
||||
if (model.isFaceInterp()) {
|
||||
gl.glDrawElements(GL2.GL_TRIANGLES, model.getVertexIndices().length, GL.GL_UNSIGNED_INT, 0);
|
||||
} else {
|
||||
gl.glShadeModel(GL2.GL_FLAT);
|
||||
gl.glDrawElements(GL2.GL_TRIANGLES, model.getVertexIndices().length, GL.GL_UNSIGNED_INT, 0);
|
||||
gl.glShadeModel(GL2.GL_SMOOTH);
|
||||
}
|
||||
}
|
||||
if (pb.isDrawOutline()) {
|
||||
boolean lightEnabled = this.lighting.isEnable();
|
||||
if (lightEnabled) {
|
||||
this.lighting.stop(gl);
|
||||
}
|
||||
gl.glLineWidth(pb.getOutlineSize() * this.dpiScale);
|
||||
if (!model.isMesh()) {
|
||||
gl.glDisableClientState(GL2.GL_COLOR_ARRAY);
|
||||
float[] rgba = pb.getOutlineColor().getRGBComponents(null);
|
||||
gl.glColor4fv(rgba, 0);
|
||||
}
|
||||
gl.glPolygonMode(GL.GL_FRONT_AND_BACK, GL2.GL_LINE);
|
||||
//gl.glDrawArrays(GL.GL_TRIANGLES, 0, meshGraphic.getVertexNumber());
|
||||
gl.glDrawElements(GL.GL_TRIANGLES, model.getVertexIndices().length, GL.GL_UNSIGNED_INT, 0);
|
||||
gl.glPolygonMode(GL.GL_FRONT_AND_BACK, GL2.GL_FILL);
|
||||
if (lightEnabled) {
|
||||
this.lighting.start(gl);
|
||||
}
|
||||
}
|
||||
|
||||
gl.glDisableClientState(GL2.GL_NORMAL_ARRAY);
|
||||
gl.glDisableClientState(GL2.GL_VERTEX_ARRAY);
|
||||
gl.glDisableClientState(GL2.GL_COLOR_ARRAY);
|
||||
|
||||
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, 0);
|
||||
gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
gl.glPopMatrix();
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user