1515 lines
48 KiB
Plaintext
1515 lines
48 KiB
Plaintext
// Filename: lmatrix.I
|
|
// Created by: drose (15Jan99)
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
#include <pandabase.h>
|
|
|
|
#include "deg_2_rad.h"
|
|
#include "nearly_zero.h"
|
|
#include "config_linmath.h"
|
|
|
|
#include <indent.h>
|
|
|
|
#include <math.h>
|
|
|
|
template<class NumType>
|
|
TypeHandle LMatrix4<NumType>::_type_handle;
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix4::Default Constructor
|
|
// Access: Public
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
INLINE LMatrix4<NumType>::
|
|
LMatrix4() {
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix4::Copy Constructor
|
|
// Access: Public
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
INLINE LMatrix4<NumType>::
|
|
LMatrix4(const LMatrix4<NumType> ©) {
|
|
(*this) = copy;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix4::Copy Assignment Operator
|
|
// Access: Public
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
LMatrix4<NumType> &LMatrix4<NumType>::
|
|
operator = (const LMatrix4<NumType> ©) {
|
|
set(copy(0, 0), copy(0, 1), copy(0, 2), copy(0, 3),
|
|
copy(1, 0), copy(1, 1), copy(1, 2), copy(1, 3),
|
|
copy(2, 0), copy(2, 1), copy(2, 2), copy(2, 3),
|
|
copy(3, 0), copy(3, 1), copy(3, 2), copy(3, 3));
|
|
return *this;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix4::Fill Assignment Operator
|
|
// Access: Public
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
INLINE LMatrix4<NumType> &LMatrix4<NumType>::
|
|
operator = (NumType fill_value) {
|
|
fill(fill_value);
|
|
return *this;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix4::Constructor
|
|
// Access: Public
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
INLINE LMatrix4<NumType>::
|
|
LMatrix4(NumType e00, NumType e01, NumType e02, NumType e03,
|
|
NumType e10, NumType e11, NumType e12, NumType e13,
|
|
NumType e20, NumType e21, NumType e22, NumType e23,
|
|
NumType e30, NumType e31, NumType e32, NumType e33) {
|
|
set(e00, e01, e02, e03,
|
|
e10, e11, e12, e13,
|
|
e20, e21, e22, e23,
|
|
e30, e31, e32, e33);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix4::Constructor, upper 3x3
|
|
// Access: Public
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
LMatrix4<NumType>::
|
|
LMatrix4(const LMatrix3<NumType> &upper3) {
|
|
set(upper3(0, 0), upper3(0, 1), upper3(0, 2), 0.0,
|
|
upper3(1, 0), upper3(1, 1), upper3(1, 2), 0.0,
|
|
upper3(2, 0), upper3(2, 1), upper3(2, 2), 0.0,
|
|
0.0, 0.0, 0.0, 1.0);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix4::Constructor, upper 3x3 plus translation
|
|
// Access: Public
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
LMatrix4<NumType>::
|
|
LMatrix4(const LMatrix3<NumType> &upper3,
|
|
const LVecBase3<NumType> &trans) {
|
|
set(upper3(0, 0), upper3(0, 1), upper3(0, 2), 0.0,
|
|
upper3(1, 0), upper3(1, 1), upper3(1, 2), 0.0,
|
|
upper3(2, 0), upper3(2, 1), upper3(2, 2), 0.0,
|
|
trans[0], trans[1], trans[2], 1.0);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix4::fill
|
|
// Access: Public
|
|
// Description: Sets each element of the matrix to the indicated
|
|
// fill_value. This is of questionable value, but is
|
|
// sometimes useful when initializing to zero.
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
void LMatrix4<NumType>::
|
|
fill(NumType fill_value) {
|
|
set(fill_value, fill_value, fill_value, fill_value,
|
|
fill_value, fill_value, fill_value, fill_value,
|
|
fill_value, fill_value, fill_value, fill_value,
|
|
fill_value, fill_value, fill_value, fill_value);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix4::set
|
|
// Access: Public
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
INLINE void LMatrix4<NumType>::
|
|
set(NumType e00, NumType e01, NumType e02, NumType e03,
|
|
NumType e10, NumType e11, NumType e12, NumType e13,
|
|
NumType e20, NumType e21, NumType e22, NumType e23,
|
|
NumType e30, NumType e31, NumType e32, NumType e33) {
|
|
(*this)(0, 0) = e00;
|
|
(*this)(0, 1) = e01;
|
|
(*this)(0, 2) = e02;
|
|
(*this)(0, 3) = e03;
|
|
|
|
(*this)(1, 0) = e10;
|
|
(*this)(1, 1) = e11;
|
|
(*this)(1, 2) = e12;
|
|
(*this)(1, 3) = e13;
|
|
|
|
(*this)(2, 0) = e20;
|
|
(*this)(2, 1) = e21;
|
|
(*this)(2, 2) = e22;
|
|
(*this)(2, 3) = e23;
|
|
|
|
(*this)(3, 0) = e30;
|
|
(*this)(3, 1) = e31;
|
|
(*this)(3, 2) = e32;
|
|
(*this)(3, 3) = e33;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix4::set_upper_3
|
|
// Access: Public
|
|
// Description: Sets the upper 3x3 submatrix.
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
INLINE void LMatrix4<NumType>::
|
|
set_upper_3(const LMatrix3<NumType> &upper3) {
|
|
(*this)(0, 0) = upper3(0, 0);
|
|
(*this)(0, 1) = upper3(0, 1);
|
|
(*this)(0, 2) = upper3(0, 2);
|
|
|
|
(*this)(1, 0) = upper3(1, 0);
|
|
(*this)(1, 1) = upper3(1, 1);
|
|
(*this)(1, 2) = upper3(1, 2);
|
|
|
|
(*this)(2, 0) = upper3(2, 0);
|
|
(*this)(2, 1) = upper3(2, 1);
|
|
(*this)(2, 2) = upper3(2, 2);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix4::get_upper_3
|
|
// Access: Public
|
|
// Description: Retrieves the upper 3x3 submatrix.
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
INLINE LMatrix3<NumType> LMatrix4<NumType>::
|
|
get_upper_3() const {
|
|
return LMatrix3<NumType>
|
|
((*this)(0, 0), (*this)(0, 1), (*this)(0, 2),
|
|
(*this)(1, 0), (*this)(1, 1), (*this)(1, 2),
|
|
(*this)(2, 0), (*this)(2, 1), (*this)(2, 2));
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix4::set_row
|
|
// Access: Public
|
|
// Description: Replaces the indicated row of the matrix.
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
INLINE void LMatrix4<NumType>::
|
|
set_row(int row, const LVecBase4<NumType> &v) {
|
|
(*this)(row, 0) = v[0];
|
|
(*this)(row, 1) = v[1];
|
|
(*this)(row, 2) = v[2];
|
|
(*this)(row, 3) = v[3];
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix4::set_col
|
|
// Access: Public
|
|
// Description: Replaces the indicated column of the matrix.
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
INLINE void LMatrix4<NumType>::
|
|
set_col(int col, const LVecBase4<NumType> &v) {
|
|
(*this)(0, col) = v[0];
|
|
(*this)(1, col) = v[1];
|
|
(*this)(2, col) = v[2];
|
|
(*this)(3, col) = v[3];
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix4::set_row
|
|
// Access: Public
|
|
// Description: Replaces the indicated row of the matrix with the
|
|
// indicated 3-component vector, ignoring the last
|
|
// column.
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
INLINE void LMatrix4<NumType>::
|
|
set_row(int row, const LVecBase3<NumType> &v) {
|
|
(*this)(row, 0) = v[0];
|
|
(*this)(row, 1) = v[1];
|
|
(*this)(row, 2) = v[2];
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix4::set_col
|
|
// Access: Public
|
|
// Description: Replaces the indicated column of the matrix with the
|
|
// indicated 3-component vector, ignoring the last
|
|
// row.
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
INLINE void LMatrix4<NumType>::
|
|
set_col(int col, const LVecBase3<NumType> &v) {
|
|
(*this)(0, col) = v[0];
|
|
(*this)(1, col) = v[1];
|
|
(*this)(2, col) = v[2];
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix4::get_row
|
|
// Access: Public
|
|
// Description: Retrieves the indicated row of the matrix as a
|
|
// 4-component vector.
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
INLINE LVecBase4<NumType> LMatrix4<NumType>::
|
|
get_row(int row) const {
|
|
return LVecBase4<NumType>((*this)(row, 0),
|
|
(*this)(row, 1),
|
|
(*this)(row, 2),
|
|
(*this)(row, 3));
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix4::get_col
|
|
// Access: Public
|
|
// Description: Retrieves the indicated column of the matrix as a
|
|
// 4-component vector.
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
INLINE LVecBase4<NumType> LMatrix4<NumType>::
|
|
get_col(int col) const {
|
|
return LVecBase4<NumType>((*this)(0, col),
|
|
(*this)(1, col),
|
|
(*this)(2, col),
|
|
(*this)(3, col));
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix4::get_row3
|
|
// Access: Public
|
|
// Description: Retrieves the row column of the matrix as a
|
|
// 3-component vector, ignoring the last column.
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
INLINE LVecBase3<NumType> LMatrix4<NumType>::
|
|
get_row3(int row) const {
|
|
return LVecBase3<NumType>((*this)(row, 0),
|
|
(*this)(row, 1),
|
|
(*this)(row, 2));
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix4::get_col3
|
|
// Access: Public
|
|
// Description: Retrieves the indicated column of the matrix as a
|
|
// 3-component vector, ignoring the last row.
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
INLINE LVecBase3<NumType> LMatrix4<NumType>::
|
|
get_col3(int col) const {
|
|
return LVecBase3<NumType>((*this)(0, col),
|
|
(*this)(1, col),
|
|
(*this)(2, col));
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix4::Indexing operator
|
|
// Access: Public
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
INLINE NumType &LMatrix4<NumType>::
|
|
operator () (int row, int col) {
|
|
nassertr(row >= 0 && row < 4, _data[0]);
|
|
nassertr(col >= 0 && col < 4, _data[0]);
|
|
return _data[row * 4 + col];
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix4::Indexing operator
|
|
// Access: Public
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
INLINE NumType LMatrix4<NumType>::
|
|
operator () (int row, int col) const {
|
|
nassertr(row >= 0 && row < 4, 0.0);
|
|
nassertr(col >= 0 && col < 4, 0.0);
|
|
return _data[row * 4 + col];
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix4::is_nan
|
|
// Access: Public
|
|
// Description: Returns true if any component of the matrix is
|
|
// not-a-number, false otherwise.
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
INLINE bool LMatrix4<NumType>::
|
|
is_nan() const {
|
|
return
|
|
cnan(_data[0]) || cnan(_data[1]) || cnan(_data[2]) || cnan(_data[3]) ||
|
|
cnan(_data[4]) || cnan(_data[5]) || cnan(_data[6]) || cnan(_data[7]) ||
|
|
cnan(_data[8]) || cnan(_data[9]) || cnan(_data[10]) || cnan(_data[11]) ||
|
|
cnan(_data[12]) || cnan(_data[13]) || cnan(_data[14]) || cnan(_data[15]);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix4::get_cell
|
|
// Access: Public
|
|
// Description: Returns a particular element of the matrix.
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
INLINE NumType LMatrix4<NumType>::
|
|
get_cell(int row, int col) const {
|
|
nassertr(row >= 0 && row < 4, 0.0);
|
|
nassertr(col >= 0 && col < 4, 0.0);
|
|
return _data[row * 4 + col];
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix4::set_cell
|
|
// Access: Public
|
|
// Description: Changes a particular element of the matrix.
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
INLINE void LMatrix4<NumType>::
|
|
set_cell(int row, int col, NumType value) {
|
|
nassertv(row >= 0 && row < 4);
|
|
nassertv(col >= 0 && col < 4);
|
|
_data[row * 4 + col] = value;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix4::get_data
|
|
// Access: Public
|
|
// Description: Returns the address of the first of the nine data
|
|
// elements in the matrix. The remaining elements
|
|
// occupy the next eight positions in row-major order.
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
INLINE const NumType *LMatrix4<NumType>::
|
|
get_data() const {
|
|
return _data;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix4::get_num_components
|
|
// Access: Public
|
|
// Description: Returns the number of elements in the matrix, 16.
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
INLINE int LMatrix4<NumType>::
|
|
get_num_components() const {
|
|
return 16;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix4::begin
|
|
// Access: Public
|
|
// Description: Returns an iterator that may be used to traverse the
|
|
// elements of the matrix, STL-style.
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
INLINE LMatrix4<NumType>::iterator LMatrix4<NumType>::
|
|
begin() {
|
|
return _data;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix4::end
|
|
// Access: Public
|
|
// Description: Returns an iterator that may be used to traverse the
|
|
// elements of the matrix, STL-style.
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
INLINE LMatrix4<NumType>::iterator LMatrix4<NumType>::
|
|
end() {
|
|
return begin() + 16;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix4::begin
|
|
// Access: Public
|
|
// Description: Returns an iterator that may be used to traverse the
|
|
// elements of the matrix, STL-style.
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
INLINE LMatrix4<NumType>::const_iterator LMatrix4<NumType>::
|
|
begin() const {
|
|
return _data;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix4::end
|
|
// Access: Public
|
|
// Description: Returns an iterator that may be used to traverse the
|
|
// elements of the matrix, STL-style.
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
INLINE LMatrix4<NumType>::const_iterator LMatrix4<NumType>::
|
|
end() const {
|
|
return begin() + 16;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix4::Equality Operator
|
|
// Access: Public
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
bool LMatrix4<NumType>::
|
|
operator == (const LMatrix4<NumType> &other) const {
|
|
return ((*this)(0, 0) == other(0, 0) &&
|
|
(*this)(0, 1) == other(0, 1) &&
|
|
(*this)(0, 2) == other(0, 2) &&
|
|
(*this)(0, 3) == other(0, 3) &&
|
|
(*this)(1, 0) == other(1, 0) &&
|
|
(*this)(1, 1) == other(1, 1) &&
|
|
(*this)(1, 2) == other(1, 2) &&
|
|
(*this)(1, 3) == other(1, 3) &&
|
|
(*this)(2, 0) == other(2, 0) &&
|
|
(*this)(2, 1) == other(2, 1) &&
|
|
(*this)(2, 2) == other(2, 2) &&
|
|
(*this)(2, 3) == other(2, 3) &&
|
|
(*this)(3, 0) == other(3, 0) &&
|
|
(*this)(3, 1) == other(3, 1) &&
|
|
(*this)(3, 2) == other(3, 2) &&
|
|
(*this)(3, 3) == other(3, 3));
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix4::Inequality Operator
|
|
// Access: Public
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
INLINE bool LMatrix4<NumType>::
|
|
operator != (const LMatrix4<NumType> &other) const {
|
|
return !operator == (other);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix4::compare_to
|
|
// Access: Public
|
|
// Description: This flavor of compare_to uses a default threshold
|
|
// value based on the numeric type.
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
INLINE int LMatrix4<NumType>::
|
|
compare_to(const LMatrix4<NumType> &other) const {
|
|
return compare_to(other, NEARLY_ZERO(NumType));
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix4::compare_to
|
|
// Access: Public
|
|
// Description: Sorts matrices lexicographically, componentwise.
|
|
// Returns a number less than 0 if this matrix sorts
|
|
// before the other one, greater than zero if it sorts
|
|
// after, 0 if they are equivalent (within the indicated
|
|
// tolerance).
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
int LMatrix4<NumType>::
|
|
compare_to(const LMatrix4<NumType> &other, NumType threshold) const {
|
|
for (int i = 0; i < 16; i++) {
|
|
if (!IS_THRESHOLD_EQUAL(_data[i], other._data[i], threshold)) {
|
|
return (_data[i] < other._data[i]) ? -1 : 1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix4::xform
|
|
// Access: Public
|
|
// Description: 4-component vector or point times matrix. This is a
|
|
// fully general operation.
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
INLINE LVecBase4<NumType> LMatrix4<NumType>::
|
|
xform(const LVecBase4<NumType> &v) const {
|
|
return LVecBase4<NumType>(v.dot(get_col(0)),
|
|
v.dot(get_col(1)),
|
|
v.dot(get_col(2)),
|
|
v.dot(get_col(3)));
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix4::xform_point
|
|
// Access: Public
|
|
// Description: The matrix transforms a 3-component point (including
|
|
// translation component) and returns the result. This
|
|
// assumes the matrix is an affine transform.
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
INLINE LVecBase3<NumType> LMatrix4<NumType>::
|
|
xform_point(const LVecBase3<NumType> &v) const {
|
|
return LVecBase3<NumType>(v.dot(get_col3(0)) + (*this)(3, 0),
|
|
v.dot(get_col3(1)) + (*this)(3, 1),
|
|
v.dot(get_col3(2)) + (*this)(3, 2));
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix4::xform_vec
|
|
// Access: Public
|
|
// Description: The matrix transforms a 3-component vector (without
|
|
// translation component) and returns the result. This
|
|
// assumes the matrix is an affine transform.
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
INLINE LVecBase3<NumType> LMatrix4<NumType>::
|
|
xform_vec(const LVecBase3<NumType> &v) const {
|
|
return LVecBase3<NumType>(v.dot(get_col3(0)),
|
|
v.dot(get_col3(1)),
|
|
v.dot(get_col3(2)));
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix4::mult_cel
|
|
// Access: Private
|
|
// Description: Returns one cell of the result of a matrix-matrix
|
|
// multiplication operation.
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
INLINE NumType LMatrix4<NumType>::
|
|
mult_cel(const LMatrix4<NumType> &other, int row, int col) const {
|
|
return get_row(row).dot(other.get_col(col));
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix4::matrix * matrix
|
|
// Access: Public
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
LMatrix4<NumType> LMatrix4<NumType>::
|
|
operator * (const LMatrix4<NumType> &other) const {
|
|
LMatrix4<NumType> t;
|
|
|
|
t(0, 0) = mult_cel(other, 0, 0);
|
|
t(0, 1) = mult_cel(other, 0, 1);
|
|
t(0, 2) = mult_cel(other, 0, 2);
|
|
t(0, 3) = mult_cel(other, 0, 3);
|
|
|
|
t(1, 0) = mult_cel(other, 1, 0);
|
|
t(1, 1) = mult_cel(other, 1, 1);
|
|
t(1, 2) = mult_cel(other, 1, 2);
|
|
t(1, 3) = mult_cel(other, 1, 3);
|
|
|
|
t(2, 0) = mult_cel(other, 2, 0);
|
|
t(2, 1) = mult_cel(other, 2, 1);
|
|
t(2, 2) = mult_cel(other, 2, 2);
|
|
t(2, 3) = mult_cel(other, 2, 3);
|
|
|
|
t(3, 0) = mult_cel(other, 3, 0);
|
|
t(3, 1) = mult_cel(other, 3, 1);
|
|
t(3, 2) = mult_cel(other, 3, 2);
|
|
t(3, 3) = mult_cel(other, 3, 3);
|
|
|
|
return t;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix4::matrix * scalar
|
|
// Access: Public
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
LMatrix4<NumType> LMatrix4<NumType>::
|
|
operator * (NumType scalar) const {
|
|
LMatrix4<NumType> t;
|
|
|
|
t(0, 0) = (*this)(0, 0) * scalar;
|
|
t(0, 1) = (*this)(0, 1) * scalar;
|
|
t(0, 2) = (*this)(0, 2) * scalar;
|
|
t(0, 3) = (*this)(0, 3) * scalar;
|
|
|
|
t(1, 0) = (*this)(1, 0) * scalar;
|
|
t(1, 1) = (*this)(1, 1) * scalar;
|
|
t(1, 2) = (*this)(1, 2) * scalar;
|
|
t(1, 3) = (*this)(1, 3) * scalar;
|
|
|
|
t(2, 0) = (*this)(2, 0) * scalar;
|
|
t(2, 1) = (*this)(2, 1) * scalar;
|
|
t(2, 2) = (*this)(2, 2) * scalar;
|
|
t(2, 3) = (*this)(2, 3) * scalar;
|
|
|
|
t(3, 0) = (*this)(3, 0) * scalar;
|
|
t(3, 1) = (*this)(3, 1) * scalar;
|
|
t(3, 2) = (*this)(3, 2) * scalar;
|
|
t(3, 3) = (*this)(3, 3) * scalar;
|
|
|
|
return t;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix4::matrix / scalar
|
|
// Access: Public
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
LMatrix4<NumType> LMatrix4<NumType>::
|
|
operator / (NumType scalar) const {
|
|
LMatrix4<NumType> t;
|
|
|
|
t(0, 0) = (*this)(0, 0) / scalar;
|
|
t(0, 1) = (*this)(0, 1) / scalar;
|
|
t(0, 2) = (*this)(0, 2) / scalar;
|
|
t(0, 3) = (*this)(0, 3) / scalar;
|
|
|
|
t(1, 0) = (*this)(1, 0) / scalar;
|
|
t(1, 1) = (*this)(1, 1) / scalar;
|
|
t(1, 2) = (*this)(1, 2) / scalar;
|
|
t(1, 3) = (*this)(1, 3) / scalar;
|
|
|
|
t(2, 0) = (*this)(2, 0) / scalar;
|
|
t(2, 1) = (*this)(2, 1) / scalar;
|
|
t(2, 2) = (*this)(2, 2) / scalar;
|
|
t(2, 3) = (*this)(2, 3) / scalar;
|
|
|
|
t(3, 0) = (*this)(3, 0) / scalar;
|
|
t(3, 1) = (*this)(3, 1) / scalar;
|
|
t(3, 2) = (*this)(3, 2) / scalar;
|
|
t(3, 3) = (*this)(3, 3) / scalar;
|
|
|
|
return t;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix4::matrix += matrix
|
|
// Access: Public
|
|
// Description: Performs a memberwise addition between two matrices.
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
LMatrix4<NumType> &LMatrix4<NumType>::
|
|
operator += (const LMatrix4<NumType> &other) {
|
|
(*this)(0, 0) += other(0, 0);
|
|
(*this)(0, 1) += other(0, 1);
|
|
(*this)(0, 2) += other(0, 2);
|
|
(*this)(0, 3) += other(0, 3);
|
|
|
|
(*this)(1, 0) += other(1, 0);
|
|
(*this)(1, 1) += other(1, 1);
|
|
(*this)(1, 2) += other(1, 2);
|
|
(*this)(1, 3) += other(1, 3);
|
|
|
|
(*this)(2, 0) += other(2, 0);
|
|
(*this)(2, 1) += other(2, 1);
|
|
(*this)(2, 2) += other(2, 2);
|
|
(*this)(2, 3) += other(2, 3);
|
|
|
|
(*this)(3, 0) += other(3, 0);
|
|
(*this)(3, 1) += other(3, 1);
|
|
(*this)(3, 2) += other(3, 2);
|
|
(*this)(3, 3) += other(3, 3);
|
|
|
|
return *this;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix4::matrix -= matrix
|
|
// Access: Public
|
|
// Description: Performs a memberwise addition between two matrices.
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
LMatrix4<NumType> &LMatrix4<NumType>::
|
|
operator -= (const LMatrix4<NumType> &other) {
|
|
(*this)(0, 0) -= other(0, 0);
|
|
(*this)(0, 1) -= other(0, 1);
|
|
(*this)(0, 2) -= other(0, 2);
|
|
(*this)(0, 3) -= other(0, 3);
|
|
|
|
(*this)(1, 0) -= other(1, 0);
|
|
(*this)(1, 1) -= other(1, 1);
|
|
(*this)(1, 2) -= other(1, 2);
|
|
(*this)(1, 3) -= other(1, 3);
|
|
|
|
(*this)(2, 0) -= other(2, 0);
|
|
(*this)(2, 1) -= other(2, 1);
|
|
(*this)(2, 2) -= other(2, 2);
|
|
(*this)(2, 3) -= other(2, 3);
|
|
|
|
(*this)(3, 0) -= other(3, 0);
|
|
(*this)(3, 1) -= other(3, 1);
|
|
(*this)(3, 2) -= other(3, 2);
|
|
(*this)(3, 3) -= other(3, 3);
|
|
|
|
return *this;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix4::matrix *= matrix
|
|
// Access: Public
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
INLINE LMatrix4<NumType> &LMatrix4<NumType>::
|
|
operator *= (const LMatrix4<NumType> &other) {
|
|
(*this) = (*this) * other;
|
|
return *this;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix4::matrix *= scalar
|
|
// Access: Public
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
LMatrix4<NumType> &LMatrix4<NumType>::
|
|
operator *= (NumType scalar) {
|
|
(*this)(0, 0) *= scalar;
|
|
(*this)(0, 1) *= scalar;
|
|
(*this)(0, 2) *= scalar;
|
|
(*this)(0, 3) *= scalar;
|
|
|
|
(*this)(1, 0) *= scalar;
|
|
(*this)(1, 1) *= scalar;
|
|
(*this)(1, 2) *= scalar;
|
|
(*this)(1, 3) *= scalar;
|
|
|
|
(*this)(2, 0) *= scalar;
|
|
(*this)(2, 1) *= scalar;
|
|
(*this)(2, 2) *= scalar;
|
|
(*this)(2, 3) *= scalar;
|
|
|
|
(*this)(3, 0) *= scalar;
|
|
(*this)(3, 1) *= scalar;
|
|
(*this)(3, 2) *= scalar;
|
|
(*this)(3, 3) *= scalar;
|
|
|
|
return *this;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix4::matrix /= scalar
|
|
// Access: Public
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
LMatrix4<NumType> &LMatrix4<NumType>::
|
|
operator /= (NumType scalar) {
|
|
(*this)(0, 0) /= scalar;
|
|
(*this)(0, 1) /= scalar;
|
|
(*this)(0, 2) /= scalar;
|
|
(*this)(0, 3) /= scalar;
|
|
|
|
(*this)(1, 0) /= scalar;
|
|
(*this)(1, 1) /= scalar;
|
|
(*this)(1, 2) /= scalar;
|
|
(*this)(1, 3) /= scalar;
|
|
|
|
(*this)(2, 0) /= scalar;
|
|
(*this)(2, 1) /= scalar;
|
|
(*this)(2, 2) /= scalar;
|
|
(*this)(2, 3) /= scalar;
|
|
|
|
(*this)(3, 0) /= scalar;
|
|
(*this)(3, 1) /= scalar;
|
|
(*this)(3, 2) /= scalar;
|
|
(*this)(3, 3) /= scalar;
|
|
|
|
return *this;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix4::transpose_from
|
|
// Access: Public
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
void LMatrix4<NumType>::
|
|
transpose_from(const LMatrix4<NumType> &other) {
|
|
(*this)(0, 0) = other(0, 0);
|
|
(*this)(0, 1) = other(1, 0);
|
|
(*this)(0, 2) = other(2, 0);
|
|
(*this)(0, 3) = other(3, 0);
|
|
|
|
(*this)(1, 0) = other(0, 1);
|
|
(*this)(1, 1) = other(1, 1);
|
|
(*this)(1, 2) = other(2, 1);
|
|
(*this)(1, 3) = other(3, 1);
|
|
|
|
(*this)(2, 0) = other(0, 2);
|
|
(*this)(2, 1) = other(1, 2);
|
|
(*this)(2, 2) = other(2, 2);
|
|
(*this)(2, 3) = other(3, 2);
|
|
|
|
(*this)(3, 0) = other(0, 3);
|
|
(*this)(3, 1) = other(1, 3);
|
|
(*this)(3, 2) = other(2, 3);
|
|
(*this)(3, 3) = other(3, 3);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix4::transpose_in_place
|
|
// Access: Public
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
INLINE void LMatrix4<NumType>::
|
|
transpose_in_place() {
|
|
LMatrix4<NumType> temp = (*this);
|
|
transpose_from(temp);
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix4::invert_from
|
|
// Access: Public
|
|
// Description: Computes the inverse of the other matrix, and stores
|
|
// the result in this matrix. This is a fully general
|
|
// operation and makes no assumptions about the type of
|
|
// transform represented by the matrix.
|
|
//
|
|
// The other matrix must be a different object than this
|
|
// matrix. However, if you need to invert a matrix in
|
|
// place, see invert_in_place.
|
|
//
|
|
// The return value is true if the matrix was
|
|
// successfully inverted, false if the was a
|
|
// singularity.
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
bool LMatrix4<NumType>::
|
|
invert_from(const LMatrix4<NumType> &other) {
|
|
if (IS_NEARLY_EQUAL(other(3, 0), 0.0) &&
|
|
IS_NEARLY_EQUAL(other(3, 1), 0.0) &&
|
|
IS_NEARLY_EQUAL(other(3, 2), 0.0) &&
|
|
IS_NEARLY_EQUAL(other(3, 3), 1.0)) {
|
|
return invert_affine_from(other);
|
|
}
|
|
|
|
(*this) = other;
|
|
|
|
int index[4];
|
|
|
|
if (!decompose_mat(index)) {
|
|
nout << "Tried to invert singular LMatrix4.\n";
|
|
return false;
|
|
}
|
|
|
|
LMatrix4<NumType> inv = LMatrix4<NumType>::ident_mat();
|
|
int row;
|
|
|
|
for (row = 0; row < 4; row++) {
|
|
back_sub_mat(index, inv, row);
|
|
}
|
|
|
|
transpose_from(inv);
|
|
return true;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix4::invert_affine_from
|
|
// Access: Public
|
|
// Description: Performs an invert of the indicated matrix, storing
|
|
// the result in this matrix. The calculation is only
|
|
// correct of the other matrix represents an affine
|
|
// transform.
|
|
//
|
|
// The other matrix must be a different object than this
|
|
// matrix. However, if you need to invert a matrix in
|
|
// place, see invert_in_place.
|
|
//
|
|
// The return value is true if the matrix was
|
|
// successfully inverted, false if the was a
|
|
// singularity.
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
bool LMatrix4<NumType>::
|
|
invert_affine_from(const LMatrix4<NumType> &other) {
|
|
LMatrix3<NumType> rot;
|
|
rot.invert_from(other.get_upper_3());
|
|
|
|
set_upper_3(rot);
|
|
set_col(3, LVecBase4<NumType>(0.0, 0.0, 0.0, 1.0));
|
|
|
|
// compute -C*inv(A)
|
|
for (int i = 0; i < 3; i++) {
|
|
(*this)(3, i) = 0.0;
|
|
for (int j = 0; j < 3; j++) {
|
|
(*this)(3, i) -= other(3, j) * (*this)(j, i);
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix4::invert_in_place
|
|
// Access: Public
|
|
// Description: Inverts the current matrix. Returns true if the
|
|
// inverse is successful, false if the matrix was
|
|
// singular.
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
INLINE bool LMatrix4<NumType>::
|
|
invert_in_place() {
|
|
LMatrix4<NumType> temp = (*this);
|
|
return invert_from(temp);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix::ident_mat
|
|
// Access: Public, Static
|
|
// Description: Returns an identity matrix.
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
const LMatrix4<NumType> &LMatrix4<NumType>::
|
|
ident_mat() {
|
|
static LMatrix4<NumType> mat(1.0, 0.0, 0.0, 0.0,
|
|
0.0, 1.0, 0.0, 0.0,
|
|
0.0, 0.0, 1.0, 0.0,
|
|
0.0, 0.0, 0.0, 1.0);
|
|
return mat;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix::translate_mat
|
|
// Access: Public, Static
|
|
// Description: Returns a matrix that applies the indicated
|
|
// translation.
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
LMatrix4<NumType> LMatrix4<NumType>::
|
|
translate_mat(const LVecBase3<NumType> &trans) {
|
|
return LMatrix4<NumType>(1.0, 0.0, 0.0, 0.0,
|
|
0.0, 1.0, 0.0, 0.0,
|
|
0.0, 0.0, 1.0, 0.0,
|
|
trans[0], trans[1], trans[2], 1.0);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix::translate_mat
|
|
// Access: Public, Static
|
|
// Description: Returns a matrix that applies the indicated
|
|
// translation.
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
LMatrix4<NumType> LMatrix4<NumType>::
|
|
translate_mat(NumType tx, NumType ty, NumType tz) {
|
|
return LMatrix4<NumType>(1.0, 0.0, 0.0, 0.0,
|
|
0.0, 1.0, 0.0, 0.0,
|
|
0.0, 0.0, 1.0, 0.0,
|
|
tx, ty, tz, 1.0);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix::rotate_mat
|
|
// Access: Public, Static
|
|
// Description: Returns a matrix that rotates by the given angle in
|
|
// degrees counterclockwise about the indicated vector.
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
LMatrix4<NumType> LMatrix4<NumType>::
|
|
rotate_mat(NumType angle, LVecBase3<NumType> axis,
|
|
CoordinateSystem cs) {
|
|
if (cs == CS_default) {
|
|
cs = default_coordinate_system;
|
|
}
|
|
LMatrix4<NumType> mat;
|
|
|
|
if (!is_right_handed(cs)) {
|
|
// In a left-handed coordinate system, counterclockwise is the
|
|
// other direction.
|
|
angle = -angle;
|
|
}
|
|
|
|
// Normalize the axis.
|
|
NumType length2 = axis.dot(axis);
|
|
// Cannot rotate about a zero-length axis.
|
|
nassertr(length2 != 0.0, ident_mat());
|
|
axis /= csqrt(length2);
|
|
|
|
double s = sin(deg_2_rad(angle));
|
|
double c = cos(deg_2_rad(angle));
|
|
double t = 1.0 - c;
|
|
|
|
mat(0, 0) = t * axis[0] * axis[0] + c;
|
|
mat(0, 1) = t * axis[0] * axis[1] + s * axis[2];
|
|
mat(0, 2) = t * axis[0] * axis[2] - s * axis[1];
|
|
mat(0, 3) = 0.0;
|
|
|
|
mat(1, 0) = t * axis[1] * axis[0] - s * axis[2];
|
|
mat(1, 1) = t * axis[1] * axis[1] + c;
|
|
mat(1, 2) = t * axis[1] * axis[2] + s * axis[0];
|
|
mat(1, 3) = 0.0;
|
|
|
|
mat(2, 0) = t * axis[2] * axis[0] + s * axis[1];
|
|
mat(2, 1) = t * axis[2] * axis[1] - s * axis[0];
|
|
mat(2, 2) = t * axis[2] * axis[2] + c;
|
|
mat(2, 3) = 0.0;
|
|
|
|
mat(3, 0) = 0.0;
|
|
mat(3, 1) = 0.0;
|
|
mat(3, 2) = 0.0;
|
|
mat(3, 3) = 1.0;
|
|
|
|
return mat;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix::scale_mat
|
|
// Access: Public, Static
|
|
// Description: Returns a matrix that applies the indicated
|
|
// scale in each of the three axes.
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
LMatrix4<NumType> LMatrix4<NumType>::
|
|
scale_mat(const LVecBase3<NumType> &scale) {
|
|
return LMatrix4<NumType>(scale[0], 0.0, 0.0, 0.0,
|
|
0.0, scale[1], 0.0, 0.0,
|
|
0.0, 0.0, scale[2], 0.0,
|
|
0.0, 0.0, 0.0, 1.0);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix::scale_mat
|
|
// Access: Public, Static
|
|
// Description: Returns a matrix that applies the indicated
|
|
// scale in each of the three axes.
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
LMatrix4<NumType> LMatrix4<NumType>::
|
|
scale_mat(NumType sx, NumType sy, NumType sz) {
|
|
return LMatrix4<NumType>(sx, 0.0, 0.0, 0.0,
|
|
0.0, sy, 0.0, 0.0,
|
|
0.0, 0.0, sz, 0.0,
|
|
0.0, 0.0, 0.0, 1.0);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix::scale_mat
|
|
// Access: Public, Static
|
|
// Description: Returns a matrix that applies the indicated
|
|
// uniform scale.
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
LMatrix4<NumType> LMatrix4<NumType>::
|
|
scale_mat(NumType scale) {
|
|
return LMatrix4<NumType>(scale, 0.0, 0.0, 0.0,
|
|
0.0, scale, 0.0, 0.0,
|
|
0.0, 0.0, scale, 0.0,
|
|
0.0, 0.0, 0.0, 1.0);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix::y_to_z_up_mat
|
|
// Access: Public, Static
|
|
// Description: Returns a matrix that transforms from the Y-up
|
|
// coordinate system to the Z-up coordinate system.
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
const LMatrix4<NumType> &LMatrix4<NumType>::
|
|
y_to_z_up_mat() {
|
|
static LMatrix4<NumType> mat(1.0, 0.0, 0.0, 0.0,
|
|
0.0, 0.0, 1.0, 0.0,
|
|
0.0,-1.0, 0.0, 0.0,
|
|
0.0, 0.0, 0.0, 1.0);
|
|
return mat;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix::z_to_y_up_mat
|
|
// Access: Public, Static
|
|
// Description: Returns a matrix that transforms from the Y-up
|
|
// coordinate system to the Z-up coordinate system.
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
const LMatrix4<NumType> &LMatrix4<NumType>::
|
|
z_to_y_up_mat() {
|
|
static LMatrix4<NumType> mat(1.0, 0.0, 0.0, 0.0,
|
|
0.0, 0.0,-1.0, 0.0,
|
|
0.0, 1.0, 0.0, 0.0,
|
|
0.0, 0.0, 0.0, 1.0);
|
|
return mat;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix::convert_mat
|
|
// Access: Public, Static
|
|
// Description: Returns a matrix that transforms from the indicated
|
|
// coordinate system to the indicated coordinate system.
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
LMatrix4<NumType> LMatrix4<NumType>::
|
|
convert_mat(CoordinateSystem from, CoordinateSystem to) {
|
|
if (from == CS_default) {
|
|
from = default_coordinate_system;
|
|
}
|
|
if (to == CS_default) {
|
|
to = default_coordinate_system;
|
|
}
|
|
switch (from) {
|
|
case CS_zup_left:
|
|
switch (to) {
|
|
case CS_zup_left: return ident_mat();
|
|
case CS_yup_left: return z_to_y_up_mat();
|
|
case CS_zup_right: return scale_mat(1.0, -1.0, 1.0);
|
|
case CS_yup_right: return scale_mat(1.0, -1.0, 1.0) * z_to_y_up_mat();
|
|
default: break;
|
|
}
|
|
break;
|
|
|
|
case CS_yup_left:
|
|
switch (to) {
|
|
case CS_zup_left: return y_to_z_up_mat();
|
|
case CS_yup_left: return ident_mat();
|
|
case CS_zup_right: return scale_mat(1.0, 1.0, -1.0) * y_to_z_up_mat();
|
|
case CS_yup_right: return scale_mat(1.0, 1.0, -1.0);
|
|
default: break;
|
|
}
|
|
break;
|
|
|
|
case CS_zup_right:
|
|
switch (to) {
|
|
case CS_zup_left: return scale_mat(1.0, -1.0, 1.0);
|
|
case CS_yup_left: return scale_mat(1.0, -1.0, 1.0) * z_to_y_up_mat();
|
|
case CS_zup_right: return ident_mat();
|
|
case CS_yup_right: return z_to_y_up_mat();
|
|
default: break;
|
|
}
|
|
break;
|
|
|
|
case CS_yup_right:
|
|
switch (to) {
|
|
case CS_zup_left: return scale_mat(1.0, 1.0, -1.0) * y_to_z_up_mat();
|
|
case CS_yup_left: return scale_mat(1.0, 1.0, -1.0);
|
|
case CS_zup_right: return y_to_z_up_mat();
|
|
case CS_yup_right: return ident_mat();
|
|
default: break;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
linmath_cat.error()
|
|
<< "Invalid coordinate system value!\n";
|
|
return ident_mat();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix4::almost_equal
|
|
// Access: Public
|
|
// Description: Returns true if two matrices are memberwise equal
|
|
// within a specified tolerance.
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
bool LMatrix4<NumType>::
|
|
almost_equal(const LMatrix4<NumType> &other, NumType threshold) const {
|
|
return (IS_THRESHOLD_EQUAL((*this)(0, 0), other(0, 0), threshold) &&
|
|
IS_THRESHOLD_EQUAL((*this)(0, 1), other(0, 1), threshold) &&
|
|
IS_THRESHOLD_EQUAL((*this)(0, 2), other(0, 2), threshold) &&
|
|
IS_THRESHOLD_EQUAL((*this)(0, 3), other(0, 3), threshold) &&
|
|
IS_THRESHOLD_EQUAL((*this)(1, 0), other(1, 0), threshold) &&
|
|
IS_THRESHOLD_EQUAL((*this)(1, 1), other(1, 1), threshold) &&
|
|
IS_THRESHOLD_EQUAL((*this)(1, 2), other(1, 2), threshold) &&
|
|
IS_THRESHOLD_EQUAL((*this)(1, 3), other(1, 3), threshold) &&
|
|
IS_THRESHOLD_EQUAL((*this)(2, 0), other(2, 0), threshold) &&
|
|
IS_THRESHOLD_EQUAL((*this)(2, 1), other(2, 1), threshold) &&
|
|
IS_THRESHOLD_EQUAL((*this)(2, 2), other(2, 2), threshold) &&
|
|
IS_THRESHOLD_EQUAL((*this)(2, 3), other(2, 3), threshold) &&
|
|
IS_THRESHOLD_EQUAL((*this)(3, 0), other(3, 0), threshold) &&
|
|
IS_THRESHOLD_EQUAL((*this)(3, 1), other(3, 1), threshold) &&
|
|
IS_THRESHOLD_EQUAL((*this)(3, 2), other(3, 2), threshold) &&
|
|
IS_THRESHOLD_EQUAL((*this)(3, 3), other(3, 3), threshold));
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix4::almost_equal
|
|
// Access: Public
|
|
// Description: Returns true if two matrices are memberwise equal
|
|
// within a default tolerance based on the numeric type.
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
INLINE bool LMatrix4<NumType>::
|
|
almost_equal(const LMatrix4<NumType> &other) const {
|
|
return almost_equal(other, NEARLY_ZERO(NumType));
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix4::output
|
|
// Access: Public
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
INLINE void LMatrix4<NumType>::
|
|
output(ostream &out) const {
|
|
out << "[ "
|
|
<< MAYBE_ZERO((*this)(0, 0)) << " "
|
|
<< MAYBE_ZERO((*this)(0, 1)) << " "
|
|
<< MAYBE_ZERO((*this)(0, 2)) << " "
|
|
<< MAYBE_ZERO((*this)(0, 3))
|
|
<< " ] [ "
|
|
<< MAYBE_ZERO((*this)(1, 0)) << " "
|
|
<< MAYBE_ZERO((*this)(1, 1)) << " "
|
|
<< MAYBE_ZERO((*this)(1, 2)) << " "
|
|
<< MAYBE_ZERO((*this)(1, 3))
|
|
<< " ] [ "
|
|
<< MAYBE_ZERO((*this)(2, 0)) << " "
|
|
<< MAYBE_ZERO((*this)(2, 1)) << " "
|
|
<< MAYBE_ZERO((*this)(2, 2)) << " "
|
|
<< MAYBE_ZERO((*this)(2, 3))
|
|
<< " ] [ "
|
|
<< MAYBE_ZERO((*this)(3, 0)) << " "
|
|
<< MAYBE_ZERO((*this)(3, 1)) << " "
|
|
<< MAYBE_ZERO((*this)(3, 2)) << " "
|
|
<< MAYBE_ZERO((*this)(3, 3))
|
|
<< " ]";
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix4::write
|
|
// Access: Public
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
INLINE void LMatrix4<NumType>::
|
|
write(ostream &out, int indent_level) const {
|
|
indent(out, indent_level)
|
|
<< MAYBE_ZERO((*this)(0, 0)) << " "
|
|
<< MAYBE_ZERO((*this)(0, 1)) << " "
|
|
<< MAYBE_ZERO((*this)(0, 2)) << " "
|
|
<< MAYBE_ZERO((*this)(0, 3))
|
|
<< "\n";
|
|
indent(out, indent_level)
|
|
<< MAYBE_ZERO((*this)(1, 0)) << " "
|
|
<< MAYBE_ZERO((*this)(1, 1)) << " "
|
|
<< MAYBE_ZERO((*this)(1, 2)) << " "
|
|
<< MAYBE_ZERO((*this)(1, 3))
|
|
<< "\n";
|
|
indent(out, indent_level)
|
|
<< MAYBE_ZERO((*this)(2, 0)) << " "
|
|
<< MAYBE_ZERO((*this)(2, 1)) << " "
|
|
<< MAYBE_ZERO((*this)(2, 2)) << " "
|
|
<< MAYBE_ZERO((*this)(2, 3))
|
|
<< "\n";
|
|
indent(out, indent_level)
|
|
<< MAYBE_ZERO((*this)(3, 0)) << " "
|
|
<< MAYBE_ZERO((*this)(3, 1)) << " "
|
|
<< MAYBE_ZERO((*this)(3, 2)) << " "
|
|
<< MAYBE_ZERO((*this)(3, 3))
|
|
<< "\n";
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix4::decompose_mat
|
|
// Access: Private
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
bool LMatrix4<NumType>::
|
|
decompose_mat(int index[4]) {
|
|
int i, j, k;
|
|
NumType vv[4];
|
|
for (i = 0; i < 4; i++) {
|
|
NumType big = 0.0;
|
|
for (j = 0; j < 4; j++) {
|
|
NumType temp = fabs((*this)(i,j));
|
|
if (temp > big) {
|
|
big = temp;
|
|
}
|
|
}
|
|
|
|
if (IS_NEARLY_ZERO(big)) {
|
|
return false;
|
|
}
|
|
vv[i] = 1.0 / big;
|
|
}
|
|
|
|
for (j = 0; j < 4; j++) {
|
|
for (i = 0; i < j; i++) {
|
|
NumType sum = (*this)(i,j);
|
|
for (k = 0; k < i; k++) {
|
|
sum -= (*this)(i,k) * (*this)(k,j);
|
|
}
|
|
(*this)(i,j) = sum;
|
|
}
|
|
|
|
NumType big = 0.0;
|
|
int imax = -1;
|
|
for (i = j; i < 4; i++) {
|
|
NumType sum = (*this)(i,j);
|
|
for (k = 0; k < j; k++) {
|
|
sum -= (*this)(i,k) * (*this)(k,j);
|
|
}
|
|
(*this)(i,j) = sum;
|
|
|
|
NumType dum = vv[i] * fabs(sum);
|
|
if (dum >= big) {
|
|
big = dum;
|
|
imax = i;
|
|
}
|
|
}
|
|
nassertr(imax >= 0, false);
|
|
if (j != imax) {
|
|
for (k = 0; k < 4; k++) {
|
|
NumType dum = (*this)(imax,k);
|
|
(*this)(imax,k) = (*this)(j,k);
|
|
(*this)(j,k) = dum;
|
|
}
|
|
vv[imax] = vv[j];
|
|
}
|
|
index[j] = imax;
|
|
|
|
if ((*this)(j,j) == 0.0) {
|
|
(*this)(j,j) = NEARLY_ZERO(NumType);
|
|
}
|
|
|
|
if (j != 4 - 1) {
|
|
NumType dum = 1.0 / (*this)(j,j);
|
|
for (i = j + 1; i < 4; i++) {
|
|
(*this)(i,j) *= dum;
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix4::back_sub_mat
|
|
// Access: Private
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
bool LMatrix4<NumType>::
|
|
back_sub_mat(int index[4], LMatrix4<NumType> &inv, int row) const {
|
|
int ii = -1;
|
|
int i, j;
|
|
for (i = 0; i < 4; i++) {
|
|
int ip = index[i];
|
|
NumType sum = inv(row, ip);
|
|
inv(row, ip) = inv(row, i);
|
|
if (ii >= 0) {
|
|
for (j = ii; j <= i - 1; j++) {
|
|
sum -= (*this)(i,j) * inv(row, j);
|
|
}
|
|
} else if (sum) {
|
|
ii = i;
|
|
}
|
|
|
|
inv(row, i) = sum;
|
|
}
|
|
|
|
for (i = 4 - 1; i >= 0; i--) {
|
|
NumType sum = inv(row, i);
|
|
for (j = i + 1; j < 4; j++) {
|
|
sum -= (*this)(i,j) * inv(row, j);
|
|
}
|
|
inv(row, i) = sum / (*this)(i,i);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix4::init_type
|
|
// Access: Public, Static
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
void LMatrix4<NumType>::
|
|
init_type() {
|
|
if (_type_handle == TypeHandle::none()) {
|
|
// Format a string to describe the type.
|
|
do_init_type(NumType);
|
|
string name =
|
|
"LMatrix4<" + get_type_handle(NumType).get_name() + ">";
|
|
register_type(_type_handle, name);
|
|
}
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix4::write_datagram
|
|
// Description: Writes the matrix to the datagram
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
void LMatrix4<NumType>::
|
|
write_datagram(Datagram &destination) const
|
|
{
|
|
for(int i = 0; i < 4; i++)
|
|
{
|
|
for(int j = 0; j < 4; j++)
|
|
{
|
|
destination.add_float32(get_cell(i,j));
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix4::read_datagram
|
|
// Description: Reads itself out of the datagram
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
void LMatrix4<NumType>::
|
|
read_datagram(DatagramIterator &scan)
|
|
{
|
|
for(int i = 0; i < 4; i++)
|
|
{
|
|
for(int j = 0; j < 4; j++)
|
|
{
|
|
set_cell(i, j, scan.get_float32());
|
|
}
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix4::transpose
|
|
// Description: Transposes the given matrix and returns it.
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
INLINE LMatrix4<NumType>
|
|
transpose(const LMatrix4<NumType> &a) {
|
|
LMatrix4<NumType> result;
|
|
result.transpose_from(a);
|
|
return result;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: LMatrix4::invert
|
|
// Description: Inverts the given matrix and returns it.
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType>
|
|
INLINE LMatrix4<NumType>
|
|
invert(const LMatrix4<NumType> &a) {
|
|
LMatrix4<NumType> result;
|
|
bool nonsingular = result.invert_from(a);
|
|
nassertr(nonsingular, LMatrix4<NumType>::ident_mat());
|
|
return result;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: lcast_to
|
|
// Description: Converts a matrix from one numeric representation to
|
|
// another one. This is usually invoked using the macro
|
|
// LCAST.
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class NumType, class NumType2>
|
|
INLINE LMatrix4<NumType2>
|
|
lcast_to(NumType2 *, const LMatrix4<NumType> &source) {
|
|
return LMatrix4<NumType2>
|
|
(source(0, 0), source(0, 1), source(0, 2), source(0, 3),
|
|
source(1, 0), source(1, 1), source(1, 2), source(1, 3),
|
|
source(2, 0), source(2, 1), source(2, 2), source(2, 3),
|
|
source(3, 0), source(3, 1), source(3, 2), source(3, 3));
|
|
}
|