#ifndef POINT_H #define POINT_H #ifndef POINT_EXTERN #define POINT_EXTERN extern #endif #include const float point_fudge = .000001; class Point { public: inline Point operator=(Point a); inline Point operator=(GLfloat *a); inline Point operator+(Point a); inline Point operator+=(Point a); inline Point operator-(Point a); // This takes a cross-product inline Point operator*(Point b); inline Point operator*(GLfloat b); inline Point operator*=(GLfloat b); inline Point operator/(GLfloat b); inline Point operator/=(GLfloat b); inline GLfloat& operator[](int index); inline void set(GLfloat x, GLfloat y, GLfloat z, GLfloat w = 1.0); inline GLfloat dist(Point b); inline GLfloat dot(Point b); inline GLfloat dot(GLfloat x, GLfloat y, GLfloat z); inline GLfloat mag(); inline GLfloat magsquared(); inline Point unit(); inline void unitize(); inline Point scale(Point p); // Angle is in RADIANS inline Point rotate(Point axis, GLfloat angle); inline Point rotate(Point axis, GLfloat c, GLfloat s); inline void rotate_self(Point axis, GLfloat c, GLfloat s); Point rotate_abouty(GLfloat c, GLfloat s); Point rotate_aboutz(GLfloat c, GLfloat s); // Returns point projected through proj_pt into XY plane // Does nothing if proj_pt - *this is parallel to XY plane inline Point project(Point proj_pt); inline void project_self(Point proj_pt); inline void Point::project_self(GLfloat px, GLfloat py, GLfloat pz); inline Point project_direction(Point direction); inline Point Point::project_direction(GLfloat x, GLfloat y, GLfloat z); // This projects (px, py, pz) into this in direction (dx, dy, dz) inline void Point::compute_projected(GLfloat px, GLfloat py, GLfloat pz, GLfloat x, GLfloat y, GLfloat z); // Returns point projected through light and refracted into XY // plane. // N is normal at point (ie normal at *this) // I is the index of refraction inline Point refract(Point light, Point N, GLfloat I); void refract_self(Point light, Point N, GLfloat I); Point refract_direction(Point light, Point N, GLfloat I); inline void glvertex(); inline void glnormal(); void print(); void print(const char *format); GLfloat pt[4]; private: }; POINT_EXTERN Point val; #define DOT(a, b) (a.pt[0]*b.pt[0] + a.pt[1]*b.pt[1] + a.pt[2]*b.pt[2]) #define THIS_DOT(b) (pt[0]*b.pt[0] + pt[1]*b.pt[1] + pt[2]*b.pt[2]) inline Point Point::operator=(Point a) { pt[0] = a.pt[0]; pt[1] = a.pt[1]; pt[2] = a.pt[2]; pt[3] = a.pt[3]; return *this; } inline Point Point::operator=(GLfloat *a) { pt[0] = a[0]; pt[1] = a[1]; pt[2] = a[2]; pt[3] = 1; return *this; } inline Point Point::operator+(Point a) { val.pt[0] = pt[0] + a.pt[0]; val.pt[1] = pt[1] + a.pt[1]; val.pt[2] = pt[2] + a.pt[2]; return val; } inline Point Point::operator+=(Point a) { pt[0] += a.pt[0]; pt[1] += a.pt[1]; pt[2] += a.pt[2]; return *this; } inline Point Point::operator-(Point a) { val.pt[0] = pt[0] - a.pt[0]; val.pt[1] = pt[1] - a.pt[1]; val.pt[2] = pt[2] - a.pt[2]; return val; } inline Point Point::operator*(Point b) { val.pt[0] = pt[1]*b.pt[2] - b.pt[1]*pt[2]; val.pt[1] = pt[2]*b.pt[0] - b.pt[2]*pt[0]; val.pt[2] = pt[0]*b.pt[1] - pt[1]*b.pt[0]; return val; } inline Point Point::operator*(GLfloat b) { val.pt[0] = pt[0] * b; val.pt[1] = pt[1] * b; val.pt[2] = pt[2] * b; return val; } inline Point Point::operator*=(GLfloat b) { pt[0] *= b; pt[1] *= b; pt[2] *= b; return *this; } inline Point Point::operator/(GLfloat b) { val.pt[0] = pt[0] / b; val.pt[1] = pt[1] / b; val.pt[2] = pt[2] / b; return val; } inline Point Point::operator/=(GLfloat b) { pt[0] /= b; pt[1] /= b; pt[2] /= b; return *this; } inline GLfloat& Point::operator[](int index) { return pt[index]; } inline void Point::set(GLfloat x, GLfloat y, GLfloat z, GLfloat w) { pt[0] = x; pt[1] = y; pt[2] = z; pt[3] = w; } inline GLfloat Point::dist(Point b) { return (*this - b).mag(); } inline GLfloat Point::dot(Point b) { return pt[0]*b.pt[0] + pt[1]*b.pt[1] + pt[2]*b.pt[2]; } inline GLfloat Point::dot(GLfloat x, GLfloat y, GLfloat z) { return pt[0]*x + pt[1]*y + pt[2]*z; } inline GLfloat Point::mag() { return sqrt(pt[0]*pt[0] + pt[1]*pt[1] + pt[2]*pt[2]); } inline GLfloat Point::magsquared() { return pt[0]*pt[0] + pt[1]*pt[1] + pt[2]*pt[2]; } inline Point Point::unit() { GLfloat m = sqrt(pt[0]*pt[0] + pt[1]*pt[1] + pt[2]*pt[2]); val.pt[0] = pt[0] / m; val.pt[1] = pt[1] / m; val.pt[2] = pt[2] / m; return val; } inline void Point::unitize() { GLfloat m = sqrt(pt[0]*pt[0] + pt[1]*pt[1] + pt[2]*pt[2]); pt[0] /= m; pt[1] /= m; pt[2] /= m; } inline Point Point::scale(Point p) { val.pt[0] = pt[0] * p.pt[0]; val.pt[1] = pt[1] * p.pt[1]; val.pt[2] = pt[2] * p.pt[2]; return val; } inline Point Point::rotate(Point axis, GLfloat angle) { return rotate(axis, cos(angle), sin(angle)); } inline Point Point::rotate(Point axis, GLfloat c, GLfloat s) { float x = axis.pt[0], y = axis.pt[1], z = axis.pt[2], t = 1.0 - c; float tx, ty; tx = t*x; /* Taking advantage of inside info that this is a common case */ if (y == 0.0) { val.pt[0] = pt[0]*(tx*x + c) + pt[1]*(-s*z) + pt[2]*(tx*z); val.pt[1] = pt[0]*(s*z) + pt[1]*c + pt[2]*(-s*x); val.pt[2] = pt[0]*(tx*z) + pt[1]*s*x + pt[2]*(t*z*z + c); } else { ty = t*y; val.pt[0] = pt[0]*(tx*x + c) + pt[1]*(tx*y - s*z) + pt[2]*(tx*z + s*y); val.pt[1] = pt[0]*(tx*y + s*z) + pt[1]*(ty*y + c) + pt[2]*(ty*z - s*x); val.pt[2] = pt[0]*(tx*z - s*y) + pt[1]*(ty*z + s*x) + pt[2]*(t*z*z + c); } return val; } inline void Point::rotate_self(Point axis, GLfloat c, GLfloat s) { float Px, Py, Pz; float x = axis.pt[0], y = axis.pt[1], z = axis.pt[2], t = 1.0 - c; float tx, ty; tx = t*x; Px = pt[0]; Py = pt[1]; Pz = pt[2]; /* Taking advantage of inside info that this is a common case */ if (!y) { pt[0] = Px*(tx*x + c) + Py*(-s*z) + Pz*(tx*z); pt[1] = Px*(s*z) + Py*c + Pz*(-s*x); pt[2] = Px*(tx*z) + Py*s*x + Pz*(t*z*z + c); } else { ty = t*y; pt[0] = Px*(tx*x + c) + Py*(tx*y - s*z) + Pz*(tx*z + s*y); pt[1] = Px*(tx*y + s*z) + Py*(ty*y + c) + Pz*(ty*z - s*x); pt[2] = Px*(tx*z - s*y) + Py*(ty*z + s*x) + Pz*(t*z*z + c); } } inline void Point::glvertex() { glVertex3fv(pt); } inline void Point::glnormal() { glNormal3fv(pt); } inline Point Point::project(Point proj_pt) { GLfloat dirx = pt[0] - proj_pt.pt[0], diry = pt[1] - proj_pt.pt[1], dirz = pt[2] - proj_pt.pt[2]; GLfloat t; if (fabs(dirz) < point_fudge) val = *this; else { t = -proj_pt.pt[2] / dirz; val.pt[0] = proj_pt.pt[0] + dirx*t; val.pt[1] = proj_pt.pt[1] + diry*t; val.pt[2] = 0.0; } return val; } // This naively assumes that proj_pt[z] != this->pt[z] inline void Point::project_self(Point proj_pt) { GLfloat dirx = pt[0] - proj_pt.pt[0], diry = pt[1] - proj_pt.pt[1], dirz = pt[2] - proj_pt.pt[2]; GLfloat t; t = -proj_pt.pt[2] / dirz; pt[0] = proj_pt.pt[0] + dirx*t; pt[1] = proj_pt.pt[1] + diry*t; pt[2] = 0.0; } inline void Point::project_self(GLfloat px, GLfloat py, GLfloat pz) { GLfloat dirx = pt[0] - px, diry = pt[1] - py, dirz = pt[2] - pz, t; t = -pz / dirz; pt[0] = px + dirx*t; pt[1] = py + diry*t; pt[2] = 0.0; } inline Point Point::project_direction(Point direction) { GLfloat t; t = -pt[2] / direction.pt[2]; val.pt[0] = pt[0] + direction.pt[0]*t; val.pt[1] = pt[1] + direction.pt[1]*t; val.pt[2] = 0; return val; } inline Point Point::project_direction(GLfloat x, GLfloat y, GLfloat z) { GLfloat t; t = -pt[2] / z; val.pt[0] = pt[0] + x*t; val.pt[1] = pt[1] + y*t; val.pt[2] = 0; return val; } inline void Point::compute_projected(GLfloat px, GLfloat py, GLfloat pz, GLfloat dx, GLfloat dy, GLfloat dz) { GLfloat t = -pz / dz; pt[0] = px + dx*t; pt[1] = py + dy*t; pt[2] = 0; } #undef POINT_EXTERN #endif