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 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
PositiveUnitRandomVector()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 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
UnitRandomVector()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
operator HPoint() const85 Point::operator HPoint() const { return HPoint(x, y, z, 0.0f); }
86
Refract(const Point & eye,const Point & n,float refractindex,Point & refracted)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
ProjectToPlane(const Plane & p)109 Point& Point::ProjectToPlane(const Plane& p)
110 {
111 *this-= (p.d + (*this|p.n))*p.n;
112 return *this;
113 }
114
ProjectToScreen(float halfrenderwidth,float halfrenderheight,const Matrix4x4 & mat,HPoint & projected) const115 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
SetNotUsed()128 void Point::SetNotUsed()
129 {
130 // We use a particular integer pattern : 0xffffffff everywhere. This is a NAN.
131 x = y = z = FR(0xffffffff);
132 }
133
IsNotUsed() const134 BOOL Point::IsNotUsed() const
135 {
136 if(IR(x)!=0xffffffff) return FALSE;
137 if(IR(y)!=0xffffffff) return FALSE;
138 if(IR(z)!=0xffffffff) return FALSE;
139 return TRUE;
140 }
141
Mult(const Matrix3x3 & mat,const Point & a)142 Point& Point::Mult(const Matrix3x3& mat, const Point& a)
143 {
144 x = a.x * mat.m[0][0] + a.y * mat.m[0][1] + a.z * mat.m[0][2];
145 y = a.x * mat.m[1][0] + a.y * mat.m[1][1] + a.z * mat.m[1][2];
146 z = a.x * mat.m[2][0] + a.y * mat.m[2][1] + a.z * mat.m[2][2];
147 return *this;
148 }
149
Mult2(const Matrix3x3 & mat1,const Point & a1,const Matrix3x3 & mat2,const Point & a2)150 Point& Point::Mult2(const Matrix3x3& mat1, const Point& a1, const Matrix3x3& mat2, const Point& a2)
151 {
152 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];
153 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];
154 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];
155 return *this;
156 }
157
Mac(const Matrix3x3 & mat,const Point & a)158 Point& Point::Mac(const Matrix3x3& mat, const Point& a)
159 {
160 x += a.x * mat.m[0][0] + a.y * mat.m[0][1] + a.z * mat.m[0][2];
161 y += a.x * mat.m[1][0] + a.y * mat.m[1][1] + a.z * mat.m[1][2];
162 z += a.x * mat.m[2][0] + a.y * mat.m[2][1] + a.z * mat.m[2][2];
163 return *this;
164 }
165
TransMult(const Matrix3x3 & mat,const Point & a)166 Point& Point::TransMult(const Matrix3x3& mat, const Point& a)
167 {
168 x = a.x * mat.m[0][0] + a.y * mat.m[1][0] + a.z * mat.m[2][0];
169 y = a.x * mat.m[0][1] + a.y * mat.m[1][1] + a.z * mat.m[2][1];
170 z = a.x * mat.m[0][2] + a.y * mat.m[1][2] + a.z * mat.m[2][2];
171 return *this;
172 }
173
Transform(const Point & r,const Matrix3x3 & rotpos,const Point & linpos)174 Point& Point::Transform(const Point& r, const Matrix3x3& rotpos, const Point& linpos)
175 {
176 x = r.x * rotpos.m[0][0] + r.y * rotpos.m[0][1] + r.z * rotpos.m[0][2] + linpos.x;
177 y = r.x * rotpos.m[1][0] + r.y * rotpos.m[1][1] + r.z * rotpos.m[1][2] + linpos.y;
178 z = r.x * rotpos.m[2][0] + r.y * rotpos.m[2][1] + r.z * rotpos.m[2][2] + linpos.z;
179 return *this;
180 }
181
InvTransform(const Point & r,const Matrix3x3 & rotpos,const Point & linpos)182 Point& Point::InvTransform(const Point& r, const Matrix3x3& rotpos, const Point& linpos)
183 {
184 float sx = r.x - linpos.x;
185 float sy = r.y - linpos.y;
186 float sz = r.z - linpos.z;
187 x = sx * rotpos.m[0][0] + sy * rotpos.m[1][0] + sz * rotpos.m[2][0];
188 y = sx * rotpos.m[0][1] + sy * rotpos.m[1][1] + sz * rotpos.m[2][1];
189 z = sx * rotpos.m[0][2] + sy * rotpos.m[1][2] + sz * rotpos.m[2][2];
190 return *this;
191 }
192