001: /*
002: * $RCSfile: ModelClip.java,v $
003: *
004: * Copyright 1999-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.6 $
028: * $Date: 2008/02/28 20:17:26 $
029: * $State: Exp $
030: */
031:
032: package javax.media.j3d;
033:
034: import javax.vecmath.*;
035: import java.util.Enumeration;
036:
037: /**
038: * The ModelClip leaf node defines a set of 6 arbitrary clipping
039: * planes in the virtual universe. The planes are specified in the
040: * local coordinate system of this node, and may be individually
041: * enabled or disabled. This node also specifies a region of
042: * influence in which this set of planes is active.
043: *<p>
044: * A ModelClip node also contains a list of Group nodes that specifies the
045: * hierarchical scope of this ModelClip. If the scope list is empty, then
046: * the ModelClip node has universe scope: all nodes within the region of
047: * influence are affected by this ModelClip node. If the scope list is
048: * non-empty, then only those Leaf nodes under the Group nodes in the
049: * scope list are affected by this ModelClip node (subject to the
050: * influencing bounds).
051: * <p>
052: * If the regions of influence of multiple ModelClip nodes overlap, the
053: * Java 3D system will choose a single set of model clip planes for those
054: * objects that lie in the intersection. This is done in an
055: * implementation-dependent manner, but in general, the ModelClip node that
056: * is "closest" to the object is chosen.
057: * <p>
058: * The individual planes specify a half-space defined by the equation:
059: * <ul>
060: * Ax + By + Cz + D <= 0
061: * </ul>
062: * where A, B, C, D are the parameters that specify the plane. The
063: * parameters are passed in the x, y, z, and w fields, respectively,
064: * of a Vector4d object. The intersection of the set of half-spaces
065: * corresponding to the enabled planes in this ModelClip node defines
066: * a region in which points are accepted. Points in this acceptance
067: * region will be rendered (subject to view clipping and other
068: * attributes). Points that are not in the acceptance region will not
069: * be rendered.
070: *
071: * @since Java 3D 1.2
072: */
073:
074: public class ModelClip extends Leaf {
075: /**
076: * Specifies that the ModelClip node allows read access to its influencing
077: * bounds and bounding leaf at runtime.
078: */
079: public static final int ALLOW_INFLUENCING_BOUNDS_READ = CapabilityBits.MODEL_CLIP_ALLOW_INFLUENCING_BOUNDS_READ;
080:
081: /**
082: * Specifies that the ModelClip node allows write access to its influencing
083: * bounds and bounding leaf at runtime.
084: */
085: public static final int ALLOW_INFLUENCING_BOUNDS_WRITE = CapabilityBits.MODEL_CLIP_ALLOW_INFLUENCING_BOUNDS_WRITE;
086:
087: /**
088: * Specifies that the ModelClip node allows read access to its planes
089: * at runtime.
090: */
091: public static final int ALLOW_PLANE_READ = CapabilityBits.MODEL_CLIP_ALLOW_PLANE_READ;
092:
093: /**
094: * Specifies that the ModelClip node allows write access to its planes
095: * at runtime.
096: */
097: public static final int ALLOW_PLANE_WRITE = CapabilityBits.MODEL_CLIP_ALLOW_PLANE_WRITE;
098:
099: /**
100: * Specifies that the ModelClip node allows read access to its enable
101: * flags at runtime.
102: */
103: public static final int ALLOW_ENABLE_READ = CapabilityBits.MODEL_CLIP_ALLOW_ENABLE_READ;
104:
105: /**
106: * Specifies that the ModelClip node allows write access to its enable
107: * flags at runtime.
108: */
109: public static final int ALLOW_ENABLE_WRITE = CapabilityBits.MODEL_CLIP_ALLOW_ENABLE_WRITE;
110:
111: /**
112: * Specifies that this ModelClip node allows read access to its scope
113: * information at runtime.
114: */
115: public static final int ALLOW_SCOPE_READ = CapabilityBits.MODEL_CLIP_ALLOW_SCOPE_READ;
116:
117: /**
118: * Specifies that this ModelClip node allows write access to its scope
119: * information at runtime.
120: */
121: public static final int ALLOW_SCOPE_WRITE = CapabilityBits.MODEL_CLIP_ALLOW_SCOPE_WRITE;
122:
123: // Array for setting default read capabilities
124: private static final int[] readCapabilities = { ALLOW_SCOPE_READ,
125: ALLOW_ENABLE_READ, ALLOW_INFLUENCING_BOUNDS_READ,
126: ALLOW_PLANE_READ };
127:
128: /**
129: * Constructs a ModelClip node with default parameters. The default
130: * values are as follows:
131: * <ul>
132: * planes[0] : x <= 1 (1,0,0,-1)<br>
133: * planes[1] : -x <= 1 (-1,0,0,-1)<br>
134: * planes[2] : y <= 1 (0,1,0,-1)<br>
135: * planes[3] : -y <= 1 (0,-1,0,-1)<br>
136: * planes[4] : z <= 1 (0,0,1,-1)<br>
137: * planes[5] : -z <= 1 (0,0,-1,-1)<br>
138: * enables : all planes enabled<br>
139: * scope : empty (universe scope)<br>
140: * influencing bounds : null<br>
141: * influencing bounding leaf : null<br>
142: * </ul>
143: */
144: public ModelClip() {
145: // Just use the defaults
146: // set default read capabilities
147: setDefaultReadCapabilities(readCapabilities);
148:
149: }
150:
151: /**
152: * Constructs a ModelClip node using the specified planes. The individual
153: * planes are copied into this node. All planes are enabled.
154: * @param planes an array of 6 model clipping planes
155: */
156: public ModelClip(Vector4d[] planes) {
157: // set default read capabilities
158: setDefaultReadCapabilities(readCapabilities);
159:
160: ((ModelClipRetained) this .retained).initPlanes(planes);
161: }
162:
163: /**
164: * Constructs a ModelClip node using the specified planes and enable
165: * flags. The individual
166: * planes and enable flags are copied into this node.
167: * @param planes an array of 6 model clipping planes
168: * @param enables an array of 6 enable flags
169: */
170: public ModelClip(Vector4d[] planes, boolean[] enables) {
171: // set default read capabilities
172: setDefaultReadCapabilities(readCapabilities);
173:
174: ((ModelClipRetained) this .retained).initPlanes(planes);
175: ((ModelClipRetained) this .retained).initEnables(enables);
176: }
177:
178: /**
179: * Set the ModelClip node's influencing region to the specified bounds.
180: * This is used when the influencing bounding leaf is set to null.
181: * @param region the bounds that contains the new influencing
182: * region.
183: * @exception CapabilityNotSetException if appropriate capability is
184: * not set and this object is part of live or compiled scene graph
185: */
186: public void setInfluencingBounds(Bounds region) {
187: if (isLiveOrCompiled())
188: if (!this .getCapability(ALLOW_INFLUENCING_BOUNDS_WRITE))
189: throw new CapabilityNotSetException(J3dI18N
190: .getString("ModelClip0"));
191:
192: if (isLive())
193: ((ModelClipRetained) this .retained)
194: .setInfluencingBounds(region);
195: else
196: ((ModelClipRetained) this .retained)
197: .initInfluencingBounds(region);
198: }
199:
200: /**
201: * Retrieves the ModelClip node's influencing bounds.
202: * @return this node's influencing bounds information
203: * @exception CapabilityNotSetException if appropriate capability is
204: * not set and this object is part of live or compiled scene graph
205: */
206: public Bounds getInfluencingBounds() {
207: if (isLiveOrCompiled())
208: if (!this .getCapability(ALLOW_INFLUENCING_BOUNDS_READ))
209: throw new CapabilityNotSetException(J3dI18N
210: .getString("ModelClip1"));
211:
212: return ((ModelClipRetained) this .retained)
213: .getInfluencingBounds();
214: }
215:
216: /**
217: * Set the ModelClip node's influencing region to the specified
218: * bounding leaf.
219: * When set to a value other than null, this overrides the influencing
220: * bounds object.
221: * @param region the bounding leaf node used to specify the
222: * new influencing region.
223: * @exception CapabilityNotSetException if appropriate capability is
224: * not set and this object is part of live or compiled scene graph
225: */
226: public void setInfluencingBoundingLeaf(BoundingLeaf region) {
227: if (isLiveOrCompiled())
228: if (!this .getCapability(ALLOW_INFLUENCING_BOUNDS_WRITE))
229: throw new CapabilityNotSetException(J3dI18N
230: .getString("ModelClip13"));
231:
232: if (isLive())
233: ((ModelClipRetained) this .retained)
234: .setInfluencingBoundingLeaf(region);
235: else
236: ((ModelClipRetained) this .retained)
237: .initInfluencingBoundingLeaf(region);
238: }
239:
240: /**
241: * Retrieves the ModelClip node's influencing bounding leaf.
242: * @return this node's influencing bounding leaf information
243: * @exception CapabilityNotSetException if appropriate capability is
244: * not set and this object is part of live or compiled scene graph
245: */
246: public BoundingLeaf getInfluencingBoundingLeaf() {
247: if (isLiveOrCompiled())
248: if (!this .getCapability(ALLOW_INFLUENCING_BOUNDS_READ))
249: throw new CapabilityNotSetException(J3dI18N
250: .getString("ModelClip14"));
251:
252: return ((ModelClipRetained) this .retained)
253: .getInfluencingBoundingLeaf();
254: }
255:
256: /**
257: * Replaces the node at the specified index in this ModelClip node's
258: * list of scopes with the specified Group node.
259: * By default, ModelClip nodes are scoped only by their influencing
260: * bounds. This allows them to be further scoped by a list of
261: * nodes in the hierarchy.
262: * @param scope the Group node to be stored at the specified index.
263: * @param index the index of the Group node to be replaced.
264: * @exception CapabilityNotSetException if appropriate capability is
265: * not set and this object is part of live or compiled scene graph
266: * @exception RestrictedAccessException if the specified group node
267: * is part of a compiled scene graph
268: */
269: public void setScope(Group scope, int index) {
270: if (isLiveOrCompiled())
271: if (!this .getCapability(ALLOW_SCOPE_WRITE))
272: throw new CapabilityNotSetException(J3dI18N
273: .getString("ModelClip7"));
274:
275: if (isLive())
276: ((ModelClipRetained) this .retained).setScope(scope, index);
277: else
278: ((ModelClipRetained) this .retained).initScope(scope, index);
279: }
280:
281: /**
282: * Retrieves the Group node at the specified index from this ModelClip node's
283: * list of scopes.
284: * @param index the index of the Group node to be returned.
285: * @return the Group node at the specified index.
286: * @exception CapabilityNotSetException if appropriate capability is
287: * not set and this object is part of live or compiled scene graph
288: */
289: public Group getScope(int index) {
290: if (isLiveOrCompiled())
291: if (!this .getCapability(ALLOW_SCOPE_READ))
292: throw new CapabilityNotSetException(J3dI18N
293: .getString("ModelClip8"));
294:
295: return ((ModelClipRetained) this .retained).getScope(index);
296: }
297:
298: /**
299: * Inserts the specified Group node into this ModelClip node's
300: * list of scopes at the specified index.
301: * By default, ModelClip nodes are scoped only by their influencing
302: * bounds. This allows them to be further scoped by a list of
303: * nodes in the hierarchy.
304: * @param scope the Group node to be inserted at the specified index.
305: * @param index the index at which the Group node is inserted.
306: * @exception CapabilityNotSetException if appropriate capability is
307: * not set and this object is part of live or compiled scene graph
308: * @exception RestrictedAccessException if the specified group node
309: * is part of a compiled scene graph
310: */
311: public void insertScope(Group scope, int index) {
312: if (isLiveOrCompiled())
313: if (!this .getCapability(ALLOW_SCOPE_WRITE))
314: throw new CapabilityNotSetException(J3dI18N
315: .getString("ModelClip9"));
316:
317: if (isLive())
318: ((ModelClipRetained) this .retained).insertScope(scope,
319: index);
320: else
321: ((ModelClipRetained) this .retained).initInsertScope(scope,
322: index);
323: }
324:
325: /**
326: * Removes the node at the specified index from this ModelClip node's
327: * list of scopes. If this operation causes the list of scopes to
328: * become empty, then this ModelClip will have universe scope: all nodes
329: * within the region of influence will be affected by this ModelClip node.
330: * @param index the index of the Group node to be removed.
331: * @exception CapabilityNotSetException if appropriate capability is
332: * not set and this object is part of live or compiled scene graph
333: * @exception RestrictedAccessException if the group node at the
334: * specified index is part of a compiled scene graph
335: */
336: public void removeScope(int index) {
337: if (isLiveOrCompiled())
338: if (!this .getCapability(ALLOW_SCOPE_WRITE))
339: throw new CapabilityNotSetException(J3dI18N
340: .getString("ModelClip10"));
341:
342: if (isLive())
343: ((ModelClipRetained) this .retained).removeScope(index);
344: else
345: ((ModelClipRetained) this .retained).initRemoveScope(index);
346: }
347:
348: /**
349: * Returns an enumeration of this ModelClip node's list of scopes.
350: * @return an Enumeration object containing all nodes in this ModelClip node's
351: * list of scopes.
352: * @exception CapabilityNotSetException if appropriate capability is
353: * not set and this object is part of live or compiled scene graph
354: */
355: public Enumeration getAllScopes() {
356: if (isLiveOrCompiled())
357: if (!this .getCapability(ALLOW_SCOPE_READ))
358: throw new CapabilityNotSetException(J3dI18N
359: .getString("ModelClip11"));
360:
361: return (Enumeration) ((ModelClipRetained) this .retained)
362: .getAllScopes();
363: }
364:
365: /**
366: * Appends the specified Group node to this ModelClip node's list of scopes.
367: * By default, ModelClip nodes are scoped only by their influencing
368: * bounds. This allows them to be further scoped by a list of
369: * nodes in the hierarchy.
370: * @param scope the Group node to be appended.
371: * @exception CapabilityNotSetException if appropriate capability is
372: * not set and this object is part of live or compiled scene graph
373: * @exception RestrictedAccessException if the specified group node
374: * is part of a compiled scene graph
375: */
376: public void addScope(Group scope) {
377: if (isLiveOrCompiled())
378: if (!this .getCapability(ALLOW_SCOPE_WRITE))
379: throw new CapabilityNotSetException(J3dI18N
380: .getString("ModelClip12"));
381:
382: if (isLive())
383: ((ModelClipRetained) this .retained).addScope(scope);
384: else
385: ((ModelClipRetained) this .retained).initAddScope(scope);
386: }
387:
388: /**
389: * Returns the number of nodes in this ModelClip node's list of scopes.
390: * If this number is 0, then the list of scopes is empty and this
391: * ModelClip node has universe scope: all nodes within the region of
392: * influence are affected by this ModelClip node.
393: * @return the number of nodes in this ModelClip node's list of scopes.
394: * @exception CapabilityNotSetException if appropriate capability is
395: * not set and this object is part of live or compiled scene graph
396: */
397: public int numScopes() {
398: if (isLiveOrCompiled())
399: if (!this .getCapability(ALLOW_SCOPE_READ))
400: throw new CapabilityNotSetException(J3dI18N
401: .getString("ModelClip11"));
402:
403: return ((ModelClipRetained) this .retained).numScopes();
404: }
405:
406: /**
407: * Retrieves the index of the specified Group node in this
408: * ModelClip node's list of scopes.
409: *
410: * @param scope the Group node to be looked up.
411: * @return the index of the specified Group node;
412: * returns -1 if the object is not in the list.
413: * @exception CapabilityNotSetException if appropriate capability is
414: * not set and this object is part of live or compiled scene graph
415: *
416: * @since Java 3D 1.3
417: */
418: public int indexOfScope(Group scope) {
419: if (isLiveOrCompiled())
420: if (!this .getCapability(ALLOW_SCOPE_READ))
421: throw new CapabilityNotSetException(J3dI18N
422: .getString("ModelClip8"));
423: return ((ModelClipRetained) this .retained).indexOfScope(scope);
424: }
425:
426: /**
427: * Removes the specified Group node from this ModelClip
428: * node's list of scopes. If the specified object is not in the
429: * list, the list is not modified. If this operation causes the
430: * list of scopes to become empty, then this ModelClip
431: * will have universe scope: all nodes within the region of
432: * influence will be affected by this ModelClip node.
433: *
434: * @param scope the Group node to be removed.
435: * @exception CapabilityNotSetException if appropriate capability is
436: * not set and this object is part of live or compiled scene graph
437: * @exception RestrictedAccessException if the specified group node
438: * is part of a compiled scene graph
439: *
440: * @since Java 3D 1.3
441: */
442: public void removeScope(Group scope) {
443: if (isLiveOrCompiled())
444: if (!this .getCapability(ALLOW_SCOPE_WRITE))
445: throw new CapabilityNotSetException(J3dI18N
446: .getString("ModelClip10"));
447: if (isLive())
448: ((ModelClipRetained) this .retained).removeScope(scope);
449: else
450: ((ModelClipRetained) this .retained).initRemoveScope(scope);
451: }
452:
453: /**
454: * Removes all Group nodes from this ModelClip node's
455: * list of scopes. The ModelClip node will then have
456: * universe scope: all nodes within the region of influence will
457: * be affected by this ModelClip node.
458: *
459: * @exception CapabilityNotSetException if appropriate capability is
460: * not set and this object is part of live or compiled scene graph
461: * @exception RestrictedAccessException if any group node in this
462: * node's list of scopes is part of a compiled scene graph
463: *
464: * @since Java 3D 1.3
465: */
466: public void removeAllScopes() {
467: if (isLiveOrCompiled())
468: if (!this .getCapability(ALLOW_SCOPE_WRITE))
469: throw new CapabilityNotSetException(J3dI18N
470: .getString("ModelClip10"));
471: if (isLive())
472: ((ModelClipRetained) this .retained).removeAllScopes();
473: else
474: ((ModelClipRetained) this .retained).initRemoveAllScopes();
475: }
476:
477: /**
478: * Sets the clipping planes of this ModelClip node to the
479: * specified planes.
480: * The individual planes are copied into this node.
481: * @param planes an array of 6 model clipping planes
482: */
483: public void setPlanes(Vector4d[] planes) {
484: if (isLiveOrCompiled())
485: if (!this .getCapability(ALLOW_PLANE_WRITE))
486: throw new CapabilityNotSetException(J3dI18N
487: .getString("ModelClip2"));
488:
489: if (isLive())
490: ((ModelClipRetained) this .retained).setPlanes(planes);
491: else
492: ((ModelClipRetained) this .retained).initPlanes(planes);
493: }
494:
495: /**
496: * Retrieves the clipping planes from this ModelClip node.
497: * The individual planes are copied into the specified planes, which
498: * must be allocated by the caller. The array must be large
499: * enough to hold all of the vectors.
500: * @param planes an array of 6 vectors that will receive the model
501: * clipping planes from this node
502: */
503: public void getPlanes(Vector4d[] planes) {
504: if (isLiveOrCompiled())
505: if (!this .getCapability(ALLOW_PLANE_READ))
506: throw new CapabilityNotSetException(J3dI18N
507: .getString("ModelClip3"));
508:
509: ((ModelClipRetained) this .retained).getPlanes(planes);
510: }
511:
512: /**
513: * Sets the specified clipping plane of this ModelClip node.
514: * The specified plane is copied into this node.
515: * @param planeNum specifies which model clipping plane (0-5) is replaced
516: * @param plane new model clipping plane
517: */
518: public void setPlane(int planeNum, Vector4d plane) {
519: if (isLiveOrCompiled())
520: if (!this .getCapability(ALLOW_PLANE_WRITE))
521: throw new CapabilityNotSetException(J3dI18N
522: .getString("ModelClip2"));
523:
524: if (isLive())
525: ((ModelClipRetained) this .retained).setPlane(planeNum,
526: plane);
527: else
528: ((ModelClipRetained) this .retained).initPlane(planeNum,
529: plane);
530:
531: }
532:
533: /**
534: * Retrieves the specified clipping plane from this ModelClip node.
535: * The plane is copied into the specified plane, which
536: * must be allocated by the caller.
537: * @param planeNum specifies which model clipping plane (0-5) is retrieved
538: * @param plane a vector that will receive the specified model
539: * clipping plane from this node
540: */
541: public void getPlane(int planeNum, Vector4d plane) {
542: if (isLiveOrCompiled())
543: if (!this .getCapability(ALLOW_PLANE_READ))
544: throw new CapabilityNotSetException(J3dI18N
545: .getString("ModelClip3"));
546:
547: ((ModelClipRetained) this .retained).getPlane(planeNum, plane);
548: }
549:
550: /**
551: * Sets the per-plane enable flags of this ModelClip node to the
552: * specified values.
553: * @param enables an array of 6 enable flags
554: */
555: public void setEnables(boolean[] enables) {
556: if (isLiveOrCompiled())
557: if (!this .getCapability(ALLOW_ENABLE_WRITE))
558: throw new CapabilityNotSetException(J3dI18N
559: .getString("ModelClip4"));
560:
561: if (isLive())
562: ((ModelClipRetained) this .retained).setEnables(enables);
563: else
564: ((ModelClipRetained) this .retained).initEnables(enables);
565: }
566:
567: /**
568: * Retrieves the per-plane enable flags from this ModelClip node.
569: * The enable flags are copied into the specified array.
570: * The array must be large enough to hold all of the enables.
571: * @param enables an array of 6 booleans that will receive the
572: * enable flags from this node
573: */
574: public void getEnables(boolean[] enables) {
575: if (isLiveOrCompiled())
576: if (!this .getCapability(ALLOW_ENABLE_READ))
577: throw new CapabilityNotSetException(J3dI18N
578: .getString("ModelClip5"));
579:
580: ((ModelClipRetained) this .retained).getEnables(enables);
581: }
582:
583: /**
584: * Sets the specified enable flag of this ModelClip node.
585: * @param planeNum specifies which enable flag (0-5) is set
586: * @param enable new enable flag
587: */
588: public void setEnable(int planeNum, boolean enable) {
589: if (isLiveOrCompiled())
590: if (!this .getCapability(ALLOW_ENABLE_WRITE))
591: throw new CapabilityNotSetException(J3dI18N
592: .getString("ModelClip4"));
593:
594: if (isLive())
595: ((ModelClipRetained) this .retained).setEnable(planeNum,
596: enable);
597: else
598: ((ModelClipRetained) this .retained).initEnable(planeNum,
599: enable);
600: }
601:
602: /**
603: * Retrieves the specified enable flag from this ModelClip node.
604: * @param planeNum specifies which enable flag (0-5) is retrieved
605: * @return the specified enable flag
606: */
607: public boolean getEnable(int planeNum) {
608: if (isLiveOrCompiled())
609: if (!this .getCapability(ALLOW_ENABLE_READ))
610: throw new CapabilityNotSetException(J3dI18N
611: .getString("ModelClip5"));
612:
613: return ((ModelClipRetained) this .retained).getEnable(planeNum);
614: }
615:
616: /**
617: * Creates the retained mode ModelClipRetained object that
618: * this ModelClip node will point to.
619: */
620: void createRetained() {
621: this .retained = new ModelClipRetained();
622: this .retained.setSource(this );
623: }
624:
625: /**
626: * Used to create a new instance of the node. This routine is called
627: * by <code>cloneTree</code> to duplicate the current node.
628: * @param forceDuplicate when set to <code>true</code>, causes the
629: * <code>duplicateOnCloneTree</code> flag to be ignored. When
630: * <code>false</code>, the value of each node's
631: * <code>duplicateOnCloneTree</code> variable determines whether
632: * NodeComponent data is duplicated or copied.
633: *
634: * @see Node#cloneTree
635: * @see Node#cloneNode
636: * @see Node#duplicateNode
637: * @see NodeComponent#setDuplicateOnCloneTree
638: */
639: public Node cloneNode(boolean forceDuplicate) {
640: ModelClip c = new ModelClip();
641: c.duplicateNode(this , forceDuplicate);
642: return c;
643: }
644:
645: /**
646: * Callback used to allow a node to check if any scene graph objects
647: * referenced
648: * by that node have been duplicated via a call to <code>cloneTree</code>.
649: * This method is called by <code>cloneTree</code> after all nodes in
650: * the sub-graph have been duplicated. The cloned Leaf node's method
651: * will be called and the Leaf node can then look up any object references
652: * by using the <code>getNewObjectReference</code> method found in the
653: * <code>NodeReferenceTable</code> object. If a match is found, a
654: * reference to the corresponding object in the newly cloned sub-graph
655: * is returned. If no corresponding reference is found, either a
656: * DanglingReferenceException is thrown or a reference to the original
657: * object is returned depending on the value of the
658: * <code>allowDanglingReferences</code> parameter passed in the
659: * <code>cloneTree</code> call.
660: * <p>
661: * NOTE: Applications should <i>not</i> call this method directly.
662: * It should only be called by the cloneTree method.
663: *
664: * @param referenceTable a NodeReferenceTableObject that contains the
665: * <code>getNewObjectReference</code> method needed to search for
666: * new object instances.
667: * @see NodeReferenceTable
668: * @see Node#cloneTree
669: * @see DanglingReferenceException
670: */
671: public void updateNodeReferences(NodeReferenceTable referenceTable) {
672: ModelClipRetained rt = (ModelClipRetained) retained;
673: BoundingLeaf bl = rt.getInfluencingBoundingLeaf();
674:
675: // check for influencingBoundingLeaf
676: if (bl != null) {
677: Object o = referenceTable.getNewObjectReference(bl);
678: rt.initInfluencingBoundingLeaf((BoundingLeaf) o);
679: }
680:
681: int num = rt.numScopes();
682: for (int i = 0; i < num; i++) {
683: rt.initScope((Group) referenceTable
684: .getNewObjectReference(rt.getScope(i)), i);
685: }
686: }
687:
688: /**
689: * Copies all Clip information from
690: * <code>originalNode</code> into
691: * the current node. This method is called from the
692: * <code>cloneNode</code> method which is, in turn, called by the
693: * <code>cloneTree</code> method.<P>
694: *
695: * @param originalNode the original node to duplicate.
696: * @param forceDuplicate when set to <code>true</code>, causes the
697: * <code>duplicateOnCloneTree</code> flag to be ignored. When
698: * <code>false</code>, the value of each node's
699: * <code>duplicateOnCloneTree</code> variable determines whether
700: * NodeComponent data is duplicated or copied.
701: *
702: * @exception RestrictedAccessException if this object is part of a live
703: * or compiled scenegraph.
704: *
705: * @see Node#duplicateNode
706: * @see Node#cloneTree
707: * @see NodeComponent#setDuplicateOnCloneTree
708: */
709: void duplicateAttributes(Node originalNode, boolean forceDuplicate) {
710: super .duplicateAttributes(originalNode, forceDuplicate);
711:
712: ModelClipRetained attr = (ModelClipRetained) originalNode.retained;
713: ModelClipRetained rt = (ModelClipRetained) retained;
714:
715: Vector4d plane = new Vector4d();
716:
717: for (int i = 5; i >= 0; i--) {
718: attr.getPlane(i, plane);
719: rt.initPlane(i, plane);
720: rt.initEnable(i, attr.getEnable(i));
721: }
722: rt.initInfluencingBounds(attr.getInfluencingBounds());
723:
724: Enumeration elm = attr.getAllScopes();
725: while (elm.hasMoreElements()) {
726: // this reference will set correctly in updateNodeReferences() callback
727: rt.initAddScope((Group) elm.nextElement());
728: }
729:
730: // correct value will set in updateNodeReferences
731: rt.initInfluencingBoundingLeaf(attr
732: .getInfluencingBoundingLeaf());
733: }
734: }
|