[896] | 1 | #pragma once
|
---|
| 2 |
|
---|
| 3 | #include <d3dx9math.h>
|
---|
| 4 | #include <float.h> |
---|
| 5 | #include <math.h>
|
---|
| 6 | #include <iostream>
|
---|
| 7 |
|
---|
| 8 | /*!
|
---|
| 9 | \brief 3D vector class with overloaded operators.
|
---|
| 10 | Used for positions, directions, colors, etc. It has the same memory layout as D3DXVECTOR3.
|
---|
| 11 | */
|
---|
| 12 | class Vector {
|
---|
| 13 | public:
|
---|
| 14 | //constants
|
---|
| 15 | static const Vector RGBBLACK;
|
---|
| 16 | static const Vector RGBWHITE;
|
---|
| 17 | static const Vector RGBRED; |
---|
| 18 | static const Vector RGBGREEN; |
---|
| 19 | static const Vector RGBBLUE; |
---|
| 20 | static const Vector RGBLIGHTBLUE; |
---|
| 21 | static const Vector RGBYELLOW; |
---|
| 22 | static const Vector RGBORANGE; |
---|
| 23 | static const Vector RGBDARKGRAY; |
---|
| 24 | static const Vector RGBLIGHTYELLOW; |
---|
| 25 |
|
---|
| 26 |
|
---|
| 27 | //Vector is also used for storing colours
|
---|
| 28 | //data can be accessed through various aliases
|
---|
| 29 | union{
|
---|
| 30 | float v[3];
|
---|
| 31 | struct{ float x; float y; float z; };
|
---|
| 32 | struct{ float r; float g; float b; };
|
---|
| 33 | };
|
---|
| 34 |
|
---|
| 35 | Vector(){}
|
---|
| 36 |
|
---|
| 37 | Vector(const D3DXVECTOR3& d)
|
---|
| 38 | {
|
---|
| 39 | v[0] = d.x;
|
---|
| 40 | v[1] = d.y;
|
---|
| 41 | v[2] = d.z;
|
---|
| 42 | }
|
---|
| 43 |
|
---|
| 44 | Vector(const D3DXVECTOR2& d)
|
---|
| 45 | {
|
---|
| 46 | v[0] = d.x;
|
---|
| 47 | v[1] = d.y;
|
---|
| 48 | v[2] = 0.0;
|
---|
| 49 | }
|
---|
| 50 |
|
---|
| 51 | Vector(const float x, const float y, const float z)
|
---|
| 52 | {
|
---|
| 53 | v[0] = x; v[1] = y; v[2] = z;
|
---|
| 54 | }
|
---|
| 55 |
|
---|
| 56 | void set(const float x, const float y, const float z)
|
---|
| 57 | {
|
---|
| 58 | v[0] = x; v[1] = y; v[2] = z;
|
---|
| 59 | }
|
---|
| 60 |
|
---|
| 61 | void setScaled(float s, const Vector& a)
|
---|
| 62 | {
|
---|
| 63 | v[0] = s * a[0]; v[1] = s * a[1]; v[2] = s * a[2];
|
---|
| 64 | }
|
---|
| 65 |
|
---|
| 66 | void addScaled(float s, const Vector& a)
|
---|
| 67 | {
|
---|
| 68 | v[0] += s * a[0]; v[1] += s * a[1]; v[2] += s * a[2];
|
---|
| 69 | }
|
---|
| 70 |
|
---|
| 71 | void clear()
|
---|
| 72 | {
|
---|
| 73 | v[0] = v[1] = v[2] = 0;
|
---|
| 74 | }
|
---|
| 75 |
|
---|
| 76 | void setDifference(const Vector& a, const Vector& b)
|
---|
| 77 | {
|
---|
| 78 | v[0] = a.v[0] - b.v[0];
|
---|
| 79 | v[1] = a.v[1] - b.v[1];
|
---|
| 80 | v[2] = a.v[2] - b.v[2];
|
---|
| 81 | }
|
---|
| 82 |
|
---|
| 83 | Vector operator-() const
|
---|
| 84 | {
|
---|
| 85 | return Vector(-v[0], -v[1], -v[2]);
|
---|
| 86 | }
|
---|
| 87 |
|
---|
| 88 | Vector operator+(const Vector& addOperand) const
|
---|
| 89 | {
|
---|
| 90 | return Vector ( v[0] + addOperand.v[0],
|
---|
| 91 | v[1] + addOperand.v[1],
|
---|
| 92 | v[2] + addOperand.v[2]);
|
---|
| 93 | }
|
---|
| 94 |
|
---|
| 95 | Vector operator-(const Vector& substractOperand) const
|
---|
| 96 | {
|
---|
| 97 | return Vector( v[0] - substractOperand.v[0],
|
---|
| 98 | v[1] - substractOperand.v[1],
|
---|
| 99 | v[2] - substractOperand.v[2]);
|
---|
| 100 | }
|
---|
| 101 |
|
---|
| 102 | void operator-=(const Vector& a)
|
---|
| 103 | {
|
---|
| 104 | v[0] -= a[0];
|
---|
| 105 | v[1] -= a[1];
|
---|
| 106 | v[2] -= a[2];
|
---|
| 107 | }
|
---|
| 108 |
|
---|
| 109 | void operator+=(const Vector& a)
|
---|
| 110 | {
|
---|
| 111 | v[0] += a[0];
|
---|
| 112 | v[1] += a[1];
|
---|
| 113 | v[2] += a[2];
|
---|
| 114 | }
|
---|
| 115 |
|
---|
| 116 | //blend operator
|
---|
| 117 | void operator%=(const Vector& a)
|
---|
| 118 | {
|
---|
| 119 | v[0] *= a[0];
|
---|
| 120 | v[1] *= a[1];
|
---|
| 121 | v[2] *= a[2];
|
---|
| 122 | }
|
---|
| 123 |
|
---|
| 124 | //scale operator
|
---|
| 125 | void operator*=(const float scale)
|
---|
| 126 | {
|
---|
| 127 | v[0] *= scale;
|
---|
| 128 | v[1] *= scale;
|
---|
| 129 | v[2] *= scale;
|
---|
| 130 | }
|
---|
| 131 |
|
---|
| 132 | //blend operator
|
---|
| 133 | Vector operator%(const Vector& blendOperand) const
|
---|
| 134 | {
|
---|
| 135 | return Vector( v[0] * blendOperand.v[0],
|
---|
| 136 | v[1] * blendOperand.v[1],
|
---|
| 137 | v[2] * blendOperand.v[2]);
|
---|
| 138 | }
|
---|
| 139 |
|
---|
| 140 | //scale operator
|
---|
| 141 | Vector operator*(const float scale) const
|
---|
| 142 | {
|
---|
| 143 | return Vector(scale * v[0], scale * v[1], scale * v[2]);
|
---|
| 144 | }
|
---|
| 145 |
|
---|
| 146 | //dot product operator
|
---|
| 147 | float operator*(const Vector& dotProductOperand) const
|
---|
| 148 | {
|
---|
| 149 | return v[0] * dotProductOperand[0] +
|
---|
| 150 | v[1] * dotProductOperand[1] +
|
---|
| 151 | v[2] * dotProductOperand[2];
|
---|
| 152 | }
|
---|
| 153 |
|
---|
| 154 | //cross product operator
|
---|
| 155 | Vector operator&&(const Vector& crossProductOperand) const
|
---|
| 156 | {
|
---|
| 157 | return Vector(
|
---|
| 158 | v[1] * crossProductOperand[2] - v[2] * crossProductOperand[1],
|
---|
| 159 | v[2] * crossProductOperand[0] - v[0] * crossProductOperand[2],
|
---|
| 160 | v[0] * crossProductOperand[1] - v[1] * crossProductOperand[0]);
|
---|
| 161 | }
|
---|
| 162 |
|
---|
| 163 | void setCrossProduct(const Vector& a, const Vector& b)
|
---|
| 164 | {
|
---|
| 165 | v[0] = a[1] * b[2] - a[2] * b[1];
|
---|
| 166 | v[1] = a[2] * b[0] - a[0] * b[2];
|
---|
| 167 | v[2] = a[0] * b[1] - a[1] * b[0];
|
---|
| 168 | }
|
---|
| 169 |
|
---|
| 170 | float norm () const
|
---|
| 171 | {
|
---|
| 172 | return sqrtf(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
|
---|
| 173 | }
|
---|
| 174 |
|
---|
| 175 | float norm2 () const
|
---|
| 176 | {
|
---|
| 177 | return v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
|
---|
| 178 | }
|
---|
| 179 |
|
---|
| 180 | void normalize ()
|
---|
| 181 | {
|
---|
| 182 | float length = 1.0f / sqrtf (v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
|
---|
| 183 | v[0] *= length;
|
---|
| 184 | v[1] *= length;
|
---|
| 185 | v[2] *= length;
|
---|
| 186 | }
|
---|
| 187 |
|
---|
| 188 | float sum () const
|
---|
| 189 | {
|
---|
| 190 | return v[0] + v[1] + v[2];
|
---|
| 191 | }
|
---|
| 192 |
|
---|
| 193 | const Vector& operator=(const Vector& other)
|
---|
| 194 | {
|
---|
| 195 | v[0] = other.v[0];
|
---|
| 196 | v[1] = other.v[1];
|
---|
| 197 | v[2] = other.v[2];
|
---|
| 198 | return *this;
|
---|
| 199 | }
|
---|
| 200 |
|
---|
| 201 | float& operator[](const int index)
|
---|
| 202 | {
|
---|
| 203 | return v[index];
|
---|
| 204 | }
|
---|
| 205 |
|
---|
| 206 | float operator[](const int index) const
|
---|
| 207 | {
|
---|
| 208 | return v[index];
|
---|
| 209 | }
|
---|
| 210 |
|
---|
| 211 | //accumulate minimum operator
|
---|
| 212 | void operator<= ( const Vector& zsmall)
|
---|
| 213 | {
|
---|
| 214 | if(v[0] > zsmall[0]) v[0] = zsmall[0];
|
---|
| 215 | if(v[1] > zsmall[1]) v[1] = zsmall[1];
|
---|
| 216 | if(v[2] > zsmall[2]) v[2] = zsmall[2];
|
---|
| 217 | }
|
---|
| 218 |
|
---|
| 219 | //accumulate maximum operator
|
---|
| 220 | void operator>= ( const Vector& large)
|
---|
| 221 | {
|
---|
| 222 | if(v[0] < large[0]) v[0] = large[0];
|
---|
| 223 | if(v[1] < large[1]) v[1] = large[1];
|
---|
| 224 | if(v[2] < large[2]) v[2] = large[2];
|
---|
| 225 | }
|
---|
| 226 |
|
---|
| 227 | void setIdealReflectedDirection (const Vector& in, const Vector& normal)
|
---|
| 228 | {
|
---|
| 229 | *this = in - normal * (2.0f * (normal * in));
|
---|
| 230 | }
|
---|
| 231 |
|
---|
| 232 | void setIdealRefractedDirection (const Vector& in, const Vector& normal, float rf)
|
---|
| 233 | {
|
---|
| 234 | float nDotIn = in * normal;
|
---|
| 235 | if(nDotIn < 0.0f)
|
---|
| 236 | {
|
---|
| 237 | float anna = -nDotIn * rf;
|
---|
| 238 | float det = anna * anna - rf * rf + 1.0f;
|
---|
| 239 | if(det < 0.0f)
|
---|
| 240 | { //total reflection
|
---|
| 241 | *this = in - normal * (2.0f * (normal * in));
|
---|
| 242 | return;
|
---|
| 243 | }
|
---|
| 244 | float sigma = - anna + sqrt(det);
|
---|
| 245 | *this = (in * rf);
|
---|
| 246 | *this += (normal * -sigma);
|
---|
| 247 | }
|
---|
| 248 | else
|
---|
| 249 | {
|
---|
| 250 | rf = 1.0f / rf;
|
---|
| 251 | float anna = nDotIn * rf;
|
---|
| 252 | float det = anna * anna - rf * rf + 1.0f;
|
---|
| 253 | if(det < 0.0f)
|
---|
| 254 | { //total reflection
|
---|
| 255 | *this = in - normal * (2.0f * (normal * in));
|
---|
| 256 | return;
|
---|
| 257 | }
|
---|
| 258 | float sigma = - anna + sqrt(det);
|
---|
| 259 | *this = (in * rf);
|
---|
| 260 | *this += (normal * sigma);
|
---|
| 261 | }
|
---|
| 262 | }
|
---|
| 263 |
|
---|
| 264 | void addAccumBlendReflecBlendEmissionScaleDist(const Vector& accum,
|
---|
| 265 | const Vector& reflec,
|
---|
| 266 | const Vector& emission,
|
---|
| 267 | const float dist2inv)
|
---|
| 268 | {
|
---|
| 269 | v[0] += accum.v[0] * reflec.v[0] * emission.v[0] * dist2inv;
|
---|
| 270 | v[1] += accum.v[1] * reflec.v[1] * emission.v[1] * dist2inv;
|
---|
| 271 | v[2] += accum.v[2] * reflec.v[2] * emission.v[2] * dist2inv;
|
---|
| 272 | }
|
---|
| 273 |
|
---|
| 274 | static const double PI;
|
---|
| 275 | };
|
---|
| 276 |
|
---|
| 277 | std::istream& operator>>(std::istream& cin, Vector& v);
|
---|
| 278 | std::ostream& operator<<(std::ostream& cout, const Vector& v);
|
---|