package org.jzy3d.plot3d.primitives;
import java.util.ArrayList;
import java.util.List;
import org.jzy3d.colors.Color;
import org.jzy3d.colors.ColorMapper;
import org.jzy3d.colors.IMultiColorable;
import org.jzy3d.colors.ISingleColorable;
import org.jzy3d.events.DrawableChangedEvent;
import org.jzy3d.maths.BoundingBox3d;
import org.jzy3d.maths.Utils;
import org.jzy3d.plot3d.rendering.canvas.Quality;
import org.jzy3d.plot3d.rendering.view.Camera;
import org.jzy3d.plot3d.transform.Transform;
import com.jogamp.opengl.GL;
import com.jogamp.opengl.GL2;
import com.jogamp.opengl.glu.GLU;
/**
* A {@link CompileableComposite} allows storage and subsequent faster execution
* of individual contained instances drawing routines in an OpenGL display list.
*
* Compiling the object take the time needed to render it as a standard
* {@link AbstractComposite}, and rendering it once it is compiled seems to take
* roughly half the time up to now. Since compilation occurs during a {@link
* draw()}, the first call to {@link draw()} is supposed to be 1.5x longer than
* a standard {@link AbstractComposite}, while all next cycles would be 0.5x
* longer.
*
* Compilation occurs when the content or the display attributes of this
* Composite changes (then all add(), remove(), setColor(),
* setWireFrameDisplayed(), etc). One can also force rebuilding the object by
* calling recompile();
*
* IMPORTANT: for the moment, {@link CompileableComposite} should not be use in
* a charts using a {@link Quality} superior to Intermediate, in other word, you
* should not desire to have alpha enabled in your scene. Indeed, alpha requires
* ordering of polygons each time the viewpoint changes, which would require to
* recompile the object.
*
* Unsupported in Android / OpenGL ES
*
* @author Nils Hoffmann
*/
public class CompileableComposite extends AbstractWireframeable implements
ISingleColorable, IMultiColorable {
private int dlID = -1;
private boolean resetDL = false;
protected ColorMapper mapper;
protected Color color;
protected boolean detailedToString = false;
protected List components = new ArrayList();
public CompileableComposite() {
super();
components = new ArrayList();
}
/**
* Force the object to be rebuilt and stored as a display list at the next
* call to draw().
*/
public void recompile() {
resetDL = true;
}
/**
* Reset the object if required, compile the object if it is not compiled,
* and execute actual rendering.
*/
@Override
public void draw(GL gl, GLU glu, Camera cam) {
if (resetDL)
reset(gl);
if (dlID == -1)
compile(gl, glu, cam);
execute(gl, glu, cam);
}
/****************************************************************/
/** If you call compile, the display list will be regenerated. */
protected void compile(GL gl, GLU glu, Camera cam) {
reset(gl); // clear old list
nullifyChildrenTransforms();
dlID = gl.getGL2().glGenLists(1);
gl.getGL2().glNewList(dlID, GL2.GL_COMPILE);
drawComponents(gl, glu, cam);
doDrawBounds(gl, glu, cam);
gl.getGL2().glEndList();
}
protected void execute(GL gl, GLU glu, Camera cam) {
doTransform(gl, glu, cam);
gl.getGL2().glCallList(dlID);
}
protected void reset(GL gl) {
if (!gl.isGL2()) {
throw new UnsupportedOperationException(
"CompileableComposite : Display lists not supported with OpenGL ES");
}
if (dlID != -1) {
if (gl.getGL2().glIsList(dlID)) {
gl.getGL2().glDeleteLists(dlID, 1);
}
dlID = -1;
}
resetDL = false;
}
/**
* When a drawable has a null transform, no transform is applied at
* draw(...).
*/
protected void nullifyChildrenTransforms() {
for (AbstractDrawable c : components) {
if (c != null) {
c.setTransform(null);
}
}
}
protected void drawComponents(GL gl, GLU glu, Camera cam) {
synchronized (components) {
for (AbstractDrawable s : components) {
s.draw(gl, glu, cam);
}
}
}
@Override
public void applyGeometryTransform(Transform transform) {
for (AbstractDrawable c : components) {
c.applyGeometryTransform(transform);
}
// updateBounds(); getBounds() do the work
}
@Override
public BoundingBox3d getBounds() {
updateBounds();
return bbox;
}
@Override
public void updateBounds() {
BoundingBox3d box = new BoundingBox3d();
for (AbstractDrawable c : components) {
if (c != null && c.getBounds() != null)
box.add(c.getBounds());
}
bbox = box;
}
/****************************************************************/
/** Append a list of Drawables to this composite. */
public void add(List extends AbstractDrawable> drawables) {
components.addAll(drawables);
recompile();
}
/** Clear the list of Drawables from this composite. */
public void clear() {
components.clear();
recompile();
}
/** Add a Drawable to this composite. */
public void add(AbstractDrawable drawable) {
components.add(drawable);
recompile();
}
/** Remove a Drawable from this composite. */
public void remove(AbstractDrawable drawable) {
components.remove(drawable);
recompile();
}
/** Get a Drawable stored by this composite. */
public AbstractDrawable get(int p) {
return components.get(p);
}
public List getDrawables() {
return components;
}
/** Return the number of Drawable stored by this composite. */
public int size() {
return components.size();
}
/* */
@Override
public void setWireframeColor(Color color) {
super.setWireframeColor(color);
if (components != null) {
for (AbstractDrawable c : components) {
if (c != null && c instanceof AbstractWireframeable) {
((AbstractWireframeable) c).setWireframeColor(color);
}
}
}
recompile();
}
@Override
public void setWireframeDisplayed(boolean status) {
super.setWireframeDisplayed(status);
if (components != null)
for (AbstractDrawable c : components)
if (c != null && c instanceof AbstractWireframeable)
((AbstractWireframeable) c).setWireframeDisplayed(status);
recompile();
}
@Override
public void setWireframeWidth(float width) {
super.setWireframeWidth(width);
if (components != null)
for (AbstractDrawable c : components)
if (c != null && c instanceof AbstractWireframeable)
((AbstractWireframeable) c).setWireframeWidth(width);
recompile();
}
@Override
public void setFaceDisplayed(boolean status) {
super.setFaceDisplayed(status);
if (components != null)
for (AbstractDrawable c : components)
if (c != null && c instanceof AbstractWireframeable)
((AbstractWireframeable) c).setFaceDisplayed(status);
recompile();
}
/****************************************************************/
@Override
public void setColorMapper(ColorMapper mapper) {
this.mapper = mapper;
if (components != null) {
for (AbstractDrawable d : components) {
if (d instanceof IMultiColorable) {
((IMultiColorable) d).setColorMapper(mapper);
} else if (d instanceof ISingleColorable) {
((ISingleColorable) d).setColor(mapper.getColor(d
.getBarycentre()));
}
}
fireDrawableChanged(new DrawableChangedEvent(this,
DrawableChangedEvent.FIELD_COLOR));
}
recompile();
}
@Override
public ColorMapper getColorMapper() {
return mapper;
}
@Override
public void setColor(Color color) {
this.color = color;
if (components != null) {
for (AbstractDrawable d : components) {
if (d instanceof ISingleColorable) {
((ISingleColorable) d).setColor(color);
}
}
fireDrawableChanged(new DrawableChangedEvent(this,
DrawableChangedEvent.FIELD_COLOR));
}
recompile();
}
@Override
public Color getColor() {
return color;
}
/****************************************************************/
/** Print out information concerning all Drawable of this composite. */
@Override
public String toString() {
return toString(0);
}
@Override
public String toString(int depth) {
String output = Utils.blanks(depth) + "(Composite3d) #elements:"
+ components.size() + " | isDisplayed=" + isDisplayed();
if (detailedToString) {
int k = 0;
for (AbstractDrawable c : components) {
if (c != null) {
if (c instanceof AbstractComposite) {
output += "\n"
+ ((AbstractComposite) c).toString(depth + 1);
} else {
output += "\n" + Utils.blanks(depth + 1)
+ " Composite element[" + (k++) + "]:"
+ c.toString();
}
} else {
output += Utils.blanks(depth + 1) + "(null)\n";
}
}
}
return output;
}
public boolean isDetailedToString() {
return detailedToString;
}
/**
* When to true, the {@link toString()} method will give the detail of each
* element of this composite object in a tree like layout.
*/
public void setDetailedToString(boolean detailedToString) {
this.detailedToString = detailedToString;
}
}
Ads help maintain this website.