javax.media.j3d.HiResCoord.java Source code

Java tutorial

Introduction

Here is the source code for javax.media.j3d.HiResCoord.java

Source

/*
 * Copyright 1996-2008 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code 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
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 *
 */

package javax.media.j3d;

import javax.vecmath.Vector3d;

/**
 * High resolution coordinate object.
 *
 */

/**
 * The HiResCoord object specifies the location of scene
 * components within the Virtual Universe.
 * The coordinates of all scene graph objects are relative to
 * the HiResCoord of the Locale in which they are contained.
 * <P>
 * The HiResCoord defines a point using a set of three
 * high-resolution coordinates, each of which consists of three
 * two's-complement fixed-point numbers.
 * Each high-resolution number consists of 256 total bits with a
 * binary point at bit 128, or between the integers at index
* 3 and 4. A high-resolution coordinate of 1.0 is defined to be exactly
 * 1 meter. This coordinate system is sufficient to describe a
 * universe in excess of several billion light years across, yet
 * still define objects smaller than a proton.
 * <P>
 * Java 3D uses integer arrays of length
 * eight to define or extract a single 256-bit coordinate value.
 * Java 3D interprets the integer at index 0 as the 32
 * most-significant bits and the integer at index 7 as the 32
 * least-significant bits.
 */

public class HiResCoord {
    /**
     * The eight-element array containing the high resolution coordinate's
     * x value.
     */
    int x[];

    /**
     * The eight-element array containing the high resolution coordinate's
     * y value.
     */
    int y[];

    /**
     * The eight-element array containing the high resolution coordinate's
     * z value.
     */
    int z[];

    private double scales[] = { 79228162514264337593543950336.0, // 2^96
            18446744073709551616.0, // 2^64
            4294967296.0, // 2^32
            1.0, // 2^0
            2.3283064365386962890625e-10, // 2^-32
            5.421010862427522170037264004349708557128906250000000000000000e-20, // 2^-64
            1.26217744835361888865876570445245796747713029617443680763244628906250e-29, // 2^-96
            2.938735877055718769921841343055614194546663891930218803771879265696043148636817932128906250e-39 };

    /**
     * Constructs and initializes a new HiResCoord using the values
     * provided in the argument.
     * The HiResCoord represents 768 bits of floating point 3-Space.
     * @param X an eight element array specifying the x position
     * @param Y an eight element array specifying the y position
     * @param Z an eight element array specifying the z position
     */
    public HiResCoord(int[] X, int[] Y, int[] Z) {
        int i;

        this.x = new int[8];
        this.y = new int[8];
        this.z = new int[8];

        for (i = 0; i < 8; i++) {
            this.x[i] = X[i];
            this.y[i] = Y[i];
            this.z[i] = Z[i];
        }

    }

    /**
     * Constructs and initializes a new HiResCoord using the values
     * provided in the argument.
     * The HiResCoord represents 768 bits of floating point 3-Space.
     * @param hc the HiResCoord to copy
     */
    public HiResCoord(HiResCoord hc) {
        this.x = new int[8];
        this.y = new int[8];
        this.z = new int[8];

        this.x[0] = hc.x[0];
        this.y[0] = hc.y[0];
        this.z[0] = hc.z[0];

        this.x[1] = hc.x[1];
        this.y[1] = hc.y[1];
        this.z[1] = hc.z[1];

        this.x[2] = hc.x[2];
        this.y[2] = hc.y[2];
        this.z[2] = hc.z[2];

        this.x[3] = hc.x[3];
        this.y[3] = hc.y[3];
        this.z[3] = hc.z[3];

        this.x[4] = hc.x[4];
        this.y[4] = hc.y[4];
        this.z[4] = hc.z[4];

        this.x[5] = hc.x[5];
        this.y[5] = hc.y[5];
        this.z[5] = hc.z[5];

        this.x[6] = hc.x[6];
        this.y[6] = hc.y[6];
        this.z[6] = hc.z[6];

        this.x[7] = hc.x[7];
        this.y[7] = hc.y[7];
        this.z[7] = hc.z[7];
    }

    /**
     * Constructs and initializes a new HiResCoord located at (0, 0, 0).
     * The HiResCoord represents 768 bits of floating point 3-Space.
     */
    public HiResCoord() {
        this.x = new int[8];
        this.y = new int[8];
        this.z = new int[8];
    }

    /**
     * Sets this HiResCoord to the location specified by the
     * parameters provided.
     * @param X an eight-element array specifying the x position
     * @param Y an eight-element array specifying the y position
     * @param Z an eight-element array specifying the z position
     */
    public void setHiResCoord(int[] X, int[] Y, int[] Z) {
        int i;

        for (i = 0; i < 8; i++) {
            this.x[i] = X[i];
            this.y[i] = Y[i];
            this.z[i] = Z[i];
        }

    }

