Android Open Source - 3D-Compass Mat4f






From Project

Back to project page 3D-Compass.

License

The source code is released under:

Apache License

If you think the Android project 3D-Compass listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package nz.gen.geek_central.GLUseful;
/*//from   ww w.  jav a 2 s.c o m
    Functional 3D matrix operations. Matrix elements are in row-major order.
    Vectors are treated as column vectors and premultiplied, i.e.

        [x']   [m11 m12 m13 m14]   [x]
        [y'] = [m21 m22 m23 m24]  [y]
        [z']   [m31 m32 m33 m34]   [z]
        [w']   [m41 m42 m43 m44]   [w]

    Q: Why not use the android.opengl.Matrix class?
    A: Because that is procedural (updates state in an existing
       object), this is functional (computes values from
       expressions). The procedural approach requires you to perform a
       sequence of calls on intermediate variables to set up a complex
       transformation, whereas the functional approach allows you to
       write it as a single expression, closer to the way it is
       formulated mathematically. For an example in this source file,
       see below how general rotation about an arbitrary axis is
       composed out of a sequence of simpler rotation components.
    Q: But doesn't that involve a whole lot of extra heap allocations?
    A: Isn't that the point of using Java?

    Copyright 2011-2013 by Lawrence D'Oliveiro <ldo@geek-central.gen.nz>.

    Licensed under the Apache License, Version 2.0 (the "License"); you may not
    use this file except in compliance with the License. You may obtain a copy of
    the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
    License for the specific language governing permissions and limitations under
    the License.
*/

