001: /*
002: * $RCSfile: BackgroundRetained.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.9 $
028: * $Date: 2008/02/28 20:17:19 $
029: * $State: Exp $
030: */
031:
032: package javax.media.j3d;
033:
034: import javax.vecmath.*;
035: import java.util.ArrayList;
036: import java.awt.geom.AffineTransform;
037: import java.awt.image.AffineTransformOp;
038: import java.awt.image.BufferedImage;
039:
040: /**
041: * The Background leaf node defines either a solid background color
042: * or a background image that is used to fill the window at the
043: * beginning of each new frame. It also specifies an application
044: * region in which this background is active.
045: */
046: class BackgroundRetained extends LeafRetained {
047:
048: static final int COLOR_CHANGED = 0x00001;
049: static final int IMAGE_CHANGED = 0x00002;
050: static final int GEOMETRY_CHANGED = 0x00004;
051: static final int BOUNDS_CHANGED = 0x00008;
052: static final int BOUNDINGLEAF_CHANGED = 0x00010;
053: static final int IMAGE_SCALE_CHANGED = 0x00020;
054: // Background color or image. If non-null, the image overrides the
055: // color.
056: Color3f color = new Color3f(0.0f, 0.0f, 0.0f);
057: ImageComponent2DRetained image = null;
058: Texture2DRetained texture = null;
059:
060: // the image scale mode if image is used.
061: int imageScaleMode = Background.SCALE_NONE;
062:
063: /**
064: * The Boundary object defining the lights's application region.
065: */
066: Bounds applicationRegion = null;
067:
068: /**
069: * The bounding leaf reference
070: */
071: BoundingLeafRetained boundingLeaf = null;
072:
073: /**
074: * Background geometry branch group
075: */
076: BranchGroup geometryBranch = null;
077:
078: /**
079: * The transformed value of the applicationRegion.
080: */
081: Bounds transformedRegion = null;
082:
083: /**
084: * The state structure used for Background Geometry
085: */
086: SetLiveState setLiveState = null;
087:
088: /**
089: * The locale of this Background node since we don't have mirror object
090: * when clearLive is called
091: * locale is set to null, we still want locale to have a
092: * non-null value, since renderingEnv structure may be using the
093: * locale
094: */
095: Locale cachedLocale = null;
096:
097: // This is true when this background is referenced in an immediate mode context
098: boolean inImmCtx = false;
099:
100: // list of light nodes for background geometry
101: ArrayList lights = new ArrayList();
102:
103: // list of fog nodes for background geometry
104: ArrayList fogs = new ArrayList();
105:
106: // a list of background geometry atoms
107: ArrayList bgGeometryAtomList = new ArrayList();
108:
109: // false is background geometry atoms list has changed
110: boolean bgGeometryAtomListDirty = true;
111:
112: // an array of background geometry atoms
113: GeometryAtom[] bgGeometryAtoms = null;
114:
115: // Target threads to be notified when light changes
116: // Note, the rendering env structure only get notified
117: // when there is a bounds related change
118: final static int targetThreads = J3dThread.UPDATE_RENDERING_ENVIRONMENT
119: | J3dThread.UPDATE_RENDER;
120:
121: // Is true, if the background is viewScoped
122: boolean isViewScoped = false;
123:
124: BackgroundRetained() {
125: this .nodeType = NodeRetained.BACKGROUND;
126: localBounds = new BoundingBox();
127: ((BoundingBox) localBounds).setLower(1.0, 1.0, 1.0);
128: ((BoundingBox) localBounds).setUpper(-1.0, -1.0, -1.0);
129: }
130:
131: /**
132: * Initializes the background color to the specified color.
133: * This color is used
134: * if the image is null.
135: * @param color the new background color
136: */
137: final void initColor(Color3f color) {
138: this .color.set(color);
139: }
140:
141: /**
142: * Sets the background color to the specified color. This color is used
143: * if the image is null.
144: * @param color the new background color
145: */
146: final void setColor(Color3f color) {
147: initColor(color);
148: if (source.isLive()) {
149: sendMessage(COLOR_CHANGED, new Color3f(color));
150: }
151: }
152:
153: /**
154: * Initializes the background color to the specified color.
155: * This color is used
156: * if the image is null.
157: * @param r the red component of the background color
158: * @param g the green component of the background color
159: * @param b the blue component of the background color
160: */
161: final void initColor(float r, float g, float b) {
162: this .color.x = r;
163: this .color.y = g;
164: this .color.z = b;
165: }
166:
167: /**
168: * Sets the background color to the specified color. This color is used
169: * if the image is null.
170: * @param r the red component of the background color
171: * @param g the green component of the background color
172: * @param b the blue component of the background color
173: */
174: final void setColor(float r, float g, float b) {
175: setColor(new Color3f(r, g, b));
176: }
177:
178: /**
179: * Retrieves the background color.
180: * @param color the vector that will receive the current background color
181: */
182: final void getColor(Color3f color) {
183: color.set(this .color);
184: }
185:
186: /**
187: * Initialize the image scale mode to the specified mode
188: * @imageScaleMode the image scale mode to the used
189: */
190: final void initImageScaleMode(int imageScaleMode) {
191: this .imageScaleMode = imageScaleMode;
192: }
193:
194: /**
195: * Sets the image scale mode for this Background node.
196: * @param imageScaleMode the image scale mode
197: */
198: final void setImageScaleMode(int imageScaleMode) {
199: initImageScaleMode(imageScaleMode);
200: if (source.isLive()) {
201: sendMessage(IMAGE_SCALE_CHANGED,
202: new Integer(imageScaleMode));
203: }
204: }
205:
206: /**
207: * gets the image scale mode for this Background node.
208: */
209: final int getImageScaleMode() {
210: return imageScaleMode;
211: }
212:
213: /**
214: * Initializes the background image to the specified image.
215: * @param image new ImageCompoent2D object used as the background image
216: */
217: final void initImage(ImageComponent2D img) {
218: int texFormat;
219:
220: if (img == null) {
221: image = null;
222: texture = null;
223: return;
224: }
225:
226: if (img.retained != image) {
227: image = (ImageComponent2DRetained) img.retained;
228: image.setEnforceNonPowerOfTwoSupport(true);
229: switch (image.getNumberOfComponents()) {
230: case 1:
231: texFormat = Texture.INTENSITY;
232: break;
233: case 2:
234: texFormat = Texture.LUMINANCE_ALPHA;
235: break;
236: case 3:
237: texFormat = Texture.RGB;
238: break;
239: case 4:
240: texFormat = Texture.RGBA;
241: break;
242: default:
243: assert false;
244: return;
245: }
246:
247: Texture2D tex2D = new Texture2D(Texture.BASE_LEVEL,
248: texFormat, img.getWidth(), img.getHeight());
249: texture = (Texture2DRetained) tex2D.retained;
250: // Background is special case of Raster.
251: texture.setUseAsRaster(true);
252: // Fix to issue 373 : ImageComponent.set(BufferedImage) ignored when used by Background
253: image.addUser(texture);
254: texture.initImage(0, img);
255: }
256: }
257:
258: /**
259: * Sets the background image to the specified image.
260: * @param image new ImageCompoent3D object used as the background image
261: */
262: final void setImage(ImageComponent2D img) {
263: if (source.isLive()) {
264: if (texture != null) {
265: texture.clearLive(refCount);
266: }
267: }
268: initImage(img);
269: if (source.isLive()) {
270: if (texture != null) {
271: texture.setLive(inBackgroundGroup, refCount);
272: }
273:
274: sendMessage(IMAGE_CHANGED,
275: (texture != null ? texture.mirror : null));
276:
277: }
278: }
279:
280: /**
281: * Retrieves the background image.
282: * @return the current background image
283: */
284: final ImageComponent2D getImage() {
285: return (image == null ? null : (ImageComponent2D) image.source);
286: }
287:
288: /**
289: * Initializes the background geometry branch group to the specified branch.
290: * @param branch new branch group object used for background geometry
291: */
292: final void initGeometry(BranchGroup branch) {
293: geometryBranch = branch;
294: }
295:
296: /**
297: * Sets the background geometry branch group to the specified branch.
298: * @param branch new branch group object used for background geometry
299: */
300: final void setGeometry(BranchGroup branch) {
301: int numMessages = 0;
302: int i;
303:
304: if (source.isLive()) {
305: J3dMessage m[];
306: if (geometryBranch != null)
307: numMessages += 2; // REMOVE_NODES, ORDERED_GROUP_REMOVED
308: if (branch != null)
309: numMessages += 2; // INSERT_NODES, ORDERED_GROUP_INSERTED
310: m = new J3dMessage[numMessages];
311: for (i = 0; i < numMessages; i++) {
312: m[i] = new J3dMessage();
313: }
314: i = 0;
315: if (geometryBranch != null) {
316: clearGeometryBranch((BranchGroupRetained) geometryBranch.retained);
317: m[i].threads = (J3dThread.UPDATE_RENDER | J3dThread.UPDATE_RENDERING_ENVIRONMENT);
318: m[i].type = J3dMessage.ORDERED_GROUP_REMOVED;
319: m[i].universe = universe;
320: m[i].args[0] = setLiveState.ogList.toArray();
321: m[i].args[1] = setLiveState.ogChildIdList.toArray();
322: m[i].args[3] = setLiveState.ogCIOList.toArray();
323: m[i].args[4] = setLiveState.ogCIOTableList.toArray();
324: i++;
325:
326: m[i].threads = setLiveState.notifyThreads;
327: m[i].type = J3dMessage.REMOVE_NODES;
328: m[i].universe = universe;
329: m[i].args[0] = setLiveState.nodeList.toArray();
330: i++;
331:
332: }
333: if (branch != null) {
334: setGeometryBranch((BranchGroupRetained) branch.retained);
335: m[i].threads = (J3dThread.UPDATE_RENDER | J3dThread.UPDATE_RENDERING_ENVIRONMENT);
336: m[i].type = J3dMessage.ORDERED_GROUP_INSERTED;
337: m[i].universe = universe;
338: m[i].args[0] = setLiveState.ogList.toArray();
339: m[i].args[1] = setLiveState.ogChildIdList.toArray();
340: m[i].args[2] = setLiveState.ogOrderedIdList.toArray();
341: m[i].args[3] = setLiveState.ogCIOList.toArray();
342: m[i].args[4] = setLiveState.ogCIOTableList.toArray();
343: i++;
344:
345: m[i].threads = setLiveState.notifyThreads;
346: m[i].type = J3dMessage.INSERT_NODES;
347: m[i].universe = universe;
348: m[i].args[0] = setLiveState.nodeList.toArray();
349: }
350: VirtualUniverse.mc.processMessage(m);
351: // Free up memory
352: setLiveState.reset(null);
353: }
354: initGeometry(branch);
355: }
356:
357: /**
358: * Retrieves the background geometry branch group.
359: * @return the current background geometry branch group
360: */
361: final BranchGroup getGeometry() {
362: return geometryBranch;
363: }
364:
365: /**
366: * Initializes the Background's application region.
367: * @param region a region that contains the Backgound's new application bounds
368: */
369: final void initApplicationBounds(Bounds region) {
370: if (region != null) {
371: applicationRegion = (Bounds) region.clone();
372: } else {
373: applicationRegion = null;
374: }
375: }
376:
377: /**
378: * Set the Background's application region.
379: * @param region a region that contains the Backgound's new application bounds
380: */
381: final void setApplicationBounds(Bounds region) {
382: initApplicationBounds(region);
383: // Don't send the message if there is a valid boundingleaf
384: if (boundingLeaf == null) {
385: J3dMessage createMessage = new J3dMessage();
386: createMessage.threads = targetThreads
387: | J3dThread.UPDATE_RENDERING_ENVIRONMENT;
388: createMessage.type = J3dMessage.BACKGROUND_CHANGED;
389: createMessage.universe = universe;
390: createMessage.args[0] = this ;
391: createMessage.args[1] = new Integer(BOUNDS_CHANGED);
392: if (region != null)
393: createMessage.args[2] = region.clone();
394: else
395: createMessage.args[2] = null;
396: VirtualUniverse.mc.processMessage(createMessage);
397: }
398: }
399:
400: /**
401: * Get the Backgound's application region.
402: * @return this Backgound's application region information
403: */
404: final Bounds getApplicationBounds() {
405: return (applicationRegion != null ? (Bounds) applicationRegion
406: .clone() : null);
407: }
408:
409: /**
410: * Initializes the Background's application region
411: * to the specified Leaf node.
412: */
413: void initApplicationBoundingLeaf(BoundingLeaf region) {
414: if (region != null) {
415: boundingLeaf = (BoundingLeafRetained) region.retained;
416: } else {
417: boundingLeaf = null;
418: }
419: }
420:
421: /**
422: * Set the Background's application region to the specified Leaf node.
423: */
424: void setApplicationBoundingLeaf(BoundingLeaf region) {
425: if (boundingLeaf != null)
426: boundingLeaf.mirrorBoundingLeaf.removeUser(this );
427:
428: if (region != null) {
429: boundingLeaf = (BoundingLeafRetained) region.retained;
430: boundingLeaf.mirrorBoundingLeaf.addUser(this );
431: } else {
432: boundingLeaf = null;
433: }
434: J3dMessage createMessage = new J3dMessage();
435: createMessage.threads = targetThreads
436: | J3dThread.UPDATE_RENDERING_ENVIRONMENT;
437: createMessage.type = J3dMessage.BACKGROUND_CHANGED;
438: createMessage.universe = universe;
439: createMessage.args[0] = this ;
440: createMessage.args[1] = new Integer(BOUNDINGLEAF_CHANGED);
441: if (boundingLeaf != null) {
442: createMessage.args[2] = boundingLeaf.mirrorBoundingLeaf;
443: createMessage.args[3] = null;
444: } else {
445: createMessage.args[2] = null;
446: if (applicationRegion != null)
447: createMessage.args[3] = applicationRegion.clone();
448: else
449: createMessage.args[3] = null;
450: }
451: VirtualUniverse.mc.processMessage(createMessage);
452: }
453:
454: /**
455: * Get the Background's application region
456: */
457: BoundingLeaf getApplicationBoundingLeaf() {
458: return (boundingLeaf != null ? (BoundingLeaf) boundingLeaf.source
459: : null);
460: }
461:
462: /**
463: * This sets the immedate mode context flag
464: */
465: void setInImmCtx(boolean inCtx) {
466: inImmCtx = inCtx;
467: }
468:
469: /**
470: * This gets the immedate mode context flag
471: */
472: boolean getInImmCtx() {
473: return (inImmCtx);
474: }
475:
476: void setGeometryBranch(BranchGroupRetained branch) {
477: setLiveState.reset(locale);
478: setLiveState.inBackgroundGroup = true;
479:
480: setLiveState.geometryBackground = this ;
481: setLiveState.currentTransforms[0] = new Transform3D[2];
482: setLiveState.currentTransforms[0][0] = new Transform3D();
483: setLiveState.currentTransforms[0][1] = new Transform3D();
484: setLiveState.currentTransformsIndex[0] = new int[2];
485: setLiveState.currentTransformsIndex[0][0] = 0;
486: setLiveState.currentTransformsIndex[0][1] = 0;
487:
488: setLiveState.localToVworld = setLiveState.currentTransforms;
489: setLiveState.localToVworldIndex = setLiveState.currentTransformsIndex;
490:
491: setLiveState.branchGroupPaths = new ArrayList();
492: setLiveState.branchGroupPaths.add(new BranchGroupRetained[0]);
493:
494: setLiveState.orderedPaths = new ArrayList(1);
495: setLiveState.orderedPaths.add(new OrderedPath());
496:
497: setLiveState.switchStates = new ArrayList(1);
498: setLiveState.switchStates.add(new SwitchState(false));
499:
500: branch.setLive(setLiveState);
501:
502: }
503:
504: void clearGeometryBranch(BranchGroupRetained branch) {
505: setLiveState.reset(locale);
506: setLiveState.inBackgroundGroup = true;
507: setLiveState.geometryBackground = this ;
508: branch.clearLive(setLiveState);
509: branch.setParent(null);
510: branch.setLocale(null);
511:
512: }
513:
514: /**
515: * This setLive routine first calls the superclass's method, then
516: * it adds itself to the list of lights
517: */
518: void setLive(SetLiveState s) {
519: TransformGroupRetained[] tlist;
520: int i;
521:
522: super .doSetLive(s);
523:
524: if (inImmCtx) {
525: throw new IllegalSharingException(J3dI18N
526: .getString("BackgroundRetained1"));
527: }
528: if (inBackgroundGroup) {
529: throw new IllegalSceneGraphException(J3dI18N
530: .getString("BackgroundRetained5"));
531: }
532:
533: if (inSharedGroup) {
534: throw new IllegalSharingException(J3dI18N
535: .getString("BackgroundRetained6"));
536: }
537:
538: if (geometryBranch != null) {
539: BranchGroupRetained branch = (BranchGroupRetained) geometryBranch.retained;
540: if (branch.inBackgroundGroup == true)
541: throw new IllegalSharingException(J3dI18N
542: .getString("BackgroundRetained0"));
543:
544: if (branch.parent != null)
545: throw new IllegalSharingException(J3dI18N
546: .getString("BackgroundRetained3"));
547:
548: if (branch.locale != null)
549: throw new IllegalSharingException(J3dI18N
550: .getString("BackgroundRetained4"));
551:
552: if (setLiveState == null) {
553: setLiveState = new SetLiveState(universe);
554: setLiveState.universe = universe;
555: }
556: setGeometryBranch((BranchGroupRetained) geometryBranch.retained);
557: // add background geometry nodes to setLiveState's nodeList
558: s.nodeList.addAll(setLiveState.nodeList);
559: s.notifyThreads |= setLiveState.notifyThreads;
560: s.ogList.addAll(setLiveState.ogList);
561: s.ogChildIdList.addAll(setLiveState.ogChildIdList);
562: s.ogOrderedIdList.addAll(setLiveState.ogOrderedIdList);
563: // Free up memory.
564: setLiveState.reset(null);
565: }
566:
567: if ((s.viewScopedNodeList != null) && (s.viewLists != null)) {
568: s.viewScopedNodeList.add(this );
569: s.scopedNodesViewList.add(s.viewLists.get(0));
570: } else {
571: s.nodeList.add(this );
572: }
573: // System.err.println("bkg.setlive nodeList " + s.nodeList);
574:
575: // process switch leaf
576: if (s.switchTargets != null && s.switchTargets[0] != null) {
577: s.switchTargets[0].addNode(this , Targets.ENV_TARGETS);
578: }
579: switchState = (SwitchState) s.switchStates.get(0);
580:
581: // Initialize some mirror values
582: if (boundingLeaf != null) {
583: transformedRegion = (Bounds) boundingLeaf.mirrorBoundingLeaf.transformedRegion;
584: } else { // Evaluate applicationRegion if not null
585: if (applicationRegion != null) {
586: transformedRegion = (Bounds) applicationRegion.clone();
587: transformedRegion.transform(applicationRegion,
588: getLastLocalToVworld());
589: } else {
590: transformedRegion = null;
591: }
592:
593: }
594: cachedLocale = s.locale;
595:
596: // add this node to the transform target
597: if (s.transformTargets != null && s.transformTargets[0] != null) {
598: s.transformTargets[0].addNode(this , Targets.ENV_TARGETS);
599: s.notifyThreads |= J3dThread.UPDATE_TRANSFORM;
600: }
601:
602: s.notifyThreads |= J3dThread.UPDATE_RENDERING_ENVIRONMENT
603: | J3dThread.UPDATE_RENDER;
604:
605: if (texture != null) {
606: texture.setLive(inBackgroundGroup, refCount);
607: }
608: super .markAsLive();
609:
610: }
611:
612: /**
613: * This clearLive routine first calls the superclass's method, then
614: * it removes itself to the list of lights
615: */
616: void clearLive(SetLiveState s) {
617: super .clearLive(s);
618: if ((s.viewScopedNodeList != null) && (s.viewLists != null)) {
619: s.viewScopedNodeList.add(this );
620: s.scopedNodesViewList.add(s.viewLists.get(0));
621: } else {
622: s.nodeList.add(this );
623: }
624: if (s.transformTargets != null && s.transformTargets[0] != null) {
625: s.transformTargets[0].addNode(this , Targets.ENV_TARGETS);
626: s.notifyThreads |= J3dThread.UPDATE_TRANSFORM;
627: }
628:
629: if (s.switchTargets != null && s.switchTargets[0] != null) {
630: s.switchTargets[0].addNode(this , Targets.ENV_TARGETS);
631: }
632:
633: if (geometryBranch != null) {
634: BranchGroupRetained branch = (BranchGroupRetained) geometryBranch.retained;
635: clearGeometryBranch((BranchGroupRetained) geometryBranch.retained);
636: // add background geometry nodes to setLiveState's nodeList
637: s.nodeList.addAll(setLiveState.nodeList);
638: s.ogList.addAll(setLiveState.ogList);
639: s.ogChildIdList.addAll(setLiveState.ogChildIdList);
640: s.notifyThreads |= setLiveState.notifyThreads;
641: // Free up memory.
642: setLiveState.reset(null);
643: lights.clear();
644: fogs.clear();
645: }
646:
647: if (texture != null) {
648: texture.clearLive(refCount);
649: }
650:
651: s.notifyThreads |= J3dThread.UPDATE_RENDERING_ENVIRONMENT
652: | J3dThread.UPDATE_RENDER;
653: }
654:
655: // The update Object function.
656: synchronized void updateImmediateMirrorObject(Object[] objs) {
657: int component = ((Integer) objs[1]).intValue();
658: Transform3D trans;
659: // If initialization
660:
661: // Bounds message only sent when boundingleaf is null
662: if ((component & BOUNDS_CHANGED) != 0) {
663: if (objs[2] != null) {
664: transformedRegion = ((Bounds) ((Bounds) objs[2]))
665: .copy(transformedRegion);
666: transformedRegion.transform((Bounds) objs[2],
667: getCurrentLocalToVworld());
668: } else {
669: transformedRegion = null;
670: }
671: } else if ((component & BOUNDINGLEAF_CHANGED) != 0) {
672: if (objs[2] != null) {
673: transformedRegion = ((BoundingLeafRetained) objs[2]).transformedRegion;
674: } else { // Evaluate applicationRegion if not null
675: Bounds appRegion = (Bounds) objs[3];
676: if (appRegion != null) {
677: transformedRegion = appRegion
678: .copy(transformedRegion);
679: transformedRegion.transform(appRegion,
680: getCurrentLocalToVworld());
681: } else {
682: transformedRegion = null;
683: }
684:
685: }
686: }
687:
688: }
689:
690: /** Note: This routine will only be called
691: * to update the object's
692: * transformed region
693: */
694: void updateBoundingLeaf() {
695: if (boundingLeaf != null
696: && boundingLeaf.mirrorBoundingLeaf.switchState.currentSwitchOn) {
697: transformedRegion = boundingLeaf.mirrorBoundingLeaf.transformedRegion;
698: } else { // Evaluate applicationRegion if not null
699: if (applicationRegion != null) {
700: transformedRegion = applicationRegion
701: .copy(transformedRegion);
702: transformedRegion.transform(applicationRegion,
703: getCurrentLocalToVworld());
704: } else {
705: transformedRegion = null;
706: }
707: }
708: }
709:
710: void updateImmediateTransformChange() {
711: // If bounding leaf is null, tranform the bounds object
712: if (boundingLeaf == null) {
713: if (applicationRegion != null) {
714: transformedRegion = applicationRegion
715: .copy(transformedRegion);
716: transformedRegion.transform(applicationRegion,
717: getCurrentLocalToVworld());
718: }
719: }
720: }
721:
722: final void sendMessage(int attrMask, Object attr) {
723: J3dMessage createMessage = new J3dMessage();
724: createMessage.threads = targetThreads;
725: createMessage.universe = universe;
726: createMessage.type = J3dMessage.BACKGROUND_CHANGED;
727: createMessage.args[0] = this ;
728: createMessage.args[1] = new Integer(attrMask);
729: createMessage.args[2] = attr;
730: VirtualUniverse.mc.processMessage(createMessage);
731: }
732:
733: void addBgGeometryAtomList(GeometryAtom geomAtom) {
734: bgGeometryAtomList.add(geomAtom);
735: bgGeometryAtomListDirty = true;
736: }
737:
738: void removeBgGeometryAtomList(GeometryAtom geomAtom) {
739: bgGeometryAtomList.remove(bgGeometryAtomList.indexOf(geomAtom));
740: bgGeometryAtomListDirty = true;
741: }
742:
743: GeometryAtom[] getBackgroundGeometryAtoms() {
744: if (bgGeometryAtomListDirty) {
745: int nAtoms = bgGeometryAtomList.size();
746: if (nAtoms == 0) {
747: bgGeometryAtoms = null;
748: } else {
749: bgGeometryAtoms = new GeometryAtom[nAtoms];
750: for (int i = 0; i < bgGeometryAtoms.length; i++) {
751: bgGeometryAtoms[i] = (GeometryAtom) bgGeometryAtomList
752: .get(i);
753: }
754: bgGeometryAtomListDirty = false;
755: }
756: }
757: return (bgGeometryAtoms);
758: }
759:
760: void mergeTransform(TransformGroupRetained xform) {
761: super .mergeTransform(xform);
762: if (applicationRegion != null) {
763: applicationRegion.transform(xform.transform);
764: }
765: }
766:
767: // notifies the Background object that the image data in a referenced
768: // ImageComponent object is changed.
769: // Currently we are not making use of this information.
770:
771: void notifyImageComponentImageChanged(ImageComponentRetained image,
772: ImageComponentUpdateInfo value) {
773: }
774:
775: void getMirrorObjects(ArrayList leafList, HashKey key) {
776: leafList.add(this ); // No Mirror in this case
777: }
778: }
|