    /**
     * Sets this HiResCoord to the location specified by the
     * hires provided.
     * @param hires the hires coordinate to copy
     */
    public void setHiResCoord(HiResCoord hires) {
        this.x[0] = hires.x[0];
        this.y[0] = hires.y[0];
        this.z[0] = hires.z[0];

        this.x[1] = hires.x[1];
        this.y[1] = hires.y[1];
        this.z[1] = hires.z[1];

        this.x[2] = hires.x[2];
        this.y[2] = hires.y[2];
        this.z[2] = hires.z[2];

        this.x[3] = hires.x[3];
        this.y[3] = hires.y[3];
        this.z[3] = hires.z[3];

        this.x[4] = hires.x[4];
        this.y[4] = hires.y[4];
        this.z[4] = hires.z[4];

        this.x[5] = hires.x[5];
        this.y[5] = hires.y[5];
        this.z[5] = hires.z[5];

        this.x[6] = hires.x[6];
        this.y[6] = hires.y[6];
        this.z[6] = hires.z[6];

        this.x[7] = hires.x[7];
        this.y[7] = hires.y[7];
        this.z[7] = hires.z[7];
    }

    /**
     * Sets this HiResCoord's X value to that specified by the argument.
     * @param X an eight-element array specifying the x position
     */
    public void setHiResCoordX(int[] X) {
        this.x[0] = X[0];
        this.x[1] = X[1];
        this.x[2] = X[2];
        this.x[3] = X[3];
        this.x[4] = X[4];
        this.x[5] = X[5];
        this.x[6] = X[6];
        this.x[7] = X[7];
    }

    /**
     * Sets this HiResCoord's Y value to that specified by the argument.
     * @param Y an eight-element array specifying the y position
     */
    public void setHiResCoordY(int[] Y) {
        this.y[0] = Y[0];
        this.y[1] = Y[1];
        this.y[2] = Y[2];
        this.y[3] = Y[3];
        this.y[4] = Y[4];
        this.y[5] = Y[5];
        this.y[6] = Y[6];
        this.y[7] = Y[7];
    }

    /**
     * Sets this HiResCoord's Z value to that specified by the argument.
     * @param Z an eight-element array specifying the z position
     */
    public void setHiResCoordZ(int[] Z) {
        this.z[0] = Z[0];
        this.z[1] = Z[1];
        this.z[2] = Z[2];
        this.z[3] = Z[3];
        this.z[4] = Z[4];
        this.z[5] = Z[5];
        this.z[6] = Z[6];
        this.z[7] = Z[7];
    }

    /**
     * Retrieves this HiResCoord's location and saves the coordinates
     * in the specified arrays. The arrays must be large enough
     * to hold all of the ints.
     * @param X an eight element array that will receive the x position
     * @param Y an eight element array that will receive the y position
     * @param Z an eight element array that will receive the z position
     */
    public void getHiResCoord(int[] X, int[] Y, int[] Z) {
        X[0] = this.x[0];
        X[1] = this.x[1];
        X[2] = this.x[2];
        X[3] = this.x[3];
        X[4] = this.x[4];
        X[5] = this.x[5];
        X[6] = this.x[6];
        X[7] = this.x[7];

        Y[0] = this.y[0];
        Y[1] = this.y[1];
        Y[2] = this.y[2];
        Y[3] = this.y[3];
        Y[4] = this.y[4];
        Y[5] = this.y[5];
        Y[6] = this.y[6];
        Y[7] = this.y[7];

        Z[0] = this.z[0];
        Z[1] = this.z[1];
        Z[2] = this.z[2];
        Z[3] = this.z[3];
        Z[4] = this.z[4];
        Z[5] = this.z[5];
        Z[6] = this.z[6];
        Z[7] = this.z[7];
    }

    /**
     * Retrieves this HiResCoord's location and places it into the hires
     * argument.
     * @param hc the hires coordinate that will receive this node's location
     */
    public void getHiResCoord(HiResCoord hc) {
        hc.x[0] = this.x[0];
        hc.x[1] = this.x[1];
        hc.x[2] = this.x[2];
        hc.x[3] = this.x[3];
        hc.x[4] = this.x[4];
        hc.x[5] = this.x[5];
        hc.x[6] = this.x[6];
        hc.x[7] = this.x[7];

        hc.y[0] = this.y[0];
        hc.y[1] = this.y[1];
        hc.y[2] = this.y[2];
        hc.y[3] = this.y[3];
        hc.y[4] = this.y[4];
        hc.y[5] = this.y[5];
        hc.y[6] = this.y[6];
        hc.y[7] = this.y[7];

        hc.z[0] = this.z[0];
        hc.z[1] = this.z[1];
        hc.z[2] = this.z[2];
        hc.z[3] = this.z[3];
        hc.z[4] = this.z[4];
        hc.z[5] = this.z[5];
        hc.z[6] = this.z[6];
        hc.z[7] = this.z[7];
    }

