001/** 002 * J3DRenderingPrefs -- A class that contains Java3D rendering preferences for this 003 * application. 004 * 005 * Copyright (C) 2013-2023, Joseph A. Huwaldt. All rights reserved. 006 * 007 * This library is free software; you can redistribute it and/or modify it under the terms 008 * of the GNU Lesser General Public License as published by the Free Software Foundation; 009 * either version 2.1 of the License, or (at your option) any later version. 010 * 011 * This library is distributed in the hope that it will be useful, but WITHOUT ANY 012 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 013 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. 014 * 015 * You should have received a copy of the GNU Lesser General Public License along with 016 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - 017 * Suite 330, Boston, MA 02111-1307, USA. Or visit: http://www.gnu.org/licenses/lgpl.html 018 */ 019package geomss.j3d; 020 021import jahuwaldt.js.param.Parameter; 022import java.awt.Color; 023import java.util.ResourceBundle; 024import javax.measure.quantity.Length; 025import javax.measure.unit.SI; 026import org.jogamp.java3d.*; 027import org.jogamp.vecmath.Color3f; 028import jahuwaldt.j3d.JColor4f; 029import javolution.lang.Immutable; 030 031/** 032 * A class that contains a set of Java3D rendering preferences for this application. 033 * 034 * <p> Modified by: Joseph A. Huwaldt </p> 035 * 036 * @author Joseph A. Huwaldt, Date: December 21, 2013 037 * @version June 4, 2023 038 */ 039public class J3DRenderingPrefs implements Immutable { 040 041 /** 042 * The resource bundle for this class. 043 */ 044 protected static final ResourceBundle RB = J3DGeomGroup.RB; 045 046 // The default color used when drawing points. 047 private static final Color DEFAULT_POINT_COLOR = new Color(255, 0, 0, 255); // Default = Red 048// Default = Red 049 050 // The default color used when drawing lines. 051 private static final Color DEFAULT_LINE_COLOR = new Color(0, 255, 0, 255); 052 // The color to use when drawing points. 053 // Default = Green 054 private JColor4f _pointColor; 055 056 // The color to use when drawing lines and curves. 057 private JColor4f _lineColor = new JColor4f(DEFAULT_LINE_COLOR); 058 059 // The size that points are rendered in pixels. 060 private int _pointSize = 2; 061 062 // The line width used when rendering lines and curves. 063 private int _lineWidth = 1; 064 065 // The appearance used when rendering surfaces and point-arrays. 066 private static final Appearance DEFAULT_APPEARANCE = new Appearance(); 067 068 static { 069 Material material = new Material(); 070 material.setDiffuseColor(new Color3f(0.5F, 0.5F, 0.5F)); 071 material.setShininess(64.5F); // Set shininess to 50% of range rather than 49.6063%. 072 material.setLightingEnable(true); 073 PolygonAttributes polyAttrib = new PolygonAttributes(); 074 polyAttrib.setCullFace(PolygonAttributes.CULL_NONE); 075 LineAttributes lineAttrib = new LineAttributes(); 076 lineAttrib.setLineWidth(1); 077 DEFAULT_APPEARANCE.setPolygonAttributes(polyAttrib); 078 DEFAULT_APPEARANCE.setLineAttributes(lineAttrib); 079 DEFAULT_APPEARANCE.setMaterial(material); 080 } 081 private Appearance _srfAppearance = DEFAULT_APPEARANCE; 082 083 // The drawing tolerance used for rendering parametric objects. 084 private Parameter<Length> _drawTol = Parameter.valueOf(0.005, SI.METER); 085 086 /** 087 * Construct a default set of rendering preferences. 088 */ 089 public J3DRenderingPrefs() {this._pointColor = new JColor4f(DEFAULT_POINT_COLOR); 090 } 091 092 /** 093 * @return the default Color used to render points. 094 */ 095 public static Color getDefaultPointColor() { 096 return DEFAULT_POINT_COLOR; 097 } 098 099 /** 100 * @return the default Color used to render lines. 101 */ 102 public static Color getDefaultLineColor() { 103 return DEFAULT_LINE_COLOR; 104 } 105 106 /** 107 * @return the Java3D Color4f used to render points. 108 */ 109 JColor4f getPointColorJ3D() { 110 return new JColor4f(_pointColor); 111 } 112 113 /** 114 * @return the Color used to render points. 115 */ 116 public Color getPointColor() { 117 return _pointColor.get(); 118 } 119 120 /** 121 * Return a set of rendering preferences that are identical to this one, but with the 122 * point color changed to the specified color. 123 * 124 * @param color The new color to use for rendering points. 125 * @return A copy of this set of rendering preferences with the point color changed. 126 */ 127 public J3DRenderingPrefs changePointColor(Color color) { 128 J3DRenderingPrefs prefs = new J3DRenderingPrefs(); 129 copyPrefs(prefs); 130 131 JColor4f color4f = new JColor4f(color); 132 133 prefs._pointColor = color4f; 134 return prefs; 135 } 136 137 /** 138 * @return the size in pixels used for rendering points. 139 */ 140 public int getPointSize() { 141 return _pointSize; 142 } 143 144 /** 145 * Return a set of rendering preferences that are identical to this one, but with the 146 * point size changed to the specified value. 147 * 148 * @param pixels The new size, in pixels, to use for rendering points. 149 * @return A copy of this set of rendering preferences with the point size changed. 150 */ 151 public J3DRenderingPrefs changePointSize(int pixels) { 152 if (pixels < 1) 153 throw new IllegalArgumentException(RB.getString("pointSizeToSmall")); 154 J3DRenderingPrefs prefs = new J3DRenderingPrefs(); 155 copyPrefs(prefs); 156 prefs._pointSize = pixels; 157 return prefs; 158 } 159 160 /** 161 * @return the Java3D Color4f used to render lines and curves. 162 */ 163 JColor4f getLineColorJ3D() { 164 return new JColor4f(_lineColor); 165 } 166 167 /** 168 * @return the Color used to render lines and curves. 169 */ 170 public Color getLineColor() { 171 return _lineColor.get(); 172 } 173 174 /** 175 * Return a set of rendering preferences that are identical to this one, but with the 176 * line or curve color changed to the specified color. 177 * 178 * @param color The color to use for rendering lines and curves. 179 * @return A copy of this set of rendering preferences with the line color changed. 180 */ 181 public J3DRenderingPrefs changeLineColor(Color color) { 182 J3DRenderingPrefs prefs = new J3DRenderingPrefs(); 183 copyPrefs(prefs); 184 185 JColor4f color4f = new JColor4f(color); 186 187 prefs._lineColor = color4f; 188 return prefs; 189 } 190 191 /** 192 * @return the width in pixels used for rendering lines and curves. 193 */ 194 public int getLineWidth() { 195 return _lineWidth; 196 } 197 198 /** 199 * Return a set of rendering preferences that are identical to this one, but with the 200 * line width changed to the specified value. 201 * 202 * @param pixels The width, in pixels, to use when rendering lines and curves. 203 * @return A copy of this set of rendering preferences with the line width changed. 204 */ 205 public J3DRenderingPrefs changeLineWidth(int pixels) { 206 if (pixels < 1) 207 throw new IllegalArgumentException(RB.getString("pointSizeToSmall")); 208 J3DRenderingPrefs prefs = new J3DRenderingPrefs(); 209 copyPrefs(prefs); 210 prefs._lineWidth = pixels; 211 return prefs; 212 } 213 214 /** 215 * @return the tolerance used when rendering parametric objects. 216 */ 217 public Parameter<Length> getDrawTolerance() { 218 return _drawTol; 219 } 220 221 /** 222 * Return a set of rendering preferences that are identical to this one, but with the 223 * draw tolerance changed to the specified value. This tolerance is used when 224 * determining how to subdivide parametric objects for rendering. If the input value 225 * is <code>null</code> or equal to <code>0</code>, it will be silently ignored. 226 * 227 * @param tol The geometric tolerance to use when rendering parametric objects. May 228 * not be null. 229 * @return A copy of this set of rendering preferences with the draw tolerance 230 * changed. 231 */ 232 public J3DRenderingPrefs changeDrawTolerance(Parameter<Length> tol) { 233 J3DRenderingPrefs prefs = new J3DRenderingPrefs(); 234 copyPrefs(prefs); 235 if (tol.getValue() < 0) 236 tol = tol.opposite(); 237 prefs._drawTol = tol; 238 return prefs; 239 } 240 241 /** 242 * @return the Java 3D Appearance used when rendering surfaces. 243 */ 244 public Appearance getSurfaceAppearance() { 245 return (Appearance)_srfAppearance.cloneNodeComponent(true); 246 } 247 248 /** 249 * Get the color (of the specified type) used to render surfaces and point-arrays. 250 * 251 * @param colorType The aspect or type of the surface color that is being set. If 252 * AMBIENT_AND_DIFFUSE is passed in, then only the ambient color is 253 * returned! 254 * @return The color used for the specified type of surface color. Alpha is ignored. 255 * @see #getSurfaceAlpha 256 */ 257 public Color getSurfaceColor(SurfaceColorType colorType) { 258 259 // Retrieve the appearance and material. 260 Appearance appearance = _srfAppearance; 261 Material material = appearance.getMaterial(); 262 263 // Get the specified color. 264 Color3f color3f = new Color3f(); 265 switch (colorType) { 266 case AMBIENT: 267 case AMBIENT_AND_DIFFUSE: 268 material.getAmbientColor(color3f); 269 break; 270 case DIFFUSE: 271 material.getDiffuseColor(color3f); 272 break; 273 case EMISSIVE: 274 material.getEmissiveColor(color3f); 275 break; 276 case SPECULAR: 277 material.getSpecularColor(color3f); 278 break; 279 } 280 281 // Return as an AWT color object. 282 return new Color(color3f.getX(), color3f.getY(), color3f.getZ(), 1F); 283 } 284 285 /** 286 * Return a set of rendering preferences that are identical to this one, but with the 287 * specified type of color used to render surfaces and point-arrays changed. 288 * 289 * @param colorType The aspect or type of the surface color that is being set. 290 * @param color The color to use for the specified type of surface color. The 291 * alpha, if present, is ignored. 292 * @return A copy of this set of rendering preferences with the surface color changed. 293 * @see #changeSurfaceAlpha 294 */ 295 public J3DRenderingPrefs changeSurfaceColor(SurfaceColorType colorType, Color color) { 296 J3DRenderingPrefs prefs = new J3DRenderingPrefs(); 297 copyPrefs(prefs); 298 299 // Copy the surface appearance data. 300 prefs._srfAppearance = (Appearance)prefs._srfAppearance.cloneNodeComponent(true); 301 302 float red = color.getRed() / 255F; 303 float green = color.getGreen() / 255F; 304 float blue = color.getBlue() / 255F; 305 306 // Retrieve the appearance and material. 307 Appearance appearance = prefs._srfAppearance; 308 Material material = appearance.getMaterial(); 309 310 // Set the material color. 311 switch (colorType) { 312 case AMBIENT: 313 material.setAmbientColor(red, green, blue); 314 break; 315 case DIFFUSE: 316 material.setDiffuseColor(red, green, blue); 317 break; 318 case AMBIENT_AND_DIFFUSE: 319 material.setAmbientColor(red, green, blue); 320 material.setDiffuseColor(red, green, blue); 321 break; 322 case EMISSIVE: 323 material.setEmissiveColor(red, green, blue); 324 break; 325 case SPECULAR: 326 material.setSpecularColor(red, green, blue); 327 break; 328 } 329 330 return prefs; 331 } 332 333 /** 334 * Get the alpha or transparency used when rendering surfaces or point-arrays. 335 * 336 * @return The alpha value used (0.0=completely transparent, 1.0=completely opaque). 337 */ 338 public float getSurfaceAlpha() { 339 340 // Get the transparency attributes (if there are any). 341 TransparencyAttributes transp = _srfAppearance.getTransparencyAttributes(); 342 float alpha = 1; 343 if (transp != null) 344 alpha -= transp.getTransparency(); 345 346 return alpha; 347 } 348 349 /** 350 * Return a set of rendering preferences that are identical to this one, but with the 351 * alpha or transparency used to render surfaces and point-arrays changed. 352 * 353 * @param alpha The alpha value to use (0.0=completely transparent, 1.0=completely 354 * opaque). 355 * @return A copy of this set of rendering preferences with the surface alpha changed. 356 */ 357 public J3DRenderingPrefs changeSurfaceAlpha(float alpha) { 358 J3DRenderingPrefs prefs = new J3DRenderingPrefs(); 359 copyPrefs(prefs); 360 361 // Copy the surface appearance data. 362 prefs._srfAppearance = (Appearance)prefs._srfAppearance.cloneNodeComponent(true); 363 364 // Retrieve the appearance. 365 Appearance appearance = prefs._srfAppearance; 366 367 // Get the transparency attributes (if there are any). 368 TransparencyAttributes transp = appearance.getTransparencyAttributes(); 369 if (transp != null) 370 transp.setTransparency(1F - alpha); 371 else { 372 transp = new TransparencyAttributes(TransparencyAttributes.NICEST, 1F - alpha); 373 appearance.setTransparencyAttributes(transp); 374 } 375 if (alpha == 1) 376 transp.setTransparencyMode(TransparencyAttributes.NONE); 377 else 378 transp.setTransparencyMode(TransparencyAttributes.NICEST); 379 380 return prefs; 381 } 382 383 /** 384 * Get the shininess used when rendering surfaces and point-arrays. 385 * 386 * @return The shininess to use in the range [0.0, 1.0] where 0.0 is not shiny and 1.0 387 * is very shiny. 388 */ 389 public float getSurfaceShininess() { 390 391 // Retrieve the appearance and material. 392 Material material = _srfAppearance.getMaterial(); 393 394 // Get the shininess value. 395 float shininess = material.getShininess(); 396 397 // Convert the shininess from Java3D to GeomSS. 398 shininess = (shininess - 1F) / 127F; 399 return shininess; 400 } 401 402 /** 403 * Return a set of rendering preferences that are identical to this one, but with the 404 * shininess used when rendering surfaces and point-arrays changed. 405 * 406 * @param shininess The shininess to use in the range [0.0, 1.0] where 0.0 is not 407 * shiny and 1.0 is very shiny. Values outside this range are 408 * clamped. 409 * @return A copy of this set of rendering preferences with the surface shininess 410 * changed. 411 */ 412 public J3DRenderingPrefs changeSurfaceShininess(float shininess) { 413 J3DRenderingPrefs prefs = new J3DRenderingPrefs(); 414 copyPrefs(prefs); 415 416 // Copy the surface appearance data. 417 prefs._srfAppearance = (Appearance)prefs._srfAppearance.cloneNodeComponent(true); 418 419 // Convert shininess value from GeomSS to Java3D values. 420 shininess = 127F * shininess + 1F; 421 422 // Retrieve a copy of the appearance and material. 423 Material material = prefs._srfAppearance.getMaterial(); 424 425 // Set the shininess. 426 material.setShininess(shininess); 427 428 return prefs; 429 } 430 431 /** 432 * Copies over the existing set of J3D rendering preferences from this object to the 433 * target one. 434 */ 435 private void copyPrefs(J3DRenderingPrefs target) { 436 target._pointColor = _pointColor; 437 target._pointSize = _pointSize; 438 target._lineColor = _lineColor; 439 target._lineWidth = _lineWidth; 440 target._srfAppearance = _srfAppearance; 441 target._drawTol = _drawTol; 442 } 443 444 /** 445 * Compares this J3DRenderingPrefs against the specified object for strict equality. 446 * 447 * @param obj the object to compare with. 448 * @return <code>true</code> if this set of preferences is identical to that one; 449 * <code>false</code> otherwise. 450 */ 451 @Override 452 public boolean equals(Object obj) { 453 if (this == obj) 454 return true; 455 if ((obj == null) || (obj.getClass() != this.getClass())) 456 return false; 457 458 J3DRenderingPrefs that = (J3DRenderingPrefs)obj; 459 if (!this._pointColor.equals(that._pointColor)) 460 return false; 461 if (this._pointSize != that._pointSize) 462 return false; 463 if (!this._lineColor.equals(that._lineColor)) 464 return false; 465 if (this._lineWidth != that._lineWidth) 466 return false; 467 if (!this._drawTol.equals(that._drawTol)) 468 return false; 469 if (this.getSurfaceAlpha() != that.getSurfaceAlpha()) 470 return false; 471 if (this.getSurfaceShininess() != that.getSurfaceShininess()) 472 return false; 473 if (!this.getSurfaceColor(SurfaceColorType.AMBIENT).equals(that.getSurfaceColor(SurfaceColorType.AMBIENT))) 474 return false; 475 if (!this.getSurfaceColor(SurfaceColorType.DIFFUSE).equals(that.getSurfaceColor(SurfaceColorType.DIFFUSE))) 476 return false; 477 if (!this.getSurfaceColor(SurfaceColorType.EMISSIVE).equals(that.getSurfaceColor(SurfaceColorType.EMISSIVE))) 478 return false; 479 480 return this.getSurfaceColor(SurfaceColorType.SPECULAR).equals(that.getSurfaceColor(SurfaceColorType.SPECULAR)); 481 } 482 483 /** 484 * Returns the hash code for this set of preferences. 485 * 486 * @return the hash code value. 487 */ 488 @Override 489 public int hashCode() { 490 int hash = 7; 491 492 hash = hash * 31 + _pointColor.hashCode(); 493 hash = hash * 31 + _pointSize; 494 hash = hash * 31 + _lineColor.hashCode(); 495 hash = hash * 31 + _lineWidth; 496 hash = hash * 31 + _srfAppearance.hashCode(); 497 hash = hash * 31 + _drawTol.hashCode(); 498 499 return hash; 500 } 501 502}