View Javadoc

1   /* -------------------------------------------------------------------
2    * Java source file for the class BasicRenderer
3    * 
4    * Copyright (c), 2003, Masahiro Takatsuka.
5    * All Rights Researved.
6    * 
7    * Original Author: Masahiro Takatsuka (masa@jbeans.net)
8    * $Author: takatsukam $
9    * 
10   * $Date: 2004/03/03 11:53:06 $
11   * 
12   * $Id: BasicRenderer.java,v 1.3 2004/03/03 11:53:06 takatsukam Exp $
13   * 
14   * Reference:		Document no:
15   * ___				___
16   * 
17   * To Do:
18   * ___
19   * 
20  ------------------------------------------------------------------- */
21  
22  /* --------------------------- Package ---------------------------- */
23  package net.jbeans.j3d.renderer;
24  
25  /* ------------------ Import classes (packages) ------------------- *//package-summary/html">class="comment"> ------------------ Import classes (packages) ------------------- *//package-summary.html">class="comment">/* ------------------ Import classes (packages) ------------------- *//package-summary.html">class="comment"> ------------------ Import classes (packages) ------------------- */
26  import java.awt.*;
27  import java.io.*;
28  import javax.media.j3d.*;
29  import javax.swing.*;
30  import javax.vecmath.*;
31  import com.sun.j3d.loaders.*;
32  import com.sun.j3d.utils.picking.*;
33  import com.sun.j3d.utils.universe.*;
34  
35  import net.jbeans.ui.*;
36  import net.jbeans.j3d.transform.*;
37  import net.jbeans.j3d.universe.*;
38  
39  import net.jbeans.util.debug.*;
40  
41  /*====================================================================
42                  Implementation of class BasicRenderer                 
43  ====================================================================*/
44  /***
45   * A BasicRenderer is a frame containing objects (2D and 3D canvas,
46   * button, dials, etc.) used to manipulate rendered object.
47   * 
48   * @version $Revision: 1.3 $
49   * @author Masahiro Takatsuka (masa@jbeans.net)
50   * @see JPanel
51   * @see Externalizable
52   */
53  
54  public abstract class BasicRenderer extends JPanel implements Externalizable {
55  	private static final boolean DEBUG = Debug.getDebugFlag(BasicRenderer.class);
56  
57  	public static final BoundingSphere DEFAULT_BOUNDS = new BoundingSphere(new Point3d(0.0, 0.0, 0.0), 2000000.0);
58  	
59  	protected static final int MRG = 10;
60  	protected static final int YGAP = 5;
61  	protected static final int DEFAULT_CANVAS3D_WIDTH  = 400;
62  	protected static final int DEFAULT_CANVAS3D_HEIGHT = 400;
63  	protected static final int DEFAULT_CANVAS3D_TOP = 0 ;
64  	
65  	/* -------------------------- serialized -------------------------- */
66  	protected Color backColor;
67  	private boolean stereoEnable = false;
68  	private double eyeSeparation = 0.0066;
69  	private int windowEyepointPolicy = View.RELATIVE_TO_FIELD_OF_VIEW;
70  	
71  	/* ------------------------ not serialized ------------------------ */
72  	/***
73  	* A Universe.
74  	*/
75  	transient protected Universe universe = null;
76  
77  	/***
78  	* A canvas to render 3D objects.
79  	*/
80  	transient protected Canvas3D canvas3D;
81  
82  	/***
83  	 * background leaf.
84  	 */
85  	transient Background background;
86  
87  	transient JPanel initRendererPanel;
88  	
89  	/***
90  	 * Constructs a new BasicRenderer object.
91  	 *                                         Masahiro Takatsuka/1999-Jun-11
92  	 */
93  	BasicRenderer() {
94  		this("Basic Renderer");
95  	}
96  
97  	/***
98  	* Constructs a new Renderer object.
99  	*                                         Masahiro Takatsuka/1999-Jun-11
100 	*/
101 	BasicRenderer(String title) {
102 		super();
103 		this.backColor = Color.black;
104 		initialize(title);
105 	}
106 
107 	private void initialize(String title) {
108 		init3D();				// initialize 3D.
109 		initUI(title);			// initialize UI.
110 		setVisible(true);
111 		setBackgroundColor(this.backColor);
112 		setEyeSeparation();		// set the default eye separation 0.0066.
113 	}
114 
115 	public boolean getStereoEnable() {
116 		return this.stereoEnable;
117 	}
118 		
119 	public void setStereoEnable(boolean b) {
120 		this.stereoEnable = b;
121 		setEyeSeparation();
122 		this.canvas3D.setStereoEnable(b);
123 	}
124 
125 	private void setEyeSeparation() {
126 		PhysicalBody myBody = this.canvas3D.getView().getPhysicalBody();
127 		myBody.setRightEyePosition(new Point3d(this.eyeSeparation/2.0, 0.0, 0.0));
128 		myBody.setLeftEyePosition(new Point3d( - this.eyeSeparation/2.0, 0.0, 0.0));
129 	}
130 
131 	public void setEyeSeparation(double eyeseparation) {
132 		this.eyeSeparation = eyeseparation;
133 		setEyeSeparation();
134 	}
135 
136 	public double getEyeSeparation() {
137 		return this.eyeSeparation;
138 	}
139 	
140 	public void setWindowEyepointPolicy(int policy) {
141 		switch(policy) {
142 		case View.RELATIVE_TO_SCREEN:
143 			break;
144 		case View.RELATIVE_TO_WINDOW:
145 			break;
146 		case View.RELATIVE_TO_COEXISTENCE:
147 			break;
148 		case View.RELATIVE_TO_FIELD_OF_VIEW:
149 		default:
150 			policy = View.RELATIVE_TO_FIELD_OF_VIEW;
151 			break;
152 		}
153 		this.windowEyepointPolicy = policy;
154 		this.canvas3D.getView().setWindowEyepointPolicy(this.windowEyepointPolicy);		
155 	}
156 
157 	public int getWindowEyepointPolicy() {
158 		return this.windowEyepointPolicy;
159 	}
160 	
161 	public void setBackgroundColor(Color color) {
162 		this.backColor = color;
163 		float[] col4f = new float[4];
164 		this.backColor.getComponents(col4f);
165 		this.background.setColor(col4f[0],
166 								 col4f[1],
167 								 col4f[2]);
168 	}
169 
170 	public Color getBackgroundColor() {
171 		return this.backColor;
172 	}
173 
174     /***
175      * Serialization methods
176      */
177     public void readExternal(ObjectInput in) throws ClassNotFoundException, IOException {
178 		String title = (String) in.readObject();
179 		this.backColor = (Color) in.readObject();
180 		initialize(title);
181     }
182 
183     /***
184      * Serialization methods
185      */
186     public void writeExternal(ObjectOutput out) throws IOException {
187 		out.writeObject(getName());
188 		out.writeObject(this.backColor);
189     }
190 
191 	/***
192 	 * Initializing GUI
193 	 *                                         Masahiro Takatsuka/1999-Jun-11
194 	 */
195 	private void initUI(String title) {
196   		setName(title);
197 
198 		// set a Borderlayout as a layout manager.
199 		setLayout(new BorderLayout());
200 
201 		// Create the "base" color for the AWT components.
202 		setBackground(new Color(100, 100, 100));
203 		this.initRendererPanel = initRendererPanel();
204 		add(this.initRendererPanel, BorderLayout.CENTER);
205 	}
206 
207 	protected JPanel initRendererPanel() {
208 		// Create the canvas container.
209 		JPanel renderPanel = new JPanel();
210 		renderPanel.setSize(DEFAULT_CANVAS3D_WIDTH+MRG*2, DEFAULT_CANVAS3D_HEIGHT+MRG*2);
211 		renderPanel.setLayout(new BorderLayout());
212 		renderPanel.setBackground( Color.darkGray );
213 		// Add the 3D canvas to the container.
214 		renderPanel.add(this.canvas3D, BorderLayout.CENTER);
215 
216 		return renderPanel;
217 	}
218 
219 	/***
220 	* Initializes 3D related stuff.
221 	* <PRE>
222 	* </PRE>
223 	*
224 	* @return void
225 	*/
226 	private void init3D() {
227 		GraphicsConfiguration gc = Universe.getPreferredConfiguration();
228 		this.canvas3D = new Canvas3D(gc);	// Create a 3D graphics canvas.
229 		this.canvas3D.setSize(DEFAULT_CANVAS3D_WIDTH, DEFAULT_CANVAS3D_HEIGHT);
230 		this.universe = createUniverse(this.canvas3D); // create universe.
231 		
232 		// Set background color
233   		Color3f bgColor = new Color3f(0.17f, 0.65f, 0.92f);
234 		this.background = new Background(bgColor);
235 		this.background.setCapability(Background.ALLOW_COLOR_READ);
236 		this.background.setCapability(Background.ALLOW_COLOR_WRITE);
237 		this.background.setApplicationBounds(DEFAULT_BOUNDS);
238 		BranchGroup bg = new BranchGroup();
239 		bg.addChild(this.background);
240 		this.universe.addBranchGraph(bg);
241 
242 		// This will move the ViewPlatform back a bit so the
243 		// objects in the scene can be viewed.
244   		this.universe.getViewingPlatform().setNominalViewingTransform();
245 
246 		// Change transparency settings to get proper ordering of transparent objects
247 		this.universe.getViewer().getView().setTransparencySortingPolicy(View.TRANSPARENCY_SORT_GEOMETRY);
248 		this.universe.getViewer().getView().setDepthBufferFreezeTransparent(false);
249 	}
250 
251 	protected abstract Universe createUniverse(Canvas3D canvas3d);
252 //    	protected Universe createUniverse(Canvas3D canvas3d) {
253 //    		return new Universe(canvas3d);
254 //    	}
255 
256 	/***
257 	* sets projection type.
258 	*
259 	* @param projection Either View.PERSPECTIVE_PROJECTION or
260 	* View.PARALLEL_PROJECTION.  If other values are set,
261 	* View.PERSPECTIVE_PROJECTION will be used.
262 	*/
263 	public void setProjection(int projection) {
264 		projection = (projection == View.PARALLEL_PROJECTION) ?
265 			View.PARALLEL_PROJECTION : View.PERSPECTIVE_PROJECTION;
266         this.canvas3D.getView().setProjectionPolicy(projection);
267 	}
268 
269 	public int getProjection() {
270         return this.canvas3D.getView().getProjectionPolicy();
271 	}
272 	
273 	/***
274 	 * Sets the projection to PERSPECTIVE.
275 	 */
276 	public void setPerspectiveProjection() {
277 		setProjection(View.PERSPECTIVE_PROJECTION);
278 	}
279 
280 	/***
281 	 * Sets the projection to PARALLEL_PROJECTION.
282 	 */
283 	public void setParallelProjection() {
284 		setProjection(View.PARALLEL_PROJECTION);
285 	}
286 
287 	/***
288 	 * Returns an universe.
289 	* <PRE>
290 	* </PRE>
291 	*
292 	* @return VirtualUniverse
293 	*/
294 	public VirtualUniverse getUniverse() {
295 		return this.universe;
296 	}
297 
298 	/***
299 	 * Returns a canvas3D object.
300 	 * <PRE>
301 	 * </PRE>
302 	 *
303 	 * @return Canvas3D
304 	 */
305 	public Canvas3D getCanvas3D() {
306 		return this.canvas3D;
307 	}
308 
309 	/***
310 	 * Adds a new branch graphoup to the scene.
311 	 * <PRE>
312 	 * </PRE>
313 	 *
314 	 * @param branch BranchGroup object to be added.
315 	 * @return void
316 	 */
317 	public void addBranchGraph(BranchGroup branch) {
318 		try {
319 			Node parent = branch.getParent();
320 			if (parent != null) {
321 				// it is already a part of a scene graph!
322 				// don't do anything, just return
323 				if (DEBUG) {
324 					System.out.println("BasicRenderer.addBranchGraph() : it already has a parent");
325 				}
326 				return;
327 			}
328 			// else
329 			if (DEBUG) {
330 				System.out.println("BasicRenderer.addBranchGraph() : adding " + branch);
331 			}
332 			/*
333 			* Nothing can be added to the live emtpy BranchGroup.
334 			* I think this is a Java3D's bug.
335 			* The following is the work around.
336 			* I'm adding a default BoundingSphere for an empty BranghGroup.
337 			* Masahiro Takatsuka/2001-Jul-14
338 			*/
339 			branch.setCapability(Node.ALLOW_BOUNDS_READ);
340 			branch.setCapability(Node.ALLOW_BOUNDS_WRITE);
341 			if (branch.getBounds().isEmpty()) {		
342 				branch.setBounds(new BoundingSphere());
343 			}
344 
345 			branch.setCapability(Group.ENABLE_PICK_REPORTING);
346 			this.universe.addBranchGraph(branch);
347 		} catch (Exception e) {// javax.media.j3d.RestrictedAccessException
348 			// it is already a part of a scene graph!
349 			// don't do anything, just return
350 			if (DEBUG) {
351 				e.printStackTrace();
352 			}
353 		}
354 	}
355 
356 	/***
357 	 * Adds a new branch graphoup to the scene.
358 	 * <PRE>
359 	 * </PRE>
360 	 *
361 	 * @param branch BranchGroup object to be added.
362 	 * @return void
363 	 */
364 	public void addBranchGraph(Object branch) {
365 		if (branch instanceof BranchGroup) {
366 			addBranchGraph((BranchGroup) branch);
367 		}
368 	}
369 	
370 	public void detachBranchGraph(BranchGroup branch) {
371 		if (DEBUG) {
372 			System.out.println("removing : " + branch);
373 		}
374 		this.universe.removeBranchGraph(branch);
375 	}
376 
377 	public void detachAllBranchGraph() {
378 		this.universe.removeAllBranchGraph();
379 	}
380 	
381 	/***
382 	 * Adds a specified scene to the current universe.
383 	 * <P>
384 	 * this is no longer used.
385 	 *
386 	 * @param scene Scene object to be added.
387 	 * @return void
388 	 */
389 	private void addScene(Scene scene) {
390 		BranchGroup sceneGroup = scene.getSceneGroup();
391 		BranchGroup g = new BranchGroup();
392 		g.setCapability(Group.ENABLE_PICK_REPORTING);
393 
394 		Behavior[] behaviors = scene.getBehaviorNodes();
395 		ResettableTransformGroup ptg = new ResettableTransformGroup();
396 
397 		ptg.setBounds(DEFAULT_BOUNDS);
398 		ptg.enableMouseBehaviors();
399 		ptg.addChild(sceneGroup);
400 		if (behaviors != null) {	// there are behaviors!
401 			for (int i = 0; i < behaviors.length; i++) {
402 				ptg.addChild(behaviors[i]);
403 			}
404 		}
405 		g.addChild(ptg);
406 		this.universe.addBranchGraph(g);
407 	}
408 }