001: /*
002: * $RCSfile: FogRetained.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:21 $
029: * $State: Exp $
030: */
031:
032: package javax.media.j3d;
033:
034: import javax.vecmath.*;
035: import java.util.Enumeration;
036: import java.util.Vector;
037: import java.util.ArrayList;
038:
039: /**
040: * The Fog leaf node defines Fog parameters.
041: * It also specifies an region of influence in which this fog node
042: * is active.
043: */
044: abstract class FogRetained extends LeafRetained {
045:
046: // Statics used when something in the fog changes
047: static final int COLOR_CHANGED = 0x0001;
048: static final int SCOPE_CHANGED = 0x0002;
049: static final int BOUNDS_CHANGED = 0x0004;
050: static final int BOUNDINGLEAF_CHANGED = 0x0008;
051: static final int INIT_MIRROR = 0x0010;
052: static final int CLEAR_MIRROR = 0x0020;
053: static final int LAST_DEFINED_BIT = 0x0020;
054:
055: // Fog color.
056: Color3f color = new Color3f(0.0f, 0.0f, 0.0f);
057:
058: /**
059: * The Boundary object defining the lights's region of influence.
060: */
061: Bounds regionOfInfluence = null;
062:
063: /**
064: * The bounding leaf reference
065: */
066: BoundingLeafRetained boundingLeaf = null;
067:
068: /**
069: * Vector of GroupRetained nodes that scopes this fog.
070: */
071: Vector scopes = new Vector();
072:
073: // An int that is set when this fog is changed
074: int isDirty = 0xffff;
075:
076: // This is true when this fog is referenced in an immediate mode context
077: boolean inImmCtx = false;
078:
079: /**
080: * The transformed value of the applicationRegion.
081: */
082: Bounds region = null;
083:
084: // A reference to the scene graph fog
085: FogRetained sgFog = null;
086:
087: // The mirror copy of this fog
088: FogRetained mirrorFog = null;
089:
090: // Target threads to be notified when light changes
091: static final int targetThreads = J3dThread.UPDATE_RENDERING_ENVIRONMENT
092: | J3dThread.UPDATE_RENDER;
093:
094: // Boolean to indicate if this object is scoped (only used for mirror objects
095: boolean isScoped = false;
096:
097: // The object that contains the dynamic HashKey - a string type object
098: // Used in scoping
099: HashKey tempKey = new HashKey(250);
100:
101: /**
102: * The EnvironmentSets which reference this fog.
103: * Note that multiple RenderBin update thread may access
104: * this shared environmentSets simultaneously.
105: * So we use UnorderList when sync. all the operations.
106: */
107: UnorderList environmentSets = new UnorderList(1,
108: EnvironmentSet.class);
109:
110: // Is true, if the mirror fog is viewScoped
111: boolean isViewScoped = false;
112:
113: // Scale value extracted from localToVworld transform
114: private double localToVworldScale = 1.0;
115:
116: FogRetained() {
117: localBounds = new BoundingBox();
118: ((BoundingBox) localBounds).setLower(1.0, 1.0, 1.0);
119: ((BoundingBox) localBounds).setUpper(-1.0, -1.0, -1.0);
120: }
121:
122: /**
123: * Initialize the fog color to the specified color.
124: */
125: void initColor(Color3f color) {
126: this .color.set(color);
127: }
128:
129: /**
130: * Sets the fog color to the specified color and send message
131: */
132: void setColor(Color3f color) {
133: this .color.set(color);
134: sendMessage(COLOR_CHANGED, new Color3f(color));
135: }
136:
137: /**
138: * Sets the fog color to the specified color.
139: */
140: void initColor(float r, float g, float b) {
141: this .color.x = r;
142: this .color.y = g;
143: this .color.z = b;
144: }
145:
146: /**
147: * Sets the fog color to the specified color and send message
148: */
149: void setColor(float r, float g, float b) {
150: initColor(r, g, b);
151: sendMessage(COLOR_CHANGED, new Color3f(r, g, b));
152: }
153:
154: /**
155: * Retrieves the fog color.
156: */
157: void getColor(Color3f color) {
158: color.set(this .color);
159: }
160:
161: /**
162: * Set the Fog's region of influence.
163: */
164: void initInfluencingBounds(Bounds region) {
165: if (region != null) {
166: this .regionOfInfluence = (Bounds) region.clone();
167: } else {
168: this .regionOfInfluence = null;
169: }
170: if (staticTransform != null) {
171: this .regionOfInfluence.transform(staticTransform.transform);
172: }
173: }
174:
175: /**
176: * Set the Fog's region of influence and send message
177: */
178: void setInfluencingBounds(Bounds region) {
179: initInfluencingBounds(region);
180: sendMessage(BOUNDS_CHANGED, (region != null ? region.clone()
181: : null));
182: }
183:
184: /**
185: * Get the Fog's region of Influence.
186: */
187: Bounds getInfluencingBounds() {
188: Bounds b = null;
189: if (regionOfInfluence != null) {
190: b = (Bounds) regionOfInfluence.clone();
191: if (staticTransform != null) {
192: Transform3D invTransform = staticTransform
193: .getInvTransform();
194: b.transform(invTransform);
195: }
196: }
197: return b;
198: }
199:
200: /**
201: * Set the Fog's region of influence to the specified Leaf node.
202: */
203: void initInfluencingBoundingLeaf(BoundingLeaf region) {
204: if (region != null) {
205: boundingLeaf = (BoundingLeafRetained) region.retained;
206: } else {
207: boundingLeaf = null;
208: }
209: }
210:
211: /**
212: * Set the Fog's region of influence to the specified Leaf node.
213: */
214: void setInfluencingBoundingLeaf(BoundingLeaf region) {
215: if (boundingLeaf != null)
216: boundingLeaf.mirrorBoundingLeaf.removeUser(mirrorFog);
217: if (region != null) {
218: boundingLeaf = (BoundingLeafRetained) region.retained;
219: boundingLeaf.mirrorBoundingLeaf.addUser(mirrorFog);
220: } else {
221: boundingLeaf = null;
222: }
223: sendMessage(BOUNDINGLEAF_CHANGED,
224: (boundingLeaf != null ? boundingLeaf.mirrorBoundingLeaf
225: : null));
226: }
227:
228: /**
229: * Get the Fog's region of influence.
230: */
231: BoundingLeaf getInfluencingBoundingLeaf() {
232: return (boundingLeaf != null ? (BoundingLeaf) boundingLeaf.source
233: : null);
234: }
235:
236: /**
237: * Replaces the specified scope with the scope provided.
238: * @param scope the new scope
239: * @param index which scope to replace
240: */
241: void initScope(Group scope, int index) {
242: scopes.setElementAt((GroupRetained) (scope.retained), index);
243:
244: }
245:
246: /**
247: * Replaces the specified scope with the scope provided.
248: * @param scope the new scope
249: * @param index which scope to replace
250: */
251: void setScope(Group scope, int index) {
252:
253: ArrayList addScopeList = new ArrayList();
254: ArrayList removeScopeList = new ArrayList();
255: GroupRetained group;
256: Object[] scopeInfo = new Object[3];
257:
258: group = (GroupRetained) scopes.get(index);
259: tempKey.reset();
260: group.removeAllNodesForScopedFog(mirrorFog, removeScopeList,
261: tempKey);
262:
263: group = (GroupRetained) scope.retained;
264: initScope(scope, index);
265: tempKey.reset();
266: // If its a group, then add the scope to the group, if
267: // its a shape, then keep a list to be added during
268: // updateMirrorObject
269: group.addAllNodesForScopedFog(mirrorFog, addScopeList, tempKey);
270:
271: scopeInfo[0] = addScopeList;
272: scopeInfo[1] = removeScopeList;
273: scopeInfo[2] = (scopes.size() > 0 ? Boolean.TRUE
274: : Boolean.FALSE);
275: sendMessage(SCOPE_CHANGED, scopeInfo);
276: }
277:
278: /**
279: * Inserts the specified scope at specified index.before the
280: * fog is live
281: * @param scope the new scope
282: * @param index position to insert new scope at
283: */
284: void initInsertScope(Node scope, int index) {
285: GroupRetained group = (GroupRetained) scope.retained;
286: group.setFogScope();
287: scopes.insertElementAt((GroupRetained) (scope.retained), index);
288: }
289:
290: /**
291: * Inserts the specified scope at specified index and sends
292: * a message
293: * @param scope the new scope
294: * @param index position to insert new scope at
295: */
296: void insertScope(Node scope, int index) {
297: Object[] scopeInfo = new Object[3];
298: ArrayList addScopeList = new ArrayList();
299:
300: initInsertScope(scope, index);
301: GroupRetained group = (GroupRetained) scope.retained;
302: tempKey.reset();
303: group.addAllNodesForScopedFog(mirrorFog, addScopeList, tempKey);
304: scopeInfo[0] = addScopeList;
305: scopeInfo[1] = null;
306: scopeInfo[2] = (scopes.size() > 0 ? Boolean.TRUE
307: : Boolean.FALSE);
308: sendMessage(SCOPE_CHANGED, scopeInfo);
309: }
310:
311: void initRemoveScope(int index) {
312: GroupRetained group = (GroupRetained) scopes.elementAt(index);
313: scopes.removeElementAt(index);
314: group.removeFogScope();
315:
316: }
317:
318: void removeScope(int index) {
319:
320: Object[] scopeInfo = new Object[3];
321: ArrayList removeScopeList = new ArrayList();
322: GroupRetained group = (GroupRetained) scopes.elementAt(index);
323:
324: tempKey.reset();
325: group.removeAllNodesForScopedFog(mirrorFog, removeScopeList,
326: tempKey);
327:
328: initRemoveScope(index);
329: scopeInfo[0] = null;
330: scopeInfo[1] = removeScopeList;
331: scopeInfo[2] = (scopes.size() > 0 ? Boolean.TRUE
332: : Boolean.FALSE);
333: sendMessage(SCOPE_CHANGED, scopeInfo);
334: }
335:
336: /**
337: * Returns the scope specified by the index.
338: * @param index which scope to return
339: * @return the scoperen at location index
340: */
341: Group getScope(int index) {
342: return (Group) (((GroupRetained) (scopes.elementAt(index))).source);
343: }
344:
345: /**
346: * Returns an enumeration object of the scoperen.
347: * @return an enumeration object of the scoperen
348: */
349: Enumeration getAllScopes() {
350: Enumeration elm = scopes.elements();
351: Vector v = new Vector(scopes.size());
352: while (elm.hasMoreElements()) {
353: v.add(((GroupRetained) elm.nextElement()).source);
354: }
355: return v.elements();
356: }
357:
358: /**
359: * Appends the specified scope to this node's list of scopes before
360: * the fog is alive
361: * @param scope the scope to add to this node's list of scopes
362: */
363: void initAddScope(Group scope) {
364: GroupRetained group = (GroupRetained) scope.retained;
365: scopes.addElement((GroupRetained) (scope.retained));
366: group.setFogScope();
367: }
368:
369: /**
370: * Appends the specified scope to this node's list of scopes.
371: * @param scope the scope to add to this node's list of scopes
372: */
373: void addScope(Group scope) {
374:
375: Object[] scopeInfo = new Object[3];
376: ArrayList addScopeList = new ArrayList();
377: GroupRetained group = (GroupRetained) scope.retained;
378:
379: initAddScope(scope);
380: tempKey.reset();
381: group.addAllNodesForScopedFog(mirrorFog, addScopeList, tempKey);
382: scopeInfo[0] = addScopeList;
383: scopeInfo[1] = null;
384: scopeInfo[2] = (scopes.size() > 0 ? Boolean.TRUE
385: : Boolean.FALSE);
386: sendMessage(SCOPE_CHANGED, scopeInfo);
387: }
388:
389: /**
390: * Returns a count of this nodes' scopes.
391: * @return the number of scopes descendant from this node
392: */
393: int numScopes() {
394: return scopes.size();
395: }
396:
397: /**
398: * Returns the index of the specified scope within this nodes' list of scopes
399: * @param scope whose index is desired
400: * @return index of specified scope
401: */
402: int indexOfScope(Group scope) {
403: if (scope != null)
404: return scopes.indexOf((GroupRetained) scope.retained);
405: else
406: return scopes.indexOf(null);
407: }
408:
409: /**
410: * Removes the specified scope from this nodes' list of scopes
411: * @param scope to be removed. If the scope is not found,
412: * the method returns silently
413: */
414: void removeScope(Group scope) {
415: int i = indexOfScope(scope);
416: if (i >= 0)
417: removeScope(i);
418: }
419:
420: void initRemoveScope(Group scope) {
421: int i = indexOfScope(scope);
422: if (i >= 0)
423: initRemoveScope(i);
424: }
425:
426: /**
427: * Removes all the scopes from this node's list of scopes.
428: * The node should revert to universal
429: * scope after this method returns
430: */
431: void removeAllScopes() {
432: Object[] scopeInfo = new Object[3];
433: ArrayList removeScopeList = new ArrayList();
434: GroupRetained group;
435: int n = scopes.size();
436:
437: tempKey.reset();
438: for (int index = n - 1; index >= 0; index--) {
439: group = (GroupRetained) scopes.elementAt(index);
440: group.removeAllNodesForScopedFog(mirrorFog,
441: removeScopeList, tempKey);
442: initRemoveScope(index);
443: }
444: scopeInfo[0] = null;
445: scopeInfo[1] = removeScopeList;
446: scopeInfo[2] = Boolean.FALSE;
447: sendMessage(SCOPE_CHANGED, scopeInfo);
448: }
449:
450: /**
451: * Removes all scopes from this node
452: */
453: void initRemoveAllScopes() {
454: int n = scopes.size();
455: for (int index = n - 1; index >= 0; index--)
456: initRemoveScope(index);
457: }
458:
459: /**
460: * This sets the immedate mode context flag
461: */
462: void setInImmCtx(boolean inCtx) {
463: inImmCtx = inCtx;
464: }
465:
466: /**
467: * This gets the immedate mode context flag
468: */
469: boolean getInImmCtx() {
470: return (inImmCtx);
471: }
472:
473: boolean isScoped() {
474: return (scopes != null);
475: }
476:
477: /**
478: * This abstract method is used to update the current native
479: * context fog values.
480: */
481: abstract void update(Context ctx, double scale);
482:
483: void updateImmediateMirrorObject(Object[] objs) {
484: GroupRetained group;
485: Vector currentScopes;
486: int i, nscopes;
487: Transform3D trans;
488:
489: int component = ((Integer) objs[1]).intValue();
490: if ((component & BOUNDS_CHANGED) != 0) {
491: mirrorFog.regionOfInfluence = (Bounds) objs[2];
492: if (mirrorFog.boundingLeaf == null) {
493: if (objs[2] != null) {
494: mirrorFog.region = ((Bounds) mirrorFog.regionOfInfluence)
495: .copy(mirrorFog.region);
496: mirrorFog.region.transform(
497: mirrorFog.regionOfInfluence,
498: getCurrentLocalToVworld());
499: } else {
500: mirrorFog.region = null;
501: }
502: }
503: } else if ((component & BOUNDINGLEAF_CHANGED) != 0) {
504: mirrorFog.boundingLeaf = (BoundingLeafRetained) objs[2];
505: if (objs[2] != null) {
506: mirrorFog.region = (Bounds) mirrorFog.boundingLeaf.transformedRegion;
507: } else {
508: if (mirrorFog.regionOfInfluence != null) {
509: mirrorFog.region = ((Bounds) mirrorFog.regionOfInfluence)
510: .copy(mirrorFog.region);
511: mirrorFog.region.transform(
512: mirrorFog.regionOfInfluence,
513: getCurrentLocalToVworld());
514: } else {
515: mirrorFog.region = null;
516: }
517:
518: }
519: } else if ((component & SCOPE_CHANGED) != 0) {
520: Object[] scopeList = (Object[]) objs[2];
521: ArrayList addList = (ArrayList) scopeList[0];
522: ArrayList removeList = (ArrayList) scopeList[1];
523: boolean isScoped = ((Boolean) scopeList[2]).booleanValue();
524:
525: if (addList != null) {
526: mirrorFog.isScoped = isScoped;
527: for (i = 0; i < addList.size(); i++) {
528: Shape3DRetained obj = ((GeometryAtom) addList
529: .get(i)).source;
530: obj.addFog(mirrorFog);
531: }
532: }
533:
534: if (removeList != null) {
535: mirrorFog.isScoped = isScoped;
536: for (i = 0; i < removeList.size(); i++) {
537: Shape3DRetained obj = ((GeometryAtom) removeList
538: .get(i)).source;
539: obj.removeFog(mirrorFog);
540: }
541: }
542: }
543:
544: }
545:
546: /**
547: * The update Object function.
548: */
549: void updateMirrorObject(Object[] objs) {
550:
551: int component = ((Integer) objs[1]).intValue();
552: if ((component & COLOR_CHANGED) != 0) {
553: mirrorFog.color.set((Color3f) objs[2]);
554: }
555: if ((component & INIT_MIRROR) != 0) {
556: mirrorFog.color.set((Color3f) objs[3]);
557: }
558: }
559:
560: /**
561: * Note: This routine will only be called on
562: * the mirror object - will update the object's
563: * cached region and transformed region
564: */
565: void updateBoundingLeaf() {
566: if (boundingLeaf != null
567: && boundingLeaf.switchState.currentSwitchOn) {
568: region = boundingLeaf.transformedRegion;
569: } else {
570: if (regionOfInfluence != null) {
571: region = regionOfInfluence.copy(region);
572: region.transform(regionOfInfluence,
573: getCurrentLocalToVworld());
574: } else {
575: region = null;
576: }
577: }
578: }
579:
580: /**
581: * This setLive routine just calls the superclass's method (after
582: * checking for use by an immediate context). It is up to the
583: * subclasses of fog to add themselves to the list of fogs
584: */
585: void setLive(SetLiveState s) {
586: GroupRetained group;
587: Vector currentScopes;
588: int i, nscopes;
589: TransformGroupRetained[] tlist;
590:
591: if (inImmCtx) {
592: throw new IllegalSharingException(J3dI18N
593: .getString("FogRetained0"));
594: }
595: super .doSetLive(s);
596:
597: if (inSharedGroup) {
598: throw new IllegalSharingException(J3dI18N
599: .getString("FogRetained1"));
600: }
601:
602: // Create the mirror object
603: // Initialization of the mirror object during the INSERT_NODE
604: // message (in updateMirrorObject)
605: if (mirrorFog == null) {
606: // mirrorFog = (FogRetained)this.clone(true);
607: mirrorFog = (FogRetained) this .clone();
608: // Assign the bounding leaf of this mirror object as null
609: // it will later be assigned to be the mirror of the lights
610: // bounding leaf object
611: mirrorFog.boundingLeaf = null;
612: mirrorFog.sgFog = this ;
613: }
614: // initMirrorObject();
615: // If bounding leaf is not null, add the mirror object as a user
616: // so that any changes to the bounding leaf will be received
617: if (boundingLeaf != null) {
618: boundingLeaf.mirrorBoundingLeaf.addUser(mirrorFog);
619: }
620:
621: if ((s.viewScopedNodeList != null) && (s.viewLists != null)) {
622: s.viewScopedNodeList.add(mirrorFog);
623: s.scopedNodesViewList.add(s.viewLists.get(0));
624: } else {
625: s.nodeList.add(mirrorFog);
626: }
627:
628: if (s.transformTargets != null && s.transformTargets[0] != null) {
629: s.transformTargets[0].addNode(mirrorFog,
630: Targets.ENV_TARGETS);
631: s.notifyThreads |= J3dThread.UPDATE_TRANSFORM;
632: }
633:
634: // process switch leaf
635: if (s.switchTargets != null && s.switchTargets[0] != null) {
636: s.switchTargets[0].addNode(mirrorFog, Targets.ENV_TARGETS);
637: }
638: mirrorFog.switchState = (SwitchState) s.switchStates.get(0);
639:
640: s.notifyThreads |= J3dThread.UPDATE_RENDERING_ENVIRONMENT
641: | J3dThread.UPDATE_RENDER;
642:
643: super .markAsLive();
644:
645: }
646:
647: // This is called on the parent object
648: void initMirrorObject(Object[] args) {
649: Shape3DRetained shape;
650: Object[] scopeInfo = (Object[]) args[2];
651: Boolean scoped = (Boolean) scopeInfo[0];
652: ArrayList shapeList = (ArrayList) scopeInfo[1];
653: BoundingLeafRetained bl = (BoundingLeafRetained) ((Object[]) args[4])[0];
654: Bounds bnds = (Bounds) ((Object[]) args[4])[1];
655:
656: mirrorFog.inBackgroundGroup = ((Boolean) ((Object[]) args[4])[2])
657: .booleanValue();
658: mirrorFog.geometryBackground = (BackgroundRetained) ((Object[]) args[4])[3];
659: for (int i = 0; i < shapeList.size(); i++) {
660: shape = ((GeometryAtom) shapeList.get(i)).source;
661: shape.addFog(mirrorFog);
662: }
663: mirrorFog.isScoped = scoped.booleanValue();
664:
665: if (bl != null) {
666: mirrorFog.boundingLeaf = bl.mirrorBoundingLeaf;
667: mirrorFog.region = boundingLeaf.transformedRegion;
668: } else {
669: mirrorFog.boundingLeaf = null;
670: mirrorFog.region = null;
671: }
672:
673: if (bnds != null) {
674: mirrorFog.regionOfInfluence = bnds;
675: if (mirrorFog.region == null) {
676: mirrorFog.region = (Bounds) regionOfInfluence.clone();
677: mirrorFog.region.transform(regionOfInfluence,
678: getLastLocalToVworld());
679: }
680: } else {
681: mirrorFog.regionOfInfluence = null;
682: }
683:
684: }
685:
686: // This is called on the parent object
687: void clearMirrorObject(Object[] args) {
688: Shape3DRetained shape;
689: ArrayList shapeList = (ArrayList) args[2];
690: ArrayList removeScopeList = new ArrayList();
691:
692: for (int i = 0; i < shapeList.size(); i++) {
693: shape = ((GeometryAtom) shapeList.get(i)).source;
694: shape.removeFog(mirrorFog);
695: }
696: mirrorFog.isScoped = false;
697:
698: }
699:
700: /**
701: * This clearLive routine first calls the superclass's method, then
702: * it removes itself to the list of fogs
703: */
704: void clearLive(SetLiveState s) {
705: int i, j;
706: GroupRetained group;
707:
708: super .clearLive(s);
709:
710: if (s.switchTargets != null && s.switchTargets[0] != null) {
711: s.switchTargets[0].addNode(mirrorFog, Targets.ENV_TARGETS);
712: }
713: s.notifyThreads |= J3dThread.UPDATE_RENDERING_ENVIRONMENT
714: | J3dThread.UPDATE_RENDER;
715:
716: // Remove this mirror light as users of the bounding leaf
717: if (mirrorFog.boundingLeaf != null)
718: mirrorFog.boundingLeaf.removeUser(mirrorFog);
719:
720: if ((s.viewScopedNodeList != null) && (s.viewLists != null)) {
721: s.viewScopedNodeList.add(mirrorFog);
722: s.scopedNodesViewList.add(s.viewLists.get(0));
723: } else {
724: s.nodeList.add(mirrorFog);
725: }
726: if (s.transformTargets != null && s.transformTargets[0] != null) {
727: s.transformTargets[0].addNode(mirrorFog,
728: Targets.ENV_TARGETS);
729: s.notifyThreads |= J3dThread.UPDATE_TRANSFORM;
730: }
731:
732: if (scopes.size() > 0) {
733: J3dMessage createMessage = new J3dMessage();
734: createMessage.threads = J3dThread.UPDATE_RENDERING_ENVIRONMENT;
735: createMessage.universe = universe;
736: createMessage.type = J3dMessage.FOG_CHANGED;
737: createMessage.args[0] = this ;
738: createMessage.args[1] = new Integer(CLEAR_MIRROR);
739: ArrayList removeScopeList = new ArrayList();
740: for (i = 0; i < scopes.size(); i++) {
741: group = (GroupRetained) scopes.get(i);
742: tempKey.reset();
743: group.removeAllNodesForScopedFog(mirrorFog,
744: removeScopeList, tempKey);
745: }
746: createMessage.args[2] = removeScopeList;
747: VirtualUniverse.mc.processMessage(createMessage);
748: }
749: }
750:
751: // Clone the retained side only, internal use only
752: protected Object clone() {
753: FogRetained fr = (FogRetained) super .clone();
754:
755: fr.color = new Color3f(color);
756: Bounds b = getInfluencingBounds();
757: if (b != null) {
758: fr.initInfluencingBounds(b);
759: }
760:
761: fr.scopes = new Vector();
762: fr.isDirty = 0xffff;
763: fr.inImmCtx = false;
764: fr.region = null;
765: fr.sgFog = null;
766: fr.mirrorFog = null;
767: fr.environmentSets = new UnorderList(1, EnvironmentSet.class);
768: return fr;
769: }
770:
771: void updateTransformChange() {
772: super .updateTransformChange();
773: setLocalToVworldScale(sgFog.getLastLocalToVworld()
774: .getDistanceScale());
775: }
776:
777: // Called on mirror object
778: void updateImmediateTransformChange() {
779: // If bounding leaf is null, tranform the bounds object
780: if (boundingLeaf == null) {
781: if (regionOfInfluence != null) {
782: region = regionOfInfluence.copy(region);
783: region.transform(regionOfInfluence, sgFog
784: .getCurrentLocalToVworld());
785: }
786:
787: }
788: }
789:
790: final void sendMessage(int attrMask, Object attr) {
791: J3dMessage createMessage = new J3dMessage();
792: createMessage.threads = targetThreads;
793: createMessage.universe = universe;
794: createMessage.type = J3dMessage.FOG_CHANGED;
795: createMessage.args[0] = this ;
796: createMessage.args[1] = new Integer(attrMask);
797: createMessage.args[2] = attr;
798: VirtualUniverse.mc.processMessage(createMessage);
799: }
800:
801: void mergeTransform(TransformGroupRetained xform) {
802: super .mergeTransform(xform);
803: if (regionOfInfluence != null) {
804: regionOfInfluence.transform(xform.transform);
805: }
806: }
807:
808: void getMirrorObjects(ArrayList leafList, HashKey key) {
809: leafList.add(mirrorFog);
810: }
811:
812: /**
813: * Scale distances from local to eye coordinate
814: */
815: protected void validateDistancesInEc(double vworldToCoexistenceScale) {
816: assert false : "subclasses should override this method";
817: }
818:
819: double getLocalToVworldScale() {
820: return localToVworldScale;
821: }
822:
823: void setLocalToVworldScale(double localToVworldScale) {
824: this.localToVworldScale = localToVworldScale;
825: }
826: }
|