All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.lessvoid.math.Mat4 Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2002-2008 LWJGL Project
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * * Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * * Neither the name of 'LWJGL' nor the names of
 *   its contributors may be used to endorse or promote products derived
 *   from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package de.lessvoid.math;

import java.io.Serializable;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

/**
 * Holds a 4x4 float matrix.
 *
 * @author foo
 * @author void256 - removed all of the base class methods and some of the
 *         vector/transformation operations to make the class usable as a self
 *         contained class.
 */
public class Mat4 implements Serializable {
  private static final long serialVersionUID = 1L;
  private FloatBuffer matrixBuffer;

  public float m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33;

  /**
   * Construct a new matrix, initialized to the identity.
   */
  public Mat4() {
    setIdentity();
  }

  public Mat4(final Mat4 src) {
    load(src);
  }

  /**
   * Returns a string representation of this matrix
   */
  @Override
  public String toString() {
    final StringBuilder buf = new StringBuilder();
    buf.append(m00).append(' ').append(m10).append(' ').append(m20).append(' ').append(m30).append('\n');
    buf.append(m01).append(' ').append(m11).append(' ').append(m21).append(' ').append(m31).append('\n');
    buf.append(m02).append(' ').append(m12).append(' ').append(m22).append(' ').append(m32).append('\n');
    buf.append(m03).append(' ').append(m13).append(' ').append(m23).append(' ').append(m33).append('\n');
    return buf.toString();
  }

  /**
   * Store this Matrix to an internal FloatBuffer and return that buffer. Please
   * note that the same internal buffer will be used for each call.
   * 
   * @return FloatBuffer with the Matrix data
   */
  public FloatBuffer toBuffer() {
    if (matrixBuffer == null) {
      matrixBuffer = ByteBuffer.allocateDirect(64).order(ByteOrder.nativeOrder()).asFloatBuffer();
    }
    matrixBuffer.clear();
    store(matrixBuffer);
    matrixBuffer.rewind();
    return matrixBuffer;
  }

  /**
   * Set this matrix to be the identity matrix.
   * 
   * @return this
   */
  public Mat4 setIdentity() {
    return setIdentity(this);
  }

  /**
   * Set the given matrix to be the identity matrix.
   * 
   * @param m
   *          The matrix to set to the identity
   * @return m
   */
  public static Mat4 setIdentity(final Mat4 m) {
    m.m00 = 1.0f;
    m.m01 = 0.0f;
    m.m02 = 0.0f;
    m.m03 = 0.0f;
    m.m10 = 0.0f;
    m.m11 = 1.0f;
    m.m12 = 0.0f;
    m.m13 = 0.0f;
    m.m20 = 0.0f;
    m.m21 = 0.0f;
    m.m22 = 1.0f;
    m.m23 = 0.0f;
    m.m30 = 0.0f;
    m.m31 = 0.0f;
    m.m32 = 0.0f;
    m.m33 = 1.0f;

    return m;
  }

  /**
   * Set this matrix to 0.
   * 
   * @return this
   */
  public Mat4 setZero() {
    return setZero(this);
  }

  /**
   * Set the given matrix to 0.
   * 
   * @param m
   *          The matrix to set to 0
   * @return m
   */
  public static Mat4 setZero(final Mat4 m) {
    m.m00 = 0.0f;
    m.m01 = 0.0f;
    m.m02 = 0.0f;
    m.m03 = 0.0f;
    m.m10 = 0.0f;
    m.m11 = 0.0f;
    m.m12 = 0.0f;
    m.m13 = 0.0f;
    m.m20 = 0.0f;
    m.m21 = 0.0f;
    m.m22 = 0.0f;
    m.m23 = 0.0f;
    m.m30 = 0.0f;
    m.m31 = 0.0f;
    m.m32 = 0.0f;
    m.m33 = 0.0f;

    return m;
  }

