6 struct { float x
, y
, z
; };
11 vec(int a
) : x(a
), y(a
), z(a
) {}
12 vec(float a
) : x(a
), y(a
), z(a
) {}
13 vec(float a
, float b
, float c
) : x(a
), y(b
), z(c
) {}
14 vec(int v
[3]) : x(v
[0]), y(v
[1]), z(v
[2]) {}
15 vec(float *v
) : x(v
[0]), y(v
[1]), z(v
[2]) {}
17 vec(float yaw
, float pitch
) : x(sinf(yaw
)*cosf(pitch
)), y(-cosf(yaw
)*cosf(pitch
)), z(sinf(pitch
)) {}
19 float &operator[](int i
) { return v
[i
]; }
20 float operator[](int i
) const { return v
[i
]; }
22 vec
&set(int i
, float f
) { v
[i
] = f
; return *this; }
24 bool operator==(const vec
&o
) const { return x
== o
.x
&& y
== o
.y
&& z
== o
.z
; }
25 bool operator!=(const vec
&o
) const { return x
!= o
.x
|| y
!= o
.y
|| z
!= o
.z
; }
27 bool iszero() const { return x
==0 && y
==0 && z
==0; }
28 float squaredlen() const { return x
*x
+ y
*y
+ z
*z
; }
29 float dot(const vec
&o
) const { return x
*o
.x
+ y
*o
.y
+ z
*o
.z
; }
30 vec
&mul(float f
) { x
*= f
; y
*= f
; z
*= f
; return *this; }
31 vec
&div(float f
) { x
/= f
; y
/= f
; z
/= f
; return *this; }
32 vec
&add(const vec
&o
) { x
+= o
.x
; y
+= o
.y
; z
+= o
.z
; return *this; }
33 vec
&add(float f
) { x
+= f
; y
+= f
; z
+= f
; return *this; }
34 vec
&sub(const vec
&o
) { x
-= o
.x
; y
-= o
.y
; z
-= o
.z
; return *this; }
35 vec
&sub(float f
) { x
-= f
; y
-= f
; z
-= f
; return *this; }
36 vec
&neg() { return mul(-1); }
37 float magnitude() const { return sqrtf(squaredlen()); }
38 vec
&normalize() { div(magnitude()); return *this; }
39 bool isnormalized() const { float m
= squaredlen(); return (m
>0.99f
&& m
<1.01f
); }
40 float dist(const vec
&e
) const { vec t
; return dist(e
, t
); }
41 float dist(const vec
&e
, vec
&t
) const { t
= *this; t
.sub(e
); return t
.magnitude(); }
42 bool reject(const vec
&o
, float max
) { return x
>o
.x
+max
|| x
<o
.x
-max
|| y
>o
.y
+max
|| y
<o
.y
-max
; }
43 vec
&cross(const vec
&a
, const vec
&b
) { x
= a
.y
*b
.z
-a
.z
*b
.y
; y
= a
.z
*b
.x
-a
.x
*b
.z
; z
= a
.x
*b
.y
-a
.y
*b
.x
; return *this; }
45 void rotate_around_z(float angle
) { *this = vec(cosf(angle
)*x
-sinf(angle
)*y
, cosf(angle
)*y
+sinf(angle
)*x
, z
); }
46 void rotate_around_x(float angle
) { *this = vec(x
, cosf(angle
)*y
-sinf(angle
)*z
, cosf(angle
)*z
+sinf(angle
)*y
); }
47 void rotate_around_y(float angle
) { *this = vec(cosf(angle
)*x
-sinf(angle
)*z
, y
, cosf(angle
)*z
+sinf(angle
)*x
); }
49 void rotate(float angle
, const vec
&d
)
51 float c
= cosf(angle
), s
= sinf(angle
);
55 void rotate(float c
, float s
, const vec
&d
)
57 *this = vec(x
*(d
.x
*d
.x
*(1-c
)+c
) + y
*(d
.x
*d
.y
*(1-c
)-d
.z
*s
) + z
*(d
.x
*d
.z
*(1-c
)+d
.y
*s
),
58 x
*(d
.y
*d
.x
*(1-c
)+d
.z
*s
) + y
*(d
.y
*d
.y
*(1-c
)+c
) + z
*(d
.y
*d
.z
*(1-c
)-d
.x
*s
),
59 x
*(d
.x
*d
.z
*(1-c
)-d
.y
*s
) + y
*(d
.y
*d
.z
*(1-c
)+d
.x
*s
) + z
*(d
.z
*d
.z
*(1-c
)+c
));
62 void orthogonal(const vec
&d
)
64 int i
= fabs(d
.x
) > fabs(d
.y
) ? (fabs(d
.x
) > fabs(d
.z
) ? 0 : 2) : (fabs(d
.y
) > fabs(d
.z
) ? 1 : 2);
70 template<class T
> float dist_to_bb(const T
&min
, const T
&max
) const
75 if (v
[i
] < min
[i
]) { float delta
= v
[i
]-min
[i
]; sqrdist
+= delta
*delta
; }
76 else if(v
[i
] > max
[i
]) { float delta
= max
[i
]-v
[i
]; sqrdist
+= delta
*delta
; }
78 return sqrtf(sqrdist
);
81 template<class T
, class S
> float dist_to_bb(const T
&o
, S size
) const
83 return dist_to_bb(o
, T(o
).add(size
));
91 vec4(vec
&_v
, float _w
= 0) : w(_w
) { *(vec
*)this = _v
; }
99 matrix(const vec
&x
, const vec
&y
, const vec
&z
) : X(x
), Y(y
), Z(z
) {}
101 void transform(vec
&o
) { o
= vec(o
.dot(X
), o
.dot(Y
), o
.dot(Z
)); }
103 void orthonormalize()
105 X
.sub(vec(Z
).mul(Z
.dot(X
)));
106 Y
.sub(vec(Z
).mul(Z
.dot(Y
)))
107 .sub(vec(X
).mul(X
.dot(Y
)));
110 void rotate(float angle
, const vec
&d
)
112 float c
= cosf(angle
), s
= sinf(angle
);
116 void rotate(float c
, float s
, const vec
&d
)
118 X
= vec(d
.x
*d
.x
*(1-c
)+c
, d
.x
*d
.y
*(1-c
)-d
.z
*s
, d
.x
*d
.z
*(1-c
)+d
.y
*s
);
119 Y
= vec(d
.y
*d
.x
*(1-c
)+d
.z
*s
, d
.y
*d
.y
*(1-c
)+c
, d
.y
*d
.z
*(1-c
)-d
.x
*s
);
120 Z
= vec(d
.x
*d
.z
*(1-c
)-d
.y
*s
, d
.y
*d
.z
*(1-c
)+d
.x
*s
, d
.z
*d
.z
*(1-c
)+c
);
123 void transposedtransform(vec
&d
)
125 d
= vec(X
.x
*d
.x
+ Y
.x
*d
.y
+ Z
.x
*d
.z
,
126 X
.y
*d
.x
+ Y
.y
*d
.y
+ Z
.y
*d
.z
,
127 X
.z
*d
.x
+ Y
.z
*d
.y
+ Z
.z
*d
.z
);
135 float dist(const vec
&p
) const { return dot(p
)+offset
; }
136 bool operator==(const plane
&p
) const { return x
==p
.x
&& y
==p
.y
&& z
==p
.z
&& offset
==p
.offset
; }
137 bool operator!=(const plane
&p
) const { return x
!=p
.x
|| y
!=p
.y
|| z
!=p
.z
|| offset
!=p
.offset
; }
140 plane(vec
&c
, float off
) : vec(c
), offset(off
) {}
141 plane(int d
, float off
)
147 plane(float a
, float b
, float c
, float d
) : vec(a
, b
, c
), offset(d
) {}
149 void toplane(const vec
&n
, const vec
&p
)
151 x
= n
.x
; y
= n
.y
; z
= n
.z
;
155 bool toplane(const vec
&a
, const vec
&b
, const vec
&c
)
157 cross(vec(b
).sub(a
), vec(c
).sub(a
));
158 float mag
= magnitude();
159 if(!mag
) return false;
165 bool rayintersect(const vec
&o
, const vec
&ray
, float &dist
)
167 float cosalpha
= dot(ray
);
168 if(cosalpha
==0) return false;
169 float deltac
= offset
+dot(o
);
170 dist
-= deltac
/cosalpha
;
174 float zintersect(const vec
&p
) const { return -(x
*p
.x
+y
*p
.y
+offset
)/z
; }
175 float zdist(const vec
&p
) const { return p
.z
-zintersect(p
); }
182 triangle(const vec
&a
, const vec
&b
, const vec
&c
) : a(a
), b(b
), c(c
) {}
185 triangle
&add(const vec
&o
) { a
.add(o
); b
.add(o
); c
.add(o
); return *this; }
186 triangle
&sub(const vec
&o
) { a
.sub(o
); b
.sub(o
); c
.sub(o
); return *this; }
188 bool operator==(const triangle
&t
) const { return a
== t
.a
&& b
== t
.b
&& c
== t
.c
; }
193 Sauerbraten uses 3 different linear coordinate systems
194 which are oriented around each of the axis dimensions.
196 So any point within the game can be defined by four coordinates: (d, x, y, z)
198 d is the reference axis dimension
199 x is the coordinate of the ROW dimension
200 y is the coordinate of the COL dimension
201 z is the coordinate of the reference dimension (DEPTH)
203 typically, if d is not used, then it is implicitly the Z dimension.
204 ie: d=z => x=x, y=y, z=z
209 const int R
[3] = {1, 2, 0}; // row
210 const int C
[3] = {2, 0, 1}; // col
211 const int D
[3] = {0, 1, 2}; // depth
217 struct { int x
, y
, z
; };
222 ivec(const vec
&v
) : x(int(v
.x
)), y(int(v
.y
)), z(int(v
.z
)) {}
229 ivec(int a
, int b
, int c
) : x(a
), y(b
), z(c
) {}
230 ivec(int d
, int row
, int col
, int depth
)
236 ivec(int i
, int cx
, int cy
, int cz
, int size
)
238 x
= cx
+((i
&1)>>0)*size
;
239 y
= cy
+((i
&2)>>1)*size
;
240 z
= cz
+((i
&4)>>2)*size
;
242 vec
tovec() const { return vec(x
, y
, z
); }
243 int toint() const { return (x
>0?1:0) + (y
>0?2:0) + (z
>0?4:0); }
245 int &operator[](int i
) { return v
[i
]; }
246 int operator[](int i
) const { return v
[i
]; }
248 //int idx(int i) { return v[i]; }
249 bool operator==(const ivec
&v
) const { return x
==v
.x
&& y
==v
.y
&& z
==v
.z
; }
250 bool operator!=(const ivec
&v
) const { return x
!=v
.x
|| y
!=v
.y
|| z
!=v
.z
; }
251 ivec
&shl(int n
) { x
<<= n
; y
<<= n
; z
<<= n
; return *this; }
252 ivec
&shr(int n
) { x
>>= n
; y
>>= n
; z
>>= n
; return *this; }
253 ivec
&mul(int n
) { x
*= n
; y
*= n
; z
*= n
; return *this; }
254 ivec
&div(int n
) { x
/= n
; y
/= n
; z
/= n
; return *this; }
255 ivec
&add(int n
) { x
+= n
; y
+= n
; z
+= n
; return *this; }
256 ivec
&sub(int n
) { x
-= n
; y
-= n
; z
-= n
; return *this; }
257 ivec
&add(const ivec
&v
) { x
+= v
.x
; y
+= v
.y
; z
+= v
.z
; return *this; }
258 ivec
&sub(const ivec
&v
) { x
-= v
.x
; y
-= v
.y
; z
-= v
.z
; return *this; }
259 ivec
&mask(int n
) { x
&= n
; y
&= n
; z
&= n
; return *this; }
260 ivec
&cross(const ivec
&a
, const ivec
&b
) { x
= a
.y
*b
.z
-a
.z
*b
.y
; y
= a
.z
*b
.x
-a
.x
*b
.z
; z
= a
.x
*b
.y
-a
.y
*b
.x
; return *this; }
261 int dot(const ivec
&o
) const { return x
*o
.x
+ y
*o
.y
+ z
*o
.z
; }
264 static inline bool htcmp(const ivec
&x
, const ivec
&y
)
269 static inline uint
hthash(const ivec
&k
)
278 struct { short x
, y
, z
; };
283 svec(short x
, short y
, short z
) : x(x
), y(y
), z(z
) {}
285 short &operator[](int i
) { return v
[i
]; }
286 short operator[](int i
) const { return v
[i
]; }
288 bool operator==(const svec
&v
) const { return x
==v
.x
&& y
==v
.y
&& z
==v
.z
; }
289 bool operator!=(const svec
&v
) const { return x
!=v
.x
|| y
!=v
.y
|| z
!=v
.z
; }
291 void add(const svec
&o
) { x
+= o
.x
; y
+= o
.y
; z
+= o
.z
; }
292 void sub(const svec
&o
) { x
-= o
.x
; y
-= o
.y
; z
-= o
.z
; }
293 void mul(int f
) { x
*= f
; y
*= f
; z
*= f
; }
294 void div(int f
) { x
/= f
; y
/= f
; z
/= f
; }
296 bool iszero() const { return x
==0 && y
==0 && z
==0; }
303 struct { uchar x
, y
, z
; };
308 bvec(uchar x
, uchar y
, uchar z
) : x(x
), y(y
), z(z
) {}
309 bvec(const vec
&v
) : x((uchar
)((v
.x
+1)*255/2)), y((uchar
)((v
.y
+1)*255/2)), z((uchar
)((v
.z
+1)*255/2)) {}
311 uchar
&operator[](int i
) { return v
[i
]; }
312 uchar
operator[](int i
) const { return v
[i
]; }
314 bool operator==(const bvec
&v
) const { return x
==v
.x
&& y
==v
.y
&& z
==v
.z
; }
315 bool operator!=(const bvec
&v
) const { return x
!=v
.x
|| y
!=v
.y
|| z
!=v
.z
; }
317 bool iszero() const { return x
==0 && y
==0 && z
==0; }
319 vec
tovec() const { return vec(x
*(2.0f
/255.0f
)-1.0f
, y
*(2.0f
/255.0f
)-1.0f
, z
*(2.0f
/255.0f
)-1.0f
); }
322 extern bool raysphereintersect(vec c
, float radius
, const vec
&o
, const vec
&ray
, float &dist
);
323 extern bool rayrectintersect(const vec
&b
, const vec
&s
, const vec
&o
, const vec
&ray
, float &dist
, int &orient
);
325 enum { INTERSECT_NONE
, INTERSECT_OVERLAP
, INTERSECT_BEFORESTART
, INTERSECT_MIDDLE
, INTERSECT_AFTEREND
};
326 extern int intersect_plane_line(vec
&linestart
, vec
&linestop
, vec
&planeorig
, vec
&planenormal
, vec
&intersectionpoint
);