View Javadoc

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