46 * The {@code Box} class defines a 3 dimensional box with the specified size. 47 * A {@code Box} is a 3D geometry primitive created with a given depth, width, 48 * and height. It is centered at the origin. 49 * 50 * @since JavaFX 8.0 51 */ 52 public class Box extends Shape3D { 53 static { 54 // This is used by classes in different packages to get access to 55 // private and package private methods. 56 BoxHelper.setBoxAccessor(new BoxHelper.BoxAccessor() { 57 @Override 58 public NGNode doCreatePeer(Node node) { 59 return ((Box) node).doCreatePeer(); 60 } 61 62 @Override 63 public void doUpdatePeer(Node node) { 64 ((Box) node).doUpdatePeer(); 65 } 66 }); 67 } 68 69 private TriangleMesh mesh; 70 71 /** 72 * Creates a new instance of {@code Box} of dimension 2 by 2 by 2. 73 */ 74 75 public static final double DEFAULT_SIZE = 2; 76 77 { 78 // To initialize the class helper at the begining each constructor of this class 79 BoxHelper.initHelper(this); 80 } 81 82 public Box() { 83 this(DEFAULT_SIZE, DEFAULT_SIZE, DEFAULT_SIZE); 84 } 85 99 * @defaultValue 2.0 100 */ 101 private DoubleProperty depth; 102 103 public final void setDepth(double value) { 104 depthProperty().set(value); 105 } 106 107 public final double getDepth() { 108 return depth == null ? 2 : depth.get(); 109 } 110 111 public final DoubleProperty depthProperty() { 112 if (depth == null) { 113 depth = new SimpleDoubleProperty(Box.this, "depth", DEFAULT_SIZE) { 114 @Override 115 public void invalidated() { 116 NodeHelper.markDirty(Box.this, DirtyBits.MESH_GEOM); 117 manager.invalidateBoxMesh(key); 118 key = 0; 119 impl_geomChanged(); 120 } 121 }; 122 } 123 return depth; 124 } 125 126 /** 127 * Defines the height or the Y dimension of the Box. 128 * 129 * @defaultValue 2.0 130 */ 131 private DoubleProperty height; 132 133 public final void setHeight(double value) { 134 heightProperty().set(value); 135 } 136 137 public final double getHeight() { 138 return height == null ? 2 : height.get(); 139 } 140 141 public final DoubleProperty heightProperty() { 142 if (height == null) { 143 height = new SimpleDoubleProperty(Box.this, "height", DEFAULT_SIZE) { 144 @Override 145 public void invalidated() { 146 NodeHelper.markDirty(Box.this, DirtyBits.MESH_GEOM); 147 manager.invalidateBoxMesh(key); 148 key = 0; 149 impl_geomChanged(); 150 } 151 }; 152 } 153 return height; 154 } 155 156 /** 157 * Defines the width or the X dimension of the Box. 158 * 159 * @defaultValue 2.0 160 */ 161 private DoubleProperty width; 162 163 public final void setWidth(double value) { 164 widthProperty().set(value); 165 } 166 167 public final double getWidth() { 168 return width == null ? 2 : width.get(); 169 } 170 171 public final DoubleProperty widthProperty() { 172 if (width == null) { 173 width = new SimpleDoubleProperty(Box.this, "width", DEFAULT_SIZE) { 174 @Override 175 public void invalidated() { 176 NodeHelper.markDirty(Box.this, DirtyBits.MESH_GEOM); 177 manager.invalidateBoxMesh(key); 178 key = 0; 179 impl_geomChanged(); 180 } 181 }; 182 } 183 return width; 184 } 185 186 /* 187 * Note: This method MUST only be called via its accessor method. 188 */ 189 private NGNode doCreatePeer() { 190 return new NGBox(); 191 } 192 193 /* 194 * Note: This method MUST only be called via its accessor method. 195 */ 196 private void doUpdatePeer() { 197 if (NodeHelper.isDirty(this, DirtyBits.MESH_GEOM)) { 198 NGBox peer = NodeHelper.getPeer(this); 199 final float w = (float) getWidth(); 200 final float h = (float) getHeight(); 201 final float d = (float) getDepth(); 202 if (w < 0 || h < 0 || d < 0) { 203 peer.updateMesh(null); 204 } else { 205 if (key == 0) { 206 key = generateKey(w, h, d); 207 } 208 mesh = manager.getBoxMesh(w, h, d, key); 209 mesh.updatePG(); 210 peer.updateMesh(mesh.getPGTriangleMesh()); 211 } 212 } 213 } 214 215 /** 216 * @treatAsPrivate implementation detail 217 * @deprecated This is an internal API that is not intended for use and will be removed in the next version 218 */ 219 @Deprecated 220 @Override 221 public BaseBounds impl_computeGeomBounds(BaseBounds bounds, BaseTransform tx) { 222 final float w = (float) getWidth(); 223 final float h = (float) getHeight(); 224 final float d = (float) getDepth(); 225 226 if (w < 0 || h < 0 || d < 0) { 227 return bounds.makeEmpty(); 228 } 229 230 final float hw = w * 0.5f; 231 final float hh = h * 0.5f; 232 final float hd = d * 0.5f; 233 234 bounds = bounds.deriveWithNewBounds(-hw, -hh, -hd, hw, hh, hd); 235 bounds = tx.transform(bounds, bounds); 236 return bounds; 237 } 238 239 /** 240 * @treatAsPrivate implementation detail 241 * @deprecated This is an internal API that is not intended for use and will be removed in the next version 242 */ 243 @Deprecated 244 @Override 245 protected boolean impl_computeContains(double localX, double localY) { 246 double w = getWidth(); 247 double h = getHeight(); 248 return -w <= localX && localX <= w && 249 -h <= localY && localY <= h; 250 } 251 252 /** 253 * @treatAsPrivate implementation detail 254 * @deprecated This is an internal API that is not intended for use and will be removed in the next version 255 */ 256 @Deprecated 257 @Override 258 protected boolean impl_computeIntersects(PickRay pickRay, PickResultChooser pickResult) { 259 260 final double w = getWidth(); 261 final double h = getHeight(); 262 final double d = getDepth(); 263 final double hWidth = w / 2.0; 264 final double hHeight = h / 2.0; 265 final double hDepth = d / 2.0; 266 final Vec3d dir = pickRay.getDirectionNoClone(); 267 final double invDirX = dir.x == 0.0 ? Double.POSITIVE_INFINITY : (1.0 / dir.x); 268 final double invDirY = dir.y == 0.0 ? Double.POSITIVE_INFINITY : (1.0 / dir.y); 269 final double invDirZ = dir.z == 0.0 ? Double.POSITIVE_INFINITY : (1.0 / dir.z); 270 final Vec3d origin = pickRay.getOriginNoClone(); 271 final double originX = origin.x; 272 final double originY = origin.y; 273 final double originZ = origin.z; 274 final boolean signX = invDirX < 0.0; 275 final boolean signY = invDirY < 0.0; 276 final boolean signZ = invDirZ < 0.0; 277 278 double t0 = Double.NEGATIVE_INFINITY; | 46 * The {@code Box} class defines a 3 dimensional box with the specified size. 47 * A {@code Box} is a 3D geometry primitive created with a given depth, width, 48 * and height. It is centered at the origin. 49 * 50 * @since JavaFX 8.0 51 */ 52 public class Box extends Shape3D { 53 static { 54 // This is used by classes in different packages to get access to 55 // private and package private methods. 56 BoxHelper.setBoxAccessor(new BoxHelper.BoxAccessor() { 57 @Override 58 public NGNode doCreatePeer(Node node) { 59 return ((Box) node).doCreatePeer(); 60 } 61 62 @Override 63 public void doUpdatePeer(Node node) { 64 ((Box) node).doUpdatePeer(); 65 } 66 67 @Override 68 public BaseBounds doComputeGeomBounds(Node node, 69 BaseBounds bounds, BaseTransform tx) { 70 return ((Box) node).doComputeGeomBounds(bounds, tx); 71 } 72 73 @Override 74 public boolean doComputeContains(Node node, double localX, double localY) { 75 return ((Box) node).doComputeContains(localX, localY); 76 } 77 78 @Override 79 public boolean doComputeIntersects(Node node, PickRay pickRay, 80 PickResultChooser pickResult) { 81 return ((Box) node).doComputeIntersects(pickRay, pickResult); 82 } 83 }); 84 } 85 86 private TriangleMesh mesh; 87 88 /** 89 * Creates a new instance of {@code Box} of dimension 2 by 2 by 2. 90 */ 91 92 public static final double DEFAULT_SIZE = 2; 93 94 { 95 // To initialize the class helper at the begining each constructor of this class 96 BoxHelper.initHelper(this); 97 } 98 99 public Box() { 100 this(DEFAULT_SIZE, DEFAULT_SIZE, DEFAULT_SIZE); 101 } 102 116 * @defaultValue 2.0 117 */ 118 private DoubleProperty depth; 119 120 public final void setDepth(double value) { 121 depthProperty().set(value); 122 } 123 124 public final double getDepth() { 125 return depth == null ? 2 : depth.get(); 126 } 127 128 public final DoubleProperty depthProperty() { 129 if (depth == null) { 130 depth = new SimpleDoubleProperty(Box.this, "depth", DEFAULT_SIZE) { 131 @Override 132 public void invalidated() { 133 NodeHelper.markDirty(Box.this, DirtyBits.MESH_GEOM); 134 manager.invalidateBoxMesh(key); 135 key = 0; 136 NodeHelper.geomChanged(Box.this); 137 } 138 }; 139 } 140 return depth; 141 } 142 143 /** 144 * Defines the height or the Y dimension of the Box. 145 * 146 * @defaultValue 2.0 147 */ 148 private DoubleProperty height; 149 150 public final void setHeight(double value) { 151 heightProperty().set(value); 152 } 153 154 public final double getHeight() { 155 return height == null ? 2 : height.get(); 156 } 157 158 public final DoubleProperty heightProperty() { 159 if (height == null) { 160 height = new SimpleDoubleProperty(Box.this, "height", DEFAULT_SIZE) { 161 @Override 162 public void invalidated() { 163 NodeHelper.markDirty(Box.this, DirtyBits.MESH_GEOM); 164 manager.invalidateBoxMesh(key); 165 key = 0; 166 NodeHelper.geomChanged(Box.this); 167 } 168 }; 169 } 170 return height; 171 } 172 173 /** 174 * Defines the width or the X dimension of the Box. 175 * 176 * @defaultValue 2.0 177 */ 178 private DoubleProperty width; 179 180 public final void setWidth(double value) { 181 widthProperty().set(value); 182 } 183 184 public final double getWidth() { 185 return width == null ? 2 : width.get(); 186 } 187 188 public final DoubleProperty widthProperty() { 189 if (width == null) { 190 width = new SimpleDoubleProperty(Box.this, "width", DEFAULT_SIZE) { 191 @Override 192 public void invalidated() { 193 NodeHelper.markDirty(Box.this, DirtyBits.MESH_GEOM); 194 manager.invalidateBoxMesh(key); 195 key = 0; 196 NodeHelper.geomChanged(Box.this); 197 } 198 }; 199 } 200 return width; 201 } 202 203 /* 204 * Note: This method MUST only be called via its accessor method. 205 */ 206 private NGNode doCreatePeer() { 207 return new NGBox(); 208 } 209 210 /* 211 * Note: This method MUST only be called via its accessor method. 212 */ 213 private void doUpdatePeer() { 214 if (NodeHelper.isDirty(this, DirtyBits.MESH_GEOM)) { 215 NGBox peer = NodeHelper.getPeer(this); 216 final float w = (float) getWidth(); 217 final float h = (float) getHeight(); 218 final float d = (float) getDepth(); 219 if (w < 0 || h < 0 || d < 0) { 220 peer.updateMesh(null); 221 } else { 222 if (key == 0) { 223 key = generateKey(w, h, d); 224 } 225 mesh = manager.getBoxMesh(w, h, d, key); 226 mesh.updatePG(); 227 peer.updateMesh(mesh.getPGTriangleMesh()); 228 } 229 } 230 } 231 232 /* 233 * Note: This method MUST only be called via its accessor method. 234 */ 235 private BaseBounds doComputeGeomBounds(BaseBounds bounds, BaseTransform tx) { 236 final float w = (float) getWidth(); 237 final float h = (float) getHeight(); 238 final float d = (float) getDepth(); 239 240 if (w < 0 || h < 0 || d < 0) { 241 return bounds.makeEmpty(); 242 } 243 244 final float hw = w * 0.5f; 245 final float hh = h * 0.5f; 246 final float hd = d * 0.5f; 247 248 bounds = bounds.deriveWithNewBounds(-hw, -hh, -hd, hw, hh, hd); 249 bounds = tx.transform(bounds, bounds); 250 return bounds; 251 } 252 253 /* 254 * Note: This method MUST only be called via its accessor method. 255 */ 256 private boolean doComputeContains(double localX, double localY) { 257 double w = getWidth(); 258 double h = getHeight(); 259 return -w <= localX && localX <= w && 260 -h <= localY && localY <= h; 261 } 262 263 /* 264 * Note: This method MUST only be called via its accessor method. 265 */ 266 private boolean doComputeIntersects(PickRay pickRay, PickResultChooser pickResult) { 267 268 final double w = getWidth(); 269 final double h = getHeight(); 270 final double d = getDepth(); 271 final double hWidth = w / 2.0; 272 final double hHeight = h / 2.0; 273 final double hDepth = d / 2.0; 274 final Vec3d dir = pickRay.getDirectionNoClone(); 275 final double invDirX = dir.x == 0.0 ? Double.POSITIVE_INFINITY : (1.0 / dir.x); 276 final double invDirY = dir.y == 0.0 ? Double.POSITIVE_INFINITY : (1.0 / dir.y); 277 final double invDirZ = dir.z == 0.0 ? Double.POSITIVE_INFINITY : (1.0 / dir.z); 278 final Vec3d origin = pickRay.getOriginNoClone(); 279 final double originX = origin.x; 280 final double originY = origin.y; 281 final double originZ = origin.z; 282 final boolean signX = invDirX < 0.0; 283 final boolean signY = invDirY < 0.0; 284 final boolean signZ = invDirZ < 0.0; 285 286 double t0 = Double.NEGATIVE_INFINITY; |