nova.core.util.math.MatrixStack.java Source code

Java tutorial

Introduction

Here is the source code for nova.core.util.math.MatrixStack.java

Source

/*
 * Copyright (c) 2015 NOVA, All rights reserved.
 * This library is free software, licensed under GNU Lesser General Public License version 3
 *
 * This file is part of NOVA.
 *
 * NOVA is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * NOVA is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with NOVA.  If not, see <http://www.gnu.org/licenses/>.
 */package nova.core.util.math;

import org.apache.commons.math3.geometry.euclidean.threed.Rotation;
import org.apache.commons.math3.geometry.euclidean.threed.Vector3D;
import org.apache.commons.math3.linear.MatrixUtils;
import org.apache.commons.math3.linear.RealMatrix;

import java.util.Stack;

public class MatrixStack implements Transformer {

    private final Stack<RealMatrix> stack;

    private RealMatrix current = MatrixUtils.createRealIdentityMatrix(4);

    /**
     * Creates new MatrixStack. Constains no transfomation base matrix.
     */
    public MatrixStack() {
        this.stack = new Stack<>();
    }

    /**
     * Clone construcotr of MatrixStack
     * @param clone instance to be cloned
     */
    public MatrixStack(MatrixStack clone) {
        //noinspection unchecked
        this.stack = (Stack<RealMatrix>) clone.stack.clone();
        this.current = clone.current.copy();
    }

    /**
     * Creates new MatrixStack with starting matrix.
     * @param current Transforation matrix to start from.
     */
    public MatrixStack(RealMatrix current) {
        this.stack = new Stack<>();
        this.current = current;
    }

    /**
     * Replaces current transformation matrix by an identity matrix.
     */
    public void loadIdentity() {
        current = MatrixUtils.createRealIdentityMatrix(4);
    }

    /**
     * Replaces current transformation matrix by an identity current.
     *
     * @param matrix The new matrix to use.
     * @return this for chaining.
     */
    public MatrixStack loadMatrix(RealMatrix matrix) {
        current = matrix;
        return this;
    }

    /**
     * Exposes current transformation matrix.
     *
     * @return current transformation matrix.
     */
    public RealMatrix getMatrix() {
        return current;
    }

    /**
     * Transforms current matrix with give matrix.
     *
     * @param matrix to transform current matrix.
     * @return The transformed matrix
     */
    public MatrixStack transform(RealMatrix matrix) {

        current = current.preMultiply(MatrixUtil.augmentWithIdentity(matrix, 4));
        return this;
    }

    /**
     * Translates current transformation matrix.
     *
     * @param x translation.
     * @param y translation.
     * @param z translation.
     * @return The tranlated matrix
     */
    public MatrixStack translate(double x, double y, double z) {
        current = current.preMultiply(TransformUtil.translationMatrix(x, y, z));
        return this;
    }

    /**
     * Translates current transformation matrix.
     *
     * @param translateVector vector of translation.
     * @return The tranformed matrix
     */
    public MatrixStack translate(Vector3D translateVector) {
        translate(translateVector.getX(), translateVector.getY(), translateVector.getZ());
        return this;
    }

    /**
     * Rotates the current matrix
     *
     * @param rotation The rotation to aply
     * @return The rorated matrix
     */
    public MatrixStack rotate(Rotation rotation) {
        RealMatrix rotMat = MatrixUtils.createRealMatrix(4, 4);
        rotMat.setSubMatrix(rotation.getMatrix(), 0, 0);
        rotMat.setEntry(3, 3, 1);
        current = current.preMultiply(rotMat);
        return this;
    }

    /**
     * Rotates transformation matrix around rotateVector axis by angle radians.
     *
     * @param rotateVector Vector serving as rotation axis.
     * @param angle in radians.
     * @return The rotated matrix
     */
    public MatrixStack rotate(Vector3D rotateVector, double angle) {
        return rotate(new Rotation(rotateVector, angle));
    }

    /**
     * Scales current transformation matrix.
     *
     * @param x scale.
     * @param y scale.
     * @param z scale.
     * @return this for chaining.
     */
    public MatrixStack scale(double x, double y, double z) {
        current = current.preMultiply(TransformUtil.scaleMatrix(x, y, z));
        return this;
    }

    /**
     * Scales current transformation matrix.
     *
     * @param scaleVector scale vector.
     * @return The current matrix
     */
    public MatrixStack scale(Vector3D scaleVector) {
        scale(scaleVector.getX(), scaleVector.getY(), scaleVector.getZ());
        return this;
    }

    /**
     * Pushes matrix onto the stack. Use it to save current state of MatrixStack in case of branching transformations.
     * @return this for chaining.
     */
    public MatrixStack pushMatrix() {
        stack.add(current);
        return this;
    }

    /**
     * Pops matrix from stack. Use it to restore saved transformation.
     * @return this for chaining.
     */
    public MatrixStack popMatrix() {
        current = stack.pop();
        return this;
    }

    /**
     * Called to transform a vector.
     * @param vec - The vector being transformed
     * @return The transformed vector by current matrix.
     */
    @Override
    public Vector3D apply(Vector3D vec) {
        return TransformUtil.transform(vec, current);
    }
}