package org.jzy3d.plot3d.primitives;
import org.jzy3d.colors.Color;
import org.jzy3d.colors.ISingleColorable;
import org.jzy3d.events.DrawableChangedEvent;
import org.jzy3d.maths.BoundingBox3d;
import org.jzy3d.maths.Coord3d;
import org.jzy3d.plot3d.rendering.compat.GLES2CompatUtils;
import org.jzy3d.plot3d.rendering.view.Camera;
import org.jzy3d.plot3d.transform.Transform;
import com.jogamp.opengl.GL;
import com.jogamp.opengl.GL2GL3;
import com.jogamp.opengl.glu.GLU;
import com.jogamp.opengl.glu.GLUquadric;
/**
* A {@link Tube} may be used to render cylinders or pyramids, according to its
* input parameters.
* The position and shape of a {@link Tube} is defined through its {@link
* setData()} method. Moreover, a {@link Tube} is Wireframeable3d and support
* only one color that is defined trough its {@link setColor()} method.
*
* @author Martin Pernollet
*/
public class Tube extends AbstractWireframeable implements ISingleColorable {
/** Initialize a Cylinder at the origin. */
public Tube() {
super();
bbox = new BoundingBox3d();
setPosition(Coord3d.ORIGIN);
setVolume(10f, 10f, 30f);
setSlicing(15, 15);
setColor(Color.BLACK);
}
/** Initialize a cylinder with the given parameters. */
public Tube(Coord3d position, float radius, float height, int hslicing,
int vslicing, Color color) {
super();
bbox = new BoundingBox3d();
setPosition(position);
setVolume(radius, radius, height);
setSlicing(hslicing, vslicing);
setColor(color);
}
/* */
@Override
public void draw(GL gl, GLU glu, Camera cam) {
doTransform(gl, glu, cam);
if (gl.isGL2()) {
gl.getGL2().glTranslatef(x, y, z);
} else {
GLES2CompatUtils.glTranslatef(x, y, z);
}
gl.glLineWidth(wfwidth);
// Draw
GLUquadric qobj = glu.gluNewQuadric();
if (gl.isGL2()) {
if (facestatus) {
if (wfstatus) {
gl.glEnable(GL.GL_POLYGON_OFFSET_FILL);
gl.glPolygonOffset(1.0f, 1.0f);
}
gl.getGL2().glPolygonMode(GL.GL_FRONT_AND_BACK, GL2GL3.GL_FILL);
gl.getGL2().glColor4f(color.r, color.g, color.b, color.a);
glu.gluCylinder(qobj, radiusBottom, radiusTop, height, slices,
stacks);
if (wfstatus)
gl.glDisable(GL.GL_POLYGON_OFFSET_FILL);
}
if (wfstatus) {
gl.getGL2().glPolygonMode(GL.GL_FRONT_AND_BACK, GL2GL3.GL_LINE);
gl.getGL2().glColor4f(wfcolor.r, wfcolor.g, wfcolor.b,
wfcolor.a);
glu.gluCylinder(qobj, radiusBottom, radiusTop, height, slices,
stacks);
}
} else {
if (facestatus) {
if (wfstatus) {
gl.glEnable(GL.GL_POLYGON_OFFSET_FILL);
gl.glPolygonOffset(1.0f, 1.0f);
}
GLES2CompatUtils.glPolygonMode(GL.GL_FRONT_AND_BACK,
GL2GL3.GL_FILL);
GLES2CompatUtils.glColor4f(color.r, color.g, color.b,
color.a);
glu.gluCylinder(qobj, radiusBottom, radiusTop, height, slices,
stacks);
if (wfstatus)
gl.glDisable(GL.GL_POLYGON_OFFSET_FILL);
}
if (wfstatus) {
GLES2CompatUtils.glPolygonMode(GL.GL_FRONT_AND_BACK,
GL2GL3.GL_LINE);
GLES2CompatUtils.glColor4f(wfcolor.r, wfcolor.g, wfcolor.b,
wfcolor.a);
glu.gluCylinder(qobj, radiusBottom, radiusTop, height, slices,
stacks);
}
}
doDrawBounds(gl, glu, cam);
}
@Override
public void applyGeometryTransform(Transform transform) {
Coord3d c = transform.compute(new Coord3d(x, y, z));
x = c.x;
y = c.y;
z = c.z;
updateBounds();
}
@Override
public void updateBounds() {
bbox.reset();
bbox.add(x + Math.max(radiusBottom, radiusTop),
y + Math.max(radiusBottom, radiusTop), z);
bbox.add(x - Math.max(radiusBottom, radiusTop),
y - Math.max(radiusBottom, radiusTop), z);
bbox.add(x + Math.max(radiusBottom, radiusTop),
y + Math.max(radiusBottom, radiusTop), z + height);
bbox.add(x - Math.max(radiusBottom, radiusTop),
y - Math.max(radiusBottom, radiusTop), z + height);
}
/* */
/**
* Set the {@link Tube} data.
*
* @param position
* cylinder position (may be handled diffrently in future
* version)
* @param radiusBottom
* radius of the bottom circle
* @param radiusTop
* radius of the top circle
* @param height
* height of the cylinder
* @param slices
* number of vertical slices (i.e. wireframes)
* @param stacks
* number of horizontal stacks (i.e. wireframes)
*/
public void setData(Coord3d position, float radiusBottom, float radiusTop,
float height, int slices, int stacks) {
setPosition(position);
setVolume(radiusBottom, radiusTop, height);
setSlicing(slices, stacks);
}
/**
* Set the position of the Cylinder and the dimensions of its boundingbox.
* Note that this position will be use to translate the object before
* drawing it (meaning a glTranslate(position) is performed right after the
* Translate.execute).
*
* @param position
*/
public void setPosition(Coord3d position) {
this.x = position.x;
this.y = position.y;
this.z = position.z;
bbox.reset();
bbox.add(x + Math.max(radiusBottom, radiusTop),
y + Math.max(radiusBottom, radiusTop), z + height);
bbox.add(x - Math.max(radiusBottom, radiusTop),
y - Math.max(radiusBottom, radiusTop), z - height);
}
/**
* Set the top and bottom radius of the cylinder, its height, and the
* dimensions of its boundingbox.
*
* @param radiusBottom
* @param radiusTop
* @param height
*/
public void setVolume(float radiusBottom, float radiusTop, float height) {
this.radiusBottom = radiusBottom;
this.radiusTop = radiusTop;
this.height = height;
updateBounds();
}
/**
* Set the cylinder slicing parameters, i.e. the subtlety of the circle
* estimation.
*
* @param verticalWires
* number of vertical slices
* @param horizontalWires
* number of horizontal slices
*/
public void setSlicing(int verticalWires, int horizontalWires) {
this.slices = verticalWires;
this.stacks = horizontalWires;
}
/* */
@Override
public void setColor(Color color) {
this.color = color;
fireDrawableChanged(new DrawableChangedEvent(this,
DrawableChangedEvent.FIELD_COLOR));
}
@Override
public Color getColor() {
return color;
}
/* */
private float x;
private float y;
private float z;
private float radiusBottom;
private float radiusTop;
private float height;
private int slices;
private int stacks;
private Color color;
}
Ads help maintain this website.