diff --git a/src/api/org/jzy3d/analysis/AnalysisLauncher.java b/src/api/org/jzy3d/analysis/AnalysisLauncher.java index a178e605..bc6bb86a 100644 --- a/src/api/org/jzy3d/analysis/AnalysisLauncher.java +++ b/src/api/org/jzy3d/analysis/AnalysisLauncher.java @@ -10,11 +10,13 @@ import org.jzy3d.bridge.swt.Bridge; import org.jzy3d.chart.Chart; import org.jzy3d.chart.ChartLauncher; import org.jzy3d.global.Settings; +import org.jzy3d.utils.LoggerUtils; public class AnalysisLauncher { /** Opens a demo with mouse/key/thread controllers for viewpoint change. */ public static void open(IAnalysis demo) throws Exception{ + LoggerUtils.minimal(); open(demo, DEFAULT_WINDOW); } diff --git a/src/api/org/jzy3d/chart/Chart.java b/src/api/org/jzy3d/chart/Chart.java index 940f93cf..66cefeeb 100644 --- a/src/api/org/jzy3d/chart/Chart.java +++ b/src/api/org/jzy3d/chart/Chart.java @@ -14,6 +14,7 @@ import javax.media.opengl.GLCapabilities; import org.jzy3d.bridge.IFrame; import org.jzy3d.chart.controllers.camera.AbstractCameraController; import org.jzy3d.chart.controllers.keyboard.camera.ICameraKeyController; +import org.jzy3d.chart.controllers.keyboard.lights.LightKeyController; import org.jzy3d.chart.controllers.keyboard.screenshot.IScreenshotKeyController; import org.jzy3d.chart.controllers.mouse.camera.ICameraMouseController; import org.jzy3d.chart.factories.ChartComponentFactory; @@ -26,6 +27,7 @@ import org.jzy3d.plot3d.primitives.axes.layout.IAxeLayout; import org.jzy3d.plot3d.rendering.canvas.ICanvas; import org.jzy3d.plot3d.rendering.canvas.IScreenCanvas; import org.jzy3d.plot3d.rendering.canvas.Quality; +import org.jzy3d.plot3d.rendering.lights.Light; import org.jzy3d.plot3d.rendering.view.Renderer2d; import org.jzy3d.plot3d.rendering.view.View; import org.jzy3d.plot3d.rendering.view.modes.ViewPositionMode; @@ -221,6 +223,21 @@ public class Chart { view.removeRenderer2d(renderer2d); } + public Light addLight(Coord3d position) { + return addLight(position, Color.BLUE, new Color(0.8f, 0.8f, 0.8f), Color.WHITE, 1); + } + + public Light addLight(Coord3d position, Color ambiant, Color diffuse, Color specular, int radius) { + Light light = new Light(); + light.setPosition(position); + light.setAmbiantColor(ambiant); + light.setDiffuseColor(diffuse); + light.setSpecularColor(specular); + light.setRepresentationRadius(radius); + getScene().add(light); + return light; + } + public View getView() { return view; } diff --git a/src/api/org/jzy3d/io/obj/OBJFileLoader.java b/src/api/org/jzy3d/io/obj/OBJFileLoader.java index 6c358a27..8da2a69e 100644 --- a/src/api/org/jzy3d/io/obj/OBJFileLoader.java +++ b/src/api/org/jzy3d/io/obj/OBJFileLoader.java @@ -5,6 +5,7 @@ import java.nio.IntBuffer; import javax.media.opengl.GL2; +import org.apache.log4j.Logger; import org.jzy3d.io.IGLLoader; import org.jzy3d.maths.BoundingBox3d; import org.jzy3d.plot3d.primitives.vbo.DrawableVBO; @@ -21,13 +22,13 @@ public class OBJFileLoader implements IGLLoader{ @Override public void load(GL2 gl, DrawableVBO drawable) { - System.err.println("loading OBJ...\n"); obj = new OBJFile(); + Logger.getLogger(OBJFileLoader.class).info("loading OBJ file '" + filename + "'"); obj.loadModelFromFile(filename); - System.err.println("compiling mesh...\n"); + Logger.getLogger(OBJFileLoader.class).info("compiling mesh"); obj.compileModel(); - System.err.println(obj.getPositionCount() + " vertices"); - System.err.println((obj.getIndexCount() / 3) + " triangles"); + Logger.getLogger(OBJFileLoader.class).info(obj.getPositionCount() + " vertices"); + Logger.getLogger(OBJFileLoader.class).info((obj.getIndexCount() / 3) + " triangles"); int size = obj.getIndexCount(); int indexSize = size * Buffers.SIZEOF_INT; diff --git a/src/api/org/jzy3d/maths/BoundingBox3d.java b/src/api/org/jzy3d/maths/BoundingBox3d.java index b7444c01..958e3be3 100644 --- a/src/api/org/jzy3d/maths/BoundingBox3d.java +++ b/src/api/org/jzy3d/maths/BoundingBox3d.java @@ -109,6 +109,11 @@ public class BoundingBox3d { add(c.x, c.y, c.z); } + public void add(List pts){ + for(Point p: pts) + add(p.xyz.x, p.xyz.y, p.xyz.z); + } + /** * Add a Point3d to the BoundingBox3d. * A shortcut for: diff --git a/src/api/org/jzy3d/maths/RotationMatrix.java b/src/api/org/jzy3d/maths/RotationMatrix.java new file mode 100644 index 00000000..7a204f2f --- /dev/null +++ b/src/api/org/jzy3d/maths/RotationMatrix.java @@ -0,0 +1,62 @@ +package org.jzy3d.maths; + +public class RotationMatrix { + + public RotationMatrix(float a, Coord3d c) { + this.a = a; + this.x = c.x; + this.y = c.y; + this.z = c.z; + } + + // TODO normalize x, y, z + public RotationMatrix(float a, float x, float y, float z) { + this.a = a; + this.x = x; + this.y = y; + this.z = z; + } + + protected void prepare(){ + c = (float)Math.cos(a); + s = (float)Math.sin(a); + } + + public Coord3d rotate(Coord3d c){ + Coord3d out = c.clone(); + return rotateSelf(c); + } + + /** + * glRotate produces a rotation of angle degrees around the + vector (x,y,z). The current matrix (see glMatrixMode) is + multiplied by a rotation matrix with the product replacing + the current matrix, as if glMultMatrix were called with the + following matrix as its argument: + + ( xx(1-c)+c xy(1-c)-zs xz(1-c)+ys 0 ) + | | + | yx(1-c)+zs yy(1-c)+c yz(1-c)-xs 0 | + | xz(1-c)-ys yz(1-c)+xs zz(1-c)+c 0 | + | | + ( 0 0 0 1 ) + Where c = cos(angle), s = sine(angle), and ||( x,y,z )|| = 1 + (if not, the GL will normalize this vector). + + * @param c + * @return + */ + public Coord3d rotateSelf(Coord3d c){ + return c; + } + + //protected float + + protected float a = 0; + protected float x = 0; + protected float y = 0; + protected float z = 0; + + protected float c = 0; + protected float s = 0; +} diff --git a/src/api/org/jzy3d/plot3d/primitives/AbstractComposite.java b/src/api/org/jzy3d/plot3d/primitives/AbstractComposite.java index 3bcd14d3..bb3707f1 100644 --- a/src/api/org/jzy3d/plot3d/primitives/AbstractComposite.java +++ b/src/api/org/jzy3d/plot3d/primitives/AbstractComposite.java @@ -84,6 +84,8 @@ public abstract class AbstractComposite extends AbstractWireframeable implements if(mapper!=null) mapper.postDraw(this); + + doDrawBounds(gl, glu, camera); } /** Delegate transforming iteratively to all Drawable of this composite @@ -106,14 +108,27 @@ public abstract class AbstractComposite extends AbstractWireframeable implements /** Creates and return a BoundingBox3d that embed all available Drawable bounds.*/ public BoundingBox3d getBounds(){ - BoundingBox3d box = new BoundingBox3d(); + updateBounds(); + return bbox; + } + + public void updateBounds() { + BoundingBox3d box = new BoundingBox3d(); for(AbstractDrawable c: components){ if(c!=null && c.getBounds()!=null) box.add(c.getBounds()); } - return box; - } + bbox = box; + } + + public void applyGeometryTransform(Transform transform){ + for(AbstractDrawable c: components){ + c.applyGeometryTransform(transform); + } + // updateBounds(); no need, as computed by getBounds() + } + /****************************************************************/ diff --git a/src/api/org/jzy3d/plot3d/primitives/AbstractDrawable.java b/src/api/org/jzy3d/plot3d/primitives/AbstractDrawable.java index 62e76651..34697d22 100644 --- a/src/api/org/jzy3d/plot3d/primitives/AbstractDrawable.java +++ b/src/api/org/jzy3d/plot3d/primitives/AbstractDrawable.java @@ -67,7 +67,33 @@ public abstract class AbstractDrawable implements IGLRenderer, ISortableDraw{ * @param cam a reference to a shooting Camera. */ public abstract void draw(GL2 gl, GLU glu, Camera cam); + public abstract void applyGeometryTransform(Transform transform); + public abstract void updateBounds(); + + public void doTransform(GL2 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(GL2 gl, GLU glu, Camera cam){ + if(isBoundingBoxDisplayed()){ + Parallelepiped p = new Parallelepiped(getBounds()); + p.setFaceDisplayed(false); + p.setWireframeColor(getBoundingBoxColor()); + p.draw(gl, glu, cam); + } + } + + + protected void call(GL2 gl, Color c){ gl.glColor4f( c.r, c.g, c.b, c.a ); } @@ -86,6 +112,7 @@ public abstract class AbstractDrawable implements IGLRenderer, ISortableDraw{ c.b = 1 - c.b; } + /** * Set object's transformation that is applied at the * beginning of a call to {@link #draw(GL,GLU,Camera)}. @@ -105,8 +132,16 @@ public abstract class AbstractDrawable implements IGLRenderer, ISortableDraw{ 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 */ @@ -158,7 +193,7 @@ public abstract class AbstractDrawable implements IGLRenderer, ISortableDraw{ return getDistance(camera); } - /***********************************************************/ + /* */ public void setLegend(Legend face){ this.legend = face; @@ -182,9 +217,26 @@ public abstract class AbstractDrawable implements IGLRenderer, ISortableDraw{ return legendDisplayed; } - /***********************************************************/ + public boolean isBoundingBoxDisplayed() { + return boundingBoxDisplayed; + } - public void addDrawableListener(IDrawableListener listener){ + public void setBoundingBoxDisplayed(boolean boundingBoxDisplayed) { + this.boundingBoxDisplayed = boundingBoxDisplayed; + } + + public Color getBoundingBoxColor() { + return boundingBoxColor; + } + + public void setBoundingBoxColor(Color boundingBoxColor) { + this.boundingBoxColor = boundingBoxColor; + } + + + /* */ + + public void addDrawableListener(IDrawableListener listener){ if(listeners==null) listeners = new ArrayList(); listeners.add(listener); @@ -209,9 +261,8 @@ public abstract class AbstractDrawable implements IGLRenderer, ISortableDraw{ } } - - /***********************************************************/ - + /* */ + public String toString(){ return toString(0); } @@ -220,9 +271,10 @@ public abstract class AbstractDrawable implements IGLRenderer, ISortableDraw{ return Utils.blanks(depth) + "("+this.getClass().getSimpleName()+")"; } - /***********************************************************/ + /* */ protected Transform transform; + protected Transform transformBefore; protected BoundingBox3d bbox; protected Legend legend = null; protected List listeners; @@ -230,5 +282,6 @@ public abstract class AbstractDrawable implements IGLRenderer, ISortableDraw{ protected boolean displayed = true; protected boolean legendDisplayed = false; - + protected boolean boundingBoxDisplayed = false; + protected Color boundingBoxColor = Color.BLACK.clone(); } diff --git a/src/api/org/jzy3d/plot3d/primitives/AbstractGeometry.java b/src/api/org/jzy3d/plot3d/primitives/AbstractGeometry.java index da979902..130dd84d 100644 --- a/src/api/org/jzy3d/plot3d/primitives/AbstractGeometry.java +++ b/src/api/org/jzy3d/plot3d/primitives/AbstractGeometry.java @@ -15,83 +15,84 @@ import org.jzy3d.maths.BoundingBox3d; import org.jzy3d.maths.Coord3d; import org.jzy3d.maths.Utils; import org.jzy3d.plot3d.rendering.view.Camera; +import org.jzy3d.plot3d.transform.Transform; - -public abstract class AbstractGeometry extends AbstractWireframeable implements ISingleColorable, IMultiColorable{ - public enum PolygonMode{ - FRONT, - BACK, - FRONT_AND_BACK +public abstract class AbstractGeometry extends AbstractWireframeable implements ISingleColorable, IMultiColorable { + public enum PolygonMode { + FRONT, BACK, FRONT_AND_BACK } - - /** Initializes an empty {@link AbstractGeometry} with face status defaulting to true, - * and wireframe status defaulting to false.*/ - public AbstractGeometry(){ - super(); - points = new ArrayList(4); // use Vector for synchro, or ArrayList for unsyncro. - bbox = new BoundingBox3d(); - center = new Coord3d(); - polygonOffsetFillEnable = true; - polygonMode = PolygonMode.FRONT_AND_BACK; - } - - /**********************************************************************/ - - public void draw(GL2 gl, GLU glu, Camera cam){ - // Execute transformation - if(transform!=null) - transform.execute(gl); - - if(mapper!=null) + + /** + * Initializes an empty {@link AbstractGeometry} with face status defaulting + * to true, and wireframe status defaulting to false. + */ + public AbstractGeometry() { + super(); + points = new ArrayList(4); // use Vector for synchro, or + // ArrayList for unsyncro. + bbox = new BoundingBox3d(); + center = new Coord3d(); + polygonOffsetFillEnable = true; + polygonMode = PolygonMode.FRONT_AND_BACK; + } + + /**********************************************************************/ + + public void draw(GL2 gl, GLU glu, Camera cam) { + doTransform(gl, glu, cam); + + if (mapper != null) mapper.preDraw(this); - - // Draw content of polygon - if(facestatus){ - applyPolygonModeFill(gl); - if(wfstatus && polygonOffsetFillEnable) - polygonOffseFillEnable(gl); - callPointsForFace(gl); - if(wfstatus && polygonOffsetFillEnable) + + // Draw content of polygon + if (facestatus) { + applyPolygonModeFill(gl); + if (wfstatus && polygonOffsetFillEnable) + polygonOffseFillEnable(gl); + callPointsForFace(gl); + if (wfstatus && polygonOffsetFillEnable) polygonOffsetFillDisable(gl); - } - - // Draw edge of polygon - if(wfstatus){ - applyPolygonModeLine(gl); - if(polygonOffsetFillEnable) - polygonOffseFillEnable(gl); - callPointForWireframe(gl); - if(polygonOffsetFillEnable) - polygonOffsetFillDisable(gl); - } - - if(mapper!=null) + } + + // Draw edge of polygon + if (wfstatus) { + applyPolygonModeLine(gl); + if (polygonOffsetFillEnable) + polygonOffseFillEnable(gl); + callPointForWireframe(gl); + if (polygonOffsetFillEnable) + polygonOffsetFillDisable(gl); + } + + if (mapper != null) mapper.postDraw(this); - } + + doDrawBounds(gl, glu, cam); + } protected void callPointForWireframe(GL2 gl) { gl.glColor4f(wfcolor.r, wfcolor.g, wfcolor.b, wfcolor.a); gl.glLineWidth(wfwidth); begin(gl); - for(Point p: points){ - gl.glVertex3f(p.xyz.x, p.xyz.y, p.xyz.z); + for (Point p : points) { + gl.glVertex3f(p.xyz.x, p.xyz.y, p.xyz.z); } end(gl); } protected void callPointsForFace(GL2 gl) { begin(gl); - for(Point p: points){ - if(mapper!=null){ - Color c = mapper.getColor(p.xyz); // TODO: should cache result in the point color - gl.glColor4f(c.r, c.g, c.b, c.a); - } - else{ - gl.glColor4f(p.rgb.r, p.rgb.g, p.rgb.b, p.rgb.a); - } - - gl.glVertex3f(p.xyz.x, p.xyz.y, p.xyz.z); + for (Point p : points) { + if (mapper != null) { + Color c = mapper.getColor(p.xyz); // TODO: should cache result + // in the point color + gl.glColor4f(c.r, c.g, c.b, c.a); + } else { + gl.glColor4f(p.rgb.r, p.rgb.g, p.rgb.b, p.rgb.a); + } + + gl.glVertex3f(p.xyz.x, p.xyz.y, p.xyz.z); } end(gl); } @@ -102,24 +103,38 @@ public abstract class AbstractGeometry extends AbstractWireframeable implements gl.glEnd(); } - protected void applyPolygonModeLine(GL2 gl) { + protected void applyPolygonModeLine(GL2 gl) { switch (polygonMode) { - case FRONT: gl.glPolygonMode(GL2.GL_FRONT, GL2.GL_LINE); break; - case BACK: gl.glPolygonMode(GL2.GL_BACK, GL2.GL_LINE); break; - case FRONT_AND_BACK: gl.glPolygonMode(GL2.GL_FRONT_AND_BACK, GL2.GL_LINE); break; - default: break; + case FRONT: + gl.glPolygonMode(GL2.GL_FRONT, GL2.GL_LINE); + break; + case BACK: + gl.glPolygonMode(GL2.GL_BACK, GL2.GL_LINE); + break; + case FRONT_AND_BACK: + gl.glPolygonMode(GL2.GL_FRONT_AND_BACK, GL2.GL_LINE); + break; + default: + break; } } protected void applyPolygonModeFill(GL2 gl) { switch (polygonMode) { - case FRONT: gl.glPolygonMode(GL2.GL_FRONT, GL2.GL_FILL); break; - case BACK: gl.glPolygonMode(GL2.GL_BACK, GL2.GL_FILL); break; - case FRONT_AND_BACK: gl.glPolygonMode(GL2.GL_FRONT_AND_BACK, GL2.GL_FILL); break; - default: break; + case FRONT: + gl.glPolygonMode(GL2.GL_FRONT, GL2.GL_FILL); + break; + case BACK: + gl.glPolygonMode(GL2.GL_BACK, GL2.GL_FILL); + break; + case FRONT_AND_BACK: + gl.glPolygonMode(GL2.GL_FRONT_AND_BACK, GL2.GL_FILL); + break; + default: + break; } } - + protected void polygonOffseFillEnable(GL2 gl) { gl.glEnable(GL2.GL_POLYGON_OFFSET_FILL); gl.glPolygonOffset(1.0f, 1.0f); @@ -129,151 +144,170 @@ public abstract class AbstractGeometry extends AbstractWireframeable implements gl.glDisable(GL2.GL_POLYGON_OFFSET_FILL); } - /* DATA */ - - /** Add a point to the polygon.*/ - public void add(Point point){ - points.add(point); - bbox.add(point); - - // recompute center - center = new Coord3d(); - for(Point p: points) - center = center.add(p.xyz); - center = center.div(points.size()); - } - - @Override - public Coord3d getBarycentre(){ - return center; - } - - public Point get(int p){ - return points.get(p); - } - - public List getPoints(){ - return points; - } - - public int size(){ - return points.size(); - } - - /* DISTANCES */ - - public double getDistance(Camera camera){ - return getBarycentre().distance(camera.getEye()); - } - - public double getShortestDistance(Camera camera){ - double min = Float.MAX_VALUE; - double dist = 0; - for(Point point: points){ - dist = point.getDistance(camera); - if(dist < min) - min = dist; - } - - dist = getBarycentre().distance(camera.getEye()); - if(dist < min) - min = dist; - return min; - } - - public double getLongestDistance(Camera camera){ - double max = 0; - double dist = 0; - for(Point point: points){ - dist = point.getDistance(camera); - if(dist > max) - max = dist; - } - return max; - } - - /* SETTINGS */ - + /* DATA */ + + public void add(Point point) { + add(point, true); + } + + /** Add a point to the polygon. */ + public void add(Point point, boolean updateBounds) { + points.add(point); + if (updateBounds) { + updateBounds(); + } + } + public void applyGeometryTransform(Transform transform){ + for(Point p: points){ + p.xyz = transform.compute(p.xyz); + } + updateBounds(); + } + + + public void updateBounds(){ + bbox.reset(); + bbox.add(getPoints()); + + // recompute center + center = new Coord3d(); + for (Point p : points) + center = center.add(p.xyz); + center = center.div(points.size()); + } + + @Override + public Coord3d getBarycentre() { + return center; + } + + public Point get(int p) { + return points.get(p); + } + + public List getPoints() { + return points; + } + + public int size() { + return points.size(); + } + + /* DISTANCES */ + + public double getDistance(Camera camera) { + return getBarycentre().distance(camera.getEye()); + } + + public double getShortestDistance(Camera camera) { + double min = Float.MAX_VALUE; + double dist = 0; + for (Point point : points) { + dist = point.getDistance(camera); + if (dist < min) + min = dist; + } + + dist = getBarycentre().distance(camera.getEye()); + if (dist < min) + min = dist; + return min; + } + + public double getLongestDistance(Camera camera) { + double max = 0; + double dist = 0; + for (Point point : points) { + dist = point.getDistance(camera); + if (dist > max) + max = dist; + } + return max; + } + + /* SETTINGS */ + public PolygonMode getPolygonMode() { return polygonMode; } /** - * A null polygonMode imply no any call to gl.glPolygonMode(...) at rendering + * A null polygonMode imply no any call to gl.glPolygonMode(...) at + * rendering */ public void setPolygonMode(PolygonMode polygonMode) { this.polygonMode = polygonMode; } - + public boolean isPolygonOffsetFillEnable() { return polygonOffsetFillEnable; } /** - * Enable offset fill, which let a polygon with a wireframe render cleanly without weird - * depth incertainty between face and border. + * Enable offset fill, which let a polygon with a wireframe render cleanly + * without weird depth incertainty between face and border. * * Default value is true. */ public void setPolygonOffsetFillEnable(boolean polygonOffsetFillEnable) { this.polygonOffsetFillEnable = polygonOffsetFillEnable; } - + /** - * A utility to change polygon offset fill status of a {@link AbstractComposite} - * containing {@link AbstractGeometry}s. + * A utility to change polygon offset fill status of a + * {@link AbstractComposite} containing {@link AbstractGeometry}s. + * * @param composite - * @param polygonOffsetFillEnable status + * @param polygonOffsetFillEnable + * status */ public static void setPolygonOffsetFillEnable(AbstractComposite composite, boolean polygonOffsetFillEnable) { - for(AbstractDrawable d: composite.getDrawables()){ - if(d instanceof AbstractGeometry){ - ((AbstractGeometry)d).setPolygonOffsetFillEnable(polygonOffsetFillEnable); - } - else if(d instanceof AbstractComposite){ - setPolygonOffsetFillEnable(((AbstractComposite)d), polygonOffsetFillEnable); + for (AbstractDrawable d : composite.getDrawables()) { + if (d instanceof AbstractGeometry) { + ((AbstractGeometry) d).setPolygonOffsetFillEnable(polygonOffsetFillEnable); + } else if (d instanceof AbstractComposite) { + setPolygonOffsetFillEnable(((AbstractComposite) d), polygonOffsetFillEnable); } } } - - - /* COLOR */ - public void setColorMapper(ColorMapper mapper){ - this.mapper = mapper; - - fireDrawableChanged(new DrawableChangedEvent(this, DrawableChangedEvent.FIELD_COLOR)); - } - - public ColorMapper getColorMapper(){ - return mapper; - } - - public void setColor(Color color){ - this.color = color; - - for(Point p: points) - p.setColor(color); - - fireDrawableChanged(new DrawableChangedEvent(this, DrawableChangedEvent.FIELD_COLOR)); - } - - public Color getColor(){ - return color; - } - - public String toString(int depth){ - return (Utils.blanks(depth) + "(" + this.getClass().getSimpleName() + ") #points:" + points.size()); - } - - /* */ - + /* COLOR */ + + public void setColorMapper(ColorMapper mapper) { + this.mapper = mapper; + + fireDrawableChanged(new DrawableChangedEvent(this, DrawableChangedEvent.FIELD_COLOR)); + } + + public ColorMapper getColorMapper() { + return mapper; + } + + public void setColor(Color color) { + this.color = color; + + for (Point p : points) + p.setColor(color); + + fireDrawableChanged(new DrawableChangedEvent(this, DrawableChangedEvent.FIELD_COLOR)); + } + + public Color getColor() { + return color; + } + + public String toString(int depth) { + return (Utils.blanks(depth) + "(" + this.getClass().getSimpleName() + ") #points:" + points.size()); + } + + /* */ + protected PolygonMode polygonMode; protected boolean polygonOffsetFillEnable = true; - protected ColorMapper mapper; - protected List points; - protected Color color; - protected Coord3d center; + protected ColorMapper mapper; + protected List points; + protected Color color; + protected Coord3d center; } diff --git a/src/api/org/jzy3d/plot3d/primitives/CompileableComposite.java b/src/api/org/jzy3d/plot3d/primitives/CompileableComposite.java index 19357365..baabe1fb 100644 --- a/src/api/org/jzy3d/plot3d/primitives/CompileableComposite.java +++ b/src/api/org/jzy3d/plot3d/primitives/CompileableComposite.java @@ -15,6 +15,7 @@ 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; /** * A {@link CompileableComposite} allows storage and subsequent faster execution of individual @@ -78,12 +79,12 @@ public class CompileableComposite extends AbstractWireframeable implements ISing dlID = gl.glGenLists(1); gl.glNewList(dlID, GL2.GL_COMPILE); drawComponents(gl, glu, cam); + doDrawBounds(gl, glu, cam); gl.glEndList(); } protected void execute(GL2 gl, GLU glu, Camera cam){ - if(transform!=null) - transform.execute(gl); + doTransform(gl, glu, cam); gl.glCallList(dlID); } @@ -114,6 +115,28 @@ public class CompileableComposite extends AbstractWireframeable implements ISing } } + public void applyGeometryTransform(Transform transform){ + for(AbstractDrawable c: components){ + c.applyGeometryTransform(transform); + } + // updateBounds(); getBounds() do the work + } + + public BoundingBox3d getBounds(){ + updateBounds(); + return bbox; + } + + 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.*/ @@ -154,19 +177,7 @@ public class CompileableComposite extends AbstractWireframeable implements ISing return components.size(); } - /*******************************/ - - /** Creates and return a BoundingBox3d that embed all available Drawable bounds.*/ - public BoundingBox3d getBounds() { - BoundingBox3d box = new BoundingBox3d(); - - for (AbstractDrawable c : components) { - if (c != null && c.getBounds() != null) { - box.add(c.getBounds()); - } - } - return box; - } + /* */ public void setWireframeColor(Color color) { super.setWireframeColor(color); diff --git a/src/api/org/jzy3d/plot3d/primitives/Disk.java b/src/api/org/jzy3d/plot3d/primitives/Disk.java index ba70768f..ce67ae5f 100644 --- a/src/api/org/jzy3d/plot3d/primitives/Disk.java +++ b/src/api/org/jzy3d/plot3d/primitives/Disk.java @@ -10,121 +10,131 @@ import org.jzy3d.events.DrawableChangedEvent; import org.jzy3d.maths.BoundingBox3d; import org.jzy3d.maths.Coord3d; import org.jzy3d.plot3d.rendering.view.Camera; +import org.jzy3d.plot3d.transform.Transform; +public class Disk extends AbstractWireframeable implements ISingleColorable { -public class Disk extends AbstractWireframeable implements ISingleColorable{ + /** Initialize a Cylinder at the origin. */ + public Disk() { + super(); + bbox = new BoundingBox3d(); + setPosition(Coord3d.ORIGIN); + setVolume(0f, 10f); + setSlicing(15, 15); + setColor(Color.BLACK); + } - /** Initialize a Cylinder at the origin.*/ - public Disk(){ - super(); - bbox = new BoundingBox3d(); - setPosition(Coord3d.ORIGIN); - setVolume(0f, 10f); - setSlicing(15, 15); - setColor(Color.BLACK); - } - - /** Initialize a cylinder with the given parameters.*/ - public Disk(Coord3d position, float radiusInner, float radiusOuter, int slices, int loops, Color color){ - super(); - bbox = new BoundingBox3d(); - setPosition(position); - setVolume(radiusInner, radiusOuter); - setSlicing(slices, loops); - setColor(color); - } - - /********************************************************/ - - public void draw(GL2 gl, GLU glu, Camera cam){ - if(transform!=null) - transform.execute(gl); - gl.glTranslatef(x,y,z); - - gl.glLineWidth(wfwidth); - - // Draw - GLUquadric qobj = glu.gluNewQuadric(); - - if(facestatus){ - if(wfstatus){ - gl.glEnable(GL2.GL_POLYGON_OFFSET_FILL); - gl.glPolygonOffset(1.0f, 1.0f); - } + /** Initialize a cylinder with the given parameters. */ + public Disk(Coord3d position, float radiusInner, float radiusOuter, int slices, int loops, Color color) { + super(); + bbox = new BoundingBox3d(); + setPosition(position); + setVolume(radiusInner, radiusOuter); + setSlicing(slices, loops); + setColor(color); + } - gl.glPolygonMode(GL2.GL_FRONT_AND_BACK, GL2.GL_FILL); - gl.glColor4f(color.r, color.g, color.b, color.a); - glu.gluDisk(qobj, radiusInner, radiusOuter, slices, loops); - - if(wfstatus) - gl.glDisable(GL2.GL_POLYGON_OFFSET_FILL); + /* */ - } - if(wfstatus){ - gl.glPolygonMode(GL2.GL_FRONT_AND_BACK, GL2.GL_LINE); - gl.glColor4f(wfcolor.r, wfcolor.g, wfcolor.b, wfcolor.a); - glu.gluDisk(qobj, radiusInner, radiusOuter, slices, loops); - } - } - - /********************************************************/ - - public void setData(Coord3d position, float radiusInner, float radiusOuter, int slices, int loops){ - setPosition(position); - setVolume(radiusInner, radiusOuter); - setSlicing(slices, loops); - } - - public void setPosition(Coord3d position){ - this.x = position.x; - this.y = position.y; - this.z = position.z; - - bbox.reset(); - bbox.add(x+radiusOuter, y+radiusOuter, z); - bbox.add(x-radiusOuter, y-radiusOuter, z); - } - - public void setVolume(float radiusInner, float radiusOuter){ - if(radiusOuter controlPoints, int resolution){ +public class LineStripInterpolated extends AbstractComposite{ + public LineStripInterpolated(IInterpolator interpolator, List controlPoints, int resolution){ this.controlCoords = controlPoints; this.resolution = resolution; this.interpolatedCoords = interpolator.interpolate(controlPoints, resolution); diff --git a/src/api/org/jzy3d/plot3d/primitives/Parallelepiped.java b/src/api/org/jzy3d/plot3d/primitives/Parallelepiped.java index 54b2074a..91f3e813 100644 --- a/src/api/org/jzy3d/plot3d/primitives/Parallelepiped.java +++ b/src/api/org/jzy3d/plot3d/primitives/Parallelepiped.java @@ -40,7 +40,7 @@ public class Parallelepiped extends AbstractWireframeable implements ISingleColo setData(b); } - /**********************************************************************/ + /* */ public void draw(GL2 gl, GLU glu, Camera cam){ for(Polygon quad: quads) @@ -53,7 +53,7 @@ public class Parallelepiped extends AbstractWireframeable implements ISingleColo quad.setTransform(transform); } - /**********************************************************************/ + /* */ public void setWireframeColor(Color color){ if(quads!=null) @@ -105,43 +105,50 @@ public class Parallelepiped extends AbstractWireframeable implements ISingleColo quads = new Polygon[6]; quads[0] = new Polygon(); - quads[0].add(new Point(new Coord3d(bbox.getXmax(), bbox.getYmin(), bbox.getZmax()))); - quads[0].add(new Point(new Coord3d(bbox.getXmax(), bbox.getYmin(), bbox.getZmin()))); - quads[0].add(new Point(new Coord3d(bbox.getXmax(), bbox.getYmax(), bbox.getZmin()))); - quads[0].add(new Point(new Coord3d(bbox.getXmax(), bbox.getYmax(), bbox.getZmax()))); + quads[0].add(new Point(new Coord3d(bbox.getXmax(), bbox.getYmin(), bbox.getZmax())), false); + quads[0].add(new Point(new Coord3d(bbox.getXmax(), bbox.getYmin(), bbox.getZmin())), false); + quads[0].add(new Point(new Coord3d(bbox.getXmax(), bbox.getYmax(), bbox.getZmin())), false); + quads[0].add(new Point(new Coord3d(bbox.getXmax(), bbox.getYmax(), bbox.getZmax())), false); + quads[0].updateBounds(); quads[1] = new Polygon(); - quads[1].add(new Point(new Coord3d(bbox.getXmin(), bbox.getYmax(), bbox.getZmax()))); - quads[1].add(new Point(new Coord3d(bbox.getXmin(), bbox.getYmax(), bbox.getZmin()))); - quads[1].add(new Point(new Coord3d(bbox.getXmin(), bbox.getYmin(), bbox.getZmin()))); - quads[1].add(new Point(new Coord3d(bbox.getXmin(), bbox.getYmin(), bbox.getZmax()))); - + quads[1].add(new Point(new Coord3d(bbox.getXmin(), bbox.getYmax(), bbox.getZmax())), false); + quads[1].add(new Point(new Coord3d(bbox.getXmin(), bbox.getYmax(), bbox.getZmin())), false); + quads[1].add(new Point(new Coord3d(bbox.getXmin(), bbox.getYmin(), bbox.getZmin())), false); + quads[1].add(new Point(new Coord3d(bbox.getXmin(), bbox.getYmin(), bbox.getZmax())), false); + quads[1].updateBounds(); + quads[2] = new Polygon(); - quads[2].add(new Point(new Coord3d(bbox.getXmax(), bbox.getYmax(), bbox.getZmax()))); - quads[2].add(new Point(new Coord3d(bbox.getXmax(), bbox.getYmax(), bbox.getZmin()))); - quads[2].add(new Point(new Coord3d(bbox.getXmin(), bbox.getYmax(), bbox.getZmin()))); - quads[2].add(new Point(new Coord3d(bbox.getXmin(), bbox.getYmax(), bbox.getZmax()))); - + quads[2].add(new Point(new Coord3d(bbox.getXmax(), bbox.getYmax(), bbox.getZmax())), false); + quads[2].add(new Point(new Coord3d(bbox.getXmax(), bbox.getYmax(), bbox.getZmin())), false); + quads[2].add(new Point(new Coord3d(bbox.getXmin(), bbox.getYmax(), bbox.getZmin())), false); + quads[2].add(new Point(new Coord3d(bbox.getXmin(), bbox.getYmax(), bbox.getZmax())), false); + quads[2].updateBounds(); + + quads[3] = new Polygon(); - quads[3].add(new Point(new Coord3d(bbox.getXmin(), bbox.getYmin(), bbox.getZmax()))); - quads[3].add(new Point(new Coord3d(bbox.getXmin(), bbox.getYmin(), bbox.getZmin()))); - quads[3].add(new Point(new Coord3d(bbox.getXmax(), bbox.getYmin(), bbox.getZmin()))); - quads[3].add(new Point(new Coord3d(bbox.getXmax(), bbox.getYmin(), bbox.getZmax()))); - + quads[3].add(new Point(new Coord3d(bbox.getXmin(), bbox.getYmin(), bbox.getZmax())), false); + quads[3].add(new Point(new Coord3d(bbox.getXmin(), bbox.getYmin(), bbox.getZmin())), false); + quads[3].add(new Point(new Coord3d(bbox.getXmax(), bbox.getYmin(), bbox.getZmin())), false); + quads[3].add(new Point(new Coord3d(bbox.getXmax(), bbox.getYmin(), bbox.getZmax())), false); + quads[3].updateBounds(); + quads[4] = new Polygon(); - quads[4].add(new Point(new Coord3d(bbox.getXmin(), bbox.getYmin(), bbox.getZmax()))); - quads[4].add(new Point(new Coord3d(bbox.getXmax(), bbox.getYmin(), bbox.getZmax()))); - quads[4].add(new Point(new Coord3d(bbox.getXmax(), bbox.getYmax(), bbox.getZmax()))); - quads[4].add(new Point(new Coord3d(bbox.getXmin(), bbox.getYmax(), bbox.getZmax()))); - + quads[4].add(new Point(new Coord3d(bbox.getXmin(), bbox.getYmin(), bbox.getZmax())), false); + quads[4].add(new Point(new Coord3d(bbox.getXmax(), bbox.getYmin(), bbox.getZmax())), false); + quads[4].add(new Point(new Coord3d(bbox.getXmax(), bbox.getYmax(), bbox.getZmax())), false); + quads[4].add(new Point(new Coord3d(bbox.getXmin(), bbox.getYmax(), bbox.getZmax())), false); + quads[4].updateBounds(); + quads[5] = new Polygon(); - quads[5].add(new Point(new Coord3d(bbox.getXmax(), bbox.getYmin(), bbox.getZmin()))); - quads[5].add(new Point(new Coord3d(bbox.getXmin(), bbox.getYmin(), bbox.getZmin()))); - quads[5].add(new Point(new Coord3d(bbox.getXmin(), bbox.getYmax(), bbox.getZmin()))); - quads[5].add(new Point(new Coord3d(bbox.getXmax(), bbox.getYmax(), bbox.getZmin()))); + quads[5].add(new Point(new Coord3d(bbox.getXmax(), bbox.getYmin(), bbox.getZmin())), false); + quads[5].add(new Point(new Coord3d(bbox.getXmin(), bbox.getYmin(), bbox.getZmin())), false); + quads[5].add(new Point(new Coord3d(bbox.getXmin(), bbox.getYmax(), bbox.getZmin())), false); + quads[5].add(new Point(new Coord3d(bbox.getXmax(), bbox.getYmax(), bbox.getZmin())), false); + quads[5].updateBounds(); } - /**********************************************************************/ + /* */ public void setColorMapper(ColorMapper mapper){ this.mapper = mapper; @@ -173,9 +180,19 @@ public class Parallelepiped extends AbstractWireframeable implements ISingleColo } - /**********************************************************************/ + public void applyGeometryTransform(Transform transform){ + for(Polygon quad: quads){ + quad.applyGeometryTransform(transform); + } + } + + /* */ private ColorMapper mapper; private Polygon quads[]; private Color color; + @Override + public void updateBounds() { + throw new RuntimeException("not implemented"); + } } diff --git a/src/api/org/jzy3d/plot3d/primitives/CompositeParallelepiped.java b/src/api/org/jzy3d/plot3d/primitives/ParallelepipedComposite.java similarity index 93% rename from src/api/org/jzy3d/plot3d/primitives/CompositeParallelepiped.java rename to src/api/org/jzy3d/plot3d/primitives/ParallelepipedComposite.java index 541c1b39..041a6400 100644 --- a/src/api/org/jzy3d/plot3d/primitives/CompositeParallelepiped.java +++ b/src/api/org/jzy3d/plot3d/primitives/ParallelepipedComposite.java @@ -12,27 +12,27 @@ import org.jzy3d.plot3d.primitives.AbstractGeometry.PolygonMode; * * Supports two kind of sub polygon: culled or simple. */ -public class CompositeParallelepiped extends AbstractComposite implements ISingleColorable, IMultiColorable { +public class ParallelepipedComposite extends AbstractComposite implements ISingleColorable, IMultiColorable { public enum PolygonType { SIMPLE, CULLED } /** Initialize a parallelepiped. */ - public CompositeParallelepiped() { + public ParallelepipedComposite() { this(PolygonType.CULLED); } - public CompositeParallelepiped(PolygonType type) { + public ParallelepipedComposite(PolygonType type) { super(); this.type = type; } /** Initialize a parallelepiped. */ - public CompositeParallelepiped(BoundingBox3d b) { + public ParallelepipedComposite(BoundingBox3d b) { this(b, PolygonType.CULLED); } - public CompositeParallelepiped(BoundingBox3d b, PolygonType type) { + public ParallelepipedComposite(BoundingBox3d b, PolygonType type) { super(); setData(b); } diff --git a/src/api/org/jzy3d/plot3d/primitives/Point.java b/src/api/org/jzy3d/plot3d/primitives/Point.java index 4b9e6a65..9f61e7bc 100644 --- a/src/api/org/jzy3d/plot3d/primitives/Point.java +++ b/src/api/org/jzy3d/plot3d/primitives/Point.java @@ -11,6 +11,7 @@ import org.jzy3d.maths.Coord3d; import org.jzy3d.maths.Utils; import org.jzy3d.plot3d.rendering.scene.Graph; import org.jzy3d.plot3d.rendering.view.Camera; +import org.jzy3d.plot3d.transform.Transform; @@ -58,11 +59,10 @@ public class Point extends AbstractDrawable implements ISingleColorable{ setColor(rgb); } - /**********************************************************************/ + /* */ public void draw(GL2 gl, GLU glu, Camera cam){ - if(transform!=null) - transform.execute(gl); + doTransform(gl, glu, cam); gl.glPointSize(width); @@ -71,8 +71,12 @@ public class Point extends AbstractDrawable implements ISingleColorable{ gl.glVertex3f(xyz.x, xyz.y, xyz.z); gl.glEnd(); } + + public void applyGeometryTransform(Transform transform){ + xyz = transform.compute(xyz); + } - /*********************************************************************/ + /* */ /** * Set the coordinates of the point. diff --git a/src/api/org/jzy3d/plot3d/primitives/Quad.java b/src/api/org/jzy3d/plot3d/primitives/Quad.java index 829740d2..3b23831a 100644 --- a/src/api/org/jzy3d/plot3d/primitives/Quad.java +++ b/src/api/org/jzy3d/plot3d/primitives/Quad.java @@ -28,8 +28,7 @@ public class Quad extends Polygon{ public void draw(GL2 gl, GLU glu, Camera cam){ // Execute transformation - if(transform!=null) - transform.execute(gl); + doTransform(gl, glu, cam); // Draw content of polygon if(facestatus){ @@ -76,6 +75,8 @@ public class Quad extends Polygon{ /*Point b = new Point(getBarycentre(), Color.BLUE); b.setWidth(5); b.draw(gl,glu,cam);*/ + + doDrawBounds(gl, glu, cam); } /** Add a point to the polygon.*/ diff --git a/src/api/org/jzy3d/plot3d/primitives/Scatter.java b/src/api/org/jzy3d/plot3d/primitives/Scatter.java index 7ec960bc..afeae2a3 100644 --- a/src/api/org/jzy3d/plot3d/primitives/Scatter.java +++ b/src/api/org/jzy3d/plot3d/primitives/Scatter.java @@ -9,6 +9,7 @@ import org.jzy3d.events.DrawableChangedEvent; import org.jzy3d.maths.BoundingBox3d; import org.jzy3d.maths.Coord3d; import org.jzy3d.plot3d.rendering.view.Camera; +import org.jzy3d.plot3d.transform.Transform; @@ -60,8 +61,7 @@ public class Scatter extends AbstractDrawable implements ISingleColorable{ /**********************************************************************/ public void draw(GL2 gl, GLU glu, Camera cam){ - if(transform!=null) - transform.execute(gl); + doTransform(gl, glu, cam); gl.glPointSize(width); @@ -79,7 +79,16 @@ public class Scatter extends AbstractDrawable implements ISingleColorable{ } } gl.glEnd(); + + doDrawBounds(gl, glu, cam); } + + public void applyGeometryTransform(Transform transform){ + for(Coord3d c: coordinates){ + c.set(transform.compute(c)); + } + updateBounds(); + } /*********************************************************************/ @@ -90,10 +99,14 @@ public class Scatter extends AbstractDrawable implements ISingleColorable{ public void setData(Coord3d[] coordinates){ this.coordinates = coordinates; - bbox.reset(); + updateBounds(); + } + + public void updateBounds() { + bbox.reset(); for(Coord3d c: coordinates) bbox.add(c); - } + } public Coord3d[] getData(){ return coordinates; diff --git a/src/api/org/jzy3d/plot3d/primitives/MultiColorScatter.java b/src/api/org/jzy3d/plot3d/primitives/ScatterMultiColor.java similarity index 79% rename from src/api/org/jzy3d/plot3d/primitives/MultiColorScatter.java rename to src/api/org/jzy3d/plot3d/primitives/ScatterMultiColor.java index 4c12cde3..0ccae88e 100644 --- a/src/api/org/jzy3d/plot3d/primitives/MultiColorScatter.java +++ b/src/api/org/jzy3d/plot3d/primitives/ScatterMultiColor.java @@ -13,6 +13,7 @@ import org.jzy3d.plot3d.primitives.axes.layout.providers.ITickProvider; import org.jzy3d.plot3d.primitives.axes.layout.renderers.ITickRenderer; import org.jzy3d.plot3d.rendering.legends.colorbars.ColorbarLegend; import org.jzy3d.plot3d.rendering.view.Camera; +import org.jzy3d.plot3d.transform.Transform; @@ -22,14 +23,14 @@ import org.jzy3d.plot3d.rendering.view.Camera; * @author Martin Pernollet * */ -public class MultiColorScatter extends AbstractDrawable implements IMultiColorable{ - public MultiColorScatter(Coord3d[] coordinates, Color[] colors, ColorMapper mapper){ +public class ScatterMultiColor extends AbstractDrawable implements IMultiColorable{ + public ScatterMultiColor(Coord3d[] coordinates, Color[] colors, ColorMapper mapper){ this(coordinates, colors, mapper, 1.0f); } - public MultiColorScatter(Coord3d[] coordinates, ColorMapper mapper){ + public ScatterMultiColor(Coord3d[] coordinates, ColorMapper mapper){ this(coordinates, null, mapper, 1.0f); } - public MultiColorScatter(Coord3d[] coordinates, Color[] colors, ColorMapper mapper, float width){ + public ScatterMultiColor(Coord3d[] coordinates, Color[] colors, ColorMapper mapper, float width){ bbox = new BoundingBox3d(); setData(coordinates); setColors(colors); @@ -47,11 +48,10 @@ public class MultiColorScatter extends AbstractDrawable implements IMultiColorab setLegendDisplayed(true); } - /**********************************************************************/ + /* */ public void draw(GL2 gl, GLU glu, Camera cam){ - if(transform!=null) - transform.execute(gl); + doTransform(gl, glu, cam); gl.glPointSize(width); gl.glBegin(GL2.GL_POINTS); @@ -64,9 +64,26 @@ public class MultiColorScatter extends AbstractDrawable implements IMultiColorab } } gl.glEnd(); + + doDrawBounds(gl, glu, cam); + } + + @Override + public void applyGeometryTransform(Transform transform) { + for(Coord3d c: coordinates){ + c.set(transform.compute(c)); + } + updateBounds(); + } + + @Override + public void updateBounds() { + bbox.reset(); + for(Coord3d c: coordinates) + bbox.add(c); } - /*********************************************************************/ + /* */ /** * Set the coordinates of the point. @@ -105,11 +122,12 @@ public class MultiColorScatter extends AbstractDrawable implements IMultiColorab this.width = width; } - /**********************************************************************/ + /* */ protected Coord3d[] coordinates; protected Color[] colors; protected float width; protected ColorMapper mapper; + } \ No newline at end of file diff --git a/src/api/org/jzy3d/plot3d/primitives/MultiColorScatterList.java b/src/api/org/jzy3d/plot3d/primitives/ScatterMultiColorList.java similarity index 79% rename from src/api/org/jzy3d/plot3d/primitives/MultiColorScatterList.java rename to src/api/org/jzy3d/plot3d/primitives/ScatterMultiColorList.java index fe408a82..7607be8d 100644 --- a/src/api/org/jzy3d/plot3d/primitives/MultiColorScatterList.java +++ b/src/api/org/jzy3d/plot3d/primitives/ScatterMultiColorList.java @@ -14,6 +14,7 @@ import org.jzy3d.plot3d.primitives.axes.layout.providers.ITickProvider; import org.jzy3d.plot3d.primitives.axes.layout.renderers.ITickRenderer; import org.jzy3d.plot3d.rendering.legends.colorbars.ColorbarLegend; import org.jzy3d.plot3d.rendering.view.Camera; +import org.jzy3d.plot3d.transform.Transform; @@ -23,12 +24,12 @@ import org.jzy3d.plot3d.rendering.view.Camera; * @author Martin Pernollet * */ -public class MultiColorScatterList extends AbstractDrawable implements IMultiColorable{ - public MultiColorScatterList(List coordinates, ColorMapper mapper){ +public class ScatterMultiColorList extends AbstractDrawable implements IMultiColorable{ + public ScatterMultiColorList(List coordinates, ColorMapper mapper){ this(coordinates, mapper, 1.0f); } - public MultiColorScatterList(List coordinates, ColorMapper mapper, float width){ + public ScatterMultiColorList(List coordinates, ColorMapper mapper, float width){ bbox = new BoundingBox3d(); setData(coordinates); setWidth(width); @@ -45,11 +46,10 @@ public class MultiColorScatterList extends AbstractDrawable implements IMultiCol setLegendDisplayed(true); } - /**********************************************************************/ + /* */ public void draw(GL2 gl, GLU glu, Camera cam){ - if(transform!=null) - transform.execute(gl); + doTransform(gl, glu, cam); gl.glPointSize(width); gl.glBegin(GL2.GL_POINTS); @@ -62,9 +62,27 @@ public class MultiColorScatterList extends AbstractDrawable implements IMultiCol } } gl.glEnd(); + + doDrawBounds(gl, glu, cam); } - /*********************************************************************/ + + @Override + public void applyGeometryTransform(Transform transform) { + for(Coord3d c: coordinates){ + c.set(transform.compute(c)); + } + updateBounds(); + } + + @Override + public void updateBounds() { + bbox.reset(); + for(Coord3d c: coordinates) + bbox.add(c); + } + + /* */ /** * Set the coordinates of the point. diff --git a/src/api/org/jzy3d/plot3d/primitives/SimplePolygon.java b/src/api/org/jzy3d/plot3d/primitives/SimplePolygon.java index f7986431..d2d05ada 100644 --- a/src/api/org/jzy3d/plot3d/primitives/SimplePolygon.java +++ b/src/api/org/jzy3d/plot3d/primitives/SimplePolygon.java @@ -27,9 +27,7 @@ public class SimplePolygon extends Polygon implements ISingleColorable, IMultiCo /**********************************************************************/ public void draw(GL2 gl, GLU glu, Camera cam){ - // Execute transformation - if(transform!=null) - transform.execute(gl); + doTransform(gl, glu, cam); // Draw content of polygon if(facestatus){ @@ -63,5 +61,7 @@ public class SimplePolygon extends Polygon implements ISingleColorable, IMultiCo } gl.glEnd(); } + + doDrawBounds(gl, glu, cam); } } diff --git a/src/api/org/jzy3d/plot3d/primitives/Sphere.java b/src/api/org/jzy3d/plot3d/primitives/Sphere.java index 9d592e92..676d32ed 100644 --- a/src/api/org/jzy3d/plot3d/primitives/Sphere.java +++ b/src/api/org/jzy3d/plot3d/primitives/Sphere.java @@ -10,6 +10,7 @@ import org.jzy3d.maths.BoundingBox3d; import org.jzy3d.maths.Coord3d; import org.jzy3d.maths.Utils; import org.jzy3d.plot3d.rendering.view.Camera; +import org.jzy3d.plot3d.transform.Transform; import com.jogamp.opengl.util.gl2.GLUT; @@ -49,8 +50,7 @@ public class Sphere extends AbstractWireframeable implements ISingleColorable{ /********************************************************/ public void draw(GL2 gl, GLU glu, Camera cam){ - if(transform!=null) - transform.execute(gl); + doTransform(gl, glu, cam); gl.glTranslatef(position.x,position.y,position.z); @@ -73,9 +73,19 @@ public class Sphere extends AbstractWireframeable implements ISingleColorable{ //gl.glPolygonMode(GL2.GL_FRONT, GL2.GL_LINE); //gl.glPolygonMode(GL2.GL_FRONT, GL2.GL_FILL); - } + } + + doDrawBounds(gl, glu, cam); } + + @Override + public void applyGeometryTransform(Transform transform) { + position.set(transform.compute(position)); + updateBounds(); + } + + /*protected GLUquadric qobj; public void draw2(){ // qobj = glu.gluNewQuadric(); @@ -112,6 +122,7 @@ public class Sphere extends AbstractWireframeable implements ISingleColorable{ return position; } + @Override public void updateBounds(){ bbox.reset(); bbox.add(position.x+radius, position.y+radius, position.z+radius); diff --git a/src/api/org/jzy3d/plot3d/primitives/Tube.java b/src/api/org/jzy3d/plot3d/primitives/Tube.java index 1262d971..8c592d0b 100644 --- a/src/api/org/jzy3d/plot3d/primitives/Tube.java +++ b/src/api/org/jzy3d/plot3d/primitives/Tube.java @@ -10,6 +10,7 @@ import org.jzy3d.events.DrawableChangedEvent; import org.jzy3d.maths.BoundingBox3d; import org.jzy3d.maths.Coord3d; import org.jzy3d.plot3d.rendering.view.Camera; +import org.jzy3d.plot3d.transform.Transform; @@ -46,11 +47,11 @@ public class Tube extends AbstractWireframeable implements ISingleColorable{ setColor(color); } - /********************************************************/ + /* */ public void draw(GL2 gl, GLU glu, Camera cam){ - if(transform!=null) - transform.execute(gl); + doTransform(gl, glu, cam); + gl.glTranslatef(x,y,z); gl.glLineWidth(wfwidth); @@ -76,10 +77,29 @@ public class Tube extends AbstractWireframeable implements ISingleColorable{ gl.glPolygonMode(GL2.GL_FRONT_AND_BACK, GL2.GL_LINE); gl.glColor4f(wfcolor.r, wfcolor.g, wfcolor.b, wfcolor.a); glu.gluCylinder(qobj, radiusBottom, radiusTop, height, slices, stacks); - } + } + + doDrawBounds(gl, glu, cam); } - /********************************************************/ + 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) @@ -121,12 +141,7 @@ public class Tube extends AbstractWireframeable implements ISingleColorable{ this.radiusBottom = radiusBottom; this.radiusTop = radiusTop; this.height = height; - - 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); + updateBounds(); } /** Set the cylinder slicing parameters, i.e. the subtlety of the circle estimation. @@ -138,7 +153,7 @@ public class Tube extends AbstractWireframeable implements ISingleColorable{ this.stacks = horizontalWires; } - /********************************************************/ + /* */ public void setColor(Color color){ this.color = color; @@ -150,7 +165,7 @@ public class Tube extends AbstractWireframeable implements ISingleColorable{ return color; } - /********************************************************/ + /* */ private float x; private float y; @@ -163,4 +178,6 @@ public class Tube extends AbstractWireframeable implements ISingleColorable{ private int stacks; private Color color; + + } diff --git a/src/api/org/jzy3d/plot3d/primitives/enlightables/EnlightableDisk.java b/src/api/org/jzy3d/plot3d/primitives/enlightables/EnlightableDisk.java index a58b5431..40d37f95 100644 --- a/src/api/org/jzy3d/plot3d/primitives/enlightables/EnlightableDisk.java +++ b/src/api/org/jzy3d/plot3d/primitives/enlightables/EnlightableDisk.java @@ -10,128 +10,135 @@ import org.jzy3d.events.DrawableChangedEvent; import org.jzy3d.maths.BoundingBox3d; import org.jzy3d.maths.Coord3d; import org.jzy3d.plot3d.rendering.view.Camera; +import org.jzy3d.plot3d.transform.Transform; +public class EnlightableDisk extends AbstractEnlightable implements ISingleColorable { -public class EnlightableDisk extends AbstractEnlightable implements ISingleColorable{ + /** Initialize a Cylinder at the origin. */ + public EnlightableDisk() { + this(Coord3d.ORIGIN, 0f, 10f, 15, 15, Color.BLACK, true); + } - /** Initialize a Cylinder at the origin.*/ - public EnlightableDisk(){ - this(Coord3d.ORIGIN, 0f, 10f, 15, 15, Color.BLACK, true); - } - - /** Initialize a cylinder with the given parameters.*/ - public EnlightableDisk(Coord3d position, float radiusInner, float radiusOuter, int slices, int loops, Color color, boolean faceup){ - super(); - bbox = new BoundingBox3d(); - - if(faceup){ - norm = new Coord3d(0,0,1); - } - else - norm = new Coord3d(0,0,-1); - - setPosition(position); - setVolume(radiusInner, radiusOuter); - setSlicing(slices, loops); - setColor(color); - } - - /********************************************************/ - - public void draw(GL2 gl, GLU glu, Camera cam){ - if(transform!=null) - transform.execute(gl); - gl.glTranslatef(x,y,z); - - applyMaterial(gl); - gl.glLineWidth(wfwidth); - - // Draw - GLUquadric qobj = glu.gluNewQuadric(); - - if(facestatus){ - if(wfstatus){ - gl.glEnable(GL2.GL_POLYGON_OFFSET_FILL); - gl.glPolygonOffset(1.0f, 1.0f); - } + /** Initialize a cylinder with the given parameters. */ + public EnlightableDisk(Coord3d position, float radiusInner, float radiusOuter, int slices, int loops, Color color, boolean faceup) { + super(); + bbox = new BoundingBox3d(); - gl.glPolygonMode(GL2.GL_FRONT_AND_BACK, GL2.GL_FILL); - gl.glNormal3f(norm.x, norm.y, norm.z); - gl.glColor4f(color.r, color.g, color.b, color.a); - glu.gluDisk(qobj, radiusInner, radiusOuter, slices, loops); - - if(wfstatus) - gl.glDisable(GL2.GL_POLYGON_OFFSET_FILL); + if (faceup) { + norm = new Coord3d(0, 0, 1); + } else + norm = new Coord3d(0, 0, -1); - } - if(wfstatus){ - gl.glPolygonMode(GL2.GL_FRONT_AND_BACK, GL2.GL_LINE); - gl.glNormal3f(norm.x, norm.y, norm.z); - gl.glColor4f(wfcolor.r, wfcolor.g, wfcolor.b, wfcolor.a); - glu.gluDisk(qobj, radiusInner, radiusOuter, slices, loops); - } - } - - /********************************************************/ - - public void setData(Coord3d position, float radiusInner, float radiusOuter, int slices, int loops){ - setPosition(position); - setVolume(radiusInner, radiusOuter); - setSlicing(slices, loops); - } - - public void setPosition(Coord3d position){ - this.x = position.x; - this.y = position.y; - this.z = position.z; - - bbox.reset(); - bbox.add(x+radiusOuter, y+radiusOuter, z); - bbox.add(x-radiusOuter, y-radiusOuter, z); - } - - public void setVolume(float radiusInner, float radiusOuter){ - if(radiusOuter extends AbstractDrawable imp if(layout==null) throw new RuntimeException("missing vertex mapping"); - if(transform!=null) - transform.execute(gl); + doTransform(gl, glu, cam); // TODO move to graph view init gl.glEnable(GL2.GL_POINT_SMOOTH); diff --git a/src/api/org/jzy3d/plot3d/primitives/graphs/impl/DefaultDrawableGraph2d.java b/src/api/org/jzy3d/plot3d/primitives/graphs/impl/DefaultDrawableGraph2d.java index f0f41383..3545fdad 100644 --- a/src/api/org/jzy3d/plot3d/primitives/graphs/impl/DefaultDrawableGraph2d.java +++ b/src/api/org/jzy3d/plot3d/primitives/graphs/impl/DefaultDrawableGraph2d.java @@ -4,14 +4,17 @@ package org.jzy3d.plot3d.primitives.graphs.impl; import javax.media.opengl.GL2; import javax.media.opengl.glu.GLU; +import org.apache.log4j.Logger; import org.jzy3d.colors.Color; import org.jzy3d.maths.BoundingBox3d; import org.jzy3d.maths.Coord2d; import org.jzy3d.maths.Coord3d; import org.jzy3d.plot3d.primitives.graphs.AbstractDrawableGraph2d; +import org.jzy3d.plot3d.primitives.textured.DrawableTexture; import org.jzy3d.plot3d.rendering.view.Camera; import org.jzy3d.plot3d.text.align.Halign; import org.jzy3d.plot3d.text.align.Valign; +import org.jzy3d.plot3d.transform.Transform; public class DefaultDrawableGraph2d extends AbstractDrawableGraph2d { public DefaultDrawableGraph2d(){ @@ -71,4 +74,15 @@ public class DefaultDrawableGraph2d extends AbstractDrawableGraph2d gl.glVertex3f(c2.x, c2.y, Z); gl.glEnd(); } + + @Override + public void applyGeometryTransform(Transform transform) { + Logger.getLogger(DrawableTexture.class).warn("not implemented"); + } + + @Override + public void updateBounds() { + Logger.getLogger(DrawableTexture.class).warn("not implemented"); + } + } diff --git a/src/api/org/jzy3d/plot3d/primitives/selectable/SelectableScatter.java b/src/api/org/jzy3d/plot3d/primitives/selectable/SelectableScatter.java index aed7739b..0b6ac543 100644 --- a/src/api/org/jzy3d/plot3d/primitives/selectable/SelectableScatter.java +++ b/src/api/org/jzy3d/plot3d/primitives/selectable/SelectableScatter.java @@ -26,8 +26,7 @@ public class SelectableScatter extends Scatter implements ISingleColorable, Sele } public void draw(GL2 gl, GLU glu, Camera cam) { - if (transform != null) - transform.execute(gl); + doTransform(gl, glu, cam); gl.glPointSize(width); diff --git a/src/api/org/jzy3d/plot3d/primitives/textured/DrawableTexture.java b/src/api/org/jzy3d/plot3d/primitives/textured/DrawableTexture.java index 133f6714..66364a2e 100644 --- a/src/api/org/jzy3d/plot3d/primitives/textured/DrawableTexture.java +++ b/src/api/org/jzy3d/plot3d/primitives/textured/DrawableTexture.java @@ -6,6 +6,7 @@ import java.util.List; import javax.media.opengl.GL2; import javax.media.opengl.glu.GLU; +import org.apache.log4j.Logger; import org.jzy3d.colors.Color; import org.jzy3d.maths.BoundingBox2d; import org.jzy3d.maths.BoundingBox3d; @@ -13,6 +14,7 @@ import org.jzy3d.maths.Coord2d; import org.jzy3d.maths.Coord3d; import org.jzy3d.maths.PlaneAxis; import org.jzy3d.plot3d.primitives.AbstractDrawable; +import org.jzy3d.plot3d.primitives.vbo.DrawableVBO; import org.jzy3d.plot3d.rendering.textures.SharedTexture; import org.jzy3d.plot3d.rendering.view.Camera; import org.jzy3d.plot3d.transform.Transform; @@ -20,242 +22,250 @@ import org.jzy3d.plot3d.transform.Transform; import com.jogamp.opengl.util.texture.Texture; import com.jogamp.opengl.util.texture.TextureCoords; -/** A {@link DrawableTexture} can only mount its texture while the GL2 thread is current, - * so the best is to let draw() automount texture file the first time the resource is - * required. - * When a texture is loaded for the first time, it updates the current view bounds since - * the texture bounds where up to now unknown and fixed to origin with no width. +/** + * A {@link DrawableTexture} can only mount its texture while the GL2 thread is + * current, so the best is to let draw() automount texture file the first time + * the resource is required. When a texture is loaded for the first time, it + * updates the current view bounds since the texture bounds where up to now + * unknown and fixed to origin with no width. + * + * A {@link DrawableTexture} requires a color filter (default is white), and a + * set of coordinates defining the polygon on which the texture should be drawn. * - * A {@link DrawableTexture} requires a color filter (default is white), and a set of coordinates - * defining the polygon on which the texture should be drawn. - * * @author Martin - * + * */ -public class DrawableTexture extends AbstractDrawable implements ITranslucent{ - public DrawableTexture(SharedTexture resource){ - this(resource, PlaneAxis.Z, 0, null, null); - } - - public DrawableTexture(SharedTexture resource, PlaneAxis orientation){ - this(resource, orientation, 0, null, null); - } - - public DrawableTexture(SharedTexture resource, PlaneAxis orientation, float axisValue){ - this(resource, orientation, axisValue, null, null); - } - - public DrawableTexture(SharedTexture resource, PlaneAxis orientation, float axisValue, Color filter){ - this(resource, orientation, axisValue, null, filter); - } - - public DrawableTexture(SharedTexture resource, PlaneAxis orientation, float axisValue, List coords){ - this(resource, orientation, axisValue, coords, null); - } - - public DrawableTexture(SharedTexture resource, PlaneAxis orientation, float axisValue, List coords, Color filter){ - this.alpha = 1.0f; - this.resource = resource; - this.axisValue = axisValue; - this.orientation = orientation; - if(filter == null) - this.filter = Color.WHITE.clone(); - else - this.filter = filter; - if( coords != null ){ - mapping = coords; - initBoundsWithMapping(); - } - else{ - mapping = getDefaultTextureMapping(); - initBoundsWithMapping(); - } - } - - public Color getColorFilter() { - return filter; - } +public class DrawableTexture extends AbstractDrawable implements ITranslucent { + public DrawableTexture(SharedTexture resource) { + this(resource, PlaneAxis.Z, 0, null, null); + } - public void setColorFilter(Color filter) { - this.filter = filter; - } + public DrawableTexture(SharedTexture resource, PlaneAxis orientation) { + this(resource, orientation, 0, null, null); + } - @Override - public void setAlphaFactor(float a) { - alpha = a; - } - - protected void initBoundsWithMapping(){ - BoundingBox2d box = new BoundingBox2d(mapping); - float enlarge = 1; - if(orientation == PlaneAxis.X) - bbox = new BoundingBox3d( axisValue-enlarge, axisValue+enlarge, box.xmin(), box.xmax(), box.ymin(), box.ymax() ); - else if(orientation == PlaneAxis.Y) - bbox = new BoundingBox3d( box.xmin(), box.xmax(), axisValue-enlarge, axisValue+enlarge, box.ymin(), box.ymax() ); - else if(orientation == PlaneAxis.Z) - bbox = new BoundingBox3d(box.xmin(), box.xmax(), box.ymin(), box.ymax(), axisValue-enlarge, axisValue+enlarge ); - - } - - protected void initBoundsWithResources(){ - float enlarge = 1; - if(orientation == PlaneAxis.X) - bbox = new BoundingBox3d( axisValue-enlarge, axisValue+enlarge, -resource.getHalfWidth(), resource.getHalfWidth(), -resource.getHalfHeight(), resource.getHalfHeight() ); - else if(orientation == PlaneAxis.Y) - bbox = new BoundingBox3d( -resource.getHalfWidth(), resource.getHalfWidth(), axisValue-enlarge, axisValue+enlarge, -resource.getHalfHeight(), resource.getHalfHeight() ); - else if(orientation == PlaneAxis.Z) - bbox = new BoundingBox3d( -resource.getHalfWidth(), resource.getHalfWidth(), -resource.getHalfHeight(), resource.getHalfHeight(), axisValue-enlarge, axisValue+enlarge ); - - } - - protected List getDefaultTextureMapping(){ - List mapping = new ArrayList(4); - mapping.add( new Coord2d(-resource.getHalfWidth(), -resource.getHalfHeight()) ); - mapping.add( new Coord2d(+resource.getHalfWidth(), -resource.getHalfHeight()) ); - mapping.add( new Coord2d(+resource.getHalfWidth(), +resource.getHalfHeight()) ); - mapping.add( new Coord2d(-resource.getHalfWidth(), +resource.getHalfHeight()) ); - return mapping; - } - - /** - * Must supply the expected size of texture in 3d coordinates. - * @return - */ - public static List getManualTextureMapping(float width, float height, float xoffset, float yoffset){ - List mapping = new ArrayList(4); - mapping.add( new Coord2d(xoffset-width/2, yoffset-height/2) ); - mapping.add( new Coord2d(xoffset+width/2, yoffset-height/2) ); - mapping.add( new Coord2d(xoffset+width/2, yoffset+height/2) ); - mapping.add( new Coord2d(xoffset-width/2, yoffset+height/2) ); - return mapping; - } - - public static List getManualTextureMapping(float width, float height){ - return getManualTextureMapping(width, height, 0, 0); - } - - public void debugMapping(){ - System.out.println("mapping"); - for(Coord2d c: mapping){ - System.out.println(c); - } - } - - public BoundingBox3d getBounds(){ - return bbox.shift(new Coord3d(planePosition,0)); - } - - public Coord2d getPlanePosition() { - return planePosition; - } + public DrawableTexture(SharedTexture resource, PlaneAxis orientation, float axisValue) { + this(resource, orientation, axisValue, null, null); + } - public void setPlanePosition(Coord2d planePosition) { - this.planePosition = planePosition; - } - - public Transform getTextureScale() { - return textureScale; - } + public DrawableTexture(SharedTexture resource, PlaneAxis orientation, float axisValue, Color filter) { + this(resource, orientation, axisValue, null, filter); + } - public void setTextureScale(Transform textureScale) { - this.textureScale = textureScale; - } + public DrawableTexture(SharedTexture resource, PlaneAxis orientation, float axisValue, List coords) { + this(resource, orientation, axisValue, coords, null); + } - protected Transform textureScale; - - public void draw(GL2 gl, GLU glu, Camera cam){ - if(transform!=null) - transform.execute(gl); - if(textureScale!=null) - textureScale.execute(gl, false); - - // Retrieve resource content - Texture texture = resource.getTexture(gl); - TextureCoords coords = resource.getCoords(); - - // Bind texture & set color filter - texture.bind(gl); - callWithAlphaFactor(gl, filter, alpha); - - // Draw - before(gl); - gl.glBegin(GL2.GL_QUADS); - - if( orientation == PlaneAxis.X ){ - gl.glTexCoord2f(coords.left(), coords.bottom()); - gl.glVertex3f( axisValue, mapping.get(0).x, mapping.get(0).y); - gl.glTexCoord2f(coords.right(), coords.bottom()); - gl.glVertex3f( axisValue, mapping.get(1).x, mapping.get(1).y); - gl.glTexCoord2f(coords.right(), coords.top()); - gl.glVertex3f( axisValue, mapping.get(2).x, mapping.get(2).y); - gl.glTexCoord2f(coords.left(), coords.top()); - gl.glVertex3f( axisValue, mapping.get(3).x, mapping.get(3).y); - } - else if( orientation == PlaneAxis.Y ){ - gl.glTexCoord2f(coords.left(), coords.bottom()); - gl.glVertex3f( mapping.get(0).x, axisValue, mapping.get(0).y); - gl.glTexCoord2f(coords.right(), coords.bottom()); - gl.glVertex3f( mapping.get(1).x, axisValue, mapping.get(1).y); - gl.glTexCoord2f(coords.right(), coords.top()); - gl.glVertex3f( mapping.get(2).x, axisValue, mapping.get(2).y); - gl.glTexCoord2f(coords.left(), coords.top()); - gl.glVertex3f( mapping.get(3).x, axisValue, mapping.get(3).y); - } - else if( orientation == PlaneAxis.Z ){ - gl.glTexCoord2f(coords.left(), coords.bottom()); - gl.glVertex3f( planePosition.x + mapping.get(0).x, planePosition.y + mapping.get(0).y, axisValue); - gl.glTexCoord2f(coords.right(), coords.bottom()); - gl.glVertex3f( planePosition.x + mapping.get(1).x, planePosition.y + mapping.get(1).y, axisValue); - gl.glTexCoord2f(coords.right(), coords.top()); - gl.glVertex3f( planePosition.x + mapping.get(2).x, planePosition.y + mapping.get(2).y, axisValue); - gl.glTexCoord2f(coords.left(), coords.top()); - gl.glVertex3f( planePosition.x + mapping.get(3).x, planePosition.y + mapping.get(3).y, axisValue); - } - - gl.glEnd(); - after(gl); - } - - protected void before(GL2 gl){ - gl.glPushMatrix(); - //gl.glHint(GL2.GL_PERSPECTIVE_CORRECTION_HINT,GL2.GL_NICEST); - gl.glPolygonMode(GL2.GL_FRONT_AND_BACK, GL2.GL_FILL); - - //gl.glEnable(GL2.GL_POLYGON_OFFSET_FILL); - //gl.glPolygonOffset(1.0f, 1.0f); - - //gl.glEnable(GL2.GL_BLEND); - //gl.glBlendFunc(GL2.GL_SRC_ALPHA, GL2.GL_ONE_MINUS_SRC_ALPHA); - - //gl.glEnable(GL2.GL_ALPHA_TEST); - //gl.glAlphaFunc(GL2.GL_GREATER, 0); - - gl.glEnable(GL2.GL_TEXTURE_2D); - gl.glTexEnvf(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_ENV_MODE, GL2.GL_REPLACE); - } - - protected void after(GL2 gl){ - gl.glDisable(GL2.GL_TEXTURE_2D); - gl.glTexEnvi(GL2.GL_TEXTURE_ENV, GL2.GL_TEXTURE_ENV_MODE, GL2.GL_MODULATE); - //gl.glDisable(GL2.GL_ALPHA); - //gl.glDisable(GL2.GL_BLEND); - gl.glPopMatrix(); - } - - public SharedTexture getResource() { - return resource; - } + public DrawableTexture(SharedTexture resource, PlaneAxis orientation, float axisValue, List coords, Color filter) { + this.alpha = 1.0f; + this.resource = resource; + this.axisValue = axisValue; + this.orientation = orientation; + if (filter == null) + this.filter = Color.WHITE.clone(); + else + this.filter = filter; + if (coords != null) { + mapping = coords; + initBoundsWithMapping(); + } else { + mapping = getDefaultTextureMapping(); + initBoundsWithMapping(); + } + } - public void setResource(SharedTexture resource) { - this.resource = resource; - } + public Color getColorFilter() { + return filter; + } - protected SharedTexture resource; - protected PlaneAxis orientation; - protected float texMatMix[] = {1.0f, 1.0f, 1.0f, 1.0f}; - protected Color filter; - protected float axisValue; - protected List mapping; - protected float alpha; - protected Coord2d planePosition = new Coord2d(); + public void setColorFilter(Color filter) { + this.filter = filter; + } + + @Override + public void setAlphaFactor(float a) { + alpha = a; + } + + protected void initBoundsWithMapping() { + BoundingBox2d box = new BoundingBox2d(mapping); + float enlarge = 1; + if (orientation == PlaneAxis.X) + bbox = new BoundingBox3d(axisValue - enlarge, axisValue + enlarge, box.xmin(), box.xmax(), box.ymin(), box.ymax()); + else if (orientation == PlaneAxis.Y) + bbox = new BoundingBox3d(box.xmin(), box.xmax(), axisValue - enlarge, axisValue + enlarge, box.ymin(), box.ymax()); + else if (orientation == PlaneAxis.Z) + bbox = new BoundingBox3d(box.xmin(), box.xmax(), box.ymin(), box.ymax(), axisValue - enlarge, axisValue + enlarge); + + } + + protected void initBoundsWithResources() { + float enlarge = 1; + if (orientation == PlaneAxis.X) + bbox = new BoundingBox3d(axisValue - enlarge, axisValue + enlarge, -resource.getHalfWidth(), resource.getHalfWidth(), -resource.getHalfHeight(), resource.getHalfHeight()); + else if (orientation == PlaneAxis.Y) + bbox = new BoundingBox3d(-resource.getHalfWidth(), resource.getHalfWidth(), axisValue - enlarge, axisValue + enlarge, -resource.getHalfHeight(), resource.getHalfHeight()); + else if (orientation == PlaneAxis.Z) + bbox = new BoundingBox3d(-resource.getHalfWidth(), resource.getHalfWidth(), -resource.getHalfHeight(), resource.getHalfHeight(), axisValue - enlarge, axisValue + enlarge); + + } + + protected List getDefaultTextureMapping() { + List mapping = new ArrayList(4); + mapping.add(new Coord2d(-resource.getHalfWidth(), -resource.getHalfHeight())); + mapping.add(new Coord2d(+resource.getHalfWidth(), -resource.getHalfHeight())); + mapping.add(new Coord2d(+resource.getHalfWidth(), +resource.getHalfHeight())); + mapping.add(new Coord2d(-resource.getHalfWidth(), +resource.getHalfHeight())); + return mapping; + } + + /** + * Must supply the expected size of texture in 3d coordinates. + * + * @return + */ + public static List getManualTextureMapping(float width, float height, float xoffset, float yoffset) { + List mapping = new ArrayList(4); + mapping.add(new Coord2d(xoffset - width / 2, yoffset - height / 2)); + mapping.add(new Coord2d(xoffset + width / 2, yoffset - height / 2)); + mapping.add(new Coord2d(xoffset + width / 2, yoffset + height / 2)); + mapping.add(new Coord2d(xoffset - width / 2, yoffset + height / 2)); + return mapping; + } + + public static List getManualTextureMapping(float width, float height) { + return getManualTextureMapping(width, height, 0, 0); + } + + public void debugMapping() { + System.out.println("mapping"); + for (Coord2d c : mapping) { + System.out.println(c); + } + } + + public BoundingBox3d getBounds() { + return bbox.shift(new Coord3d(planePosition, 0)); + } + + public Coord2d getPlanePosition() { + return planePosition; + } + + public void setPlanePosition(Coord2d planePosition) { + this.planePosition = planePosition; + } + + public Transform getTextureScale() { + return textureScale; + } + + public void setTextureScale(Transform textureScale) { + this.textureScale = textureScale; + } + + protected Transform textureScale; + + public void draw(GL2 gl, GLU glu, Camera cam) { + doTransform(gl, glu, cam); + if (textureScale != null) + textureScale.execute(gl, false); + + // Retrieve resource content + Texture texture = resource.getTexture(gl); + TextureCoords coords = resource.getCoords(); + + // Bind texture & set color filter + texture.bind(gl); + callWithAlphaFactor(gl, filter, alpha); + + // Draw + before(gl); + gl.glBegin(GL2.GL_QUADS); + + if (orientation == PlaneAxis.X) { + gl.glTexCoord2f(coords.left(), coords.bottom()); + gl.glVertex3f(axisValue, mapping.get(0).x, mapping.get(0).y); + gl.glTexCoord2f(coords.right(), coords.bottom()); + gl.glVertex3f(axisValue, mapping.get(1).x, mapping.get(1).y); + gl.glTexCoord2f(coords.right(), coords.top()); + gl.glVertex3f(axisValue, mapping.get(2).x, mapping.get(2).y); + gl.glTexCoord2f(coords.left(), coords.top()); + gl.glVertex3f(axisValue, mapping.get(3).x, mapping.get(3).y); + } else if (orientation == PlaneAxis.Y) { + gl.glTexCoord2f(coords.left(), coords.bottom()); + gl.glVertex3f(mapping.get(0).x, axisValue, mapping.get(0).y); + gl.glTexCoord2f(coords.right(), coords.bottom()); + gl.glVertex3f(mapping.get(1).x, axisValue, mapping.get(1).y); + gl.glTexCoord2f(coords.right(), coords.top()); + gl.glVertex3f(mapping.get(2).x, axisValue, mapping.get(2).y); + gl.glTexCoord2f(coords.left(), coords.top()); + gl.glVertex3f(mapping.get(3).x, axisValue, mapping.get(3).y); + } else if (orientation == PlaneAxis.Z) { + gl.glTexCoord2f(coords.left(), coords.bottom()); + gl.glVertex3f(planePosition.x + mapping.get(0).x, planePosition.y + mapping.get(0).y, axisValue); + gl.glTexCoord2f(coords.right(), coords.bottom()); + gl.glVertex3f(planePosition.x + mapping.get(1).x, planePosition.y + mapping.get(1).y, axisValue); + gl.glTexCoord2f(coords.right(), coords.top()); + gl.glVertex3f(planePosition.x + mapping.get(2).x, planePosition.y + mapping.get(2).y, axisValue); + gl.glTexCoord2f(coords.left(), coords.top()); + gl.glVertex3f(planePosition.x + mapping.get(3).x, planePosition.y + mapping.get(3).y, axisValue); + } + + gl.glEnd(); + after(gl); + } + + protected void before(GL2 gl) { + gl.glPushMatrix(); + // gl.glHint(GL2.GL_PERSPECTIVE_CORRECTION_HINT,GL2.GL_NICEST); + gl.glPolygonMode(GL2.GL_FRONT_AND_BACK, GL2.GL_FILL); + + // gl.glEnable(GL2.GL_POLYGON_OFFSET_FILL); + // gl.glPolygonOffset(1.0f, 1.0f); + + // gl.glEnable(GL2.GL_BLEND); + // gl.glBlendFunc(GL2.GL_SRC_ALPHA, GL2.GL_ONE_MINUS_SRC_ALPHA); + + // gl.glEnable(GL2.GL_ALPHA_TEST); + // gl.glAlphaFunc(GL2.GL_GREATER, 0); + + gl.glEnable(GL2.GL_TEXTURE_2D); + gl.glTexEnvf(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_ENV_MODE, GL2.GL_REPLACE); + } + + protected void after(GL2 gl) { + gl.glDisable(GL2.GL_TEXTURE_2D); + gl.glTexEnvi(GL2.GL_TEXTURE_ENV, GL2.GL_TEXTURE_ENV_MODE, GL2.GL_MODULATE); + // gl.glDisable(GL2.GL_ALPHA); + // gl.glDisable(GL2.GL_BLEND); + gl.glPopMatrix(); + } + + public SharedTexture getResource() { + return resource; + } + + public void setResource(SharedTexture resource) { + this.resource = resource; + } + + @Override + public void applyGeometryTransform(Transform transform) { + Logger.getLogger(DrawableTexture.class).warn("not implemented"); + } + + @Override + public void updateBounds() { + Logger.getLogger(DrawableTexture.class).warn("not implemented"); + } + + protected SharedTexture resource; + protected PlaneAxis orientation; + protected float texMatMix[] = { 1.0f, 1.0f, 1.0f, 1.0f }; + protected Color filter; + protected float axisValue; + protected List mapping; + protected float alpha; + protected Coord2d planePosition = new Coord2d(); } diff --git a/src/api/org/jzy3d/plot3d/primitives/textured/TranslucentQuad.java b/src/api/org/jzy3d/plot3d/primitives/textured/TranslucentQuad.java index 644491a3..779697f7 100644 --- a/src/api/org/jzy3d/plot3d/primitives/textured/TranslucentQuad.java +++ b/src/api/org/jzy3d/plot3d/primitives/textured/TranslucentQuad.java @@ -12,8 +12,7 @@ import org.jzy3d.plot3d.rendering.view.Camera; public class TranslucentQuad extends Quad implements ITranslucent{ public void draw(GL2 gl, GLU glu, Camera cam){ // Execute transformation - if(transform!=null) - transform.execute(gl); + doTransform(gl, glu, cam); // Draw content of polygon if(facestatus){ diff --git a/src/api/org/jzy3d/plot3d/primitives/vbo/DrawableVBO.java b/src/api/org/jzy3d/plot3d/primitives/vbo/DrawableVBO.java index 248a7632..a59236d7 100644 --- a/src/api/org/jzy3d/plot3d/primitives/vbo/DrawableVBO.java +++ b/src/api/org/jzy3d/plot3d/primitives/vbo/DrawableVBO.java @@ -10,9 +10,11 @@ import org.apache.log4j.Logger; import org.jzy3d.colors.Color; import org.jzy3d.io.IGLLoader; import org.jzy3d.maths.BoundingBox3d; +import org.jzy3d.maths.Coord3d; import org.jzy3d.plot3d.primitives.AbstractDrawable; import org.jzy3d.plot3d.primitives.IGLBindedResource; import org.jzy3d.plot3d.rendering.view.Camera; +import org.jzy3d.plot3d.transform.Transform; import com.jogamp.common.nio.Buffers; @@ -36,10 +38,10 @@ public class DrawableVBO extends AbstractDrawable implements IGLBindedResource{ // @see http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-9-vbo-indexing/ public void draw(GL2 gl, GLU glu, Camera cam) { if(hasMountedOnce){ - if(transform!=null) - transform.execute(gl); + doTransform(gl, glu, cam); configure(gl); doDrawElements(gl); + doDrawBounds(gl, glu, cam); } } @@ -78,6 +80,24 @@ public class DrawableVBO extends AbstractDrawable implements IGLBindedResource{ return GL2.GL_TRIANGLES; } + public void applyGeometryTransform(Transform transform){ + /*Coord3d c = transform.compute(new Coord3d(x,y, z)); + x = c.x; + y = c.y; + z = c.z;*/ + Logger.getLogger(DrawableVBO.class).warn("not implemented"); + } + + @Override + public void updateBounds() { // requires smart reload + Logger.getLogger(DrawableVBO.class).warn("not implemented"); + /*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);*/ + } + /* IO */ public void mount(GL2 gl){ diff --git a/src/api/org/jzy3d/plot3d/rendering/view/View.java b/src/api/org/jzy3d/plot3d/rendering/view/View.java index 6445b12e..95c82906 100644 --- a/src/api/org/jzy3d/plot3d/rendering/view/View.java +++ b/src/api/org/jzy3d/plot3d/rendering/view/View.java @@ -762,19 +762,19 @@ public class View { // Make smoothing setting if (quality.isSmoothPolygon()) { gl.glEnable(GL2.GL_POLYGON_SMOOTH); - gl.glHint(GL2.GL_POLYGON_SMOOTH_HINT, GL2.GL_FASTEST); + gl.glHint(GL2.GL_POLYGON_SMOOTH_HINT, GL2.GL_NICEST); } else gl.glDisable(GL2.GL_POLYGON_SMOOTH); if (quality.isSmoothLine()) { gl.glEnable(GL2.GL_LINE_SMOOTH); - gl.glHint(GL2.GL_LINE_SMOOTH_HINT, GL2.GL_FASTEST); + gl.glHint(GL2.GL_LINE_SMOOTH_HINT, GL2.GL_NICEST); } else gl.glDisable(GL2.GL_LINE_SMOOTH); if (quality.isSmoothPoint()) { gl.glEnable(GL2.GL_POINT_SMOOTH); - gl.glHint(GL2.GL_POINT_SMOOTH_HINT, GL2.GL_FASTEST); + gl.glHint(GL2.GL_POINT_SMOOTH_HINT, GL2.GL_NICEST); // gl.glDisable(GL2.GL_BLEND); // gl.glHint(GL2.GL_POINT_SMOOTH_HINT, GL2.GL_NICEST); } else diff --git a/src/api/org/jzy3d/plot3d/rendering/view/annotation/CameraDistanceAnnotation.java b/src/api/org/jzy3d/plot3d/rendering/view/annotation/CameraDistanceAnnotation.java index b5ceb876..13120785 100644 --- a/src/api/org/jzy3d/plot3d/rendering/view/annotation/CameraDistanceAnnotation.java +++ b/src/api/org/jzy3d/plot3d/rendering/view/annotation/CameraDistanceAnnotation.java @@ -38,8 +38,7 @@ public class CameraDistanceAnnotation extends Point{ @Override public void draw(GL2 gl, GLU glu, Camera cam) { computeCameraPosition(); - if(transform!=null) - transform.execute(gl); + doTransform(gl, glu, cam); doDrawCamera(gl, glu, cam); diff --git a/src/api/org/jzy3d/plot3d/text/DrawableTextWrapper.java b/src/api/org/jzy3d/plot3d/text/DrawableTextWrapper.java index bd798b3d..63d5dbc0 100644 --- a/src/api/org/jzy3d/plot3d/text/DrawableTextWrapper.java +++ b/src/api/org/jzy3d/plot3d/text/DrawableTextWrapper.java @@ -10,6 +10,7 @@ import org.jzy3d.plot3d.primitives.AbstractDrawable; import org.jzy3d.plot3d.rendering.view.Camera; import org.jzy3d.plot3d.text.align.Halign; import org.jzy3d.plot3d.text.align.Valign; +import org.jzy3d.plot3d.transform.Transform; /** * A {@link DrawableTextWrapper} wraps any text rendered by an {@link ITextRenderer} @@ -31,8 +32,7 @@ public class DrawableTextWrapper extends AbstractDrawable{ /*******************************************************************************************/ public void draw(GL2 gl, GLU glu, Camera cam){ - if(transform!=null) - transform.execute(gl); + doTransform(gl, glu, cam); BoundingBox3d box = renderer.drawText(gl, glu, cam, txt, position, halign, valign, color); if(box!=null) bbox = box.scale(new Coord3d(1/10,1/10,1/10)); @@ -103,4 +103,15 @@ public class DrawableTextWrapper extends AbstractDrawable{ protected Color color; protected ITextRenderer renderer; + + @Override + public void applyGeometryTransform(Transform transform) { + position.set(transform.compute(position)); + updateBounds(); + } + + @Override + public void updateBounds() { + // given after drawing + } } diff --git a/src/api/org/jzy3d/plot3d/transform/Rotate.java b/src/api/org/jzy3d/plot3d/transform/Rotate.java index bb23ccda..7534ad37 100644 --- a/src/api/org/jzy3d/plot3d/transform/Rotate.java +++ b/src/api/org/jzy3d/plot3d/transform/Rotate.java @@ -8,8 +8,9 @@ import org.jzy3d.plot3d.pipelines.NotImplementedException; /** * Rotate is a {@link Transformer} that stores the angle and rotate values - * required to perform the effective OpenGL2 rotation in the - * ModelView Matrix. + * required to perform the effective OpenGL rotation in the + * ModelView matrix. + * * @author Martin Pernollet */ public class Rotate implements Transformer { @@ -41,7 +42,21 @@ public class Rotate implements Transformer { return "(Rotate)a=" + angle + " " + rotate; } - /**************************************************/ + public float getAngle() { + return angle; + } + + public void setAngle(float angle) { + this.angle = angle; + } + + public Coord3d getRotate() { + return rotate; + } + + public void setRotate(Coord3d rotate) { + this.rotate = rotate; + } private float angle; private Coord3d rotate; diff --git a/src/api/org/jzy3d/plot3d/transform/Rotator.java b/src/api/org/jzy3d/plot3d/transform/Rotator.java new file mode 100644 index 00000000..ba3ba63b --- /dev/null +++ b/src/api/org/jzy3d/plot3d/transform/Rotator.java @@ -0,0 +1,53 @@ +package org.jzy3d.plot3d.transform; + +import org.jzy3d.plot3d.transform.Rotate; + +public class Rotator { + public Rotator(int sleep, final Rotate rotate) { + this.sleep = sleep; + this.rotate = rotate; + + this.t = new Thread(new Runnable() { + @Override + public void run() { + while (running) { + Rotator.this.rotate.setAngle(Rotator.this.rotate.getAngle()+1); + try { + Thread.sleep(Rotator.this.sleep); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + }); + } + + protected boolean running = false; + + public void start(){ + running = true; + t.start(); + } + + + public void stop(){ + running = false; + } + + public int getSleep() { + return sleep; + } + public void setSleep(int sleep) { + this.sleep = sleep; + } + public Rotate getRotate() { + return rotate; + } + public void setRotate(Rotate rotate) { + this.rotate = rotate; + } + + protected Thread t; + protected int sleep; + protected Rotate rotate; +} diff --git a/src/api/org/jzy3d/plot3d/transform/Translate.java b/src/api/org/jzy3d/plot3d/transform/Translate.java index 4870d12e..3be481a8 100644 --- a/src/api/org/jzy3d/plot3d/transform/Translate.java +++ b/src/api/org/jzy3d/plot3d/transform/Translate.java @@ -12,6 +12,9 @@ import org.jzy3d.maths.Coord3d; * @author Martin Pernollet */ public class Translate implements Transformer { + protected Translate(){ + + } /** * Initialize a Translate. * @param shift translation offset. diff --git a/src/api/org/jzy3d/plot3d/transform/TranslateDrawable.java b/src/api/org/jzy3d/plot3d/transform/TranslateDrawable.java new file mode 100644 index 00000000..35c700ca --- /dev/null +++ b/src/api/org/jzy3d/plot3d/transform/TranslateDrawable.java @@ -0,0 +1,70 @@ +package org.jzy3d.plot3d.transform; + +import javax.media.opengl.GL2; + +import org.jzy3d.maths.BoundingBox3d; +import org.jzy3d.maths.Coord3d; +import org.jzy3d.plot3d.primitives.AbstractDrawable; + +/** Translate drawable to (0,0,0) or back to its previous position. */ + +public class TranslateDrawable implements Transformer { + public TranslateDrawable(AbstractDrawable drawable, boolean reverse) { + super(); + this.reverse = reverse; + this.drawable = drawable; + } + + public void execute(GL2 gl) { + if (drawable != null) { + BoundingBox3d bounds = drawable.getBounds(); + if (bounds != null) { + Coord3d center = bounds.getCenter(); + if (reverse) + gl.glTranslatef(-center.x/2, -center.y/2, -center.z/2); + else + gl.glTranslatef(center.x/2, center.y/2, center.z/2); + + } + } + } + + public Coord3d compute(Coord3d input) { + if (drawable != null) { + BoundingBox3d bounds = drawable.getBounds(); + if (bounds != null) { + Coord3d center = bounds.getCenter(); + if(reverse) + return input.sub(center.div(2)); + else + return input.add(center.div(2)); + } + } + return null; + } + + + + public AbstractDrawable getDrawable() { + return drawable; + } + + public void setDrawable(AbstractDrawable drawable) { + this.drawable = drawable; + } + + public boolean isReverse() { + return reverse; + } + + public void setReverse(boolean reverse) { + this.reverse = reverse; + } + + public String toString() { + return "(TranslateDrawable)" + drawable; + } + + protected AbstractDrawable drawable; + protected boolean reverse; +}