javax.media.j3d.HiResCoord Maven / Gradle / Ivy
/*
* 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.
*
* 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.
*
* 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;
}
}