source: trunk/src/matrix.cpp @ 1041

Last change on this file since 1041 was 1041, checked in by sam, 8 years ago

core: new combinations of integer vectors (unsigned, 8-bit, etc.), dot and
cross product, normalize, etc.

  • Property svn:keywords set to Id
File size: 7.7 KB
Line 
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
15#include <cstdlib> /* free() */
16#include <cstring> /* strdup() */
17
18#include "core.h"
19
20using namespace std;
21
22namespace lol
23{
24
25template<> float dot(vec2 v1, vec2 v2)
26{
27    return v1.x * v2.x + v1.y * v2.y;
28}
29
30template<> float dot(vec3 v1, vec3 v2)
31{
32    return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
33}
34
35template<> float dot(vec4 v1, vec4 v2)
36{
37    return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z + v1.w * v2.w;
38}
39
40template<> vec3 cross(vec3 v1, vec3 v2)
41{
42    return vec3(v1.y * v2.z - v1.z * v2.y,
43                v1.z * v2.x - v1.x * v2.z,
44                v1.x * v2.y - v1.y * v2.x);
45}
46
47template<> vec2 normalize(vec2 v)
48{
49    float norm = v.sqlen();
50    if (!norm)
51        return vec2(0);
52    return v / norm;
53}
54
55template<> vec3 normalize(vec3 v)
56{
57    float norm = v.sqlen();
58    if (!norm)
59        return vec3(0);
60    return v / norm;
61}
62
63template<> vec4 normalize(vec4 v)
64{
65    float norm = v.sqlen();
66    if (!norm)
67        return vec4(0);
68    return v / norm;
69}
70
71static inline float det3(float a, float b, float c,
72                         float d, float e, float f,
73                         float g, float h, float i)
74{
75    return a * (e * i - h * f)
76         + b * (f * g - i * d)
77         + c * (d * h - g * e);
78}
79
80static inline float cofact3(mat4 const &mat, int i, int j)
81{
82    return det3(mat[(i + 1) & 3][(j + 1) & 3],
83                mat[(i + 2) & 3][(j + 1) & 3],
84                mat[(i + 3) & 3][(j + 1) & 3],
85                mat[(i + 1) & 3][(j + 2) & 3],
86                mat[(i + 2) & 3][(j + 2) & 3],
87                mat[(i + 3) & 3][(j + 2) & 3],
88                mat[(i + 1) & 3][(j + 3) & 3],
89                mat[(i + 2) & 3][(j + 3) & 3],
90                mat[(i + 3) & 3][(j + 3) & 3]) * (((i + j) & 1) ? -1.0f : 1.0f);
91}
92
93template<> float mat4::det() const
94{
95    float ret = 0;
96    for (int n = 0; n < 4; n++)
97        ret += (*this)[n][0] * cofact3(*this, n, 0);
98    return ret;
99}
100
101template<> mat4 mat4::invert() const
102{
103    mat4 ret;
104    float d = det();
105    if (d)
106    {
107        d = 1.0f / d;
108        for (int j = 0; j < 4; j++)
109            for (int i = 0; i < 4; i++)
110                ret[j][i] = cofact3(*this, i, j) * d;
111    }
112    return ret;
113}
114
115template<> void vec2::printf() const
116{
117    Log::Debug("[ %6.6f %6.6f ]\n", x, y);
118}
119
120template<> void vec3::printf() const
121{
122    Log::Debug("[ %6.6f %6.6f %6.6f ]\n", x, y, z);
123}
124
125template<> void vec4::printf() const
126{
127    Log::Debug("[ %6.6f %6.6f %6.6f %6.6f ]\n", x, y, z, w);
128}
129
130template<> void mat4::printf() const
131{
132    mat4 const &p = *this;
133
134    Log::Debug("[ %6.6f %6.6f %6.6f %6.6f\n",
135               p[0][0], p[1][0], p[2][0], p[3][0]);
136    Log::Debug("  %6.6f %6.6f %6.6f %6.6f\n",
137               p[0][1], p[1][1], p[2][1], p[3][1]);
138    Log::Debug("  %6.6f %6.6f %6.6f %6.6f\n",
139               p[0][2], p[1][2], p[2][2], p[3][2]);
140    Log::Debug("  %6.6f %6.6f %6.6f %6.6f ]\n",
141               p[0][3], p[1][3], p[2][3], p[3][3]);
142}
143
144#if !defined __ANDROID__
145template<> std::ostream &operator<<(std::ostream &stream, ivec2 const &v)
146{
147    return stream << "(" << v.x << ", " << v.y << ")";
148}
149
150template<> std::ostream &operator<<(std::ostream &stream, ivec3 const &v)
151{
152    return stream << "(" << v.x << ", " << v.y << ", " << v.z << ")";
153}
154
155template<> std::ostream &operator<<(std::ostream &stream, ivec4 const &v)
156{
157    return stream << "(" << v.x << ", " << v.y << ", "
158                         << v.z << ", " << v.w << ")";
159}
160
161template<> std::ostream &operator<<(std::ostream &stream, vec2 const &v)
162{
163    return stream << "(" << v.x << ", " << v.y << ")";
164}
165
166template<> std::ostream &operator<<(std::ostream &stream, vec3 const &v)
167{
168    return stream << "(" << v.x << ", " << v.y << ", " << v.z << ")";
169}
170
171template<> std::ostream &operator<<(std::ostream &stream, vec4 const &v)
172{
173    return stream << "(" << v.x << ", " << v.y << ", "
174                         << v.z << ", " << v.w << ")";
175}
176
177template<> std::ostream &operator<<(std::ostream &stream, mat4 const &m)
178{
179    stream << "((" << m[0][0] << ", " << m[1][0]
180            << ", " << m[2][0] << ", " << m[3][0] << "), ";
181    stream << "(" << m[0][1] << ", " << m[1][1]
182           << ", " << m[2][1] << ", " << m[3][1] << "), ";
183    stream << "(" << m[0][2] << ", " << m[1][2]
184           << ", " << m[2][2] << ", " << m[3][2] << "), ";
185    stream << "(" << m[0][3] << ", " << m[1][3]
186           << ", " << m[2][3] << ", " << m[3][3] << "))";
187    return stream;
188}
189#endif
190
191template<> mat4 mat4::ortho(float left, float right, float bottom,
192                            float top, float near, float far)
193{
194    float invrl = (right != left) ? 1.0f / (right - left) : 0.0f;
195    float invtb = (top != bottom) ? 1.0f / (top - bottom) : 0.0f;
196    float invfn = (far != near) ? 1.0f / (far - near) : 0.0f;
197
198    mat4 ret(0.0f);
199    ret[0][0] = 2.0f * invrl;
200    ret[1][1] = 2.0f * invtb;
201    ret[2][2] = -2.0f * invfn;
202    ret[3][0] = - (right + left) * invrl;
203    ret[3][1] = - (top + bottom) * invtb;
204    ret[3][2] = - (far + near) * invfn;
205    ret[3][3] = 1.0f;
206    return ret;
207}
208
209template<> mat4 mat4::frustum(float left, float right, float bottom,
210                              float top, float near, float far)
211{
212    float invrl = (right != left) ? 1.0f / (right - left) : 0.0f;
213    float invtb = (top != bottom) ? 1.0f / (top - bottom) : 0.0f;
214    float invfn = (far != near) ? 1.0f / (far - near) : 0.0f;
215
216    mat4 ret(0.0f);
217    ret[0][0] = 2.0f * near * invrl;
218    ret[1][1] = 2.0f * near * invtb;
219    ret[2][0] = (right + left) * invrl;
220    ret[2][1] = (top + bottom) * invtb;
221    ret[2][2] = - (far + near) * invfn;
222    ret[2][3] = -1.0f;
223    ret[3][2] = -2.0f * far * near * invfn;
224    return ret;
225}
226
227template<> mat4 mat4::translate(float x, float y, float z)
228{
229    mat4 ret(1.0f);
230    ret[3][0] = x;
231    ret[3][1] = y;
232    ret[3][2] = z;
233    return ret;
234}
235
236template<> mat4 mat4::translate(vec3 v)
237{
238    return translate(v.x, v.y, v.z);
239}
240
241template<> mat4 mat4::lookat(vec3 eye, vec3 center, vec3 up)
242{
243    vec3 f = normalize(center - eye);
244    vec3 u = normalize(up);
245    vec3 s = normalize(cross(f, u));
246    u = cross(s, f);
247
248    mat4 ret(1.0f);
249    ret[0][0] = s.x;
250    ret[0][1] = s.y;
251    ret[0][2] = s.z;
252    ret[1][0] = u.x;
253    ret[1][1] = u.y;
254    ret[1][2] = u.z;
255    ret[2][0] =-f.x;
256    ret[2][1] =-f.y;
257    ret[2][2] =-f.z;
258    return ret * mat4::translate(-eye);
259}
260
261template<> mat4 mat4::perspective(float theta, float width,
262                                  float height, float near, float far)
263{
264    float t1 = tanf(theta * 0.5f);
265    float t2 = t1 * height / width;
266
267    return frustum(-near * t1, near * t1, -near * t2, near * t2, near, far);
268}
269
270template<> mat4 mat4::rotate(float theta, float x, float y, float z)
271{
272    float st = sinf(theta);
273    float ct = cosf(theta);
274
275    float len = sqrtf(x * x + y * y + z * z);
276    float invlen = len ? 1.0f / len : 0.0f;
277    x *= invlen;
278    y *= invlen;
279    z *= invlen;
280
281    float mtx = (1.0f - ct) * x;
282    float mty = (1.0f - ct) * y;
283    float mtz = (1.0f - ct) * z;
284
285    mat4 ret(1.0f);
286
287    ret[0][0] = x * mtx + ct;
288    ret[0][1] = x * mty + st * z;
289    ret[0][2] = x * mtz - st * y;
290
291    ret[1][0] = y * mtx - st * z;
292    ret[1][1] = y * mty + ct;
293    ret[1][2] = y * mtz + st * x;
294
295    ret[2][0] = z * mtx + st * y;
296    ret[2][1] = z * mty - st * x;
297    ret[2][2] = z * mtz + ct;
298
299    return ret;
300}
301
302template<> mat4 mat4::rotate(float theta, vec3 v)
303{
304    return rotate(theta, v.x, v.y, v.z);
305}
306
307} /* namespace lol */
308
Note: See TracBrowser for help on using the repository browser.