  public static Mat4 createTranslate(final float x, final float y, final float z) {
    final Mat4 result = new Mat4();
    result.m30 = x;
    result.m31 = y;
    result.m32 = z;
    return result;
  }

  public static Mat4 createScale(final float x, final float y, final float z) {
    final Mat4 result = new Mat4();
    result.m00 = x;
    result.m11 = y;
    result.m22 = z;
    return result;
  }

  public static Mat4 createRotate(final float angle, final float x, final float y, final float z) {
    final double angleRad = angle * Math.PI / 180.;
    final float c = (float) Math.cos(angleRad);
    final float s = (float) Math.sin(angleRad);

    final Mat4 result = new Mat4();
    result.m00 = x * x * (1 - c) + c;
    result.m10 = x * y * (1 - c) - z * s;
    result.m20 = x * z * (1 - c) + y * s;
    result.m30 = 0;

    result.m01 = y * x * (1 - c) + z * s;
    result.m11 = y * y * (1 - c) + c;
    result.m21 = y * z * (1 - c) - x * s;
    result.m31 = 0;

    result.m02 = x * z * (1 - c) - y * s;
    result.m12 = y * z * (1 - c) + x * s;
    result.m22 = z * z * (1 - c) + c;
    result.m32 = 0;

    result.m03 = 0;
    result.m13 = 0;
    result.m23 = 0;
    result.m33 = 1;
    return result;
  }

  /**
   * Load from another matrix4f
   * 
   * @param src
   *          The source matrix
   * @return this
   */
  public Mat4 load(final Mat4 src) {
    return load(src, this);
  }

  /**
   * Copy the source matrix to the destination matrix
   * 
   * @param src
   *          The source matrix
   * @param dest
   *          The destination matrix, or null of a new one is to be created
   * @return The copied matrix
   */
  public static Mat4 load(final Mat4 src, Mat4 dest) {
    if (dest == null) dest = new Mat4();
    dest.m00 = src.m00;
    dest.m01 = src.m01;
    dest.m02 = src.m02;
    dest.m03 = src.m03;
    dest.m10 = src.m10;
    dest.m11 = src.m11;
    dest.m12 = src.m12;
    dest.m13 = src.m13;
    dest.m20 = src.m20;
    dest.m21 = src.m21;
    dest.m22 = src.m22;
    dest.m23 = src.m23;
    dest.m30 = src.m30;
    dest.m31 = src.m31;
    dest.m32 = src.m32;
    dest.m33 = src.m33;

    return dest;
  }

  /**
   * Load from a float buffer. The buffer stores the matrix in column major
   * (OpenGL) order.
   *
   * @param buf
   *          A float buffer to read from
   * @return this
   */
  public Mat4 load(final FloatBuffer buf) {

    m00 = buf.get();
    m01 = buf.get();
    m02 = buf.get();
    m03 = buf.get();
    m10 = buf.get();
    m11 = buf.get();
    m12 = buf.get();
    m13 = buf.get();
    m20 = buf.get();
    m21 = buf.get();
    m22 = buf.get();
    m23 = buf.get();
    m30 = buf.get();
    m31 = buf.get();
    m32 = buf.get();
    m33 = buf.get();

    return this;
  }

  /**
   * Load from a float buffer. The buffer stores the matrix in row major (maths)
   * order.
   *
   * @param buf
   *          A float buffer to read from
   * @return this
   */
  public Mat4 loadTranspose(final FloatBuffer buf) {

    m00 = buf.get();
    m10 = buf.get();
    m20 = buf.get();
    m30 = buf.get();
    m01 = buf.get();
    m11 = buf.get();
    m21 = buf.get();
    m31 = buf.get();
    m02 = buf.get();
    m12 = buf.get();
    m22 = buf.get();
    m32 = buf.get();
    m03 = buf.get();
    m13 = buf.get();
    m23 = buf.get();
    m33 = buf.get();

    return this;
  }

