[216] | 1 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
| 2 | /** |
---|
| 3 | * Contains code for 3D vectors. |
---|
| 4 | * \file IcePoint.cpp |
---|
| 5 | * \author Pierre Terdiman |
---|
| 6 | * \date April, 4, 2000 |
---|
| 7 | */ |
---|
| 8 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
| 9 | |
---|
| 10 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
| 11 | /** |
---|
| 12 | * 3D point. |
---|
| 13 | * |
---|
| 14 | * The name is "Point" instead of "Vector" since a vector is N-dimensional, whereas a point is an implicit "vector of dimension 3". |
---|
| 15 | * So the choice was between "Point" and "Vector3", the first one looked better (IMHO). |
---|
| 16 | * |
---|
| 17 | * Some people, then, use a typedef to handle both points & vectors using the same class: typedef Point Vector3; |
---|
| 18 | * This is bad since it opens the door to a lot of confusion while reading the code. I know it may sounds weird but check this out: |
---|
| 19 | * |
---|
| 20 | * \code |
---|
| 21 | * Point P0,P1 = some 3D points; |
---|
| 22 | * Point Delta = P1 - P0; |
---|
| 23 | * \endcode |
---|
| 24 | * |
---|
| 25 | * This compiles fine, although you should have written: |
---|
| 26 | * |
---|
| 27 | * \code |
---|
| 28 | * Point P0,P1 = some 3D points; |
---|
| 29 | * Vector3 Delta = P1 - P0; |
---|
| 30 | * \endcode |
---|
| 31 | * |
---|
| 32 | * Subtle things like this are not caught at compile-time, and when you find one in the code, you never know whether it's a mistake |
---|
| 33 | * from the author or something you don't get. |
---|
| 34 | * |
---|
| 35 | * One way to handle it at compile-time would be to use different classes for Point & Vector3, only overloading operator "-" for vectors. |
---|
| 36 | * But then, you get a lot of redundant code in thoses classes, and basically it's really a lot of useless work. |
---|
| 37 | * |
---|
| 38 | * Another way would be to use homogeneous points: w=1 for points, w=0 for vectors. That's why the HPoint class exists. Now, to store |
---|
| 39 | * your model's vertices and in most cases, you really want to use Points to save ram. |
---|
| 40 | * |
---|
| 41 | * \class Point |
---|
| 42 | * \author Pierre Terdiman |
---|
| 43 | * \version 1.0 |
---|
| 44 | */ |
---|
| 45 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
| 46 | |
---|
| 47 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
| 48 | // Precompiled Header |
---|
| 49 | #include "Stdafx.h" |
---|
| 50 | |
---|
| 51 | using namespace IceMaths; |
---|
| 52 | |
---|
| 53 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
| 54 | /** |
---|
| 55 | * Creates a positive unit random vector. |
---|
| 56 | * \return Self-reference |
---|
| 57 | */ |
---|
| 58 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
| 59 | Point& Point::PositiveUnitRandomVector() |
---|
| 60 | { |
---|
| 61 | x = UnitRandomFloat(); |
---|
| 62 | y = UnitRandomFloat(); |
---|
| 63 | z = UnitRandomFloat(); |
---|
| 64 | Normalize(); |
---|
| 65 | return *this; |
---|
| 66 | } |
---|
| 67 | |
---|
| 68 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
| 69 | /** |
---|
| 70 | * Creates a unit random vector. |
---|
| 71 | * \return Self-reference |
---|
| 72 | */ |
---|
| 73 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
| 74 | Point& Point::UnitRandomVector() |
---|
| 75 | { |
---|
| 76 | x = UnitRandomFloat() - 0.5f; |
---|
| 77 | y = UnitRandomFloat() - 0.5f; |
---|
| 78 | z = UnitRandomFloat() - 0.5f; |
---|
| 79 | Normalize(); |
---|
| 80 | return *this; |
---|
| 81 | } |
---|
| 82 | |
---|
| 83 | // Cast operator |
---|
| 84 | // WARNING: not inlined |
---|
| 85 | Point::operator HPoint() const { return HPoint(x, y, z, 0.0f); } |
---|
| 86 | |
---|
| 87 | Point& Point::Refract(const Point& eye, const Point& n, float refractindex, Point& refracted) |
---|
| 88 | { |
---|
| 89 | // Point EyePt = eye position |
---|
| 90 | // Point p = current vertex |
---|
| 91 | // Point n = vertex normal |
---|
| 92 | // Point rv = refracted vector |
---|
| 93 | // Eye vector - doesn't need to be normalized |
---|
| 94 | Point Env; |
---|
| 95 | Env.x = eye.x - x; |
---|
| 96 | Env.y = eye.y - y; |
---|
| 97 | Env.z = eye.z - z; |
---|
| 98 | |
---|
| 99 | float NDotE = n|Env; |
---|
| 100 | float NDotN = n|n; |
---|
| 101 | NDotE /= refractindex; |
---|
| 102 | |
---|
| 103 | // Refracted vector |
---|
| 104 | refracted = n*NDotE - Env*NDotN; |
---|
| 105 | |
---|
| 106 | return *this; |
---|
| 107 | } |
---|
| 108 | |
---|
| 109 | Point& Point::ProjectToPlane(const Plane& p) |
---|
| 110 | { |
---|
| 111 | *this-= (p.d + (*this|p.n))*p.n; |
---|
| 112 | return *this; |
---|
| 113 | } |
---|
| 114 | |
---|
| 115 | void Point::ProjectToScreen(float halfrenderwidth, float halfrenderheight, const Matrix4x4& mat, HPoint& projected) const |
---|
| 116 | { |
---|
| 117 | projected = HPoint(x, y, z, 1.0f) * mat; |
---|
| 118 | projected.w = 1.0f / projected.w; |
---|
| 119 | |
---|
| 120 | projected.x*=projected.w; |
---|
| 121 | projected.y*=projected.w; |
---|
| 122 | projected.z*=projected.w; |
---|
| 123 | |
---|
| 124 | projected.x *= halfrenderwidth; projected.x += halfrenderwidth; |
---|
| 125 | projected.y *= -halfrenderheight; projected.y += halfrenderheight; |
---|
| 126 | } |
---|
| 127 | |
---|
| 128 | void Point::SetNotUsed() |
---|
| 129 | { |
---|
| 130 | // We use a particular integer pattern : 0xffffffff everywhere. This is a NAN. |
---|
| 131 | IR(x) = 0xffffffff; |
---|
| 132 | IR(y) = 0xffffffff; |
---|
| 133 | IR(z) = 0xffffffff; |
---|
| 134 | } |
---|
| 135 | |
---|
| 136 | BOOL Point::IsNotUsed() const |
---|
| 137 | { |
---|
| 138 | if(IR(x)!=0xffffffff) return FALSE; |
---|
| 139 | if(IR(y)!=0xffffffff) return FALSE; |
---|
| 140 | if(IR(z)!=0xffffffff) return FALSE; |
---|
| 141 | return TRUE; |
---|
| 142 | } |
---|
| 143 | |
---|
| 144 | Point& Point::Mult(const Matrix3x3& mat, const Point& a) |
---|
| 145 | { |
---|
| 146 | x = a.x * mat.m[0][0] + a.y * mat.m[0][1] + a.z * mat.m[0][2]; |
---|
| 147 | y = a.x * mat.m[1][0] + a.y * mat.m[1][1] + a.z * mat.m[1][2]; |
---|
| 148 | z = a.x * mat.m[2][0] + a.y * mat.m[2][1] + a.z * mat.m[2][2]; |
---|
| 149 | return *this; |
---|
| 150 | } |
---|
| 151 | |
---|
| 152 | Point& Point::Mult2(const Matrix3x3& mat1, const Point& a1, const Matrix3x3& mat2, const Point& a2) |
---|
| 153 | { |
---|
| 154 | x = a1.x * mat1.m[0][0] + a1.y * mat1.m[0][1] + a1.z * mat1.m[0][2] + a2.x * mat2.m[0][0] + a2.y * mat2.m[0][1] + a2.z * mat2.m[0][2]; |
---|
| 155 | y = a1.x * mat1.m[1][0] + a1.y * mat1.m[1][1] + a1.z * mat1.m[1][2] + a2.x * mat2.m[1][0] + a2.y * mat2.m[1][1] + a2.z * mat2.m[1][2]; |
---|
| 156 | z = a1.x * mat1.m[2][0] + a1.y * mat1.m[2][1] + a1.z * mat1.m[2][2] + a2.x * mat2.m[2][0] + a2.y * mat2.m[2][1] + a2.z * mat2.m[2][2]; |
---|
| 157 | return *this; |
---|
| 158 | } |
---|
| 159 | |
---|
| 160 | Point& Point::Mac(const Matrix3x3& mat, const Point& a) |
---|
| 161 | { |
---|
| 162 | x += a.x * mat.m[0][0] + a.y * mat.m[0][1] + a.z * mat.m[0][2]; |
---|
| 163 | y += a.x * mat.m[1][0] + a.y * mat.m[1][1] + a.z * mat.m[1][2]; |
---|
| 164 | z += a.x * mat.m[2][0] + a.y * mat.m[2][1] + a.z * mat.m[2][2]; |
---|
| 165 | return *this; |
---|
| 166 | } |
---|
| 167 | |
---|
| 168 | Point& Point::TransMult(const Matrix3x3& mat, const Point& a) |
---|
| 169 | { |
---|
| 170 | x = a.x * mat.m[0][0] + a.y * mat.m[1][0] + a.z * mat.m[2][0]; |
---|
| 171 | y = a.x * mat.m[0][1] + a.y * mat.m[1][1] + a.z * mat.m[2][1]; |
---|
| 172 | z = a.x * mat.m[0][2] + a.y * mat.m[1][2] + a.z * mat.m[2][2]; |
---|
| 173 | return *this; |
---|
| 174 | } |
---|
| 175 | |
---|
| 176 | Point& Point::Transform(const Point& r, const Matrix3x3& rotpos, const Point& linpos) |
---|
| 177 | { |
---|
| 178 | x = r.x * rotpos.m[0][0] + r.y * rotpos.m[0][1] + r.z * rotpos.m[0][2] + linpos.x; |
---|
| 179 | y = r.x * rotpos.m[1][0] + r.y * rotpos.m[1][1] + r.z * rotpos.m[1][2] + linpos.y; |
---|
| 180 | z = r.x * rotpos.m[2][0] + r.y * rotpos.m[2][1] + r.z * rotpos.m[2][2] + linpos.z; |
---|
| 181 | return *this; |
---|
| 182 | } |
---|
| 183 | |
---|
| 184 | Point& Point::InvTransform(const Point& r, const Matrix3x3& rotpos, const Point& linpos) |
---|
| 185 | { |
---|
| 186 | float sx = r.x - linpos.x; |
---|
| 187 | float sy = r.y - linpos.y; |
---|
| 188 | float sz = r.z - linpos.z; |
---|
| 189 | x = sx * rotpos.m[0][0] + sy * rotpos.m[1][0] + sz * rotpos.m[2][0]; |
---|
| 190 | y = sx * rotpos.m[0][1] + sy * rotpos.m[1][1] + sz * rotpos.m[2][1]; |
---|
| 191 | z = sx * rotpos.m[0][2] + sy * rotpos.m[1][2] + sz * rotpos.m[2][2]; |
---|
| 192 | return *this; |
---|
| 193 | } |
---|