package org.geogebra.common.geogebra3D.euclidian3D.openGL;
import java.util.ArrayList;
import org.geogebra.common.geogebra3D.euclidian3D.EuclidianView3D;
import org.geogebra.common.geogebra3D.euclidian3D.draw.DrawPoint3D;
import org.geogebra.common.geogebra3D.euclidian3D.openGL.ManagerShaders.TypeElement;
import org.geogebra.common.kernel.Matrix.Coords;
import org.geogebra.common.kernel.Matrix.Coords3;
import org.geogebra.common.kernel.discrete.PolygonTriangulation.TriangleFan;
import org.geogebra.common.main.Feature;
/**
* Class that manage all geometry objects
*
* @author mathieu
*
*/
abstract public class Manager {
public static enum Type { // quads and quad strips are not supported in
// gwtgl
TRIANGLE_STRIP, TRIANGLE_FAN, TRIANGLES, LINE_LOOP, LINE_STRIP
}
// geometries
/** geometry : cursor */
public PlotterCursor cursor;
/** geometry : view in front of */
private PlotterViewInFrontOf viewInFrontOf;
/** brush */
private PlotterBrush brush;
/** surfaces */
private PlotterSurface surface;
/** text */
private PlotterText text;
/** mouse cursor */
private PlotterMouseCursor mouseCursor;
/** completing task cursor */
private PlotterCompletingCursor completingCursor;
// geogebra stuff
private EuclidianView3D view3D;
/**
* create a manager for geometries
*
* @param renderer
* openGL renderer
* @param view3D
* 3D view
*/
public Manager(Renderer renderer, EuclidianView3D view3D) {
init(renderer, view3D);
}
public Manager() {
// empty constructor
}
final protected void init(Renderer renderer, EuclidianView3D newView3D) {
// geogebra
this.view3D = newView3D;
setScalerView();
setRenderer(renderer);
initGeometriesList();
// creating geometries
brush = newPlotterBrush();
surface = newPlotterSurface();
text = new PlotterText(this);
cursor = new PlotterCursor(this);
viewInFrontOf = new PlotterViewInFrontOf(this);
mouseCursor = new PlotterMouseCursor(this);
completingCursor = new PlotterCompletingCursor(this);
}
/**
* set the 3D view
*
* @param view3D
* 3D view
*/
public Manager(EuclidianView3D view3D) {
this.view3D = view3D;
}
/**
*
* @return new plotter brush
*/
protected PlotterBrush newPlotterBrush() {
return new PlotterBrush(this);
}
/**
*
* @return new plotter surface
*/
protected PlotterSurface newPlotterSurface() {
return new PlotterSurface(this);
}
/**
* init list of geometries
*/
protected void initGeometriesList() {
// used only for shaders
}
/**
* set the renderer
*
* @param renderer
* renderer
*/
abstract protected void setRenderer(Renderer renderer);
/**
*
* @return the renderer
*/
abstract protected Renderer getRenderer();
public PlotterViewInFrontOf getViewInFrontOf() {
return viewInFrontOf;
}
public PlotterBrush getBrush() {
return brush;
}
public PlotterSurface getSurface() {
return surface;
}
protected PlotterText getText() {
return text;
}
public PlotterMouseCursor getMouseCursor() {
return mouseCursor;
}
public PlotterCompletingCursor getCompletingCursor() {
return completingCursor;
}
// ///////////////////////////////////////////
// GEOGEBRA METHODS
// ///////////////////////////////////////////
/**
* return the 3D view
*
* @return the 3D view
*/
public EuclidianView3D getView3D() {
return view3D;
}
// ///////////////////////////////////////////
// LIST METHODS
// ///////////////////////////////////////////
abstract public int startNewList(int old);
abstract public void endList();
abstract public void startGeometry(Type type);
/**
* direct write in buffer mode
*
* @param type
* geometry type
* @param size
* number of vertices
*/
public void startGeometryDirect(Type type, int size) {
startGeometry(type);
}
abstract public void endGeometry();
/**
* end current geometry (direct buffer mode)
*/
public void endGeometryDirect() {
endGeometry();
}
/**
* end current geometry (only with shaders + elements, with type)
*
* @param size
* geometry size
* @param type
* geometry type
*/
public void endGeometry(int size, TypeElement type) {
// not used for all managers
}
/**
* start drawing polygons
*
* @return geometry index for the polygons
*/
abstract public int startPolygons(int old);
/**
* draw a convex polygon
*
* @param n
* normal
* @param v
* vertices
* @param length
* vertices length (maybe different from v.length due to cache)
* @param reverse
* vertex order has to be reversed
*/
public void drawPolygonConvex(Coords n, Coords[] v, int length,
boolean reverse) {
startGeometry(Type.TRIANGLE_FAN);
// set texture
setDummyTexture();
// set normal
normalToScale(n);
triangleFanApex(v[0]);
if (reverse) {
for (int i = length - 1; i > 0; i--) {
triangleFanVertex(v[i]);
}
} else {
for (int i = 1; i < length; i++) {
triangleFanVertex(v[i]);
}
}
endGeometry();
}
/**
* set dummy texture (needed for GLList)
*/
abstract protected void setDummyTexture();
/**
* draw a triangle fan
*
* @param n
* normal
* @param v
* vertices
* @param triFan
* indices
*/
final private void drawTriangleFan(Coords n, Coords[] v,
TriangleFan triFan) {
startGeometry(Type.TRIANGLE_FAN);
// set texture
setDummyTexture();
// set normal
normalToScale(n);
// fan apex
triangleFanApex(v[triFan.getApexPoint()]);
// int i = 0;
for (int i = 0; i < triFan.size(); i++) {
triangleFanVertex(v[triFan.getVertexIndex(i)]);
}
endGeometry();
}
/**
* end the polygons
*/
abstract public void endPolygons();
// ///////////////////////////////////////////
// DRAWING METHODS
// ///////////////////////////////////////////
abstract public void draw(int index);
abstract public void drawLabel(int index);
abstract public void remove(int index);
/**
* creates a vertex at coordinates (x,y,z)
*
* @param x
* x coord
* @param y
* y coord
* @param z
* z coord
*/
abstract protected void vertex(double x, double y, double z);
/**
* creates a vertex at coordinates (x,y,z) (direct buffer mode)
*
* @param x
* x coord
* @param y
* y coord
* @param z
* z coord
*/
protected void vertexDirect(double x, double y, double z) {
vertex(x, y, z);
}
/**
* creates a vertex at coordinates (x,y,z)
*
* @param x
* x coord
* @param y
* y coord
* @param z
* z coord
*/
abstract protected void vertexInt(double x, double y, double z);
/**
* creates a vertex at coordinates v
*
* @param v
*/
final protected void vertex(Coords v) {
vertex(v.getX(), v.getY(), v.getZ());
}
/**
* scale vertex and draw it
*
* @param v
* vertex
*/
final protected void vertexToScale(Coords v) {
if (view3D.getApplication().has(Feature.DIFFERENT_AXIS_RATIO_3D)) {
vertexToScale(v.getX(), v.getY(), v.getZ());
} else {
vertex(v);
}
}
/**
* scale vertex and draw it
*
* @param x
* x
* @param y
* y
* @param z
* z
*
*/
final protected void vertexToScale(double x, double y, double z) {
if (view3D.getApplication().has(Feature.DIFFERENT_AXIS_RATIO_3D)) {
vertex(x * getXscale(), y * getYscale(), z * getZscale());
} else {
vertex(x, y, z);
}
}
/**
* creates a vertex at coordinates v (direct buffer mode)
*
* @param v
*/
protected void vertexDirect(Coords3 v) {
vertexDirect(v.getXf(), v.getYf(), v.getZf());
}
/**
* set apex for triangle fan
*
* @param v
* apex coords
*/
protected void triangleFanApex(Coords v) {
vertexToScale(v);
}
/**
* set vertex for triangle fan
*
* @param v
* apex coords
*/
protected void triangleFanVertex(Coords v) {
vertexToScale(v);
}
/**
* fill array of vertices
*
* @param vertices
* array of vertices
*/
abstract protected void vertices(double[] vertices);
/**
* creates a normal at coordinates (x,y,z)
*
* @param x
* x coord
* @param y
* y coord
* @param z
* z coord
*/
abstract protected void normal(double x, double y, double z);
/**
* creates a normal at coordinates (x,y,z) (direct buffer mode)
*
* @param x
* x coord
* @param y
* y coord
* @param z
* z coord
*/
protected void normalDirect(double x, double y, double z) {
normal(x, y, z);
}
/**
* creates a normal at coordinates n
*
* @param n
*/
protected void normal(Coords n) {
normal(n.getX(), n.getY(), n.getZ());
}
private Coords normalToScaleTmp = new Coords(3);
/**
* scale normal and draw it
*
* @param n
* normal
*/
final protected void normalToScale(Coords n) {
if (view3D.getApplication().has(Feature.DIFFERENT_AXIS_RATIO_3D)) {
if (scalerXYZ.scaleAndNormalizeNormalXYZ(n, normalToScaleTmp)){
normal(normalToScaleTmp);
} else {
normal(n);
}
} else {
normal(n);
}
}
/**
* creates a normal at coordinates n (direct buffer mode)
*
* @param n
*/
protected void normalDirect(Coords3 n) {
normalDirect(n.getXf(), n.getYf(), n.getZf());
}
/**
* creates a texture at coordinates (x,y)
*
* @param x
* x coord
* @param y
* y coord
*/
abstract protected void texture(double x, double y);
/**
* creates a color (r,g,b)
*
* @param r
* red
* @param g
* green
* @param b
* blue
*
*/
abstract protected void color(double r, double g, double b);
/**
* creates a color (r,g,b,a)
*
* @param r
* red
* @param g
* green
* @param b
* blue
* @param a
* blue alpha
*
*/
abstract protected void color(double r, double g, double b, double a);
/**
* set the line width (for GL_LINE rendering)
*
* @param width
* width
*/
final protected void lineWidth(double width) {
getRenderer().setLineWidth(width);
}
/**
* set the point size (for GL_POINT rendering)
*
* @param size
* size
*/
abstract protected void pointSize(double size);
// ///////////////////////////////////////////
// COLOR METHODS
// ///////////////////////////////////////////
/**
* draws a rectangle
*
* @param x
* @param y
* @param z
* @param width
* @param height
*/
final public int rectangle(double x, double y, double z, double width,
double height, int old) {
int index = startNewList(old);
rectangleGeometry(x, y, z, width, height);
endList();
return index;
}
abstract protected void rectangleGeometry(double x, double y, double z,
double width, double height);
public int rectangleBounds(double x, double y, double z, double width,
double height, int old) {
int index = startNewList(old);
getText().rectangleBounds(x, y, z, width, height);
endList();
return index;
}
/**
*
* @return max number of longitudes
*/
public int getLongitudeMax() {
return 1024;
}
/**
*
* @return default number of longitudes
*/
public int getLongitudeDefault() {
return 64;
}
/**
*
* @param radius
* circle radius
* @param viewScale
* view scale
* @return correct longitudes size regarding radius * viewScale
*/
public int getLongitude(double radius, double viewScale) {
int longitude = 8;
double size = radius * viewScale;
// App.error(""+size);
while (longitude < 2 * size && longitude < getLongitudeDefault()) {// find
// the
// correct
// longitude
// size
longitude *= 2;
}
// Log.debug("getLongitude="+longitude);
return longitude;
}
/**
* draw a point
*
* @param size
* size
* @param center
* center
* @return geometry index
*/
public int drawPoint(int size, Coords center, int index) {
double radius = getView3D()
.unscale(size * DrawPoint3D.DRAW_POINT_FACTOR);
scaleXYZ(center);
center.setW(1); // changed for shaders (point size)
setScalerIdentity();
int ret = drawSphere(size, center, radius, index);
setScalerView();
return ret;
}
/**
* draws a sphere
*
* @param size
* point size
* @param center
* center
* @param radius
* sphere radius
* @return geometry index
*/
final protected int drawSphere(int size, Coords center, double radius,
int index) {
surface.start(index);
surface.drawSphere(size, center, radius);
return surface.end();
}
/**
* draw indexed geometry with center information
*
* @param index
* geometry
* @param center
* center
*/
public void draw(int index, Coords center) {
draw(index);
}
/**
* draw all triangles fans
*
* @param n
* normal
* @param verticesWithIntersections
* all vertices needed for fans
* @param length
* points used
* @param triFanList
* fans list
*/
public void drawTriangleFans(Coords n, Coords[] verticesWithIntersections,
int length, ArrayList<TriangleFan> triFanList) {
for (TriangleFan triFan : triFanList) {
drawTriangleFan(n, verticesWithIntersections, triFan);
}
}
/**
* (used only for elements)
*
* @param size
* size
* @return current geometry indices buffer with correct size
*/
public GLBufferIndices getCurrentGeometryIndices(int size) {
return null;
}
/**
* simple interface to scale coords
*
*/
public interface ScalerXYZ {
/**
* scale x, y, z values
*
* @param coords
* coords
*/
public void scaleXYZ(Coords coords);
/**
* scale and normalize x, y, z values
*
* @param coords
* coords
*
* @return false if nothing scaled (then use coords instead of ret)
*/
public boolean scaleAndNormalizeNormalXYZ(Coords coords, Coords ret);
/**
* @return scale on x-axis
*/
public double getXscale();
/**
* @return scale on y-axis
*/
public double getYscale();
/**
* @return scale on z-axis
*/
public double getZscale();
}
/**
* identity scaler
*/
protected static final ScalerXYZ scalerXYZIdentity = new ScalerXYZ() {
@Override
public void scaleXYZ(Coords coords) {
// do nothing
}
@Override
public boolean scaleAndNormalizeNormalXYZ(Coords coords, Coords ret) {
// do nothing
return false;
}
@Override
public double getXscale() {
return 1;
}
@Override
public double getYscale() {
return 1;
}
@Override
public double getZscale() {
return 1;
}
};
/**
* current scaler (identity/3D view)
*/
protected ScalerXYZ scalerXYZ;
/**
* scale coords using current scaler
*
* @param coords
* coords
*/
public void scaleXYZ(Coords coords) {
if (view3D.getApplication().has(Feature.DIFFERENT_AXIS_RATIO_3D)) {
scalerXYZ.scaleXYZ(coords);
}
}
/**
* @return scale on x-axis
*/
public double getXscale() {
return scalerXYZ.getXscale();
}
/**
* @return scale on y-axis
*/
public double getYscale() {
return scalerXYZ.getYscale();
}
/**
* @return scale on z-axis
*/
public double getZscale() {
return scalerXYZ.getZscale();
}
/**
* set scaler to identity
*/
public void setScalerIdentity() {
scalerXYZ = scalerXYZIdentity;
}
/**
* set scaler to view
*/
public void setScalerView() {
scalerXYZ = view3D;
}
}