mirror of
https://github.com/NVIDIA/cuda-samples.git
synced 2024-11-28 23:29:16 +08:00
447 lines
10 KiB
C
447 lines
10 KiB
C
|
/*
|
||
|
* Copyright 1993-2015 NVIDIA Corporation. All rights reserved.
|
||
|
*
|
||
|
* Please refer to the NVIDIA end user license agreement (EULA) associated
|
||
|
* with this source code for terms and conditions that govern your use of
|
||
|
* this software. Any use, reproduction, disclosure, or distribution of
|
||
|
* this software and related documentation outside the terms of the EULA
|
||
|
* is strictly prohibited.
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
//
|
||
|
// Template math library for common 3D functionality
|
||
|
//
|
||
|
// nvMatrix.h - template matrix code
|
||
|
//
|
||
|
// This code is in part deriver from glh, a cross platform glut helper library.
|
||
|
// The copyright for glh follows this notice.
|
||
|
//
|
||
|
// Copyright (c) NVIDIA Corporation. All rights reserved.
|
||
|
////////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
/*
|
||
|
Copyright (c) 2000 Cass Everitt
|
||
|
Copyright (c) 2000 NVIDIA Corporation
|
||
|
All rights reserved.
|
||
|
|
||
|
Redistribution and use in source and binary forms, with or
|
||
|
without modification, are permitted provided that the following
|
||
|
conditions are met:
|
||
|
|
||
|
* Redistributions of source code must retain the above
|
||
|
copyright notice, this list of conditions and the following
|
||
|
disclaimer.
|
||
|
|
||
|
* Redistributions in binary form must reproduce the above
|
||
|
copyright notice, this list of conditions and the following
|
||
|
disclaimer in the documentation and/or other materials
|
||
|
provided with the distribution.
|
||
|
|
||
|
* The names of contributors to this software may not be used
|
||
|
to endorse or promote products derived from this software
|
||
|
without specific prior written permission.
|
||
|
|
||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||
|
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||
|
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||
|
REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||
|
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||
|
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||
|
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||
|
POSSIBILITY OF SUCH DAMAGE.
|
||
|
|
||
|
|
||
|
Cass Everitt - cass@r3.nu
|
||
|
*/
|
||
|
|
||
|
#ifndef NV_MATRIX_H
|
||
|
#define NV_MATRIX_H
|
||
|
|
||
|
namespace nv {
|
||
|
|
||
|
template <class T>
|
||
|
class vec2;
|
||
|
template <class T>
|
||
|
class vec3;
|
||
|
template <class T>
|
||
|
class vec4;
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Matrix
|
||
|
//
|
||
|
////////////////////////////////////////////////////////////////////////////////
|
||
|
template <class T>
|
||
|
class matrix4 {
|
||
|
public:
|
||
|
matrix4() { make_identity(); }
|
||
|
|
||
|
matrix4(T t) { set_value(t); }
|
||
|
|
||
|
matrix4(const T *m) { set_value(m); }
|
||
|
|
||
|
matrix4(T a00, T a01, T a02, T a03, T a10, T a11, T a12, T a13, T a20, T a21,
|
||
|
T a22, T a23, T a30, T a31, T a32, T a33)
|
||
|
: _11(a00),
|
||
|
_12(a01),
|
||
|
_13(a02),
|
||
|
_14(a03),
|
||
|
_21(a10),
|
||
|
_22(a11),
|
||
|
_23(a12),
|
||
|
_24(a13),
|
||
|
_31(a20),
|
||
|
_32(a21),
|
||
|
_33(a22),
|
||
|
_34(a23),
|
||
|
_41(a30),
|
||
|
_42(a31),
|
||
|
_43(a32),
|
||
|
_44(a33) {}
|
||
|
|
||
|
void get_value(T *mp) const {
|
||
|
int c = 0;
|
||
|
|
||
|
for (int j = 0; j < 4; j++)
|
||
|
for (int i = 0; i < 4; i++) {
|
||
|
mp[c++] = element(i, j);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
const T *get_value() const { return _array; }
|
||
|
|
||
|
void set_value(T *mp) {
|
||
|
int c = 0;
|
||
|
|
||
|
for (int j = 0; j < 4; j++)
|
||
|
for (int i = 0; i < 4; i++) {
|
||
|
element(i, j) = mp[c++];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void set_value(T r) {
|
||
|
for (int i = 0; i < 4; i++)
|
||
|
for (int j = 0; j < 4; j++) {
|
||
|
element(i, j) = r;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void make_identity() {
|
||
|
element(0, 0) = 1.0;
|
||
|
element(0, 1) = 0.0;
|
||
|
element(0, 2) = 0.0;
|
||
|
element(0, 3) = 0.0;
|
||
|
|
||
|
element(1, 0) = 0.0;
|
||
|
element(1, 1) = 1.0;
|
||
|
element(1, 2) = 0.0;
|
||
|
element(1, 3) = 0.0;
|
||
|
|
||
|
element(2, 0) = 0.0;
|
||
|
element(2, 1) = 0.0;
|
||
|
element(2, 2) = 1.0;
|
||
|
element(2, 3) = 0.0;
|
||
|
|
||
|
element(3, 0) = 0.0;
|
||
|
element(3, 1) = 0.0;
|
||
|
element(3, 2) = 0.0;
|
||
|
element(3, 3) = 1.0;
|
||
|
}
|
||
|
|
||
|
// set a uniform scale
|
||
|
void set_scale(T s) {
|
||
|
element(0, 0) = s;
|
||
|
element(1, 1) = s;
|
||
|
element(2, 2) = s;
|
||
|
}
|
||
|
|
||
|
void set_scale(const vec3<T> &s) {
|
||
|
for (int i = 0; i < 3; i++) {
|
||
|
element(i, i) = s[i];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void set_translate(const vec3<T> &t) {
|
||
|
for (int i = 0; i < 3; i++) {
|
||
|
element(i, 3) = t[i];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void set_row(int r, const vec4<T> &t) {
|
||
|
for (int i = 0; i < 4; i++) {
|
||
|
element(r, i) = t[i];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void set_column(int c, const vec4<T> &t) {
|
||
|
for (int i = 0; i < 4; i++) {
|
||
|
element(i, c) = t[i];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
vec4<T> get_row(int r) const {
|
||
|
vec4<T> v;
|
||
|
|
||
|
for (int i = 0; i < 4; i++) {
|
||
|
v[i] = element(r, i);
|
||
|
}
|
||
|
|
||
|
return v;
|
||
|
}
|
||
|
|
||
|
vec4<T> get_column(int c) const {
|
||
|
vec4<T> v;
|
||
|
|
||
|
for (int i = 0; i < 4; i++) {
|
||
|
v[i] = element(i, c);
|
||
|
}
|
||
|
|
||
|
return v;
|
||
|
}
|
||
|
|
||
|
friend matrix4 inverse(const matrix4 &m) {
|
||
|
matrix4 minv;
|
||
|
|
||
|
T r1[8], r2[8], r3[8], r4[8];
|
||
|
T *s[4], *tmprow;
|
||
|
|
||
|
s[0] = &r1[0];
|
||
|
s[1] = &r2[0];
|
||
|
s[2] = &r3[0];
|
||
|
s[3] = &r4[0];
|
||
|
|
||
|
register int i, j, p, jj;
|
||
|
|
||
|
for (i = 0; i < 4; i++) {
|
||
|
for (j = 0; j < 4; j++) {
|
||
|
s[i][j] = m.element(i, j);
|
||
|
|
||
|
if (i == j) {
|
||
|
s[i][j + 4] = 1.0;
|
||
|
} else {
|
||
|
s[i][j + 4] = 0.0;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
T scp[4];
|
||
|
|
||
|
for (i = 0; i < 4; i++) {
|
||
|
scp[i] = T(fabs(s[i][0]));
|
||
|
|
||
|
for (j = 1; j < 4; j++)
|
||
|
if (T(fabs(s[i][j])) > scp[i]) {
|
||
|
scp[i] = T(fabs(s[i][j]));
|
||
|
}
|
||
|
|
||
|
if (scp[i] == 0.0) {
|
||
|
return minv; // singular matrix!
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int pivot_to;
|
||
|
T scp_max;
|
||
|
|
||
|
for (i = 0; i < 4; i++) {
|
||
|
// select pivot row
|
||
|
pivot_to = i;
|
||
|
scp_max = T(fabs(s[i][i] / scp[i]));
|
||
|
|
||
|
// find out which row should be on top
|
||
|
for (p = i + 1; p < 4; p++)
|
||
|
if (T(fabs(s[p][i] / scp[p])) > scp_max) {
|
||
|
scp_max = T(fabs(s[p][i] / scp[p]));
|
||
|
pivot_to = p;
|
||
|
}
|
||
|
|
||
|
// Pivot if necessary
|
||
|
if (pivot_to != i) {
|
||
|
tmprow = s[i];
|
||
|
s[i] = s[pivot_to];
|
||
|
s[pivot_to] = tmprow;
|
||
|
T tmpscp;
|
||
|
tmpscp = scp[i];
|
||
|
scp[i] = scp[pivot_to];
|
||
|
scp[pivot_to] = tmpscp;
|
||
|
}
|
||
|
|
||
|
T mji;
|
||
|
|
||
|
// perform gaussian elimination
|
||
|
for (j = i + 1; j < 4; j++) {
|
||
|
mji = s[j][i] / s[i][i];
|
||
|
s[j][i] = 0.0;
|
||
|
|
||
|
for (jj = i + 1; jj < 8; jj++) {
|
||
|
s[j][jj] -= mji * s[i][jj];
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (s[3][3] == 0.0) {
|
||
|
return minv; // singular matrix!
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Now we have an upper triangular matrix.
|
||
|
//
|
||
|
// x x x x | y y y y
|
||
|
// 0 x x x | y y y y
|
||
|
// 0 0 x x | y y y y
|
||
|
// 0 0 0 x | y y y y
|
||
|
//
|
||
|
// we'll back substitute to get the inverse
|
||
|
//
|
||
|
// 1 0 0 0 | z z z z
|
||
|
// 0 1 0 0 | z z z z
|
||
|
// 0 0 1 0 | z z z z
|
||
|
// 0 0 0 1 | z z z z
|
||
|
//
|
||
|
|
||
|
T mij;
|
||
|
|
||
|
for (i = 3; i > 0; i--) {
|
||
|
for (j = i - 1; j > -1; j--) {
|
||
|
mij = s[j][i] / s[i][i];
|
||
|
|
||
|
for (jj = j + 1; jj < 8; jj++) {
|
||
|
s[j][jj] -= mij * s[i][jj];
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < 4; i++)
|
||
|
for (j = 0; j < 4; j++) {
|
||
|
minv(i, j) = s[i][j + 4] / s[i][i];
|
||
|
}
|
||
|
|
||
|
return minv;
|
||
|
}
|
||
|
|
||
|
friend matrix4 transpose(const matrix4 &m) {
|
||
|
matrix4 mtrans;
|
||
|
|
||
|
for (int i = 0; i < 4; i++)
|
||
|
for (int j = 0; j < 4; j++) {
|
||
|
mtrans(i, j) = m.element(j, i);
|
||
|
}
|
||
|
|
||
|
return mtrans;
|
||
|
}
|
||
|
|
||
|
matrix4 &operator*=(const matrix4 &rhs) {
|
||
|
matrix4 mt(*this);
|
||
|
set_value(T(0));
|
||
|
|
||
|
for (int i = 0; i < 4; i++)
|
||
|
for (int j = 0; j < 4; j++)
|
||
|
for (int c = 0; c < 4; c++) {
|
||
|
element(i, j) += mt(i, c) * rhs(c, j);
|
||
|
}
|
||
|
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
friend matrix4 operator*(const matrix4 &lhs, const matrix4 &rhs) {
|
||
|
matrix4 r(T(0));
|
||
|
|
||
|
for (int i = 0; i < 4; i++)
|
||
|
for (int j = 0; j < 4; j++)
|
||
|
for (int c = 0; c < 4; c++) {
|
||
|
r.element(i, j) += lhs(i, c) * rhs(c, j);
|
||
|
}
|
||
|
|
||
|
return r;
|
||
|
}
|
||
|
|
||
|
// dst = M * src
|
||
|
vec4<T> operator*(const vec4<T> &src) const {
|
||
|
vec4<T> r;
|
||
|
|
||
|
for (int i = 0; i < 4; i++)
|
||
|
r[i] = (src[0] * element(i, 0) + src[1] * element(i, 1) +
|
||
|
src[2] * element(i, 2) + src[3] * element(i, 3));
|
||
|
|
||
|
return r;
|
||
|
}
|
||
|
|
||
|
// dst = src * M
|
||
|
friend vec4<T> operator*(const vec4<T> &lhs, const matrix4 &rhs) {
|
||
|
vec4<T> r;
|
||
|
|
||
|
for (int i = 0; i < 4; i++)
|
||
|
r[i] = (lhs[0] * rhs.element(0, i) + lhs[1] * rhs.element(1, i) +
|
||
|
lhs[2] * rhs.element(2, i) + lhs[3] * rhs.element(3, i));
|
||
|
|
||
|
return r;
|
||
|
}
|
||
|
|
||
|
T &operator()(int row, int col) { return element(row, col); }
|
||
|
|
||
|
const T &operator()(int row, int col) const { return element(row, col); }
|
||
|
|
||
|
T &element(int row, int col) { return _array[row | (col << 2)]; }
|
||
|
|
||
|
const T &element(int row, int col) const { return _array[row | (col << 2)]; }
|
||
|
|
||
|
matrix4 &operator*=(const T &r) {
|
||
|
for (int i = 0; i < 4; ++i) {
|
||
|
element(0, i) *= r;
|
||
|
element(1, i) *= r;
|
||
|
element(2, i) *= r;
|
||
|
element(3, i) *= r;
|
||
|
}
|
||
|
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
matrix4 &operator+=(const matrix4 &mat) {
|
||
|
for (int i = 0; i < 4; ++i) {
|
||
|
element(0, i) += mat.element(0, i);
|
||
|
element(1, i) += mat.element(1, i);
|
||
|
element(2, i) += mat.element(2, i);
|
||
|
element(3, i) += mat.element(3, i);
|
||
|
}
|
||
|
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
friend bool operator==(const matrix4 &lhs, const matrix4 &rhs) {
|
||
|
bool r = true;
|
||
|
|
||
|
for (int i = 0; i < 16; i++) {
|
||
|
r &= lhs._array[i] == rhs._array[i];
|
||
|
}
|
||
|
|
||
|
return r;
|
||
|
}
|
||
|
|
||
|
friend bool operator!=(const matrix4 &lhs, const matrix4 &rhs) {
|
||
|
bool r = true;
|
||
|
|
||
|
for (int i = 0; i < 16; i++) {
|
||
|
r &= lhs._array[i] != rhs._array[i];
|
||
|
}
|
||
|
|
||
|
return r;
|
||
|
}
|
||
|
|
||
|
union {
|
||
|
struct {
|
||
|
T _11, _12, _13, _14; // standard names for components
|
||
|
T _21, _22, _23, _24; // standard names for components
|
||
|
T _31, _32, _33, _34; // standard names for components
|
||
|
T _41, _42, _43, _44; // standard names for components
|
||
|
};
|
||
|
T _array[16]; // array access
|
||
|
};
|
||
|
};
|
||
|
};
|
||
|
|
||
|
#endif
|