  /**
   * Store this matrix in a float buffer. The matrix is stored in column major
   * (openGL) order.
   * 
   * @param buf
   *          The buffer to store this matrix in
   */
  public Mat4 store(final FloatBuffer buf) {
    buf.put(m00);
    buf.put(m01);
    buf.put(m02);
    buf.put(m03);
    buf.put(m10);
    buf.put(m11);
    buf.put(m12);
    buf.put(m13);
    buf.put(m20);
    buf.put(m21);
    buf.put(m22);
    buf.put(m23);
    buf.put(m30);
    buf.put(m31);
    buf.put(m32);
    buf.put(m33);
    return this;
  }

  /**
   * Store this matrix in a float buffer. The matrix is stored in row major
   * (maths) order.
   * 
   * @param buf
   *          The buffer to store this matrix in
   */
  public Mat4 storeTranspose(final FloatBuffer buf) {
    buf.put(m00);
    buf.put(m10);
    buf.put(m20);
    buf.put(m30);
    buf.put(m01);
    buf.put(m11);
    buf.put(m21);
    buf.put(m31);
    buf.put(m02);
    buf.put(m12);
    buf.put(m22);
    buf.put(m32);
    buf.put(m03);
    buf.put(m13);
    buf.put(m23);
    buf.put(m33);
    return this;
  }

  /**
   * Store the rotation portion of this matrix in a float buffer. The matrix is
   * stored in column major (openGL) order.
   * 
   * @param buf
   *          The buffer to store this matrix in
   */
  public Mat4 store3f(final FloatBuffer buf) {
    buf.put(m00);
    buf.put(m01);
    buf.put(m02);
    buf.put(m10);
    buf.put(m11);
    buf.put(m12);
    buf.put(m20);
    buf.put(m21);
    buf.put(m22);
    return this;
  }

  /**
   * Add two matrices together and place the result in a third matrix.
   * 
   * @param left
   *          The left source matrix
   * @param right
   *          The right source matrix
   * @param dest
   *          The destination matrix, or null if a new one is to be created
   * @return the destination matrix
   */
  public static Mat4 add(final Mat4 left, final Mat4 right, Mat4 dest) {
    if (dest == null) dest = new Mat4();

    dest.m00 = left.m00 + right.m00;
    dest.m01 = left.m01 + right.m01;
    dest.m02 = left.m02 + right.m02;
    dest.m03 = left.m03 + right.m03;
    dest.m10 = left.m10 + right.m10;
    dest.m11 = left.m11 + right.m11;
    dest.m12 = left.m12 + right.m12;
    dest.m13 = left.m13 + right.m13;
    dest.m20 = left.m20 + right.m20;
    dest.m21 = left.m21 + right.m21;
    dest.m22 = left.m22 + right.m22;
    dest.m23 = left.m23 + right.m23;
    dest.m30 = left.m30 + right.m30;
    dest.m31 = left.m31 + right.m31;
    dest.m32 = left.m32 + right.m32;
    dest.m33 = left.m33 + right.m33;

    return dest;
  }

  /**
   * Subtract the right matrix from the left and place the result in a third
   * matrix.
   * 
   * @param left
   *          The left source matrix
   * @param right
   *          The right source matrix
   * @param dest
   *          The destination matrix, or null if a new one is to be created
   * @return the destination matrix
   */
  public static Mat4 sub(final Mat4 left, final Mat4 right, Mat4 dest) {
    if (dest == null) dest = new Mat4();

    dest.m00 = left.m00 - right.m00;
    dest.m01 = left.m01 - right.m01;
    dest.m02 = left.m02 - right.m02;
    dest.m03 = left.m03 - right.m03;
    dest.m10 = left.m10 - right.m10;
    dest.m11 = left.m11 - right.m11;
    dest.m12 = left.m12 - right.m12;
    dest.m13 = left.m13 - right.m13;
    dest.m20 = left.m20 - right.m20;
    dest.m21 = left.m21 - right.m21;
    dest.m22 = left.m22 - right.m22;
    dest.m23 = left.m23 - right.m23;
    dest.m30 = left.m30 - right.m30;
    dest.m31 = left.m31 - right.m31;
    dest.m32 = left.m32 - right.m32;
    dest.m33 = left.m33 - right.m33;

    return dest;
  }

