001: /*
002: * $RCSfile: SpotLight.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:31 $
029: * $State: Exp $
030: */
031:
032: package javax.media.j3d;
033:
034: import javax.vecmath.Color3f;
035: import javax.vecmath.Point3f;
036: import javax.vecmath.Vector3f;
037:
038: /**
039: * The SpotLight object specifies an attenuated light source at a
040: * fixed point in space that radiates light in a specified direction
041: * from the light source. A SpotLight has the same attributes as a
042: * PointLight node, with the addition of the following:<P>
043: * <UL>
044: * <LI>Direction - The axis of the cone of light. The default
045: * direction is (0.0, 0.0, -1.0). The spot light direction is
046: * significant only when the spread angle is not PI radians
047: * (which it is by default).</LI>
048: * <P>
049: * <LI>Spread angle - The angle in radians between the direction axis
050: * and a ray along the edge of the cone. Note that the angle of the
051: * cone at the apex is then twice this value. The range of values
052: * is [0.0,PI/2] radians, with a special value of PI radians. Values
053: * lower than 0 are clamped to 0 and values over PI/2 are clamped
054: * to PI. The default spread angle is PI radians. </LI>
055: * <P>
056: * <LI>Concentration - Specifies how quickly the light intensity
057: * attenuates as a function of the angle of radiation as measured from
058: * the direction of radiation. The light's intensity is highest at the
059: * center of the cone and is attenuated toward the edges of the cone
060: * by the cosine of the angle between the direction of the light
061: * and the direction from the light to the object being lit, raised
062: * to the power of the spot concentration exponent.
063: * The higher the concentration value, the more focused the light
064: * source. The range of values is [0.0,128.0]. The default
065: * concentration is 0.0, which provides uniform light
066: * distribution.</LI><P>
067: * </UL>
068: * A spot light contributes to diffuse and specular reflections, which
069: * depend on the orientation and position of an object's surface.
070: * A spot light does not contribute to ambient reflections.
071: */
072:
073: public class SpotLight extends PointLight {
074: /**
075: * Specifies that the Node allows writing to its spot lights spread angle
076: * information.
077: */
078: public static final int ALLOW_SPREAD_ANGLE_WRITE = CapabilityBits.SPOT_LIGHT_ALLOW_SPREAD_ANGLE_WRITE;
079:
080: /**
081: * Specifies that the Node allows reading its spot lights spread angle
082: * information.
083: */
084: public static final int ALLOW_SPREAD_ANGLE_READ = CapabilityBits.SPOT_LIGHT_ALLOW_SPREAD_ANGLE_READ;
085:
086: /**
087: * Specifies that the Node allows writing to its spot lights concentration
088: * information.
089: */
090: public static final int ALLOW_CONCENTRATION_WRITE = CapabilityBits.SPOT_LIGHT_ALLOW_CONCENTRATION_WRITE;
091:
092: /**
093: * Specifies that the Node allows reading its spot lights concentration
094: * information.
095: */
096: public static final int ALLOW_CONCENTRATION_READ = CapabilityBits.SPOT_LIGHT_ALLOW_CONCENTRATION_READ;
097:
098: /**
099: * Specifies that the Node allows writing to its spot lights direction
100: * information.
101: */
102: public static final int ALLOW_DIRECTION_WRITE = CapabilityBits.SPOT_LIGHT_ALLOW_DIRECTION_WRITE;
103:
104: /**
105: * Specifies that the Node allows reading its spot lights direction
106: * information.
107: */
108: public static final int ALLOW_DIRECTION_READ = CapabilityBits.SPOT_LIGHT_ALLOW_DIRECTION_READ;
109:
110: // Array for setting default read capabilities
111: private static final int[] readCapabilities = {
112: ALLOW_SPREAD_ANGLE_READ, ALLOW_CONCENTRATION_READ,
113: ALLOW_DIRECTION_READ };
114:
115: /**
116: * Constructs a SpotLight node with default parameters.
117: * The default values are as follows:
118: * <ul>
119: * direction : (0,0,-1)<br>
120: * spread angle : <i>PI</i> radians<br>
121: * concentration : 0.0<br>
122: * </ul>
123: */
124: public SpotLight() {
125: // set default read capabilities
126: setDefaultReadCapabilities(readCapabilities);
127: }
128:
129: /**
130: * Constructs and initializes a SpotLight node using the
131: * specified parameters.
132: * @param color the color of the light source
133: * @param position the position of the light in three-space
134: * @param attenuation the attenuation (constant, linear, quadratic)
135: * of the light
136: * @param direction the direction of the light
137: * @param spreadAngle the spread angle of the light
138: * @param concentration the concentration of the light
139: */
140: public SpotLight(Color3f color, Point3f position,
141: Point3f attenuation, Vector3f direction, float spreadAngle,
142: float concentration) {
143: super (color, position, attenuation);
144:
145: // set default read capabilities
146: setDefaultReadCapabilities(readCapabilities);
147:
148: ((SpotLightRetained) this .retained).initDirection(direction);
149: ((SpotLightRetained) this .retained)
150: .initSpreadAngle(spreadAngle);
151: ((SpotLightRetained) this .retained)
152: .initConcentration(concentration);
153: }
154:
155: /**
156: * Constructs and initializes a SpotLight node using the
157: * specified parameters.
158: * @param lightOn flag indicating whether this light is on or off
159: * @param color the color of the light source
160: * @param position the position of the light in three-space
161: * @param attenuation the attenuation (constant, linear, quadratic) of the light
162: * @param direction the direction of the light
163: * @param spreadAngle the spread angle of the light
164: * @param concentration the concentration of the light
165: */
166: public SpotLight(boolean lightOn, Color3f color, Point3f position,
167: Point3f attenuation, Vector3f direction, float spreadAngle,
168: float concentration) {
169: super (lightOn, color, position, attenuation);
170:
171: // set default read capabilities
172: setDefaultReadCapabilities(readCapabilities);
173:
174: ((SpotLightRetained) this .retained).initDirection(direction);
175: ((SpotLightRetained) this .retained)
176: .initSpreadAngle(spreadAngle);
177: ((SpotLightRetained) this .retained)
178: .initConcentration(concentration);
179: }
180:
181: /**
182: * Creates the retained mode SpotLightRetained object that this
183: * SpotLight component object will point to.
184: */
185: void createRetained() {
186: this .retained = new SpotLightRetained();
187: this .retained.setSource(this );
188: }
189:
190: /**
191: * Sets spot light spread angle.
192: * @param spreadAngle the new spread angle for spot light
193: * @exception CapabilityNotSetException if appropriate capability is
194: * not set and this object is part of live or compiled scene graph.
195: */
196: public void setSpreadAngle(float spreadAngle) {
197: if (isLiveOrCompiled())
198: if (!this .getCapability(ALLOW_SPREAD_ANGLE_WRITE))
199: throw new CapabilityNotSetException(J3dI18N
200: .getString("SpotLight0"));
201:
202: if (isLive())
203: ((SpotLightRetained) this .retained)
204: .setSpreadAngle(spreadAngle);
205: else
206: ((SpotLightRetained) this .retained)
207: .initSpreadAngle(spreadAngle);
208: }
209:
210: /**
211: * Gets spot light spread angle.
212: * @return the new spread angle for spot light. The value returned
213: * is the clamped value.
214: * @exception CapabilityNotSetException if appropriate capability is
215: * not set and this object is part of live or compiled scene graph
216: */
217: public float getSpreadAngle() {
218: if (isLiveOrCompiled())
219: if (!this .getCapability(ALLOW_SPREAD_ANGLE_READ))
220: throw new CapabilityNotSetException(J3dI18N
221: .getString("SpotLight1"));
222:
223: return ((SpotLightRetained) this .retained).getSpreadAngle();
224: }
225:
226: /**
227: * Sets spot light concentration.
228: * @param concentration the new concentration for spot light
229: * @exception CapabilityNotSetException if appropriate capability is
230: * not set and this object is part of live or compiled scene graph
231: */
232: public void setConcentration(float concentration) {
233: if (isLiveOrCompiled())
234: if (!this .getCapability(ALLOW_CONCENTRATION_WRITE))
235: throw new CapabilityNotSetException(J3dI18N
236: .getString("SpotLight2"));
237:
238: if (isLive())
239: ((SpotLightRetained) this .retained)
240: .setConcentration(concentration);
241: else
242: ((SpotLightRetained) this .retained)
243: .initConcentration(concentration);
244: }
245:
246: /**
247: * Gets spot light concentration.
248: * @return the new concentration for spot light
249: * @exception CapabilityNotSetException if appropriate capability is
250: * not set and this object is part of live or compiled scene graph
251: */
252: public float getConcentration() {
253: if (isLiveOrCompiled())
254: if (!this .getCapability(ALLOW_CONCENTRATION_READ))
255: throw new CapabilityNotSetException(J3dI18N
256: .getString("SpotLight3"));
257: return ((SpotLightRetained) this .retained).getConcentration();
258: }
259:
260: /**
261: * Sets light direction.
262: * @param x the new X direction
263: * @param y the new Y direction
264: * @param z the new Z direction
265: * @exception CapabilityNotSetException if appropriate capability is
266: * not set and this object is part of live or compiled scene graph
267: */
268: public void setDirection(float x, float y, float z) {
269: if (isLiveOrCompiled())
270: if (!this .getCapability(ALLOW_DIRECTION_WRITE))
271: throw new CapabilityNotSetException(J3dI18N
272: .getString("SpotLight4"));
273:
274: if (isLive())
275: ((SpotLightRetained) this .retained).setDirection(x, y, z);
276: else
277: ((SpotLightRetained) this .retained).initDirection(x, y, z);
278: }
279:
280: /**
281: * Sets this Light's current direction and places it in the parameter specified.
282: * @param direction the vector that will receive this node's direction
283: * @exception CapabilityNotSetException if appropriate capability is
284: * not set and this object is part of live or compiled scene graph
285: */
286: public void setDirection(Vector3f direction) {
287: if (isLiveOrCompiled())
288: if (!this .getCapability(ALLOW_DIRECTION_WRITE))
289: throw new CapabilityNotSetException(J3dI18N
290: .getString("SpotLight4"));
291:
292: if (isLive())
293: ((SpotLightRetained) this .retained).setDirection(direction);
294: else
295: ((SpotLightRetained) this .retained)
296: .initDirection(direction);
297: }
298:
299: /**
300: * Gets this Light's current direction and places it in the
301: * parameter specified.
302: * @param direction the vector that will receive this node's direction
303: * @exception CapabilityNotSetException if appropriate capability is
304: * not set and this object is part of live or compiled scene graph
305: */
306: public void getDirection(Vector3f direction) {
307: if (isLiveOrCompiled())
308: if (!this .getCapability(ALLOW_DIRECTION_READ))
309: throw new CapabilityNotSetException(J3dI18N
310: .getString("SpotLight6"));
311: ((SpotLightRetained) this .retained).getDirection(direction);
312: }
313:
314: /**
315: * Used to create a new instance of the node. This routine is called
316: * by <code>cloneTree</code> to duplicate the current node.
317: * @param forceDuplicate when set to <code>true</code>, causes the
318: * <code>duplicateOnCloneTree</code> flag to be ignored. When
319: * <code>false</code>, the value of each node's
320: * <code>duplicateOnCloneTree</code> variable determines whether
321: * NodeComponent data is duplicated or copied.
322: *
323: * @see Node#cloneTree
324: * @see Node#cloneNode
325: * @see Node#duplicateNode
326: * @see NodeComponent#setDuplicateOnCloneTree
327: */
328: public Node cloneNode(boolean forceDuplicate) {
329: SpotLight s = new SpotLight();
330: s.duplicateNode(this , forceDuplicate);
331: return s;
332: }
333:
334: /**
335: * Copies all SpotLight information from
336: * <code>originalNode</code> into
337: * the current node. This method is called from the
338: * <code>cloneNode</code> method which is, in turn, called by the
339: * <code>cloneTree</code> method.<P>
340: *
341: * @param originalNode the original node to duplicate.
342: * @param forceDuplicate when set to <code>true</code>, causes the
343: * <code>duplicateOnCloneTree</code> flag to be ignored. When
344: * <code>false</code>, the value of each node's
345: * <code>duplicateOnCloneTree</code> variable determines whether
346: * NodeComponent data is duplicated or copied.
347: *
348: * @exception RestrictedAccessException if this object is part of a live
349: * or compiled scenegraph.
350: *
351: * @see Node#duplicateNode
352: * @see Node#cloneTree
353: * @see NodeComponent#setDuplicateOnCloneTree
354: */
355: void duplicateAttributes(Node originalNode, boolean forceDuplicate) {
356:
357: super .duplicateAttributes(originalNode, forceDuplicate);
358:
359: SpotLightRetained attr = (SpotLightRetained) originalNode.retained;
360: SpotLightRetained rt = (SpotLightRetained) retained;
361:
362: rt.initSpreadAngle(attr.getSpreadAngle());
363: rt.initConcentration(attr.getConcentration());
364: Vector3f v = new Vector3f();
365: attr.getDirection(v);
366: rt.initDirection(v);
367:
368: }
369: }
|