// // DefaultDisplayRendererJ3D.java // /* VisAD system for interactive analysis and visualization of numerical data. Copyright (C) 1996 - 2017 Bill Hibbard, Curtis Rueden, Tom Rink, Dave Glowacki, Steve Emmerson, Tom Whittaker, Don Murray, and Tommy Jasmin. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ package visad.java3d; import java.lang.reflect.Constructor; import javax.media.j3d.AmbientLight; import javax.media.j3d.Appearance; import javax.media.j3d.BoundingSphere; import javax.media.j3d.BranchGroup; import javax.media.j3d.ColoringAttributes; import javax.media.j3d.DirectionalLight; import javax.media.j3d.GeometryArray; import javax.media.j3d.Light; import javax.media.j3d.LineArray; import javax.media.j3d.LineAttributes; import javax.media.j3d.Shape3D; import javax.media.j3d.TransformGroup; import javax.media.j3d.View; import javax.vecmath.Color3f; import javax.vecmath.Point3d; import javax.vecmath.Vector3f; import visad.VisADError; /** * <CODE>DefaultDisplayRendererJ3D</CODE> is the VisAD class for the * default background and metadata rendering algorithm under Java3D.<P> */ public class DefaultDisplayRendererJ3D extends DisplayRendererJ3D { private Object not_destroyed = new Object(); /** color of box and cursor */ private ColoringAttributes box_color = null; private ColoringAttributes cursor_color = null; /** line of box and cursor */ private LineAttributes box_line = null; private LineAttributes cursor_line = null; private Class mouseBehaviorJ3DClass = null; private MouseBehaviorJ3D mouse = null; // Behavior for mouse interactions /** * This is the default <CODE>DisplayRenderer</CODE> used by the * <CODE>DisplayImplJ3D</CODE> constructor. * It draws a 3-D cube around the scene.<P> * The left mouse button controls the projection as follows: * <UL> * <LI>mouse drag rotates in 3-D * <LI>mouse drag with Shift down zooms the scene * <LI>mouse drag with Ctrl translates the scene sideways * </UL> * The center mouse button activates and controls the * 3-D cursor as follows: * <UL> * <LI>mouse drag translates the cursor sideways * <LI>mouse drag with Shift translates the cursor in and out * <LI>mouse drag with Ctrl rotates scene in 3-D with cursor on * </UL> * The right mouse button is used for direct manipulation by clicking on * the depiction of a <CODE>Data</CODE> object and dragging or re-drawing * it.<P> * Cursor and direct manipulation locations are displayed in RealType * values.<P> * <CODE>BadMappingExceptions</CODE> and * <CODE>UnimplementedExceptions</CODE> are displayed<P> */ public DefaultDisplayRendererJ3D () { super(); mouseBehaviorJ3DClass = MouseBehaviorJ3D.class; } /** * @param mbj3dClass - sub Class of MouseBehaviorJ3D */ public DefaultDisplayRendererJ3D (Class mbj3dClass) { super(); mouseBehaviorJ3DClass = mbj3dClass; } public void destroy() { not_destroyed = null; box_color = null; cursor_color = null; mouse = null; super.destroy(); } /** * Create scene graph root, if none exists, with Transform * and direct manipulation root; * create 3-D box, lights and <CODE>MouseBehaviorJ3D</CODE> for * embedded user interface. * @param v * @param vpt * @param c * @return Scene graph root. */ public BranchGroup createSceneGraph(View v, TransformGroup vpt, VisADCanvasJ3D c) { if (not_destroyed == null) return null; BranchGroup root = getRoot(); if (root != null) return root; // create MouseBehaviorJ3D for mouse interactions try { Class[] param = new Class[] {DisplayRendererJ3D.class}; Constructor mbConstructor = mouseBehaviorJ3DClass.getConstructor(param); mouse = (MouseBehaviorJ3D) mbConstructor.newInstance(new Object[] {this}); } catch (Exception e) { throw new VisADError("cannot construct " + mouseBehaviorJ3DClass); } // mouse = new MouseBehaviorJ3D(this); getDisplay().setMouseBehavior(mouse); box_color = new ColoringAttributes(); cursor_color = new ColoringAttributes(); root = createBasicSceneGraph(v, vpt, c, mouse, box_color, cursor_color); TransformGroup trans = getTrans(); // create the box containing data depictions LineArray box_geometry = new LineArray(24, LineArray.COORDINATES); // WLH 24 Nov 2000 box_geometry.setCapability(GeometryArray.ALLOW_COORDINATE_WRITE); box_geometry.setCapability(GeometryArray.ALLOW_COLOR_READ); box_geometry.setCapability(GeometryArray.ALLOW_COORDINATE_READ); box_geometry.setCapability(GeometryArray.ALLOW_COUNT_READ); box_geometry.setCapability(GeometryArray.ALLOW_FORMAT_READ); box_geometry.setCapability(GeometryArray.ALLOW_NORMAL_READ); // box_geometry.setCapability(GeometryArray.ALLOW_REF_DATA_READ); box_geometry.setCapability(GeometryArray.ALLOW_TEXCOORD_READ); box_geometry.setCoordinates(0, box_verts); Appearance box_appearance = new Appearance(); box_appearance.setCapability(Appearance.ALLOW_COLORING_ATTRIBUTES_READ); box_appearance.setCapability(Appearance.ALLOW_LINE_ATTRIBUTES_READ); box_appearance.setCapability(Appearance.ALLOW_MATERIAL_READ); box_appearance.setCapability(Appearance.ALLOW_POINT_ATTRIBUTES_READ); box_appearance.setCapability(Appearance.ALLOW_POLYGON_ATTRIBUTES_READ); box_appearance.setCapability(Appearance.ALLOW_RENDERING_ATTRIBUTES_READ); box_appearance.setCapability(Appearance.ALLOW_TEXGEN_READ); box_appearance.setCapability(Appearance.ALLOW_TEXTURE_ATTRIBUTES_READ); box_appearance.setCapability(Appearance.ALLOW_TEXTURE_READ); // box_appearance.setCapability(Appearance.ALLOW_TEXTURE_UNIT_STATE_READ); box_appearance.setCapability(Appearance.ALLOW_TRANSPARENCY_ATTRIBUTES_READ); // WLH 2 Dec 2002 in response to qomo2.txt box_line = new LineAttributes(); box_line.setCapability(LineAttributes.ALLOW_WIDTH_WRITE); box_appearance.setLineAttributes(box_line); box_color.setCapability(ColoringAttributes.ALLOW_COLOR_READ); box_color.setCapability(ColoringAttributes.ALLOW_COLOR_WRITE); float[] ctlBox = getRendererControl().getBoxColor(); box_color.setColor(ctlBox[0], ctlBox[1], ctlBox[2]); box_appearance.setColoringAttributes(box_color); Shape3D box = new Shape3D(box_geometry, box_appearance); box.setCapability(Shape3D.ALLOW_GEOMETRY_READ); // WLH 24 Nov 2000 box.setCapability(Shape3D.ALLOW_APPEARANCE_READ); box.setCapability(Shape3D.ALLOW_APPEARANCE_WRITE); BranchGroup box_on = getBoxOnBranch(); box_on.addChild(box); Appearance cursor_appearance = new Appearance(); // WLH 2 Dec 2002 in response to qomo2.txt cursor_line = new LineAttributes(); cursor_line.setCapability(LineAttributes.ALLOW_WIDTH_WRITE); cursor_appearance.setCapability(Appearance.ALLOW_COLORING_ATTRIBUTES_READ); cursor_appearance.setCapability(Appearance.ALLOW_LINE_ATTRIBUTES_READ); cursor_appearance.setCapability(Appearance.ALLOW_MATERIAL_READ); cursor_appearance.setCapability(Appearance.ALLOW_POINT_ATTRIBUTES_READ); cursor_appearance.setCapability(Appearance.ALLOW_POLYGON_ATTRIBUTES_READ); cursor_appearance.setCapability(Appearance.ALLOW_RENDERING_ATTRIBUTES_READ); cursor_appearance.setCapability(Appearance.ALLOW_TEXGEN_READ); cursor_appearance.setCapability(Appearance.ALLOW_TEXTURE_ATTRIBUTES_READ); cursor_appearance.setCapability(Appearance.ALLOW_TEXTURE_READ); // cursor_appearance.setCapability(Appearance.ALLOW_TEXTURE_UNIT_STATE_READ); cursor_appearance.setCapability(Appearance.ALLOW_TRANSPARENCY_ATTRIBUTES_READ); cursor_color.setCapability(ColoringAttributes.ALLOW_COLOR_READ); cursor_color.setCapability(ColoringAttributes.ALLOW_COLOR_WRITE); cursor_appearance.setLineAttributes(cursor_line); cursor_color.setCapability(ColoringAttributes.ALLOW_COLOR_READ); cursor_color.setCapability(ColoringAttributes.ALLOW_COLOR_WRITE); float[] ctlCursor = getRendererControl().getCursorColor(); cursor_color.setColor(ctlCursor[0], ctlCursor[1], ctlCursor[2]); cursor_appearance.setColoringAttributes(cursor_color); BranchGroup cursor_on = getCursorOnBranch(); LineArray cursor_geometry = new LineArray(6, LineArray.COORDINATES); cursor_geometry.setCoordinates(0, cursor_verts); cursor_geometry.setCapability(GeometryArray.ALLOW_COLOR_READ); cursor_geometry.setCapability(GeometryArray.ALLOW_COORDINATE_READ); cursor_geometry.setCapability(GeometryArray.ALLOW_COUNT_READ); cursor_geometry.setCapability(GeometryArray.ALLOW_FORMAT_READ); cursor_geometry.setCapability(GeometryArray.ALLOW_NORMAL_READ); // cursor_geometry.setCapability(GeometryArray.ALLOW_REF_DATA_READ); cursor_geometry.setCapability(GeometryArray.ALLOW_TEXCOORD_READ); Shape3D cursor = new Shape3D(cursor_geometry, cursor_appearance); cursor.setCapability(Shape3D.ALLOW_GEOMETRY_READ); cursor.setCapability(Shape3D.ALLOW_APPEARANCE_READ); cursor_on.addChild(cursor); // insert MouseBehaviorJ3D into scene graph BoundingSphere bounds = new BoundingSphere(new Point3d(0.0,0.0,0.0), 2000000.0); mouse.setSchedulingBounds(bounds); trans.addChild(mouse); // create ambient light, directly under root (not transformed) Color3f color = new Color3f(0.6f, 0.6f, 0.6f); AmbientLight light = new AmbientLight(color); light.setCapability(Light.ALLOW_COLOR_READ); light.setCapability(Light.ALLOW_INFLUENCING_BOUNDS_READ); light.setCapability(Light.ALLOW_SCOPE_READ); light.setCapability(Light.ALLOW_STATE_READ); light.setInfluencingBounds(bounds); root.addChild(light); // create directional lights, directly under root (not transformed) Color3f dcolor = new Color3f(0.9f, 0.9f, 0.9f); Vector3f direction1 = new Vector3f(0.0f, 0.0f, 1.0f); Vector3f direction2 = new Vector3f(0.0f, 0.0f, -1.0f); DirectionalLight light1 = new DirectionalLight(true, dcolor, direction1); light1.setCapability(DirectionalLight.ALLOW_DIRECTION_READ); light1.setCapability(Light.ALLOW_COLOR_READ); light1.setCapability(Light.ALLOW_INFLUENCING_BOUNDS_READ); light1.setCapability(Light.ALLOW_SCOPE_READ); light1.setCapability(Light.ALLOW_STATE_READ); light1.setInfluencingBounds(bounds); DirectionalLight light2 = new DirectionalLight(true, dcolor, direction2); light2.setCapability(DirectionalLight.ALLOW_DIRECTION_READ); light2.setCapability(Light.ALLOW_COLOR_READ); light2.setCapability(Light.ALLOW_INFLUENCING_BOUNDS_READ); light2.setCapability(Light.ALLOW_SCOPE_READ); light2.setCapability(Light.ALLOW_STATE_READ); light2.setInfluencingBounds(bounds); root.addChild(light1); root.addChild(light2); return root; } /** * set the aspect for the containing box * aspect double[3] array used to scale x, y and z box sizes */ public void setBoxAspect(double[] aspect) { if (not_destroyed == null) return; float[] new_verts = new float[box_verts.length]; for (int i=0; i<box_verts.length; i+=3) { new_verts[i] = (float) (box_verts[i] * aspect[0]); new_verts[i+1] = (float) (box_verts[i+1] * aspect[1]); new_verts[i+2] = (float) (box_verts[i+2] * aspect[2]); } BranchGroup box_on = getBoxOnBranch(); Shape3D box = (Shape3D) box_on.getChild(0); LineArray box_geometry = (LineArray) box.getGeometry(); box_geometry.setCoordinates(0, new_verts); } // WLH 2 Dec 2002 in response to qomo2.txt public void setLineWidth(float width) { box_line.setLineWidth(width); cursor_line.setLineWidth(width); } private static final float[] box_verts = { // front face -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, // back face -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, // connectors -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f }; private static final float[] cursor_verts = { 0.0f, 0.0f, 0.1f, 0.0f, 0.0f, -0.1f, 0.0f, 0.1f, 0.0f, 0.0f, -0.1f, 0.0f, 0.1f, 0.0f, 0.0f, -0.1f, 0.0f, 0.0f }; }