org.spout.api.math.Quaternion.java Source code

Java tutorial

Introduction

Here is the source code for org.spout.api.math.Quaternion.java

Source

/*
 * This file is part of SpoutAPI.
 *
 * Copyright (c) 2011-2012, SpoutDev <http://www.spout.org/>
 * SpoutAPI is licensed under the SpoutDev License Version 1.
 *
 * SpoutAPI is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * In addition, 180 days after any changes are published, you can use the
 * software, incorporating those changes, under the terms of the MIT license,
 * as described in the SpoutDev License Version 1.
 *
 * SpoutAPI 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 Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License,
 * the MIT license and the SpoutDev License Version 1 along with this program.
 * If not, see <http://www.gnu.org/licenses/> for the GNU Lesser General Public
 * License and see <http://www.spout.org/SpoutDevLicenseV1.txt> for the full license,
 * including the MIT license.
 */
package org.spout.api.math;

import java.io.Serializable;

import javolution.lang.ValueType;

import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.spout.api.util.StringUtil;

/**
 * Represents a rotation around a unit 4d circle.
 */
public class Quaternion implements Serializable, ValueType {
    private static final long serialVersionUID = 1L;

    protected final float x, y, z, w;
    protected transient volatile Vector3 cachedAngle = null;

    /**
     * Represents no rotation
     */
    public static final Quaternion IDENTITY = new Quaternion(0, 0, 0, 1, true);

    /**
     * Represents 90 degrees rotation around the x axis
     */
    public static final Quaternion UNIT_X = new Quaternion(1, 0, 0, 0, true);

    /**
     * Represents 90 degrees rotation around the < axis
     */
    public static final Quaternion UNIT_Y = new Quaternion(0, 1, 0, 0, true);

    /**
     * Represents 90 degrees rotation around the z axis
     */
    public static final Quaternion UNIT_Z = new Quaternion(0, 0, 1, 0, true);

    /**
     * Constructs a new Quaternion with the given xyzw NOTE: This represents a
     * Unit Vector in 4d space. Do not use unless you know what you are doing.
     * If you want to create a normal rotation, use the angle/axis override.
     *
     * @param x
     * @param y
     * @param z
     * @param w
     * @param ignore Ignored.  This is because float float float float should be for angle/x,y,z
     */
    public Quaternion(float x, float y, float z, float w, boolean ignore) {
        this.x = x;
        this.y = y;
        this.z = z;
        this.w = w;
    }

    /**
     * Constructs a new Quaternion that represents a given rotation around an
     * arbatrary axis
     *
     * @param angle Angle, in Degrees, to rotate the axis about by
     * @param x-axis
     * @param y-axis
     * @param z-axis
     */
    public Quaternion(float angle, float x, float y, float z) {
        double rads = Math.toRadians(angle);
        double halfAngle = Math.sin(rads / 2);
        this.x = (float) (x * halfAngle);
        this.y = (float) (y * halfAngle);
        this.z = (float) (z * halfAngle);
        this.w = (float) Math.cos(rads / 2);
    }

    /**
     * Constructs a new Quaternion that represents a given rotation around an
     * arbatrary axis
     *
     * @param angle Angle, in Degrees, to rotate the axis about by
     * @param axis
     */
    public Quaternion(float angle, Vector3 axis) {
        this(angle, axis.getX(), axis.getY(), axis.getZ());
    }

    /**
     * Copy Constructor
     */
    public Quaternion(Quaternion rotation) {
        this(rotation.x, rotation.y, rotation.z, rotation.w, false);
    }

    /**
     * Returns the X component of the quaternion
     *
     * @return
     */
    public float getX() {
        return x;
    }

    /**
     * Returns the Y component of the quaternion
     *
     * @return
     */
    public float getY() {
        return y;
    }

    /**
     * Returns the Z component of the quaternion
     *
     * @return
     */
    public float getZ() {
        return z;
    }

    /**
     * Returns the W component of the quaternion
     *
     * @return
     */
    public float getW() {
        return w;
    }

    public float getPitch() {
        return getAxisAngles().getX();
    }

    public float getYaw() {
        return getAxisAngles().getY();
    }

    public float getRoll() {
        return getAxisAngles().getZ();
    }

    /**
     * Returns the length squared of the quaternion
     *
     * @return
     */
    public float lengthSquared() {
        return MathHelper.lengthSquared(this);
    }

    /**
     * Returns the length of the quaternion. Note: This uses square root, so is
     * slowish
     *
     * @return
     */
    public float length() {
        return MathHelper.length(this);
    }

    /**
     * Returns this quaternion but length() == 1
     *
     * @return
     */
    public Quaternion normalize() {
        return MathHelper.normalize(this);
    }

    /**
     * Multiplies this Quaternion by the other Quaternion
     *
     * @param o
     * @return
     */
    public Quaternion multiply(Quaternion o) {
        return MathHelper.multiply(this, o);
    }

    /**
     * Creates and returns a new Quaternion that represnets this quaternion
     * rotated by the given Axis and Angle
     *
     * @param angle
     * @param axis
     * @return rotated Quaternion
     */
    public Quaternion rotate(float angle, Vector3 axis) {
        return MathHelper.rotate(this, angle, axis);
    }

    /**
     * Creates and returns a new Quaternion that represnets this quaternion
     * rotated by the given Axis and Angle
     *
     * @param angle
     * @param x axis
     * @param y axis
     * @param z axis
     * @return rotated Quaternion
     */
    public Quaternion rotate(float angle, float x, float y, float z) {
        return MathHelper.rotate(this, angle, x, y, z);
    }

    /**
     * Returns the angles about each axis of this quaternion stored in a Vector3
     *
     * vect.X = Rotation about the X axis (Roll) vect.Y = Rotation about the Y
     * axis (Yaw) vect.Z = Rotation about the Z axis (Pitch)
     *
     * @return
     */
    public Vector3 getAxisAngles() {
        if (cachedAngle == null) {
            cachedAngle = MathHelper.getAxisAngles(this);
        }

        return cachedAngle;
    }

    @Override
    public String toString() {
        return getClass().getSimpleName() + StringUtil.toString(this.x, this.y, this.z, this.w);
    }

    @Override
    public boolean equals(Object obj) {
        if (!(obj instanceof Quaternion)) {
            return false;
        }
        if (obj == this) {
            return true;
        }
        Quaternion q = (Quaternion) obj;
        return this.w == q.w && this.x == q.x && this.y == q.y && this.z == q.z;
    }

    @Override
    public int hashCode() {
        return new HashCodeBuilder(41, 63).append(w).append(x).append(y).append(z).toHashCode();
    }

    @Override
    public Object copy() {
        return new Quaternion(this);
    }
}