axmol/cocos/math/Mat3.cpp

1006 lines
22 KiB
C++
Raw Normal View History

2020-08-04 00:14:35 +08:00
#include "Mat3.h"
NS_CC_MATH_BEGIN
/**
* Constructor instantiates a new Mat3 object. The initial
* values for the matrix is that of the identity matrix.
* Ĭ<EFBFBD>Ϲ<EFBFBD><EFBFBD>λ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
*/
Mat3::Mat3() {
loadIdentity();
}
/**
* constructs a matrix with the given values.
*
* @param m[0]
* 0x0 in the matrix.
* @param m[1]
* 0x1 in the matrix.
* @param m[2]
* 0x2 in the matrix.
* @param m[3]
* 1x0 in the matrix.
* @param m[4]
* 1x1 in the matrix.
* @param m[5]
* 1x2 in the matrix.
* @param m[6]
* 2x0 in the matrix.
* @param m[7]
* 2x1 in the matrix.
* @param m[8]
* 2x2 in the matrix.
*/
Mat3::Mat3(float m[9]) {
this->m[0] = m[0];
this->m[1] = m[1];
this->m[2] = m[2];
this->m[3] = m[3];
this->m[4] = m[4];
this->m[5] = m[5];
this->m[6] = m[6];
this->m[8] = m[7];
this->m[9] = m[8];
}
/**
* get retrieves a value from the matrix at the given position.
* If the position is invalid a JmeException is thrown.
* <EFBFBD><EFBFBD>ȡָ<EFBFBD><EFBFBD>λ<EFBFBD>õ<EFBFBD>Ԫ<EFBFBD><EFBFBD>ֵ
*
* @param i
* the row index.<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡֵ<EFBFBD><EFBFBD>Χ<EFBFBD><EFBFBD>0<EFBFBD><EFBFBD>1<EFBFBD><EFBFBD>2<EFBFBD><EFBFBD>
* @param j
* the colum index.<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡֵ<EFBFBD><EFBFBD>Χ<EFBFBD><EFBFBD>0<EFBFBD><EFBFBD>1<EFBFBD><EFBFBD>2<EFBFBD><EFBFBD>
* @return the value at (i, j).
*/
float Mat3::get(int i, int j) {
switch (i) {
case 0:
switch (j) {
case 0:
return m[0];
case 1:
return m[1];
case 2:
return m[2];
}
case 1:
switch (j) {
case 0:
return m[3];
case 1:
return m[4];
case 2:
return m[5];
}
case 2:
switch (j) {
case 0:
return m[6];
case 1:
return m[7];
case 2:
return m[8];
}
}
return 0.0f;
// throw new JmeException("Invalid indices into matrix.");
}
/**
* getColumn returns one of three columns specified by the
* parameter. This column is returned as a cocos2d::Vec3 object.
* <EFBFBD><EFBFBD>ȡָ<EFBFBD><EFBFBD><EFBFBD>й<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* @param i
* the column to retrieve. Must be between 0 and 2.
* @param store
* the vector object to store the result in. if null, a new one
* is created.
* @return the column specified by the index.
*/
cocos2d::Vec3 Mat3::getColumn(int i) {
cocos2d::Vec3 store;
switch (i) {
case 0:
store.x = m[0];
store.y = m[3];
store.z = m[6];
break;
case 1:
store.x = m[1];
store.y = m[4];
store.z = m[7];
break;
case 2:
store.x = m[2];
store.y = m[5];
store.z = m[8];
break;
default:;
//logger.warning("Invalid column index.");
//throw new JmeException("Invalid column index. " + i);
}
return store;
}
/**
* getRow returns one of three rows as specified by the
* parameter. This row is returned as a cocos2d::Vec3 object.
* <EFBFBD><EFBFBD>ȡָ<EFBFBD><EFBFBD><EFBFBD>й<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* @param i
* the row to retrieve. Must be between 0 and 2.
* @param store
* the vector object to store the result in. if null, a new one
* is created.
* @return the row specified by the index.
*/
cocos2d::Vec3 Mat3::getRow(int i) {
cocos2d::Vec3 store;
switch (i) {
case 0:
store.x = m[0];
store.y = m[1];
store.z = m[2];
break;
case 1:
store.x = m[3];
store.y = m[4];
store.z = m[5];
break;
case 2:
store.x = m[6];
store.y = m[7];
store.z = m[8];
break;
default:;
// throw new JmeException("Invalid row index. " + i);
}
return store;
}
std::string Mat3::toString() {
return "";
}
/**
*
* setColumn sets a particular column of this matrix to that
* represented by the provided vector.
* <EFBFBD><EFBFBD><EFBFBD>ݸ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>þ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* @param i
* the column to set.
* @param column
* the data to set.
*/
void Mat3::setColumn(int i, const cocos2d::Vec3& column) {
switch (i) {
case 0:
m[0] = column.x;
m[3] = column.y;
m[6] = column.z;
break;
case 1:
m[1] = column.x;
m[4] = column.y;
m[7] = column.z;
break;
case 2:
m[2] = column.x;
m[5] = column.y;
m[8] = column.z;
break;
default:;
//logger.warning("Invalid column index.");
//throw new JmeException("Invalid column index. " + i);
}
}
/**
*
* setRow sets a particular row of this matrix to that
* represented by the provided vector.
* <EFBFBD><EFBFBD><EFBFBD>ݸ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>þ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* @param i
* the row to set.
* @param row
* the data to set.
*/
void Mat3::setRow(int i, const cocos2d::Vec3& row) {
switch (i) {
case 0:
m[0] = row.x;
m[1] = row.y;
m[2] = row.z;
break;
case 1:
m[3] = row.x;
m[4] = row.y;
m[5] = row.z;
break;
case 2:
m[6] = row.x;
m[7] = row.y;
m[8] = row.z;
break;
default:;
// logger.warning("Invalid row index.");
// throw new JmeException("Invalid row index. " + i);
}
}
/**
* set places a given value into the matrix at the given
* position. If the position is invalid a JmeException is
* thrown.
* <EFBFBD>ijλ<EFBFBD>õ<EFBFBD>ֵ
*
* @param i
* the row index.
* @param j
* the colum index.
* @param value
* the value for (i, j).
*/
void Mat3::set(int i, int j, float value) {
switch (i) {
case 0:
switch (j) {
case 0:
m[0] = value;
return;
case 1:
m[1] = value;
return;
case 2:
m[2] = value;
return;
}
case 1:
switch (j) {
case 0:
m[3] = value;
return;
case 1:
m[4] = value;
return;
case 2:
m[5] = value;
return;
}
case 2:
switch (j) {
case 0:
m[6] = value;
return;
case 1:
m[7] = value;
return;
case 2:
m[8] = value;
return;
}
}
//logger.warning("Invalid matrix index.");
//throw new JmeException("Invalid indices into matrix.");
}
/**
*
* set sets the values of the matrix to those supplied by the
* 3x3 two dimenion array.
* <EFBFBD>ö<EFBFBD>ά<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>þ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD><EFBFBD>ֵ
*
* @param matrix
* the new values of the matrix.
* @throws JmeException
* if the array is not of size 9.
*/
void Mat3::set(float matrix[3][3]) {
//if (matrix.length != 3 || matrix[0].length != 3) {
// throw new JmeException("Array must be of size 9.");
//}
m[0] = matrix[0][0];
m[1] = matrix[0][1];
m[2] = matrix[0][2];
m[3] = matrix[1][0];
m[4] = matrix[1][1];
m[5] = matrix[1][2];
m[6] = matrix[2][0];
m[7] = matrix[2][1];
m[8] = matrix[2][2];
}
/**
* Recreate Matrix using the provided axis.
* <EFBFBD><EFBFBD><EFBFBD>ݸ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* @param uAxis
* cocos2d::Vec3
* @param vAxis
* cocos2d::Vec3
* @param wAxis
* cocos2d::Vec3
*/
void Mat3::set(const cocos2d::Vec3& uAxis, const cocos2d::Vec3& vAxis, const cocos2d::Vec3& wAxis) {
m[0] = uAxis.x;
m[3] = uAxis.y;
m[6] = uAxis.z;
m[1] = vAxis.x;
m[4] = vAxis.y;
m[7] = vAxis.z;
m[2] = wAxis.x;
m[5] = wAxis.y;
m[8] = wAxis.z;
}
/**
* set sets the values of this matrix from an array of values;
* <EFBFBD><EFBFBD><EFBFBD>ݸ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>л<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>þ<EFBFBD><EFBFBD><EFBFBD>
*
* @param matrix
* the matrix to set the value to.
* @param rowMajor
* whether the incoming data is in row or column major order.
*/
void Mat3::set(float matrix[9], bool rowMajor) {
//if (matrix.length != 9)
// throw new JmeException("Array must be of size 9.");
if (rowMajor) {
m[0] = matrix[0];
m[1] = matrix[1];
m[2] = matrix[2];
m[3] = matrix[3];
m[4] = matrix[4];
m[5] = matrix[5];
m[6] = matrix[6];
m[7] = matrix[7];
m[8] = matrix[8];
}
else {
m[0] = matrix[0];
m[1] = matrix[3];
m[2] = matrix[6];
m[3] = matrix[1];
m[4] = matrix[4];
m[5] = matrix[7];
m[6] = matrix[2];
m[7] = matrix[5];
m[8] = matrix[8];
}
}
/**
* fromAngleNormalAxis sets this matrix4f to the values
* specified by an angle and a normalized axis of rotation.
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD>axis<EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>תangle<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȣ<EFBFBD><EFBFBD>ǵ<EFBFBD>3D<EFBFBD><EFBFBD>ת<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* @param angle
* the angle to rotate (in radians).
* @param axis
* the axis of rotation (already normalized).
*/
/**
* Creates a matrix describing a rotation around the z-axis.
*
* @param angle The angle of rotation (in radians).
* @param dst A matrix to store the result in.
*/
/**
* Creates a matrix describing a rotation around the y-axis.
*
* @param angle The angle of rotation (in radians).
* @param dst A matrix to store the result in.
*/
/**
* Creates a matrix describing a rotation around the x-axis.
*
* @param angle The angle of rotation (in radians).
* @param dst A matrix to store the result in.
*/
/**
* Creates a matrix describing a rotation around the z-axis.
*
* @param angle The angle of rotation (in radians).
* @param dst A matrix to store the result in.
*/
/**
* Creates a matrix describing a rotation around the y-axis.
*
* @param angle The angle of rotation (in radians).
* @param dst A matrix to store the result in.
*/
/**
* Creates a matrix describing a rotation around the x-axis.
*
* @param angle The angle of rotation (in radians).
* @param dst A matrix to store the result in.
*/
/**
* <EFBFBD>Ƿ<EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* @return true if this matrix is identity
*/
/**
* loadIdentity sets this matrix to the identity matrix. Where
* all values are zero except those along the diagonal which are one.
* <EFBFBD><EFBFBD>λ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
*/
void Mat3::loadIdentity() {
m[1] = m[2] = m[3] = m[5] = m[6] = m[7] = 0;
m[0] = m[4] = m[8] = 1;
}
bool Mat3::isIdentity() {
return (m[0] == 1 && m[1] == 0 && m[2] == 0)
&& (m[3] == 0 && m[4] == 1 && m[5] == 0)
&& (m[6] == 0 && m[7] == 0 && m[8] == 1);
}
void Mat3::rotateX(float angle)
{
rotateX(std::sin(angle), std::cos(angle));
}
void Mat3::rotateY(float angle)
{
rotateY(std::sin(angle), std::cos(angle));
}
void Mat3::rotateZ(float angle)
{
rotateZ(std::sin(angle), std::cos(angle));
}
void Mat3::rotateX(float s, float c)
{
Mat3 temp;
temp.createRotationX(s, c);
mult(temp);
}
void Mat3::rotateY(float s, float c)
{
Mat3 temp;
temp.createRotationY(s, c);
mult(temp);
}
void Mat3::rotateZ(float s, float c)
{
Mat3 temp;
temp.createRotationZ(s, c);
mult(temp);
}
void Mat3::createRotation(const cocos2d::Vec3& axis, float fSin, float fCos) {
float x = axis.x;
float y = axis.y;
float z = axis.z;
// Make sure the input axis is normalized.
float n = x * x + y * y + z * z;
if (n != 1.0f)
{
// Not normalized.
n = sqrt(n);
// Prevent divide too close to zero.
if (n > 0.000001f)
{
n = 1.0f / n;
x *= n;
y *= n;
z *= n;
}
}
float fOneMinusCos = ((float)1.0) - fCos;
float fX2 = x * x;
float fY2 = y * y;
float fZ2 = z * z;
float fXYM = x * y * fOneMinusCos;
float fXZM = x * z * fOneMinusCos;
float fYZM = y * z * fOneMinusCos;
float fXSin = x * fSin;
float fYSin = y * fSin;
float fZSin = z * fSin;
m[0] = fX2 * fOneMinusCos + fCos;
m[1] = fXYM - fZSin;
m[2] = fXZM + fYSin;
m[3] = fXYM + fZSin;
m[4] = fY2 * fOneMinusCos + fCos;
m[5] = fYZM - fXSin;
m[6] = fXZM - fYSin;
m[7] = fYZM + fXSin;
m[8] = fZ2 * fOneMinusCos + fCos;
}
/**
* Creates a matrix describing a rotation around the x-axis.
*
* @param angle The angle of rotation (in radians).
* @param dst A matrix to store the result in.
*/
void Mat3::createRotationX(float s, float c)
{
m[4] = c;
m[5] = s;
m[7] = -s;
m[8] = c;
}
/**
* Creates a matrix describing a rotation around the y-axis.
*
* @param angle The angle of rotation (in radians).
* @param dst A matrix to store the result in.
*/
void Mat3::createRotationY(float s, float c)
{
m[0] = c;
m[2] = -s;
m[6] = s;
m[8] = c;
}
/**
* Creates a matrix describing a rotation around the z-axis.
*
* @param angle The angle of rotation (in radians).
* @param dst A matrix to store the result in.
*/
void Mat3::createRotationZ(float s, float c)
{
m[0] = c;
m[1] = s;
m[3] = -s;
m[4] = c;
}
Mat3& Mat3::mult(const Mat3& mat, Mat3& product) const
{
float temp00, temp01, temp02;
float temp10, temp11, temp12;
float temp20, temp21, temp22;
temp00 = m[0] * mat.m[0] + m[1] * mat.m[3] + m[2] * mat.m[6];
temp01 = m[0] * mat.m[1] + m[1] * mat.m[4] + m[2] * mat.m[7];
temp02 = m[0] * mat.m[2] + m[1] * mat.m[5] + m[2] * mat.m[8];
temp10 = m[3] * mat.m[0] + m[4] * mat.m[3] + m[5] * mat.m[6];
temp11 = m[3] * mat.m[1] + m[4] * mat.m[4] + m[5] * mat.m[7];
temp12 = m[3] * mat.m[2] + m[4] * mat.m[5] + m[5] * mat.m[8];
temp20 = m[6] * mat.m[0] + m[7] * mat.m[3] + m[8] * mat.m[6];
temp21 = m[6] * mat.m[1] + m[7] * mat.m[4] + m[8] * mat.m[7];
temp22 = m[6] * mat.m[2] + m[7] * mat.m[5] + m[8] * mat.m[8];
product.m[0] = temp00;
product.m[1] = temp01;
product.m[2] = temp02;
product.m[3] = temp10;
product.m[4] = temp11;
product.m[5] = temp12;
product.m[6] = temp20;
product.m[7] = temp21;
product.m[8] = temp22;
return product;
}
/**
* Multiplies this 3x3 matrix by the 1x3 Vector vec and stores the result in
* product.
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>product<EFBFBD><EFBFBD>
*
* @param vec
* The cocos2d::Vec3 to multiply.
* @return The given product vector.
*/
cocos2d::Vec3 Mat3::mult(const cocos2d::Vec3& vec) const {
cocos2d::Vec3 product;
float x = vec.x;
float y = vec.y;
float z = vec.z;
product.x = m[0] * x + m[1] * y + m[2] * z;
product.y = m[3] * x + m[4] * y + m[5] * z;
product.z = m[6] * x + m[7] * y + m[8] * z;
return product;
}
/**
* multLocal multiplies this matrix internally by a given float
* scale factor.
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* @param scale
* the value to scale by.
* @return this Mat3
*/
Mat3& Mat3::multLocal(float scale) {
m[0] *= scale;
m[1] *= scale;
m[2] *= scale;
m[3] *= scale;
m[4] *= scale;
m[5] *= scale;
m[6] *= scale;
m[7] *= scale;
m[8] *= scale;
return *this;
}
/**
* add adds the values of a parameter matrix to this matrix.
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӷ<EFBFBD>
*
* @param mat
* the matrix to add to this.
*/
Mat3& Mat3::addLocal(const Mat3& mat) {
m[0] += mat.m[0];
m[1] += mat.m[1];
m[2] += mat.m[2];
m[3] += mat.m[3];
m[4] += mat.m[4];
m[5] += mat.m[5];
m[6] += mat.m[6];
m[7] += mat.m[7];
m[8] += mat.m[8];
return *this;
}
/**
* Transposes this matrix in place. Returns this matrix for chaining
* ת<EFBFBD>þ<EFBFBD><EFBFBD><EFBFBD>
*
* @return This matrix after transpose
*/
Mat3& Mat3::transposeLocal() {
float tmp[9];
get(tmp, false);
set(tmp, true);
return *this;
}
/**
* Inverts this matrix and stores it in the given store.
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>󣬱<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڲ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ı<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* @return The store
*/
Mat3 Mat3::invertNew(void) {
Mat3 store;
float det = determinant();
if (std::abs(det) <= 0)
return store.zero();
store.m[0] = m[4] * m[8] - m[5] * m[7];
store.m[1] = m[2] * m[7] - m[1] * m[8];
store.m[2] = m[1] * m[5] - m[2] * m[4];
store.m[3] = m[5] * m[6] - m[3] * m[8];
store.m[4] = m[0] * m[8] - m[2] * m[6];
store.m[5] = m[2] * m[3] - m[0] * m[5];
store.m[6] = m[3] * m[7] - m[4] * m[6];
store.m[7] = m[1] * m[6] - m[0] * m[7];
store.m[8] = m[0] * m[4] - m[1] * m[3];
store.multLocal(1 / det);
return store;
}
/**
* Inverts this matrix locally.
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>󣬸ı<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* @return this
*/
Mat3& Mat3::invertLocal() {
float det = determinant();
if (std::abs(det) <= FLT_EPSILON)
return zero();
float f00 = m[4] * m[8] - m[5] * m[7];
float f01 = m[2] * m[7] - m[1] * m[8];
float f02 = m[1] * m[5] - m[2] * m[4];
float f10 = m[5] * m[6] - m[3] * m[8];
float f11 = m[0] * m[8] - m[2] * m[6];
float f12 = m[2] * m[3] - m[0] * m[5];
float f20 = m[3] * m[7] - m[4] * m[6];
float f21 = m[1] * m[6] - m[0] * m[7];
float f22 = m[0] * m[4] - m[1] * m[3];
m[0] = f00;
m[1] = f01;
m[2] = f02;
m[3] = f10;
m[4] = f11;
m[5] = f12;
m[6] = f20;
m[7] = f21;
m[8] = f22;
multLocal(1 / det);
return *this;
}
/**
* Places the adjoint of this matrix in store (creates store if null.)
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* @param store
* The matrix to store the result in. If null, a new matrix is
* created.
* @return store
*/
Mat3 Mat3::adjoint() {
Mat3 store;
store.m[0] = m[4] * m[8] - m[5] * m[7];
store.m[1] = m[2] * m[7] - m[1] * m[8];
store.m[2] = m[1] * m[5] - m[2] * m[4];
store.m[3] = m[5] * m[6] - m[3] * m[8];
store.m[4] = m[0] * m[8] - m[2] * m[6];
store.m[5] = m[2] * m[3] - m[0] * m[5];
store.m[6] = m[3] * m[7] - m[4] * m[6];
store.m[7] = m[1] * m[6] - m[0] * m[7];
store.m[8] = m[0] * m[4] - m[1] * m[3];
return store;
}
/**
* determinant generates the determinate of this matrix.
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ
*
* @return the determinate
*/
float Mat3::determinant() {
float fCo00 = m[4] * m[8] - m[5] * m[7];
float fCo10 = m[5] * m[6] - m[3] * m[8];
float fCo20 = m[3] * m[7] - m[4] * m[6];
float fDet = m[0] * fCo00 + m[1] * fCo10 + m[2] * fCo20;
return fDet;
}
/**
* Sets all of the values in this matrix to zero.
* <EFBFBD><EFBFBD><EFBFBD>þ<EFBFBD><EFBFBD>󣬸<EFBFBD>Ԫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ0
*
* @return this matrix
*/
Mat3& Mat3::zero() {
m[0] = m[1] = m[2] = m[3] = m[4] = m[5] = m[6] = m[7] = m[8] = 0.0f;
return *this;
}
/**
* transposeNew returns a transposed version of this matrix.
* ת<EFBFBD>þ<EFBFBD><EFBFBD><EFBFBD>
*
* @return The new Mat3 object.
*/
Mat3 Mat3::transposeNew() {
float temp[9] = { m[0], m[3], m[6], m[1], m[4], m[7], m[2], m[5], m[8] };
return Mat3(temp);
}
/**
* are these two matrices the same? they are is they both have the same mXX
* values.
*
* @param o
* the object to compare for equality
* @return true if they are equal
*/
bool Mat3::equals(const Mat3& o) const {
return memcmp(&o, this, sizeof(o)) == 0;
}
/**
* A function for creating a rotation matrix that rotates a vector called
* "start" into another vector called "end".
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ת<EFBFBD><EFBFBD><EFBFBD>󣬴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>start<EFBFBD><EFBFBD>ת<EFBFBD><EFBFBD>end
*
* @param start
* normalized non-zero starting vector
* @param end
* normalized non-zero ending vector
* @see "Tomas M?ller, John Hughes /"Efficiently Building a Matrix to Rotate
* / One Vector to Another/" Journal of Graphics Tools, 4(4):1-4, 1999"
*/
void Mat3::fromStartEndVectors(cocos2d::Vec3 start, cocos2d::Vec3 end) {
cocos2d::Vec3 v;
float e, h, f;
cocos2d::Vec3::cross(start, end, &v);
e = start.dot(end);
f = (e < 0) ? -e : e;
// if "from" and "to" vectors are nearly parallel
if (f > 1.0f - FLT_EPSILON) {
cocos2d::Vec3 u;
cocos2d::Vec3 x;
float c1, c2, c3; /* coefficients for later use */
int i, j;
x.x = (start.x > 0.0) ? start.x : -start.x;
x.y = (start.y > 0.0) ? start.y : -start.y;
x.z = (start.z > 0.0) ? start.z : -start.z;
if (x.x < x.y) {
if (x.x < x.z) {
x.x = 1.0f;
x.y = x.z = 0.0f;
}
else {
x.z = 1.0f;
x.x = x.y = 0.0f;
}
}
else {
if (x.y < x.z) {
x.y = 1.0f;
x.x = x.z = 0.0f;
}
else {
x.z = 1.0f;
x.x = x.y = 0.0f;
}
}
u.x = x.x - start.x;
u.y = x.y - start.y;
u.z = x.z - start.z;
v.x = x.x - end.x;
v.y = x.y - end.y;
v.z = x.z - end.z;
c1 = 2.0f / u.dot(u);
c2 = 2.0f / v.dot(v);
c3 = c1 * c2 * u.dot(v);
for (i = 0; i < 3; i++) {
for (j = 0; j < 3; j++) {
float val = -c1 * (&u.x)[i] * (&u.x)[j] - c2 * (&v.x)[i]
* (&v.x)[j] + c3 * (&v.x)[i] * (&u.x)[j];
set(i, j, val);
}
float val = get(i, i);
set(i, i, val + 1.0f);
}
}
else {
// the most common case, unless "start"="end", or "start"=-"end"
float hvx, hvz, hvxy, hvxz, hvyz;
h = 1.0f / (1.0f + e);
hvx = h * v.x;
hvz = h * v.z;
hvxy = hvx * v.y;
hvxz = hvx * v.z;
hvyz = hvz * v.y;
set(0, 0, e + hvx * v.x);
set(0, 1, hvxy - v.z);
set(0, 2, hvxz + v.y);
set(1, 0, hvxy + v.z);
set(1, 1, e + h * v.y * v.y);
set(1, 2, hvyz - v.x);
set(2, 0, hvxz - v.y);
set(2, 1, hvyz + v.x);
set(2, 2, e + hvz * v.z);
}
}
/**
* scale scales the operation performed by this matrix on a
* per-component basis.
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>зֱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* @param scale
* The scale applied to each of the X, Y and Z output values.
*/
void Mat3::scale(const cocos2d::Vec3& scale) {
m[0] *= scale.x;
m[3] *= scale.x;
m[6] *= scale.x;
m[1] *= scale.y;
m[4] *= scale.y;
m[7] *= scale.y;
m[2] *= scale.z;
m[5] *= scale.z;
m[8] *= scale.z;
}
bool Mat3::equalIdentity(const Mat3& mat) {
if (std::abs(mat.m[0] - 1) > 1e-4)
return false;
if (std::abs(mat.m[4] - 1) > 1e-4)
return false;
if (std::abs(mat.m[8] - 1) > 1e-4)
return false;
if (std::abs(mat.m[1]) > 1e-4)
return false;
if (std::abs(mat.m[2]) > 1e-4)
return false;
if (std::abs(mat.m[3]) > 1e-4)
return false;
if (std::abs(mat.m[5]) > 1e-4)
return false;
if (std::abs(mat.m[6]) > 1e-4)
return false;
if (std::abs(mat.m[7]) > 1e-4)
return false;
return true;
}
NS_CC_MATH_END