diff options
Diffstat (limited to 'src/classes/share/com/sun/j3d/internal')
10 files changed, 2481 insertions, 0 deletions
diff --git a/src/classes/share/com/sun/j3d/internal/BufferWrapper.java b/src/classes/share/com/sun/j3d/internal/BufferWrapper.java new file mode 100755 index 0000000..40370bc --- /dev/null +++ b/src/classes/share/com/sun/j3d/internal/BufferWrapper.java @@ -0,0 +1,186 @@ +/* + * $RCSfile$ + * + * Copyright (c) 2004 Sun Microsystems, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any + * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND + * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY + * EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL + * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF + * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS + * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR + * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, + * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND + * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR + * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed, licensed or + * intended for use in the design, construction, operation or + * maintenance of any nuclear facility. + * + * $Revision$ + * $Date$ + * $State$ + */ + +package com.sun.j3d.internal; + +import javax.media.j3d.J3DBuffer; +import java.nio.Buffer; + +/** + * NIO Buffers are new in Java 1.4 but we need to run on 1.3 + * as well, so this class was created to hide the NIO classes + * from non-1.4 Java 3D users. + * + * <p> + * NOTE: We no longer need to support JDK 1.3 as of the Java 3D 1.3.2 + * community source release on java.net. We should be able to get rid + * of this class. + */ + +public abstract class BufferWrapper { + + /** + * Value returned from getBufferType(), this indicates + * that the BufferWrapper contains a null buffer. + */ + public static final int TYPE_NULL = 0; + + /** + * Value returned from getBufferType(), this indicates + * that the BufferWrapper does not hold data of type + * byte, float, or double. + */ + public static final int TYPE_UNKNOWN = 1; + + /** + * Value returned from getBufferType(), this indicates + * that the BufferWrapper contains a java.nio.ByteBuffer. + */ + public static final int TYPE_BYTE = 2; + + /** + * Value returned from getBufferType(), this indicates + * that the BufferWrapper contains a java.nio.FloatBuffer. + */ + public static final int TYPE_FLOAT = 3; + + /** + * Value returned from getBufferType(), this indicates + * that the BufferWrapper contains a java.nio.DoubleBuffer. + */ + public static final int TYPE_DOUBLE = 4; + + /** + * Never used - this class is abstract. + */ + public BufferWrapper() { + } + + /** + * Must be implemented by sublasses. + */ + abstract Buffer getBuffer(); + + /** + * @return Buffer as object of type Object. + */ + public Object getBufferAsObject() { + return getBuffer(); + } + + // Wrapper for all relevant Buffer methods. + + /** + * @return This buffer's capacity (set at initialization in + * allocateDirect() ). + * @see ByteBufferWrapper#allocateDirect + */ + public int capacity() { + return getBuffer().capacity(); + } + + /** + * @return This buffer's limit. + */ + public int limit() { + return getBuffer().limit(); + } + + /** + * @return This buffer's position. + */ + public int position() { + return getBuffer().position(); + } + + /** + * Sets this buffer's position. + * @return This buffer. + */ + public BufferWrapper position(int newPosition){ + getBuffer().position(newPosition); + return this; + } + + /** + * Resets this buffer's position to the previously marked + * position. + * @return This buffer. + */ + public BufferWrapper rewind() { + getBuffer().rewind(); + return this; + } + + /** + * @return An integer indicating the type of data held in + * this buffer. + * @see #TYPE_NULL + * @see #TYPE_BYTE + * @see #TYPE_FLOAT + * @see #TYPE_DOUBLE + * @see #TYPE_UNKNOWN + */ + public static int getBufferType(J3DBuffer b) { + int bufferType; + Buffer buffer = b.getBuffer(); + + if (buffer == null) { + bufferType = TYPE_NULL; + } + else if (buffer instanceof java.nio.ByteBuffer) { + bufferType = TYPE_BYTE; + } + else if (buffer instanceof java.nio.FloatBuffer) { + bufferType = TYPE_FLOAT; + } + else if (buffer instanceof java.nio.DoubleBuffer) { + bufferType = TYPE_DOUBLE; + } + else { + bufferType = TYPE_UNKNOWN; + } + return bufferType; + } +} diff --git a/src/classes/share/com/sun/j3d/internal/ByteBufferWrapper.java b/src/classes/share/com/sun/j3d/internal/ByteBufferWrapper.java new file mode 100755 index 0000000..61f2c58 --- /dev/null +++ b/src/classes/share/com/sun/j3d/internal/ByteBufferWrapper.java @@ -0,0 +1,197 @@ +/* + * $RCSfile$ + * + * Copyright (c) 2004 Sun Microsystems, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any + * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND + * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY + * EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL + * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF + * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS + * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR + * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, + * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND + * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR + * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed, licensed or + * intended for use in the design, construction, operation or + * maintenance of any nuclear facility. + * + * $Revision$ + * $Date$ + * $State$ + */ + +package com.sun.j3d.internal; + +import javax.media.j3d.J3DBuffer; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +/** + * NIO Buffers are new in Java 1.4 but we need to run on 1.3 + * as well, so this class was created to hide the NIO classes + * from non-1.4 Java 3D users. + * + * <p> + * NOTE: We no longer need to support JDK 1.3 as of the Java 3D 1.3.2 + * community source release on java.net. We should be able to get rid + * of this class. + */ + +public class ByteBufferWrapper extends BufferWrapper { + + private ByteBuffer buffer = null; + + /** + * Constructor initializes buffer with a + * java.nio.ByteBuffer object. + */ + public ByteBufferWrapper(ByteBuffer buffer) { + this.buffer = buffer; + } + + /** + * Constructor initializes buffer with a + * javax.media.j3d.J3DBuffer object. + */ + public ByteBufferWrapper(J3DBuffer b) { + buffer = (ByteBuffer)(b.getBuffer()); + } + + /** + * Allocate a direct ByteBuffer with the given capacity. + * @return New ByteBufferWrapper containing the + * new buffer. + */ + public static ByteBufferWrapper allocateDirect(int capacity) { + ByteBuffer bb = ByteBuffer.allocateDirect(capacity); + return new ByteBufferWrapper(bb); + } + + /** + * Returns the java.nio.Buffer contained within this + * ByteBufferWrapper. + */ + public java.nio.Buffer getBuffer() { + return this.buffer; + } + + // Wrapper for all relevant ByteBuffer methods. + + /** + * @return A boolean indicating whether the java.nio.Buffer + * object contained within this ByteBuffer is direct or + * indirect. + */ + public boolean isDirect() { + return buffer.isDirect(); + } + + /** + * Reads the byte at this buffer's current position, + * and then increments the position. + */ + public byte get() { + return buffer.get(); + } + + /** + * Reads the byte at the given offset into the buffer. + */ + public byte get(int index) { + return buffer.get(index); + } + + /** + * Bulk <i>get</i> method. Transfers <code>dst.length</code> + * bytes from + * the buffer to the destination array and increments the + * buffer's position by <code>dst.length</code>. + */ + public ByteBufferWrapper get(byte[] dst) { + buffer.get(dst); + return this; + } + + /** + * Bulk <i>get</i> method. Transfers <i>length</i> bytes + * from the buffer starting at position <i>offset</i> into + * the destination array. + */ + public ByteBufferWrapper get(byte[] dst, int offset, int length) { + buffer.get(dst, offset, length); + return this; + } + + /** + * Returns the byte order of this buffer. + */ + public ByteOrderWrapper order() { + if ( buffer.order()==ByteOrder.BIG_ENDIAN ) return ByteOrderWrapper.BIG_ENDIAN; + else return ByteOrderWrapper.LITTLE_ENDIAN; + } + + /** + * Modifies this buffer's byte order. + */ + public ByteBufferWrapper order(ByteOrderWrapper bo) + { + if ( bo == ByteOrderWrapper.BIG_ENDIAN ) buffer.order( ByteOrder.BIG_ENDIAN ); + else buffer.order( ByteOrder.LITTLE_ENDIAN ); + return this; + } + + /** + * Creates a view of this ByteBufferWrapper as a + * FloatBufferWrapper. Uses the correct + */ + public FloatBufferWrapper asFloatBuffer() { + return new FloatBufferWrapper( buffer.asFloatBuffer() ); + } + + /** + * Creates a view of this ByteBufferWrapper as a + * DoubleBufferWrapper. + */ + public DoubleBufferWrapper asDoubleBuffer() { + return new DoubleBufferWrapper( buffer.asDoubleBuffer() ); + } + + /** + * Bulk <i>put</i> method. Transfers <code>src.length</code> + * bytes into the buffer at the current position. + */ + public ByteBufferWrapper put(byte[] src) { + buffer.put(src); + return this; + } + + /** + * Creates and returns a J3DBuffer object containing the + * buffer in this ByteBufferWrapper object. + */ + public J3DBuffer getJ3DBuffer() { + return new J3DBuffer( buffer ); + } +} diff --git a/src/classes/share/com/sun/j3d/internal/ByteOrderWrapper.java b/src/classes/share/com/sun/j3d/internal/ByteOrderWrapper.java new file mode 100755 index 0000000..bfaa373 --- /dev/null +++ b/src/classes/share/com/sun/j3d/internal/ByteOrderWrapper.java @@ -0,0 +1,101 @@ +/* + * $RCSfile$ + * + * Copyright (c) 2004 Sun Microsystems, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any + * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND + * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY + * EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL + * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF + * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS + * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR + * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, + * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND + * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR + * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed, licensed or + * intended for use in the design, construction, operation or + * maintenance of any nuclear facility. + * + * $Revision$ + * $Date$ + * $State$ + */ + +package com.sun.j3d.internal; + +import javax.media.j3d.J3DBuffer; +import java.nio.Buffer; +import java.nio.ByteOrder; + +/** + * NIO Buffers are new in Java 1.4 but we need to run on 1.3 + * as well, so this class was created to hide the NIO classes + * from non-1.4 Java 3D users. + * + * <p> + * Typesafe enum for byte orders. + * + * <p> + * NOTE: We no longer need to support JDK 1.3 as of the Java 3D 1.3.2 + * community source release on java.net. We should be able to get rid + * of this class. + */ + +public final class ByteOrderWrapper { + + private final String enum_name; + + /** + * Private constructor is only called from static initializers + * in this class. + */ + private ByteOrderWrapper(String name) { + enum_name = name; + } + + /** + * Static initializer creates object of this type. + */ + public static final ByteOrderWrapper BIG_ENDIAN = + new ByteOrderWrapper("BIG_ENDIAN"); + + /** + * Static initializer creates object of this type. + */ + public static final ByteOrderWrapper LITTLE_ENDIAN = + new ByteOrderWrapper("LITTLE_ENDIAN"); + + public String toString() { + return enum_name; + } + + /** + * Returns the native byte order of the host system. + */ + public static ByteOrderWrapper nativeOrder() { + if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN) { + return ByteOrderWrapper.BIG_ENDIAN; + } else return ByteOrderWrapper.LITTLE_ENDIAN; + } +} diff --git a/src/classes/share/com/sun/j3d/internal/Distance.java b/src/classes/share/com/sun/j3d/internal/Distance.java new file mode 100644 index 0000000..f49659f --- /dev/null +++ b/src/classes/share/com/sun/j3d/internal/Distance.java @@ -0,0 +1,1096 @@ +/* + * $RCSfile$ + * + * Copyright (c) 2004 Sun Microsystems, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any + * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND + * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY + * EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL + * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF + * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS + * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR + * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, + * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND + * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR + * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed, licensed or + * intended for use in the design, construction, operation or + * maintenance of any nuclear facility. + * + * $Revision$ + * $Date$ + * $State$ + */ + +// -------------------------------------------------- +// +// Distance routines, ported from: +// +// Magic Software, Inc. +// http://www.magic-software.com +// http://www.wild-magic.com +// Copyright (c) 2004. All Rights Reserved +// +// The Wild Magic Library (WML) source code is supplied under the terms of +// the license agreement http://www.magic-software.com/License/WildMagic.pdf +// and may not be copied or disclosed except in accordance with the terms of +// that agreement. +// +// -------------------------------------------------- + +package com.sun.j3d.internal; + +import javax.vecmath.*; + +/** + * Utility class used to calculate distance. Contains static methods + * used by picking method to determine intersections. + */ + +public class Distance { + /* Threshold factor to determine if two lines are parallel */ + static final double FUZZ = 1E-5; + + /* Utility method, for easy switch between distance and squared distance */ + private static final double DIST (double in) { + // return Math.sqrt (Math.abs (in)); + return Math.abs (in); + } + + /** + * Minimum ray to segment distance. + * + * @param rayorig Origin of the ray + * @param raydir Direction of the ray + * @param segstart Segment start point + * @param segend Segment end point + * @return the square of the minimum distance from the ray to the segment + */ + static public double rayToSegment (Point3d rayorig, + Vector3d raydir, + Point3d segstart, + Point3d segend) { + return rayToSegment (rayorig, raydir, segstart, segend, null, null, null); + } + + /** + * Minimum ray to segment distance. Returns the square of the distance. + * + * @param rayorig Origin of the ray + * + * @param raydir Direction of the ray + * + * @param segstart Segment start point + * + * @param segend Segment end point + * + * @param rayint If non-null, will be filled with the coordinates of + * the point corresponding to the minimum distance on the ray. + * + * @param segint If non-null, will be filled with the coordinates of + * the point corresponding to the minimum distance on the segment. + * + * @param param An array of two doubles, will be filled with the + * parametric factors used to find the point of shortest distance on + * each primitive (ray = O +sD, with O=origin and + * D=direction). param[0] will contain the parameter for the ray, + * and param[1] the parameter for the segment. + * + * @return the square of the minimum distance from the ray to the + * segment + */ + static public double rayToSegment (Point3d rayorig, + Vector3d raydir, + Point3d segstart, + Point3d segend, + Point3d rayint, + Point3d segint, + double[] param) { + double s, t; + + Vector3d diff = new Vector3d(); + diff.sub (rayorig,segstart); + Vector3d segdir = new Vector3d(); + segdir.sub (segend, segstart); + /* + System.out.println (rayorig + "\n" + raydir + "\n" + segstart + "\n" + + segdir); + */ + double A = raydir.dot (raydir);//Dot(ray.m,ray.m); + double B = -raydir.dot (segdir);//-Dot(ray.m,seg.m); + double C = segdir.dot (segdir);//Dot(seg.m,seg.m); + double D = raydir.dot (diff);//Dot(ray.m,diff); + double E; // -Dot(seg.m,diff), defer until needed + double F = diff.dot (diff);//Dot(diff,diff); + double det = Math.abs(A*C-B*B); // A*C-B*B = |Cross(M0,M1)|^2 >= 0 + + double tmp; + + if (det >= FUZZ) { + // ray and segment are not parallel + E = -segdir.dot (diff);//-Dot(seg.m,diff); + s = B*E-C*D; + t = B*D-A*E; + + if (s >= 0) { + if (t >= 0) { + if (t <= det) { // region 0 + // minimum at interior points of ray and segment + double invDet = 1.0f/det; + s *= invDet; + t *= invDet; + if (rayint!=null) rayint.scaleAdd (s, raydir, rayorig); + if (segint!=null) segint.scaleAdd (t, segdir, segstart); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(s*(A*s+B*t+2*D)+t*(B*s+C*t+2*E)+F); + } + else { // region 1 + + t = 1; + if (D >= 0) { + s = 0; + if (rayint!=null) rayint.set (rayorig); + if (segint!=null) segint.set (segend); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(C+2*E+F); + } + else { + s = -D/A; + if (rayint!=null) rayint.scaleAdd (s, raydir, rayorig); + if (segint!=null) segint.set (segend); + if (param != null) { param[0] = s; param[1] = t; } + return DIST((D+2*B)*s+C+2*E+F); + } + } + } + else { // region 5 + t = 0; + if (D >= 0) { + s = 0; + if (rayint != null) rayint.set (rayorig); + if (segint != null) segint.set (segstart); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(F); + } + else { + s = -D/A; + if (rayint != null) rayint.scaleAdd (s, raydir, rayorig); + if (segint != null) segint.set (segstart); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(D*s+F); + } + } + } + else { + if (t <= 0) { // region 4 + if (D < 0) { + s = -D/A; + t = 0; + if (rayint != null) rayint.scaleAdd (s, raydir, rayorig); + if (segint != null) segint.set (segstart); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(D*s+F); + } + else { + s = 0; + if (E >= 0) { + t = 0; + if (rayint != null) rayint.set (rayorig); + if (segint != null) segint.set (segstart); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(F); + } + else if (-E >= C) { + t = 1; + if (rayint != null) rayint.set (rayorig); + if (segint != null) segint.set (segend); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(C+2*E+F); + } + else { + t = -E/C; + if (rayint != null) rayint.set (rayorig); + if (segint != null) segint.scaleAdd (t, segdir, segstart); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(E*t+F); + } + } + } + else if (t <= det) { // region 3 + s = 0; + if (E >= 0) { + t = 0; + if (rayint != null) rayint.set (rayorig); + if (segint != null) segint.set (segstart); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(F); + } + else if (-E >= C) { + t = 1; + if (rayint != null) rayint.set (rayorig); + if (segint != null) segint.set (segend); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(C+2*E+F); + } + else { + t = -E/C; + if (rayint != null) rayint.set (rayorig); + if (segint != null) segint.scaleAdd (t, segdir, segstart); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(E*t+F); + } + } + else { // region 2 + tmp = B+D; + if (tmp < 0) { + s = -tmp/A; + t = 1; + if (rayint != null) rayint.scaleAdd (s, raydir, rayorig); + if (segint != null) segint.set (segend); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(tmp*s+C+2*E+F); + } + else { + s = 0; + if (E >= 0) { + t = 0; + if (rayint != null) rayint.set (rayorig); + if (segint != null) segint.set (segstart); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(F); + } + else if (-E >= C) { + t = 1; + if (rayint != null) rayint.set (rayorig); + if (segint != null) segint.set (segend); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(C+2*E+F); + } + else { + t = -E/C; + if (rayint != null) rayint.set (rayorig); + if (segint != null) segint.scaleAdd (t, segdir, segstart); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(E*t+F); + } + } + } + } + } + else { + // ray and segment are parallel + if (B > 0) { + // opposite direction vectors + t = 0; + if (D >= 0) { + s = 0; + if (rayint != null) rayint.set (rayorig); + if (segint != null) segint.set (segstart); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(F); + } + else { + s = -D/A; + if (rayint != null) rayint.scaleAdd (s, raydir, rayorig); + if (segint != null) segint.set (segstart); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(D*s+F); + } + } + else { + // same direction vectors + E = segdir.dot (diff);//-Dot(seg.m,diff); + t = 1; + tmp = B+D; + if (tmp >= 0) { + s = 0; + if (rayint != null) rayint.set (rayorig); + if (segint != null) segint.set (segend); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(C+2*E+F); + } + else { + s = -tmp/A; + if (rayint != null) rayint.scaleAdd (s, raydir, rayorig); + if (segint != null) segint.set (segend); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(tmp*s+C+2*E+F); + } + } + } + } + + /** + * Minimum ray to ray distance. Returns the square of the distance. + * + * @param ray0orig Origin of ray 0 + * @param ray0dir Direction of ray 0 + * @param ray1orig Origin of ray 1 + * @param ray1dir Direction of ray 1 + * @return the square of the minimum distance from the ray to the segment + */ + static public double rayToRay (Point3d ray0orig, + Vector3d ray0dir, + Point3d ray1orig, + Vector3d ray1dir) { + return rayToRay (ray0orig, ray0dir, ray1orig, ray1dir, null, null, null); + } + + /** + * Minimum ray to ray distance. Returns the square of the distance. + * + * @param ray0orig Origin of ray 0 + * + * @param ray0dir Direction of ray 0 + * + * @param ray1orig Origin of ray 1 + * + * @param ray1dir Direction of ray 1 + * + * @param ray0int If non-null, will be filled with the coordinates + * of the point corresponding to the minimum distance on ray 0. + * + * @param ray1int If non-null, will be filled with the coordinates + * of the point corresponding to the minimum distance on ray 1. + * + * @param param An array of two doubles, will be filled with the + * parametric factors used to find the point of shortest distance on + * each primitive (ray = O +sD, with O=origin and + * D=direction). param[0] will contain the parameter for ray0, and + * param[1] the parameter for ray1. + * + * @return the square of the minimum distance from the ray to the segment + */ + static public double rayToRay (Point3d ray0orig, + Vector3d ray0dir, + Point3d ray1orig, + Vector3d ray1dir, + Point3d ray0int, + Point3d ray1int, + double[] param) { + + double s, t; + + Vector3d diff = new Vector3d(); + diff.sub (ray0orig, ray1orig); + + double A = ray0dir.dot (ray0dir); //Dot(ray0.m,ray0.m); + double B = -ray0dir.dot (ray1dir); //-Dot(ray0.m,ray1.m); + double C = ray1dir.dot (ray1dir); //Dot(ray1.m,ray1.m); + double D = ray0dir.dot (diff); //Dot(ray0.m,diff); + double E; // -Dot(ray1.m,diff), defer until needed + double F = diff.dot (diff); //Dot(diff,diff); + double det = Math.abs(A*C-B*B); // A*C-B*B = |Cross(M0,M1)|^2 >= 0 + /* + System.out.println (ray0orig + "\n" + ray0dir + "\n" + + ray1orig + "\n" + ray1dir); + System.out.println (A + " " + B + " " + C + " " + D + " " + F + " " + det); + */ + if (det >= FUZZ) { + // rays are not parallel + E = -ray1dir.dot (diff); //-Dot(ray1.m,diff); + s = B*E-C*D; + t = B*D-A*E; + + if (s >= 0) { + if (t >= 0) { // region 0 (interior) + // minimum at two interior points of rays + double invDet = 1.0f/det; + s *= invDet; + t *= invDet; + if (ray0int != null) ray0int.scaleAdd (s, ray0dir, ray0orig); + if (ray1int != null) ray1int.scaleAdd (t, ray1dir, ray1orig); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(s*(A*s+B*t+2*D)+t*(B*s+C*t+2*E)+F); + } + else { // region 3 (side) + t = 0; + if (D >= 0) { + s = 0; + if (ray0int != null) ray0int.set (ray0orig); + if (ray1int != null) ray1int.set (ray1orig); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(F); + } + else { + s = -D/A; + if (ray0int != null) ray0int.scaleAdd (s, ray0dir, ray0orig); + if (ray1int != null) ray1int.set (ray1orig); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(D*s+F); + } + } + } + else { + if (t >= 0) { // region 1 (side) + s = 0; + if (E >= 0) { + t = 0; + if (ray0int != null) ray0int.set (ray0orig); + if (ray1int != null) ray1int.set (ray1orig); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(F); + } + else { + t = -E/C; + if (ray0int != null) ray0int.set (ray0orig); + if (ray1int != null) ray1int.scaleAdd (t, ray1dir, ray1orig); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(E*t+F); + } + } + else { // region 2 (corner) + if (D < 0) { + s = -D/A; + t = 0; + if (ray0int != null) ray0int.scaleAdd (s, ray0dir, ray0orig); + if (ray1int != null) ray1int.set (ray1orig); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(D*s+F); + } + else { + s = 0; + if (E >= 0) { + t = 0; + if (ray0int != null) ray0int.set (ray0orig); + if (ray1int != null) ray1int.set (ray1orig); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(F); + } + else { + t = -E/C; + if (ray0int != null) ray0int.set (ray0orig); + if (ray1int != null) ray1int.scaleAdd (t, ray1dir, ray1orig); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(E*t+F); + } + } + } + } + } + else { + // rays are parallel + if (B > 0) { + // opposite direction vectors + t = 0; + if (D >= 0) { + s = 0; + if (ray0int != null) ray0int.set (ray0orig); + if (ray1int != null) ray1int.set (ray1orig); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(F); + } + else { + s = -D/A; + if (ray0int != null) ray0int.scaleAdd (s, ray0dir, ray0orig); + if (ray1int != null) ray1int.set (ray1orig); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(D*s+F); + } + } + else { + // same direction vectors + if (D >= 0) { + E = ray1dir.dot (diff); //-Dot(ray1.m,diff); + s = 0; + t = -E/C; + if (ray0int != null) ray0int.set (ray0orig); + if (ray1int != null) ray1int.scaleAdd (t, ray1dir, ray1orig); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(E*t+F); + } + else { + s = -D/A; + t = 0; + if (ray0int != null) ray0int.scaleAdd (s, ray0dir, ray0orig); + if (ray1int != null) ray1int.set (ray1orig); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(D*s+F); + } + } + } + } + + /** + * Minimum pt to ray distance. Returns the square of the distance. + * @param pt The point + * @param rayorig Origin of the ray + * @param raydir Direction of the ray + * @return the square of the minimum distance between the point and the ray + */ + static public double pointToRay (Point3d pt, + Point3d rayorig, + Vector3d raydir) { + return pointToRay (pt, rayorig, raydir, null, null); + } + + /** + * Minimum pt to ray distance. Returns the square of the distance. + * + * @param pt The point + * + * @param rayorig Origin of the ray + * + * @param raydir Direction of the ray + * + * @param rayint If non-null, will be filled with the coordinates of + * the point corresponding to the minimum distance on the ray. + * + * @param param An array of one double, will be filled with the + * parametric factors used to find the point of shortest distance on + * the ray (ray = O +sD, with O=origin and D=direction). param[0] + * will contain the parameter for the ray. + * + * @return the square of the minimum distance between the point and the ray + */ + static public double pointToRay (Point3d pt, + Point3d rayorig, + Vector3d raydir, + Point3d rayint, + double[] param) { + + double t; + + Vector3d diff = new Vector3d(); + diff.sub (pt, rayorig); + t = raydir.dot (diff); //Dot(ray.m,diff); + + if (t <= 0.0) { + t = 0.0; // behind start of ray + if (rayint != null) rayint.set (rayorig); + if (param != null) { param[0] = t; } + } else { + t /= raydir.dot (raydir); //Dot(ray.m,ray.m); + diff.scaleAdd (-t, raydir, diff); // diff = diff - t*ray.m; + if (rayint != null) rayint.scaleAdd (t, raydir, rayorig); + if (param != null) { param[0] = t; } + } + return diff.dot(diff); + } + + /** + * Minimum pt to segment distance. Returns the square of the distance. + */ + static public double pointToSegment (Point3d pt, + Point3d segstart, + Point3d segend) { + return pointToSegment (pt, segstart, segend, null, null); + } + + /** + * Minimum pt to segment distance. Returns the square of the distance. + */ + static public double pointToSegment (Point3d pt, + Point3d segstart, + Point3d segend, + Point3d segint, + double[] param) { + + double t; + Vector3d segdir = new Vector3d (); + segdir.sub (segend, segstart); + Vector3d diff = new Vector3d(); + diff.sub (pt,segstart); + t = segdir.dot (diff); //Dot(seg.m,diff); + + if (t <= 0.0) { + t = 0.0f; + if (segint != null) segint.set (segstart); + if (param != null) { param[0] = t; } + } + else { + double mDotm = segdir.dot (segdir); //Dot(seg.m,seg.m); + if (t >= mDotm) { + t = 1.0f; + diff.sub (segdir); + if (segint != null) segint.set (segend); + if (param != null) { param[0] = t; } + } + else { + t /= mDotm; + diff.scaleAdd (-t, segdir, diff); //diff = diff - t*seg.m; + if (segint != null) segint.scaleAdd (t, segdir, segstart); + if (param != null) { param[0] = t; } + } + } + return diff.dot(diff); //DIST(diff); + } + + + /** + * Minimum segment to segment distance. Returns the square of the distance. + * @param seg0start the start of segment 0 + * @param seg0end the end of segment 0 + * @param seg1start the start of segment 1 + * @param seg1end the end of segment 1 + * @return the square of the minimum distance from segment to segment + */ + static public double segmentToSegment (Point3d seg0start, + Point3d seg0end, + Point3d seg1start, + Point3d seg1end) { + return segmentToSegment (seg0start, seg0end, seg1start, seg1end, + null, null, null); + } + + /** + * Minimum segment to segment distance. Returns the square of the distance. + * + * @param seg0start the start of segment 0 + * + * @param seg0end the end of segment 0 + * + * @param seg1start the start of segment 1 + * + * @param seg1end the end of segment 1 + * + * @param seg0int If non-null, will be filled with the coordinates + * of the point corresponding to the minimum distance on segment 0. + * + * @param seg1int If non-null, will be filled with the coordinates + * of the point corresponding to the minimum distance on segment 1. + * + * @param param An array of two doubles, will be filled with the + * parametric factors used to find the point of shortest distance on + * each primitive (segment = O +sD, with O=origin and + * D=direction). param[0] will contain the parameter for segment 0, + * and param[1] the parameter for segment 1. + * + * @return the square of the minimum distance from segment to segment + */ + static public double segmentToSegment (Point3d seg0start, + Point3d seg0end, + Point3d seg1start, + Point3d seg1end, + Point3d seg0int, + Point3d seg1int, + double[] param) { + double s,t; + + Vector3d diff = new Vector3d(); + diff.sub (seg0start,seg1start); + + Vector3d seg0dir = new Vector3d(); + seg0dir.sub (seg0end, seg0start); + Vector3d seg1dir = new Vector3d(); + seg1dir.sub (seg1end, seg1start); + + double A = seg0dir.dot (seg0dir); //Dot(seg0dir,seg0dir); + double B = -seg0dir.dot (seg1dir); //-Dot(seg0dir,seg1dir); + double C = seg1dir.dot (seg1dir); //Dot(seg1dir,seg1dir); + double D = seg0dir.dot (diff); //Dot(seg0dir,diff); + double E; // -Dot(seg1dir,diff), defer until needed + double F = diff.dot (diff); //Dot(diff,diff); + double det = Math.abs(A*C-B*B); // A*C-B*B = |Cross(M0,M1)|^2 >= 0 + + double tmp; + + if (det >= FUZZ) { + // line segments are not parallel + E = -seg1dir.dot (diff); //-Dot(seg1dir,diff); + s = B*E-C*D; + t = B*D-A*E; + + if (s >= 0) { + if (s <= det) { + if (t >= 0) { + if (t <= det) { // region 0 (interior) + // minimum at two interior points of 3D lines + double invDet = 1.0f/det; + s *= invDet; + t *= invDet; + if (seg0int != null) seg0int.scaleAdd (s, seg0dir, seg0start); + if (seg1int != null) seg1int.scaleAdd (t, seg1dir, seg1start); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(s*(A*s+B*t+2*D)+t*(B*s+C*t+2*E)+F); + } + else { // region 3 (side) + t = 1; + tmp = B+D; + if (tmp >= 0) { + s = 0; + if (seg0int != null) seg0int.set (seg0start); + if (seg1int != null) seg1int.set (seg1end); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(C+2*E+F); + } + else if (-tmp >= A) { + s = 1; + if (seg0int != null) seg0int.set (seg0end); + if (seg1int != null) seg1int.set (seg1end); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(A+C+F+2*(E+tmp)); + } + else { + s = -tmp/A; + if (seg0int != null) seg0int.scaleAdd (s, seg0dir, seg0start); + if (seg1int != null) seg1int.set (seg1end); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(tmp*s+C+2*E+F); + } + } + } + else { // region 7 (side) + t = 0; + if (D >= 0) { + s = 0; + if (seg0int != null) seg0int.set (seg0start); + if (seg1int != null) seg1int.set (seg1start); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(F); + } + else if (-D >= A) { + s = 1; + if (seg0int != null) seg0int.set (seg0end); + if (seg1int != null) seg1int.set (seg1start); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(A+2*D+F); + } + else { + s = -D/A; + if (seg0int != null) seg0int.scaleAdd (s, seg0dir, seg0start); + if (seg1int != null) seg1int.set (seg1start); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(D*s+F); + } + } + } + else { + if (t >= 0) { + if (t <= det) { // region 1 (side) + s = 1; + tmp = B+E; + if (tmp >= 0) { + t = 0; + if (seg0int != null) seg0int.set (seg0end); + if (seg1int != null) seg1int.set (seg1start); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(A+2*D+F); + } + else if (-tmp >= C) { + t = 1; + if (seg0int != null) seg0int.set (seg0end); + if (seg1int != null) seg1int.set (seg1end); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(A+C+F+2*(D+tmp)); + } + else { + t = -tmp/C; + if (seg0int != null) seg0int.set (seg0end); + if (seg1int != null) seg1int.scaleAdd (t, seg1dir, seg1start); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(tmp*t+A+2*D+F); + } + } + else { // region 2 (corner) + tmp = B+D; + if (-tmp <= A) { + t = 1; + if (tmp >= 0) { + s = 0; + if (seg0int != null) seg0int.set (seg0start); + if (seg1int != null) seg1int.set (seg1end); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(C+2*E+F); + } + else { + s = -tmp/A; + if (seg0int!=null) seg0int.scaleAdd (s, seg0dir, seg0start); + if (seg1int!=null) seg1int.set (seg1end); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(tmp*s+C+2*E+F); + } + } + else { + s = 1; + tmp = B+E; + if (tmp >= 0) { + t = 0; + if (seg0int!=null) seg0int.set (seg0end); + if (seg1int!=null) seg1int.set (seg1start); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(A+2*D+F); + } + else if (-tmp >= C) { + t = 1; + if (seg0int != null) seg0int.set (seg0end); + if (seg1int != null) seg1int.set (seg1end); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(A+C+F+2*(D+tmp)); + } + else { + t = -tmp/C; + if (seg0int!=null) seg0int.set (seg0end); + if (seg1int!=null) seg1int.scaleAdd (t, seg1dir, seg1start); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(tmp*t+A+2*D+F); + } + } + } + } + else { // region 8 (corner) + if (-D < A) { + t = 0; + if (D >= 0) { + s = 0; + if (seg0int != null) seg0int.set (seg0start); + if (seg1int != null) seg1int.set (seg1start); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(F); + } + else { + s = -D/A; + if (seg0int != null) seg0int.scaleAdd (s, seg0dir, seg0start); + if (seg1int != null) seg1int.set (seg1start); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(D*s+F); + } + } + else { + s = 1; + tmp = B+E; + if (tmp >= 0) { + t = 0; + if (seg0int != null) seg0int.set (seg0end); + if (seg1int != null) seg1int.set (seg1start); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(A+2*D+F); + } + else if (-tmp >= C) { + t = 1; + if (seg0int != null) seg0int.set (seg0end); + if (seg1int != null) seg1int.set (seg1end); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(A+C+F+2*(D+tmp)); + } + else { + t = -tmp/C; + if (seg0int != null) seg0int.set (seg0end); + if (seg1int != null) seg1int.scaleAdd (t, seg1dir, seg1start); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(tmp*t+A+2*D+F); + } + } + } + } + } + else { + if (t >= 0) { + if (t <= det) { // region 5 (side) + s = 0; + if (E >= 0) { + t = 0; + if (seg0int != null) seg0int.set (seg0start); + if (seg1int != null) seg1int.set (seg1start); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(F); + } + else if (-E >= C) { + t = 1; + if (seg0int != null) seg0int.set (seg0start); + if (seg1int != null) seg1int.set (seg1end); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(C+2*E+F); + } + else { + t = -E/C; + if (seg0int != null) seg0int.set (seg0start); + if (seg1int != null) seg1int.scaleAdd (t, seg1dir, seg1start); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(E*t+F); + } + } + else { // region 4 (corner) + tmp = B+D; + if (tmp < 0) { + t = 1; + if (-tmp >= A) { + s = 1; + if (seg0int != null) seg0int.set (seg0end); + if (seg1int != null) seg1int.set (seg1end); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(A+C+F+2*(E+tmp)); + } + else { + s = -tmp/A; + if (seg0int != null) seg0int.scaleAdd (s, seg0dir, seg0start); + if (seg1int != null) seg1int.set (seg1end); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(tmp*s+C+2*E+F); + } + } + else { + s = 0; + if (E >= 0) { + t = 0; + if (seg0int != null) seg0int.set (seg0start); + if (seg1int != null) seg1int.set (seg1start); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(F); + } + else if (-E >= C) { + t = 1; + if (seg0int != null) seg0int.set (seg0start); + if (seg1int != null) seg1int.set (seg1end); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(C+2*E+F); + } + else { + t = -E/C; + if (seg0int != null) seg0int.set (seg0start); + if (seg1int != null) seg1int.scaleAdd (t, seg1dir, seg1start); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(E*t+F); + } + } + } + } + else { // region 6 (corner) + if (D < 0) { + t = 0; + if (-D >= A) { + s = 1; + if (seg0int != null) seg0int.set (seg0end); + if (seg1int != null) seg1int.set (seg1start); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(A+2*D+F); + } + else { + s = -D/A; + if (seg0int != null) seg0int.scaleAdd (s, seg0dir, seg0start); + if (seg1int != null) seg1int.set (seg1start); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(D*s+F); + } + } + else { + s = 0; + if (E >= 0) { + t = 0; + if (seg0int != null) seg0int.set (seg0start); + if (seg1int != null) seg1int.set (seg1start); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(F); + } + else if (-E >= C) { + t = 1; + if (seg0int != null) seg0int.set (seg0start); + if (seg1int != null) seg1int.set (seg1end); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(C+2*E+F); + } + else { + t = -E/C; + if (seg0int != null) seg0int.set (seg0start); + if (seg1int != null) seg1int.scaleAdd (t, seg1dir, seg1start); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(E*t+F); + } + } + } + } + } + else { + // line segments are parallel + if (B > 0) { + // direction vectors form an obtuse angle + if (D >= 0) { + s = 0; + t = 0; + if (seg0int != null) seg0int.set (seg0start); + if (seg1int != null) seg1int.set (seg1start); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(F); + } + else if (-D <= A) { + s = -D/A; + t = 0; + if (seg0int != null) seg0int.scaleAdd (s, seg0dir, seg0start); + if (seg1int != null) seg1int.set (seg1start); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(D*s+F); + } + else { + E = -seg1dir.dot (diff); //-Dot(seg1dir,diff); + s = 1; + tmp = A+D; + if (-tmp >= B) { + t = 1; + if (seg0int != null) seg0int.set (seg0end); + if (seg1int != null) seg1int.set (seg1end); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(A+C+F+2*(B+D+E)); + } + else { + t = -tmp/B; + if (seg0int != null) seg0int.set (seg0end); + if (seg1int != null) seg1int.scaleAdd (t, seg1dir, seg1start); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(A+2*D+F+t*(C*t+2*(B+E))); + } + } + } + else { + // direction vectors form an acute angle + if (-D >= A) { + s = 1; + t = 0; + if (seg0int != null) seg0int.set (seg0end); + if (seg1int != null) seg1int.set (seg1start); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(A+2*D+F); + } + else if (D <= 0) { + s = -D/A; + t = 0; + if (seg0int != null) seg0int.scaleAdd (s, seg0dir, seg0start); + if (seg1int != null) seg1int.set (seg1start); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(D*s+F); + } + else { + E = -seg1dir.dot (diff); //-Dot(seg1dir,diff); + s = 0; + if (D >= -B) { + t = 1; + if (seg0int != null) seg0int.set (seg0start); + if (seg1int != null) seg1int.set (seg1end); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(C+2*E+F); + } + else { + t = -D/B; + if (seg0int != null) seg0int.set (seg0start); + if (seg1int != null) seg1int.scaleAdd (t, seg1dir, seg1start); + if (param != null) { param[0] = s; param[1] = t; } + return DIST(F+t*(2*E+C*t)); + } + } + } + } + } +} + + + + diff --git a/src/classes/share/com/sun/j3d/internal/DoubleBufferWrapper.java b/src/classes/share/com/sun/j3d/internal/DoubleBufferWrapper.java new file mode 100755 index 0000000..c6f011d --- /dev/null +++ b/src/classes/share/com/sun/j3d/internal/DoubleBufferWrapper.java @@ -0,0 +1,153 @@ +/* + * $RCSfile$ + * + * Copyright (c) 2004 Sun Microsystems, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any + * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND + * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY + * EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL + * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF + * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS + * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR + * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, + * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND + * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR + * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed, licensed or + * intended for use in the design, construction, operation or + * maintenance of any nuclear facility. + * + * $Revision$ + * $Date$ + * $State$ + */ + +package com.sun.j3d.internal; + +import javax.media.j3d.J3DBuffer; +import java.nio.DoubleBuffer; + +/** + * NIO Buffers are new in Java 1.4 but we need to run on 1.3 + * as well, so this class was created to hide the NIO classes + * from non-1.4 Java 3D users. + * + * <p> + * NOTE: We no longer need to support JDK 1.3 as of the Java 3D 1.3.2 + * community source release on java.net. We should be able to get rid + * of this class. + */ + +public class DoubleBufferWrapper extends BufferWrapper { + + private DoubleBuffer buffer = null; + + /** + * Constructor initializes buffer with a + * java.nio.DoubleBuffer object. + */ + public DoubleBufferWrapper(DoubleBuffer buffer) { + this.buffer = buffer; + } + + /** + * Constructor initializes buffer with a + * javax.media.j3d.J3DBuffer object. + */ + public DoubleBufferWrapper(J3DBuffer b) { + buffer = (DoubleBuffer)(b.getBuffer()); + } + + /** + * Returns the java.nio.Buffer contained within this + * DoubleBufferWrapper. + */ + public java.nio.Buffer getBuffer() { + return this.buffer; + } + + // Wrapper for all relevant DoubleBuffer methods. + + /** + * @return A boolean indicating whether the java.nio.Buffer + * object contained within this DoubleBuffer is direct or + * indirect. + */ + public boolean isDirect() { + return buffer.isDirect(); + } + + /** + * Reads the double at this buffer's current position, + * and then increments the position. + */ + public double get() { + return buffer.get(); + } + + /** + * Reads the double at the given offset into the buffer. + */ + public double get(int index) { + return buffer.get(index); + } + + /** + * Bulk <i>get</i> method. Transfers <code>dst.length</code> + * doubles from + * the buffer to the destination array and increments the + * buffer's position by <code>dst.length</code>. + */ + public DoubleBufferWrapper get(double[] dst) { + buffer.get(dst); + return this; + } + + /** + * Bulk <i>get</i> method. Transfers <i>length</i> doubles + * from the buffer starting at position <i>offset</i> into + * the destination array. + */ + public DoubleBufferWrapper get(double[] dst, int offset, int length){ + buffer.get(dst, offset, length); + return this; + } + + /** + * Bulk <i>put</i> method. Transfers <code>src.length</code> + * doubles into the buffer at the current position. + */ + public DoubleBufferWrapper put(double[] src) { + buffer.put(src); + return this; + } + + /** + * Creates and returns a J3DBuffer object containing the + * buffer in this DoubleBufferWrapper object. + */ + public J3DBuffer getJ3DBuffer() { + return new J3DBuffer( buffer ); + } + +} diff --git a/src/classes/share/com/sun/j3d/internal/FastVector.java b/src/classes/share/com/sun/j3d/internal/FastVector.java new file mode 100644 index 0000000..b3ed4c2 --- /dev/null +++ b/src/classes/share/com/sun/j3d/internal/FastVector.java @@ -0,0 +1,143 @@ +/* + * $RCSfile$ + * + * Copyright (c) 2004 Sun Microsystems, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any + * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND + * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY + * EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL + * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF + * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS + * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR + * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, + * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND + * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR + * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed, licensed or + * intended for use in the design, construction, operation or + * maintenance of any nuclear facility. + * + * $Revision$ + * $Date$ + * $State$ + */ + +package com.sun.j3d.internal; + +/** + * The FastVector object is a growable array of ints. It's much faster + * than the Java Vector class because it isn't synchronized. This class + * was created because it is needed in several places by graphics + * utilities. + */ +public class FastVector { + + private int data[]; + private int capacity; + private int increment; + private int size; + + /** + * Add an element to the end of the array. + */ + public void addElement(int element) + { + if (size >= capacity) { + capacity += (increment == 0) ? capacity : increment; + int newData[] = new int[capacity]; + System.arraycopy(data, 0, newData, 0, size); + data = newData; + } + data[size++] = element; + } // End of addElement + + + + /** + * Get number of ints currently stored in the array; + */ + public int getSize() + { + return size; + } // End of getSize + + + + /** + * Get access to array data + */ + public int[] getData() + { + return data; + } // End of getData + + + + /** + * Constructor. + * @param initialCapacity Number of ints the object can hold + * without reallocating the array. + * @param capacityIncrement Once the array has grown beyond + * its capacity, how much larger the reallocated array should be. + */ + public FastVector(int initialCapacity, int capacityIncrement) + { + data = new int[initialCapacity]; + capacity = initialCapacity; + increment = capacityIncrement; + size = 0; + } // End of FastVector(int, int) + + + + /** + * Constructor. + * When the array runs out of space, its size is doubled. + * @param initialCapacity Number of ints the object can hold + * without reallocating the array. + */ + public FastVector(int initialCapacity) + { + data = new int[initialCapacity]; + capacity = initialCapacity; + increment = 0; + size = 0; + } // End of FastVector(int) + + + + /** + * Constructor. + * The array is constructed with initial capacity of one integer. + * When the array runs out of space, its size is doubled. + */ + public FastVector() + { + data = new int[1]; + capacity = 1; + increment = 0; + size = 0; + } // End of FastVector() +} // End of class FastVector + +// End of file FastVector.java diff --git a/src/classes/share/com/sun/j3d/internal/FloatBufferWrapper.java b/src/classes/share/com/sun/j3d/internal/FloatBufferWrapper.java new file mode 100755 index 0000000..8868901 --- /dev/null +++ b/src/classes/share/com/sun/j3d/internal/FloatBufferWrapper.java @@ -0,0 +1,152 @@ +/* + * $RCSfile$ + * + * Copyright (c) 2004 Sun Microsystems, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any + * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND + * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY + * EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL + * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF + * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS + * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR + * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, + * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND + * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR + * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed, licensed or + * intended for use in the design, construction, operation or + * maintenance of any nuclear facility. + * + * $Revision$ + * $Date$ + * $State$ + */ + +package com.sun.j3d.internal; + +import javax.media.j3d.J3DBuffer; +import java.nio.FloatBuffer; + +/** + * NIO Buffers are new in Java 1.4 but we need to run on 1.3 + * as well, so this class was created to hide the NIO classes + * from non-1.4 Java 3D users. + * + * <p> + * NOTE: We no longer need to support JDK 1.3 as of the Java 3D 1.3.2 + * community source release on java.net. We should be able to get rid + * of this class. + */ + +public class FloatBufferWrapper extends BufferWrapper { + + private FloatBuffer buffer = null; + + /** + * Constructor initializes buffer with a + * java.nio.FloatBuffer object. + */ + public FloatBufferWrapper(FloatBuffer buffer) { + this.buffer = buffer; + } + + /** + * Constructor initializes buffer with a + * javax.media.j3d.J3DBuffer object. + */ + public FloatBufferWrapper(javax.media.j3d.J3DBuffer b) { + this.buffer = (FloatBuffer)(b.getBuffer()); + } + + /** + * Returns the java.nio.Buffer contained within this + * FloatBufferWrapper. + */ + public java.nio.Buffer getBuffer() { + return this.buffer; + } + + // Wrapper for all relevant FloatBuffer methods. + + /** + * @return A boolean indicating whether the java.nio.Buffer + * object contained within this FloatBuffer is direct or + * indirect. + */ + public boolean isDirect() { + return buffer.isDirect(); + } + + /** + * Reads the float at this buffer's current position, + * and then increments the position. + */ + public float get() { + return buffer.get(); + } + + /** + * Reads the float at the given offset into the buffer. + */ + public float get(int index) { + return buffer.get(index); + } + + /** + * Bulk <i>get</i> method. Transfers <code>dst.length</code> + * floats from + * the buffer to the destination array and increments the + * buffer's position by <code>dst.length</code>. + */ + public FloatBufferWrapper get(float[] dst) { + buffer.get(dst); + return this; + } + + /** + * Bulk <i>get</i> method. Transfers <i>length</i> floats + * from the buffer starting at position <i>offset</i> into + * the destination array. + */ + public FloatBufferWrapper get(float[] dst, int offset, int length){ + buffer.get(dst, offset, length); + return this; + } + + /** + * Bulk <i>put</i> method. Transfers <code>src.length</code> + * floats into the buffer at the current position. + */ + public FloatBufferWrapper put(float[] src) { + buffer.put(src); + return this; + } + + /** + * Creates and returns a J3DBuffer object containing the + * buffer in this FloatBufferWrapper object. + */ + public J3DBuffer getJ3DBuffer() { + return new J3DBuffer( buffer ); + } +} diff --git a/src/classes/share/com/sun/j3d/internal/J3dUtilsI18N.java b/src/classes/share/com/sun/j3d/internal/J3dUtilsI18N.java new file mode 100644 index 0000000..a61c43a --- /dev/null +++ b/src/classes/share/com/sun/j3d/internal/J3dUtilsI18N.java @@ -0,0 +1,63 @@ +/* + * $RCSfile$ + * + * Copyright (c) 2004 Sun Microsystems, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any + * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND + * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY + * EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL + * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF + * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS + * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR + * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, + * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND + * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR + * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed, licensed or + * intended for use in the design, construction, operation or + * maintenance of any nuclear facility. + * + * $Revision$ + * $Date$ + * $State$ + */ + +package com.sun.j3d.internal; + +import java.io.*; +import java.util.*; + + +public class J3dUtilsI18N { + static public String getString(String key) { + String s; + try { + s = (String) ResourceBundle.getBundle("com.sun.j3d.ExceptionStrings").getString(key); + } + catch (MissingResourceException e) { + System.err.println("J3dUtilsI18N: Error looking up: " + key); + s = key; + } + return s; + } +} diff --git a/src/classes/share/com/sun/j3d/internal/UtilFreelistManager.java b/src/classes/share/com/sun/j3d/internal/UtilFreelistManager.java new file mode 100644 index 0000000..457968a --- /dev/null +++ b/src/classes/share/com/sun/j3d/internal/UtilFreelistManager.java @@ -0,0 +1,98 @@ +/* + * $RCSfile$ + * + * Copyright (c) 2004 Sun Microsystems, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any + * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND + * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY + * EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL + * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF + * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS + * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR + * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, + * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND + * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR + * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed, licensed or + * intended for use in the design, construction, operation or + * maintenance of any nuclear facility. + * + * $Revision$ + * $Date$ + * $State$ + */ + +package com.sun.j3d.internal; + + +public class UtilFreelistManager { + + private static final boolean DEBUG = false; + + // constants that represent the freelists managed by the Manager + public static final int VECTOR3D = 0; + public static final int POINT3D = 1; + public static final int PICKRESULT = 2; + public static final int MAXINT = 2; + + // what list we are going to shrink next + private static int currlist = 0; + + // the freelists managed by the manager + public static UtilMemoryFreelist vector3dFreelist = new UtilMemoryFreelist("javax.vecmath.Vector3d"); + public static UtilMemoryFreelist point3dFreelist = new UtilMemoryFreelist("javax.vecmath.Point3d"); + public static UtilMemoryFreelist pickResultFreelist = new UtilMemoryFreelist("com.sun.j3d.utils.picking.PickResult"); + + +// static MemoryFreeList[] freelist = new MemoryFreeList[MAXINT+1]; + +// static void createFreeLists() { +// freelist[VECTOR3D] = new MemoryFreeList("javax.vecmath.Vector3d"); +// freelist[POINT3D] = new MemoryFreeList("javax.vecmath.Point3d"); +// } + + +// // see if the current list can be shrunk +// static void manageLists() { +// // System.out.println("manageLists"); +// if (freelist[currlist] != null) { +// freelist[currlist].shrink(); +// } + +// currlist++; +// if (currlist > MAXINT) currlist = 0; +// } + +// // return the freelist specified by the list param +// static MemoryFreeList getFreeList(int list) { +// if (list < 0 || list > MAXINT) { +// if (DEBUG) System.out.println("illegal list"); +// return null; +// } +// else { +// return freelist[list]; +// } +// } + + +} diff --git a/src/classes/share/com/sun/j3d/internal/UtilMemoryFreelist.java b/src/classes/share/com/sun/j3d/internal/UtilMemoryFreelist.java new file mode 100644 index 0000000..3f559b7 --- /dev/null +++ b/src/classes/share/com/sun/j3d/internal/UtilMemoryFreelist.java @@ -0,0 +1,292 @@ +/* + * $RCSfile$ + * + * Copyright (c) 2004 Sun Microsystems, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any + * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND + * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY + * EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL + * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF + * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS + * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR + * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, + * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND + * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR + * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed, licensed or + * intended for use in the design, construction, operation or + * maintenance of any nuclear facility. + * + * $Revision$ + * $Date$ + * $State$ + */ + +package com.sun.j3d.internal; + +import java.util.*; + +// this class must be synchronized because different threads may try to access +// the freelists +public class UtilMemoryFreelist { // extends AbstractList { + + // never go smaller than the initial capacity + ArrayList elementData = null; + int size = 0; + int currBlockSize = 10; + Object[] currBlock = null; + int currBlockIndex = 0; + int spaceUsed = 0; + int numBlocks = 0; + int capacity = 0; + int minBlockSize = 0; + boolean justShrunk = false; + int initcap = 10; + + // the minimum size since the last shrink + int minSize = 0; + + Class c = null; + + public UtilMemoryFreelist(String className) { + this(className, 10); + } + + public UtilMemoryFreelist(String className, int initialCapacity) { + if (initialCapacity < 0) { + throw new IllegalArgumentException ("Illegal Capacity: " + + initialCapacity); + } + + try { + c = Class.forName(className); + } + catch (Exception e) { +// System.out.println(e); + } + + initcap = initialCapacity; + currBlockSize = initialCapacity; + minBlockSize = currBlockSize; + elementData = new ArrayList(); + // add the first block of memory to the arraylist + currBlock = new Object[currBlockSize]; + elementData.add(currBlock); + numBlocks++; + capacity += currBlockSize; + } + + public UtilMemoryFreelist(String className, Collection collection) { + try { + c = Class.forName(className); + } + catch (Exception e) { +// System.out.println(e); + } + size = collection.size(); + initcap = size; + currBlockSize = size; + minBlockSize = currBlockSize; + elementData = new ArrayList(); + currBlock = new Object[currBlockSize]; + collection.toArray(currBlock); + elementData.add(currBlock); + numBlocks++; + capacity += currBlockSize; + spaceUsed = size; + } + + public synchronized int size() { + return size; + } + + + public synchronized boolean add(Object o) { + if (justShrunk) { + // empty some space out in the current block instead of + // adding this message + if ((currBlockSize/2) < spaceUsed) { + size -= (spaceUsed - (currBlockSize/2)); + spaceUsed = (currBlockSize/2); + Arrays.fill(currBlock, spaceUsed, currBlockSize-1, null); + } + justShrunk = false; + return false; + } + else { + ensureCapacity(size+1); + + // check to see if the whole block is used and if so, reset the + // current block +// System.out.println("spaceUsed = " + spaceUsed + " currBlockSize = " + +// currBlockSize + " currBlockIndex = " + +// currBlockIndex + " currBlock = " + currBlock); + if ((currBlockIndex == -1) || (spaceUsed >= currBlockSize)) { + currBlockIndex++; + currBlock = (Object[])elementData.get(currBlockIndex); + currBlockSize = currBlock.length; + spaceUsed = 0; + } + int index = spaceUsed++; + currBlock[index] = o; + size++; + + return true; + } + } + + private synchronized Object removeLastElement() { +// System.out.println("removeLastElement: size = " + size); + int index = --spaceUsed; +// System.out.println("index = " + index); + Object elm = currBlock[index]; + currBlock[index] = null; + size--; + + // see if this block is empty now, and if it is set the previous + // block to the current block + if (spaceUsed == 0) { + currBlockIndex--; + if (currBlockIndex < 0) { + currBlock = null; + currBlockSize = 0; + } + else { + currBlock = (Object[])elementData.get(currBlockIndex); + currBlockSize = currBlock.length; + } + spaceUsed = currBlockSize; + } + + return elm; + } + + + public synchronized void shrink() { +// System.out.println("shrink size = " + size + " minSize = " + +// minSize); + if ((minSize > minBlockSize) && (numBlocks > 1)) { + justShrunk = true; + +// System.out.println("removing a block"); +// Runtime r = Runtime.getRuntime(); +// r.gc(); +// System.out.println("numBlocks = " + numBlocks + " size = " + size); +// System.out.println("free memory before shrink: " + r.freeMemory()); + + // remove the last block + Object[] block = (Object[])elementData.remove(numBlocks-1); + numBlocks--; + capacity -= block.length; + + // we only need to do this if the block removed was the current + // block. otherwise we just removed a null block. + if (numBlocks == currBlockIndex) { + size -= spaceUsed; + // set the current block to the last one + currBlockIndex = numBlocks-1; + currBlock = (Object[])elementData.get(currBlockIndex); + currBlockSize = currBlock.length; + + spaceUsed = currBlockSize; + + } + +// r.gc(); +// System.out.println("free memory after shrink: " + r.freeMemory()); +// System.out.println("numBlocks = " + numBlocks + " size = " + size); + } + else { + justShrunk = false; + } + minSize = size; + } + + public synchronized void ensureCapacity(int minCapacity) { +// System.out.println("ensureCapacity: size = " + size + " capacity: " + +// elementData.length); +// System.out.println("minCapacity = " + minCapacity + " capacity = " +// + capacity); + + if (minCapacity > capacity) { +// System.out.println("adding a block: numBlocks = " + numBlocks); + int lastBlockSize = + ((Object[])elementData.get(numBlocks-1)).length; + int prevBlockSize = 0; + if (numBlocks > 1) { + prevBlockSize = + ((Object[])elementData.get(numBlocks-2)).length; + } + currBlockSize = lastBlockSize + prevBlockSize; + currBlock = new Object[currBlockSize]; + elementData.add(currBlock); + numBlocks++; + currBlockIndex++; + capacity += currBlockSize; + // there is nothing used in this block yet + spaceUsed = 0; + } + } + + synchronized void rangeCheck(int index) { + if (index >= size || index < 0) { + throw new IndexOutOfBoundsException("Index: " + index + + ", Size: " + size); + } + } + + public synchronized void clear() { +// System.out.println("clear"); + elementData.clear(); + + // put an empty block in + currBlockSize = initcap; + minBlockSize = currBlockSize; + currBlock = new Object[currBlockSize]; + elementData.add(currBlock); + numBlocks = 1; + capacity = currBlockSize; + spaceUsed = 0; + size = 0; + currBlockIndex = 0; + justShrunk = false; + } + + public synchronized Object getObject() { + if (size > 0) { + return removeLastElement(); + } + else { + try { + return c.newInstance(); + } + catch (Exception e) { +// System.out.println("caught exception"); +// System.out.print(e); + return null; + } + } + } + +} + |