package org.jzy3d.plot3d.primitives;
import java.util.ArrayList;
import java.util.List;
import org.jzy3d.colors.Color;
import org.jzy3d.events.DrawableChangedEvent;
import org.jzy3d.events.IDrawableListener;
import org.jzy3d.maths.BoundingBox3d;
import org.jzy3d.maths.Coord3d;
import org.jzy3d.maths.Utils;
import org.jzy3d.plot3d.primitives.axes.AxeBox;
import org.jzy3d.plot3d.rendering.canvas.ICanvas;
import org.jzy3d.plot3d.rendering.compat.GLES2CompatUtils;
import org.jzy3d.plot3d.rendering.legends.ILegend;
import org.jzy3d.plot3d.rendering.view.Camera;
import org.jzy3d.plot3d.transform.Transform;
import org.jzy3d.plot3d.transform.space.SpaceTransformer;
import com.jogamp.opengl.GL;
import com.jogamp.opengl.glu.GLU;
/**
* A {@link AbstractDrawable} defines objects that may be rendered into an
* OpenGL context provided by a {@link ICanvas}.
* A {@link AbstractDrawable} must basically provide a rendering function called
* draw() that receives a reference to a GL2 and a GLU context. It may also use
* a reference to a Camera in order to implement specific behaviors according to
* the Camera position.
* A {@link AbstractDrawable} provides services for setting the transformation
* factor that is used inside the draw function, as well as a getter of the
* object's BoundingBox3d. Note that the BoundingBox must be set by a concrete
* descendant of a {@link AbstractDrawable}.
* A good practice is to define a setData function for initializing a
* {@link AbstractDrawable} and building its polygons. Since each class may have
* its own inputs, setData is not part of the interface but should be used as a
* convention. When not defining a setData function, a {@link AbstractDrawable}
* may have its data loaded by an {@link add(Drawable)} function.
*
* Note: A {@link AbstractDrawable} may last provide the information whether it
* is displayed or not, according to a rendering into the FeedBack buffer. This
* is currently supported specifically for the {@link AxeBox} object but could
* be extended with some few more algorithm for referencing all GL2 polygons.
*
* @author Martin Pernollet
*
*/
public abstract class AbstractDrawable implements IGLRenderer, ISortableDraw {
/**
* Performs all required operation to cleanup the Drawable.
*/
public void dispose() {
if (listeners != null)
listeners.clear();
}
/**
* Call OpenGL2 routines for rendering the object.
*
* @param gl
* GL2 context
* @param glu
* GLU context
* @param cam
* a reference to a shooting Camera.
*/
@Override
public abstract void draw(GL gl, GLU glu, Camera cam);
public abstract void applyGeometryTransform(Transform transform);
public abstract void updateBounds();
public void doTransform(GL gl, GLU glu, Camera cam) {
if (transformBefore != null) {
if (transformBefore != null)
transformBefore.execute(gl, true);
if (transform != null)
transform.execute(gl, false);
} else {
if (transform != null)
transform.execute(gl);
}
}
protected void doDrawBounds(GL gl, GLU glu, Camera cam) {
if (isBoundingBoxDisplayed()) {
Parallelepiped p = new Parallelepiped(getBounds());
p.setFaceDisplayed(false);
p.setWireframeColor(getBoundingBoxColor());
p.draw(gl, glu, cam);
}
}
/**
* A helper to call glVerted3f on the input coordinate. For GL2 profile only.
* If logTransform is non null, then each dimension transform is processed before calling glVertex3d.
*/
protected void vertexGL2(GL gl, Coord3d c) {
if (spaceTransformer == null) {
gl.getGL2().glVertex3f(c.x, c.y, c.z);
} else {
gl.getGL2().glVertex3f(spaceTransformer.getX().compute(c.x), spaceTransformer.getY().compute(c.y), spaceTransformer.getZ().compute(c.z));
}
}
/**
* A helper to call glVerted3f on the input coordinate. For GLES2 profile only.
* If logTransform is non null, then each dimension transform is processed before calling glVertex3d.
*/
protected void vertexGLES2(Coord3d c) {
if(spaceTransformer==null){
GLES2CompatUtils.glVertex3f(c.x, c.y, c.z);
}
else{
GLES2CompatUtils.glVertex3f(spaceTransformer.getX().compute(c.x), spaceTransformer.getY().compute(c.y),spaceTransformer.getZ().compute(c.z));
}
}
/** A helper to call glColor4f on the input color. For GL2 profile only. */
protected void colorGL2(GL gl, Color c) {
gl.getGL2().glColor4f(c.r, c.g, c.b, c.a);
}
/** A helper to call glColor4f on the input color. For GLES2 profile only. */
protected void colorGLES2(Color c) {
GLES2CompatUtils.glColor4f(c.r, c.g, c.b, c.a);
}
protected void call(GL gl, Color c) {
if (gl.isGL2()) {
colorGL2(gl, c);
} else {
colorGLES2(c);
}
}
protected void call(GL gl, Color c, float alpha) {
if (gl.isGL2()) {
gl.getGL2().glColor4f(c.r, c.g, c.b, alpha);
} else {
GLES2CompatUtils.glColor4f(c.r, c.g, c.b, alpha);
}
}
protected void callWithAlphaFactor(GL gl, Color c, float alpha) {
if (gl.isGL2()) {
gl.getGL2().glColor4f(c.r, c.g, c.b, c.a * alpha);
} else {
GLES2CompatUtils.glColor4f(c.r, c.g, c.b, c.a * alpha);
}
}
protected void negative(Color c) {
c.r = 1 - c.r;
c.g = 1 - c.g;
c.b = 1 - c.b;
}
/**
* Set object's transformation that is applied at the beginning of a call to
* {@link #draw(GL,GLU,Camera)}.
*
* @param transform
*/
public void setTransform(Transform transform) {
this.transform = transform;
fireDrawableChanged(DrawableChangedEvent.FIELD_TRANSFORM);
}
/**
* Get object's transformation that is applied at the beginning of a call to
* {@link #draw(GL,GLU,Camera)}.
*
* @return transform
*/
public Transform getTransform() {
return transform;
}
public Transform getTransformBefore() {
return transformBefore;
}
public void setTransformBefore(Transform transformBefore) {
this.transformBefore = transformBefore;
}
/**
* Return the BoundingBox of this object.
*
* @return a bounding box
*/
public BoundingBox3d getBounds() {
return bbox;
}
/**
* Return the barycentre of this object, which is computed as the center of
* its bounding box. If the bounding box is not available, the returned
* value is {@link Coord3d.INVALID}
*
* @return the center of the bounding box, or {@link Coord3d.INVALID}.
*/
public Coord3d getBarycentre() {
if (bbox != null)
return bbox.getCenter();
else
return Coord3d.INVALID.clone();
}
/**
* Set to true or false the displayed status of this object.
*
* @param status
*/
public void setDisplayed(boolean status) {
displayed = status;
fireDrawableChanged(DrawableChangedEvent.FIELD_DISPLAYED);
}
/** Return the display status of this object. */
public boolean isDisplayed() {
return displayed;
}
/** Return the distance of the object center to the {@link Camera}'s eye. */
@Override
public double getDistance(Camera camera) {
return getBarycentre().distance(camera.getEye());
}
@Override
public double getShortestDistance(Camera camera) {
return getDistance(camera);
}
@Override
public double getLongestDistance(Camera camera) {
return getDistance(camera);
}
/* */
public void setLegend(ILegend face) {
this.legend = face;
legendDisplayed = true;
fireDrawableChanged(DrawableChangedEvent.FIELD_METADATA);
}
public ILegend getLegend() {
return legend;
}
public boolean hasLegend() {
return (legend != null);
}
public void setLegendDisplayed(boolean status) {
legendDisplayed = status;
}
public boolean isLegendDisplayed() {
return legendDisplayed;
}
public boolean isBoundingBoxDisplayed() {
return boundingBoxDisplayed;
}
public void setBoundingBoxDisplayed(boolean boundingBoxDisplayed) {
this.boundingBoxDisplayed = boundingBoxDisplayed;
}
public Color getBoundingBoxColor() {
return boundingBoxColor;
}
public void setBoundingBoxColor(Color boundingBoxColor) {
this.boundingBoxColor = boundingBoxColor;
}
public SpaceTransformer getSpaceTransformer() {
return spaceTransformer;
}
public void setSpaceTransformer(SpaceTransformer spaceTransformer) {
this.spaceTransformer = spaceTransformer;
}
/* */
public void addDrawableListener(IDrawableListener listener) {
if (listeners == null)
listeners = new ArrayList();
listeners.add(listener);
hasListeners = true;
}
public void removeDrawableListener(IDrawableListener listener) {
listeners.remove(listener);
}
protected void fireDrawableChanged(int eventType) {
if (listeners != null) {
fireDrawableChanged(new DrawableChangedEvent(this, eventType));
}
}
protected void fireDrawableChanged(DrawableChangedEvent e) {
if (listeners != null) {
for (IDrawableListener listener : listeners) {
listener.drawableChanged(e);
}
}
}
/* */
@Override
public String toString() {
return toString(0);
}
public String toString(int depth) {
return Utils.blanks(depth) + "(" + this.getClass().getSimpleName() + ")";
}
/* */
protected Transform transform;
protected Transform transformBefore;
protected BoundingBox3d bbox;
protected ILegend legend = null;
protected List listeners;
protected boolean hasListeners = true;
protected boolean displayed = true;
protected boolean legendDisplayed = false;
protected boolean boundingBoxDisplayed = false;
protected Color boundingBoxColor = Color.BLACK.clone();
protected SpaceTransformer spaceTransformer = null;
}
Ads help maintain this website.