    /**
     * Retrieves this HiResCoord's X value and stores it in the specified
     * array. The array must be large enough to hold all of the ints.
     * @param X an eight-element array that will receive the x position
     */
    public void getHiResCoordX(int[] X) {
        X[0] = this.x[0];
        X[1] = this.x[1];
        X[2] = this.x[2];
        X[3] = this.x[3];
        X[4] = this.x[4];
        X[5] = this.x[5];
        X[6] = this.x[6];
        X[7] = this.x[7];
    }

    /**
     * Retrieves this HiResCoord's Y value and stores it in the specified
     * array. The array must be large enough to hold all of the ints.
     * @param Y an eight-element array that will receive the y position
     */
    public void getHiResCoordY(int[] Y) {
        Y[0] = this.y[0];
        Y[1] = this.y[1];
        Y[2] = this.y[2];
        Y[3] = this.y[3];
        Y[4] = this.y[4];
        Y[5] = this.y[5];
        Y[6] = this.y[6];
        Y[7] = this.y[7];
    }

    /**
     * Retrieves this HiResCoord's Z value and stores it in the specified
     * array. The array must be large enough to hold all of the ints.
     * @param Z an eight-element array that will receive the z position
     */
    public void getHiResCoordZ(int[] Z) {
        Z[0] = this.z[0];
        Z[1] = this.z[1];
        Z[2] = this.z[2];
        Z[3] = this.z[3];
        Z[4] = this.z[4];
        Z[5] = this.z[5];
        Z[6] = this.z[6];
        Z[7] = this.z[7];
    }

    /**
     * Compares the specified HiResCoord to this HiResCoord.
     * @param h1 the second HiResCoord
     * @return true if equal, false if not equal
     */
    public boolean equals(HiResCoord h1) {
        try {
            return ((this.x[0] == h1.x[0]) && (this.x[1] == h1.x[1]) && (this.x[2] == h1.x[2])
                    && (this.x[3] == h1.x[3]) && (this.x[4] == h1.x[4]) && (this.x[5] == h1.x[5])
                    && (this.x[6] == h1.x[6]) && (this.x[7] == h1.x[7]) && (this.y[0] == h1.y[0])
                    && (this.y[1] == h1.y[1]) && (this.y[2] == h1.y[2]) && (this.y[3] == h1.y[3])
                    && (this.y[4] == h1.y[4]) && (this.y[5] == h1.y[5]) && (this.y[6] == h1.y[6])
                    && (this.y[7] == h1.y[7]) && (this.z[0] == h1.z[0]) && (this.z[1] == h1.z[1])
                    && (this.z[2] == h1.z[2]) && (this.z[3] == h1.z[3]) && (this.z[4] == h1.z[4])
                    && (this.z[5] == h1.z[5]) && (this.z[6] == h1.z[6]) && (this.z[7] == h1.z[7]));
        } catch (NullPointerException e2) {
            return false;
        }

    }

    /**
     * Returns true if the Object o1 is of type HiResCoord and all of the
     * data members of o1 are equal to the corresponding data members in
     * this HiResCoord.
     * @param o1 the second HiResCoord
     * @return true if equal, false if not equal
     */
    @Override
    public boolean equals(Object o1) {
        try {
            HiResCoord h1 = (HiResCoord) o1;
            return ((this.x[0] == h1.x[0]) && (this.x[1] == h1.x[1]) && (this.x[2] == h1.x[2])
                    && (this.x[3] == h1.x[3]) && (this.x[4] == h1.x[4]) && (this.x[5] == h1.x[5])
                    && (this.x[6] == h1.x[6]) && (this.x[7] == h1.x[7]) && (this.y[0] == h1.y[0])
                    && (this.y[1] == h1.y[1]) && (this.y[2] == h1.y[2]) && (this.y[3] == h1.y[3])
                    && (this.y[4] == h1.y[4]) && (this.y[5] == h1.y[5]) && (this.y[6] == h1.y[6])
                    && (this.y[7] == h1.y[7]) && (this.z[0] == h1.z[0]) && (this.z[1] == h1.z[1])
                    && (this.z[2] == h1.z[2]) && (this.z[3] == h1.z[3]) && (this.z[4] == h1.z[4])
                    && (this.z[5] == h1.z[5]) && (this.z[6] == h1.z[6]) && (this.z[7] == h1.z[7]));
        } catch (NullPointerException e2) {
            return false;
        } catch (ClassCastException e1) {
            return false;
        }

    }