  /**
   * Multiply the right matrix by the left and return the result in a new
   * matrix.
   * 
   * @param left
   *          The left source matrix
   * @param right
   *          The right source matrix
   * @return the destination matrix
   */
  public static Mat4 mul(final Mat4 left, final Mat4 right) {
    return Mat4.mul(left, right, null);
  }

  /**
   * Multiply the right matrix by the left and place the result in a third
   * matrix.
   * 
   * @param left
   *          The left source matrix
   * @param right
   *          The right source matrix
   * @param dest
   *          The destination matrix, or null if a new one is to be created
   * @return the destination matrix
   */
  public static Mat4 mul(final Mat4 left, final Mat4 right, Mat4 dest) {
    if (dest == null) dest = new Mat4();

    final float m00 = left.m00 * right.m00 + left.m10 * right.m01 + left.m20 * right.m02 + left.m30 * right.m03;
    final float m01 = left.m01 * right.m00 + left.m11 * right.m01 + left.m21 * right.m02 + left.m31 * right.m03;
    final float m02 = left.m02 * right.m00 + left.m12 * right.m01 + left.m22 * right.m02 + left.m32 * right.m03;
    final float m03 = left.m03 * right.m00 + left.m13 * right.m01 + left.m23 * right.m02 + left.m33 * right.m03;
    final float m10 = left.m00 * right.m10 + left.m10 * right.m11 + left.m20 * right.m12 + left.m30 * right.m13;
    final float m11 = left.m01 * right.m10 + left.m11 * right.m11 + left.m21 * right.m12 + left.m31 * right.m13;
    final float m12 = left.m02 * right.m10 + left.m12 * right.m11 + left.m22 * right.m12 + left.m32 * right.m13;
    final float m13 = left.m03 * right.m10 + left.m13 * right.m11 + left.m23 * right.m12 + left.m33 * right.m13;
    final float m20 = left.m00 * right.m20 + left.m10 * right.m21 + left.m20 * right.m22 + left.m30 * right.m23;
    final float m21 = left.m01 * right.m20 + left.m11 * right.m21 + left.m21 * right.m22 + left.m31 * right.m23;
    final float m22 = left.m02 * right.m20 + left.m12 * right.m21 + left.m22 * right.m22 + left.m32 * right.m23;
    final float m23 = left.m03 * right.m20 + left.m13 * right.m21 + left.m23 * right.m22 + left.m33 * right.m23;
    final float m30 = left.m00 * right.m30 + left.m10 * right.m31 + left.m20 * right.m32 + left.m30 * right.m33;
    final float m31 = left.m01 * right.m30 + left.m11 * right.m31 + left.m21 * right.m32 + left.m31 * right.m33;
    final float m32 = left.m02 * right.m30 + left.m12 * right.m31 + left.m22 * right.m32 + left.m32 * right.m33;
    final float m33 = left.m03 * right.m30 + left.m13 * right.m31 + left.m23 * right.m32 + left.m33 * right.m33;

    dest.m00 = m00;
    dest.m01 = m01;
    dest.m02 = m02;
    dest.m03 = m03;
    dest.m10 = m10;
    dest.m11 = m11;
    dest.m12 = m12;
    dest.m13 = m13;
    dest.m20 = m20;
    dest.m21 = m21;
    dest.m22 = m22;
    dest.m23 = m23;
    dest.m30 = m30;
    dest.m31 = m31;
    dest.m32 = m32;
    dest.m33 = m33;

    return dest;
  }

