001/** 002 * Copyright (c) 2008-2014 Ardor Labs, Inc. 003 * 004 * This file is part of Ardor3D. 005 * 006 * Ardor3D is free software: you can redistribute it and/or modify it 007 * under the terms of its license which may be found in the accompanying 008 * LICENSE file or at <http://www.ardor3d.com/LICENSE>. 009 */ 010 011package com.ardor3d.intersection; 012 013import java.util.Arrays; 014import java.util.List; 015 016import com.ardor3d.math.Vector3; 017import com.ardor3d.util.Ardor3dException; 018 019public class IntersectionRecord { 020 021 private static final class Intersection implements Comparable<Intersection> { 022 private final double _distance; 023 private final Vector3 _point; 024 private final Vector3 _normal; 025 private final PrimitiveKey _primitiveKey; 026 027 private Intersection(final double distance, final Vector3 point, final Vector3 normal, 028 final PrimitiveKey primitiveKey) { 029 _distance = distance; 030 _point = point; 031 _normal = normal; 032 _primitiveKey = primitiveKey; 033 } 034 035 @Override 036 public int compareTo(final Intersection other) { 037 return _distance == other._distance ? 0 : (_distance < other._distance ? -1 : 1); 038 } 039 } 040 041 private final Intersection[] _intersections; 042 043 private boolean _isSorted = true; 044 045 /** 046 * Instantiates a new IntersectionRecord defining the distances and points. 047 * 048 * @param distances 049 * the distances of this intersection. 050 * @param points 051 * the points of this intersection. 052 * @throws Ardor3dException 053 * if distances.length != points.length 054 */ 055 public IntersectionRecord(final double[] distances, final Vector3[] points) { 056 this(distances, points, null); 057 } 058 059 /** 060 * Instantiates a new IntersectionRecord defining the distances and points. 061 * 062 * @param distances 063 * the distances of this intersection. 064 * @param points 065 * the points of this intersection. 066 * @param primitives 067 * the primitives at each index. May be null. 068 * @throws Ardor3dException 069 * if distances.length != points.length or points.length != primitives.size() (if primitives is not 070 * null) 071 */ 072 public IntersectionRecord(final double[] distances, final Vector3[] points, final List<PrimitiveKey> primitives) { 073 this(distances, points, null, primitives); 074 } 075 076 /** 077 * Instantiates a new IntersectionRecord defining the distances and points. 078 * 079 * @param distances 080 * the distances of this intersection. 081 * @param points 082 * the points of this intersection. 083 * @param normals 084 * the normals of this intersection. 085 * @param primitives 086 * the primitives at each index. May be null. 087 * @throws Ardor3dException 088 * if distances.length != points.length or points.length != primitives.size() (if primitives is not 089 * null) 090 */ 091 public IntersectionRecord(final double[] distances, final Vector3[] points, final Vector3[] normals, 092 final List<PrimitiveKey> primitives) { 093 if (distances.length != points.length || (primitives != null && points.length != primitives.size()) 094 || (normals != null && points.length != normals.length)) { 095 throw new Ardor3dException("All arguments must have an equal number of elements."); 096 } 097 _isSorted = distances.length < 2; 098 _intersections = new Intersection[distances.length]; 099 for (int i = 0; i < distances.length; i++) { 100 _intersections[i] = new Intersection(distances[i], points[i], normals != null ? normals[i] : null, 101 primitives != null ? primitives.get(i) : null); 102 } 103 } 104 105 /** 106 * Sorts intersections from near to far 107 */ 108 public void sortIntersections() { 109 if (!_isSorted) { 110 Arrays.sort(_intersections); 111 _isSorted = true; 112 } 113 } 114 115 /** 116 * @return the number of intersections that occurred. 117 */ 118 public int getNumberOfIntersections() { 119 return _intersections.length; 120 } 121 122 /** 123 * Returns an intersection point at a provided index. 124 * 125 * @param index 126 * the index of the point to obtain. 127 * @return the point at the index of the array. 128 */ 129 public Vector3 getIntersectionPoint(final int index) { 130 return _intersections[index]._point; 131 } 132 133 /** 134 * Returns an intersection normal at a provided index. 135 * 136 * @param index 137 * the index of the point to obtain. 138 * @return the normal at the index of the array. 139 */ 140 public Vector3 getIntersectionNormal(final int index) { 141 return _intersections[index]._normal; 142 } 143 144 /** 145 * Returns an intersection distance at a provided index. 146 * 147 * @param index 148 * the index of the distance to obtain. 149 * @return the distance at the index of the array. 150 */ 151 public double getIntersectionDistance(final int index) { 152 return _intersections[index]._distance; 153 } 154 155 /** 156 * @param index 157 * the index of the primitive to obtain. 158 * @return the primitive at the given index. 159 */ 160 public PrimitiveKey getIntersectionPrimitive(final int index) { 161 return _intersections[index]._primitiveKey; 162 } 163 164 /** 165 * @return the smallest distance in the distance array or -1 if there are no distances in this. 166 */ 167 public double getClosestDistance() { 168 final int i = getClosestIntersection(); 169 return i != -1 ? _intersections[i]._distance : -1.0; 170 } 171 172 /** 173 * @return the largest distance in the distance array or -1 if there are no distances in this. 174 */ 175 public double getFurthestDistance() { 176 final int i = getFurthestIntersection(); 177 return i != -1 ? _intersections[i]._distance : -1.0; 178 } 179 180 /** 181 * @return the index in this record with the smallest relative distance or -1 if there are no distances in this 182 * record. 183 */ 184 public int getClosestIntersection() { 185 int index = -1; 186 if (_isSorted) { 187 index = _intersections.length > 0 ? 0 : -1; 188 } else { 189 double min = Double.MAX_VALUE; 190 for (int i = _intersections.length; --i >= 0;) { 191 final double val = _intersections[i]._distance; 192 if (val < min) { 193 min = val; 194 index = i; 195 } 196 } 197 } 198 return index; 199 } 200 201 /** 202 * @return the index in this record with the largest relative distance or -1 if there are no distances in this 203 * record. 204 */ 205 public int getFurthestIntersection() { 206 int index = -1; 207 if (_isSorted) { 208 index = _intersections.length > 0 ? _intersections.length - 1 : -1; 209 } else { 210 double max = -Double.MAX_VALUE; 211 for (int i = _intersections.length; --i >= 0;) { 212 final double val = _intersections[i]._distance; 213 if (val > max) { 214 max = val; 215 index = i; 216 } 217 } 218 } 219 return index; 220 } 221 222}