#pragma once #include #include #include #include /*! \brief 3D vector class with overloaded operators. Used for positions, directions, colors, etc. It has the same memory layout as D3DXVECTOR3. */ class Vector { public: //constants static const Vector RGBBLACK; static const Vector RGBWHITE; static const Vector RGBRED; static const Vector RGBGREEN; static const Vector RGBBLUE; static const Vector RGBLIGHTBLUE; static const Vector RGBYELLOW; static const Vector RGBORANGE; static const Vector RGBDARKGRAY; static const Vector RGBLIGHTYELLOW; //Vector is also used for storing colours //data can be accessed through various aliases union{ float v[3]; struct{ float x; float y; float z; }; struct{ float r; float g; float b; }; }; Vector(){} Vector(const D3DXVECTOR3& d) { v[0] = d.x; v[1] = d.y; v[2] = d.z; } Vector(const D3DXVECTOR2& d) { v[0] = d.x; v[1] = d.y; v[2] = 0.0; } Vector(const float x, const float y, const float z) { v[0] = x; v[1] = y; v[2] = z; } void set(const float x, const float y, const float z) { v[0] = x; v[1] = y; v[2] = z; } void setScaled(float s, const Vector& a) { v[0] = s * a[0]; v[1] = s * a[1]; v[2] = s * a[2]; } void addScaled(float s, const Vector& a) { v[0] += s * a[0]; v[1] += s * a[1]; v[2] += s * a[2]; } void clear() { v[0] = v[1] = v[2] = 0; } void setDifference(const Vector& a, const Vector& b) { v[0] = a.v[0] - b.v[0]; v[1] = a.v[1] - b.v[1]; v[2] = a.v[2] - b.v[2]; } Vector operator-() const { return Vector(-v[0], -v[1], -v[2]); } Vector operator+(const Vector& addOperand) const { return Vector ( v[0] + addOperand.v[0], v[1] + addOperand.v[1], v[2] + addOperand.v[2]); } Vector operator-(const Vector& substractOperand) const { return Vector( v[0] - substractOperand.v[0], v[1] - substractOperand.v[1], v[2] - substractOperand.v[2]); } void operator-=(const Vector& a) { v[0] -= a[0]; v[1] -= a[1]; v[2] -= a[2]; } void operator+=(const Vector& a) { v[0] += a[0]; v[1] += a[1]; v[2] += a[2]; } //blend operator void operator%=(const Vector& a) { v[0] *= a[0]; v[1] *= a[1]; v[2] *= a[2]; } //scale operator void operator*=(const float scale) { v[0] *= scale; v[1] *= scale; v[2] *= scale; } //blend operator Vector operator%(const Vector& blendOperand) const { return Vector( v[0] * blendOperand.v[0], v[1] * blendOperand.v[1], v[2] * blendOperand.v[2]); } //scale operator Vector operator*(const float scale) const { return Vector(scale * v[0], scale * v[1], scale * v[2]); } //dot product operator float operator*(const Vector& dotProductOperand) const { return v[0] * dotProductOperand[0] + v[1] * dotProductOperand[1] + v[2] * dotProductOperand[2]; } //cross product operator Vector operator&&(const Vector& crossProductOperand) const { return Vector( v[1] * crossProductOperand[2] - v[2] * crossProductOperand[1], v[2] * crossProductOperand[0] - v[0] * crossProductOperand[2], v[0] * crossProductOperand[1] - v[1] * crossProductOperand[0]); } void setCrossProduct(const Vector& a, const Vector& b) { v[0] = a[1] * b[2] - a[2] * b[1]; v[1] = a[2] * b[0] - a[0] * b[2]; v[2] = a[0] * b[1] - a[1] * b[0]; } float norm () const { return sqrtf(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]); } float norm2 () const { return v[0]*v[0] + v[1]*v[1] + v[2]*v[2]; } void normalize () { float length = 1.0f / sqrtf (v[0]*v[0] + v[1]*v[1] + v[2]*v[2]); v[0] *= length; v[1] *= length; v[2] *= length; } float sum () const { return v[0] + v[1] + v[2]; } const Vector& operator=(const Vector& other) { v[0] = other.v[0]; v[1] = other.v[1]; v[2] = other.v[2]; return *this; } float& operator[](const int index) { return v[index]; } float operator[](const int index) const { return v[index]; } //accumulate minimum operator void operator<= ( const Vector& zsmall) { if(v[0] > zsmall[0]) v[0] = zsmall[0]; if(v[1] > zsmall[1]) v[1] = zsmall[1]; if(v[2] > zsmall[2]) v[2] = zsmall[2]; } //accumulate maximum operator void operator>= ( const Vector& large) { if(v[0] < large[0]) v[0] = large[0]; if(v[1] < large[1]) v[1] = large[1]; if(v[2] < large[2]) v[2] = large[2]; } void setIdealReflectedDirection (const Vector& in, const Vector& normal) { *this = in - normal * (2.0f * (normal * in)); } void setIdealRefractedDirection (const Vector& in, const Vector& normal, float rf) { float nDotIn = in * normal; if(nDotIn < 0.0f) { float anna = -nDotIn * rf; float det = anna * anna - rf * rf + 1.0f; if(det < 0.0f) { //total reflection *this = in - normal * (2.0f * (normal * in)); return; } float sigma = - anna + sqrt(det); *this = (in * rf); *this += (normal * -sigma); } else { rf = 1.0f / rf; float anna = nDotIn * rf; float det = anna * anna - rf * rf + 1.0f; if(det < 0.0f) { //total reflection *this = in - normal * (2.0f * (normal * in)); return; } float sigma = - anna + sqrt(det); *this = (in * rf); *this += (normal * sigma); } } void addAccumBlendReflecBlendEmissionScaleDist(const Vector& accum, const Vector& reflec, const Vector& emission, const float dist2inv) { v[0] += accum.v[0] * reflec.v[0] * emission.v[0] * dist2inv; v[1] += accum.v[1] * reflec.v[1] * emission.v[1] * dist2inv; v[2] += accum.v[2] * reflec.v[2] * emission.v[2] * dist2inv; } static const double PI; }; std::istream& operator>>(std::istream& cin, Vector& v); std::ostream& operator<<(std::ostream& cout, const Vector& v);