#ifndef _GEOMETRY_H_ #define _GEOMETRY_H_ #include // Utility functions // returns true if number is zero within EPSILON tolerance // To modify the value of EPSILON, see "constants.cpp" bool isZero(const float x); // returns the number of zeros (within an EPSILON tolerance) // among three numbers. After execution, "destination" holds // boolean results of zero tests corresponding to each number. int whichAreZero(bool * destination, const float x, const float y, const float z); class Point3 { private: float _x; float _y; float _z; public: // constructors Point3(); Point3(float x, float y, float z); Point3(const Point3 &toBeCopied); // member functions inline void SetX(const float &x){_x = x;} inline void SetY(const float &y){_y = y;} inline void SetZ(const float &z){_z = z;} inline const float GetX() const{return _x;} inline const float GetY() const{return _y;} inline const float GetZ() const{return _z;} inline float GetX() {return _x;} inline float GetY() {return _y;} inline float GetZ() {return _z;} inline void Clear() {_x = 0.0; _y = 0.0; _z = 0.0;} inline bool IsZero(); // operators Point3 operator + (const Point3 &p); Point3 operator - (const Point3 &p); Point3 operator *(float f); friend ostream& operator << (ostream &os, const Point3 &p); friend istream& operator >> (istream &is, Point3 &p); }; float distance(const Point3 &p1, const Point3 &p2); float distanceFromLine(const Point3 &lineP1, const Point3 &lineP2, const Point3 &point); float projection(const Point3 &lineP1, const Point3 &lineP2, const Point3 &point); class Vector3 { private: // assumes origin of vector is at (0, 0, 0) Point3 _endPoint; public: // constructors Vector3(){} Vector3(float x, float y, float z); Vector3(Point3 tip); // assumes origin at (0, 0, 0) Vector3(Point3 tip, Point3 origin); Vector3(const Vector3 &toBeCopied); // member functions inline void SetX(const float &x){_endPoint.SetX(x);} inline void SetY(const float &y){_endPoint.SetY(y);} inline void SetZ(const float &z){_endPoint.SetZ(z);} inline const float GetX() const{return _endPoint.GetX();} inline const float GetY() const{return _endPoint.GetY();} inline const float GetZ() const{return _endPoint.GetZ();} inline float GetX() {return _endPoint.GetX();} inline float GetY() {return _endPoint.GetY();} inline float GetZ() {return _endPoint.GetZ();} inline float Norm(); inline void Normalize(); float Dot(const Vector3 &vec); Vector3 Cross(const Vector3 &w); inline void SetEndPoint(const Point3 &end){_endPoint = end;} inline const Point3 GetEndPoint() const{return _endPoint;} inline bool IsZero(); // operators Vector3 operator +(const Vector3 &vec); Vector3 operator -(const Vector3 &vec); Vector3 operator -(); Vector3 operator *(float f); friend ostream& operator << (ostream &os, const Vector3 &p); friend istream& operator >> (istream &is, Vector3 &p); }; // non-member products float Dot(const Vector3 &vec1, const Vector3 &vec2); Vector3 Cross(const Vector3 &vec1, const Vector3 &vec2); Vector3 Hadamard(const Vector3 &vec1, const Vector3 &vec2); Vector3 ReflectedVector(const Vector3 &vec, const Vector3 &normal, bool glossy); bool RefractedVector(const Vector3 &vec, const Vector3 &normal, const float &refractIndex, Vector3 &transmitted); // This function returns true if the two vectors are proportional. t is returned as the // proportionality factor, namely vec1 = t * vec2 bool areVectorsProportional(const Vector3 &vec1, const Vector3 &vec2, float &t); // interval class class Interval { public: float low, high; Interval(){low = 0.0; high = 0.0;} Interval(float l, float h); friend ostream& operator << (ostream &os, const Interval &i); }; Interval Intersection(Interval i1, Interval i2); // RGB color class. It keeps the RGB values between 0.0 and 1.0. class RGBColor { private: float _red; float _green; float _blue; public: // constructors RGBColor(); RGBColor(float red, float green, float blue); RGBColor(const RGBColor& toBeCopied); // member functions void SetRed(const float &r); void SetGreen(const float &g); void SetBlue(const float &b); const float GetRed() const{return _red;} const float GetGreen() const{return _green;} const float GetBlue() const{return _blue;} float GetRed() {return _red;} float GetGreen() {return _green;} float GetBlue() {return _blue;} // operators RGBColor operator +(const RGBColor& C); void operator += (const RGBColor& C); RGBColor operator -(const RGBColor& C); void operator -= (const RGBColor& C); RGBColor operator *(const float &num); RGBColor operator /(const float &num); float operator *(const RGBColor &C); // dot product friend ostream& operator << (ostream &os, const RGBColor &C); friend istream& operator >> (istream &is, RGBColor &C); }; RGBColor Hadamard(const RGBColor &c1, const RGBColor &c2); class Light; // Material class: encapsulates color and light // parameters. class Material { private: RGBColor _materialColor; float _ambi; // ambient light coefficient float _diff; // diffuse light coefficient float _spec; // specular light coefficient float _specExp ; // specular (Phong) exponent float _refl; // reflective light coefficient float _refr; // refractive index // The three following coefficients are explained on page 164 // of Shirley's book. They represent the respective color // attenuations for Beer's law. float _redAtt; // red attenuation float _greenAtt; // green attenuation float _blueAtt; // blue attenuation bool _metal; // is material a metal? bool _glossy; // is material glossy? bool _dielectric; // is material a dielectric? int _texture; // kind of texture (0 = none, 1 = vertical lines) public: // constructors Material(); Material(const RGBColor& C, float ambi, float diff, float spec, float specExp, float refl, float refr, float redAtt, float greenAtt, float blueAtt, bool metal, bool glossy, bool dielectric, int tex = 0); Material(float red, float green, float blue, float ambi, float diff, float spec, float specExp, float refl, float refr, float redAtt, float greenAtt, float blueAtt, bool metal, bool glossy, bool dielectric, int tex = 0); Material(const Material& toBeCopied); // Get/Sets inline void SetMaterialColor(RGBColor& color){_materialColor = color;} inline const RGBColor GetMaterialColor() const{return _materialColor;} inline RGBColor GetMaterialColor() {return _materialColor;} inline float GetAmbi(){return _ambi;} inline const float GetAmbi()const{return _ambi;} inline float GetDiff(){return _diff;} inline const float GetDiff()const{return _diff;} inline float GetSpec(){return _spec;} inline const float GetSpec()const{return _spec;} inline float GetSpecExp() {return _specExp;} inline const float GetSpecExp() const{return _specExp;} inline float GetRefl(){return _refl;} inline const float GetRefl()const{return _refl;} inline float GetRedAtt(){return _redAtt;} inline const float GetRedAtt()const{return _redAtt;} inline float GetGreenAtt(){return _greenAtt;} inline const float GetGreenAtt()const{return _greenAtt;} inline float GetBlueAtt(){return _blueAtt;} inline const float GetBlueAtt()const{return _blueAtt;} inline float GetRefr(){return _refr;} inline const float GetRefr()const{return _refr;} inline bool GetMetal(){return _metal;} inline const bool GetMetal()const{return _metal;} inline bool GetGlossy(){return _glossy;} inline const bool GetGlossy()const{return _glossy;} inline bool GetDielectric(){return _dielectric;} inline const bool GetDielectric()const{return _dielectric;} inline int GetTexture(){return _texture;} inline const int GetTexture()const{return _texture;} inline void SetAmbi(float ambi); inline void SetDiff(float diff); inline void SetSpec(float spec); inline void SetSpecExp(float specExp); inline void SetRefl(float x); inline void SetRefr(float x){_refr = x;} inline void SetRedAtt(float x){_redAtt = x;} inline void SetGreenAtt(float x){_greenAtt = x;} inline void SetBlueAtt(float x){_blueAtt = x;} inline void SetMetal(bool b){_metal= b;} inline void SetGlossy(bool b){_glossy= b;} inline void SetDielectric(bool d){_dielectric = d;} // operators friend ostream& operator << (ostream &os, const Material &M); friend istream& operator >> (istream &is, Material &M); }; // This encapsulates a ray of light. class Ray { private: Point3 _origin; Vector3 _rayDirection; public: // constructors Ray(){} Ray(Point3 pointOnRay, Point3 origin); Ray(Vector3 direction, Point3 origin); Ray(const Ray& toBeCopied); // member functions inline void SetOrigin(const Point3& point){_origin = point;} inline void SetRayDirection(const Vector3 dir){_rayDirection = dir;} inline const Point3 GetOrigin() const{return _origin;} inline Point3 GetOrigin() {return _origin;} inline const Vector3 GetRayDirection() const{return _rayDirection;} inline Vector3 GetRayDirection() {return _rayDirection;} Point3 RayPoint(const float &t); // intersection test bool IsPointOnRay(const Point3 &point, float &t); // operator friend ostream& operator << (ostream &os, const Ray &R); }; void RayPoint(const Ray &ray, const float &t, Point3 &pt); // This is the base class of all objects a ray can hit class Surface { protected: Material _material; public: enum Type {SPHERE, TRIANGLE, QUAD}; // tests whether a ray hits the surface; pt is intersection virtual bool Hit(const Ray &ray, Point3 &pt, const float &minT, const float &maxT, float &t, Vector3 &normal) = 0; virtual bool QuickHit(const Ray &ray, const float &minT, const float &maxT) = 0; virtual Type GetType() = 0; virtual Material GetMaterial(){return _material;} virtual Material const GetMaterial()const {return _material;} virtual void SetMaterial(Material &M){_material = M;} virtual RGBColor AmbientLight(const Point3 &hitPoint) = 0; virtual RGBColor DiffuseLight(const Vector3 &normal, const Vector3 &lightDirection, const RGBColor &lightColor, const Vector3 &eyeDirection, const Point3 &hitPoint) = 0; virtual RGBColor SpecularLight(const Vector3 &normal, const Vector3 &lightDirection, const RGBColor &lightColor, const Vector3 &eyeDirection, const Point3 &hitPoint) = 0; }; class Sphere: public Surface { private: Point3 _center; float _radius; public: // constructors Sphere(); Sphere(Point3 center, float radius, Material sphereMaterial); Sphere(float x, float y, float z, float radius, Material sphereMaterial); Sphere(const Sphere &toBeCopied); // member functions inline void SetCenter(const Point3& center){_center = center;} inline void SetRadius(const float radius){_radius = radius;} inline const Point3 GetCenter() const{return _center;} inline Point3 GetCenter() {return _center;} inline const float GetRadius() const{return _radius;} inline float GetRadius() {return _radius;} bool IsPointOnSphere(const Point3 &point); bool Hit(const Ray &ray, Point3 &point, const float &minT, const float &maxT, float &t, Vector3 &normal); bool QuickHit(const Ray &ray, const float &minT, const float &maxT); void SphereNormal(const Point3 &pt, Vector3 &normal); inline Type GetType(void){return SPHERE;} RGBColor AmbientLight(const Point3 &hitPoint); RGBColor DiffuseLight(const Vector3 &normal, const Vector3 &lightDirection, const RGBColor &lightColor, const Vector3 &eyeDirection, const Point3 &hitPoint); RGBColor SpecularLight(const Vector3 &normal, const Vector3 &lightDirection, const RGBColor &lightColor, const Vector3 &eyeDirection, const Point3 &hitPoint); // operators friend ostream& operator << (ostream &os, const Sphere &S); friend istream& operator >> (istream &is, Sphere &S); }; class Triangle: public Surface { private: Point3 _p1, _p2, _p3; Vector3 _normal; // save this to speed up Hit calculations float a, b, c, d, e, f, g, h, i, j, k, l; float eihf, gfdi, dheg, akjb, jcal, blkc; public: // constructors Triangle(); Triangle(Point3 p1, Point3 p2, Point3 p3, Material triangleMaterial); Triangle(const Triangle &toBeCopied); //member functions inline void SetP1(const Point3 &p){_p1 = p;} inline void SetP2(const Point3 &p){_p2 = p;} inline void SetP3(const Point3 &p){_p3 = p;} inline Point3 GetP1(){return _p1;} inline Point3 GetP2(){return _p2;} inline Point3 GetP3(){return _p3;} inline const Point3 GetP1()const {return _p1;} inline const Point3 GetP2()const {return _p2;} inline const Point3 GetP3()const {return _p3;} bool Hit(const Ray &ray, Point3 &point, const float &minT, const float &maxT, float &t, Vector3 &normal); bool QuickHit(const Ray &ray, const float &minT, const float &maxT); inline Vector3 GetNormal(){return _normal;} inline const Vector3 GetNormal()const{return _normal;} inline Type GetType(void){return TRIANGLE;} // This is an ad hoc function to // tranform the quad coordinates defined from // my assignment 2 to quad coordinates for the // present project. void TrainTransform(); void Translate(float X, float Y, float Z); void RotateY(float radians); RGBColor AmbientLight(const Point3 &hitPoint); RGBColor DiffuseLight(const Vector3 &normal, const Vector3 &lightDirection, const RGBColor &lightColor, const Vector3 &eyeDirection, const Point3 &hitPoint); RGBColor SpecularLight(const Vector3 &normal, const Vector3 &lightDirection, const RGBColor &lightColor, const Vector3 &eyeDirection, const Point3 &hitPoint); // operators friend ostream& operator << (ostream &os, const Triangle &T); friend istream& operator >> (istream &is, Triangle &T); }; class Quad: public Surface { private: Point3 _p1, _p2, _p3, _p4; Vector3 _normal; // these are the coefficients of the plane equation // Ax + By + Cz + D = 0 in which the quad is embedded float _A, _B, _C, _D; // these are recorded to speed up texture calculations public: // constructors Quad(Point3 p1, Point3 p2, Point3 p3, Point3 p4, Material quadMaterial); Quad(const Quad &toBeCopied); //member functions inline void SetP1(const Point3 &p){_p1 = p;} inline void SetP2(const Point3 &p){_p2 = p;} inline void SetP3(const Point3 &p){_p3 = p;} inline void SetP4(const Point3 &p){_p4 = p;} inline Point3 GetP1(){return _p1;} inline Point3 GetP2(){return _p2;} inline Point3 GetP3(){return _p3;} inline Point3 GetP4(){return _p4;} inline const Point3 GetP1()const {return _p1;} inline const Point3 GetP2()const {return _p2;} inline const Point3 GetP3()const {return _p3;} inline const Point3 GetP4()const {return _p4;} // This is an ad hoc function to // tranform the quad coordinates defined from // my assignment 2 to quad coordinates for the // present project. void TrainTransform(); void Translate(float X, float Y, float Z); void RotateY(float radians); bool Hit(const Ray &ray, Point3 &point, const float &minT, const float &maxT, float &t, Vector3 &normal); bool QuickHit(const Ray &ray, const float &minT, const float &maxT); inline Vector3 GetNormal(){return _normal;} inline const Vector3 GetNormal()const{return _normal;} inline Type GetType(void){return QUAD;} RGBColor AmbientLight(const Point3 &hitPoint); RGBColor DiffuseLight(const Vector3 &normal, const Vector3 &lightDirection, const RGBColor &lightColor, const Vector3 &eyeDirection, const Point3 &hitPoint); RGBColor SpecularLight(const Vector3 &normal, const Vector3 &lightDirection, const RGBColor &lightColor, const Vector3 &eyeDirection, const Point3 &hitPoint); // operators friend ostream& operator << (ostream &os, const Quad &T); friend istream& operator >> (istream &is, Quad &T); }; class Canvas { private: GLubyte* _canvas; // pointer to storage int _width; int _height; public: // Constructor and destructor Canvas(int width, int height); ~Canvas(); void drawPixel(int x, int y, GLfloat r, GLfloat g, GLfloat b); void drawPixel(int x, int y, RGBColor &color); void flushCanvas(); }; class Light { public: enum LightType{DIRECTIONAL, POINT}; // "_position" is relevant to a point light Point3 _position; // "_up" is relevant to a directional light Vector3 _up; LightType _type; RGBColor _color ; Light(const Point3 &pos, RGBColor &col, const int &type); void UnitVector(const Point3 &pos, Vector3 &direction); // operators friend ostream& operator << (ostream &os, const Light &T); }; class Scene { public: }; class Camera { public: Point3 cameraPosition; }; // This function is from the "OpenGL Bible" book. It // saves the canvas as a targa file. GLint gltWriteTGA(const char *szFileName); #endif