001: /*
002: * $RCSfile: SceneGraphObject.java,v $
003: *
004: * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
006: *
007: * This code is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU General Public License version 2 only, as
009: * published by the Free Software Foundation. Sun designates this
010: * particular file as subject to the "Classpath" exception as provided
011: * by Sun in the LICENSE file that accompanied this code.
012: *
013: * This code is distributed in the hope that it will be useful, but WITHOUT
014: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
015: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
016: * version 2 for more details (a copy is included in the LICENSE file that
017: * accompanied this code).
018: *
019: * You should have received a copy of the GNU General Public License version
020: * 2 along with this work; if not, write to the Free Software Foundation,
021: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
022: *
023: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
024: * CA 95054 USA or visit www.sun.com if you need additional information or
025: * have any questions.
026: *
027: * $Revision: 1.7 $
028: * $Date: 2008/02/28 20:17:29 $
029: * $State: Exp $
030: */
031:
032: package javax.media.j3d;
033:
034: import java.util.Hashtable;
035:
036: /**
037: * SceneGraphObject is the common superclass for all scene graph
038: * objects. Scene graph objects are classified into two main types:
039: * nodes and node components. The Node object is the common superclass
040: * of all nodes, which includes TransformGroup, Shape3D, etc.
041: * The NodeComponent object is the common superclass of all node
042: * components, which includes Geometry, Appearance, etc.
043: *
044: * <p>
045: * All scene graph objects have a name, a user data object, a set of
046: * capability bits, and a set of capabilityIsFrequent bits.
047: *
048: * <p>
049: * Capability bits control whether a particular attribute in a node or
050: * node component is readable or writable. For live or compiled scene
051: * graphs, only those attributes whose capabilities are set before the
052: * scene graph is compiled or made live may be read or written. The
053: * default value for all <i>read</i> capability bits is true, meaning
054: * that all attributes may be read by default. The default value for
055: * all <i>write</i> capability bits is false, meaning that no
056: * attributes may be written by default. Read capability bits are
057: * defined as those capability bits of the form <code>ALLOW_*_READ</code>,
058: * plus the <code>ALLOW_INTERSECT</code> capability bit. Write
059: * capability bits are defined as those capability bits of the form
060: * <code>ALLOW_*_WRITE</code>, plus the <code>ALLOW_CHILDREN_EXTEND</code>
061: * and <code>ALLOW_DETACH</code> capability bits.
062: *
063: * <p>
064: * NOTE that the <code>ENABLE_COLLISION_REPORTING</code> and
065: * <code>ENABLE_PICK_REPORTING</code> bits are not really capability bits,
066: * although they are set with the setCapability method. The default value
067: * for each of the <code>ENABLE_*_REPORTING bits</code> is false.
068: *
069: * <p>
070: * For more information, see the
071: * <a href="doc-files/intro.html">Introduction to the Java 3D API</a>.
072: */
073: public abstract class SceneGraphObject extends Object {
074: // Any global flags? (e.g., execution cullable, collideable)
075:
076: // Reference to the retained-mode scene-graph element.
077: SceneGraphObjectRetained retained;
078:
079: // This object's capability bits
080: private long capabilityBits = 0L;
081:
082: // This object's capabilityIsFrequent bits
083: private long capabilityIsFrequentBits = ~0L;
084:
085: //boolean indicating is Scene Graph is compiled
086: private boolean compiled = false;
087:
088: //boolean indicating if Scene Graph is live.
089: private boolean live = false;
090:
091: //boolean indicating if Scene Graph is live or compiled
092: private boolean liveOrCompiled = false;
093:
094: // A reference to user data
095: private Object userData = null;
096:
097: // Optional name for object.
098: private String objectName = null;
099:
100: // use for cloneTree/cloneNode only, set to null after the operation
101: Hashtable nodeHashtable = null;
102:
103: /**
104: * Constructs a SceneGraphObject with default parameters. The default
105: * values are as follows:
106: * <ul>
107: * all <i>read</i> capability bits : set (true)<br>
108: * all <i>write</i> capability bits : clear (false)<br>
109: * all capabilityIsFrequent bits : set (true)<br>
110: * isLive : false<br>
111: * isCompiled : false<br>
112: * user data : null<br>
113: * name : null<br>
114: * </ul>
115: */
116: public SceneGraphObject() {
117: createRetained();
118: }
119:
120: /**
121: * Creates the retained mode object that this scene graph object
122: * will point to. This should be overridden by those classes
123: * that have a specific retained mode object.
124: */
125: void createRetained() {
126: this .retained = null;
127:
128: // Non-abstract subclasses of SceneGraphObject should override
129: // this function with code which is something like the following:
130: //
131: // this.retained = new <ClassName>Retained();
132: // this.retained.setSource(this);
133: }
134:
135: /**
136: * Method to set default read capability bits to true
137: */
138: void setDefaultReadCapabilities(int[] bits) {
139: if (true /*VirtualUniverse.mc.defaultReadCapability*/) {
140: for (int i = 0; i < bits.length; i++) {
141: setCapability(bits[i]);
142: }
143: }
144: }
145:
146: /**
147: * Retrieves the specified capability bit. Note that only one capability
148: * bit may be retrieved per method invocation--capability bits cannot
149: * be ORed together.
150: * @param bit the bit whose value is returned
151: * @return true if the bit is set, false if the bit is clear
152: */
153: public final boolean getCapability(int bit) {
154: return (capabilityBits & (1L << bit)) != 0L;
155: }
156:
157: /**
158: * Sets the specified capability bit. Note that only one capability bit
159: * may be set per method invocation--capability bits cannot be ORed
160: * together.
161: * @param bit the bit to set
162: * @exception RestrictedAccessException if this object is part of live
163: * or compiled scene graph
164: */
165: public final void setCapability(int bit) {
166: if (isLiveOrCompiled()) {
167: throw new RestrictedAccessException(J3dI18N
168: .getString("SceneGraphObject0"));
169: }
170:
171: capabilityBits |= (1L << bit);
172: retained.handleFrequencyChange(bit);
173:
174: }
175:
176: /**
177: * Clear the specified capability bit. Note that only one capability bit
178: * may be cleared per method invocation--capability bits cannot be ORed
179: * together.
180: * @param bit the bit to clear
181: * @exception RestrictedAccessException if this object is part of live
182: * or compiled scene graph
183: */
184: public final void clearCapability(int bit) {
185: if (isLiveOrCompiled())
186: throw new RestrictedAccessException(J3dI18N
187: .getString("SceneGraphObject0"));
188:
189: capabilityBits &= ~(1L << bit);
190: retained.handleFrequencyChange(bit);
191: }
192:
193: // Internal method, returns true if no capability bits are set
194: final boolean capabilityBitsEmpty() {
195: return capabilityBits == 0L;
196: }
197:
198: /**
199: * Retrieves the isFrequent bit associated with the specified capability
200: * bit.
201: *
202: * Note that only one isFrequent bit, for a single capability
203: * bit, may be retrieved per method invocation--capability bits cannot
204: * be ORed together.
205: *
206: * @param bit the bit whose value is returned
207: *
208: * @return true if the isFrequent bit is set, false if the isFrequent
209: * bit is clear
210: *
211: * @since Java 3D 1.3
212: */
213: public final boolean getCapabilityIsFrequent(int bit) {
214: return (capabilityIsFrequentBits & (1L << bit)) != 0L;
215: }
216:
217: /**
218: * Sets the isFrequent bit associated with the specified
219: * capability bit. Setting the isFrequent bit indicates that the
220: * application may frequently access or modify those attributes
221: * permitted by the associated capability bit. This can be used
222: * by Java 3D as a hint to avoid certain optimizations that could
223: * cause those accesses or modifications to be expensive. By
224: * default the isFrequent bit associated with each capability bit
225: * is set.
226: *
227: * <p>
228: * Unlike setCapability, this method may be called on a live scene
229: * graph object (but not on a compiled object).
230: *
231: * <p>
232: * Note that only one isFrequent bit, for a single capability bit,
233: * may be set per method invocation--capability bits cannot be ORed
234: * together.
235: *
236: * @param bit the capability bit for which to set the associated
237: * isFrequent bit
238: *
239: * @exception RestrictedAccessException if this object is part of a
240: * compiled scene graph
241: *
242: * @since Java 3D 1.3
243: */
244: public final void setCapabilityIsFrequent(int bit) {
245: if (isCompiled())
246: throw new RestrictedAccessException(J3dI18N
247: .getString("SceneGraphObject1"));
248:
249: capabilityIsFrequentBits |= (1L << bit);
250: retained.handleFrequencyChange(bit);
251: }
252:
253: /**
254: * Clears the isFrequent bit associated with the specified
255: * capability bit. Clearing the isFrequent bit indicates that the
256: * application will infrequently access or modify those attributes
257: * permitted by the associated capability bit. This can be used
258: * by Java 3D as a hint to enable certain optimizations that it
259: * might otherwise avoid, for example, optimizations that could
260: * cause those accesses or modifications to be expensive.
261: *
262: * <p>
263: * Unlike clearCapability, this method may be called on a live scene
264: * graph object (but not on a compiled object).
265: *
266: * <p>
267: * Note that only one isFrequent bit, for a single capability bit,
268: * may be cleared per method invocation--capability bits cannot be ORed
269: * together.
270: *
271: * @param bit the capability bit for which to clear the associated
272: * isFrequent bit
273: *
274: * @exception RestrictedAccessException if this object is part of a
275: * compiled scene graph
276: *
277: * @since Java 3D 1.3
278: */
279: public final void clearCapabilityIsFrequent(int bit) {
280: if (isCompiled())
281: throw new RestrictedAccessException(J3dI18N
282: .getString("SceneGraphObject1"));
283:
284: capabilityIsFrequentBits &= ~(1L << bit);
285: retained.handleFrequencyChange(bit);
286: }
287:
288: /**
289: * Sets an internal flag which indicates that this scene graph object
290: * has been compiled.
291: */
292: final void setCompiled() {
293: this .compiled = true;
294: this .liveOrCompiled = this .live || this .compiled;
295: }
296:
297: /**
298: * Returns a flag indicating whether the node is part of a scene graph
299: * that has been compiled. If so, then only those capabilities explicitly
300: * allowed by the object's capability bits are allowed.
301: * @return true if node is part of a compiled scene graph, else false
302: */
303:
304: public final boolean isCompiled() {
305: return this .compiled;
306: }
307:
308: /**
309: * Sets an internal flag which indicates that this scene graph object
310: * is part of a live scene graph.
311: */
312: final void setLive() {
313: this .live = true;
314: this .liveOrCompiled = this .live || this .compiled;
315: }
316:
317: /**
318: * Clears an internal flag which indicates that this scene graph object
319: * is no longer part of a live scene graph.
320: */
321: final void clearLive() {
322: this .live = false;
323: this .liveOrCompiled = this .live || this .compiled;
324: }
325:
326: /**
327: * Returns a flag indicating whether the node is part of a live
328: * scene graph.
329: * @return true if node is part of a live scene graph, else false
330: */
331: public final boolean isLive() {
332: return this .live;
333: }
334:
335: /**
336: * Returns a flag indicating whether the node is part of a live
337: * scene graph or a compiled scene graph.
338: * @return true if either live or compiled
339: */
340: final boolean isLiveOrCompiled() {
341: return liveOrCompiled;
342: }
343:
344: final void checkForLiveOrCompiled() {
345: if (isLiveOrCompiled())
346: throw new RestrictedAccessException(J3dI18N
347: .getString("SceneGraphObject2"));
348: }
349:
350: /**
351: * Sets the userData field associated with this scene graph object.
352: * The userData field is a reference to an arbitrary object
353: * and may be used to store any user-specific data associated
354: * with this scene graph object--it is not used by the Java 3D API.
355: * If this object is cloned, the userData field is copied
356: * to the newly cloned object.
357: * @param userData a reference to the new userData field
358: */
359: public void setUserData(Object userData) {
360: this .userData = userData;
361: }
362:
363: /**
364: * Retrieves the userData field from this scene graph object.
365: * @return the current userData field
366: */
367: public Object getUserData() {
368: return this .userData;
369: }
370:
371: /**
372: * Callback used to allow a node to check if any scene graph objects
373: * referenced by that node have been duplicated via a call to
374: * <code>cloneTree</code>.
375: * This method is called by <code>cloneTree</code> after all nodes in
376: * the sub-graph have been duplicated. The cloned Leaf
377: * node and cloned NodeComponent's method
378: * will be called and the Leaf node/NodeComponent can then look up
379: * any object references
380: * by using the <code>getNewObjectReference</code> method found in the
381: * <code>NodeReferenceTable</code> object. If a match is found, a
382: * reference to the corresponding object in the newly cloned sub-graph
383: * is returned. If no corresponding reference is found, either a
384: * DanglingReferenceException is thrown or a reference to the original
385: * object is returned depending on the value of the
386: * <code>allowDanglingReferences</code> parameter passed in the
387: * <code>cloneTree</code> call.
388: * <p>
389: * NOTE: Applications should <i>not</i> call this method directly.
390: * It should only be called by the cloneTree method.
391: *
392: * @param referenceTable a NodeReferenceTableObject that contains the
393: * <code>getNewObjectReference</code> method needed to search for
394: * new object instances.
395: * @see NodeReferenceTable
396: * @see Node#cloneTree
397: * @see DanglingReferenceException
398: */
399: public void updateNodeReferences(NodeReferenceTable referenceTable) {
400: }
401:
402: /**
403: * Sets the name of this object. Object names are for information
404: * only.
405: *
406: * @param name the new name of this object
407: *
408: * @since Java 3D 1.4
409: */
410: public void setName(String name) {
411: objectName = name;
412: }
413:
414: /**
415: * Returns the name of this object.
416: *
417: * @return the name of this object
418: *
419: * @since Java 3D 1.4
420: */
421: public String getName() {
422: return objectName;
423: }
424:
425: /**
426: * Copies all SceneGraphObject information from
427: * <code>originalNode</code> into
428: * the current node. This method is called from the
429: * <code>cloneNode</code> method which is, in turn, called by the
430: * <code>cloneTree</code> method.
431: * <P>
432: * NOTE: Applications should <i>not</i> call this method directly.
433: * It should only be called by the cloneNode method.
434: *
435: * @param originalNode the original node to duplicate.
436: *
437: * @see Group#cloneNode
438: * @see Node#duplicateNode
439: * @see Node#cloneTree
440: * @see NodeComponent#setDuplicateOnCloneTree
441: */
442: protected void duplicateSceneGraphObject(
443: SceneGraphObject originalNode) {
444: // Duplicate any class specific data here.
445: capabilityBits = originalNode.capabilityBits;
446: userData = originalNode.userData;
447: objectName = originalNode.objectName;
448: }
449:
450: /**
451: * If <code>forceDuplicate</code> is <code>true</code> or
452: * <code>duplicateOnCloneTree</code> flag is true. This procedure
453: * will return a clone of originalNode or the value in
454: * in <code>nodeHashtable</code> if found. Otherwise return
455: * <code>originalNode</code>
456: *
457: * This method is called from the
458: * <code>duplicateAttributes</code> method during cloneNodeComponent.
459: *
460: * @param originalNodeComponent the original node to duplicate.
461: * @param forceDuplicate when set to <code>true</code>, causes the
462: * <code>duplicateOnCloneTree</code> flag to be ignored. When
463: * <code>false</code>, the value of each node's
464: * <code>duplicateOnCloneTree</code> variable determines whether
465: * NodeComponent data is duplicated or copied.
466: * @param nodeHashtable is used to keep track of mapping between old and
467: * new node references.
468: */
469: NodeComponent getNodeComponent(NodeComponent originalNodeComponent,
470: boolean forceDuplicate, Hashtable hashtable) {
471: if ((originalNodeComponent != null)
472: && (forceDuplicate || originalNodeComponent
473: .duplicateChild())) {
474: NodeComponent nc = (NodeComponent) hashtable
475: .get(originalNodeComponent);
476: if (nc == null) {
477: originalNodeComponent.nodeHashtable = hashtable;
478: try {
479: nc = originalNodeComponent
480: .cloneNodeComponent(forceDuplicate);
481: } catch (RuntimeException e) {
482: // must reset nodeHashtable in any case
483: originalNodeComponent.nodeHashtable = null;
484: throw e;
485: }
486: originalNodeComponent.nodeHashtable = null;
487: // put link to be shared by other Node
488: hashtable.put(originalNodeComponent, nc);
489: } // use the share clone node otherwise
490: return nc;
491: } else {
492: return originalNodeComponent;
493: }
494: }
495:
496: // Internal method to make a prefix out of the name of this object
497: String getNamePrefix() {
498: String name = getName();
499:
500: if (name != null) {
501: return "[" + name + "] ";
502: }
503:
504: return "";
505: }
506:
507: /**
508: * Returns a String representation of this SceneGraphObject.
509: * If its name is non-null, then it is concatenated with
510: * super.toString().
511: */
512: public String toString() {
513: return getNamePrefix() + super.toString();
514: }
515:
516: }
|