001: /*
002: * $RCSfile: ClipRetained.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 Clip leaf node defines the back, or far, clipping distance in
039: * the virtual universe. The front clipping plane is defined in the
040: * View object. If no clip node is in scope of the view platform
041: * associated with the current view, then the back clipping plane is
042: * also defined by the View.
043: * @see View
044: */
045: class ClipRetained extends LeafRetained {
046:
047: static final int BOUNDS_CHANGED = 0x00001;
048: static final int BOUNDINGLEAF_CHANGED = 0x00002;
049: static final int BACKDISTANCE_CHANGED = 0x00004;
050:
051: /**
052: * Clip's back distance
053: */
054: double backDistance = 100.0;
055:
056: /**
057: * back distance scaled to vworld
058: */
059: double backDistanceInVworld;
060:
061: /**
062: * The Boundary object defining the application region.
063: */
064: Bounds applicationRegion = null;
065:
066: /**
067: * The bounding leaf reference
068: */
069: BoundingLeafRetained boundingLeaf = null;
070:
071: /**
072: * The transformed value of the applicationRegion.
073: */
074: Bounds transformedRegion = null;
075:
076: // This is true when this object is referenced in an immediate mode context
077: boolean inImmCtx = false;
078:
079: // Target threads to be notified when light changes
080: // Note, the rendering env structure only get notified
081: // when there is a bounds related change
082: static final int targetThreads = J3dThread.UPDATE_RENDER
083: | J3dThread.UPDATE_RENDERING_ENVIRONMENT;
084:
085: // Is true, if the clip is viewScoped
086: boolean isViewScoped = false;
087:
088: /**
089: * Constructs a Clip node with a default color (black).
090: */
091: ClipRetained() {
092: this .nodeType = NodeRetained.CLIP;
093: localBounds = new BoundingBox();
094: ((BoundingBox) localBounds).setLower(1.0, 1.0, 1.0);
095: ((BoundingBox) localBounds).setUpper(-1.0, -1.0, -1.0);
096: }
097:
098: /**
099: * initializes the clip's back distance to the specified value.
100: * @param backDistance the new back clipping distance
101: */
102: final void initBackDistance(double backDistance) {
103: this .backDistance = backDistance;
104: }
105:
106: /**
107: * Sets the clip's back distance to the specified value.
108: * @param backDistance the new back clipping distance
109: */
110: final void setBackDistance(double backDistance) {
111: this .backDistance = backDistance;
112: sendMessage(BACKDISTANCE_CHANGED, new Double(backDistance),
113: null);
114: }
115:
116: /**
117: * Retrieves the clip's back distance.
118: * @return the current back clipping distance
119: */
120: final double getBackDistance() {
121: return backDistance;
122: }
123:
124: /**
125: * Initializes the Clip's application region.
126: * @param region a region that contains the Backgound's new application bounds
127: */
128: final void initApplicationBounds(Bounds region) {
129: if (region != null) {
130: applicationRegion = (Bounds) region.clone();
131: } else {
132: applicationRegion = null;
133: }
134: }
135:
136: /**
137: * Set the Clip's application region.
138: * @param region a region that contains the Clip's new application bounds
139: */
140: final void setApplicationBounds(Bounds region) {
141: initApplicationBounds(region);
142: // Don't send the message if there is a valid boundingleaf
143: if (boundingLeaf == null) {
144: sendMessage(BOUNDS_CHANGED, (region != null ? region
145: .clone() : null), null);
146: }
147: }
148:
149: /**
150: * Get the Backgound's application region.
151: * @return this Clip's application bounds information
152: */
153: final Bounds getApplicationBounds() {
154: return (applicationRegion != null ? (Bounds) applicationRegion
155: .clone() : null);
156: }
157:
158: /**
159: * Initializes the Clip's application region
160: * to the specified Leaf node.
161: */
162: void initApplicationBoundingLeaf(BoundingLeaf region) {
163: if (region != null) {
164: boundingLeaf = (BoundingLeafRetained) region.retained;
165: } else {
166: boundingLeaf = null;
167: }
168: }
169:
170: /**
171: * Set the Clip's application region to the specified Leaf node.
172: */
173: void setApplicationBoundingLeaf(BoundingLeaf region) {
174: if (boundingLeaf != null)
175: boundingLeaf.mirrorBoundingLeaf.removeUser(this );
176:
177: if (region != null) {
178: boundingLeaf = (BoundingLeafRetained) region.retained;
179: boundingLeaf.mirrorBoundingLeaf.addUser(this );
180: } else {
181: boundingLeaf = null;
182: }
183: sendMessage(BOUNDINGLEAF_CHANGED,
184: (boundingLeaf != null ? boundingLeaf.mirrorBoundingLeaf
185: : null),
186: (applicationRegion != null ? applicationRegion.clone()
187: : null));
188: }
189:
190: /**
191: * Get the Clip's application region
192: */
193: BoundingLeaf getApplicationBoundingLeaf() {
194: return (boundingLeaf != null ? (BoundingLeaf) boundingLeaf.source
195: : null);
196: }
197:
198: /**
199: * This sets the immedate mode context flag
200: */
201: void setInImmCtx(boolean inCtx) {
202: inImmCtx = inCtx;
203: }
204:
205: /**
206: * This gets the immedate mode context flag
207: */
208: boolean getInImmCtx() {
209: return inImmCtx;
210: }
211:
212: /**
213: * This setLive routine first calls the superclass's method, then
214: * it adds itself to the list of lights
215: */
216: void setLive(SetLiveState s) {
217: if (inImmCtx) {
218: throw new IllegalSharingException(J3dI18N
219: .getString("ClipRetained0"));
220: }
221:
222: super .doSetLive(s);
223:
224: if (inBackgroundGroup) {
225: throw new IllegalSceneGraphException(J3dI18N
226: .getString("ClipRetained1"));
227: }
228:
229: if (inSharedGroup) {
230: throw new IllegalSharingException(J3dI18N
231: .getString("ClipRetained2"));
232: }
233:
234: initMirrorObject();
235: if ((s.viewScopedNodeList != null) && (s.viewLists != null)) {
236: s.viewScopedNodeList.add(this );
237: s.scopedNodesViewList.add(s.viewLists.get(0));
238: } else {
239: s.nodeList.add(this );
240: }
241: // process switch leaf
242: if (s.switchTargets != null && s.switchTargets[0] != null) {
243: s.switchTargets[0].addNode(this , Targets.ENV_TARGETS);
244: }
245: switchState = (SwitchState) s.switchStates.get(0);
246:
247: // add this node to the transform target
248: if (s.transformTargets != null && s.transformTargets[0] != null) {
249: s.transformTargets[0].addNode(this , Targets.ENV_TARGETS);
250: s.notifyThreads |= J3dThread.UPDATE_TRANSFORM;
251: }
252:
253: s.notifyThreads |= J3dThread.UPDATE_RENDERING_ENVIRONMENT
254: | J3dThread.UPDATE_RENDER;
255:
256: super .markAsLive();
257: }
258:
259: /**
260: * This clearLive routine first calls the superclass's method, then
261: * it removes itself to the list of lights
262: */
263: void clearLive(SetLiveState s) {
264: super .clearLive(s);
265: if ((s.viewScopedNodeList != null) && (s.viewLists != null)) {
266: s.viewScopedNodeList.add(this );
267: s.scopedNodesViewList.add(s.viewLists.get(0));
268: } else {
269: s.nodeList.add(this );
270: }
271: if (s.transformTargets != null && s.transformTargets[0] != null) {
272: s.transformTargets[0].addNode(this , Targets.ENV_TARGETS);
273: s.notifyThreads |= J3dThread.UPDATE_TRANSFORM;
274: }
275:
276: s.notifyThreads |= J3dThread.UPDATE_RENDERING_ENVIRONMENT
277: | J3dThread.UPDATE_RENDER;
278: if (s.switchTargets != null && s.switchTargets[0] != null) {
279: s.switchTargets[0].addNode(this , Targets.ENV_TARGETS);
280: }
281: }
282:
283: void initMirrorObject() {
284: Transform3D lastLocalToVworld = getLastLocalToVworld();
285:
286: if (boundingLeaf != null) {
287: transformedRegion = (Bounds) boundingLeaf.mirrorBoundingLeaf.transformedRegion;
288: } else { // Evaluate applicationRegion if not null
289: if (applicationRegion != null) {
290: transformedRegion = (Bounds) applicationRegion.clone();
291: transformedRegion.transform(applicationRegion,
292: lastLocalToVworld);
293: } else {
294: transformedRegion = null;
295: }
296:
297: }
298: backDistanceInVworld = backDistance
299: * lastLocalToVworld.getDistanceScale();
300: }
301:
302: // The update Object function.
303: void updateImmediateMirrorObject(Object[] objs) {
304: int component = ((Integer) objs[1]).intValue();
305: Transform3D trans;
306: Transform3D currentLocalToVworld = getCurrentLocalToVworld();
307:
308: // Bounds message only sent when boundingleaf is null
309: if ((component & BOUNDS_CHANGED) != 0) {
310: if (objs[2] != null) {
311: transformedRegion = ((Bounds) objs[2])
312: .copy(transformedRegion);
313: transformedRegion.transform(transformedRegion,
314: currentLocalToVworld);
315: } else {
316: transformedRegion = null;
317: }
318: } else if ((component & BOUNDINGLEAF_CHANGED) != 0) {
319: if (objs[2] != null) {
320: transformedRegion = ((BoundingLeafRetained) objs[2]).transformedRegion;
321: } else { // Evaluate applicationRegion if not null
322: Bounds appRegion = (Bounds) objs[3];
323: if (appRegion != null) {
324: transformedRegion = ((Bounds) appRegion)
325: .copy(transformedRegion);
326: transformedRegion.transform(appRegion,
327: currentLocalToVworld);
328: } else {
329: transformedRegion = null;
330: }
331:
332: }
333:
334: } else if ((component & BACKDISTANCE_CHANGED) != 0) {
335: backDistanceInVworld = ((Double) objs[2]).doubleValue()
336: * currentLocalToVworld.getDistanceScale();
337: }
338: }
339:
340: /** Note: This routine will only be called on
341: * the mirror object - will update the object's
342: * cached region and transformed region
343: */
344:
345: void updateBoundingLeaf() {
346: if (boundingLeaf != null
347: && boundingLeaf.mirrorBoundingLeaf.switchState.currentSwitchOn) {
348: transformedRegion = boundingLeaf.mirrorBoundingLeaf.transformedRegion;
349: } else { // Evaluate applicationRegion if not null
350: if (applicationRegion != null) {
351: transformedRegion = applicationRegion
352: .copy(transformedRegion);
353: transformedRegion.transform(applicationRegion,
354: getCurrentLocalToVworld());
355: } else {
356: transformedRegion = null;
357: }
358: }
359: }
360:
361: void updateImmediateTransformChange() {
362: // If bounding leaf is null, tranform the bounds object
363: if (boundingLeaf == null) {
364: if (applicationRegion != null) {
365: transformedRegion = (Bounds) applicationRegion.clone();
366: transformedRegion.transform(applicationRegion,
367: getCurrentLocalToVworld());
368: }
369: }
370: }
371:
372: final void sendMessage(int attrMask, Object attr, Object attr2) {
373: J3dMessage createMessage = new J3dMessage();
374: createMessage.threads = targetThreads;
375: createMessage.type = J3dMessage.CLIP_CHANGED;
376: createMessage.universe = universe;
377: createMessage.args[0] = this ;
378: createMessage.args[1] = new Integer(attrMask);
379: createMessage.args[2] = attr;
380: createMessage.args[3] = attr2;
381: VirtualUniverse.mc.processMessage(createMessage);
382: }
383:
384: void mergeTransform(TransformGroupRetained xform) {
385: super .mergeTransform(xform);
386: if (applicationRegion != null) {
387: applicationRegion.transform(xform.transform);
388: }
389: }
390:
391: void getMirrorObjects(ArrayList leafList, HashKey key) {
392: leafList.add(this);
393: }
394: }
|