public class Mat4f
  /* 4x4 matrices */
  {
    public final float
        m11, m12, m13, m14,
        m21, m22, m23, m24,
        m31, m32, m33, m34,
        m41, m42, m43, m44;

    public Mat4f
      (
        float m11,
        float m12,
        float m13,
        float m14,
        float m21,
        float m22,
        float m23,
        float m24,
        float m31,
        float m32,
        float m33,
        float m34,
        float m41,
        float m42,
        float m43,
        float m44
      )
      {
        this.m11 = m11;
        this.m12 = m12;
        this.m13 = m13;
        this.m14 = m14;
        this.m21 = m21;
        this.m22 = m22;
        this.m23 = m23;
        this.m24 = m24;
        this.m31 = m31;
        this.m32 = m32;
        this.m33 = m33;
        this.m34 = m34;
        this.m41 = m41;
        this.m42 = m42;
        this.m43 = m43;
        this.m44 = m44;
      } /*Mat4f*/

    public Mat4f
      (
        float[] m
      )
      {
        if (m.length == 16)
          {
            m11 = m[0];
            m21 = m[1];
            m31 = m[2];
            m41 = m[3];
            m12 = m[4];
            m22 = m[5];
            m32 = m[6];
            m42 = m[7];
            m13 = m[8];
            m23 = m[9];
            m33 = m[10];
            m43 = m[11];
            m14 = m[12];
            m24 = m[13];
            m34 = m[14];
            m44 = m[15];
          }
        else if (m.length == 9)
          {
            m11 = m[0];
            m21 = m[1];
            m31 = m[2];
            m41 = 0.0f;
            m12 = m[3];
            m22 = m[4];
            m32 = m[5];
            m42 = 0.0f;
            m13 = m[6];
            m23 = m[7];
            m33 = m[8];
            m43 = 0.0f;
            m14 = 0.0f;
            m24 = 0.0f;
            m34 = 0.0f;
            m44 = 1.0f;
          }
        else
          {
            throw new RuntimeException("need 9 or 16 array elements");
          } /*if*/
      } /*Mat4f*/

    public float[] to_floats
      (
        boolean by_cols, /* false to go by rows */
        int nrelts /* 9 or 16 */
      )
      {
        if (nrelts != 9 && nrelts != 16)
          {
            throw new RuntimeException("must return 9 or 16 array elements");
          } /*if*/
        final float[] m = new float[nrelts];
        switch (nrelts)
          {
        case 9:
            if (by_cols)
              {
                m[0] = m11;
                m[1] = m21;
                m[2] = m31;
                m[3] = m12;
                m[4] = m22;
                m[5] = m32;
                m[6] = m13;
                m[7] = m23;
                m[8] = m33;
              }
            else
              {
                m[0] = m11;
                m[1] = m12;
                m[2] = m13;
                m[3] = m21;
                m[4] = m22;
                m[5] = m23;
                m[6] = m31;
                m[7] = m32;
                m[8] = m33;
              } /*if*/
        break;
        case 16:
            if (by_cols)
              {
                m[0] = m11;
                m[1] = m21;
                m[2] = m31;
                m[3] = m41;
                m[4] = m12;
                m[5] = m22;
                m[6] = m32;
                m[7] = m42;
                m[8] = m13;
                m[9] = m23;
                m[10] = m33;
                m[11] = m43;
                m[12] = m14;
                m[13] = m24;
                m[14] = m34;
                m[15] = m44;
              }
            else
              {
                m[0] = m11;
                m[1] = m12;
                m[2] = m13;
                m[3] = m14;
                m[4] = m21;
                m[5] = m22;
                m[6] = m23;
                m[7] = m24;
                m[8] = m31;
                m[9] = m32;
                m[10] = m33;
                m[11] = m34;
                m[12] = m41;
                m[13] = m42;
                m[14] = m43;
                m[15] = m44;
              } /*if*/
        break;
          } /*switch*/
        return
            m;
      } /*to_floats*/

    public static Mat4f zero()
      {
        return
            new Mat4f
              (
                0.0f, 0.0f, 0.0f, 0.0f,
                0.0f, 0.0f, 0.0f, 0.0f,
                0.0f, 0.0f, 0.0f, 0.0f,
                0.0f, 0.0f, 0.0f, 0.0f
              );
      } /*Mat4f*/

    public static Mat4f identity()
      {
        return
            new Mat4f
              (
                1.0f, 0.0f, 0.0f, 0.0f,
                0.0f, 1.0f, 0.0f, 0.0f,
                0.0f, 0.0f, 1.0f, 0.0f,
                0.0f, 0.0f, 0.0f, 1.0f
              );
      } /*identity*/

    public boolean eq
      (
        Mat4f m
      )
      /* equality to another Matrix. */
      {
        return
                m11 == m.m11
            &&
                m12 == m.m12
            &&
                m13 == m.m13
            &&
                m14 == m.m14
            &&
                m21 == m.m21
            &&
                m22 == m.m22
            &&
                m23 == m.m23
            &&
                m24 == m.m24
            &&
                m31 == m.m31
            &&
                m32 == m.m32
            &&
                m33 == m.m33
            &&
                m34 == m.m34
            &&
                m41 == m.m41
            &&
                m42 == m.m42
            &&
                m43 == m.m43
            &&
                m44 == m.m44;
      } /*eq*/

    public Mat4f trn()
      /* returns the transpose. */
      {
        return new Mat4f
          (
            m11, m21, m31, m41,
            m12, m22, m32, m42,
            m13, m23, m33, m43,
            m14, m24, m34, m44
          );
      } /*trn*/

    public Mat4f mul
      (
        Mat4f m
      )
      {
        return
            new Mat4f
              (
                m11 * m.m11 + m12 * m.m21 + m13 * m.m31 + m14 * m.m41,
                m11 * m.m12 + m12 * m.m22 + m13 * m.m32 + m14 * m.m42,
                m11 * m.m13 + m12 * m.m23 + m13 * m.m33 + m14 * m.m43,
                m11 * m.m14 + m12 * m.m24 + m13 * m.m34 + m14 * m.m44,

                m21 * m.m11 + m22 * m.m21 + m23 * m.m31 + m24 * m.m41,
                m21 * m.m12 + m22 * m.m22 + m23 * m.m32 + m24 * m.m42,
                m21 * m.m13 + m22 * m.m23 + m23 * m.m33 + m24 * m.m43,
                m21 * m.m14 + m22 * m.m24 + m23 * m.m34 + m24 * m.m44,

                m31 * m.m11 + m32 * m.m21 + m33 * m.m31 + m34 * m.m41,
                m31 * m.m12 + m32 * m.m22 + m33 * m.m32 + m34 * m.m42,
                m31 * m.m13 + m32 * m.m23 + m33 * m.m33 + m34 * m.m43,
                m31 * m.m14 + m32 * m.m24 + m33 * m.m34 + m34 * m.m44,

                m41 * m.m11 + m42 * m.m21 + m43 * m.m31 + m44 * m.m41,
                m41 * m.m12 + m42 * m.m22 + m43 * m.m32 + m44 * m.m42,
                m41 * m.m13 + m42 * m.m23 + m43 * m.m33 + m44 * m.m43,
                m41 * m.m14 + m42 * m.m24 + m43 * m.m34 + m44 * m.m44
              );
      } /*mul*/

    public float det()
      /* returns determinant. */
      {
      /* compute a suitable set of sub-determinants which can each be used twice: */
        final float[] m = to_floats(true, 16); /* easier this way */
        final float[] det2 =
            {
                m[10] * m[15] - m[11] * m[14],
                m[6] * m[15] - m[7] * m[14],
                m[6] * m[11] - m[7] * m[10],
                m[2] * m[15] - m[3] * m[14],
                m[2] * m[11] - m[3] * m[10],
                m[2] * m[7] - m[3] * m[6],
            };
        return
                    m[0]
                *
                    (
                        m[5] * det2[0]
                    -
                        m[9] * det2[1]
                    +
                        m[13] * det2[2]
                    )
            -
                    m[4]
                *
                    (
                        m[1] * det2[0]
                    -
                        m[9] * det2[3]
                    +
                        m[13] * det2[4]
                    )
            +
                    m[8]
                *
                    (
                        m[1] * det2[1]
                    -
                        m[5] * det2[3]
                    +
                        m[13] * det2[5]
                    )
            -
                    m[12]
                *
                    (
                        m[1] * det2[2]
                    -
                        m[5] * det2[4]
                    +
                        m[9] * det2[5]
                    );
      } /*det*/

    public Mat4f adj()
      /* returns adjoint. */
      {
      /* compute a suitable set of sub-determinants which can each be used four times: */
        final float[] m = to_floats(true, 16); /* easier this way */
        final float[] det2 =
            {
                m[10] * m[15] - m[11] * m[14],
                m[6] * m[15] - m[7] * m[14],
                m[6] * m[11] - m[7] * m[10],
                m[2] * m[15] - m[3] * m[14],
                m[2] * m[11] - m[3] * m[10],
                m[2] * m[7] - m[3] * m[6],
                m[8] * m[13] - m[9] * m[12],
                m[4] * m[13] - m[5] * m[12],
                m[4] * m[9] - m[5] * m[8],
                m[0] * m[13] - m[1] * m[12],
                m[0] * m[9] - m[1] * m[8],
                m[0] * m[5] - m[1] * m[4],
            };
        return
            new Mat4f
              (
                m[5] * det2[0] - m[9] * det2[1] + m[13] * det2[2],
                - m[4] * det2[0] + m[8] * det2[1] - m[12] * det2[2],
                m[7] * det2[6] - m[11] * det2[7] + m[15] * det2[8],
                - m[6] * det2[6] + m[10] * det2[7] - m[14] * det2[8],

                - m[1] * det2[0] + m[9] * det2[3] - m[13] * det2[4],
                m[0] * det2[0] - m[8] * det2[3] + m[12] * det2[4],
                - m[3] * det2[6] + m[11] * det2[9] - m[15] * det2[10],
                m[2] * det2[6] - m[10] * det2[9] + m[14] * det2[10],

                m[1] * det2[1] - m[5] * det2[3] + m[13] * det2[5],
                - m[0] * det2[1] + m[4] * det2[3] - m[12] * det2[5],
                m[3] * det2[7] - m[7] * det2[9] + m[15] * det2[11],
                - m[2] * det2[7] + m[6] * det2[9] - m[14] * det2[11],

                - m[1] * det2[2] + m[5] * det2[4] - m[9] * det2[5],
                m[0] * det2[2] - m[4] * det2[4] + m[8] * det2[5],
                - m[3] * det2[8] + m[7] * det2[10] - m[11] * det2[11],
                m[2] * det2[8] - m[6] * det2[10] + m[10] * det2[11]
              );
      } /*adj*/

    public Mat4f inv()
      /* returns inverse, or null if none. */
      {
        Mat4f m;
        final float det = this.det();
        if (det != 0.0f)
          {
            final float[] adj = this.adj().to_floats(false, 16);
            m = new Mat4f
              (
                adj[0] / det,
                adj[1] / det,
                adj[2] / det,
                adj[3] / det,
                adj[4] / det,
                adj[5] / det,
                adj[6] / det,
                adj[7] / det,
                adj[8] / det,
                adj[9] / det,
                adj[10] / det,
                adj[11] / det,
                adj[12] / det,
                adj[13] / det,
                adj[14] / det,
                adj[15] / det
              );
          }
        else
          {
            m = null;
          } /*if*/
        return
            m;
      } /*inv*/

    public static Mat4f translation
      (
        Vec3f v
      )
      /* returns a matrix that will translate by the specified vector. */
      {
        return
            new Mat4f
              (
                1.0f, 0.0f, 0.0f, v.x,
                0.0f, 1.0f, 0.0f, v.y,
                0.0f, 0.0f, 1.0f, v.z,
                0.0f, 0.0f, 0.0f, v.w
              );
      } /*translation*/

    public static Mat4f translation
      (
        float dx,
        float dy,
        float dz
      )
      /* returns a matrix that will translate by the specified amounts. */
      {
        return
            new Mat4f
              (
                1.0f, 0.0f, 0.0f, dx,
                0.0f, 1.0f, 0.0f, dy,
                0.0f, 0.0f, 1.0f, dz,
                0.0f, 0.0f, 0.0f, 1.0f
              );
      } /*translation*/

    public static Mat4f scaling
      (
        Vec3f v
      )
      /* returns a matrix that will scale about the origin by the specified vector. */
      {
        return
            new Mat4f
              (
                v.x, 0.0f, 0.0f, 0.0f,
                0.0f, v.y, 0.0f, 0.0f,
                0.0f, 0.0f, v.z, 0.0f,
                0.0f, 0.0f, 0.0f, v.w
              );
      } /*scaling*/

    public static Mat4f scaling
      (
        float sx,
        float sy,
        float sz
      )
      /* returns a matrix that will scale about the origin by the specified factors. */
      {
        return
            new Mat4f
              (
                sx, 0.0f, 0.0f, 0.0f,
                0.0f, sy, 0.0f, 0.0f,
                0.0f, 0.0f, sz, 0.0f,
                0.0f, 0.0f, 0.0f, 1.0f
              );
      } /*scaling*/

    public static Mat4f scaling
      (
        Vec3f v,
        Vec3f origin
      )
      /* returns a matrix that will scale about the specified point by the specified vector. */
      {
        return
            translation(origin).mul(scaling(v)).mul(translation(origin.neg()));
      } /*scaling*/

    public static final int AXIS_X = 0;
    public static final int AXIS_Y = 1;
    public static final int AXIS_Z = 2;

    public static Mat4f rotation
      (
        int axis, /* AXIS_X, AXIS_Y or AXIS_Z */
        float angle,
        boolean degrees /* false for radians */
      )
      {
        final float radians = degrees ? (float)Math.toRadians(angle) : angle;
        final float cos = (float)Math.cos(radians);
        final float sin = (float)Math.sin(radians);
        Mat4f m;
        switch (axis)
          {
        case AXIS_X:
            m = new Mat4f
              (
                1.0f, 0.0f, 0.0f, 0.0f,
                0.0f, cos, - sin, 0.0f,
                0.0f, sin, cos, 0.0f,
                0.0f, 0.0f, 0.0f, 1.0f
              );
        break;
        case AXIS_Y:
            m = new Mat4f
              (
                cos, 0.0f, sin, 0.0f,
                0.0f, 1.0f, 0.0f, 0.0f,
                - sin, 0.0f, cos, 0.0f,
                0.0f, 0.0f, 0.0f, 1.0f
              );
        break;
        case AXIS_Z:
            m = new Mat4f
              (
                cos, - sin, 0.0f, 0.0f,
                sin, cos, 0.0f, 0.0f,
                0.0f, 0.0f, 1.0f, 0.0f,
                0.0f, 0.0f, 0.0f, 1.0f
              );
        break;
        default:
            throw new RuntimeException("invalid rotation axis");
      /* break; */
          } /*switch*/
        return
            m;
      } /*rotation*/

    public static Mat4f rotation
      (
        int axis, /* AXIS_X, AXIS_Y or AXIS_Z */
        float angle,
        boolean degrees /* false for radians */,
        Vec3f origin
      )
      {
        return
            translation(origin).mul(rotation(axis, angle, degrees)).mul(translation(origin.neg()));
      } /*rotation*/

    public static Mat4f rotation
      (
        Vec3f axis, /* assumed unit vector */
        float angle,
        boolean degrees /* false for radians */
      )
      /* generates a rotation about an arbitrary axis passing through the origin. */
      {
        final float zangle = (float)Math.atan2(axis.y, axis.x);
          /* rotate about z into x-z plane */
        final float yangle = (float)Math.atan2
          (
            axis.z,
            Math.sqrt(axis.y * axis.y + axis.x * axis.x)
          );
          /* rotate within x-z plane about y to align with x-axis */
        return
                rotation(AXIS_Z, zangle, false)
            .mul(
                rotation(AXIS_Y, - yangle, false)
            ).mul(
                rotation(AXIS_X, angle, degrees)
            ).mul(
                rotation(AXIS_Y, yangle, false)
            ).mul(
                rotation(AXIS_Z, - zangle, false)
            );
      } /*rotation*/

    public static Mat4f rotation
      (
        Vec3f axis,
        float angle,
        boolean degrees /* false for radians */,
        Vec3f origin
      )
      /* generates a rotation about an arbitrary axis. */
      {
        return
                translation(origin)
            .mul(
                rotation(axis.sub(origin), angle, degrees))
            .mul(
                translation(origin.neg())
            );
      } /*rotation*/

    public static Mat4f rotate_align
      (
        Vec3f src,
        Vec3f dst
      )
      /* generates a rotation matrix which, when applied to src, turns it into dst. */
      {
        return
            rotation(src.cross(dst).unit(), (float)Math.acos(src.unit().dot(dst.unit())), false);
      } /*rotate_align*/

    public static Mat4f frustum
      (
        float L,
        float R,
        float B,
        float T,
        float N,
        float F
      )
      {
        return
            new Mat4f
              (
                2 * N / (R - L), 0.0f, (R + L) / (R - L), 0.0f,
                0.0f, 2 * N / (T - B), (T + B) / (T - B), 0.0f,
                0.0f, 0.0f, - (F + N) / (F - N), - 2 * F * N / (F - N),
                0.0f, 0.0f, -1.0f, 0.0f
              );
      } /*frustum*/

    public static Mat4f ortho
      (
        float L,
        float R,
        float B,
        float T,
        float N,
        float F
      )
      {
        return
            new Mat4f
              (
                2 / (R - L), 0.0f, 0.0f, - (R + L) / (R - L),
                0.0f, 2 / (T - B), 0.0f, - (T + B) / (T - B),
                0.0f, 0.0f, -2 / (F - N), - (F + N) / (F - N),
                0.0f, 0.0f, 0.0f, 1.0f
              );
      } /*ortho*/

    public static Mat4f map_cuboid
      (
        Vec3f src_lo,
        Vec3f src_hi,
        Vec3f dst_lo,
        Vec3f dst_hi
      )
      /* returns a matrix that maps the axis-aligned cuboid defined by
        opposite corners src_lo and src_hi to the one with opposite
        corners dst_lo and dst_hi. */
      {
        return
            (
                translation(dst_lo)
            ).mul(
                scaling(dst_hi.sub(dst_lo))
            ).mul(
                scaling(src_hi.sub(src_lo).recip())
            ).mul(
                translation(src_lo.neg())
            );
      } /*map_cuboid*/

    public static Mat4f fit_cuboid
      (
        Vec3f src_lo,
        Vec3f src_hi,
        Vec3f dst_lo,
        Vec3f dst_hi,
        boolean outside
      )
      /* returns a matrix that does appropriate scaling and translation
        to fit the axis-aligned cuboid defined by opposite corners src_lo
        and src_hi to the middle of the one with opposite corners dst_lo
        and dst_hi without distortion. If outside, then the minimum dimension
        of the src cuboid will equal the maximum dimension of dst (src
        fits outside dst); otherwise, the maximum dimension of src will
        equal the minimum dimension of dst (src fits inside dst). */
      {
        final Vec3f scalev = (dst_hi.sub(dst_lo)).div(src_hi.sub(src_lo));
        final float scale =
            outside ?
                (float)Math.max(Math.max(scalev.x, scalev.y), scalev.z)
            :
                (float)Math.min(Math.min(scalev.x, scalev.y), scalev.z);
        return
                translation((dst_lo.add(dst_hi)).div(2))
            .mul(
                scaling(scale, scale, scale)
            ).mul(
                translation((src_lo.add(src_hi)).div(2).neg())
            );
      } /*fit_cuboid*/

    public Vec3f xform
      (
        Vec3f v
      )
      /* returns the transformation of v by the matrix. */
      {
        return
            new Vec3f
              (
                v.x * m11 + v.y * m12 + v.z * m13 + v.w * m14,
                v.x * m21 + v.y * m22 + v.z * m23 + v.w * m24,
                v.x * m31 + v.y * m32 + v.z * m33 + v.w * m34,
                v.x * m41 + v.y * m42 + v.z * m43 + v.w * m44
              );
      } /*xform*/

    public Vec3f[] xform
      (
        Vec3f[] v
      )
      /* returns the transformation of the elements of v by the matrix. */
      {
        final java.util.ArrayList<Vec3f> result = new java.util.ArrayList<Vec3f>();
        for (Vec3f elt : v)
          {
            result.add(xform(elt));
          } /*for*/
        return
            result.toArray(new Vec3f[v.length]);
      } /*xform*/

    public Vec3f dxform
      (
        Vec3f v
      )
      /* returns the transformation of v by the matrix, excluding translation. */
      {
        return
            new Vec3f
              (
                v.x * m11 + v.y * m12 + v.z * m13,
                v.x * m21 + v.y * m22 + v.z * m23,
                v.x * m31 + v.y * m32 + v.z * m33
              );
      } /*dxform*/

    public Vec3f[] dxform
      (
        Vec3f[] v
      )
      /* returns the transformation of the elements of v by the matrix, excluding translation. */
      {
        final java.util.ArrayList<Vec3f> result = new java.util.ArrayList<Vec3f>();
        for (Vec3f elt : v)
          {
            result.add(dxform(elt));
          } /*for*/
        return
            result.toArray(new Vec3f[v.length]);
      } /*dxform*/

    @Override
    public String toString()
      {
        return
            String.format /* should I worry about locale? */
              (
                "Mat4f[[%.3f, %.3f, %.3f, %.3f], [%.3f, %.3f, %.3f, %.3f], [%.3f, %.3f, %.3f, %.3f], [%.3f, %.3f, %.3f, %.3f]]",
                m11, m12, m13, m14,
                m21, m22, m23, m24,
                m31, m32, m33, m34,
                m41, m42, m43, m44
              );
      } /*toString*/

  } /*Mat4f*/




Java Source Code List

nz.gen.geek_central.Compass3D.CameraList.java
nz.gen.geek_central.Compass3D.CameraUseful.java
nz.gen.geek_central.Compass3D.Compass.java
nz.gen.geek_central.Compass3D.MainView.java
nz.gen.geek_central.Compass3D.Main.java
nz.gen.geek_central.GLUseful.BaseRenderer.java
nz.gen.geek_central.GLUseful.GLBitmapView.java
nz.gen.geek_central.GLUseful.GLTextureView.java
nz.gen.geek_central.GLUseful.GLUseful.java
nz.gen.geek_central.GLUseful.GeomBuilder.java
nz.gen.geek_central.GLUseful.Lathe.java
nz.gen.geek_central.GLUseful.Mat4f.java
nz.gen.geek_central.GLUseful.Vec3f.java