  /**
   * Transpose this matrix
   * 
   * @return this
   */
  public Mat4 transpose() {
    return transpose(this);
  }

  /**
   * Transpose this matrix and place the result in another matrix
   * 
   * @param dest
   *          The destination matrix or null if a new matrix is to be created
   * @return the transposed matrix
   */
  public Mat4 transpose(final Mat4 dest) {
    return transpose(this, dest);
  }

  /**
   * Transpose the source matrix and place the result in the destination matrix
   * 
   * @param src
   *          The source matrix
   * @param dest
   *          The destination matrix or null if a new matrix is to be created
   * @return the transposed matrix
   */
  public static Mat4 transpose(final Mat4 src, Mat4 dest) {
    if (dest == null) dest = new Mat4();
    final float m00 = src.m00;
    final float m01 = src.m10;
    final float m02 = src.m20;
    final float m03 = src.m30;
    final float m10 = src.m01;
    final float m11 = src.m11;
    final float m12 = src.m21;
    final float m13 = src.m31;
    final float m20 = src.m02;
    final float m21 = src.m12;
    final float m22 = src.m22;
    final float m23 = src.m32;
    final float m30 = src.m03;
    final float m31 = src.m13;
    final float m32 = src.m23;
    final float m33 = src.m33;

    dest.m00 = m00;
    dest.m01 = m01;
    dest.m02 = m02;
    dest.m03 = m03;
    dest.m10 = m10;
    dest.m11 = m11;
    dest.m12 = m12;
    dest.m13 = m13;
    dest.m20 = m20;
    dest.m21 = m21;
    dest.m22 = m22;
    dest.m23 = m23;
    dest.m30 = m30;
    dest.m31 = m31;
    dest.m32 = m32;
    dest.m33 = m33;

    return dest;
  }

  /**
   * @return the determinant of the matrix
   */
  public float determinant() {
    float f = m00
        * ((m11 * m22 * m33 + m12 * m23 * m31 + m13 * m21 * m32) - m13 * m22 * m31 - m11 * m23 * m32 - m12 * m21 * m33);
    f -= m01
        * ((m10 * m22 * m33 + m12 * m23 * m30 + m13 * m20 * m32) - m13 * m22 * m30 - m10 * m23 * m32 - m12 * m20 * m33);
    f += m02
        * ((m10 * m21 * m33 + m11 * m23 * m30 + m13 * m20 * m31) - m13 * m21 * m30 - m10 * m23 * m31 - m11 * m20 * m33);
    f -= m03
        * ((m10 * m21 * m32 + m11 * m22 * m30 + m12 * m20 * m31) - m12 * m21 * m30 - m10 * m22 * m31 - m11 * m20 * m32);
    return f;
  }

  /**
   * Calculate the determinant of a 3x3 matrix
   * 
   * @return result
   */

  private static float determinant3x3(final float t00,
                                      final float t01,
                                      final float t02,
                                      final float t10,
                                      final float t11,
                                      final float t12,
                                      final float t20,
                                      final float t21,
                                      final float t22) {
    return t00 * (t11 * t22 - t12 * t21) + t01 * (t12 * t20 - t10 * t22) + t02 * (t10 * t21 - t11 * t20);
  }

  /**
   * Invert this matrix
   * 
   * @return this if successful, null otherwise
   */
  public Mat4 invert() {
    return invert(this, this);
  }

