#include "libfisheye/Fisheye.hxx" // XXX homogeneous coordinates for helping texture coordinates namespace Coords { using std::vector; using std::cout; using namespace Vec23; class CoordSys { protected: CoordSys *super; float *params; public: virtual void setSuper(CoordSys *super) { this->super = super; } virtual void setParams(float *params) { this->params = params; } // For Pt as well? /** Call glVertex with the given ZPt transformed * into this coordinate system. */ virtual void vertex(const ZPt &p) const = 0; /** Return the given ZPt transformed * into this coordinate system. * Note that some "coordinate systems" may overload * this to return e.g. a color in the ZPt always, * without regard to the parameter. */ virtual ZPt transform(const ZPt &p) const = 0; /** How nonlinear is the coordinate system at the given point. * The return value is 1/l where l would be a reasonable length for dicing. * Returns 0 if dicing is required. */ virtual float nonlinearity(const ZPt &p) { return 0; } /** Whether this transformation can be performed by OpenGL * alone. */ virtual bool canPerformGL() { return false; } /** Try to perform the GL operations to set this * coordinate system in the modelview matrix. * Only the topmost modelview matrix may be altered by * this routine, no other GL state. * @return True if successful, but if false is * returned, then the modelview matrix * is in an undefined state. If this is * not acecptable, try canPerformGL() first. */ virtual bool performGL() { return false; } virtual ~CoordSys() { } virtual void dump() { cout << "Unknown coordsys\n"; } }; class RootCoords : public CoordSys { public: virtual ZPt transform(const ZPt &p) const { return p; } virtual void vertex(const ZPt &p) const { glVertex3f(p.x, p.y, p.z); } }; /** Affine coordinate system (in xy), offset in z. * Parameter layout: x, y, depth, xx, xy, yx, yy */ class AffineXYCoords : public CoordSys { public: enum { NParams = 7 }; /** Perform the internal transformation of this * coordsys. */ void tr(const ZPt &from, ZPt &to) const { to.x = params[0] + from.x * params[3] + from.y * params[4]; to.y = params[1] + from.x * params[5] + from.y * params[6]; to.z = params[2] + from.z; } virtual ZPt transform(const ZPt &p) const { ZPt mp; tr(p, mp); return super->transform(mp); } virtual void vertex(const ZPt &p) const { ZPt mp; tr(p, mp); super->vertex(mp); } }; /** Rotation clockwise. * Parameter layout: angle (degrees) */ class RotateXYCoords : public CoordSys { float s, c; public: enum { NParams = 1 }; virtual void setParams(float *params) { CoordSys::setParams(params); s = sin(params[0]); c = cos(params[0]); } /** Perform the internal transformation of this * coordsys. */ void tr(const ZPt &from, ZPt &to) const { to.x = c * from.x + s * from.y; to.y = -s * from.x + c * from.y; to.z = from.z; } virtual ZPt transform(const ZPt &p) const { ZPt mp; tr(p, mp); return super->transform(mp); } virtual void vertex(const ZPt &p) const { ZPt mp; tr(p, mp); super->vertex(mp); } }; ; ; /** Distorted coordinate system. * Parameter layout: x, y (of center), log(mag), log(min), w, h. * W and h give the width and height in the inside coordinate system * of the zoomed area. */ class DistortCoords : public CoordSys { float mmin; float mmax; Fisheye::vector_mag_isotropic distort; public: enum { NParams = 6 }; virtual void setParams(float *params) { CoordSys::setParams(params); mmax = exp(params[2]); mmin = exp(params[3]); distort.f = Fisheye::scalar_mag_atan(mmax / mmin); } virtual ZPt transform(const ZPt &p) const { ZPt mp; tr(p, mp); return super->transform(mp); } virtual void vertex(const ZPt &p) const { ZPt mp; tr(p, mp); super->vertex(mp); } void tr(const ZPt &from, ZPt &to) const { to = distort(from); to.x *= mmin; to.y *= mmin; } }; struct SomeFactory { virtual int nparams() = 0; virtual CoordSys *create() = 0; }; template class Factory : public SomeFactory { public: virtual int nparams() { return C::NParams; } virtual CoordSys *create() { return new C(); } }; extern SomeFactory* facs[]; /** A class that manages a set of coordinate systems. */ class CoordSet { vector cs; vector params; RootCoords *root; int nparams(int typecode) { return facs[typecode]->nparams(); } CoordSys *create(int typecode) { return facs[typecode]->create(); } public: ~CoordSet() { delete root; } void clean() { for(unsigned i=0; i