source: trunk/src/vector.cpp @ 1149

Last change on this file since 1149 was 1149, checked in by gary, 8 years ago

math: minor compilation fixes for Visual Studio. Still does not link.

  • Property svn:keywords set to Id
File size: 10.4 KB
RevLine 
[648]1//
2// Lol Engine
3//
4// Copyright: (c) 2010-2011 Sam Hocevar <sam@hocevar.net>
5//   This program is free software; you can redistribute it and/or
6//   modify it under the terms of the Do What The Fuck You Want To
7//   Public License, Version 2, as published by Sam Hocevar. See
8//   http://sam.zoy.org/projects/COPYING.WTFPL for more details.
9//
10
11#if defined HAVE_CONFIG_H
12#   include "config.h"
13#endif
14
[1044]15#if defined WIN32 && !defined _XBOX
16#   define _USE_MATH_DEFINES /* for M_PI */
17#   define WIN32_LEAN_AND_MEAN
18#   include <windows.h>
19#   undef near /* Fuck Microsoft */
20#   undef far /* Fuck Microsoft again */
21#endif
22
23#include <cmath> /* for M_PI */
[648]24#include <cstdlib> /* free() */
25#include <cstring> /* strdup() */
26
27#include "core.h"
28
[758]29using namespace std;
30
[686]31namespace lol
32{
33
[1137]34float dot(vec2 v1, vec2 v2)
[1041]35{
36    return v1.x * v2.x + v1.y * v2.y;
37}
38
[1137]39float dot(vec3 v1, vec3 v2)
[1041]40{
41    return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
42}
43
[1137]44float dot(vec4 v1, vec4 v2)
[1041]45{
46    return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z + v1.w * v2.w;
47}
48
49template<> vec3 cross(vec3 v1, vec3 v2)
50{
51    return vec3(v1.y * v2.z - v1.z * v2.y,
52                v1.z * v2.x - v1.x * v2.z,
53                v1.x * v2.y - v1.y * v2.x);
54}
55
[648]56static inline float det3(float a, float b, float c,
57                         float d, float e, float f,
58                         float g, float h, float i)
59{
60    return a * (e * i - h * f)
61         + b * (f * g - i * d)
62         + c * (d * h - g * e);
63}
64
[664]65static inline float cofact3(mat4 const &mat, int i, int j)
[648]66{
67    return det3(mat[(i + 1) & 3][(j + 1) & 3],
68                mat[(i + 2) & 3][(j + 1) & 3],
69                mat[(i + 3) & 3][(j + 1) & 3],
70                mat[(i + 1) & 3][(j + 2) & 3],
71                mat[(i + 2) & 3][(j + 2) & 3],
72                mat[(i + 3) & 3][(j + 2) & 3],
73                mat[(i + 1) & 3][(j + 3) & 3],
74                mat[(i + 2) & 3][(j + 3) & 3],
75                mat[(i + 3) & 3][(j + 3) & 3]) * (((i + j) & 1) ? -1.0f : 1.0f);
76}
77
[664]78template<> float mat4::det() const
[648]79{
80    float ret = 0;
81    for (int n = 0; n < 4; n++)
82        ret += (*this)[n][0] * cofact3(*this, n, 0);
83    return ret;
84}
85
[664]86template<> mat4 mat4::invert() const
[648]87{
[664]88    mat4 ret;
[648]89    float d = det();
90    if (d)
91    {
92        d = 1.0f / d;
93        for (int j = 0; j < 4; j++)
94            for (int i = 0; i < 4; i++)
95                ret[j][i] = cofact3(*this, i, j) * d;
96    }
97    return ret;
98}
99
[1041]100template<> void vec2::printf() const
101{
102    Log::Debug("[ %6.6f %6.6f ]\n", x, y);
103}
104
[1046]105template<> void ivec2::printf() const
106{
107    Log::Debug("[ %i %i ]\n", x, y);
108}
109
[1052]110template<> void cmplx::printf() const
111{
112    Log::Debug("[ %6.6f %6.6f ]\n", x, y);
113}
114
[1041]115template<> void vec3::printf() const
116{
117    Log::Debug("[ %6.6f %6.6f %6.6f ]\n", x, y, z);
118}
119
[1046]120template<> void ivec3::printf() const
121{
122    Log::Debug("[ %i %i %i ]\n", x, y, z);
123}
124
[1041]125template<> void vec4::printf() const
126{
127    Log::Debug("[ %6.6f %6.6f %6.6f %6.6f ]\n", x, y, z, w);
128}
129
[1046]130template<> void ivec4::printf() const
131{
132    Log::Debug("[ %i %i %i %i ]\n", x, y, z, w);
133}
134
[1047]135template<> void quat::printf() const
136{
137    Log::Debug("[ %6.6f %6.6f %6.6f %6.6f ]\n", x, y, z, w);
138}
139
[708]140template<> void mat4::printf() const
141{
142    mat4 const &p = *this;
143
[734]144    Log::Debug("[ %6.6f %6.6f %6.6f %6.6f\n",
145               p[0][0], p[1][0], p[2][0], p[3][0]);
146    Log::Debug("  %6.6f %6.6f %6.6f %6.6f\n",
147               p[0][1], p[1][1], p[2][1], p[3][1]);
148    Log::Debug("  %6.6f %6.6f %6.6f %6.6f\n",
149               p[0][2], p[1][2], p[2][2], p[3][2]);
150    Log::Debug("  %6.6f %6.6f %6.6f %6.6f ]\n",
151               p[0][3], p[1][3], p[2][3], p[3][3]);
[708]152}
153
[939]154#if !defined __ANDROID__
[929]155template<> std::ostream &operator<<(std::ostream &stream, ivec2 const &v)
156{
157    return stream << "(" << v.x << ", " << v.y << ")";
158}
159
[1052]160template<> std::ostream &operator<<(std::ostream &stream, icmplx const &v)
161{
162    return stream << "(" << v.x << ", " << v.y << ")";
163}
164
[929]165template<> std::ostream &operator<<(std::ostream &stream, ivec3 const &v)
166{
167    return stream << "(" << v.x << ", " << v.y << ", " << v.z << ")";
168}
169
170template<> std::ostream &operator<<(std::ostream &stream, ivec4 const &v)
171{
172    return stream << "(" << v.x << ", " << v.y << ", "
173                         << v.z << ", " << v.w << ")";
174}
175
[1047]176template<> std::ostream &operator<<(std::ostream &stream, iquat const &v)
177{
178    return stream << "(" << v.x << ", " << v.y << ", "
179                         << v.z << ", " << v.w << ")";
180}
181
[929]182template<> std::ostream &operator<<(std::ostream &stream, vec2 const &v)
183{
184    return stream << "(" << v.x << ", " << v.y << ")";
185}
186
[1052]187template<> std::ostream &operator<<(std::ostream &stream, cmplx const &v)
188{
189    return stream << "(" << v.x << ", " << v.y << ")";
190}
191
[929]192template<> std::ostream &operator<<(std::ostream &stream, vec3 const &v)
193{
194    return stream << "(" << v.x << ", " << v.y << ", " << v.z << ")";
195}
196
197template<> std::ostream &operator<<(std::ostream &stream, vec4 const &v)
198{
199    return stream << "(" << v.x << ", " << v.y << ", "
200                         << v.z << ", " << v.w << ")";
201}
202
[1047]203template<> std::ostream &operator<<(std::ostream &stream, quat const &v)
204{
205    return stream << "(" << v.x << ", " << v.y << ", "
206                         << v.z << ", " << v.w << ")";
207}
208
[929]209template<> std::ostream &operator<<(std::ostream &stream, mat4 const &m)
210{
211    stream << "((" << m[0][0] << ", " << m[1][0]
212            << ", " << m[2][0] << ", " << m[3][0] << "), ";
213    stream << "(" << m[0][1] << ", " << m[1][1]
214           << ", " << m[2][1] << ", " << m[3][1] << "), ";
215    stream << "(" << m[0][2] << ", " << m[1][2]
216           << ", " << m[2][2] << ", " << m[3][2] << "), ";
217    stream << "(" << m[0][3] << ", " << m[1][3]
218           << ", " << m[2][3] << ", " << m[3][3] << "))";
219    return stream;
220}
[939]221#endif
[929]222
[664]223template<> mat4 mat4::translate(float x, float y, float z)
[660]224{
[664]225    mat4 ret(1.0f);
[660]226    ret[3][0] = x;
227    ret[3][1] = y;
228    ret[3][2] = z;
229    return ret;
230}
231
[1041]232template<> mat4 mat4::translate(vec3 v)
233{
234    return translate(v.x, v.y, v.z);
235}
236
[1044]237template<> mat4 mat4::rotate(float angle, float x, float y, float z)
[1041]238{
[1044]239    angle *= (M_PI / 180.0f);
[1041]240
[1044]241    float st = sinf(angle);
242    float ct = cosf(angle);
[1041]243
[661]244    float len = sqrtf(x * x + y * y + z * z);
245    float invlen = len ? 1.0f / len : 0.0f;
246    x *= invlen;
247    y *= invlen;
248    z *= invlen;
249
250    float mtx = (1.0f - ct) * x;
251    float mty = (1.0f - ct) * y;
252    float mtz = (1.0f - ct) * z;
253
[664]254    mat4 ret(1.0f);
[661]255
256    ret[0][0] = x * mtx + ct;
257    ret[0][1] = x * mty + st * z;
258    ret[0][2] = x * mtz - st * y;
259
260    ret[1][0] = y * mtx - st * z;
261    ret[1][1] = y * mty + ct;
262    ret[1][2] = y * mtz + st * x;
263
264    ret[2][0] = z * mtx + st * y;
265    ret[2][1] = z * mty - st * x;
266    ret[2][2] = z * mtz + ct;
267
268    return ret;
269}
270
[1044]271template<> mat4 mat4::rotate(float angle, vec3 v)
[1041]272{
[1044]273    return rotate(angle, v.x, v.y, v.z);
[1041]274}
275
[1048]276template<> mat4 mat4::rotate(quat q)
277{
278    mat4 ret(1.0f);
[1135]279    float n = norm(q);
[1048]280
281    if (!n)
282        return ret;
283
284    float s = 2.0f / n;
285
286    ret[0][0] = 1.0f - s * (q.y * q.y + q.z * q.z);
287    ret[0][1] = s * (q.x * q.y - q.z * q.w);
288    ret[0][2] = s * (q.x * q.z + q.y * q.w);
289
290    ret[1][0] = s * (q.x * q.y + q.z * q.w);
291    ret[1][1] = 1.0f - s * (q.z * q.z + q.x * q.x);
292    ret[1][2] = s * (q.y * q.z - q.x * q.w);
293
294    ret[2][0] = s * (q.x * q.z - q.y * q.w);
295    ret[2][1] = s * (q.y * q.z + q.x * q.w);
296    ret[2][2] = 1.0f - s * (q.x * q.x + q.y * q.y);
297
298    return ret;
299}
300
301template<> quat::Quat(mat4 const &m)
302{
303    /* See http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/christian.htm for a version with no branches */
304    float t = m[0][0] + m[1][1] + m[2][2];
305    if (t > 0)
306    {
307        w = 0.5f * sqrtf(1.0f + t);
308        float s = 0.25f / w;
309        x = s * (m[2][1] - m[1][2]);
310        y = s * (m[0][2] - m[2][0]);
311        z = s * (m[1][0] - m[0][1]);
312    }
313    else if (m[0][0] > m[1][1] && m[0][0] > m[2][2])
314    {
[1149]315        x = 0.5f * sqrtf(1.0f + m[0][0] - m[1][1] - m[2][2]);
[1048]316        float s = 0.25f / x;
317        y = s * (m[1][0] + m[0][1]);
318        z = s * (m[0][2] + m[2][0]);
319        w = s * (m[2][1] - m[1][2]);
320    }
321    else if (m[1][1] > m[2][2])
322    {
323        y = 0.5f * sqrtf(1.0f - m[0][0] + m[1][1] - m[2][2]);
324        float s = 0.25f / y;
325        x = s * (m[1][0] + m[0][1]);
326        z = s * (m[2][1] + m[1][2]);
327        w = s * (m[0][2] - m[2][0]);
328    }
329    else
330    {
331        z = 0.5f * sqrtf(1.0f - m[0][0] - m[1][1] + m[2][2]);
332        float s = 0.25f / z;
333        x = s * (m[0][2] + m[2][0]);
334        y = s * (m[2][1] + m[1][2]);
335        w = s * (m[1][0] - m[0][1]);
336    }
337}
338
[1044]339template<> mat4 mat4::lookat(vec3 eye, vec3 center, vec3 up)
340{
341    vec3 v3 = normalize(eye - center);
342    vec3 v2 = normalize(up);
343    vec3 v1 = normalize(cross(v2, v3));
344    v2 = cross(v3, v1);
345
346    mat4 orient(1.0f);
347    orient[0][0] = v1.x;
348    orient[0][1] = v2.x;
349    orient[0][2] = v3.x;
350    orient[1][0] = v1.y;
351    orient[1][1] = v2.y;
352    orient[1][2] = v3.y;
353    orient[2][0] = v1.z;
354    orient[2][1] = v2.z;
355    orient[2][2] = v3.z;
356
357    return orient * mat4::translate(-eye);
358}
359
360template<> mat4 mat4::ortho(float left, float right, float bottom,
361                            float top, float near, float far)
362{
363    float invrl = (right != left) ? 1.0f / (right - left) : 0.0f;
364    float invtb = (top != bottom) ? 1.0f / (top - bottom) : 0.0f;
365    float invfn = (far != near) ? 1.0f / (far - near) : 0.0f;
366
367    mat4 ret(0.0f);
368    ret[0][0] = 2.0f * invrl;
369    ret[1][1] = 2.0f * invtb;
370    ret[2][2] = -2.0f * invfn;
371    ret[3][0] = - (right + left) * invrl;
372    ret[3][1] = - (top + bottom) * invtb;
373    ret[3][2] = - (far + near) * invfn;
374    ret[3][3] = 1.0f;
375    return ret;
376}
377
378template<> mat4 mat4::frustum(float left, float right, float bottom,
379                              float top, float near, float far)
380{
381    float invrl = (right != left) ? 1.0f / (right - left) : 0.0f;
382    float invtb = (top != bottom) ? 1.0f / (top - bottom) : 0.0f;
383    float invfn = (far != near) ? 1.0f / (far - near) : 0.0f;
384
385    mat4 ret(0.0f);
386    ret[0][0] = 2.0f * near * invrl;
387    ret[1][1] = 2.0f * near * invtb;
388    ret[2][0] = (right + left) * invrl;
389    ret[2][1] = (top + bottom) * invtb;
390    ret[2][2] = - (far + near) * invfn;
391    ret[2][3] = -1.0f;
392    ret[3][2] = -2.0f * far * near * invfn;
393    return ret;
394}
395
396template<> mat4 mat4::perspective(float fov_y, float width,
397                                  float height, float near, float far)
398{
399    fov_y *= (M_PI / 180.0f);
400
401    float t2 = tanf(fov_y * 0.5f);
402    float t1 = t2 * width / height;
403
404    return frustum(-near * t1, near * t1, -near * t2, near * t2, near, far);
405}
406
[686]407} /* namespace lol */
408
Note: See TracBrowser for help on using the repository browser.