  /**
   * Invert the source matrix and put the result in the destination
   * 
   * @param src
   *          The source matrix
   * @param dest
   *          The destination matrix, or null if a new matrix is to be created
   * @return The inverted matrix if successful, null otherwise
   */
  public static Mat4 invert(final Mat4 src, Mat4 dest) {
    final float determinant = src.determinant();

    if (determinant != 0) {
      /*
       * m00 m01 m02 m03 m10 m11 m12 m13 m20 m21 m22 m23 m30 m31 m32 m33
       */
      if (dest == null) dest = new Mat4();
      final float determinant_inv = 1f / determinant;

      // first row
      final float t00 = determinant3x3(src.m11, src.m12, src.m13, src.m21, src.m22, src.m23, src.m31, src.m32, src.m33);
      final float t01 = -determinant3x3(src.m10,
                                        src.m12,
                                        src.m13,
                                        src.m20,
                                        src.m22,
                                        src.m23,
                                        src.m30,
                                        src.m32,
                                        src.m33);
      final float t02 = determinant3x3(src.m10, src.m11, src.m13, src.m20, src.m21, src.m23, src.m30, src.m31, src.m33);
      final float t03 = -determinant3x3(src.m10,
                                        src.m11,
                                        src.m12,
                                        src.m20,
                                        src.m21,
                                        src.m22,
                                        src.m30,
                                        src.m31,
                                        src.m32);
      // second row
      final float t10 = -determinant3x3(src.m01,
                                        src.m02,
                                        src.m03,
                                        src.m21,
                                        src.m22,
                                        src.m23,
                                        src.m31,
                                        src.m32,
                                        src.m33);
      final float t11 = determinant3x3(src.m00, src.m02, src.m03, src.m20, src.m22, src.m23, src.m30, src.m32, src.m33);
      final float t12 = -determinant3x3(src.m00,
                                        src.m01,
                                        src.m03,
                                        src.m20,
                                        src.m21,
                                        src.m23,
                                        src.m30,
                                        src.m31,
                                        src.m33);
      final float t13 = determinant3x3(src.m00, src.m01, src.m02, src.m20, src.m21, src.m22, src.m30, src.m31, src.m32);
      // third row
      final float t20 = determinant3x3(src.m01, src.m02, src.m03, src.m11, src.m12, src.m13, src.m31, src.m32, src.m33);
      final float t21 = -determinant3x3(src.m00,
                                        src.m02,
                                        src.m03,
                                        src.m10,
                                        src.m12,
                                        src.m13,
                                        src.m30,
                                        src.m32,
                                        src.m33);
      final float t22 = determinant3x3(src.m00, src.m01, src.m03, src.m10, src.m11, src.m13, src.m30, src.m31, src.m33);
      final float t23 = -determinant3x3(src.m00,
                                        src.m01,
                                        src.m02,
                                        src.m10,
                                        src.m11,
                                        src.m12,
                                        src.m30,
                                        src.m31,
                                        src.m32);
      // fourth row
      final float t30 = -determinant3x3(src.m01,
                                        src.m02,
                                        src.m03,
                                        src.m11,
                                        src.m12,
                                        src.m13,
                                        src.m21,
                                        src.m22,
                                        src.m23);
      final float t31 = determinant3x3(src.m00, src.m02, src.m03, src.m10, src.m12, src.m13, src.m20, src.m22, src.m23);
      final float t32 = -determinant3x3(src.m00,
                                        src.m01,
                                        src.m03,
                                        src.m10,
                                        src.m11,
                                        src.m13,
                                        src.m20,
                                        src.m21,
                                        src.m23);
      final float t33 = determinant3x3(src.m00, src.m01, src.m02, src.m10, src.m11, src.m12, src.m20, src.m21, src.m22);

      // transpose and divide by the determinant
      dest.m00 = t00 * determinant_inv;
      dest.m11 = t11 * determinant_inv;
      dest.m22 = t22 * determinant_inv;
      dest.m33 = t33 * determinant_inv;
      dest.m01 = t10 * determinant_inv;
      dest.m10 = t01 * determinant_inv;
      dest.m20 = t02 * determinant_inv;
      dest.m02 = t20 * determinant_inv;
      dest.m12 = t21 * determinant_inv;
      dest.m21 = t12 * determinant_inv;
      dest.m03 = t30 * determinant_inv;
      dest.m30 = t03 * determinant_inv;
      dest.m13 = t31 * determinant_inv;
      dest.m31 = t13 * determinant_inv;
      dest.m32 = t23 * determinant_inv;
      dest.m23 = t32 * determinant_inv;
      return dest;
    } else return null;
  }

