0001: /*
0002: * $RCSfile: PickIntersection.java,v $
0003: *
0004: * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved.
0005: *
0006: * Redistribution and use in source and binary forms, with or without
0007: * modification, are permitted provided that the following conditions
0008: * are met:
0009: *
0010: * - Redistribution of source code must retain the above copyright
0011: * notice, this list of conditions and the following disclaimer.
0012: *
0013: * - Redistribution in binary form must reproduce the above copyright
0014: * notice, this list of conditions and the following disclaimer in
0015: * the documentation and/or other materials provided with the
0016: * distribution.
0017: *
0018: * Neither the name of Sun Microsystems, Inc. or the names of
0019: * contributors may be used to endorse or promote products derived
0020: * from this software without specific prior written permission.
0021: *
0022: * This software is provided "AS IS," without a warranty of any
0023: * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND
0024: * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,
0025: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
0026: * EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL
0027: * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF
0028: * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
0029: * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR
0030: * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
0031: * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
0032: * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
0033: * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
0034: * POSSIBILITY OF SUCH DAMAGES.
0035: *
0036: * You acknowledge that this software is not designed, licensed or
0037: * intended for use in the design, construction, operation or
0038: * maintenance of any nuclear facility.
0039: *
0040: * $Revision: 1.5 $
0041: * $Date: 2007/02/09 17:20:24 $
0042: * $State: Exp $
0043: */
0044:
0045: package com.sun.j3d.utils.pickfast;
0046:
0047: import javax.vecmath.*;
0048: import javax.media.j3d.*;
0049: import com.sun.j3d.utils.geometry.Primitive;
0050:
0051: /**
0052: * Holds information about an intersection of a PickShape with a Node
0053: * as part of a PickInfo.IntersectionInfo. Information about
0054: * the intersected geometry, intersected primitive, intersection point, and
0055: * closest vertex can be inquired.
0056: * <p>
0057: * The intersected primitive indicates which primitive out of the GeometryArray
0058: * was intersected (where the primitive is a point, line, triangle or quad,
0059: * not a
0060: * <code>com.sun.j3d.utils.geometry.Primitive)</code>.
0061: * For example, the intersection would indicate which triangle out of a
0062: * triangle strip was intersected.
0063: * The methods which return primitive data will have one value if the primitive
0064: * is
0065: * a point, two values if the primitive is a line, three values if the primitive
0066: * is a triangle and four values if the primitive is quad.
0067: * <p>
0068: * The primitive's VWorld coordinates are saved when then intersection is
0069: * calculated. The local coordinates, normal, color and texture coordinates
0070: * for the primitive can also be inquired if they are present and readable.
0071: * <p>
0072: * The intersection point is the location on the primitive which intersects the
0073: * pick shape closest to the center of the pick shape. The intersection point's
0074: * location in VWorld coordinates is saved when the intersection is calculated.
0075: * The local coordinates, normal, color and texture coordiantes of at the
0076: * intersection can be interpolated if they are present and readable.
0077: * <p>
0078: * The closest vertex is the vertex of the primitive closest to the intersection
0079: * point. The vertex index, VWorld coordinates and local coordinates of the
0080: * closest vertex can be inquired. The normal, color and texture coordinate
0081: * of the closest vertex can be inquired from the geometry array:
0082: * <p><blockquote><pre>
0083: * Vector3f getNormal(PickIntersection pi, int vertexIndex) {
0084: * int index;
0085: * Vector3d normal = new Vector3f();
0086: * GeometryArray ga = pickIntersection.getGeometryArray();
0087: * if (pickIntersection.geometryIsIndexed()) {
0088: * index = ga.getNormalIndex(vertexIndex);
0089: * } else {
0090: * index = vertexIndex;
0091: * }
0092: * ga.getNormal(index, normal);
0093: * return normal;
0094: * }
0095: * </pre></blockquote>
0096: * <p>
0097: * The color, normal
0098: * and texture coordinate information for the intersected primitive and the
0099: * intersection point
0100: * can be inquired
0101: * the geometry includes them and the corresponding READ capibility bits are
0102: * set.
0103: */
0104:
0105: public class PickIntersection {
0106:
0107: /* The intersection point */
0108: // Point3d getIntersectionPoint()
0109: /* Distance between start point of pickShape and intersection point */
0110: // double getDistance()
0111: /* The vertex indices of the intersected primitive in the geometry */
0112: // int[] getVertexIndices()
0113: /*************************/
0114:
0115: /** Weight factors for interpolation, values correspond to vertex indices,
0116: * sum == 1
0117: */
0118: private double[] interpWeights;
0119:
0120: private static final boolean debug = false;
0121:
0122: // Axis constants
0123: private static final int X_AXIS = 1;
0124: private static final int Y_AXIS = 2;
0125: private static final int Z_AXIS = 3;
0126:
0127: // Tolerance for numerical stability
0128: static final double TOL = 1.0e-5;
0129:
0130: /* The references to the intersectionInfo object */
0131: private PickInfo.IntersectionInfo iInfo = null;
0132: private Transform3D l2vw = null;
0133: private Geometry geometry = null;
0134: private boolean geometryIsIndexed = false;
0135: private double distance;
0136:
0137: private boolean hasColors;
0138: private boolean hasNormals;
0139: private boolean hasTexCoords;
0140:
0141: // Primitive
0142: /* indices for the different data types */
0143: private int[] primitiveCoordinateIndices;
0144: private int[] primitiveNormalIndices;
0145: private int[] primitiveColorIndices;
0146: private int[] primitiveTexCoordIndices;
0147:
0148: /** Indices of the intersected primitive */
0149: private int[] primitiveVertexIndices = null;
0150:
0151: /* Local coordinates of the intersected primitive */
0152: private Point3d[] primitiveCoordinates = null;
0153:
0154: /** VWorld coordinates of intersected primitive */
0155: private Point3d[] primitiveCoordinatesVW = null;
0156:
0157: /* Normals of the intersected primitive */
0158: private Vector3f[] primitiveNormals = null;
0159:
0160: /* Colors of the intersected primitive */
0161: private Color4f[] primitiveColors = null;
0162:
0163: /* TextureCoordinates of the intersected primitive */
0164: private TexCoord3f[] primitiveTexCoords = null;
0165:
0166: // Intersection point
0167: /** VWorld Coordinates of the intersection point */
0168: private Point3d pointCoordinatesVW = null;
0169:
0170: /** Local Coordinates of the intersection point */
0171: private Point3d pointCoordinates = null;
0172:
0173: /** Normal at the intersection point */
0174: private Vector3f pointNormal = null;
0175:
0176: /** Color at the intersection point */
0177: private Color4f pointColor = null;
0178:
0179: /** TexCoord at the intersection point */
0180: private TexCoord3f pointTexCoord = null;
0181:
0182: // Closest Vertex
0183: /** Index of the closest vertex */
0184: private int closestVertexIndex = -1;
0185:
0186: /** Coordinates of the closest vertex */
0187: private Point3d closestVertexCoordinates = null;
0188:
0189: /** Coordinates of the closest vertex (World coordinates) */
0190: private Point3d closestVertexCoordinatesVW = null;
0191:
0192: /* =================== METHODS ======================= */
0193:
0194: /**
0195: * Constructor
0196: * @param intersectionInfo The IntersectionInfo this intersection is part of.
0197: */
0198: public PickIntersection(Transform3D localToVWorld,
0199: PickInfo.IntersectionInfo intersectionInfo) {
0200:
0201: // Should check and throw NPE if the following is null.
0202: // localToVWorld can't be null.
0203: l2vw = localToVWorld;
0204: // intersectionInfo can't be null.
0205: iInfo = intersectionInfo;
0206: // geometry can't be null.
0207: geometry = iInfo.getGeometry();
0208:
0209: pointCoordinates = iInfo.getIntersectionPoint();
0210: distance = iInfo.getDistance();
0211: primitiveVertexIndices = iInfo.getVertexIndices();
0212:
0213: if (geometry instanceof GeometryArray) {
0214:
0215: int vertexFormat = ((GeometryArray) geometry)
0216: .getVertexFormat();
0217: hasColors = (0 != (vertexFormat & (GeometryArray.COLOR_3 | GeometryArray.COLOR_4)));
0218: hasNormals = (0 != (vertexFormat & GeometryArray.NORMALS));
0219: hasTexCoords = (0 != (vertexFormat & (GeometryArray.TEXTURE_COORDINATE_2 | GeometryArray.TEXTURE_COORDINATE_3)));
0220:
0221: if (geometry instanceof IndexedGeometryArray) {
0222: geometryIsIndexed = true;
0223: }
0224: }
0225: }
0226:
0227: /**
0228: * Returns true if the geometry is indexed
0229: *
0230: */
0231: public boolean geometryIsIndexed() {
0232: return geometryIsIndexed;
0233: }
0234:
0235: /**
0236: * Get coordinates of closest vertex (local)
0237: * @return the coordinates of the vertex closest to the intersection point
0238: *
0239: */
0240: public Point3d getClosestVertexCoordinates() {
0241: // System.out.println("PI.closestVertexCoordinates " + closestVertexCoordinates);
0242: GeometryArray geom = (GeometryArray) geometry;
0243:
0244: if (closestVertexCoordinates == null) {
0245: int vertexIndex = getClosestVertexIndex();
0246: int vformat = geom.getVertexFormat();
0247: int val;
0248:
0249: int[] indices = getPrimitiveCoordinateIndices();
0250: if ((vformat & GeometryArray.BY_REFERENCE) == 0) {
0251: closestVertexCoordinates = new Point3d();
0252: geom.getCoordinate(indices[vertexIndex],
0253: closestVertexCoordinates);
0254: // System.out.println("PI.closestVertexCoordinates " +
0255: // closestVertexCoordinates + " vertexIndex " +
0256: // vertexIndex);
0257: } else {
0258: if ((vformat & GeometryArray.INTERLEAVED) == 0) {
0259: double[] doubleData = geom.getCoordRefDouble();
0260: // If data was set as float then ..
0261: if (doubleData == null) {
0262: float[] floatData = geom.getCoordRefFloat();
0263: if (floatData == null) {
0264: throw new UnsupportedOperationException(
0265: "Deprecated : BY_REF - p3f and p3d");
0266: } else {
0267: val = indices[vertexIndex] * 3; // for x,y,z
0268: closestVertexCoordinates = new Point3d(
0269: floatData[val], floatData[val + 1],
0270: floatData[val + 2]);
0271: }
0272: } else {
0273: val = indices[vertexIndex] * 3; // for x,y,z
0274: closestVertexCoordinates = new Point3d(
0275: doubleData[val], doubleData[val + 1],
0276: doubleData[val + 2]);
0277: }
0278: } else {
0279: float[] floatData = geom.getInterleavedVertices();
0280: int offset = getInterleavedVertexOffset(geom);
0281: int stride = offset + 3; // for the vertices .
0282: val = stride * indices[vertexIndex] + offset;
0283: closestVertexCoordinates = new Point3d(
0284: floatData[val], floatData[val + 1],
0285: floatData[val + 2]);
0286: }
0287: }
0288: }
0289:
0290: return closestVertexCoordinates;
0291: }
0292:
0293: /**
0294: * Get coordinates of closest vertex (world)
0295: * @return the coordinates of the vertex closest to the intersection point
0296: *
0297: */
0298: public Point3d getClosestVertexCoordinatesVW() {
0299: if (closestVertexCoordinatesVW == null) {
0300: int vertexIndex = getClosestVertexIndex();
0301: Point3d[] coordinatesVW = getPrimitiveCoordinatesVW();
0302: closestVertexCoordinatesVW = coordinatesVW[vertexIndex];
0303: }
0304: return closestVertexCoordinatesVW;
0305: }
0306:
0307: /**
0308: * Get index of closest vertex
0309: * @return the index of the closest vertex
0310: */
0311: public int getClosestVertexIndex() {
0312: if (closestVertexIndex == -1) {
0313: double maxDist = Double.MAX_VALUE;
0314: double curDist = Double.MAX_VALUE;
0315: int closestIndex = -1;
0316: primitiveCoordinates = getPrimitiveCoordinates();
0317:
0318: assert (primitiveCoordinates != null);
0319:
0320: // System.out.println("PI.getClosestVertexIndex : primitiveCoordinates.length " +
0321: // primitiveCoordinates.length);
0322:
0323: for (int i = 0; i < primitiveCoordinates.length; i++) {
0324: curDist = pointCoordinates
0325: .distance(primitiveCoordinates[i]);
0326:
0327: // System.out.println("pointCoordinates " + pointCoordinates);
0328: // System.out.println("primitiveCoordinates[" + i + "] " +
0329: // primitiveCoordinates[i]);
0330: // System.out.println("curDist " + curDist);
0331:
0332: if (curDist < maxDist) {
0333: closestIndex = i;
0334: maxDist = curDist;
0335: }
0336: }
0337: closestVertexIndex = closestIndex;
0338: }
0339: return closestVertexIndex;
0340: }
0341:
0342: /**
0343: * Get the distance from the PickShape start point to the intersection point
0344: * @return the distance to the intersection point, if available.
0345: */
0346: public double getDistance() {
0347: return distance;
0348: }
0349:
0350: /**
0351: * Returns the color of the intersection point. Returns null if the geometry
0352: * does not contain colors. If the geometry was defined with
0353: * GeometryArray.COLOR_3, the 'w' component of the color will initialized to
0354: * 1.0
0355: * @return color at the intersection point.
0356: */
0357: public Color4f getPointColor() {
0358: if (hasColors && (pointColor == null)) {
0359: double[] weights = getInterpWeights();
0360: Color4f[] colors = getPrimitiveColors();
0361: pointColor = new Color4f();
0362: for (int i = 0; i < weights.length; i++) {
0363: pointColor.x += (float) weights[i] * colors[i].x;
0364: pointColor.y += (float) weights[i] * colors[i].y;
0365: pointColor.z += (float) weights[i] * colors[i].z;
0366: pointColor.w += (float) weights[i] * colors[i].w;
0367: }
0368: }
0369: return pointColor;
0370: }
0371:
0372: /**
0373: * Returns the coordinates of the intersection point (local coordinates),
0374: * if available.
0375: * @return coordinates of the intersection point
0376: */
0377: public Point3d getPointCoordinates() {
0378: return pointCoordinates;
0379: }
0380:
0381: /**
0382: * Returns the coordinates of the intersection point (world coordinates),
0383: * if available.
0384: * @return coordinates of the point
0385: */
0386: public Point3d getPointCoordinatesVW() {
0387:
0388: if (pointCoordinatesVW != null) {
0389: return pointCoordinatesVW;
0390: }
0391:
0392: pointCoordinatesVW = new Point3d();
0393:
0394: pointCoordinatesVW.x = pointCoordinates.x;
0395: pointCoordinatesVW.y = pointCoordinates.y;
0396: pointCoordinatesVW.z = pointCoordinates.z;
0397:
0398: l2vw.transform(pointCoordinatesVW);
0399: return pointCoordinatesVW;
0400: }
0401:
0402: /**
0403: * Returns the normal of the intersection point. Returns null if the geometry
0404: * does not contain normals.
0405: * @return normal at the intersection point.
0406: */
0407: public Vector3f getPointNormal() {
0408: if (hasNormals && (pointNormal == null)) {
0409: double[] weights = getInterpWeights();
0410: Vector3f[] normals = getPrimitiveNormals();
0411: pointNormal = new Vector3f();
0412: for (int i = 0; i < weights.length; i++) {
0413: pointNormal.x += (float) weights[i] * normals[i].x;
0414: pointNormal.y += (float) weights[i] * normals[i].y;
0415: pointNormal.z += (float) weights[i] * normals[i].z;
0416: }
0417: }
0418: return pointNormal;
0419: }
0420:
0421: /**
0422: * Returns the texture coordinate of the intersection point at the specifed
0423: * index in the specified texture coordinate set.
0424: * Returns null if the geometry
0425: * does not contain texture coordinates. If the geometry was defined with
0426: * GeometryArray.TEXTURE_COORDINATE_3, the 'z' component of the texture
0427: * coordinate will initialized to 0.0
0428: * @return texture coordinate at the intersection point.
0429: */
0430: public TexCoord3f getPointTextureCoordinate(int index) {
0431: if (hasTexCoords && (pointTexCoord == null)) {
0432: double[] weights = getInterpWeights();
0433: TexCoord3f[] texCoords = getPrimitiveTexCoords(index);
0434: pointTexCoord = new TexCoord3f();
0435: for (int i = 0; i < weights.length; i++) {
0436: pointTexCoord.x += (float) weights[i] * texCoords[i].x;
0437: pointTexCoord.y += (float) weights[i] * texCoords[i].y;
0438: pointTexCoord.z += (float) weights[i] * texCoords[i].z;
0439: }
0440: }
0441: return pointTexCoord;
0442: }
0443:
0444: /**
0445: * Get the color indices for the intersected primitive. For a non-indexed
0446: * primitive, this will be the same as the primitive vertex indices
0447: * If the geometry array does not contain colors this will return null.
0448: * @return an array indices
0449: */
0450: public int[] getPrimitiveColorIndices() {
0451: if (hasColors && (primitiveColorIndices == null)) {
0452: if (geometryIsIndexed()) {
0453: primitiveColorIndices = new int[primitiveVertexIndices.length];
0454: for (int i = 0; i < primitiveVertexIndices.length; i++) {
0455: primitiveColorIndices[i] = ((IndexedGeometryArray) (geometry))
0456: .getColorIndex(primitiveVertexIndices[i]);
0457: }
0458: } else {
0459: primitiveColorIndices = primitiveVertexIndices;
0460: }
0461: }
0462: return primitiveColorIndices;
0463: }
0464:
0465: /**
0466: * Get the colors of the intersected primitive. This will return null if
0467: * the primitive does not contain colors. If the geometry was defined
0468: * using GeometryArray.COLOR_3, the 'w' value of the color will be set to 1.0.
0469: * @return an array of Point3d's for the primitive that was intersected
0470: */
0471: public Color4f[] getPrimitiveColors() {
0472: // System.out.println("PI.getPrimitiveColors " + primitiveColors);
0473: GeometryArray geom = (GeometryArray) geometry;
0474:
0475: if (hasColors && (primitiveColors == null)) {
0476: primitiveColors = new Color4f[primitiveVertexIndices.length];
0477: int[] indices = getPrimitiveColorIndices();
0478: int vformat = geom.getVertexFormat();
0479: if ((vformat & GeometryArray.BY_REFERENCE) == 0) {
0480: if ((vformat & GeometryArray.COLOR_4) == GeometryArray.COLOR_4) {
0481: for (int i = 0; i < indices.length; i++) {
0482: primitiveColors[i] = new Color4f();
0483: geom.getColor(indices[i], primitiveColors[i]);
0484: }
0485: } else {
0486: Color3f color = new Color3f();
0487: for (int i = 0; i < indices.length; i++) {
0488: primitiveColors[i] = new Color4f();
0489: geom.getColor(indices[i], color);
0490: primitiveColors[i].x = color.x;
0491: primitiveColors[i].y = color.y;
0492: primitiveColors[i].z = color.z;
0493: primitiveColors[i].w = 1.0f;
0494: }
0495: }
0496: } else {
0497: if ((vformat & GeometryArray.INTERLEAVED) == 0) {
0498: float[] floatData = geom.getColorRefFloat();
0499: // If data was set as float then ..
0500: if (floatData == null) {
0501: byte[] byteData = geom.getColorRefByte();
0502: if (byteData == null) {
0503: throw new UnsupportedOperationException(
0504: "Deprecated : BY_REF - c3b and c3f");
0505: } else {
0506: // Could be color3 or color4
0507: int val;
0508: if ((vformat & GeometryArray.COLOR_4) == GeometryArray.COLOR_4) {
0509: for (int i = 0; i < indices.length; i++) {
0510: val = indices[i] << 2; // for color4f
0511: primitiveColors[i] = new Color4f(
0512: byteData[val],
0513: byteData[val + 1],
0514: byteData[val + 2],
0515: byteData[val + 3]);
0516:
0517: }
0518: } else {
0519: for (int i = 0; i < indices.length; i++) {
0520: val = indices[i] * 3; // for color3f
0521: primitiveColors[i] = new Color4f(
0522: byteData[val],
0523: byteData[val + 1],
0524: byteData[val + 2], 1.0f);
0525:
0526: }
0527: }
0528: }
0529: } else {
0530: // Could be color3 or color4
0531: int val;
0532: if ((vformat & GeometryArray.COLOR_4) == GeometryArray.COLOR_4) {
0533: for (int i = 0; i < indices.length; i++) {
0534: val = indices[i] << 2; // for color4f
0535: primitiveColors[i] = new Color4f(
0536: floatData[val],
0537: floatData[val + 1],
0538: floatData[val + 2],
0539: floatData[val + 3]);
0540: }
0541: } else {
0542: for (int i = 0; i < indices.length; i++) {
0543: val = indices[i] * 3; // for color3f
0544: primitiveColors[i] = new Color4f(
0545: floatData[val],
0546: floatData[val + 1],
0547: floatData[val + 2], 1.0f);
0548:
0549: }
0550: }
0551: }
0552:
0553: } else {
0554: float[] floatData = geom.getInterleavedVertices();
0555: int offset = getInterleavedColorOffset(geom);
0556: int stride = getInterleavedStride(geom);
0557: for (int i = 0; i < indices.length; i++) {
0558: int val = stride * indices[i] + offset;
0559: if ((vformat & GeometryArray.COLOR_4) == GeometryArray.COLOR_4) {
0560: primitiveColors[i] = new Color4f(
0561: floatData[val], floatData[val + 1],
0562: floatData[val + 2],
0563: floatData[val + 3]);
0564: } else {
0565: primitiveColors[i] = new Color4f(
0566: floatData[val], floatData[val + 1],
0567: floatData[val + 2], 1.0f);
0568: }
0569: }
0570: }
0571: }
0572: }
0573: return primitiveColors;
0574: }
0575:
0576: /**
0577: * Get the coordinates indices for the intersected primitive. For a non-indexed
0578: * primitive, this will be the same as the primitive vertex indices
0579: * @return an array indices
0580: */
0581: public int[] getPrimitiveCoordinateIndices() {
0582: if (primitiveCoordinateIndices == null) {
0583: if (geometryIsIndexed()) {
0584: primitiveCoordinateIndices = new int[primitiveVertexIndices.length];
0585: for (int i = 0; i < primitiveVertexIndices.length; i++) {
0586: primitiveCoordinateIndices[i] = ((IndexedGeometryArray) (geometry))
0587: .getCoordinateIndex(primitiveVertexIndices[i]);
0588: }
0589: } else {
0590: primitiveCoordinateIndices = primitiveVertexIndices;
0591: }
0592: }
0593: return primitiveCoordinateIndices;
0594: }
0595:
0596: /**
0597: * Get the local coordinates intersected primitive
0598: * @return an array of Point3d's for the primitive that was intersected
0599: */
0600: public Point3d[] getPrimitiveCoordinates() {
0601: // System.out.println("PI.getPrimitiveCoordinates " + primitiveCoordinates);
0602: GeometryArray geom = (GeometryArray) geometry;
0603:
0604: if (primitiveCoordinates == null) {
0605: primitiveCoordinates = new Point3d[primitiveVertexIndices.length];
0606: int[] indices = getPrimitiveCoordinateIndices();
0607: int vformat = geom.getVertexFormat();
0608: int val;
0609:
0610: // System.out.println("---- indices.length - " + indices.length);
0611: if ((vformat & GeometryArray.BY_REFERENCE) == 0) {
0612: for (int i = 0; i < indices.length; i++) {
0613: primitiveCoordinates[i] = new Point3d();
0614: // System.out.println("PickIntersection : indices["+i+"] = " + indices[i]);
0615: geom.getCoordinate(indices[i],
0616: primitiveCoordinates[i]);
0617: }
0618: } else {
0619: if ((vformat & GeometryArray.INTERLEAVED) == 0) {
0620: double[] doubleData = geom.getCoordRefDouble();
0621: // If data was set as float then ..
0622: if (doubleData == null) {
0623: float[] floatData = geom.getCoordRefFloat();
0624: if (floatData == null) {
0625: throw new UnsupportedOperationException(
0626: "Deprecated : BY_REF - c3f and c3d");
0627: } else {
0628: for (int i = 0; i < indices.length; i++) {
0629: val = indices[i] * 3;
0630: primitiveCoordinates[i] = new Point3d(
0631: floatData[val],
0632: floatData[val + 1],
0633: floatData[val + 2]);
0634: }
0635: }
0636: } else {
0637: for (int i = 0; i < indices.length; i++) {
0638: val = indices[i] * 3;
0639: primitiveCoordinates[i] = new Point3d(
0640: doubleData[val],
0641: doubleData[val + 1],
0642: doubleData[val + 2]);
0643: }
0644: }
0645: } else {
0646: float[] floatData = geom.getInterleavedVertices();
0647: int offset = getInterleavedVertexOffset(geom);
0648: int stride = offset + 3; // for the vertices .
0649: for (int i = 0; i < indices.length; i++) {
0650: val = stride * indices[i] + offset;
0651: primitiveCoordinates[i] = new Point3d(
0652: floatData[val], floatData[val + 1],
0653: floatData[val + 2]);
0654: }
0655: }
0656: }
0657:
0658: }
0659: return primitiveCoordinates;
0660: }
0661:
0662: /**
0663: * Get VWorld coordinates of the intersected primitive
0664: * @return an array of Point3d's for the primitive that was picked
0665: */
0666: public Point3d[] getPrimitiveCoordinatesVW() {
0667:
0668: // System.out.println("PI.getPrimitiveCoordinatesVW " + primitiveCoordinatesVW);
0669:
0670: if (primitiveCoordinatesVW == null) {
0671: // We need to call getPrimitiveCoordinates first.
0672: Point3d[] coords = getPrimitiveCoordinates();
0673:
0674: primitiveCoordinatesVW = new Point3d[coords.length];
0675: for (int i = 0; i < coords.length; i++) {
0676: primitiveCoordinatesVW[i] = new Point3d();
0677:
0678: primitiveCoordinatesVW[i].x = coords[i].x;
0679: primitiveCoordinatesVW[i].y = coords[i].y;
0680: primitiveCoordinatesVW[i].z = coords[i].z;
0681:
0682: l2vw.transform(primitiveCoordinatesVW[i]);
0683: }
0684: }
0685: return primitiveCoordinatesVW;
0686: }
0687:
0688: /**
0689: * Get the normal indices for the intersected primitive. For a non-indexed
0690: * primitive, this will be the same as the primitive vertex indices
0691: * If the geometry array does not contain normals this will return null
0692: * @return an array indices
0693: */
0694: public int[] getPrimitiveNormalIndices() {
0695: if (hasNormals && (primitiveNormalIndices == null)) {
0696: if (geometryIsIndexed()) {
0697: primitiveNormalIndices = new int[primitiveVertexIndices.length];
0698: for (int i = 0; i < primitiveVertexIndices.length; i++) {
0699: primitiveNormalIndices[i] = ((IndexedGeometryArray) (geometry))
0700: .getNormalIndex(primitiveVertexIndices[i]);
0701: }
0702: } else {
0703: primitiveNormalIndices = primitiveVertexIndices;
0704: }
0705: }
0706: return primitiveNormalIndices;
0707: }
0708:
0709: /**
0710: * Get the normals of the intersected primitive. This will return null if
0711: * the primitive does not contain normals.
0712: * @return an array of Point3d's for the primitive that was intersected
0713: */
0714: public Vector3f[] getPrimitiveNormals() {
0715: // System.out.println("PI.getPrimitiveNormals " + primitiveNormals);
0716: GeometryArray geom = (GeometryArray) geometry;
0717:
0718: if (hasNormals && (primitiveNormals == null)) {
0719: primitiveNormals = new Vector3f[primitiveVertexIndices.length];
0720: int[] indices = getPrimitiveNormalIndices();
0721: int vformat = geom.getVertexFormat();
0722: int val;
0723:
0724: if ((vformat & GeometryArray.BY_REFERENCE) == 0) {
0725: for (int i = 0; i < indices.length; i++) {
0726: primitiveNormals[i] = new Vector3f();
0727: geom.getNormal(indices[i], primitiveNormals[i]);
0728: }
0729: } else {
0730: if ((vformat & GeometryArray.INTERLEAVED) == 0) {
0731: float[] floatNormals = geom.getNormalRefFloat();
0732: if (floatNormals != null) {
0733: for (int i = 0; i < indices.length; i++) {
0734: val = indices[i] * 3;
0735: primitiveNormals[i] = new Vector3f(
0736: floatNormals[val],
0737: floatNormals[val + 1],
0738: floatNormals[val + 2]);
0739: }
0740: } else {
0741: throw new UnsupportedOperationException(
0742: "Deprecated : BY_REF - n3f");
0743: }
0744: } else {
0745: float[] floatData = geom.getInterleavedVertices();
0746: int offset = getInterleavedColorOffset(geom);
0747: int stride = getInterleavedStride(geom);
0748: for (int i = 0; i < indices.length; i++) {
0749: val = stride * indices[i] + offset;
0750: primitiveNormals[i] = new Vector3f(
0751: floatData[val], floatData[val + 1],
0752: floatData[val + 2]);
0753:
0754: }
0755: }
0756: }
0757: }
0758: return primitiveNormals;
0759: }
0760:
0761: /**
0762: * Get the texture coordinate indices for the intersected primitive at the specifed
0763: * index in the specified texture coordinate set. For a non-indexed
0764: * primitive, this will be the same as the primitive vertex indices
0765: * If the geometry array does not contain texture coordinates, this will
0766: * return null.
0767: * @return an array indices
0768: */
0769: public int[] getPrimitiveTexCoordIndices(int index) {
0770: if (hasTexCoords && (primitiveTexCoordIndices == null)) {
0771: if (geometryIsIndexed()) {
0772: primitiveTexCoordIndices = new int[primitiveVertexIndices.length];
0773: for (int i = 0; i < primitiveVertexIndices.length; i++) {
0774: primitiveTexCoordIndices[i] = ((IndexedGeometryArray) (geometry))
0775: .getTextureCoordinateIndex(index,
0776: primitiveVertexIndices[i]);
0777: }
0778: } else {
0779: primitiveTexCoordIndices = primitiveVertexIndices;
0780: }
0781: }
0782: return primitiveTexCoordIndices;
0783: }
0784:
0785: /**
0786: * Get the texture coordinates of the intersected primitive at the specifed
0787: * index in the specified texture coordinate set.
0788: * null if the primitive does not contain texture coordinates.
0789: * If the geometry was defined
0790: * using GeometryArray.TEXTURE_COORDINATE_2, the 'z' value of the texture
0791: * coordinate will be set to 0.0.
0792: * @return an array of TexCoord3f's for the primitive that was intersected
0793: */
0794: public TexCoord3f[] getPrimitiveTexCoords(int index) {
0795: // System.out.println("PI.getPrimitiveTexCoords " + primitiveTexCoords);
0796: GeometryArray geom = (GeometryArray) geometry;
0797:
0798: if (primitiveTexCoords == null) {
0799: primitiveTexCoords = new TexCoord3f[primitiveVertexIndices.length];
0800: int[] indices = getPrimitiveTexCoordIndices(index);
0801: int vformat = geom.getVertexFormat();
0802: if ((vformat & GeometryArray.BY_REFERENCE) == 0) {
0803: for (int i = 0; i < indices.length; i++) {
0804: primitiveTexCoords[i] = new TexCoord3f();
0805: geom.getTextureCoordinate(index, indices[i],
0806: primitiveTexCoords[i]);
0807: }
0808: } else {
0809: if ((vformat & GeometryArray.INTERLEAVED) == 0) {
0810: int val;
0811: float[] floatTexCoords = geom
0812: .getTexCoordRefFloat(index);
0813: if (floatTexCoords != null) {
0814: if ((vformat & GeometryArray.TEXTURE_COORDINATE_2) == GeometryArray.TEXTURE_COORDINATE_2) {
0815: for (int i = 0; i < indices.length; i++) {
0816: val = indices[i] << 1; // t2f
0817: primitiveTexCoords[i] = new TexCoord3f(
0818: floatTexCoords[val],
0819: floatTexCoords[val + 1], 0.0f);
0820: }
0821: } else {
0822: for (int i = 0; i < indices.length; i++) {
0823: val = indices[i] * 3; // t3f
0824: primitiveTexCoords[i] = new TexCoord3f(
0825: floatTexCoords[val],
0826: floatTexCoords[val + 1],
0827: floatTexCoords[val + 2]);
0828: }
0829: }
0830: } else {
0831: throw new UnsupportedOperationException(
0832: "Deprecated : BY_REF - t2f and t3f");
0833: }
0834: } else {
0835: float[] floatData = geom.getInterleavedVertices();
0836: int stride = getInterleavedStride(geom);
0837: int offset;
0838: // Get the correct tex coord set
0839: if ((vformat & GeometryArray.TEXTURE_COORDINATE_2) == GeometryArray.TEXTURE_COORDINATE_2) {
0840: offset = index << 1;
0841: } else {
0842: offset = index * 3;
0843: }
0844: for (int i = 0; i < indices.length; i++) {
0845: int val = stride * indices[i];
0846: if ((vformat & GeometryArray.TEXTURE_COORDINATE_2) == GeometryArray.TEXTURE_COORDINATE_2) {
0847: primitiveTexCoords[i] = new TexCoord3f(
0848: floatData[val + offset],
0849: floatData[val + 1 + offset], 0.0f);
0850: } else {
0851: primitiveTexCoords[i] = new TexCoord3f(
0852: floatData[val + offset],
0853: floatData[val + 1 + offset],
0854: floatData[val + 2 + offset]);
0855: }
0856: }
0857: }
0858: }
0859: }
0860: return primitiveTexCoords;
0861: }
0862:
0863: /**
0864: * Get vertex indices of the intersected primitive
0865: * @return an array which contains the list of indices
0866: */
0867: public int[] getPrimitiveVertexIndices() {
0868: return primitiveVertexIndices;
0869: }
0870:
0871: /**
0872: * Gets the IntersectionInfo this intersection is part of.
0873: */
0874: public PickInfo.IntersectionInfo getIntersectionInfo() {
0875: return iInfo;
0876: }
0877:
0878: /**
0879: * String representation of this object
0880: */
0881: public String toString() {
0882: String rt = new String("PickIntersection: ");
0883: rt += " IntersectionInfo = " + iInfo + "\n";
0884: rt += " geometry = " + geometry + "\n";
0885: if (distance != -1)
0886: rt += " dist:" + distance + "\n";
0887: if (pointCoordinates != null)
0888: rt += " pt:" + pointCoordinates + "\n";
0889: if (pointCoordinatesVW != null)
0890: rt += " ptVW:" + pointCoordinatesVW + "\n";
0891:
0892: if (primitiveCoordinateIndices != null) {
0893: rt += " prim coordinate ind:" + "\n";
0894: for (int i = 0; i < primitiveCoordinateIndices.length; i++) {
0895: rt += " " + primitiveCoordinateIndices[i] + "\n";
0896: }
0897: }
0898:
0899: if (primitiveColorIndices != null) {
0900: rt += " prim color ind:" + "\n";
0901: for (int i = 0; i < primitiveColorIndices.length; i++) {
0902: rt += " " + primitiveColorIndices[i] + "\n";
0903: }
0904: }
0905:
0906: if (primitiveNormalIndices != null) {
0907: rt += " prim normal ind:" + "\n";
0908: for (int i = 0; i < primitiveNormalIndices.length; i++) {
0909: rt += " " + primitiveNormalIndices[i] + "\n";
0910: }
0911: }
0912:
0913: if (primitiveTexCoordIndices != null) {
0914: rt += " prim texture ind:" + "\n";
0915: for (int i = 0; i < primitiveTexCoordIndices.length; i++) {
0916: rt += " " + primitiveTexCoordIndices[i] + "\n";
0917: }
0918: }
0919:
0920: if (closestVertexCoordinates != null) {
0921: rt += " clos. vert:" + closestVertexCoordinates + "\n";
0922: }
0923:
0924: if (closestVertexCoordinatesVW != null) {
0925: rt += " clos. vert:" + closestVertexCoordinatesVW + "\n";
0926: }
0927:
0928: if (closestVertexIndex != -1) {
0929: rt += " clos. vert. ind.:" + closestVertexIndex + "\n";
0930: }
0931: return rt;
0932: }
0933:
0934: /******************** Helper methods ***************************************/
0935:
0936: int getInterleavedVertexOffset(GeometryArray geo) {
0937: int offset = 0;
0938: int vformat = geo.getVertexFormat();
0939: if ((vformat & GeometryArray.COLOR_3) == GeometryArray.COLOR_3) {
0940: offset += 3;
0941: } else if ((vformat & GeometryArray.COLOR_4) == GeometryArray.COLOR_4) {
0942: offset += 4;
0943: }
0944: if ((vformat & GeometryArray.NORMALS) != 0)
0945: offset += 3;
0946: if ((vformat & GeometryArray.TEXTURE_COORDINATE_2) == GeometryArray.TEXTURE_COORDINATE_2) {
0947: offset += 2 * geo.getTexCoordSetCount();
0948: } else if ((vformat & GeometryArray.TEXTURE_COORDINATE_3) == GeometryArray.TEXTURE_COORDINATE_3) {
0949: offset += 3 * geo.getTexCoordSetCount();
0950: }
0951:
0952: return offset;
0953: }
0954:
0955: int getInterleavedStride(GeometryArray geo) {
0956: int offset = 3; // Add 3 for vertices
0957: int vformat = geo.getVertexFormat();
0958: if ((vformat & GeometryArray.COLOR_3) == GeometryArray.COLOR_3) {
0959: offset += 3;
0960: } else if ((vformat & GeometryArray.COLOR_4) == GeometryArray.COLOR_4) {
0961: offset += 4;
0962: }
0963: if ((vformat & GeometryArray.NORMALS) != 0)
0964: offset += 3;
0965: if ((vformat & GeometryArray.TEXTURE_COORDINATE_2) == GeometryArray.TEXTURE_COORDINATE_2) {
0966: offset += 2 * geo.getTexCoordSetCount();
0967: } else if ((vformat & GeometryArray.TEXTURE_COORDINATE_3) == GeometryArray.TEXTURE_COORDINATE_3) {
0968: offset += 3 * geo.getTexCoordSetCount();
0969: }
0970:
0971: return offset;
0972: }
0973:
0974: int getInterleavedColorOffset(GeometryArray geo) {
0975: int offset = 0;
0976: int vformat = geo.getVertexFormat();
0977: if ((vformat & GeometryArray.TEXTURE_COORDINATE_2) == GeometryArray.TEXTURE_COORDINATE_2) {
0978: offset += 2 * geo.getTexCoordSetCount();
0979: } else if ((vformat & GeometryArray.TEXTURE_COORDINATE_3) == GeometryArray.TEXTURE_COORDINATE_3) {
0980: offset += 3 * geo.getTexCoordSetCount();
0981: }
0982:
0983: return offset;
0984: }
0985:
0986: /* ================================================================== */
0987: /* Utility code for interpolating intersection point data */
0988: /* ================================================================== */
0989:
0990: /* absolute value */
0991: double abs(double value) {
0992: if (value < 0.0) {
0993: return -value;
0994: } else {
0995: return value;
0996: }
0997: }
0998:
0999: /* return the axis corresponding to the largest component of delta */
1000: int maxAxis(Vector3d delta) {
1001: int axis = X_AXIS;
1002: double max = abs(delta.x);
1003: if (abs(delta.y) > max) {
1004: axis = Y_AXIS;
1005: max = abs(delta.y);
1006: }
1007: if (abs(delta.z) > max) {
1008: axis = Z_AXIS;
1009: }
1010: return axis;
1011: }
1012:
1013: /* Triangle interpolation. Basic idea:
1014: * Map the verticies of the triangle to the form:
1015: *
1016: * L--------R
1017: * \ /
1018: * IL+--P-+IR
1019: * \ /
1020: * Base
1021: *
1022: where P is the intersection point Base, L and R and the triangle
1023: points. IL and IR are the projections if P along the Base-L and Base-R
1024: edges using an axis:
1025:
1026: IL = leftFactor * L + (1- leftFactor) * Base
1027: IR = rightFactor * R + (1-rightFactor) * Base
1028:
1029: then find the interp factor, midFactor, for P between IL and IR. If
1030: this is outside the range 0->1 then we have the wrong triangle of a
1031: quad and we return false.
1032:
1033: Else, the weighting is:
1034:
1035: IP = midFactor * IL + (1 - midFactor) * IR;
1036:
1037: Solving for weights for the formula:
1038: IP = BaseWeight * Base + LeftWeight * L + RightWeight * R;
1039: We get:
1040: BaseWeight = 1 - midFactor * leftFactor
1041: - rightFactor + midFactor * rightFactor;
1042: LeftWeight = midFactor * leftFactor;
1043: RightWeight = righFactor - midFactor * rightFactor;
1044: As a check, note that the sum of the weights is 1.0.
1045: */
1046:
1047: boolean interpTriangle(int index0, int index1, int index2,
1048: Point3d[] coords, Point3d intPt) {
1049:
1050: // find the longest edge, we'll use that to pick the axis */
1051: Vector3d delta0 = new Vector3d();
1052: Vector3d delta1 = new Vector3d();
1053: Vector3d delta2 = new Vector3d();
1054: delta0.sub(coords[index1], coords[index0]);
1055: delta1.sub(coords[index2], coords[index0]);
1056: delta2.sub(coords[index2], coords[index1]);
1057: double len0 = delta0.lengthSquared();
1058: double len1 = delta1.lengthSquared();
1059: double len2 = delta2.lengthSquared();
1060: Vector3d longest = delta0;
1061: double maxLen = len0;
1062: if (len1 > maxLen) {
1063: longest = delta1;
1064: maxLen = len1;
1065: }
1066: if (len2 > maxLen) {
1067: longest = delta2;
1068: }
1069: int mainAxis = maxAxis(longest);
1070:
1071: /*
1072: System.out.println("index0 = " + index0 + " index1 = " + index1 +
1073: " index2 = " + index2);
1074:
1075: System.out.println("coords[index0] = " + coords[index0]);
1076: System.out.println("coords[index1] = " + coords[index1]);
1077: System.out.println("coords[index2] = " + coords[index2]);
1078: System.out.println("intPt = " + intPt);
1079:
1080: System.out.println("delta0 = " + delta0 + " len0 " + len0);
1081: System.out.println("delta1 = " + delta1 + " len1 " + len1);
1082: System.out.println("delta2 = " + delta2 + " len2 " + len2);
1083: */
1084:
1085: /* now project the intersection point along the axis onto the edges */
1086: double[] factor = new double[3];
1087: /* the factor is for the projection opposide the vertex 0 = 1->2, etc*/
1088: factor[0] = getInterpFactorForBase(intPt, coords[index1],
1089: coords[index2], mainAxis);
1090: factor[1] = getInterpFactorForBase(intPt, coords[index2],
1091: coords[index0], mainAxis);
1092: factor[2] = getInterpFactorForBase(intPt, coords[index0],
1093: coords[index1], mainAxis);
1094:
1095: if (debug) {
1096: System.out.println("intPt = " + intPt);
1097: switch (mainAxis) {
1098: case X_AXIS:
1099: System.out.println("mainAxis = X_AXIS");
1100: break;
1101: case Y_AXIS:
1102: System.out.println("mainAxis = Y_AXIS");
1103: break;
1104: case Z_AXIS:
1105: System.out.println("mainAxis = Z_AXIS");
1106: break;
1107: }
1108: System.out.println("factor[0] = " + factor[0]);
1109: System.out.println("factor[1] = " + factor[1]);
1110: System.out.println("factor[2] = " + factor[2]);
1111: }
1112:
1113: /* Find the factor that is out of range, it will tell us which
1114: * vertex to use for base
1115: */
1116: int base, left, right;
1117: double leftFactor, rightFactor;
1118: if ((factor[0] < 0.0) || (factor[0] > 1.0)) {
1119: base = index0;
1120: right = index1;
1121: left = index2;
1122: rightFactor = factor[2];
1123: leftFactor = 1.0 - factor[1];
1124: if (debug) {
1125: System.out.println("base 0, rightFactor = "
1126: + rightFactor + " leftFactor = " + leftFactor);
1127: }
1128: } else if ((factor[1] < 0.0) || (factor[1] > 1.0)) {
1129: base = index1;
1130: right = index2;
1131: left = index0;
1132: rightFactor = factor[0];
1133: leftFactor = 1.0 - factor[2];
1134: if (debug) {
1135: System.out.println("base 1, rightFactor = "
1136: + rightFactor + " leftFactor = " + leftFactor);
1137: }
1138: } else {
1139: base = index2;
1140: right = index0;
1141: left = index1;
1142: rightFactor = factor[1];
1143: leftFactor = 1.0 - factor[0];
1144: if (debug) {
1145: System.out.println("base 2, rightFactor = "
1146: + rightFactor + " leftFactor = " + leftFactor);
1147: }
1148: }
1149: if (debug) {
1150: System.out.println("base = " + coords[base]);
1151: System.out.println("left = " + coords[left]);
1152: System.out.println("right = " + coords[right]);
1153: }
1154: /* find iLeft and iRight */
1155: Point3d iLeft = new Point3d(leftFactor * coords[left].x
1156: + (1.0 - leftFactor) * coords[base].x, leftFactor
1157: * coords[left].y + (1.0 - leftFactor) * coords[base].y,
1158: leftFactor * coords[left].z + (1.0 - leftFactor)
1159: * coords[base].z);
1160:
1161: Point3d iRight = new Point3d(rightFactor * coords[right].x
1162: + (1.0 - rightFactor) * coords[base].x, rightFactor
1163: * coords[right].y + (1.0 - rightFactor)
1164: * coords[base].y, rightFactor * coords[right].z
1165: + (1.0 - rightFactor) * coords[base].z);
1166:
1167: if (debug) {
1168: System.out.println("iLeft = " + iLeft);
1169: System.out.println("iRight = " + iRight);
1170: }
1171:
1172: /* now find an axis and solve for midFactor */
1173: delta0.sub(iLeft, iRight);
1174: int midAxis = maxAxis(delta0);
1175: double midFactor = getInterpFactor(intPt, iRight, iLeft,
1176: midAxis);
1177:
1178: if (debug) {
1179: switch (midAxis) {
1180: case X_AXIS:
1181: System.out.println("midAxis = X_AXIS");
1182: break;
1183: case Y_AXIS:
1184: System.out.println("midAxis = Y_AXIS");
1185: break;
1186: case Z_AXIS:
1187: System.out.println("midAxis = Z_AXIS");
1188: break;
1189: }
1190: System.out.println("midFactor = " + midFactor);
1191: }
1192:
1193: if (midFactor < 0.0) {
1194: // System.out.println("midFactor = " + midFactor);
1195: if ((midFactor + TOL) >= 0.0) {
1196: // System.out.println("In Tol case : midFactor = " + midFactor);
1197: midFactor = 0.0;
1198: } else {
1199: /* int point is outside triangle */
1200: return false;
1201: }
1202: } else if (midFactor > 1.0) {
1203: // System.out.println("midFactor = " + midFactor);
1204: if ((midFactor - TOL) <= 1.0) {
1205: // System.out.println("In Tol case : midFactor = " + midFactor);
1206: midFactor = 1.0;
1207: } else {
1208: /* int point is outside triangle */
1209: return false;
1210: }
1211: }
1212:
1213: // Assign the weights
1214: interpWeights[base] = 1.0 - midFactor * leftFactor
1215: - rightFactor + midFactor * rightFactor;
1216: interpWeights[left] = midFactor * leftFactor;
1217: interpWeights[right] = rightFactor - midFactor * rightFactor;
1218: return true;
1219:
1220: }
1221:
1222: /* Get the interpolation weights for each of the verticies of the
1223: * primitive.
1224: */
1225: double[] getInterpWeights() {
1226:
1227: Point3d pt = getPointCoordinates();
1228: Point3d[] coordinates = getPrimitiveCoordinates();
1229: double factor;
1230: int axis;
1231:
1232: if (interpWeights != null) {
1233: return interpWeights;
1234: }
1235:
1236: interpWeights = new double[coordinates.length];
1237:
1238: // Interpolate
1239: switch (coordinates.length) {
1240: case 1:
1241: // Nothing to interpolate
1242: interpWeights[0] = 1.0;
1243: break;
1244: case 2: // edge
1245: Vector3d delta = new Vector3d();
1246: delta.sub(coordinates[1], coordinates[0]);
1247: axis = maxAxis(delta);
1248: factor = getInterpFactor(pt, coordinates[1],
1249: coordinates[0], axis);
1250: interpWeights[0] = factor;
1251: interpWeights[1] = 1.0 - factor;
1252: break;
1253: case 3: // triangle
1254: if (!interpTriangle(0, 1, 2, coordinates, pt)) {
1255: throw new RuntimeException(
1256: "Interp point outside triangle");
1257: }
1258: break;
1259: case 4: // quad
1260: if (!interpTriangle(0, 1, 2, coordinates, pt)) {
1261: if (!interpTriangle(0, 2, 3, coordinates, pt)) {
1262: throw new RuntimeException(
1263: "Interp point outside quad");
1264: }
1265: }
1266: break;
1267: default:
1268: throw new RuntimeException("Unexpected number of points.");
1269: }
1270: return interpWeights;
1271: }
1272:
1273: /**
1274: Calculate the interpolation factor for point p by projecting it along
1275: an axis (x,y,z) onto the edge between p1 and p2. If the result is
1276: in the 0->1 range, point is between p1 and p2 (0 = point is at p1,
1277: 1 => point is at p2).
1278: */
1279: private static float getInterpFactor(Point3d p, Point3d p1,
1280: Point3d p2, int axis) {
1281: float t;
1282: switch (axis) {
1283: case X_AXIS:
1284: if (p1.x == p2.x)
1285: //t = Float.MAX_VALUE; // TODO: should be 0?
1286: t = 0.0f;
1287: else
1288: t = (float) ((p1.x - p.x) / (p1.x - p2.x));
1289: break;
1290: case Y_AXIS:
1291: if (p1.y == p2.y)
1292: // t = Float.MAX_VALUE;
1293: t = 0.0f;
1294: else
1295: t = (float) ((p1.y - p.y) / (p1.y - p2.y));
1296: break;
1297: case Z_AXIS:
1298: if (p1.z == p2.z)
1299: // t = Float.MAX_VALUE;
1300: t = 0.0f;
1301: else
1302: t = (float) ((p1.z - p.z) / (p1.z - p2.z));
1303: break;
1304: default:
1305: throw new RuntimeException("invalid axis parameter " + axis
1306: + " (must be 0-2)");
1307: }
1308: return t;
1309: }
1310:
1311: /**
1312: Calculate the interpolation factor for point p by projecting it along
1313: an axis (x,y,z) onto the edge between p1 and p2. If the result is
1314: in the 0->1 range, point is between p1 and p2 (0 = point is at p1,
1315: 1 => point is at p2).
1316: return MAX_VALUE if component of vertices are the same.
1317: */
1318: private static float getInterpFactorForBase(Point3d p, Point3d p1,
1319: Point3d p2, int axis) {
1320: float t;
1321: switch (axis) {
1322: case X_AXIS:
1323: if (p1.x == p2.x)
1324: t = Float.MAX_VALUE;
1325: else
1326: t = (float) ((p1.x - p.x) / (p1.x - p2.x));
1327: break;
1328: case Y_AXIS:
1329: if (p1.y == p2.y)
1330: t = Float.MAX_VALUE;
1331: else
1332: t = (float) ((p1.y - p.y) / (p1.y - p2.y));
1333: break;
1334: case Z_AXIS:
1335: if (p1.z == p2.z)
1336: t = Float.MAX_VALUE;
1337: else
1338: t = (float) ((p1.z - p.z) / (p1.z - p2.z));
1339: break;
1340: default:
1341: throw new RuntimeException("invalid axis parameter " + axis
1342: + " (must be 0-2)");
1343: }
1344: return t;
1345: }
1346:
1347: } // PickIntersection
|