    /**
     * Adds two HiResCoords placing the results into this HiResCoord.
     * @param h1 the first HiResCoord
     * @param h2 the second HiResCoord
     */
    public void add(HiResCoord h1, HiResCoord h2) {
        // needs to handle carry bits
        // move to long, add, add in carry bit

        hiResAdd(this, h1, h2);

    }

    /**
     * Subtracts two HiResCoords placing the results into this HiResCoord.
     * @param h1 the first HiResCoord
     * @param h2 the second HiResCoord
     */
    public void sub(HiResCoord h1, HiResCoord h2) {
        HiResCoord tmpHc = new HiResCoord();

        // negate via two's complement then add
        //
        hiResNegate(tmpHc, h2);
        hiResAdd(this, h1, tmpHc);

    }

    /**
     * Negates the specified HiResCoords and places the
     * results into this HiResCoord.
     * @param h1 the source HiResCoord
     */
    public void negate(HiResCoord h1) {

        hiResNegate(this, h1);

    }

    /**
     * Negates this HiResCoord
     */
    public void negate() {

        hiResNegate(this, this);

    }

    /**
     * Scales the specified HiResCoords by the specified value and
     * places the results into this HiResCoord.
     * @param scale the amount to scale the specified HiResCoord
     * @param h1 the source HiResCoord
     */
    public void scale(int scale, HiResCoord h1) {
        hiResScale(h1.x, this.x, scale);
        hiResScale(h1.y, this.y, scale);
        hiResScale(h1.z, this.z, scale);
    }

    /**
     * Scales this HiResCoord by the specified value.
     * @param scale the amount to scale the specified HiResCoord
     */
    public void scale(int scale) {
        hiResScale(this.x, this.x, scale);
        hiResScale(this.y, this.y, scale);
        hiResScale(this.z, this.z, scale);
        return;
    }

    /**
     * Subtracts the specified HiResCoord from this HiResCoord
     * placing the difference vector into the specified
     * double-precision vector.
     * @param h1 the HiResCoord to be subtracted from this
     * @param v the vector that will receive the result
     */
    public void difference(HiResCoord h1, Vector3d v) {
        // negate coord via two compliment, add, convert result to double
        // by scaling each bit set appropriately

        hiResDiff(this, h1, v);
        return;
    }

    /**
     * The floating point distance between the specified
     * HiResCoord and this HiResCoord.
     * @param h1 the second HiResCoord
     */
    public double distance(HiResCoord h1) {
        Vector3d diff = new Vector3d();

        hiResDiff(this, h1, diff);

        return (Math.sqrt(diff.x * diff.x + diff.y * diff.y + diff.z * diff.z));
    }

    private void hiResNegate(HiResCoord ho, HiResCoord hi) {

        negateCoord(ho.x, hi.x);
        negateCoord(ho.y, hi.y);
        negateCoord(ho.z, hi.z);

        return;
    }

    private void negateCoord(int cout[], int cin[]) {
        int i;

        for (i = 0; i < 8; i++) {
            cout[i] = ~cin[i]; // take compliment of each
        }

        for (i = 7; i >= 0; i--) { // add one
            if (cout[i] == 0xffffffff) {
                cout[i] = 0;
            } else {
                cout[i] += 1;
                break;
            }
        }
        return;
    }

