package ddddbb.math; import ddddbb.comb.ACell; import ddddbb.comb.DSignedAxis; public abstract class Camera4d extends Camera { public static Point4d[] initialV(Point4d viewDirIn, Point4d eyeInOut) { Point4d w = new Point4d(0,0,0,1); Point4d[] v = new Point4d[] { new Point4d(1,0,0,0), new Point4d(0,1,0,0), new Point4d(0,0,1,0), new Point4d(0,0,0,1) }; eyeInOut.rotate(w, viewDirIn); for (int i=0;i<4;i++) { v[i].rotate(w, viewDirIn); } assert v[3].equals(viewDirIn.clone().normalize()) : v[3] + "!=" + viewDirIn; return v; } protected static Point4d defaultInitialEye() { return new Point4d(3,2,0,0); } protected static Point4d[] defaultInitialV() { return new Point4d[] { new Point4d(1,0,0,0), new Point4d(0,1,0,0), new Point4d(0,0,1,0), new Point4d(0,0,0,1) }; } // public abstract void rotate(double ph, Point4d a4d, Point4d b4d, Point4d p4d); //public abstract void initAxes(double ph1,double ph2,double ph3); // public abstract void initAxes(DSignedAxis a); /** projects the point p to res via this camera * and returns whether the point p was in front of the camera */ protected abstract boolean nproj3d(Point4d p,Point3d res); public abstract Point4d viewingDirection(); public abstract boolean facedBy(ACell d); public Point4d eye; private double zoom = 1; protected final Point4d initialEye; protected final Point4d[] initialV; private int orientation = +1; //+1 for left-handed or -1 for right-handed /** Specify initial camera v coordinate system with origin at eye. * v[3] is supposed to be the viewing direction in the left-handed case. * Coordinate system must be orthonormal. * */ protected Camera4d(Point4d _initialEye,Point4d[] _initialV) { initialEye = _initialEye; initialV = _initialV; v = new Point4d[4]; //v[0],v[1],v[2] projection plane; v[3] viewing direction setToDefault(); //no changed() comes outside as long as initialization } /** Camera coordinate system is derived by rotating * the standard R4 basis and initial eye by (0,0,0,1) -> initialViewDir */ protected Camera4d(Point4d _initialEye, Point4d initialViewDir) { initialEye = _initialEye; initialV = initialV(initialViewDir,eye); assert v[0].equals(initialViewDir); setToDefault(); } private void initAxes() { for (int i=0;i<4;i++) { v[i] = initialV[i].clone(); } eye = initialEye.clone(); } private void initAxes(DSignedAxis axis) { initAxes(); Point4d w = AOP.unitVector4(3); Point4d x = AOP.unitVector4(0); Point4d a = new Point4d(axis); if (axis.human()==-4) { rotateAxes(w,x); rotateAxes(x,a); eye.rotate(w,x); eye.rotate(x,a ); } else { rotateAxes(w,a); eye.rotate(w,a); } } public void setZoom(double _zoom) { if (zoom!=_zoom) { zoom = _zoom; changed(); } } //sets cameras viewing direction given by the poloar coordinate arcs //aligns other directions with local tetrahedrals of the sphere public void initAxes(double ph1,double ph2,double ph3) { eye = initialEye.clone(); v = eye.polarRotate(ph1, ph2, ph3); changed(); } // private void setViewArb0() { // eye=new Point4d(0,0,0,-zoom); //// setDirec(Math.PI/4,0,-Math.PI/6); // setDirec(0,0,0); // eye.translate(new Point4d(3.5,2.7,1,-1)); // } public void rotate(Point4d a,Point4d b) { assert a.isNormal() && b.isNormal(); rotate(a.arc(b),a,b,new Point4d(0,0,0,0)); changed(); } public void translate(Point a,double dist) { assert a.dim() == 4; assert a.isNormal(); eye.addby(a,dist); changed(); } private void rotateAxes(Point4d a,Point4d b) { assert a.isNormal() && b.isNormal(); for (int i=0;i<4;i++) { v[i].rotate(a,b); } AOP.orthoNormalize(v); //avoid those tiny drifts } public void rotate(double ph,Point a, Point b, Point c) { assert a.dim() == 4 : a.dim(); assert b.dim() == 4 : b.dim(); assert c.dim() == 4 : c.dim(); for (int i=0;i<4;i++) { v[i].rotate(ph, a,b); } eye.rotate(ph,a,b,c); AOP.orthoNormalize(v); //avoid those tiny drifts changed(); } public void setToDefault() { notify=false; setOrientation(1); initAxes(); zoom = 1; notify=true; changed(); } public Point getDirec() { return viewingDirection().getPolarArcs(); } public Point getEye() { return eye; } public void setEye(double x1, double x2, double x3, double x4) { eye = new Point4d(x1,x2,x3,x4); changed(); } @SuppressWarnings("serial") public static class ProjectionException extends Exception { } /** Returns true if p4 is in front of this camera */ public boolean proj3d(Point4d p4,Point3d p3) { boolean inFront = nproj3d(p4,p3); p3.multiply(zoom); return inFront; } public void setDirec(DSignedAxis a) { initAxes(a); changed(); } private void swapOrientation() { orientation *= -1; for (int i=0;i<4;i++) { v[i].x[3] *= -1; } eye.x[3] *= -1; } /** +1 for left handed, -1 for right handed */ public void setOrientation(int _orientation) { if (orientation != _orientation) { swapOrientation(); } changed(); } public int getOrientation() { return orientation; } }