001: /*
002: * $RCSfile: BoundingLeafRetained.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.6 $
028: * $Date: 2008/02/28 20:17:20 $
029: * $State: Exp $
030: */
031:
032: package javax.media.j3d;
033:
034: import javax.vecmath.*;
035: import java.util.ArrayList;
036:
037: /**
038: * The BoundingLeaf node defines a bounding region object that can be
039: * referenced by other nodes to define a region of influence, an
040: * application region, or a scheduling region.
041: */
042: class BoundingLeafRetained extends LeafRetained {
043: // Statics used when something in the boundingleaf changes
044: static final int REGION_CHANGED = 0x0001;
045: static final Integer REGION_CHANGED_MESSAGE = new Integer(
046: REGION_CHANGED);
047:
048: // The bounding region object defined by this node
049: Bounds region = null;
050:
051: // For the mirror object, this region is the transformed region
052: // (the region of the original bounding leaf object transformed
053: // by the cache transform)
054: Bounds transformedRegion = null;
055:
056: BoundingLeafRetained mirrorBoundingLeaf;
057:
058: // A list of Objects that refer, directly or indirectly, to this
059: // bounding leaf object
060: ArrayList users = new ArrayList();
061:
062: // Target threads to be notified when light changes
063: int targetThreads = J3dThread.UPDATE_RENDERING_ENVIRONMENT
064: | J3dThread.UPDATE_RENDER;
065:
066: // Target threads for tranform change
067: int transformTargetThreads = J3dThread.UPDATE_RENDERING_ENVIRONMENT
068: | J3dThread.UPDATE_GEOMETRY;
069:
070: BoundingLeafRetained() {
071: this .nodeType = NodeRetained.BOUNDINGLEAF;
072: }
073:
074: void createBoundingLeaf() {
075: this .nodeType = NodeRetained.BOUNDINGLEAF;
076: mirrorBoundingLeaf = new BoundingLeafRetained();
077: }
078:
079: /**
080: * Initialize the bounding region
081: */
082: void initRegion(Bounds region) {
083: if (region != null) {
084: this .region = (Bounds) region.clone();
085: } else {
086: this .region = null;
087: }
088: if (staticTransform != null) {
089: this .region.transform(staticTransform.transform);
090: }
091: }
092:
093: /**
094: * Set the bounding region
095: */
096: void setRegion(Bounds region) {
097: initRegion(region);
098: J3dMessage createMessage = new J3dMessage();
099: createMessage.threads = mirrorBoundingLeaf.targetThreads;
100: createMessage.type = J3dMessage.BOUNDINGLEAF_CHANGED;
101: createMessage.universe = universe;
102: createMessage.args[0] = this ;
103: createMessage.args[1] = REGION_CHANGED_MESSAGE;
104: if (region != null) {
105: createMessage.args[2] = (Bounds) (region.clone());
106: } else {
107: createMessage.args[2] = null;
108: }
109: createMessage.args[3] = mirrorBoundingLeaf.users.toArray();
110: VirtualUniverse.mc.processMessage(createMessage);
111: }
112:
113: /**
114: * Get the bounding region
115: */
116: Bounds getRegion() {
117: Bounds b = null;
118: if (this .region != null) {
119: b = (Bounds) this .region.clone();
120: if (staticTransform != null) {
121: Transform3D invTransform = staticTransform
122: .getInvTransform();
123: b.transform(invTransform);
124: }
125: }
126: return b;
127: }
128:
129: void setLive(SetLiveState s) {
130: super .doSetLive(s);
131:
132: if (inBackgroundGroup) {
133: throw new IllegalSceneGraphException(J3dI18N
134: .getString("BoundingLeafRetained0"));
135: }
136:
137: if (inSharedGroup) {
138: throw new IllegalSharingException(J3dI18N
139: .getString("BoundingLeafRetained1"));
140: }
141:
142: if (s.transformTargets != null && s.transformTargets[0] != null) {
143: s.transformTargets[0].addNode(mirrorBoundingLeaf,
144: Targets.BLN_TARGETS);
145: s.notifyThreads |= J3dThread.UPDATE_TRANSFORM;
146: }
147: mirrorBoundingLeaf.localToVworld = new Transform3D[1][];
148: mirrorBoundingLeaf.localToVworldIndex = new int[1][];
149: mirrorBoundingLeaf.localToVworld[0] = this .localToVworld[0];
150: mirrorBoundingLeaf.localToVworldIndex[0] = this .localToVworldIndex[0];
151: mirrorBoundingLeaf.parent = parent;
152: if (region != null) {
153: mirrorBoundingLeaf.region = (Bounds) region.clone();
154: mirrorBoundingLeaf.transformedRegion = (Bounds) region
155: .clone();
156: mirrorBoundingLeaf.transformedRegion
157: .transform(mirrorBoundingLeaf
158: .getCurrentLocalToVworld());
159: } else {
160: mirrorBoundingLeaf.region = null;
161: mirrorBoundingLeaf.transformedRegion = null;
162: }
163: // process switch leaf
164: if (s.switchTargets != null && s.switchTargets[0] != null) {
165: s.switchTargets[0].addNode(mirrorBoundingLeaf,
166: Targets.BLN_TARGETS);
167: }
168: mirrorBoundingLeaf.switchState = (SwitchState) s.switchStates
169: .get(0);
170: super .markAsLive();
171: }
172:
173: /** Update the "component" field of the mirror object with the
174: * given "value"
175: */
176: synchronized void updateImmediateMirrorObject(Object[] objs) {
177:
178: int component = ((Integer) objs[1]).intValue();
179: Bounds b = ((Bounds) objs[2]);
180: Transform3D t;
181:
182: if ((component & REGION_CHANGED) != 0) {
183: mirrorBoundingLeaf.region = b;
184: if (b != null) {
185: mirrorBoundingLeaf.transformedRegion = (Bounds) b
186: .clone();
187: t = mirrorBoundingLeaf.getCurrentLocalToVworld();
188: mirrorBoundingLeaf.transformedRegion.transform(b, t);
189: } else {
190: mirrorBoundingLeaf.transformedRegion = null;
191: }
192:
193: }
194: }
195:
196: /**
197: * Add a user to the list of users.
198: * There is no if (node.source.isLive()) check since
199: * mirror objects are the users of the mirror bounding leaf
200: * and they do not have a source.
201: */
202: synchronized void addUser(LeafRetained node) {
203: users.add(node);
204: if (node.nodeType == NodeRetained.BACKGROUND
205: || node.nodeType == NodeRetained.CLIP
206: || node.nodeType == NodeRetained.ALTERNATEAPPEARANCE
207: || node instanceof FogRetained
208: || node instanceof LightRetained) {
209: transformTargetThreads |= J3dThread.UPDATE_RENDER;
210: } else if (node instanceof BehaviorRetained) {
211: transformTargetThreads |= J3dThread.UPDATE_BEHAVIOR;
212: targetThreads |= J3dThread.UPDATE_BEHAVIOR;
213: } else if (node instanceof SoundRetained
214: || node.nodeType == NodeRetained.SOUNDSCAPE) {
215: transformTargetThreads |= J3dThread.UPDATE_SOUND;
216: }
217:
218: }
219:
220: /**
221: * Remove user from the list of users.
222: * There is no if (node.source.isLive()) check since
223: * mirror objects are the users of the mirror bounding leaf
224: * and they do not have a source.
225: */
226: synchronized void removeUser(LeafRetained u) {
227: int i;
228: users.remove(users.indexOf(u));
229: // For now reconstruct the transform target threads from scratch
230: transformTargetThreads = J3dThread.UPDATE_RENDERING_ENVIRONMENT;
231: targetThreads = J3dThread.UPDATE_RENDERING_ENVIRONMENT
232: | J3dThread.UPDATE_RENDER;
233:
234: for (i = 0; i < users.size(); i++) {
235: LeafRetained node = (LeafRetained) users.get(i);
236: if (node.nodeType == NodeRetained.BACKGROUND
237: || node.nodeType == NodeRetained.CLIP
238: || node.nodeType == NodeRetained.ALTERNATEAPPEARANCE
239: || node instanceof FogRetained
240: || node instanceof LightRetained) {
241: transformTargetThreads |= J3dThread.UPDATE_RENDER;
242: } else if (node.nodeType == NodeRetained.BEHAVIOR) {
243: transformTargetThreads |= J3dThread.UPDATE_BEHAVIOR;
244: targetThreads |= J3dThread.UPDATE_BEHAVIOR;
245: } else if (node instanceof SoundRetained
246: || node.nodeType == NodeRetained.SOUNDSCAPE) {
247: transformTargetThreads |= J3dThread.UPDATE_SOUND;
248: }
249: }
250: }
251:
252: // This function is called on the mirror bounding leaf
253: void updateImmediateTransformChange() {
254: Transform3D t;
255: t = getCurrentLocalToVworld();
256: if (region != null) {
257: transformedRegion.transform(region, t);
258: }
259: }
260:
261: void clearLive(SetLiveState s) {
262: super .clearLive();
263: if (s.switchTargets != null && s.switchTargets[0] != null) {
264: s.switchTargets[0].addNode(mirrorBoundingLeaf,
265: Targets.BLN_TARGETS);
266: }
267: if (s.transformTargets != null && s.transformTargets[0] != null) {
268: s.transformTargets[0].addNode(mirrorBoundingLeaf,
269: Targets.BLN_TARGETS);
270: s.notifyThreads |= J3dThread.UPDATE_TRANSFORM;
271: }
272: }
273:
274: void mergeTransform(TransformGroupRetained xform) {
275: super.mergeTransform(xform);
276: region.transform(xform.transform);
277: }
278:
279: }
|