001: /*
002: * $RCSfile: SharedGroupRetained.java,v $
003: *
004: * Copyright 1996-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.10 $
028: * $Date: 2008/02/28 20:17:30 $
029: * $State: Exp $
030: */
031:
032: package javax.media.j3d;
033:
034: import java.util.*;
035:
036: /**
037: * The SharedGroup node provides the ability to share a scene graph from
038: * multiple other scene graphs through the use of a Link node.
039: */
040:
041: class SharedGroupRetained extends GroupRetained implements
042: TargetsInterface {
043:
044: /*
045: static final int ILLEGAL_LEAF_MASK =
046: 1 << NodeRetained.BACKGROUND |
047: 1 << NodeRetained.BEHAVIOR |
048: 1 << NodeRetained.CLIP |
049: 1 << NodeRetained.LINEARFOG |
050: 1 << NodeRetained.EXPONENTIALFOG |
051: 1 << NodeRetained.SOUNDSCAPE |
052: 1 << NodeRetained.VIEWPLATFORM |
053: 1 << NodeRetained.BOUNDINGLEAF;
054: */
055:
056: // The current list of child transform group nodes or link nodes
057: // under a transform group
058: ArrayList childTransformLinks = new ArrayList(1);
059:
060: // key which identifies a unique path from a
061: // locale to this transform group
062: HashKey currentKey = new HashKey();
063:
064: // key which identifies a unique path from a locale to this switch link
065: HashKey switchKey = new HashKey();
066:
067: /**
068: * The Shared Group Node's parent vector.
069: */
070: Vector parents = new Vector(1);
071:
072: // J3d copy.
073: CachedTargets[] j3dCTs = null;
074:
075: // User copy.
076: CachedTargets[] cachedTargets = null;
077:
078: // A bitmask of the types in targets for transform targets
079: int localTargetThreads = 0;
080: // combined localTargetThreads and decendants' localTargetThreads
081: int targetThreads = 0;
082:
083: ArrayList switchStates = null;
084:
085: SharedGroupRetained() {
086: this .nodeType = NodeRetained.SHAREDGROUP;
087: }
088:
089: // SharedGroup specific data at SetLive.
090: void setAuxData(SetLiveState s, int index, int hkIndex) {
091: int i, size;
092:
093: // Group's setAuxData()
094: super .setAuxData(s, index, hkIndex);
095:
096: branchGroupPaths.add(hkIndex, s.branchGroupPaths.get(index));
097:
098: if (orderedPaths == null) {
099: orderedPaths = new ArrayList(1);
100: }
101: orderedPaths.add(hkIndex, s.orderedPaths.get(index));
102:
103: if (switchStates == null) {
104: switchStates = new ArrayList(1);
105: }
106: switchStates.add(hkIndex, s.switchStates.get(index));
107:
108: if (viewLists == null) {
109: viewLists = new ArrayList(1);
110: }
111: // If there are some ViewSpecificGroups in the path above this SharedGroup
112: // System.err.println("====> hkIndex = "+hkIndex+" s.viewLists = "+s.viewLists);
113: if (s.viewLists != null) {
114: viewLists.add(hkIndex, s.viewLists.get(index));
115: } else {
116: viewLists.add(hkIndex, null);
117: }
118:
119: if (lights == null) {
120: lights = new ArrayList(1);
121: }
122: if (s.lights != null) {
123: lights.add(hkIndex, s.lights.get(index));
124: } else {
125: lights.add(hkIndex, null);
126: }
127:
128: if (fogs == null) {
129: fogs = new ArrayList(1);
130: }
131: if (s.fogs != null) {
132: fogs.add(hkIndex, s.fogs.get(index));
133: } else {
134: fogs.add(hkIndex, null);
135: }
136:
137: if (modelClips == null) {
138: modelClips = new ArrayList(1);
139: }
140: if (s.modelClips != null) {
141: modelClips.add(hkIndex, s.modelClips.get(index));
142: } else {
143: modelClips.add(hkIndex, null);
144: }
145:
146: if (altAppearances == null) {
147: altAppearances = new ArrayList(1);
148: }
149: if (s.altAppearances != null) {
150: altAppearances.add(hkIndex, s.altAppearances.get(index));
151: } else {
152: altAppearances.add(hkIndex, null);
153: }
154: }
155:
156: void setNodeData(SetLiveState s) {
157:
158: // For inSharedGroup case.
159: int i, j, len;
160:
161: if (localToVworld == null) {
162: localToVworld = new Transform3D[s.keys.length][];
163: localToVworldIndex = new int[s.keys.length][];
164: localToVworldKeys = new HashKey[s.keys.length];
165: cachedTargets = new CachedTargets[s.keys.length];
166: len = 0;
167: } else {
168:
169: int newLen = localToVworld.length + s.keys.length;
170:
171: Transform3D newTList[][] = new Transform3D[newLen][];
172: HashKey newHList[] = new HashKey[newLen];
173: int newIndexList[][] = new int[newLen][];
174: CachedTargets newTargets[] = new CachedTargets[newLen];
175:
176: len = localToVworld.length;
177:
178: // Copy the existing data into the newly created data objects.
179: System.arraycopy(localToVworld, 0, newTList, 0,
180: localToVworld.length);
181: System.arraycopy(localToVworldIndex, 0, newIndexList, 0,
182: localToVworldIndex.length);
183: System.arraycopy(localToVworldKeys, 0, newHList, 0,
184: localToVworldKeys.length);
185: System.arraycopy(cachedTargets, 0, newTargets, 0,
186: cachedTargets.length);
187:
188: localToVworld = newTList;
189: localToVworldIndex = newIndexList;
190: localToVworldKeys = newHList;
191: cachedTargets = newTargets;
192: }
193:
194: int[] hkIndex = new int[1];
195: int hkIndexPlus1, blkSize;
196:
197: s.hashkeyIndex = new int[s.keys.length];
198:
199: // This should appear before super.setNodeData() if it exists
200: s.parentBranchGroupPaths = branchGroupPaths;
201:
202: for (i = len, j = 0; i < localToVworld.length; i++, j++) {
203:
204: if (s.keys[j].equals(localToVworldKeys, hkIndex, 0, i)) {
205: MasterControl.getCoreLogger().severe(
206: "Found matching hashKey in setNodeData.");
207: }
208: s.hashkeyIndex[j] = hkIndex[0];
209:
210: if (hkIndex[0] == i) { // Append to last.
211: localToVworldKeys[i] = s.keys[j];
212: localToVworld[i] = s.currentTransforms[j];
213: localToVworldIndex[i] = s.currentTransformsIndex[j];
214: } else { // Insert in between array elements.
215: hkIndexPlus1 = hkIndex[0] + 1;
216: blkSize = i - hkIndex[0];
217:
218: // Shift the later portion of array elements by one position.
219: // This is the make room for the new data entry.
220: System.arraycopy(localToVworldKeys, hkIndex[0],
221: localToVworldKeys, hkIndexPlus1, blkSize);
222: System.arraycopy(localToVworld, hkIndex[0],
223: localToVworld, hkIndexPlus1, blkSize);
224: System.arraycopy(localToVworldIndex, hkIndex[0],
225: localToVworldIndex, hkIndexPlus1, blkSize);
226: System.arraycopy(cachedTargets, hkIndex[0],
227: cachedTargets, hkIndexPlus1, blkSize);
228:
229: localToVworldKeys[hkIndex[0]] = s.keys[j];
230: localToVworld[hkIndex[0]] = s.currentTransforms[j];
231: localToVworldIndex[hkIndex[0]] = s.currentTransformsIndex[j];
232: }
233:
234: // System.err.println("SG: j = "+j+" hkIndex[0] = "+hkIndex[0]+" s.keys[j] = "+s.keys[j]);
235: // For now (1.2.1beta2) only. We cleanup setLive, and clearLive in
236: // next release.
237: setAuxData(s, j, hkIndex[0]);
238: }
239:
240: // The SetLiveState need the reflect the new state of this SharedGroup.
241: // The SetLiveState will get reset back in SetLive, after all children of this
242: // node have been set live.
243: s.localToVworld = localToVworld;
244: s.localToVworldIndex = localToVworldIndex;
245: s.localToVworldKeys = localToVworldKeys;
246: s.orderedPaths = orderedPaths;
247: s.switchStates = switchStates;
248:
249: // Note that s.childSwitchLinks is updated in super.setLive
250: s.childTransformLinks = childTransformLinks;
251: s.parentTransformLink = this ;
252: s.parentSwitchLink = this ;
253: s.viewLists = viewLists;
254: s.lights = lights;
255: s.fogs = fogs;
256: s.altAppearances = altAppearances;
257: s.modelClips = modelClips;
258: }
259:
260: void setLive(SetLiveState s) {
261:
262: int i, j;
263: Targets[] newTargets = null;
264:
265: // save setLiveState
266: Transform3D savedLocalToVworld[][] = s.localToVworld;
267: int savedLocalToVworldIndex[][] = s.localToVworldIndex;
268: HashKey savedLocalToVworldKeys[] = s.localToVworldKeys;
269: ArrayList savedOrderedPaths = s.orderedPaths;
270: ArrayList savedViewList = s.viewLists;
271: ArrayList savedLights = s.lights;
272: ArrayList savedFogs = s.fogs;
273: ArrayList savedMclips = s.modelClips;
274: ArrayList savedAltApps = s.altAppearances;
275:
276: SharedGroupRetained savedLastSharedGroup = s.lastSharedGroup;
277: Targets[] savedSwitchTargets = s.switchTargets;
278: ArrayList savedSwitchStates = s.switchStates;
279: ArrayList savedChildSwitchLinks = s.childSwitchLinks;
280: GroupRetained savedParentSwitchLink = s.parentSwitchLink;
281: ArrayList savedChildTransformLinks = s.childTransformLinks;
282: GroupRetained savedParentTransformLink = s.parentTransformLink;
283: int[] savedHashkeyIndex = s.hashkeyIndex;
284:
285: // update setLiveState for this node
286: // Note that s.containsNodesList is updated in super.setLive
287: s.lastSharedGroup = this ;
288:
289: Targets[] savedTransformTargets = s.transformTargets;
290:
291: int numPaths = s.keys.length;
292: newTargets = new Targets[numPaths];
293: for (i = 0; i < numPaths; i++) {
294: if (s.transformLevels[i] >= 0) {
295: newTargets[i] = new Targets();
296: } else {
297: newTargets[i] = null;
298: }
299: }
300: s.transformTargets = newTargets;
301:
302: super .setLive(s);
303:
304: int hkIndex;
305: for (i = 0; i < numPaths; i++) {
306: if (s.transformTargets[i] != null) {
307: hkIndex = s.hashkeyIndex[i];
308: cachedTargets[hkIndex] = s.transformTargets[i]
309: .snapShotInit();
310: }
311: }
312: // Assign data in cachedTargets to j3dCTs.
313: j3dCTs = new CachedTargets[cachedTargets.length];
314: copyCachedTargets(TargetsInterface.TRANSFORM_TARGETS, j3dCTs);
315:
316: computeTargetThreads(TargetsInterface.TRANSFORM_TARGETS,
317: cachedTargets);
318:
319: // restore setLiveState
320: s.localToVworld = savedLocalToVworld;
321: s.localToVworldIndex = savedLocalToVworldIndex;
322: s.localToVworldKeys = savedLocalToVworldKeys;
323: s.orderedPaths = savedOrderedPaths;
324: s.viewLists = savedViewList;
325:
326: s.lights = savedLights;
327: s.fogs = savedFogs;
328: s.modelClips = savedMclips;
329: s.altAppearances = savedAltApps;
330:
331: s.lastSharedGroup = savedLastSharedGroup;
332: s.switchTargets = savedSwitchTargets;
333: s.switchStates = savedSwitchStates;
334:
335: s.childSwitchLinks = savedChildSwitchLinks;
336: s.parentSwitchLink = savedParentSwitchLink;
337: s.childTransformLinks = savedChildTransformLinks;
338: s.parentTransformLink = savedParentTransformLink;
339:
340: s.transformTargets = savedTransformTargets;
341: s.hashkeyIndex = savedHashkeyIndex;
342: /*
343: // XXXX : port this
344: for (int i=0; i < children.size(); i++) {
345: if ((childContains[i][0] & ILLEGAL_LEAF_MASK) != 0) {
346: throw new IllegalSharingException(J3dI18N.getString("SharedGroupRetained0")); }
347: }
348: */
349: }
350:
351: /**
352: * remove the localToVworld transform for a node.
353: */
354: void removeNodeData(SetLiveState s) {
355:
356: int numChildren = children.size();
357: ArrayList switchTargets;
358: int i, j;
359:
360: if (refCount <= 0) {
361: localToVworld = null;
362: localToVworldIndex = null;
363: localToVworldKeys = null;
364: // restore to default and avoid calling clear()
365: // that may clear parent reference branchGroupPaths
366: // Note that this function did not invoke super.removeNodeData()
367: branchGroupPaths = new ArrayList(1);
368: orderedPaths = null;
369: switchStates = null;
370: cachedTargets = null;
371: targetThreads = 0;
372: lights.clear();
373: fogs.clear();
374: modelClips.clear();
375: altAppearances.clear();
376: } else {
377: int index, len;
378:
379: // Remove the localToVworld key
380: int newLen = localToVworld.length - s.keys.length;
381:
382: Transform3D[][] newTList = new Transform3D[newLen][];
383: HashKey[] newHList = new HashKey[newLen];
384: Transform3D newChildTList[][] = null;
385: int[][] newIndexList = new int[newLen][];
386: CachedTargets[] newTargets = new CachedTargets[newLen];
387:
388: int[] tempIndex = new int[s.keys.length];
389: int curStart = 0, newStart = 0;
390: boolean found = false;
391:
392: for (i = 0; i < s.keys.length; i++) {
393: index = s.keys[i].equals(localToVworldKeys, 0,
394: localToVworldKeys.length);
395:
396: tempIndex[i] = index;
397:
398: if (index >= 0) {
399: found = true;
400: if (index == curStart) {
401: curStart++;
402: } else {
403: len = index - curStart;
404: System.arraycopy(localToVworld, curStart,
405: newTList, newStart, len);
406: System.arraycopy(localToVworldIndex, curStart,
407: newIndexList, newStart, len);
408: System.arraycopy(localToVworldKeys, curStart,
409: newHList, newStart, len);
410: System.arraycopy(cachedTargets, curStart,
411: newTargets, newStart, len);
412:
413: curStart = index + 1;
414: newStart = newStart + len;
415: }
416: } else {
417: found = false;
418: MasterControl
419: .getCoreLogger()
420: .severe(
421: "Can't Find matching hashKey in SG.removeNodeData.");
422: }
423: }
424:
425: if ((found == true) && (curStart < localToVworld.length)) {
426: len = localToVworld.length - curStart;
427: System.arraycopy(localToVworld, curStart, newTList,
428: newStart, len);
429: System.arraycopy(localToVworldIndex, curStart,
430: newIndexList, newStart, len);
431: System.arraycopy(localToVworldKeys, curStart, newHList,
432: newStart, len);
433: System.arraycopy(cachedTargets, curStart, newTargets,
434: newStart, len);
435: }
436:
437: // Must be in reverse, to preserve right indexing.
438: for (i = tempIndex.length - 1; i >= 0; i--) {
439: if (tempIndex[i] >= 0) {
440: branchGroupPaths.remove(tempIndex[i]);
441: orderedPaths.remove(tempIndex[i]);
442: switchStates.remove(tempIndex[i]);
443: lights.remove(tempIndex[i]);
444: fogs.remove(tempIndex[i]);
445: modelClips.remove(tempIndex[i]);
446: altAppearances.remove(tempIndex[i]);
447: }
448: }
449:
450: localToVworld = newTList;
451: localToVworldIndex = newIndexList;
452: localToVworldKeys = newHList;
453: cachedTargets = newTargets;
454: }
455: s.localToVworld = localToVworld;
456: s.localToVworldIndex = localToVworldIndex;
457: s.localToVworldKeys = localToVworldKeys;
458: s.orderedPaths = orderedPaths;
459: s.switchStates = switchStates;
460: s.viewLists = viewLists;
461: s.lights = lights;
462: s.fogs = fogs;
463: s.modelClips = modelClips;
464: s.altAppearances = altAppearances;
465: }
466:
467: void clearLive(SetLiveState s) {
468:
469: int i, j, k, index;
470:
471: Transform3D savedLocalToVworld[][] = s.localToVworld;
472: int savedLocalToVworldIndex[][] = s.localToVworldIndex;
473: HashKey savedLocalToVworldKeys[] = s.localToVworldKeys;
474: ArrayList savedOrderedPaths = s.orderedPaths;
475: ArrayList savedViewLists = s.viewLists;
476:
477: ArrayList savedLights = s.lights;
478: ArrayList savedFogs = s.fogs;
479: ArrayList savedMclips = s.modelClips;
480: ArrayList savedAltApps = s.altAppearances;
481:
482: Targets[] savedSwitchTargets = s.switchTargets;
483: Targets[] savedTransformTargets = s.transformTargets;
484: // no need to gather targets from sg in clear live
485: s.transformTargets = null;
486: s.switchTargets = null;
487:
488: // XXXX: This is a hack since removeNodeData is called before
489: // children are clearLives
490: int[] tempIndex = null;
491: // Don't keep the indices if everything will be cleared
492: if (s.keys.length != localToVworld.length) {
493: tempIndex = new int[s.keys.length];
494: for (i = s.keys.length - 1; i >= 0; i--) {
495: tempIndex[i] = s.keys[i].equals(localToVworldKeys, 0,
496: localToVworldKeys.length);
497: }
498: }
499:
500: super .clearLive(s);
501: // Do this after children clearlive since part of the viewLists may get cleared
502: // during removeNodeData
503: if (refCount <= 0) {
504: viewLists.clear();
505: } else {
506: // Must be in reverse, to preserve right indexing.
507: for (i = tempIndex.length - 1; i >= 0; i--) {
508: if (tempIndex[i] >= 0) {
509: viewLists.remove(tempIndex[i]);
510: }
511: }
512: }
513:
514: // restore setLiveState from it's local variables.
515: // removeNodeData has altered these variables.
516: s.localToVworld = savedLocalToVworld;
517: s.localToVworldIndex = savedLocalToVworldIndex;
518: s.localToVworldKeys = savedLocalToVworldKeys;
519: s.orderedPaths = savedOrderedPaths;
520: s.viewLists = savedViewLists;
521: s.lights = savedLights;
522: s.fogs = savedFogs;
523: s.modelClips = savedMclips;
524: s.altAppearances = savedAltApps;
525: s.transformTargets = savedTransformTargets;
526: s.switchTargets = savedSwitchTargets;
527: }
528:
529: void updateChildLocalToVworld(HashKey key, int index,
530: ArrayList dirtyTransformGroups, ArrayList keySet,
531: UpdateTargets targets, ArrayList blUsers) {
532:
533: LinkRetained ln;
534: TransformGroupRetained tg;
535: int i, j;
536: Object obj;
537:
538: CachedTargets ct = j3dCTs[index];
539: if (ct != null) {
540: targets.addCachedTargets(ct);
541: if (ct.targetArr[Targets.BLN_TARGETS] != null) {
542: gatherBlUsers(blUsers,
543: ct.targetArr[Targets.BLN_TARGETS]);
544: }
545: }
546:
547: synchronized (childTransformLinks) {
548: for (i = 0; i < childTransformLinks.size(); i++) {
549: obj = childTransformLinks.get(i);
550:
551: if (obj instanceof TransformGroupRetained) {
552: tg = (TransformGroupRetained) obj;
553: tg.updateChildLocalToVworld(
554: tg.localToVworldKeys[index], index,
555: dirtyTransformGroups, keySet, targets,
556: blUsers);
557:
558: } else { // LinkRetained
559: ln = (LinkRetained) obj;
560: currentKey.set(key);
561: currentKey.append(LinkRetained.plus).append(
562: ln.nodeId);
563: if (ln.sharedGroup.localToVworldKeys != null) {
564: j = currentKey
565: .equals(
566: ln.sharedGroup.localToVworldKeys,
567: 0,
568: ln.sharedGroup.localToVworldKeys.length);
569: if (j < 0) {
570: System.err
571: .println("SharedGroupRetained : Can't find hashKey");
572: }
573:
574: if (j < ln.sharedGroup.localToVworldKeys.length) {
575: ln.sharedGroup
576: .updateChildLocalToVworld(
577: ln.sharedGroup.localToVworldKeys[j],
578: j, dirtyTransformGroups,
579: keySet, targets, blUsers);
580: }
581: }
582: }
583: }
584: }
585: }
586:
587: void traverseSwitchChild(int child, HashKey key, int index,
588: SwitchRetained switchRoot, boolean init, boolean swChanged,
589: boolean switchOn, int switchLevel, ArrayList updateList) {
590:
591: SwitchRetained sw;
592: LinkRetained ln;
593: Object obj;
594: ArrayList childSwitchLinks;
595: int i, j, k;
596:
597: childSwitchLinks = (ArrayList) childrenSwitchLinks.get(child);
598: for (i = 0; i < childSwitchLinks.size(); i++) {
599: obj = childSwitchLinks.get(i);
600:
601: if (obj instanceof SwitchRetained) {
602: sw = (SwitchRetained) obj;
603: for (j = 0; j < sw.children.size(); j++) {
604: sw.traverseSwitchChild(j, key, index, switchRoot,
605: init, swChanged, switchOn, switchLevel,
606: updateList);
607: }
608: } else { // LinkRetained
609: ln = (LinkRetained) obj;
610: switchKey.set(key);
611: switchKey.append(LinkRetained.plus).append(ln.nodeId);
612:
613: if (ln.sharedGroup.localToVworldKeys != null) {
614:
615: j = switchKey.equals(
616: ln.sharedGroup.localToVworldKeys, 0,
617: ln.sharedGroup.localToVworldKeys.length);
618: if (j < 0) {
619: System.err
620: .println("SharedGroupRetained : Can't find hashKey");
621: }
622:
623: if (j < ln.sharedGroup.localToVworldKeys.length) {
624: for (k = 0; k < ln.sharedGroup.children.size(); k++) {
625: ln.sharedGroup
626: .traverseSwitchChild(
627: k,
628: ln.sharedGroup.localToVworldKeys[j],
629: j, switchRoot, init,
630: swChanged, switchOn,
631: switchLevel, updateList);
632: }
633: }
634: }
635: }
636: }
637: }
638:
639: void traverseSwitchParent() {
640: int i;
641: NodeRetained ln;
642:
643: for (i = 0; i < parents.size(); i++) {
644: ln = (NodeRetained) parents.elementAt(i);
645: if (ln.parentSwitchLink != null) {
646: if (parentSwitchLink instanceof SwitchRetained) {
647: ((SwitchRetained) parentSwitchLink)
648: .traverseSwitchParent();
649: } else if (parentSwitchLink instanceof SharedGroupRetained) {
650: ((SharedGroupRetained) parentSwitchLink)
651: .traverseSwitchParent();
652: }
653: }
654: }
655: }
656:
657: // Top level compile call, same as BranchGroup.compile()
658: void compile() {
659:
660: if (source.isCompiled() || VirtualUniverse.mc.disableCompile)
661: return;
662:
663: if (J3dDebug.devPhase && J3dDebug.debug) {
664: J3dDebug.doDebug(J3dDebug.compileState, J3dDebug.LEVEL_3,
665: "SharedGroupRetained.compile()....\n");
666: }
667:
668: CompileState compState = new CompileState();
669:
670: isRoot = true;
671:
672: compile(compState);
673: merge(compState);
674:
675: if (J3dDebug.devPhase && J3dDebug.debug) {
676: if (J3dDebug.doDebug(J3dDebug.compileState,
677: J3dDebug.LEVEL_3)) {
678: compState.printStats();
679: }
680: if (J3dDebug.doDebug(J3dDebug.compileState,
681: J3dDebug.LEVEL_5)) {
682: this .traverse(false, 1);
683: System.err.println();
684: }
685: }
686:
687: }
688:
689: /**
690: * Returns the Link nodes that refer to this SharedGroup node
691: * @return An array of Link nodes
692: */
693: Link[] getLinks() {
694: Link[] links;
695: // make sure this method is MT-safe
696: synchronized (parents) {
697: int n = parents.size();
698: // allocate new array
699: links = new Link[n];
700: for (int i = 0; i < n; i++) {
701: // copy Link nodes from this node's list of parents
702: links[i] = (Link) ((LinkRetained) parents.elementAt(i)).source;
703: }
704: }
705: return links;
706: }
707:
708: void insertChildrenData(int index) {
709: if (childrenSwitchLinks == null) {
710: childrenSwitchLinks = new ArrayList(1);
711: }
712: childrenSwitchLinks.add(index, new ArrayList(1));
713: }
714:
715: void appendChildrenData() {
716: if (childrenSwitchLinks == null) {
717: childrenSwitchLinks = new ArrayList(1);
718: }
719: childrenSwitchLinks.add(new ArrayList(1));
720: }
721:
722: void removeChildrenData(int index) {
723: ArrayList oldSwitchLinks = (ArrayList) childrenSwitchLinks
724: .get(index);
725: oldSwitchLinks.clear();
726: childrenSwitchLinks.remove(index);
727: }
728:
729: // ***************************
730: // TargetsInterface methods
731: // ***************************
732:
733: public int getTargetThreads(int type) {
734: if (type == TargetsInterface.TRANSFORM_TARGETS) {
735: return targetThreads;
736: } else {
737: System.err.println("getTargetThreads: wrong arguments");
738: return -1;
739: }
740: }
741:
742: TargetsInterface getClosestTargetsInterface(int type) {
743: return this ;
744: }
745:
746: // re-evalute localTargetThreads using newCachedTargets and
747: // re-evaluate targetThreads
748: public void computeTargetThreads(int type,
749: CachedTargets[] newCachedTargets) {
750:
751: localTargetThreads = 0;
752: if (type == TargetsInterface.TRANSFORM_TARGETS) {
753: for (int i = 0; i < newCachedTargets.length; i++) {
754: if (newCachedTargets[i] != null) {
755: localTargetThreads |= newCachedTargets[i]
756: .computeTargetThreads();
757: }
758: }
759: targetThreads = localTargetThreads;
760:
761: int numLinks = childTransformLinks.size();
762: TargetsInterface childLink;
763: NodeRetained node;
764:
765: for (int i = 0; i < numLinks; i++) {
766: node = (NodeRetained) childTransformLinks.get(i);
767: if (node.nodeType == NodeRetained.LINK) {
768: childLink = (TargetsInterface) ((LinkRetained) node).sharedGroup;
769: } else {
770: childLink = (TargetsInterface) node;
771: }
772: if (childLink != null) {
773: targetThreads |= childLink
774: .getTargetThreads(TargetsInterface.TRANSFORM_TARGETS);
775: }
776: }
777:
778: } else {
779: System.err
780: .println("computeTargetsThreads: wrong arguments");
781: }
782: }
783:
784: // re-compute localTargetThread, targetThreads and
785: // propagate changes to ancestors
786: public void updateTargetThreads(int type,
787: CachedTargets[] newCachedTargets) {
788: // type is ignored here, only need for SharedGroup
789: if (type == TargetsInterface.TRANSFORM_TARGETS) {
790: computeTargetThreads(type, newCachedTargets);
791: if (parentTransformLink != null) {
792: TargetsInterface pti = (TargetsInterface) parentTransformLink;
793: pti.propagateTargetThreads(
794: TargetsInterface.TRANSFORM_TARGETS,
795: targetThreads);
796: }
797: } else {
798: System.err.println("updateTargetThreads: wrong arguments");
799: }
800: }
801:
802: // re-evaluate targetThreads using childTargetThreads and
803: // propagate changes to ancestors
804: public void propagateTargetThreads(int type, int childTargetThreads) {
805: if (type == TargetsInterface.TRANSFORM_TARGETS) {
806: LinkRetained ln;
807: // XXXX : For now we'll OR more than exact.
808: //targetThreads = localTargetThreads | childTargetThreads;
809: targetThreads = targetThreads | childTargetThreads;
810: for (int i = 0; i < parents.size(); i++) {
811: ln = (LinkRetained) parents.elementAt(i);
812: if (ln.parentTransformLink != null) {
813: TargetsInterface pti = (TargetsInterface) ln.parentTransformLink;
814: pti.propagateTargetThreads(type, targetThreads);
815: }
816: }
817: } else {
818: System.err
819: .println("propagateTargetThreads: wrong arguments");
820: }
821: }
822:
823: public void updateCachedTargets(int type, CachedTargets[] newCt) {
824: if (type == TargetsInterface.TRANSFORM_TARGETS) {
825: j3dCTs = newCt;
826: } else {
827: System.err.println("updateCachedTargets: wrong arguments");
828: }
829: }
830:
831: public void copyCachedTargets(int type, CachedTargets[] newCt) {
832: if (type == TargetsInterface.TRANSFORM_TARGETS) {
833: int size = cachedTargets.length;
834: for (int i = 0; i < size; i++) {
835: newCt[i] = cachedTargets[i];
836: }
837: } else {
838: System.err.println("copyCachedTargets: wrong arguments");
839: }
840: }
841:
842: public CachedTargets getCachedTargets(int type, int index, int child) {
843: if (type == TargetsInterface.SWITCH_TARGETS) {
844: // child info is not used, SG does not have per child states
845: if (index < switchStates.size()) {
846: SwitchState switchState = (SwitchState) switchStates
847: .get(index);
848: return switchState.cachedTargets;
849: } else {
850: return null;
851: }
852: } else {
853: // type == TargetsInterface.TRANSFORM_TARGETS
854: return cachedTargets[index];
855: }
856: }
857:
858: public void resetCachedTargets(int type, CachedTargets[] newCtArr,
859: int child) {
860: if (type == TargetsInterface.SWITCH_TARGETS) {
861: // child info is not used, SG does not have per child states
862: SwitchState switchState;
863: if (newCtArr.length != switchStates.size()) {
864: System.err
865: .println("resetCachedTargets: unmatched length!"
866: + newCtArr.length
867: + " "
868: + switchStates.size());
869: System.err.println(" resetCachedTargets: " + this );
870: }
871: for (int i = 0; i < newCtArr.length; i++) {
872: switchState = (SwitchState) switchStates.get(i);
873: switchState.cachedTargets = newCtArr[i];
874: }
875:
876: } else {
877: // type == TargetsInterface.TRANSFORM_TARGETS
878: cachedTargets = newCtArr;
879: }
880: }
881:
882: public ArrayList getTargetsData(int type, int index) {
883: // index is ignores for SharedGroup
884: if (type == TargetsInterface.SWITCH_TARGETS) {
885: return switchStates;
886: } else {
887: System.err.println("getTargetsData: wrong arguments");
888: return null;
889: }
890: }
891:
892: void childDoSetLive(NodeRetained child, int childIndex,
893: SetLiveState s) {
894:
895: int i;
896: s.childSwitchLinks = (ArrayList) childrenSwitchLinks
897: .get(childIndex);
898: s.switchStates = switchStates;
899:
900: if (child != null)
901: child.setLive(s);
902: }
903:
904: void childCheckSetLive(NodeRetained child, int childIndex,
905: SetLiveState s) {
906: s.childTransformLinks = childTransformLinks;
907: s.parentTransformLink = this ;
908: child.setLive(s);
909: }
910:
911: /**
912: * Make the boundsCache of this node and all its parents dirty
913: */
914: void dirtyBoundsCache() {
915: // Possible optimisation is to not traverse up the tree
916: // if the cachedBounds==null. However this is not the case
917: // if the node is the child of a SharedGroup
918: if (VirtualUniverse.mc.cacheAutoComputedBounds) {
919: // Issue 514 : NPE in Wonderland : triggered in cached bounds computation
920: validCachedBounds = false;
921: synchronized (parents) {
922: Enumeration e = parents.elements();
923: while (e.hasMoreElements()) {
924: LinkRetained parent = (LinkRetained) e
925: .nextElement();
926: if (parent != null) {
927: parent.dirtyBoundsCache();
928: }
929: }
930: }
931: }
932: }
933: }
|