    private void hiResAdd(HiResCoord ho, HiResCoord h1, HiResCoord h2) {
        int i;
        long tmp1, tmp2, carry;
        long signMask = Integer.MAX_VALUE;
        long signBit = 1;
        signBit = signBit << 31;
        long carryMask = 0x7fffffff;
        carryMask = carryMask << 1;
        carryMask += 1;

        carry = 0;
        for (i = 7; i > 0; i--) {
            tmp1 = 0;
            tmp1 = signMask & h1.x[i]; // mask off sign bit so will not get put in msb
            if (h1.x[i] < 0)
                tmp1 |= signBit; // add sign bit back

            tmp2 = 0;
            tmp2 = signMask & h2.x[i]; // mask off sign bit so will not get put in msb
            if (h2.x[i] < 0)
                tmp2 |= signBit; // add sign bit back

            tmp2 = tmp2 + tmp1 + carry;
            carry = tmp2 >> 32; // get carry bits for next operation
            ho.x[i] = (int) (tmp2 & carryMask); // mask off high bits
        }
        ho.x[0] = h1.x[0] + h2.x[0] + (int) carry;

        carry = 0;
        for (i = 7; i > 0; i--) {
            tmp1 = 0;
            tmp1 = signMask & h1.y[i]; // mask off sign bit so will not get put in msb
            if (h1.y[i] < 0)
                tmp1 |= signBit; // add sign bit back

            tmp2 = 0;
            tmp2 = signMask & h2.y[i]; // mask off sign bit so will not get put in msb
            if (h2.y[i] < 0)
                tmp2 |= signBit; // add sign bit back

            tmp2 = tmp2 + tmp1 + carry;
            carry = tmp2 >> 32; // get carry bits for next operation
            ho.y[i] = (int) (tmp2 & carryMask); // mask off high bits
        }
        ho.y[0] = h1.y[0] + h2.y[0] + (int) carry;

        carry = 0;
        for (i = 7; i > 0; i--) {
            tmp1 = 0;
            tmp1 = signMask & h1.z[i]; // mask off sign bit so will not get put in msb
            if (h1.z[i] < 0)
                tmp1 |= signBit; // add sign bit back

            tmp2 = 0;
            tmp2 = signMask & h2.z[i]; // mask off sign bit so will not get put in msb
            if (h2.z[i] < 0)
                tmp2 |= signBit; // add sign bit back

            tmp2 = tmp2 + tmp1 + carry;
            carry = tmp2 >> 32; // get carry bits for next operation
            ho.z[i] = (int) (tmp2 & carryMask); // mask off high bits
        }
        ho.z[0] = h1.z[0] + h2.z[0] + (int) carry;
        return;
    }

    private void hiResScale(int tin[], int tout[], double scale) {
        int i;
        long tmp, carry;
        int signMask = Integer.MAX_VALUE;
        long carryMask = 0x7fffffff;
        carryMask = carryMask << 1;
        carryMask += 1;
        long signBit = 1;
        signBit = signBit << 31;

        carry = 0;
        for (i = 7; i > 0; i--) {
            tmp = 0;
            tmp = (long) (signMask & tin[i]); // mask off sign bit
            if (tin[i] < 0)
                tmp |= signBit; // add sign bit back
            tmp = (long) (tmp * scale + carry);
            carry = tmp >> 32; // get carry bits for next operation
            tout[i] = (int) (tmp & carryMask); // mask off high bits
        }
        tout[0] = (int) (tin[0] * scale + carry);
        return;
    }

    private void hiResDiff(HiResCoord h1, HiResCoord h2, Vector3d diff) {
        int i;
        HiResCoord diffHi = new HiResCoord();
        long value;
        int coordSpace[] = new int[8];
        int[] tempCoord;
        int signMask = Integer.MAX_VALUE;
        long signBit = 1;
        signBit = signBit << 31;

        // negate via two's complement then add
        //
        hiResNegate(diffHi, h2);
        hiResAdd(diffHi, h1, diffHi);

        if (diffHi.x[0] < 0) {
            tempCoord = coordSpace;
            negateCoord(tempCoord, diffHi.x);
        } else {
            tempCoord = diffHi.x;
        }
        diff.x = 0;
        for (i = 7; i > 0; i--) {
            value = (long) (tempCoord[i] & signMask);
            if (tempCoord[i] < 0)
                value |= signBit;
            diff.x += (double) (scales[i] * value);
        }
        diff.x += scales[0] * tempCoord[0];
        if (diffHi.x[0] < 0)
            diff.x = -diff.x;

        if (diffHi.y[0] < 0) {
            tempCoord = coordSpace;
            negateCoord(tempCoord, diffHi.y);
        } else {
            tempCoord = diffHi.y;
        }
        diff.y = 0;
        for (i = 7; i > 0; i--) {
            value = (long) (tempCoord[i] & signMask);
            if (tempCoord[i] < 0)
                value |= signBit;
            diff.y += scales[i] * value;
        }
        diff.y += scales[0] * tempCoord[0];
        if (diffHi.y[0] < 0)
            diff.y = -diff.y;

        if (diffHi.z[0] < 0) {
            tempCoord = coordSpace;
            negateCoord(tempCoord, diffHi.z);
        } else {
            tempCoord = diffHi.z;
        }
        diff.z = 0;
        for (i = 7; i > 0; i--) {
            value = (long) (tempCoord[i] & signMask);
            if (tempCoord[i] < 0)
                value |= signBit;
            diff.z += scales[i] * value;
        }
        diff.z += scales[0] * tempCoord[0];
        if (diffHi.z[0] < 0)
            diff.z = -diff.z;
        return;
    }
}