le3d - LightEngine 3D
A straightforward C++ 3D software engine for real-time graphics
geometry_simd.h
Go to the documentation of this file.
1 
33 #ifndef LE_GEOMETRY_SIMD_H
34 #define LE_GEOMETRY_SIMD_H
35 
36 #include "global.h"
37 #include "config.h"
38 
39 #include "simd.h"
40 #include <math.h>
41 
42 /*****************************************************************************/
47 struct __attribute__ ((aligned (16))) LeVertex
48 {
49  union {
50  V4SF vf;
51  struct {float x, y, z, w;};
52  };
53 
54  LeVertex()
55  {
56  V4SF vi = {0.0f, 0.0f, 0.0f, 1.0f};
57  vf = vi;
58  }
59 
60  LeVertex(float px, float py, float pz)
61  {
62  V4SF vi = {px, py, pz, 1.0f};
63  vf = vi;
64  }
65 
66  LeVertex(float px, float py, float pz, float pw)
67  {
68  V4SF vi = {px, py, pz, pw};
69  vf = vi;
70  }
71 
72 /*****************************************************************************/
73  static LeVertex spherical(float azi, float inc, float dist)
74  {
75  LeVertex r;
76  r.x = cosf(azi) * cosf(inc) * dist;
77  r.y = sinf(inc) * dist;
78  r.z = -sinf(azi) * cosf(inc) * dist;
79  return r;
80  }
81 
82  LeVertex operator + (LeVertex v) const
83  {
84  LeVertex r;
85  r.vf = vf + v.vf;
86  return r;
87  }
88 
89  LeVertex operator += (LeVertex v)
90  {
91  vf += v.vf;
92  return *this;
93  }
94 
95  LeVertex operator - (LeVertex v) const
96  {
97  LeVertex r;
98  r.vf = vf - v.vf;
99  return r;
100  }
101 
102  LeVertex operator - () const
103  {
104  LeVertex r;
105  r.vf = - vf;
106  return r;
107  }
108 
109  LeVertex operator -= (LeVertex v)
110  {
111  vf -= v.vf;
112  return *this;
113  }
114 
115  LeVertex operator * (LeVertex v) const
116  {
117  LeVertex r;
118  r.vf = vf * v.vf;
119  return r;
120  }
121 
122  LeVertex operator / (LeVertex v) const
123  {
124  LeVertex r;
125  r.vf = vf / v.vf;
126  return r;
127  }
128 
129  LeVertex operator * (float v) const
130  {
131  LeVertex r;
132  V4SF vs = {v, v, v, v};
133  r.vf = vf * vs;
134  return r;
135  }
136 
137  LeVertex operator / (float v) const
138  {
139  LeVertex r;
140  V4SF vs = {v, v, v, v};
141  r.vf = vf / vs;
142  return r;
143  }
144 
145  LeVertex operator *= (LeVertex v)
146  {
147  vf *= v.vf;
148  return *this;
149  }
150 
151  LeVertex operator /= (LeVertex v)
152  {
153  vf /= v.vf;
154  return *this;
155  }
156 
157  LeVertex operator *= (float v)
158  {
159  V4SF vs = {v, v, v, v};
160  vf *= vs;
161  return *this;
162  }
163 
164  LeVertex operator /= (float v)
165  {
166  V4SF vs = {v, v, v, v};
167  vf /= vs;
168  return *this;
169  }
170 
171  bool operator == (LeVertex v)
172  {
173  return x == v.x &&
174  y == v.y &&
175  z == v.z;
176  }
177 
178  float dot(LeVertex v) const
179  {
180  LeVertex d;
181  d.vf = vf * v.vf;
182  return d.x + d.y + d.z;
183  }
184 
185  LeVertex cross(LeVertex v) const
186  {
187  LeVertex c;
188  c.x = y * v.z - v.y * z;
189  c.y = -x * v.z + v.x * z;
190  c.z = x * v.y - v.x * y;
191  return c;
192  }
193 
194  LeVertex sign() const
195  {
196  LeVertex c;
197  c.x = copysignf(1.0f, x);
198  c.y = copysignf(1.0f, y);
199  c.z = copysignf(1.0f, z);
200  c.w = copysignf(1.0f, w);
201  return c;
202  }
203 
204  LeVertex round() const
205  {
206  LeVertex c;
207  c.x = floorf(x + 0.5f);
208  c.y = floorf(y + 0.5f);
209  c.z = floorf(z + 0.5f);
210  c.w = floorf(w + 0.5f);
211  return c;
212  }
213 
214  LeVertex floor() const
215  {
216  LeVertex c;
217  c.x = floorf(x);
218  c.y = floorf(y);
219  c.z = floorf(z);
220  c.w = floorf(w);
221  return c;
222  }
223 
224  LeVertex normalize()
225  {
226  float d = norm();
227  if (d == 0.0f) {
228  V4SF vi = {0.0f, 0.0f, 0.0f, 1.0f};
229  vf = vi;
230  }else{
231  d = 1.0f / d;
232  V4SF vs = {d, d, d, d};
233  vf *= vs;
234  }
235  return *this;
236  }
237 
238  float norm() const
239  {
240  return sqrtf(dot(*this));
241  }
242 };
243 
244 /*****************************************************************************/
249 struct __attribute__ ((aligned (16))) LeAxis
250 {
251  LeVertex origin;
252  LeVertex axis;
253  float norm;
255  LeAxis() :
256  origin(),
257  axis(LeVertex(0.0f, 0.0f, 1.0f)),
258  norm(1.0f)
259  {
260  }
261 
262  LeAxis(const LeVertex & v1, const LeVertex & v2) :
263  origin(v1)
264  {
265  axis = (v2 - v1).normalize();
266  norm = (v2 - v1).norm();
267  }
268 };
269 
270 /*****************************************************************************/
275 struct __attribute__ ((aligned (16))) LePlane
276 {
277  LeAxis xAxis;
278  LeAxis yAxis;
279  LeAxis zAxis;
280 
281  LePlane()
282  {
283  xAxis.axis = LeVertex(1.0f, 0.0f, 0.0f);
284  yAxis.axis = LeVertex(0.0f, 1.0f, 0.0f);
285  zAxis.axis = LeVertex(0.0f, 0.0f, 1.0f);
286  }
287 
288  LePlane(const LeVertex & v1, const LeVertex & v2, const LeVertex & v3) :
289  xAxis(LeAxis(v1, v2)), yAxis(LeAxis(v1, v3))
290  {
291  zAxis = LeAxis(v1, v1 + xAxis.axis.cross(yAxis.axis));
292  }
293 };
294 
295 /*****************************************************************************/
300 struct __attribute__ ((aligned (16))) LeMatrix
301 {
302  LeVertex lines[4];
303 
304  LeMatrix()
305  {
306  identity();
307  }
308 
309  void identity()
310  {
311  lines[0] = LeVertex(1.0f, 0.0f, 0.0f, 0.0f);
312  lines[1] = LeVertex(0.0f, 1.0f, 0.0f, 0.0f);
313  lines[2] = LeVertex(0.0f, 0.0f, 1.0f, 0.0f);
314  lines[3] = LeVertex(0.0f, 0.0f, 0.0f, 1.0f);
315  }
316 
317  void zero()
318  {
319  LeVertex zv = LeVertex(0.0f, 0.0f, 0.0f, 0.0f);
320  lines[0] = zv;
321  lines[1] = zv;
322  lines[2] = zv;
323  lines[3] = zv;
324  }
325 
326  void transpose()
327  {
328  LeMatrix m;
329  m.lines[0] = LeVertex(lines[0].x, lines[1].x, lines[2].x, lines[3].x);
330  m.lines[1] = LeVertex(lines[0].x, lines[1].x, lines[2].x, lines[3].x);
331  m.lines[2] = LeVertex(lines[0].x, lines[1].x, lines[2].x, lines[3].x);
332  m.lines[3] = LeVertex(lines[0].x, lines[1].x, lines[2].x, lines[3].x);
333  *this = m;
334  }
335 
336  void translate(LeVertex d)
337  {
338  lines[0].w += d.x;
339  lines[1].w += d.y;
340  lines[2].w += d.z;
341  }
342 
343  void scale(LeVertex s)
344  {
345  LeMatrix m;
346  m.lines[0].x *= s.x;
347  m.lines[1].y *= s.y;
348  m.lines[2].z *= s.z;
349  *this = m * *this;
350  }
351 
352 /*****************************************************************************/
353  void rotateEulerXYZ(LeVertex a)
354  {
355  rotateX(a.x);
356  rotateY(a.y);
357  rotateZ(a.z);
358  }
359 
360  void rotateEulerXZY(LeVertex a)
361  {
362  rotateX(a.x);
363  rotateZ(a.z);
364  rotateY(a.y);
365  }
366 
367  void rotateEulerYZX(LeVertex a)
368  {
369  rotateY(a.y);
370  rotateZ(a.z);
371  rotateX(a.x);
372  }
373 
374  void rotateEulerYXZ(LeVertex a)
375  {
376  rotateY(a.y);
377  rotateX(a.x);
378  rotateZ(a.z);
379  }
380 
381  void rotateEulerZXY(LeVertex a)
382  {
383  rotateZ(a.z);
384  rotateX(a.x);
385  rotateY(a.y);
386  }
387 
388  void rotateEulerZYX(LeVertex a)
389  {
390  rotateZ(a.z);
391  rotateY(a.y);
392  rotateX(a.x);
393  }
394 
395  void rotateX(float a)
396  {
397  float c = cosf(a);
398  float s = sinf(a);
399 
400  LeMatrix m;
401  m.lines[1].y = c;
402  m.lines[1].z = -s;
403  m.lines[2].y = s;
404  m.lines[2].z = c;
405 
406  *this = m * *this;
407  }
408 
409  void rotateY(float a)
410  {
411  float c = cosf(a);
412  float s = sinf(a);
413 
414  LeMatrix m;
415  m.lines[0].x = c;
416  m.lines[0].z = s;
417  m.lines[2].x = -s;
418  m.lines[2].z = c;
419 
420  *this = m * *this;
421  }
422 
423  void rotateZ(float a)
424  {
425  float c = cosf(a);
426  float s = sinf(a);
427 
428  LeMatrix m;
429  m.lines[0].x = c;
430  m.lines[0].y = -s;
431  m.lines[1].x = s;
432  m.lines[1].y = c;
433 
434  *this = m * *this;
435  }
436 
437  void rotate(LeVertex axis, float angle)
438  {
439  float c = cosf(angle);
440  float s = sinf(angle);
441  float d = 1.0f - c;
442 
443  LeMatrix m;
444  m.lines[0] = LeVertex(c + axis.x * axis.x * d, axis.x * axis.y * d - axis.z * s, axis.x * axis.z * d + axis.y * s, 0.0f);
445  m.lines[1] = LeVertex(axis.y * axis.x * d + axis.z * s, c + axis.y * axis.y * d, axis.y * axis.z * d - axis.x * s, 0.0f);
446  m.lines[2] = LeVertex(axis.z * axis.x * d - axis.y * s, axis.z * axis.y * d + axis.x * s, c + axis.z * axis.z * d, 0.0f);
447  m.lines[3] = LeVertex(0.0f, 0.0f, 0.0f, 1.0f);
448 
449  *this = m * *this;
450  }
451 
452 /*****************************************************************************/
453  void toEulerZYX(LeVertex & angle)
454  {
455  float l = sqrtf(lines[0].x * lines[0].x + lines[1].x * lines[1].x);
456  if (l > 1e-6) {
457  angle.x = atan2f(lines[2].y, lines[2].z);
458  angle.y = atan2f(-lines[2].x, l);
459  angle.z = atan2f(lines[1].x, lines[0].x);
460  }
461  else {
462  angle.x = atan2f(-lines[1].z, lines[1].y);
463  angle.y = atan2f(-lines[2].x, l);
464  angle.z = 0.0f;
465  }
466  }
467 
468 /*****************************************************************************/
469  void alignBackUp(LeVertex back, LeVertex up)
470  {
471  back.normalize();
472  up.normalize();
473  LeVertex right = up.cross(back);
474 
475  LeMatrix m;
476  m.lines[0] = LeVertex(right.x, up.x, back.x, 0.0f);
477  m.lines[1] = LeVertex(right.y, up.y, back.y, 0.0f);
478  m.lines[2] = LeVertex(right.z, up.z, back.z, 0.0f);
479  m.lines[3] = LeVertex(0.0f, 0.0f, 0.0f, 1.0f);
480 
481  *this = m * *this;
482  }
483 
484  void alignBackRight(LeVertex back, LeVertex right)
485  {
486  back.normalize();
487  right.normalize();
488  LeVertex up = back.cross(right);
489 
490  LeMatrix m;
491  m.lines[0] = LeVertex(right.x, up.x, back.x, 0.0f);
492  m.lines[1] = LeVertex(right.y, up.y, back.y, 0.0f);
493  m.lines[2] = LeVertex(right.z, up.z, back.z, 0.0f);
494  m.lines[3] = LeVertex(0.0f, 0.0f, 0.0f, 1.0f);
495 
496  *this = m * *this;
497  }
498 
499 /*****************************************************************************/
500  LeMatrix inverse3x3()
501  {
502  float d = lines[0].x*(lines[1].y*lines[2].z-lines[2].y*lines[1].z)
503  - lines[0].y*(lines[1].x*lines[2].z-lines[1].z*lines[2].x)
504  + lines[0].z*(lines[1].x*lines[2].y-lines[1].y*lines[2].x);
505 
506  LeMatrix m;
507  if (d == 0.0f) {m.zero(); return m;}
508  d = 1.0f / d;
509 
510  m.lines[0].x = (lines[1].y * lines[2].z - lines[2].y * lines[1].z) * d;
511  m.lines[0].y = -(lines[0].y * lines[2].z - lines[2].y * lines[0].z) * d;
512  m.lines[0].z = (lines[0].y * lines[1].z - lines[1].y * lines[0].z) * d;
513 
514  m.lines[1].x = -(lines[1].x * lines[2].z - lines[2].x * lines[1].z) * d;
515  m.lines[1].y = (lines[0].x * lines[2].z - lines[2].x * lines[0].z) * d;
516  m.lines[1].z = -(lines[0].x * lines[1].z - lines[1].x * lines[0].z) * d;
517 
518  m.lines[2].x = (lines[1].x * lines[2].y - lines[2].x * lines[1].y) * d;
519  m.lines[2].y = -(lines[0].x * lines[2].y - lines[2].x * lines[0].y) * d;
520  m.lines[2].z = (lines[0].x * lines[1].y - lines[1].x * lines[0].y) * d;
521 
522  return m;
523  }
524 
525  LeVertex operator * (LeVertex v) const
526  {
527  v.w = 1.0f;
528  LeVertex l1 = lines[0] * v;
529  LeVertex l2 = lines[1] * v;
530  LeVertex l3 = lines[2] * v;
531 
532  return LeVertex(l1.x + l1.y + l1.z + l1.w,
533  l2.x + l2.y + l2.z + l2.w,
534  l3.x + l3.y + l3.z + l3.w);
535  }
536 
537  LeMatrix operator + (LeMatrix m) const
538  {
539  LeMatrix r;
540  r.lines[0] = lines[0] + m.lines[0];
541  r.lines[1] = lines[1] + m.lines[1];
542  r.lines[2] = lines[2] + m.lines[2];
543  r.lines[3] = lines[3] + m.lines[3];
544 
545  return r;
546  }
547 
548  LeMatrix operator * (LeMatrix m) const
549  {
550  LeMatrix r;
551  for (int i = 0; i < 4; i++) {
552  LeVertex vx = LeVertex(lines[i].x, lines[i].x, lines[i].x, lines[i].x);
553  LeVertex vy = LeVertex(lines[i].y, lines[i].y, lines[i].y, lines[i].y);
554  LeVertex vz = LeVertex(lines[i].z, lines[i].z, lines[i].z, lines[i].z);
555  LeVertex vw = LeVertex(lines[i].w, lines[i].w, lines[i].w, lines[i].w);
556  r.lines[i] = vx * m.lines[0] + vy * m.lines[1] + vz * m.lines[2] + vw * m.lines[3];
557  }
558 
559  return r;
560  }
561 };
562 
563 /*****************************************************************************/
564 namespace LePrimitives {
565  const LeVertex up = LeVertex(0.0f, 1.0f, 0.0f);
566  const LeVertex down = LeVertex(0.0f, -1.0f, 0.0f);
567  const LeVertex front = LeVertex(0.0f, 0.0f, -1.0f);
568  const LeVertex back = LeVertex(0.0f, 0.0f, 1.0f);
569  const LeVertex left = LeVertex(-1.0f, 0.0f, 0.0f);
570  const LeVertex right = LeVertex(1.0f, 0.0f, 0.0f);
571  const LeVertex zero = LeVertex(0.0f, 0.0f, 0.0f);
572 }
573 
574 #endif //LE_GEOMETRY_SIMD_H
const LeVertex up
Definition: geometry_scalar.h:661
struct __attribute__((aligned(16))) LeVertex
Definition: geometry_simd.h:47
LightEngine 3D: General engine configuration file.
float x
Definition: geometry_scalar.h:48
LightEngine 3D: Global helpers and definitions.
Definition: geometry_scalar.h:660
const LeVertex down
Definition: geometry_scalar.h:662
const LeVertex back
Definition: geometry_scalar.h:664
const LeVertex front
Definition: geometry_scalar.h:663
LeVertex cross(LeVertex v) const
Definition: geometry_scalar.h:198
float y
Definition: geometry_scalar.h:48
LeVertex normalize()
Definition: geometry_scalar.h:237
Represent a vertex in 3D space.
Definition: geometry_scalar.h:46
Represent a 4x4 matrix to handle 3D transforms.
Definition: geometry_scalar.h:346
LeVertex axis
Definition: geometry_scalar.h:268
float z
Definition: geometry_scalar.h:48
float w
Definition: geometry_scalar.h:48
Represent an axis in 3D space.
Definition: geometry_scalar.h:265
const LeVertex left
Definition: geometry_scalar.h:665
const LeVertex zero
Definition: geometry_scalar.h:667
LightEngine 3D: SIMD constants / types and intrinsic definitions.
const LeVertex right
Definition: geometry_scalar.h:666
Represent a plane in 3D space.
Definition: geometry_scalar.h:302
void zero()
Definition: geometry_scalar.h:378