View Javadoc

1   /*
2    * @(#) Animation3DCanvas.java May 10, 2004
3    * 
4    * Copyright (c) 2002-2005 Delft University of Technology Jaffalaan 5, 2628 BX
5    * Delft, the Netherlands. All rights reserved.
6    * 
7    * This software is proprietary information of Delft University of Technology
8    * The code is published under the Lesser General Public License
9    */
10  package nl.tudelft.simulation.dsol.gui.animation3D;
11  
12  import java.rmi.RemoteException;
13  
14  import javax.media.j3d.BoundingSphere;
15  import javax.media.j3d.BranchGroup;
16  import javax.media.j3d.Canvas3D;
17  import javax.media.j3d.Locale;
18  import javax.media.j3d.VirtualUniverse;
19  import javax.naming.Binding;
20  import javax.naming.NamingEnumeration;
21  import javax.naming.event.EventContext;
22  import javax.naming.event.NamespaceChangeListener;
23  import javax.naming.event.NamingEvent;
24  import javax.naming.event.NamingExceptionEvent;
25  
26  import nl.tudelft.simulation.dsol.animation.D3.Renderable3DInterface;
27  import nl.tudelft.simulation.dsol.experiment.Experiment;
28  import nl.tudelft.simulation.dsol.gui.DSOLApplicationInterface;
29  import nl.tudelft.simulation.dsol.gui.animation3D.mouse.PickObjectMouseBehavior;
30  import nl.tudelft.simulation.dsol.simulators.AnimatorInterface;
31  import nl.tudelft.simulation.dsol.simulators.SimulatorInterface;
32  import nl.tudelft.simulation.event.Event;
33  import nl.tudelft.simulation.event.EventInterface;
34  import nl.tudelft.simulation.event.EventListenerInterface;
35  import nl.tudelft.simulation.logger.Logger;
36  import nl.tudelft.simulation.naming.InitialEventContext;
37  
38  import com.sun.j3d.utils.universe.SimpleUniverse;
39  
40  /***
41   * Animation3DCanvas, a canvas for 3d animation <br>
42   * (c) copyright 2002-2005 <a href="http://www.simulation.tudelft.nl">Delft
43   * University of Technology </a>, the Netherlands. <br>
44   * See for project information <a
45   * href="http://www.simulation.tudelft.nl">www.simulation.tudelft.nl </a> <br>
46   * License of use: <a href="http://www.gnu.org/copyleft/lesser.html">Lesser
47   * General Public License (LGPL) </a>, no warranty.
48   * 
49   * @version $Revision$ $Date$
50   * @author <a href="http://www.tbm.tudelft.nl/webstaf/royc/index.htm">Roy Chin
51   *         </a>
52   */
53  public class Animation3DCanvas extends Canvas3D implements
54  		EventListenerInterface, NamespaceChangeListener
55  {
56  
57  	/*** the application */
58  	private DSOLApplicationInterface application = null;
59  
60  	/*** the eventContext */
61  	private EventContext context = null;
62  
63  	/*** View branch */
64  	private ViewBranch viewBranch = null;
65  
66  	/*** Content branch */
67  	private ContentBranch contentBranch = null;
68  
69  	/***
70  	 * Constructs a new panel
71  	 * 
72  	 * @param application DSOLApplicationInterface
73  	 */
74  	public Animation3DCanvas(final DSOLApplicationInterface application)
75  	{
76  		super(SimpleUniverse.getPreferredConfiguration());
77  		this.application = application;
78  		initializePanel();
79  		initializeSubscription();
80  	}
81  
82  	/***
83  	 * Initializes the panel
84  	 */
85  	public void initializePanel()
86  	{
87  		// ----------------
88  		// Configure canvas
89  		this.setFocusable(true);
90  
91  		// ------------------------------------
92  		// Create a default universe and locale
93  		VirtualUniverse universe = new VirtualUniverse();
94  		Locale locale = new Locale(universe);
95  
96  		// ---------------------
97  		// Build the scene graph
98  		this.viewBranch = new ViewBranch(this);
99  		this.contentBranch = new ContentBranch();
100 
101 		// --------------
102 		// Enable picking
103 		new PickObjectMouseBehavior(this, this.contentBranch,
104 				new BoundingSphere());
105 
106 		locale.addBranchGraph(this.viewBranch);
107 		locale.addBranchGraph(this.contentBranch);
108 	}
109 
110 	/***
111 	 * initializes the panel subscription
112 	 */
113 	private void initializeSubscription()
114 	{
115 		try
116 		{
117 			this.application.addListener(this,
118 					DSOLApplicationInterface.EXPERIMENT_CHANGED_EVENT);
119 			this.notify(new Event(
120 					DSOLApplicationInterface.EXPERIMENT_CHANGED_EVENT,
121 					this.application, this.application.getExperiment()));
122 		} catch (RemoteException exception)
123 		{
124 			Logger.warning(this, "initialize", exception);
125 		}
126 	}
127 
128 	/***
129 	 * @see nl.tudelft.simulation.event.EventListenerInterface#notify
130 	 *      (nl.tudelft.simulation.event.EventInterface)
131 	 */
132 	public void notify(final EventInterface event) throws RemoteException
133 	{
134 		// UPDATE_ANIMATION_EVENT
135 		if (event.getSource() instanceof AnimatorInterface
136 				&& event.getType().equals(
137 						AnimatorInterface.UPDATE_ANIMATION_EVENT))
138 		{
139 			if (this.getWidth() > 0 || this.getHeight() > 0)
140 			{
141 				this.updateElements();
142 				// this.repaint();
143 			}
144 			return;
145 		}
146 		// START_REPLICATION_EVENT
147 		if (event.getSource() instanceof AnimatorInterface
148 				&& event.getType().equals(
149 						SimulatorInterface.START_REPLICATION_EVENT))
150 		{
151 			this.contentBranch.getDynamicObjectBranch().removeAllChildren();
152 			this.contentBranch.getStaticObjectBranch().removeAllChildren();
153 			AnimatorInterface simulator = (AnimatorInterface) event.getSource();
154 			String contextName = this.application.getExperiment().getRun()
155 					+ "/treatment("
156 					+ simulator.getReplication().getRunControl().getTreatment()
157 							.getNumber() + ")/replication("
158 					+ simulator.getReplication().getNumber() + ")/animation/3D";
159 			try
160 			{
161 				if (this.context != null)
162 				{
163 					this.context.removeNamingListener(this);
164 				}
165 				this.context = (EventContext) new InitialEventContext()
166 						.lookup(contextName);
167 				this.context.addNamingListener("", EventContext.SUBTREE_SCOPE,
168 						this);
169 				NamingEnumeration list = this.context.listBindings("");
170 				while (list.hasMore())
171 				{
172 					Binding binding = (Binding) list.next();
173 					this.objectAdded(new NamingEvent(this.context, -1, binding,
174 							binding, null));
175 				}
176 				this.updateElements();
177 				// this.repaint();
178 			} catch (Exception exception)
179 			{
180 				Logger.warning(this, "notify", exception);
181 			}
182 		}
183 		// SIMULATOR_CHANGED_EVENT
184 		if (event.getSource() instanceof Experiment
185 				&& event.getType().equals(Experiment.SIMULATOR_CHANGED_EVENT))
186 		{
187 			// System.out.println("SIMULATOR_CHANGED_EVENT");
188 			this.contentBranch.getDynamicObjectBranch().removeAllChildren();
189 			this.contentBranch.getStaticObjectBranch().removeAllChildren();
190 			this.updateElements();
191 			// this.repaint();
192 			if (event.getContent() instanceof AnimatorInterface
193 					&& event.getContent() != null)
194 			{
195 				AnimatorInterface simulator = (AnimatorInterface) event
196 						.getContent();
197 				simulator.addListener(this,
198 						AnimatorInterface.UPDATE_ANIMATION_EVENT);
199 				if (simulator.getReplication() != null)
200 				{
201 					this.notify(new Event(
202 							SimulatorInterface.START_REPLICATION_EVENT,
203 							simulator, simulator));
204 				} else
205 				{
206 					simulator.addListener(this,
207 							SimulatorInterface.START_REPLICATION_EVENT);
208 				}
209 			}
210 		}
211 		// EXPERIMENT_CHANGED_EVENT
212 		if (event.getSource().equals(this.application)
213 				&& event.getType().equals(
214 						DSOLApplicationInterface.EXPERIMENT_CHANGED_EVENT))
215 		{
216 			// System.out.println("EXPERIMENT_CHANGED_EVENT");
217 			this.contentBranch.getDynamicObjectBranch().removeAllChildren();
218 			this.contentBranch.getStaticObjectBranch().removeAllChildren();
219 			this.updateElements();
220 			// this.repaint();
221 			if (event.getContent() != null)
222 			{
223 				Experiment experiment = (Experiment) event.getContent();
224 				experiment
225 						.addListener(this, Experiment.SIMULATOR_CHANGED_EVENT);
226 				this.notify(new Event(Experiment.SIMULATOR_CHANGED_EVENT,
227 						experiment, experiment.getSimulator()));
228 			}
229 			return;
230 		}
231 
232 	}
233 
234 	/***
235 	 * @see javax.naming.event.NamespaceChangeListener#objectAdded
236 	 *      (javax.naming.event.NamingEvent)
237 	 */
238 	public void objectAdded(final NamingEvent namingEvent)
239 	{
240 		Renderable3DInterface element = (Renderable3DInterface) namingEvent
241 				.getNewBinding().getObject();
242 		// Add the element's model to the content branch
243 		BranchGroup model = (BranchGroup) element;
244 		if (model != null)
245 		{
246 			if (element.getType() != Renderable3DInterface.DYNAMIC_OBJECT)
247 			{
248 				this.contentBranch.getStaticObjectBranch().addChild(model);
249 			} else
250 			{
251 				this.contentBranch.getDynamicObjectBranch().addChild(model);
252 			}
253 		}
254 	}
255 
256 	/***
257 	 * @see javax.naming.event.NamespaceChangeListener#objectRemoved
258 	 *      (javax.naming.event.NamingEvent)
259 	 */
260 	public void objectRemoved(final NamingEvent namingEvent)
261 	{
262 		System.out.println("Animation3d: Object removed");
263 		Renderable3DInterface element = (Renderable3DInterface) namingEvent
264 				.getOldBinding().getObject();
265 
266 		// Remove element's model from the branch graph
267 		this.contentBranch.getDynamicObjectBranch().removeChild(
268 				(BranchGroup) element);
269 	}
270 
271 	/***
272 	 * @see javax.naming.event.NamespaceChangeListener#objectRenamed
273 	 *      (javax.naming.event.NamingEvent)
274 	 */
275 	public void objectRenamed(final NamingEvent namingEvent)
276 	{
277 		this.objectRemoved(namingEvent);
278 		this.objectAdded(namingEvent);
279 	}
280 
281 	/***
282 	 * @see javax.naming.event.NamingListener#namingExceptionThrown
283 	 *      (javax.naming.event.NamingExceptionEvent)
284 	 */
285 	public void namingExceptionThrown(final NamingExceptionEvent namingEvent)
286 	{
287 		Logger.warning(this, "namingExceptionThrown", namingEvent
288 				.getException());
289 	}
290 
291 	/***
292 	 * Update all elements
293 	 */
294 	public void updateElements()
295 	{
296 		BranchGroup dynamicObjectBranch = this.contentBranch
297 				.getDynamicObjectBranch();
298 		// Synchronize is meant to prevent shaky animation
299 		// when updating lots of objects. Seems to work.
300 		synchronized (this)
301 		{
302 			for (int i = 0; i < dynamicObjectBranch.numChildren(); i++)
303 			{
304 				Renderable3DInterface element = (Renderable3DInterface) dynamicObjectBranch
305 						.getChild(i);
306 				element.update();
307 			}
308 		}
309 	}
310 
311 	/***
312 	 * @return ContentBranch
313 	 */
314 	public ContentBranch getContentBranch()
315 	{
316 		return this.contentBranch;
317 	}
318 
319 	/***
320 	 * @return ViewBranch
321 	 */
322 	public ViewBranch getViewBranch()
323 	{
324 		return this.viewBranch;
325 	}
326 
327 }