mirror of https://github.com/rusefi/jzy3d-api.git
added Scatter VBO, with List<Coord3d> data loader
This commit is contained in:
parent
b476382b9d
commit
5eec39a1b4
|
@ -1,6 +1,8 @@
|
||||||
package org.jzy3d.maths;
|
package org.jzy3d.maths;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link Coord3d} stores a 3 dimensional coordinate for cartesian or polar
|
* A {@link Coord3d} stores a 3 dimensional coordinate for cartesian or polar
|
||||||
|
@ -14,6 +16,23 @@ import java.io.Serializable;
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class Coord3d implements Serializable{
|
public class Coord3d implements Serializable{
|
||||||
|
public static List<Coord3d> list(int size){
|
||||||
|
return new ArrayList<Coord3d>(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Range getZRange(List<Coord3d> coords) {
|
||||||
|
float min = Float.POSITIVE_INFINITY;
|
||||||
|
float max = Float.NEGATIVE_INFINITY;
|
||||||
|
|
||||||
|
for(Coord3d c: coords){
|
||||||
|
if(c.z>max)
|
||||||
|
max = c.z;
|
||||||
|
if(c.z<min)
|
||||||
|
min = c.z;
|
||||||
|
}
|
||||||
|
return new Range(min, max);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/** The origin is a Coord3d having value 0 for each dimension. */
|
/** The origin is a Coord3d having value 0 for each dimension. */
|
||||||
public static final Coord3d ORIGIN = new Coord3d(0.0f, 0.0f, 0.0f);
|
public static final Coord3d ORIGIN = new Coord3d(0.0f, 0.0f, 0.0f);
|
||||||
|
|
|
@ -13,215 +13,285 @@ import org.apache.log4j.Logger;
|
||||||
import org.jzy3d.colors.Color;
|
import org.jzy3d.colors.Color;
|
||||||
import org.jzy3d.io.IGLLoader;
|
import org.jzy3d.io.IGLLoader;
|
||||||
import org.jzy3d.maths.BoundingBox3d;
|
import org.jzy3d.maths.BoundingBox3d;
|
||||||
|
import org.jzy3d.maths.Coord3d;
|
||||||
import org.jzy3d.plot3d.primitives.AbstractDrawable;
|
import org.jzy3d.plot3d.primitives.AbstractDrawable;
|
||||||
import org.jzy3d.plot3d.primitives.IGLBindedResource;
|
import org.jzy3d.plot3d.primitives.IGLBindedResource;
|
||||||
import org.jzy3d.plot3d.rendering.compat.GLES2CompatUtils;
|
import org.jzy3d.plot3d.rendering.compat.GLES2CompatUtils;
|
||||||
import org.jzy3d.plot3d.rendering.view.Camera;
|
import org.jzy3d.plot3d.rendering.view.Camera;
|
||||||
|
import org.jzy3d.plot3d.transform.Rotate;
|
||||||
|
import org.jzy3d.plot3d.transform.Rotator;
|
||||||
import org.jzy3d.plot3d.transform.Transform;
|
import org.jzy3d.plot3d.transform.Transform;
|
||||||
|
|
||||||
import com.jogamp.common.nio.Buffers;
|
import com.jogamp.common.nio.Buffers;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link DrawableVBO} is able to efficiently draw a large collection of geometries.
|
* A {@link DrawableVBO} is able to efficiently draw a large collection of
|
||||||
|
* geometries.
|
||||||
|
*
|
||||||
|
* The user must provide a loader that will be later called when the GL context
|
||||||
|
* requires loading the VBO data in GPU memory.
|
||||||
|
*
|
||||||
|
* The loader might freely make settings on the drawable as it is called with a
|
||||||
|
* reference to the {@link DrawableVBO} is will be loading data into.
|
||||||
|
*
|
||||||
|
* One can separate data and appearance by setting geometry settings out of
|
||||||
|
* loading process.
|
||||||
|
*
|
||||||
|
* DrawableVBO shape1 = new DrawableVBO(new MemoryVBOLoader(getScatter(size)));
|
||||||
|
* shape1.setGeometry(GL.GL_POINTS); shape1.setColor(Color.WHITE);
|
||||||
*
|
*
|
||||||
* @author Martin Pernollet
|
* @author Martin Pernollet
|
||||||
*/
|
*/
|
||||||
public class DrawableVBO extends AbstractDrawable implements IGLBindedResource {
|
public class DrawableVBO extends AbstractDrawable implements IGLBindedResource {
|
||||||
public DrawableVBO(IGLLoader<DrawableVBO> loader) {
|
protected int geometry = GL.GL_TRIANGLES;
|
||||||
this.loader = loader;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
protected int colorChannelNumber = 3;
|
||||||
|
|
||||||
|
public DrawableVBO(IGLLoader<DrawableVBO> loader) {
|
||||||
|
this.loader = loader;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean hasMountedOnce() {
|
public boolean hasMountedOnce() {
|
||||||
return hasMountedOnce;
|
return hasMountedOnce;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// element array buffer is an index:
|
// element array buffer is an index:
|
||||||
// @see
|
// @see
|
||||||
// http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-9-vbo-indexing/
|
// http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-9-vbo-indexing/
|
||||||
@Override
|
@Override
|
||||||
public void draw(GL gl, GLU glu, Camera cam) {
|
public void draw(GL gl, GLU glu, Camera cam) {
|
||||||
if (hasMountedOnce) {
|
if (hasMountedOnce) {
|
||||||
doTransform(gl, glu, cam);
|
doTransform(gl, glu, cam);
|
||||||
configure(gl);
|
configure(gl);
|
||||||
doDrawElements(gl);
|
doDrawElements(gl);
|
||||||
doDrawBounds(gl, glu, cam);
|
doDrawBounds(gl, glu, cam);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* rotate around Z axis
|
||||||
|
*/
|
||||||
|
public Rotator rotator(boolean start) {
|
||||||
|
final Rotate r = new Rotate(25, new Coord3d(0, 0, 1));
|
||||||
|
Transform t = new Transform();
|
||||||
|
t.add(r);
|
||||||
|
setTransformBefore(t);
|
||||||
|
Rotator rotator = new Rotator(10, r);
|
||||||
|
if(start)
|
||||||
|
rotator.start();
|
||||||
|
return rotator;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* An OBJ file appears to be really really slow to render without a
|
|
||||||
* FRONT_AND_BACK spec, probably because such a big polygon set has huge
|
|
||||||
* cost to have culling status computed (culling enabled by depth peeling).
|
|
||||||
*/
|
|
||||||
protected void configure(GL gl) {
|
|
||||||
// gl.glPolygonMode(GL2.GL_FRONT, GL2.GL_FILL);
|
|
||||||
// gl.glPolygonMode(GL2.GL_FRONT, GL2.GL_LINE);
|
|
||||||
// gl.glColor4f(1f,0f,1f,0.6f);
|
|
||||||
// gl.glLineWidth(0.00001f);
|
|
||||||
if (gl.isGL2()) {
|
|
||||||
gl.getGL2().glPolygonMode(GL.GL_FRONT_AND_BACK, GL2GL3.GL_FILL);
|
|
||||||
} else {
|
|
||||||
GLES2CompatUtils.glPolygonMode(GL.GL_FRONT_AND_BACK,
|
|
||||||
GL2GL3.GL_FILL);
|
|
||||||
}
|
|
||||||
call(gl, color);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void doDrawElements(GL gl) {
|
/*
|
||||||
if (gl.isGL2()) {
|
* An OBJ file appears to be really really slow to render without a
|
||||||
gl.getGL2().glBindBuffer(GL.GL_ARRAY_BUFFER, arrayName[0]);
|
* FRONT_AND_BACK spec, probably because such a big polygon set has huge
|
||||||
gl.getGL2().glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, elementName[0]);
|
* cost to have culling status computed (culling enabled by depth peeling).
|
||||||
|
*/
|
||||||
|
protected void configure(GL gl) {
|
||||||
|
// gl.glPolygonMode(GL2.GL_FRONT, GL2.GL_FILL);
|
||||||
|
// gl.glPolygonMode(GL2.GL_FRONT, GL2.GL_LINE);
|
||||||
|
// gl.glColor4f(1f,0f,1f,0.6f);
|
||||||
|
// gl.glLineWidth(0.00001f);
|
||||||
|
if (gl.isGL2()) {
|
||||||
|
gl.getGL2().glPolygonMode(GL.GL_FRONT_AND_BACK, GL2GL3.GL_FILL);
|
||||||
|
} else {
|
||||||
|
GLES2CompatUtils.glPolygonMode(GL.GL_FRONT_AND_BACK, GL2GL3.GL_FILL);
|
||||||
|
}
|
||||||
|
call(gl, color);
|
||||||
|
}
|
||||||
|
|
||||||
gl.getGL2().glVertexPointer(dimensions, GL.GL_FLOAT, byteOffset, pointer);
|
boolean hasColorBuffer = false;
|
||||||
gl.getGL2().glNormalPointer(GL.GL_FLOAT, byteOffset, normalOffset);
|
|
||||||
gl.getGL2().glEnableClientState(GLPointerFunc.GL_VERTEX_ARRAY);
|
|
||||||
gl.getGL2().glEnableClientState(GLPointerFunc.GL_NORMAL_ARRAY);
|
|
||||||
|
|
||||||
gl.getGL2().glDrawElements(getGeometry(), size, GL.GL_UNSIGNED_INT, pointer);
|
|
||||||
|
|
||||||
|
public boolean isHasColorBuffer() {
|
||||||
|
return hasColorBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
gl.getGL2().glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, elementName[0]);
|
public void setHasColorBuffer(boolean hasColorBuffer) {
|
||||||
gl.getGL2().glBindBuffer(GL.GL_ARRAY_BUFFER, arrayName[0]);
|
this.hasColorBuffer = hasColorBuffer;
|
||||||
gl.getGL2().glDisableClientState(GLPointerFunc.GL_VERTEX_ARRAY);
|
}
|
||||||
gl.getGL2().glDisableClientState(GLPointerFunc.GL_NORMAL_ARRAY);
|
|
||||||
} else {
|
|
||||||
GLES2CompatUtils.glBindBuffer(GL.GL_ARRAY_BUFFER, arrayName[0]);
|
|
||||||
GLES2CompatUtils.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, elementName[0]);
|
|
||||||
|
|
||||||
GLES2CompatUtils.glVertexPointer(dimensions, GL.GL_FLOAT, byteOffset, pointer);
|
protected void doDrawElements(GL gl) {
|
||||||
GLES2CompatUtils.glNormalPointer(GL.GL_FLOAT, byteOffset, normalOffset);
|
if (gl.isGL2()) {
|
||||||
GLES2CompatUtils.glEnableClientState(GLPointerFunc.GL_VERTEX_ARRAY);
|
doBindGL2(gl);
|
||||||
GLES2CompatUtils.glEnableClientState(GLPointerFunc.GL_NORMAL_ARRAY);
|
|
||||||
|
|
||||||
GLES2CompatUtils.glDrawElements(getGeometry(), size, GL.GL_UNSIGNED_INT, pointer);
|
gl.getGL2().glVertexPointer(dimensions, GL.GL_FLOAT, byteOffset, pointer);
|
||||||
|
gl.getGL2().glNormalPointer(GL.GL_FLOAT, byteOffset, normalOffset);
|
||||||
|
|
||||||
GLES2CompatUtils.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, elementName[0]);
|
if (hasColorBuffer) {
|
||||||
GLES2CompatUtils.glBindBuffer(GL.GL_ARRAY_BUFFER, arrayName[0]);
|
// int bo = 6 * Buffers.SIZEOF_FLOAT;
|
||||||
GLES2CompatUtils.glEnableClientState(GLPointerFunc.GL_VERTEX_ARRAY);
|
int p = 3 * Buffers.SIZEOF_FLOAT;
|
||||||
GLES2CompatUtils.glEnableClientState(GLPointerFunc.GL_NORMAL_ARRAY);
|
gl.getGL2().glEnableClientState(GL2.GL_COLOR_ARRAY);
|
||||||
}
|
gl.getGL2().glColorPointer(colorChannelNumber, GL.GL_FLOAT, byteOffset, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected int getGeometry() {
|
// enable
|
||||||
return GL.GL_TRIANGLES;
|
gl.getGL2().glEnableClientState(GLPointerFunc.GL_VERTEX_ARRAY);
|
||||||
}
|
gl.getGL2().glEnableClientState(GLPointerFunc.GL_NORMAL_ARRAY);
|
||||||
|
|
||||||
@Override
|
// draw
|
||||||
|
gl.getGL2().glDrawElements(getGeometry(), size, GL.GL_UNSIGNED_INT, pointer);
|
||||||
|
|
||||||
|
doBindGL2(gl);
|
||||||
|
|
||||||
|
// disable
|
||||||
|
gl.getGL2().glDisableClientState(GLPointerFunc.GL_VERTEX_ARRAY);
|
||||||
|
gl.getGL2().glDisableClientState(GLPointerFunc.GL_NORMAL_ARRAY);
|
||||||
|
|
||||||
|
if (hasColorBuffer) {
|
||||||
|
gl.getGL2().glDisableClientState(GL2.GL_COLOR_ARRAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
GLES2CompatUtils.glBindBuffer(GL.GL_ARRAY_BUFFER, arrayName[0]);
|
||||||
|
GLES2CompatUtils.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, elementName[0]);
|
||||||
|
|
||||||
|
GLES2CompatUtils.glVertexPointer(dimensions, GL.GL_FLOAT, byteOffset, pointer);
|
||||||
|
GLES2CompatUtils.glNormalPointer(GL.GL_FLOAT, byteOffset, normalOffset);
|
||||||
|
GLES2CompatUtils.glEnableClientState(GLPointerFunc.GL_VERTEX_ARRAY);
|
||||||
|
GLES2CompatUtils.glEnableClientState(GLPointerFunc.GL_NORMAL_ARRAY);
|
||||||
|
|
||||||
|
GLES2CompatUtils.glDrawElements(getGeometry(), size, GL.GL_UNSIGNED_INT, pointer);
|
||||||
|
|
||||||
|
GLES2CompatUtils.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, elementName[0]);
|
||||||
|
GLES2CompatUtils.glBindBuffer(GL.GL_ARRAY_BUFFER, arrayName[0]);
|
||||||
|
GLES2CompatUtils.glEnableClientState(GLPointerFunc.GL_VERTEX_ARRAY);
|
||||||
|
GLES2CompatUtils.glEnableClientState(GLPointerFunc.GL_NORMAL_ARRAY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doBindGL2(GL gl) {
|
||||||
|
gl.getGL2().glBindBuffer(GL.GL_ARRAY_BUFFER, arrayName[0]);
|
||||||
|
gl.getGL2().glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, elementName[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getGeometry() {
|
||||||
|
return geometry;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set geometry, use: GL.GL_TRIANGLES (default) ...
|
||||||
|
*
|
||||||
|
* @param geometry
|
||||||
|
*/
|
||||||
|
public void setGeometry(int geometry) {
|
||||||
|
this.geometry = geometry;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void applyGeometryTransform(Transform transform) {
|
public void applyGeometryTransform(Transform transform) {
|
||||||
/*
|
/*
|
||||||
* Coord3d c = transform.compute(new Coord3d(x,y, z)); x = c.x; y = c.y;
|
* Coord3d c = transform.compute(new Coord3d(x,y, z)); x = c.x; y = c.y;
|
||||||
* z = c.z;
|
* z = c.z;
|
||||||
*/
|
*/
|
||||||
Logger.getLogger(DrawableVBO.class).warn("not implemented");
|
Logger.getLogger(DrawableVBO.class).warn("not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateBounds() { // requires smart reload
|
public void updateBounds() { // requires smart reload
|
||||||
Logger.getLogger(DrawableVBO.class).warn("not implemented");
|
Logger.getLogger(DrawableVBO.class).warn("not implemented");
|
||||||
/*
|
/*
|
||||||
* bbox.reset(); bbox.add(x+Math.max(radiusBottom, radiusTop),
|
* bbox.reset(); bbox.add(x+Math.max(radiusBottom, radiusTop),
|
||||||
* y+Math.max(radiusBottom, radiusTop), z);
|
* y+Math.max(radiusBottom, radiusTop), z);
|
||||||
* bbox.add(x-Math.max(radiusBottom, radiusTop),
|
* bbox.add(x-Math.max(radiusBottom, radiusTop),
|
||||||
* y-Math.max(radiusBottom, radiusTop), z);
|
* y-Math.max(radiusBottom, radiusTop), z);
|
||||||
* bbox.add(x+Math.max(radiusBottom, radiusTop),
|
* bbox.add(x+Math.max(radiusBottom, radiusTop),
|
||||||
* y+Math.max(radiusBottom, radiusTop), z+height);
|
* y+Math.max(radiusBottom, radiusTop), z+height);
|
||||||
* bbox.add(x-Math.max(radiusBottom, radiusTop),
|
* bbox.add(x-Math.max(radiusBottom, radiusTop),
|
||||||
* y-Math.max(radiusBottom, radiusTop), z+height);
|
* y-Math.max(radiusBottom, radiusTop), z+height);
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
/* IO */
|
/* IO */
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mount(GL gl) {
|
public void mount(GL gl) {
|
||||||
try {
|
try {
|
||||||
loader.load(gl, this);
|
loader.load(gl, this);
|
||||||
hasMountedOnce = true;
|
hasMountedOnce = true;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Logger.getLogger(DrawableVBO.class).error(e, e);
|
Logger.getLogger(DrawableVBO.class).error(e, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setData(GL gl, IntBuffer indices, FloatBuffer vertices,
|
public void setData(GL gl, IntBuffer indices, FloatBuffer vertices, BoundingBox3d bounds) {
|
||||||
BoundingBox3d bounds) {
|
setData(gl.getGL2(), indices, vertices, bounds, 0);
|
||||||
setData(gl.getGL2(), indices, vertices, bounds, 0);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public void setData(GL2 gl, IntBuffer indices, FloatBuffer vertices,
|
public void setData(GL2 gl, IntBuffer indices, FloatBuffer vertices, BoundingBox3d bounds, int pointer) {
|
||||||
BoundingBox3d bounds, int pointer) {
|
doConfigure(pointer, indices.capacity());
|
||||||
doConfigure(pointer, indices.capacity());
|
doLoadArrayBuffer(gl, vertices);
|
||||||
doLoadArrayBuffer(gl, vertices);
|
doLoadElementBuffer(gl, indices);
|
||||||
doLoadElementBuffer(gl, indices);
|
doSetBoundingBox(bounds);
|
||||||
doSetBoundingBox(bounds);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public void doConfigure(int pointer, int size) {
|
public void doConfigure(int pointer, int size) {
|
||||||
int dimensions = 3;
|
int dimensions = 3;
|
||||||
int byteOffset = (dimensions * 2) * Buffers.SIZEOF_FLOAT; // (coord+normal)
|
int byteOffset = (dimensions * 2) * Buffers.SIZEOF_FLOAT; // (coord+normal)
|
||||||
int normalOffset = dimensions * Buffers.SIZEOF_FLOAT;
|
int normalOffset = dimensions * Buffers.SIZEOF_FLOAT;
|
||||||
doConfigure(pointer, size, byteOffset, normalOffset, dimensions);
|
doConfigure(pointer, size, byteOffset, normalOffset, dimensions);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void doConfigure(int pointer, int size, int byteOffset,
|
public void doConfigure(int pointer, int size, int byteOffset, int normalOffset, int dimensions) {
|
||||||
int normalOffset, int dimensions) {
|
this.byteOffset = byteOffset;
|
||||||
this.byteOffset = byteOffset;
|
this.normalOffset = normalOffset;
|
||||||
this.normalOffset = normalOffset;
|
this.dimensions = dimensions;
|
||||||
this.dimensions = dimensions;
|
this.size = size;
|
||||||
this.size = size;
|
this.pointer = pointer;
|
||||||
this.pointer = pointer;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public void doLoadArrayBuffer(GL gl, FloatBuffer vertices) {
|
public void doLoadArrayBuffer(GL gl, FloatBuffer vertices) {
|
||||||
doLoadArrayBuffer(gl, vertices.capacity() * Buffers.SIZEOF_FLOAT,
|
doLoadArrayBuffer(gl, vertices.capacity() * Buffers.SIZEOF_FLOAT, vertices);
|
||||||
vertices);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public void doLoadArrayBuffer(GL gl, int vertexSize, FloatBuffer vertices) {
|
public void doLoadArrayBuffer(GL gl, int vertexSize, FloatBuffer vertices) {
|
||||||
gl.glGenBuffers(1, arrayName, 0);
|
gl.glGenBuffers(1, arrayName, 0);
|
||||||
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, arrayName[0]);
|
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, arrayName[0]);
|
||||||
gl.glBufferData(GL.GL_ARRAY_BUFFER, vertexSize, vertices,
|
gl.glBufferData(GL.GL_ARRAY_BUFFER, vertexSize, vertices, GL.GL_STATIC_DRAW);
|
||||||
GL.GL_STATIC_DRAW);
|
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, pointer);
|
||||||
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, pointer);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public void doLoadElementBuffer(GL gl, IntBuffer indices) {
|
public void doLoadElementBuffer(GL gl, IntBuffer indices) {
|
||||||
doLoadElementBuffer(gl, indices.capacity() * Buffers.SIZEOF_INT,
|
doLoadElementBuffer(gl, indices.capacity() * Buffers.SIZEOF_INT, indices);
|
||||||
indices);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public void doLoadElementBuffer(GL gl, int indexSize, IntBuffer indices) {
|
public void doLoadElementBuffer(GL gl, int indexSize, IntBuffer indices) {
|
||||||
gl.glGenBuffers(1, elementName, 0);
|
gl.glGenBuffers(1, elementName, 0);
|
||||||
gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, elementName[0]);
|
gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, elementName[0]);
|
||||||
gl.glBufferData(GL.GL_ELEMENT_ARRAY_BUFFER, indexSize, indices,
|
gl.glBufferData(GL.GL_ELEMENT_ARRAY_BUFFER, indexSize, indices, GL.GL_STATIC_DRAW);
|
||||||
GL.GL_STATIC_DRAW);
|
gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, pointer);
|
||||||
gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, pointer);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public void doSetBoundingBox(BoundingBox3d bounds) {
|
public void doSetBoundingBox(BoundingBox3d bounds) {
|
||||||
bbox = bounds;
|
bbox = bounds;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* */
|
/* */
|
||||||
|
|
||||||
public Color getColor() {
|
public Color getColor() {
|
||||||
return color;
|
return color;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setColor(Color color) {
|
public void setColor(Color color) {
|
||||||
this.color = color;
|
this.color = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected IGLLoader<DrawableVBO> loader;
|
protected IGLLoader<DrawableVBO> loader;
|
||||||
|
|
||||||
protected int byteOffset;
|
protected int byteOffset;
|
||||||
protected int normalOffset;
|
protected int normalOffset;
|
||||||
protected int dimensions;
|
protected int dimensions;
|
||||||
protected int size;
|
protected int size;
|
||||||
protected int pointer;
|
protected int pointer;
|
||||||
|
|
||||||
protected int arrayName[] = new int[1];
|
protected int arrayName[] = new int[1];
|
||||||
protected int elementName[] = new int[1];
|
protected int elementName[] = new int[1];
|
||||||
|
|
||||||
protected boolean hasMountedOnce = false;
|
protected boolean hasMountedOnce = false;
|
||||||
protected Color color = new Color(1f, 0f, 1f, 0.75f);
|
protected Color color = new Color(1f, 0f, 1f, 0.75f);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,131 @@
|
||||||
|
package org.jzy3d.plot3d.primitives.vbo;
|
||||||
|
|
||||||
|
import java.nio.FloatBuffer;
|
||||||
|
import java.nio.IntBuffer;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.media.opengl.GL;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
import org.jzy3d.colors.Color;
|
||||||
|
import org.jzy3d.colors.ColorMapper;
|
||||||
|
import org.jzy3d.io.IGLLoader;
|
||||||
|
import org.jzy3d.maths.BoundingBox3d;
|
||||||
|
import org.jzy3d.maths.Coord3d;
|
||||||
|
import org.jzy3d.plot3d.primitives.vbo.DrawableVBO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A simple loader loading an existing collection of coordinates into a Vertex
|
||||||
|
* Buffer Objects once GL initialization stage requires it to be loaded.
|
||||||
|
*
|
||||||
|
* If a colormapper is given, color buffer will be filled according to coloring policy.
|
||||||
|
*
|
||||||
|
* @author martin
|
||||||
|
*/
|
||||||
|
public class ListCoord3dVBOLoader implements IGLLoader<DrawableVBO> {
|
||||||
|
protected List<Coord3d> coordinates = null;
|
||||||
|
protected ColorMapper coloring = null;
|
||||||
|
|
||||||
|
public ListCoord3dVBOLoader(List<Coord3d> coordinates) {
|
||||||
|
this.coordinates = coordinates;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ListCoord3dVBOLoader(List<Coord3d> coordinates, ColorMapper coloring) {
|
||||||
|
this.coordinates = coordinates;
|
||||||
|
this.coloring = coloring;
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Override
|
||||||
|
// @SuppressWarnings("unchecked")
|
||||||
|
public void load(GL gl, DrawableVBO drawable) throws Exception {
|
||||||
|
// configure
|
||||||
|
boolean hasNormal = false;
|
||||||
|
int n = coordinates.size();
|
||||||
|
int dimension = 3; // x, y, z
|
||||||
|
int geometrySize = computeGeometrySize(drawable);
|
||||||
|
int verticeBufferSize = computeVerticeBufferSize(n, dimension, geometrySize, hasNormal, coloring!=null);
|
||||||
|
int indexBufferSize = n * geometrySize;
|
||||||
|
|
||||||
|
// build and load buffers
|
||||||
|
FloatBuffer vertices = FloatBuffer.allocate(verticeBufferSize);
|
||||||
|
IntBuffer indices = IntBuffer.allocate(indexBufferSize);
|
||||||
|
BoundingBox3d bounds = new BoundingBox3d();
|
||||||
|
fillBuffersWithCollection(drawable, vertices, indices, bounds);
|
||||||
|
|
||||||
|
// Store in GPU
|
||||||
|
drawable.setData(gl, indices, vertices, bounds);
|
||||||
|
Logger.getLogger(ListCoord3dVBOLoader.class).info("done loading " + n + " coords");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void fillBuffersWithCollection(DrawableVBO drawable, FloatBuffer vertices, IntBuffer indices, BoundingBox3d bounds) {
|
||||||
|
fillBuffersWithCollection(drawable, coordinates, coloring, vertices, indices, bounds);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void fillBuffersWithCollection(DrawableVBO drawable, Collection<Coord3d> coordinates, FloatBuffer vertices, IntBuffer indices, BoundingBox3d bounds) {
|
||||||
|
fillBuffersWithCollection(drawable, coordinates, null, vertices, indices, bounds);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void fillBuffersWithCollection(DrawableVBO drawable, Collection<Coord3d> coordinates, ColorMapper colors, FloatBuffer vertices, IntBuffer indices, BoundingBox3d bounds) {
|
||||||
|
drawable.setHasColorBuffer(colors!=null);
|
||||||
|
|
||||||
|
int size = 0;
|
||||||
|
for (Coord3d c : coordinates) {
|
||||||
|
indices.put(size++);
|
||||||
|
putCoord(vertices, c);
|
||||||
|
bounds.add(c);
|
||||||
|
|
||||||
|
if(colors!=null){
|
||||||
|
putColor(vertices, colors.getColor(c));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vertices.rewind();
|
||||||
|
indices.rewind();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void putCoord(FloatBuffer vertices, Coord3d c) {
|
||||||
|
vertices.put(c.x);
|
||||||
|
vertices.put(c.y);
|
||||||
|
vertices.put(c.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void putColor(FloatBuffer vertices, Color color) {
|
||||||
|
vertices.put(color.r);
|
||||||
|
vertices.put(color.g);
|
||||||
|
vertices.put(color.b);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected int computeVerticeBufferSize(int n, int dimension, int geometrysize, boolean hasNormal, boolean hasColor) {
|
||||||
|
int verticeBufferSize = 0;
|
||||||
|
|
||||||
|
if(hasColor){
|
||||||
|
verticeBufferSize = n * (dimension * 2) * geometrysize;// *2 normals
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasNormal) {
|
||||||
|
verticeBufferSize = n * (dimension * 2) * geometrysize;// *2 normals
|
||||||
|
} else {
|
||||||
|
verticeBufferSize = n * dimension * geometrysize;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if(hasColor){
|
||||||
|
verticeBufferSize = n * (dimension * 2) * geometrysize;// *2 color
|
||||||
|
}
|
||||||
|
|
||||||
|
return verticeBufferSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int computeGeometrySize(DrawableVBO drawable) {
|
||||||
|
int geomsize = 0; // triangle
|
||||||
|
|
||||||
|
if (drawable.getGeometry() == GL.GL_POINTS) {
|
||||||
|
geomsize = 1;
|
||||||
|
} else if (drawable.getGeometry() == GL.GL_TRIANGLES) {
|
||||||
|
geomsize = 3;
|
||||||
|
}
|
||||||
|
return geomsize;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
package org.jzy3d.plot3d.primitives.vbo;
|
||||||
|
|
||||||
|
import javax.media.opengl.GL;
|
||||||
|
|
||||||
|
import org.jzy3d.io.IGLLoader;
|
||||||
|
|
||||||
|
public class ScatterVBO extends DrawableVBO{
|
||||||
|
|
||||||
|
public ScatterVBO(IGLLoader<DrawableVBO> loader) {
|
||||||
|
super(loader);
|
||||||
|
geometry = GL.GL_POINTS;
|
||||||
|
}
|
||||||
|
}
|
|
@ -597,14 +597,21 @@ public class View {
|
||||||
else if (boundmode == ViewBoundMode.MANUAL)
|
else if (boundmode == ViewBoundMode.MANUAL)
|
||||||
bounds = viewbounds;
|
bounds = viewbounds;
|
||||||
else {
|
else {
|
||||||
throw new RuntimeException("Unknown bounds");
|
throw new RuntimeException("Unknown bounds mode");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute factors
|
// Compute factors
|
||||||
float xLen = spaceTransformer.getX().compute(bounds.getXmax()) - spaceTransformer.getX().compute(bounds.getXmin());
|
float xLen = 1;
|
||||||
float yLen = spaceTransformer.getY().compute(bounds.getYmax()) - spaceTransformer.getY().compute(bounds.getYmin());
|
float yLen = 1;
|
||||||
float zLen = spaceTransformer.getZ().compute(bounds.getZmax()) - spaceTransformer.getZ().compute(bounds.getZmin());
|
float zLen = 1;
|
||||||
float lmax = (float) Math.max(Math.max(xLen, yLen), zLen);
|
float lmax = 1;
|
||||||
|
|
||||||
|
if(bounds!=null){
|
||||||
|
xLen = spaceTransformer.getX().compute(bounds.getXmax()) - spaceTransformer.getX().compute(bounds.getXmin());
|
||||||
|
yLen = spaceTransformer.getY().compute(bounds.getYmax()) - spaceTransformer.getY().compute(bounds.getYmin());
|
||||||
|
zLen = spaceTransformer.getZ().compute(bounds.getZmax()) - spaceTransformer.getZ().compute(bounds.getZmin());
|
||||||
|
lmax = (float) Math.max(Math.max(xLen, yLen), zLen);
|
||||||
|
}
|
||||||
|
|
||||||
if (Float.isInfinite(xLen) || Float.isNaN(xLen) || xLen == 0)
|
if (Float.isInfinite(xLen) || Float.isNaN(xLen) || xLen == 0)
|
||||||
xLen = 1;
|
xLen = 1;
|
||||||
|
|
Loading…
Reference in New Issue