  /**
   * Negate this matrix
   * 
   * @return this
   */
  public Mat4 negate() {
    return negate(this);
  }

  /**
   * Negate this matrix and place the result in a destination matrix.
   * 
   * @param dest
   *          The destination matrix, or null if a new matrix is to be created
   * @return the negated matrix
   */
  public Mat4 negate(final Mat4 dest) {
    return negate(this, this);
  }

  /**
   * Negate this matrix and place the result in a destination matrix.
   * 
   * @param src
   *          The source matrix
   * @param dest
   *          The destination matrix, or null if a new matrix is to be created
   * @return The negated matrix
   */
  public static Mat4 negate(final Mat4 src, Mat4 dest) {
    if (dest == null) dest = new Mat4();

    dest.m00 = -src.m00;
    dest.m01 = -src.m01;
    dest.m02 = -src.m02;
    dest.m03 = -src.m03;
    dest.m10 = -src.m10;
    dest.m11 = -src.m11;
    dest.m12 = -src.m12;
    dest.m13 = -src.m13;
    dest.m20 = -src.m20;
    dest.m21 = -src.m21;
    dest.m22 = -src.m22;
    dest.m23 = -src.m23;
    dest.m30 = -src.m30;
    dest.m31 = -src.m31;
    dest.m32 = -src.m32;
    dest.m33 = -src.m33;

    return dest;
  }

  /**
   * Create a new identity matrix.
   * 
   * @return a identity matrix
   */
  public static Mat4 createIdentity() {
    return new Mat4();
  }

  /**
   * Transform a Vector by a matrix and return the result in a destination
   * vector.
   * 
   * @param left
   *          The left matrix
   * @param right
   *          The right vector
   * @return the destination vector
   */
  public static Vec4 transform(final Mat4 left, final Vec4 right) {
    return transform(left, right, null);
  }

  /**
   * Transform a Vector by a matrix and return the result in a destination
   * vector.
   * 
   * @param left
   *          The left matrix
   * @param right
   *          The right vector
   * @param dest
   *          The destination vector, or null if a new one is to be created
   * @return the destination vector
   */
  public static Vec4 transform(final Mat4 left, final Vec4 right, Vec4 dest) {
    if (dest == null) dest = new Vec4();

    final float x = left.m00 * right.x + left.m10 * right.y + left.m20 * right.z + left.m30 * right.w;
    final float y = left.m01 * right.x + left.m11 * right.y + left.m21 * right.z + left.m31 * right.w;
    final float z = left.m02 * right.x + left.m12 * right.y + left.m22 * right.z + left.m32 * right.w;
    final float w = left.m03 * right.x + left.m13 * right.y + left.m23 * right.z + left.m33 * right.w;

    dest.x = x;
    dest.y = y;
    dest.z = z;
    dest.w = w;

    return dest;
  }

  /**
   * Compare this Matrix with some other matrix and return true when they are
   * equal.
   * 
   * @param other
   */
  public boolean compare(final Mat4 other) {
    return equals(m00, other.m00) && equals(m01, other.m01) && equals(m02, other.m02) && equals(m03, other.m03)
        && equals(m10, other.m10) && equals(m11, other.m11) && equals(m12, other.m12) && equals(m13, other.m13)
        && equals(m20, other.m20) && equals(m21, other.m21) && equals(m22, other.m22) && equals(m23, other.m23)
        && equals(m30, other.m30) && equals(m31, other.m31) && equals(m32, other.m32) && equals(m33, other.m33);
  }

  private boolean equals(final float a, final float b) {
    return Math.abs(a - b) < 0.00000001f;
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy