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.Coord3d;
import org.jzy3d.maths.Utils;
import org.jzy3d.plot3d.rendering.compat.GLES2CompatUtils;
import org.jzy3d.plot3d.rendering.view.Camera;
import org.jzy3d.plot3d.transform.Transform;
import com.jogamp.opengl.GL;
import com.jogamp.opengl.GL2GL3;
import com.jogamp.opengl.glu.GLU;
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);
bbox = new BoundingBox3d();
center = new Coord3d();
polygonOffsetFillEnable = true;
polygonMode = PolygonMode.FRONT_AND_BACK;
}
/* * */
@Override
public void draw(GL 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)
polygonOffsetFillDisable(gl);
}
// 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);
}
/** Drawing the point list in wireframe mode if GL2 profile is available */
protected void callPointForWireframe(GL gl) {
if (gl.isGL2()) {
callPointsForWireframeGL2(gl);
}
}
/** Drawing the point list in wireframe mode */
public void callPointsForWireframeGL2(GL gl) {
colorGL2(gl, wfcolor);
gl.glLineWidth(wfwidth);
begin(gl);
for (Point p : points) {
vertexGL2(gl, p.xyz);
}
end(gl);
}
/** Drawing the point list in face mode (polygon content) */
protected void callPointsForFace(GL gl) {
if (gl.isGL2()) {
callPointsForFaceGL2(gl);
} else {
callPointsForFaceGLES2(gl);
}
}
/** Drawing the point list in face mode (polygon content) with GLES2 profile */
public void callPointsForFaceGLES2(GL gl) {
callPointsForFaceGLES2(gl, points);
}
/** Drawing the point list in face mode (polygon content) with GLES2 profile */
public void callPointsForFaceGLES2(GL gl, List points) {
begin(gl);
for (Point p : points) {
if (mapper != null) {
Color c = mapper.getColor(p.xyz);
colorGLES2(c);
} else {
colorGLES2(p.rgb);
}
vertexGLES2(p.xyz);
}
end(gl);
}
/** Drawing the point list in face mode (polygon content) with GL2 profile */
public void callPointsForFaceGL2(GL gl) {
begin(gl);
for (Point p : points) {
if (mapper != null) {
Color c = mapper.getColor(p.xyz);
colorGL2(gl, c);
} else {
colorGL2(gl, p.rgb);
}
vertexGL2(gl, p.xyz);
}
end(gl);
}
protected abstract void begin(GL gl);
protected void end(GL gl) {
if (gl.isGL2()) {
gl.getGL2().glEnd();
} else {
GLES2CompatUtils.glEnd();
}
}
protected void applyPolygonModeLine(GL gl) {
if (gl.isGL2()) {
applyPolygonModeLineGL2(gl);
} else {
applyPolygonModeLineGLES2();
}
}
protected void applyPolygonModeLineGLES2() {
switch (polygonMode) {
case FRONT:
GLES2CompatUtils.glPolygonMode(GL.GL_FRONT, GL2GL3.GL_LINE);
break;
case BACK:
GLES2CompatUtils.glPolygonMode(GL.GL_BACK, GL2GL3.GL_LINE);
break;
case FRONT_AND_BACK:
GLES2CompatUtils.glPolygonMode(GL.GL_FRONT_AND_BACK, GL2GL3.GL_LINE);
break;
default:
break;
}
}
protected void applyPolygonModeLineGL2(GL gl) {
switch (polygonMode) {
case FRONT:
gl.getGL2().glPolygonMode(GL.GL_FRONT, GL2GL3.GL_LINE);
break;
case BACK:
gl.getGL2().glPolygonMode(GL.GL_BACK, GL2GL3.GL_LINE);
break;
case FRONT_AND_BACK:
gl.getGL2().glPolygonMode(GL.GL_FRONT_AND_BACK, GL2GL3.GL_LINE);
break;
default:
break;
}
}
protected void applyPolygonModeFill(GL gl) {
if (gl.isGL2()) {
applyPolygonModeFillGL2(gl);
} else {
applyPolygonModeFillGLES2();
}
}
public void applyPolygonModeFillGLES2() {
switch (polygonMode) {
case FRONT:
GLES2CompatUtils.glPolygonMode(GL.GL_FRONT, GL2GL3.GL_FILL);
break;
case BACK:
GLES2CompatUtils.glPolygonMode(GL.GL_BACK, GL2GL3.GL_FILL);
break;
case FRONT_AND_BACK:
GLES2CompatUtils.glPolygonMode(GL.GL_FRONT_AND_BACK, GL2GL3.GL_FILL);
break;
default:
break;
}
}
public void applyPolygonModeFillGL2(GL gl) {
switch (polygonMode) {
case FRONT:
gl.getGL2().glPolygonMode(GL.GL_FRONT, GL2GL3.GL_FILL);
break;
case BACK:
gl.getGL2().glPolygonMode(GL.GL_BACK, GL2GL3.GL_FILL);
break;
case FRONT_AND_BACK:
gl.getGL2().glPolygonMode(GL.GL_FRONT_AND_BACK, GL2GL3.GL_FILL);
break;
default:
break;
}
}
protected void polygonOffseFillEnable(GL gl) {
gl.glEnable(GL.GL_POLYGON_OFFSET_FILL);
gl.glPolygonOffset(1.0f, 1.0f);
}
protected void polygonOffsetFillDisable(GL gl) {
gl.glDisable(GL.GL_POLYGON_OFFSET_FILL);
}
/* 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();
}
}
@Override
public void applyGeometryTransform(Transform transform) {
for (Point p : points) {
p.xyz = transform.compute(p.xyz);
}
updateBounds();
}
@Override
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 */
@Override
public double getDistance(Camera camera) {
return getBarycentre().distance(camera.getEye());
}
@Override
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;
}
@Override
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
*/
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.
*
* 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.
*
* @param composite
* @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);
}
}
}
/* COLOR */
@Override
public void setColorMapper(ColorMapper mapper) {
this.mapper = mapper;
fireDrawableChanged(new DrawableChangedEvent(this, DrawableChangedEvent.FIELD_COLOR));
}
@Override
public ColorMapper getColorMapper() {
return mapper;
}
@Override
public void setColor(Color color) {
this.color = color;
for (Point p : points)
p.setColor(color);
fireDrawableChanged(new DrawableChangedEvent(this, DrawableChangedEvent.FIELD_COLOR));
}
@Override
public Color getColor() {
return color;
}
@Override
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;
}
Ads help maintain this website.