axmol/cocos/editor-support/cocostudio/ext/matrix3f.hpp

1167 lines
32 KiB
C++
Raw Normal View History

2019-11-24 23:15:56 +08:00
/**
* Matrix3f defines a 3x3 matrix. Matrix data is maintained
* internally and is accessible via the get and set methods. Convenience methods
* are used for matrix operations as well as generating a matrix from a given
* set of values.
* 3X3<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @autohr HALX99 2016
* @author Mark Powell
* @author Joshua Slack
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#ifndef _MATRIX3F_H_
#define _MATRIX3F_H_
#include <cocos2d.h>
class Matrix3f {
public:
float m[9];
/**
* Constructor instantiates a new Matrix3f object. The initial
* values for the matrix is that of the identity matrix.
* Ĭ<EFBFBD>Ϲ<EFBFBD><EFBFBD>λ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
*/
Matrix3f() {
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.
*/
Matrix3f(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 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];
}
}
// throw new JmeException("Invalid indices into matrix.");
}
/**
* get(float[]) returns the matrix in row-major or column-major
* order.
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>л<EFBFBD><EFBFBD>е<EFBFBD>˳<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>data<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* @param data
* The array to return the data into. This array can be 9 or 16
* floats in size. Only the upper 3x3 are assigned to in the case
* of a 16 element array.
* @param rowMajor
* True for row major storage in the array (translation in
* elements 3, 7, 11 for a 4x4), false for column major
* (translation in elements 12, 13, 14 for a 4x4).
*/
template<size_t _Length>
void get(float(&data)[_Length], bool rowMajor) {
if (_Length == 9) {
if (rowMajor) {
data[0] = m[0];
data[1] = m[1];
data[2] = m[2];
data[3] = m[3];
data[4] = m[4];
data[5] = m[5];
data[6] = m[6];
data[7] = m[7];
data[8] = m[8];
}
else {
data[0] = m[0];
data[1] = m[3];
data[2] = m[6];
data[3] = m[1];
data[4] = m[4];
data[5] = m[7];
data[6] = m[2];
data[7] = m[5];
data[8] = m[8];
}
}
else if (_Length == 16) {
if (rowMajor) {
data[0] = m[0];
data[1] = m[1];
data[2] = m[2];
data[4] = m[3];
data[5] = m[4];
data[6] = m[5];
data[8] = m[6];
data[9] = m[7];
data[10] = m[8];
}
else {
data[0] = m[0];
data[1] = m[3];
data[2] = m[6];
data[4] = m[1];
data[5] = m[4];
data[6] = m[7];
data[8] = m[2];
data[9] = m[5];
data[10] = m[8];
}
}
else {
// throw new JmeException("Array size must be 9 or 16 in Matrix3f.get().");
}
}
/**
* 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 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 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 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 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 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 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 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 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
* assuming that the data is rowMajor order;
* <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.
*/
void set(float matrix[9]) {
set(matrix, true);
}
/**
* 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 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];
}
}
/**
*
* set defines the values of the matrix based on a supplied
* Quaternion. It should be noted that all previous values will
* be overridden.
* <EFBFBD><EFBFBD>Ԫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ת<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* @param quaternion
* the quaternion to create a rotational matrix from.
*/
void set(const cocos2d::Quaternion& quaternion) {
//quaternion.toRotationMatrix(this);
}
/**
* 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 loadIdentity() {
m[1] = m[2] = m[3] = m[5] = m[6] = m[7] = 0;
m[0] = m[4] = m[8] = 1;
}
/**
* <EFBFBD>Ƿ<EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* @return true if this matrix is identity
*/
bool 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);
}
/**
* 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 rotateX(float angle)
{
rotateX(std::sin(angle), std::cos(angle));
}
/**
* 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 rotateY(float angle)
{
rotateY(std::sin(angle), std::cos(angle));
}
/**
* 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 rotateZ(float angle)
{
rotateZ(std::sin(angle), std::cos(angle));
}
/**
* 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 rotateX(float s, float c)
{
Matrix3f temp;
temp.createRotationX(s, c);
mult(temp);
}
/**
* 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 rotateY(float s, float c)
{
Matrix3f temp;
temp.createRotationY(s, c);
mult(temp);
}
/**
* 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 rotateZ(float s, float c)
{
Matrix3f temp;
temp.createRotationZ(s, c);
mult(temp);
}
/**
* fromAngleAxis sets this matrix4f to the values specified by
* an angle and an axis of rotation. This method creates an object, so use
* fromAngleNormalAxis if your axis is already normalized.
* <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.
*/
void createRotation(const cocos2d::Vec3& axis, float angle) {
createRotation(axis, std::sin(angle), std::cos(angle));
}
/**
* 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).
*/
void 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 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 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 createRotationZ(float s, float c)
{
m[0] = c;
m[1] = s;
m[3] = -s;
m[4] = c;
}
/**
* Creates a scale matrix.
*
* @param scale The amount to scale.
* @param dst A matrix to store the result in.
*/
void createScale(const cocos2d::Vec3& scale);
/**
* Creates a scale matrix.
*
* @param xScale The amount to scale along the x-axis.
* @param yScale The amount to scale along the y-axis.
* @param zScale The amount to scale along the z-axis.
* @param dst A matrix to store the result in.
*/
void createScale(float xScale, float yScale, float zScale);
/**
* Creates a translation matrix.
*
* @param translation The translation.
* @param dst A matrix to store the result in.
*/
void createTranslation(const cocos2d::Vec3& translation);
/**
* Creates a translation matrix.
*
* @param xTranslation The translation on the x-axis.
* @param yTranslation The translation on the y-axis.
* @param zTranslation The translation on the z-axis.
* @param dst A matrix to store the result in.
*/
void createTranslation(float xTranslation, float yTranslation, float zTranslation);
/**
* mult multiplies this matrix by a given matrix. The result
* matrix is returned as a new object.
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˷<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>product<EFBFBD><EFBFBD>
*
* @param mat
* the matrix to multiply this matrix by.
* @param product
* the matrix to store the result in. if null, a new matrix3f is
* created. It is safe for mat and product to be the same object.
* @return a matrix3f object containing the result of this operation
*/
Matrix3f& mult(const Matrix3f& mat) {
return mult(mat, *this);
}
Matrix3f& mult(const Matrix3f& mat, Matrix3f& 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 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;
}
Matrix3f& premultAlpha(float alpha) {
return multLocal(alpha);
}
/**
* 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 Matrix3f
*/
Matrix3f& 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.
*/
Matrix3f& addLocal(const Matrix3f& 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];
}
/**
* mult multiplies this matrix by a given matrix. The result
* matrix is saved in the current matrix. If the given matrix is null,
* nothing happens. The current matrix is returned. This is equivalent to
* this*=mat
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ծ<EFBFBD><EFBFBD><EFBFBD>
*
* @param mat
* the matrix to multiply this matrix by.
* @return This matrix, after the multiplication
*/
/*void multLocal() {
return mult(mat, this);
}*/
/**
* Transposes this matrix in place. Returns this matrix for chaining
* ת<EFBFBD>þ<EFBFBD><EFBFBD><EFBFBD>
*
* @return This matrix after transpose
*/
Matrix3f& 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
*/
Matrix3f invertNew(void) {
Matrix3f 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
*/
Matrix3f& 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
*/
Matrix3f adjoint() {
Matrix3f 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 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
*/
Matrix3f& 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 Matrix3f object.
*/
Matrix3f transposeNew() {
float temp[9] = { m[0], m[3], m[6], m[1], m[4], m[7], m[2], m[5], m[8] };
return Matrix3f(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 equals(const Matrix3f& o) const {
return true;
}
/**
* 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 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 scale(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;
}
static bool equalIdentity(const Matrix3f& 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;
}
};
#endif