View Javadoc

1   /*
2    * @(#) Renderable3D.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  
11  package nl.tudelft.simulation.dsol.animation.D3;
12  
13  import java.awt.geom.Point2D;
14  import java.rmi.RemoteException;
15  import java.util.Enumeration;
16  
17  import javax.media.j3d.BranchGroup;
18  import javax.media.j3d.Group;
19  import javax.media.j3d.Node;
20  import javax.media.j3d.Transform3D;
21  import javax.media.j3d.TransformGroup;
22  import javax.vecmath.AxisAngle4d;
23  import javax.vecmath.Vector3d;
24  
25  import nl.tudelft.simulation.dsol.animation.LocatableInterface;
26  import nl.tudelft.simulation.dsol.animation.StaticLocation;
27  import nl.tudelft.simulation.dsol.context.ContextUtil;
28  import nl.tudelft.simulation.dsol.simulators.SimulatorInterface;
29  import nl.tudelft.simulation.language.d3.DirectedPoint;
30  import nl.tudelft.simulation.logger.Logger;
31  
32  /***
33   * Renderable3D, a 3d renderable <br>
34   * (c) copyright 2003 <a href="http://www.simulation.tudelft.nl">Delft
35   * University of Technology </a>, the Netherlands. <br>
36   * See for project information <a
37   * href="http://www.simulation.tudelft.nl">www.simulation.tudelft.nl </a> <br>
38   * License of use: <a href="http://www.gnu.org/copyleft/gpl.html">General Public
39   * License (GPL) </a>, no warranty <br>
40   * 
41   * @version 1.0 10.05.2004 <br>
42   * @author <a href="http://www.tbm.tudelft.nl/webstaf/royc/index.htm">Roy Chin
43   *         </a>
44   */
45  public abstract class Renderable3D extends BranchGroup implements
46  		Renderable3DInterface
47  {
48  	/*** the source of this animatableObject */
49  	protected LocatableInterface source = null;
50  
51  	/*** the simulator */
52  	protected SimulatorInterface simulator = null;
53  
54  	/*** Rotation group */
55  	protected TransformGroup locationGroup = null;
56  
57  	/*** Type of renderable (world, static or simulated */
58  	protected int type = Renderable3DInterface.DYNAMIC_OBJECT;
59  
60  	/***
61  	 * Scale: temporary solution This scale is used to scale translations and
62  	 * can also be used to scale the model (shape). This is a temporary solution
63  	 * as we would actually like to scale the entire content branch, but this is
64  	 * not possible yet
65  	 */
66  	protected double scale = 1.0d;
67  
68  	/***
69  	 * translation Used in update; put here to prevent garbage
70  	 */
71  	private Transform3D translate = new Transform3D();
72  
73  	/***
74  	 * combined rotation angle Used in update; put here to prevent garbage
75  	 */
76  	private Transform3D rotate = new Transform3D();
77  
78  	/***
79  	 * yaw angle Used in update; put here to prevent garbage
80  	 */
81  	private Transform3D yaw = new Transform3D();
82  
83  	/***
84  	 * pitch angle Used in update; put here to prevent garbage
85  	 */
86  	private Transform3D pitch = new Transform3D();
87  
88  	/***
89  	 * roll angle Used in update; put here to prevent garbage
90  	 */
91  	private Transform3D roll = new Transform3D();
92  
93  	/***
94  	 * @param simulator SimulatorInterface
95  	 */
96  	public Renderable3D(final SimulatorInterface simulator)
97  	{
98  		if (!LocatableInterface.class.isAssignableFrom(this.getClass()))
99  		{
100 			throw new IllegalArgumentException(
101 					"this class should implement Locatable interface");
102 		}
103 		this.source = (LocatableInterface) this;
104 		this.simulator = simulator;
105 		this.initialize();
106 	}
107 
108 	/***
109 	 * @param staticLocation Point3d
110 	 * @param simulator SimulatorInterface
111 	 */
112 	public Renderable3D(final DirectedPoint staticLocation,
113 			final SimulatorInterface simulator)
114 	{
115 		super();
116 		this.source = new StaticLocation(staticLocation, null);
117 		this.simulator = simulator;
118 		this.type = Renderable3DInterface.STATIC_OBJECT;
119 		this.initialize();
120 	}
121 
122 	/***
123 	 * @param staticLocation Point3d
124 	 * @param branchGroup A branchGroup containing (a part of) the model
125 	 * @param simulator SimulatorInterface
126 	 */
127 	public Renderable3D(final DirectedPoint staticLocation,
128 			final BranchGroup branchGroup, final SimulatorInterface simulator)
129 	{
130 		super();
131 		this.source = new StaticLocation(staticLocation, null);
132 		this.simulator = simulator;
133 		this.type = Renderable3DInterface.STATIC_OBJECT;
134 		this.initializeTransformGroups();
135 		this.provideModel(this.locationGroup);
136 		this.addChild(this.locationGroup);
137 		this.addChild(branchGroup);
138 		this.update();
139 		ContextUtil.bindToContext(this.simulator, "/animation/3D", this);
140 	}
141 
142 	/***
143 	 * @param staticLocation Point2D
144 	 * @param simulator SimulatorInterface
145 	 */
146 	public Renderable3D(final Point2D staticLocation,
147 			final SimulatorInterface simulator)
148 	{
149 		this(new DirectedPoint(staticLocation), simulator);
150 	}
151 
152 	/***
153 	 * @param source LocatableInterface
154 	 * @param simulator SimulatorInterface
155 	 */
156 	public Renderable3D(final LocatableInterface source,
157 			final SimulatorInterface simulator)
158 	{
159 		super();
160 		this.source = source;
161 		this.simulator = simulator;
162 		this.initialize();
163 	}
164 
165 	/***
166 	 * Initialize
167 	 */
168 	private void initialize()
169 	{
170 		// Note: the order of the lines below does matter!
171 		// AnimationFrame3D wants to draw as soon as it has
172 		// got the object from the context, so transforms
173 		// better be initialized.
174 		//
175 		// Note2: RunControl.notify() must create the subcontext:
176 		// "/animation3d"
177 		this.initializeTransformGroups();
178 		this.provideModel(this.locationGroup);
179 		this.addChild(this.locationGroup);
180 		this.update();
181 		ContextUtil.bindToContext(this.simulator, "/animation/3D", this);
182 	}
183 
184 	/***
185 	 * Initialize TransformGroups
186 	 */
187 	private void initializeTransformGroups()
188 	{
189 		this.setCapability(Group.ALLOW_CHILDREN_READ);
190 		this.setCapability(Group.ALLOW_CHILDREN_WRITE);
191 		this.setCapability(Group.ALLOW_CHILDREN_EXTEND);
192 		this.setCapability(BranchGroup.ALLOW_DETACH);
193 		this.setCapability(Node.ENABLE_PICK_REPORTING);
194 		// Determine if this branch group is pickable
195 		if (this.type == Renderable3DInterface.DYNAMIC_OBJECT)
196 		{
197 			this.setPickable(true);
198 		} else
199 		{
200 			this.setPickable(false);
201 		}
202 
203 		this.locationGroup = new TransformGroup();
204 
205 		this.locationGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
206 		this.locationGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
207 		this.locationGroup.setCapability(Group.ALLOW_CHILDREN_READ);
208 		this.locationGroup.setCapability(Group.ALLOW_CHILDREN_WRITE);
209 		this.locationGroup.setCapability(Group.ALLOW_CHILDREN_EXTEND);
210 		if (this.type == Renderable3DInterface.DYNAMIC_OBJECT)
211 		{
212 			this.locationGroup
213 					.setCapabilityIsFrequent(TransformGroup.ALLOW_TRANSFORM_READ);
214 			this.locationGroup
215 					.setCapabilityIsFrequent(TransformGroup.ALLOW_TRANSFORM_READ);
216 		}
217 	}
218 
219 	/***
220 	 * Provide the 3D model and add it to the locationGroup
221 	 * 
222 	 * @param locationGroup The location of the object
223 	 */
224 	protected abstract void provideModel(final TransformGroup locationGroup);
225 
226 	/***
227 	 * @see nl.tudelft.simulation.dsol.animation.D3.
228 	 *      Renderable3DInterface#update()
229 	 */
230 	public void update()
231 	{
232 		try
233 		{
234 			this.update(this.getAllChildren());
235 			DirectedPoint location = this.getSource().getLocation();
236 			this.translate.set(new Vector3d(location.x * this.scale, location.y
237 					* this.scale, location.z * this.scale));
238 
239 			// Hope the order of the rotations is correct ...
240 			this.yaw.setRotation(new AxisAngle4d(0, 0, 1, location.getRotX()));
241 			this.pitch.setRotation(new AxisAngle4d(0, 1, 0, location.getRotZ()));
242 			this.roll.setRotation(new AxisAngle4d(1, 0, 0, location.getRotY()));
243 
244 			// first translate then rotate
245 			this.rotate.set(this.translate);
246 			this.rotate.mul(this.yaw);
247 			this.rotate.mul(this.pitch);
248 			this.rotate.mul(this.roll);
249 
250 			this.locationGroup.setTransform(this.rotate);
251 		} catch (RemoteException exception)
252 		{
253 			this.rotate.set(new Vector3d(0, 0, 0));
254 			Logger.warning(this, "update", exception);
255 		}
256 	}
257 
258 	/***
259 	 * Method update.
260 	 * 
261 	 * @param children the children to update.
262 	 */
263 	protected abstract void update(final Enumeration children);
264 
265 	/***
266 	 * @return LocatableInterface
267 	 */
268 	public LocatableInterface getSource()
269 	{
270 		return this.source;
271 	}
272 
273 	/***
274 	 * @see nl.tudelft.simulation.dsol.animation.D3.
275 	 *      Renderable3DInterface#getType()
276 	 */
277 	public int getType()
278 	{
279 		return this.type;
280 	}
281 
282 	/***
283 	 * @return scale
284 	 */
285 	public double getScale()
286 	{
287 		return this.scale;
288 	}
289 
290 	/***
291 	 * @param scale Set the scale of the coordinates
292 	 */
293 	public void setScale(final double scale)
294 	{
295 		this.scale = scale;
296 	}
297 }