package org.geogebra.common.geogebra3D.euclidian3D.openGL; import org.geogebra.common.awt.GColor; import org.geogebra.common.kernel.Matrix.Coords; /** * Class that describes the geometry of the 3D cursor * * @author ggb3D * */ public class PlotterCursor { public static final int TYPE_CROSS2D = 0; public static final int TYPE_DIAMOND = 1; public static final int TYPE_CYLINDER = 2; public static final int TYPE_CROSS3D = 3; public static final int TYPE_ALREADY_XY = 4; public static final int TYPE_ALREADY_Z = 5; public static final int TYPE_ALREADY_XYZ = 6; public static final int TYPE_CUBE = 7; public static final int TYPE_SPHERE = 8; public static final int TYPE_SPHERE_HIGHLIGHTED = 9; public static final int TYPE_ROTATION = 10; static private int TYPE_LENGTH = 11; static private float size = 12f; static private float thickness = 1.25f; static private float thickness2 = 1.25f; static private float depth = 1f; static private float size_start_move = 7f; static private float size_move = 40f; static private float thickness3 = 2 * thickness; static private float size_cube = size_start_move; private int[] index; private Manager manager; /** * common constructor * * @param geometryRenderer */ public PlotterCursor(Manager manager) { this.manager = manager; manager.setScalerIdentity(); index = new int[TYPE_LENGTH]; // crosses for (int i = 0; i < 4; i++) { index[i] = manager.startNewList(-1); manager.startGeometry(Manager.Type.TRIANGLES); cursor(i); manager.endGeometry(); manager.endList(); } // moving cursors PlotterBrush brush = manager.getBrush(); brush.setArrowType(PlotterBrush.ARROW_TYPE_SIMPLE); // sets the thickness for arrows brush.setThickness(1, 1f); brush.setAffineTexture(0.5f, 0.125f); // xy brush.start(-1); brush.setColor(GColor.GRAY); brush.setThickness(thickness3);// re sets the thickness brush.segment(new Coords(size_start_move, 0, 0, 1), new Coords(size_move, 0, 0, 1)); brush.setThickness(thickness3);// re sets the thickness brush.segment(new Coords(-size_start_move, 0, 0, 1), new Coords(-size_move, 0, 0, 1)); brush.setThickness(thickness3);// re sets the thickness brush.segment(new Coords(0, size_start_move, 0, 1), new Coords(0, size_move, 0, 1)); brush.setThickness(thickness3);// re sets the thickness brush.segment(new Coords(0, -size_start_move, 0, 1), new Coords(0, -size_move, 0, 1)); index[TYPE_ALREADY_XY] = brush.end(); // z brush.start(-1); brush.setColor(GColor.GRAY); brush.setThickness(thickness3);// re sets the thickness brush.segment(new Coords(0, 0, size_start_move, 1), new Coords(0, 0, size_move, 1)); brush.setThickness(thickness3);// re sets the thickness brush.segment(new Coords(0, 0, -size_start_move, 1), new Coords(0, 0, -size_move, 1)); index[TYPE_ALREADY_Z] = brush.end(); // xyz brush.start(-1); brush.setColor(GColor.GRAY); brush.setThickness(thickness3);// re sets the thickness brush.segment(new Coords(size_start_move, 0, 0, 1), new Coords(size_move, 0, 0, 1)); brush.setThickness(thickness3);// re sets the thickness brush.segment(new Coords(-size_start_move, 0, 0, 1), new Coords(-size_move, 0, 0, 1)); brush.setThickness(thickness3);// re sets the thickness brush.segment(new Coords(0, size_start_move, 0, 1), new Coords(0, size_move, 0, 1)); brush.setThickness(thickness3);// re sets the thickness brush.segment(new Coords(0, -size_start_move, 0, 1), new Coords(0, -size_move, 0, 1)); brush.setThickness(thickness3);// re sets the thickness brush.segment(new Coords(0, 0, size_start_move, 1), new Coords(0, 0, size_move, 1)); brush.setThickness(thickness3);// re sets the thickness brush.segment(new Coords(0, 0, -size_start_move, 1), new Coords(0, 0, -size_move, 1)); index[TYPE_ALREADY_XYZ] = brush.end(); brush.setArrowType(PlotterBrush.ARROW_TYPE_NONE); // cube index[TYPE_CUBE] = manager.startNewList(-1); manager.startGeometry(Manager.Type.TRIANGLES); color(0.5f, 0.5f, 0.5f); // up manager.normal(0, 0, 1); quad(size_cube, size_cube, size_cube, -size_cube, size_cube, size_cube, -size_cube, -size_cube, size_cube, size_cube, -size_cube, size_cube); // down manager.normal(0, 0, -1); quad(size_cube, size_cube, -size_cube, size_cube, -size_cube, -size_cube, -size_cube, -size_cube, -size_cube, -size_cube, size_cube, -size_cube); // right manager.normal(1, 0, 0); quad(size_cube, size_cube, size_cube, size_cube, -size_cube, size_cube, size_cube, -size_cube, -size_cube, size_cube, size_cube, -size_cube); // left manager.normal(-1, 0, 0); quad(-size_cube, size_cube, size_cube, -size_cube, size_cube, -size_cube, -size_cube, -size_cube, -size_cube, -size_cube, -size_cube, size_cube); // back manager.normal(0, 1, 0); quad(size_cube, size_cube, size_cube, size_cube, size_cube, -size_cube, -size_cube, size_cube, -size_cube, -size_cube, size_cube, size_cube); // front manager.normal(0, -1, 0); quad(size_cube, -size_cube, size_cube, -size_cube, -size_cube, size_cube, -size_cube, -size_cube, -size_cube, size_cube, -size_cube, -size_cube); manager.endGeometry(); manager.endList(); // sphere index[TYPE_SPHERE] = manager.startNewList(-1); manager.startGeometry(Manager.Type.TRIANGLES); cursorSphere(0.25f, 0.25f); manager.endGeometry(); manager.endList(); // sphere index[TYPE_SPHERE_HIGHLIGHTED] = manager.startNewList(-1); manager.startGeometry(Manager.Type.TRIANGLES); cursorSphere(0.75f, 0.25f); manager.endGeometry(); manager.endList(); // rotation brush.start(-1); brush.setColor(GColor.GRAY); brush.setThickness(thickness3);// re sets the thickness brush.arcExtendedWithArrows(new Coords(0, 0, 0, 1), new Coords(1, 0, 0, 0), new Coords(0, 1, 0, 0), size_move / 2, -Math.PI * 0.6, Math.PI * 1.2, 64); index[TYPE_ROTATION] = brush.end(); manager.setScalerView(); } private float r, g, b, a; private void color(float red, float green, float blue, float alpha) { this.r = red; this.g = green; this.b = blue; this.a = alpha; } private void color(float red, float green, float blue) { color(red, green, blue, 1f); } private void vertex(float x, float y, float z) { manager.color(r, g, b, a); manager.vertex(x, y, z); } private void quad(float x1, float y1, float z1, float x2, float y2, float z2, float x3, float y3, float z3, float x4, float y4, float z4) { vertex(x1, y1, z1); vertex(x2, y2, z2); vertex(x3, y3, z3); vertex(x1, y1, z1); vertex(x3, y3, z3); vertex(x4, y4, z4); } /** * used to say if light is on or not * * @param type * @return true it type is of "already" (xy or z) */ public static final boolean isTypeAlready(int type) { return type == TYPE_ALREADY_XY || type == TYPE_ALREADY_Z || type == TYPE_ALREADY_XYZ || type == TYPE_CUBE || type == TYPE_ROTATION; } // //////////////////////////////// // INDEX // //////////////////////////////// /** * return geometry index for each type of cursor * * @param i * @return geometry index for each type of cursor */ public int getIndex(int i) { return index[i]; } // //////////////////////////////// // GEOMETRIES // //////////////////////////////// private void cursor(int i) { switch (i) { default: case 0: cursorCross2D(); break; case 1: cursorDiamond(); break; case 2: cursorCylinder(); break; case 3: cursorCross3D(); break; } } private void cursorCross2D() { // white parts color(1, 1, 1); // up quad(thickness, size, depth, -thickness, size, depth, -thickness, -size, depth, thickness, -size, depth); quad(size, thickness, depth, thickness, thickness, depth, thickness, -thickness, depth, size, -thickness, depth); quad(-size, thickness, depth, -size, -thickness, depth, -thickness, -thickness, depth, -thickness, thickness, depth); // down quad(thickness, size, -depth, thickness, -size, -depth, -thickness, -size, -depth, -thickness, size, -depth); quad(size, thickness, -depth, size, -thickness, -depth, thickness, -thickness, -depth, thickness, thickness, -depth); quad(-size, thickness, -depth, -thickness, thickness, -depth, -thickness, -thickness, -depth, -size, -thickness, -depth); // black parts color(0, 0, 0); // up and down quadSymxOyRotOz90SymOz(thickness, thickness, depth, thickness + thickness2, thickness + thickness2, depth, thickness + thickness2, size + thickness2, depth, thickness, size, depth); quadSymxOyRotOz90SymOz(thickness, -thickness, depth, thickness, -size, depth, thickness + thickness2, -size - thickness2, depth, thickness + thickness2, -thickness - thickness2, depth); quadSymxOyRotOz90SymOz(size, thickness, depth, size, -thickness, depth, size + thickness2, -thickness - thickness2, depth, size + thickness2, thickness + thickness2, depth); // edges quadSymxOyRotOz90SymOz(thickness + thickness2, thickness + thickness2, -depth, thickness + thickness2, size + thickness2, -depth, thickness + thickness2, size + thickness2, depth, thickness + thickness2, thickness + thickness2, depth); quadSymxOyRotOz90SymOz(thickness + thickness2, -thickness - thickness2, -depth, thickness + thickness2, -thickness - thickness2, depth, thickness + thickness2, -size - thickness2, depth, thickness + thickness2, -size - thickness2, -depth); quadRotOz90SymOz(size + thickness2, thickness + thickness2, -depth, size + thickness2, thickness + thickness2, depth, size + thickness2, -thickness - thickness2, depth, size + thickness2, -thickness - thickness2, -depth); } private void cursorCross3D() { float t = (float) (thickness / Math.tan(Math.PI / 8)); float size2 = size + thickness2; // white parts color(1, 1, 1); quadSymxOyRotOz90SymOz(thickness, t, t, -thickness, t, t, -thickness, t, size2, thickness, t, size2); quadSymxOyRotOz90SymOz(thickness, t, t, thickness, size2, t, -thickness, size2, t, -thickness, t, t); quadRotOz90SymOz(t, t, thickness, t, t, -thickness, t, size2, -thickness, t, size2, thickness); quadRotOz90SymOz(-t, t, thickness, -t, size2, thickness, -t, size2, -thickness, -t, t, -thickness); quadRotOz90SymOz(thickness, size2 + t - thickness, -thickness, -thickness, size2 + t - thickness, -thickness, -thickness, size2 + t - thickness, thickness, thickness, size2 + t - thickness, thickness); quadSymxOyRotOz90SymOz(thickness, -thickness, size2 + t - thickness, thickness, thickness, size2 + t - thickness, -thickness, thickness, size2 + t - thickness, -thickness, -thickness, size2 + t - thickness); // black parts color(0, 0, 0); quadSymxOyRotOz90SymOz(t, t, t, t, t, size2, t, thickness, size2, t, thickness, t); quadSymxOyRotOz90SymOz(thickness, t, t, thickness, t, size2, t, t, size2, t, t, t); quadSymxOyRotOz90SymOz(t, t, t, t, t, thickness, t, size2, thickness, t, size2, t); quadSymxOyRotOz90SymOz(thickness, t, t, t, t, t, t, size2, t, thickness, size2, t); quadSymxOyRotOz90SymOz(-t, t, t, -t, size2, t, -t, size2, thickness, -t, t, thickness); quadSymxOyRotOz90SymOz(-thickness, t, t, -thickness, size2, t, -t, size2, t, -t, t, t); quadSymxOyRotOz90SymOz(t, size2, t, t, size2 + t - thickness, t, -t, size2 + t - thickness, t, -t, size2, t); quadSymxOyRotOz90SymOz(t, size2 + t - thickness, t, t, size2 + t - thickness, thickness, -t, size2 + t - thickness, thickness, -t, size2 + t - thickness, t); quadRotOz90SymOz(t, size2, t, t, size2, -t, t, size2 + t - thickness, -t, t, size2 + t - thickness, t); quadRotOz90SymOz(t, size2 + t - thickness, thickness, t, size2 + t - thickness, -thickness, thickness, size2 + t - thickness, -thickness, thickness, size2 + t - thickness, thickness); quadRotOz90SymOz(-t, size2, t, -t, size2 + t - thickness, t, -t, size2 + t - thickness, -t, -t, size2, -t); quadRotOz90SymOz(-t, size2 + t - thickness, thickness, -thickness, size2 + t - thickness, thickness, -thickness, size2 + t - thickness, -thickness, -t, size2 + t - thickness, -thickness); quadSymxOyRotOz90SymOz(t, t, size2, t, t, size2 + t - thickness, t, -t, size2 + t - thickness, t, -t, size2); quadSymxOyRotOz90SymOz(t, t, size2 + t - thickness, thickness, thickness, size2 + t - thickness, thickness, -thickness, size2 + t - thickness, t, -t, size2 + t - thickness); } private void cursorDiamond() { float t1 = 0.15f; float t2 = 1f - 2 * t1; // black parts color(0, 0, 0); quadSymxOyRotOz90SymOz(1f, 0f, 0f, t2, t1, t1, t1, t1, t2, 0f, 0f, 1f); quadSymxOyRotOz90SymOz(0f, 0f, 1f, t1, t1, t2, t1, t2, t1, 0f, 1f, 0f); quadSymxOyRotOz90SymOz(0f, 1f, 0f, t1, t2, t1, t2, t1, t1, 1f, 0f, 0f); // white parts color(1, 1, 1); quadSymxOyRotOz90SymOz(t2, t1, t1, t2, t1, t1, t1, t2, t1, t1, t1, t2); } private void cursorCylinder() { int latitude = 8; float x1 = 4f; float r1 = PlotterBrush.LINE3D_THICKNESS / 3f; float r2 = (float) (r1 * Math.sqrt(2)); float x2 = x1 / 3; float da = (float) (Math.PI / latitude); float y1; float z1; float y0, z0; // white parts color(1, 1, 1); // ring y1 = 2 * r2 * (float) Math.sin(da); z1 = 2 * r2 * (float) Math.cos(da); for (int i = 1; i <= latitude; i++) { y0 = y1; z0 = z1; y1 = 2 * r2 * (float) Math.sin((2 * i + 1) * da); z1 = 2 * r2 * (float) Math.cos((2 * i + 1) * da); quad(-x2, y0, z0, x2, y0, z0, x2, y1, z1, -x2, y1, z1); } // caps y1 = 2 * r1 * (float) Math.sin(da); z1 = 2 * r1 * (float) Math.cos(da); for (int i = 1; i < latitude / 2; i++) { y0 = y1; z0 = z1; y1 = 2 * r1 * (float) Math.sin((2 * i + 1) * da); z1 = 2 * r1 * (float) Math.cos((2 * i + 1) * da); quadSymOz(x1, y0, z0, x1, -y0, z0, x1, -y1, z1, x1, y1, z1); } // black parts color(0, 0, 0); // ring y1 = 2 * (float) Math.sin(da); z1 = 2 * (float) Math.cos(da); for (int i = 1; i <= latitude; i++) { y0 = y1; z0 = z1; y1 = 2 * (float) Math.sin((2 * i + 1) * da); z1 = 2 * (float) Math.cos((2 * i + 1) * da); quadSymOz(x2, y0 * r2, z0 * r2, x1, y0 * r1, z0 * r1, x1, y1 * r1, z1 * r1, x2, y1 * r2, z1 * r2); } } private void cursorSphere(float gray, float alpha) { manager.setDummyTexture(); color(gray, gray, gray, alpha); int latitude = 8; int r1 = 15; float d = (float) (0.5 * Math.PI / latitude); float rcjp = r1; float z3 = 0; for (int j = 0; j < latitude; j++) { float rcj = rcjp; float x2 = rcj; float y2 = 0f; float z1 = z3; rcjp = (float) (r1 * Math.cos((j + 1) * d)); float x3 = rcjp; float y3 = 0f; z3 = (float) (r1 * Math.sin((j + 1) * d)); for (int i = 0; i < 4 * latitude; i++) { float x1 = x2; float y1 = y2; float ci = (float) (Math.cos((i + 1) * d)); float si = (float) (Math.sin((i + 1) * d)); x2 = ci * rcj; y2 = si * rcj; float x4 = x3; float y4 = y3; x3 = ci * rcjp; y3 = si * rcjp; quad(x1, y1, z1, x2, y2, z1, x3, y3, z3, x4, y4, z3); quad(x1, y1, -z1, x4, y4, -z3, x3, y3, -z3, x2, y2, -z1); } } } private void quadSymxOyRotOz90SymOz(float x1, float y1, float z1, float x2, float y2, float z2, float x3, float y3, float z3, float x4, float y4, float z4) { quadRotOz90SymOz(x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4); quadRotOz90SymOz(x1, y1, -z1, x4, y4, -z4, x3, y3, -z3, x2, y2, -z2); } private void quadRotOz90SymOz(float x1, float y1, float z1, float x2, float y2, float z2, float x3, float y3, float z3, float x4, float y4, float z4) { quadSymOz(x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4); quadSymOz(-y1, x1, z1, -y2, x2, z2, -y3, x3, z3, -y4, x4, z4); } private void quadSymOz(float x1, float y1, float z1, float x2, float y2, float z2, float x3, float y3, float z3, float x4, float y4, float z4) { quad(x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4); quad(-x1, -y1, z1, -x2, -y2, z2, -x3, -y3, z3, -x4, -y4, z4); /* * vertex(-x1,y1,z1); vertex(-x4,y4,z4); vertex(-x3,y3,z3); * vertex(-x2,y2,z2); */ } }