001: /*
002: * $RCSfile: PointSound.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:28 $
029: * $State: Exp $
030: */
031:
032: package javax.media.j3d;
033:
034: import javax.vecmath.Point2f;
035: import javax.vecmath.Point3f;
036:
037: /**
038: * The PointSound node (a sub-class of the Sound node) defines a spatially
039: * located sound source whose waves radiate uniformly in all directions from
040: * a given location in space. It has the same attributes as a Sound object
041: * with the addition of a location and the specification of distance-based
042: * gain attenuation for listener positions between an array of distances.
043: *<P>
044: * A sound's amplitude is attenuated based on the distance between the listener
045: * and the sound source position. A piecewise linear curve (defined in terms of
046: * pairs of distance and gain scale factor) specifies the gain scale factor slope.
047: *
048: * The PointSound's location and attenuation distances are defined in the local
049: * coordinate system of the node.
050: *<P>
051: * Distance Gain Attenuation
052: * <UL>
053: * Associated with distances from the listener to the sound source via an
054: * array of (distance, gain-scale-factor) pairs. The gain scale factor
055: * applied to the sound source is the linear interpolated gain value between
056: * the distance value range that includes the current distance from
057: * the listener to the sound source. If the distance from the listener to
058: * the sound source is less than the first distance in the array, the first
059: * gain scale factor is applied to the sound source. This creates a
060: * spherical region around the listener within which all sound gain is
061: * uniformly scaled by the first gain in the array. If the distance from
062: * the listener to the sound source is greater than the last distance in
063: * the array, the last gain scale factor is applied to the sound source.
064: *<P>
065: * Distance elements in this array of Point2f is a monotonically-increasing
066: * set of floating point numbers measured from the location of the sound
067: * source. Gain scale factors elements in this list of pairs can be any
068: * positive floating point numbers. While for most applications this list
069: * of gain scale factors will usually be monotonically-decreasing, they
070: * do not have to be.
071: * If this
072: * is not set, no distance gain attenuation is performed (equivalent to
073: * using a distance gain of 1.0 for all distances).
074: *<P>
075: * getDistanceGainLength method returns the length of the distance gain
076: * attenuation arrays. Arrays passed into getDistanceGain methods should all
077: * be at least this size.
078: *<P>
079: * There are two methods for getDistanceGain, one returning an array of
080: * points, the other returning separate arrays for each attenuation
081: * component.</UL>
082: */
083:
084: public class PointSound extends Sound {
085: // Constants
086: //
087: // These flags, when enabled using the setCapability method, allow an
088: // application to invoke methods that respectively read and write the position
089: // and the distance gain array. These capability flags are enforced only when
090: // the node is part of a live or compiled scene graph
091:
092: /**
093: * Specifies that this node allows access to its object's position
094: * information.
095: */
096: public static final int ALLOW_POSITION_READ = CapabilityBits.POINT_SOUND_ALLOW_POSITION_READ;
097:
098: /**
099: * Specifies that this node allows writing to its object's position
100: * information.
101: */
102: public static final int ALLOW_POSITION_WRITE = CapabilityBits.POINT_SOUND_ALLOW_POSITION_WRITE;
103:
104: /**
105: * Specifies that this node allows access to its object's distance
106: * gain attenuation information.
107: */
108: public static final int ALLOW_DISTANCE_GAIN_READ = CapabilityBits.POINT_SOUND_ALLOW_DISTANCE_GAIN_READ;
109:
110: /**
111: * Specifies that this node allows writing to its object's distance
112: * gain attenuation information.
113: */
114: public static final int ALLOW_DISTANCE_GAIN_WRITE = CapabilityBits.POINT_SOUND_ALLOW_DISTANCE_GAIN_WRITE;
115:
116: // Array for setting default read capabilities
117: private static final int[] readCapabilities = {
118: ALLOW_POSITION_READ, ALLOW_DISTANCE_GAIN_READ };
119:
120: /**
121: * Constructs and initializes a new PointSound node using default
122: * parameters. The following default values are used:
123: * <ul>
124: * position vector: (0.0, 0.0, 0.0)<br>
125: * Back attenuation: null<br>
126: * distance gain attenuation: null (no attenuation performed)<br>
127: * </ul>
128: */
129: public PointSound() {
130: // Uses default values defined for Sound and PointSound nodes
131: super ();
132: // set default read capabilities
133: setDefaultReadCapabilities(readCapabilities);
134:
135: }
136:
137: /**
138: * Constructs a PointSound node object using only the provided parameter
139: * values for sound data, sample gain, and position. The remaining fields
140: * are set to the above default values. This form uses a point as input for
141: * its position.
142: * @param soundData sound data associated with this sound source node
143: * @param initialGain amplitude scale factor applied to sound source
144: * @param position 3D location of source
145: */
146: public PointSound(MediaContainer soundData, float initialGain,
147: Point3f position) {
148: super (soundData, initialGain);
149:
150: // set default read capabilities
151: setDefaultReadCapabilities(readCapabilities);
152:
153: ((PointSoundRetained) this .retained).setPosition(position);
154: }
155:
156: /**
157: * Constructs a PointSound node object using only the provided parameter
158: * values for sound data, sample gain, and position. The remaining fields
159: * are set to to the above default values. This form uses individual float
160: * parameters for the elements of the position point.
161: * @param soundData sound data associated with this sound source node
162: * @param initialGain amplitude scale factor applied to sound source data
163: * @param posX x coordinate of location of source
164: * @param posY y coordinate of location of source
165: * @param posZ z coordinate of location of source
166: */
167: public PointSound(MediaContainer soundData, float initialGain,
168: float posX, float posY, float posZ) {
169: super (soundData, initialGain);
170:
171: // set default read capabilities
172: setDefaultReadCapabilities(readCapabilities);
173:
174: ((PointSoundRetained) this .retained).setPosition(posX, posY,
175: posZ);
176: }
177:
178: // The next four constructors fill all this classes fields with the provided
179: // arguments values.
180: // See the header for the setDistanceGain method for details on how the
181: // those arrays are interpreted.
182:
183: /**
184: * Construct a PointSound object accepting Point3f as input for the position
185: * and accepting an array of Point2f for the distance attenuation values
186: * where each pair in the array contains a distance and a gain scale factor.
187: * @param soundData sound data associated with this sound source node
188: * @param initialGain amplitude scale factor applied to sound source
189: * @param loopCount number of times loop is looped
190: * @param release flag denoting playing sound data to end
191: * @param continuous denotes that sound silently plays when disabled
192: * @param enable sound switched on/off
193: * @param region scheduling bounds
194: * @param priority playback ranking value
195: * @param position 3D location of source
196: * @param distanceGain array of (distance,gain) pairs controling attenuation
197: */
198: public PointSound(MediaContainer soundData, float initialGain,
199: int loopCount, boolean release, boolean continuous,
200: boolean enable, Bounds region, float priority,
201: Point3f position, Point2f[] distanceGain) {
202:
203: super (soundData, initialGain, loopCount, release, continuous,
204: enable, region, priority);
205:
206: // set default read capabilities
207: setDefaultReadCapabilities(readCapabilities);
208:
209: ((PointSoundRetained) this .retained).setPosition(position);
210: ((PointSoundRetained) this .retained)
211: .setDistanceGain(distanceGain);
212: }
213:
214: /**
215: * Construct a PointSound object accepting individual float parameters for
216: * the elements of the position point, and accepting an array of Point2f for
217: * the distance attenuation values where each pair in the array contains a
218: * distance and a gain scale factor.
219: * @param soundData sound data associated with this sound source node
220: * @param initialGain amplitude scale factor applied to sound source
221: * @param loopCount number of times loop is looped
222: * @param release flag denoting playing sound to end
223: * @param continuous denotes that sound silently plays when disabled
224: * @param enable sound switched on/off
225: * @param region scheduling bounds
226: * @param priority playback ranking value
227: * @param posX x coordinate of location of source
228: * @param posY y coordinate of location of source
229: * @param posZ z coordinate of location of source
230: * @param distanceGain array of (distance,gain) pairs controling attenuation
231: */
232: public PointSound(MediaContainer soundData, float initialGain,
233: int loopCount, boolean release, boolean continuous,
234: boolean enable, Bounds region, float priority, float posX,
235: float posY, float posZ, Point2f[] distanceGain) {
236:
237: super (soundData, initialGain, loopCount, release, continuous,
238: enable, region, priority);
239:
240: // set default read capabilities
241: setDefaultReadCapabilities(readCapabilities);
242:
243: ((PointSoundRetained) this .retained).setPosition(posX, posY,
244: posZ);
245: ((PointSoundRetained) this .retained)
246: .setDistanceGain(distanceGain);
247: }
248:
249: /**
250: * Construct a PointSound object accepting points as input for the position.
251: * and accepting separate arrays for the distance and gain scale factors
252: * components of distance attenuation.
253: * @param soundData sound data associated with this sound source node
254: * @param initialGain amplitude scale factor applied to sound source
255: * @param loopCount number of times loop is looped
256: * @param release flag denoting playing sound data to end
257: * @param continuous denotes that sound silently plays when disabled
258: * @param enable sound switched on/off
259: * @param region scheduling bounds
260: * @param priority playback ranking value
261: * @param position 3D location of source
262: * @param attenuationDistance array of distance values used for attenuation
263: * @param attenuationGain array of gain scale factors used for attenuation
264: */
265: public PointSound(MediaContainer soundData, float initialGain,
266: int loopCount, boolean release, boolean continuous,
267: boolean enable, Bounds region, float priority,
268: Point3f position, float[] attenuationDistance,
269: float[] attenuationGain) {
270:
271: super (soundData, initialGain, loopCount, release, continuous,
272: enable, region, priority);
273:
274: // set default read capabilities
275: setDefaultReadCapabilities(readCapabilities);
276:
277: ((PointSoundRetained) this .retained).setPosition(position);
278: ((PointSoundRetained) this .retained).setDistanceGain(
279: attenuationDistance, attenuationGain);
280: }
281:
282: /**
283: * Construct a PointSound object accepting individual float parameters for
284: * the elements of the position points, and accepting separate arrays for
285: * the distance and gain scale factors components of distance attenuation.
286: * @param soundData sound data associated with this sound source node
287: * @param initialGain amplitude scale factor applied to sound source
288: * @param loopCount number of times loop is looped
289: * @param release flag denoting playing sound to end
290: * @param continuous denotes that sound silently plays when disabled
291: * @param enable sound switched on/off
292: * @param region scheduling bounds
293: * @param priority playback ranking value
294: * @param posX x coordinate of location of source
295: * @param posY y coordinate of location of source
296: * @param posZ z coordinate of location of source
297: * @param attenuationDistance array of distance values used for attenuation
298: * @param attenuationGain array of gain scale factors used for attenuation
299: */
300: public PointSound(MediaContainer soundData, float initialGain,
301: int loopCount, boolean release, boolean continuous,
302: boolean enable, Bounds region, float priority, float posX,
303: float posY, float posZ, float[] attenuationDistance,
304: float[] attenuationGain) {
305:
306: super (soundData, initialGain, loopCount, release, continuous,
307: enable, region, priority);
308:
309: // set default read capabilities
310: setDefaultReadCapabilities(readCapabilities);
311:
312: ((PointSoundRetained) this .retained).setPosition(posX, posY,
313: posZ);
314: ((PointSoundRetained) this .retained).setDistanceGain(
315: attenuationDistance, attenuationGain);
316: }
317:
318: /**
319: * Creates the retained mode PointSoundRetained object that this
320: * PointSound object will point to.
321: */
322: void createRetained() {
323: this .retained = new PointSoundRetained();
324: this .retained.setSource(this );
325: }
326:
327: /**
328: * Sets this sound's location from the vector provided.
329: * @param position the new location
330: * @exception CapabilityNotSetException if appropriate capability is
331: * not set and this object is part of live or compiled scene graph
332: */
333: public void setPosition(Point3f position) {
334: if (isLiveOrCompiled())
335: if (!this .getCapability(ALLOW_POSITION_WRITE))
336: throw new CapabilityNotSetException(J3dI18N
337: .getString("PointSound0"));
338:
339: ((PointSoundRetained) this .retained).setPosition(position);
340: }
341:
342: /**
343: * Sets this sound's position from the three values provided.
344: * @param x the new x position
345: * @param y the new y position
346: * @param z the new z position
347: * @exception CapabilityNotSetException if appropriate capability is
348: * not set and this object is part of live or compiled scene graph
349: */
350: public void setPosition(float x, float y, float z) {
351: if (isLiveOrCompiled())
352: if (!this .getCapability(ALLOW_POSITION_WRITE))
353: throw new CapabilityNotSetException(J3dI18N
354: .getString("PointSound0"));
355:
356: ((PointSoundRetained) this .retained).setPosition(x, y, z);
357: }
358:
359: /**
360: * Retrieves this sound's direction and places it in the
361: * vector provided.
362: * @param position the variable to receive the direction vector
363: * @exception CapabilityNotSetException if appropriate capability is
364: * not set and this object is part of live or compiled scene graph
365: */
366: public void getPosition(Point3f position) {
367: if (isLiveOrCompiled())
368: if (!this .getCapability(ALLOW_POSITION_READ))
369: throw new CapabilityNotSetException(J3dI18N
370: .getString("PointSound2"));
371:
372: ((PointSoundRetained) this .retained).getPosition(position);
373: }
374:
375: /**
376: * Sets this sound's distance gain attenuation - where gain scale factor
377: * is applied to sound based on distance listener is from sound source.
378: * This form of setDistanceGain takes these pairs of values as an array of
379: * Point2f.
380: * @param attenuation defined by pairs of (distance,gain-scale-factor)
381: * @exception CapabilityNotSetException if appropriate capability is
382: * not set and this object is part of live or compiled scene graph
383: */
384: public void setDistanceGain(Point2f[] attenuation) {
385: if (isLiveOrCompiled())
386: if (!this .getCapability(ALLOW_DISTANCE_GAIN_WRITE))
387: throw new CapabilityNotSetException(J3dI18N
388: .getString("PointSound3"));
389:
390: ((PointSoundRetained) this .retained)
391: .setDistanceGain(attenuation);
392: }
393:
394: /**
395: * Sets this sound's distance gain attenuation as an array of Point2fs.
396: * This form of setDistanceGain accepts two separate arrays for these values.
397: * The distance and gainScale arrays should be of the same length. If the
398: * gainScale array length is greater than the distance array length, the
399: * gainScale array elements beyond the length of the distance array are
400: * ignored. If the gainScale array is shorter than the distance array, the
401: * last gainScale array value is repeated to fill an array of length equal
402: * to distance array.
403: * @param distance array of monotonically-increasing floats
404: * @param gain array of non-negative scale factors
405: * @exception CapabilityNotSetException if appropriate capability is
406: * not set and this object is part of live or compiled scene graph
407: */
408: public void setDistanceGain(float[] distance, float[] gain) {
409: if (isLiveOrCompiled())
410: if (!this .getCapability(ALLOW_DISTANCE_GAIN_WRITE))
411: throw new CapabilityNotSetException(J3dI18N
412: .getString("PointSound3"));
413:
414: ((PointSoundRetained) this .retained).setDistanceGain(distance,
415: gain);
416: }
417:
418: /**
419: * Get the length of this node's distance gain attenuation arrays.
420: * @return distance gain attenuation array length
421: * @exception CapabilityNotSetException if appropriate capability is
422: * not set and this object is part of live or compiled scene graph
423: */
424: public int getDistanceGainLength() {
425: if (isLiveOrCompiled())
426: if (!this .getCapability(ALLOW_DISTANCE_GAIN_READ))
427: throw new CapabilityNotSetException(J3dI18N
428: .getString("PointSound4"));
429:
430: return (((PointSoundRetained) this .retained)
431: .getDistanceGainLength());
432: }
433:
434: /**
435: * Gets this sound's distance attenuation. The distance attenuation
436: * pairs are copied into the specified array.
437: * The array must be large enough to hold all of the points.
438: * The individual array elements must be allocated by the caller.
439: * @param attenuation arrays containing distance attenuation pairs
440: * @exception CapabilityNotSetException if appropriate capability is
441: * not set and this object is part of live or compiled scene graph
442: */
443: public void getDistanceGain(Point2f[] attenuation) {
444: if (isLiveOrCompiled())
445: if (!this .getCapability(ALLOW_DISTANCE_GAIN_READ))
446: throw new CapabilityNotSetException(J3dI18N
447: .getString("PointSound4"));
448:
449: ((PointSoundRetained) this .retained)
450: .getDistanceGain(attenuation);
451: }
452:
453: /**
454: * Gets this sound's distance gain attenuation values in separate arrays.
455: * The arrays must be large enough to hold all of the values.
456: * @param distance array of float distance from sound source
457: * @param gain array of non-negative scale factors associated with
458: * @exception CapabilityNotSetException if appropriate capability is
459: * not set and this object is part of live or compiled scene graph
460: */
461: public void getDistanceGain(float[] distance, float[] gain) {
462: if (isLiveOrCompiled())
463: if (!this .getCapability(ALLOW_DISTANCE_GAIN_READ))
464: throw new CapabilityNotSetException(J3dI18N
465: .getString("PointSound4"));
466:
467: ((PointSoundRetained) this .retained).getDistanceGain(distance,
468: gain);
469: }
470:
471: /**
472: * Creates a new instance of the node. This routine is called
473: * by <code>cloneTree</code> to duplicate the current node.
474: * @param forceDuplicate when set to <code>true</code>, causes the
475: * <code>duplicateOnCloneTree</code> flag to be ignored. When
476: * <code>false</code>, the value of each node's
477: * <code>duplicateOnCloneTree</code> variable determines whether
478: * NodeComponent data is duplicated or copied.
479: *
480: * @see Node#cloneTree
481: * @see Node#cloneNode
482: * @see Node#duplicateNode
483: * @see NodeComponent#setDuplicateOnCloneTree
484: */
485: public Node cloneNode(boolean forceDuplicate) {
486: PointSound p = new PointSound();
487: p.duplicateNode(this , forceDuplicate);
488: return p;
489: }
490:
491: /**
492: * Copies all node information from <code>originalNode</code> into
493: * the current node. This method is called from the
494: * <code>cloneNode</code> method which is, in turn, called by the
495: * <code>cloneTree</code> method.
496: * <P>
497: * For any <code>NodeComponent</code> objects
498: * contained by the object being duplicated, each <code>NodeComponent</code>
499: * object's <code>duplicateOnCloneTree</code> value is used to determine
500: * whether the <code>NodeComponent</code> should be duplicated in the new node
501: * or if just a reference to the current node should be placed in the
502: * new node. This flag can be overridden by setting the
503: * <code>forceDuplicate</code> parameter in the <code>cloneTree</code>
504: * method to <code>true</code>.
505: * <br>
506: * NOTE: Applications should <i>not</i> call this method directly.
507: * It should only be called by the cloneNode method.
508: *
509: * @param originalNode the original node to duplicate.
510: * @param forceDuplicate when set to <code>true</code>, causes the
511: * <code>duplicateOnCloneTree</code> flag to be ignored. When
512: * <code>false</code>, the value of each node's
513: * <code>duplicateOnCloneTree</code> variable determines whether
514: * NodeComponent data is duplicated or copied.
515: * @exception ClassCastException if originalNode is not an instance of
516: * <code>PointSound</code>
517: *
518: * @see Node#cloneTree
519: * @see Node#cloneNode
520: * @see NodeComponent#setDuplicateOnCloneTree
521: */
522: public void duplicateNode(Node originalNode, boolean forceDuplicate) {
523: checkDuplicateNode(originalNode, forceDuplicate);
524: }
525:
526: /**
527: * Copies all PointSound information from
528: * <code>originalNode</code> into
529: * the current node. This method is called from the
530: * <code>cloneNode</code> method which is, in turn, called by the
531: * <code>cloneTree</code> method.<P>
532: *
533: * @param originalNode the original node to duplicate.
534: * @param forceDuplicate when set to <code>true</code>, causes the
535: * <code>duplicateOnCloneTree</code> flag to be ignored. When
536: * <code>false</code>, the value of each node's
537: * <code>duplicateOnCloneTree</code> variable determines whether
538: * NodeComponent data is duplicated or copied.
539: *
540: * @exception RestrictedAccessException if this object is part of a live
541: * or compiled scenegraph.
542: *
543: * @see Node#duplicateNode
544: * @see Node#cloneTree
545: * @see NodeComponent#setDuplicateOnCloneTree
546: */
547: void duplicateAttributes(Node originalNode, boolean forceDuplicate) {
548: super .duplicateAttributes(originalNode, forceDuplicate);
549:
550: PointSoundRetained orgRetained = (PointSoundRetained) originalNode.retained;
551: PointSoundRetained this Retained = (PointSoundRetained) this .retained;
552:
553: Point3f p = new Point3f();
554: orgRetained.getPosition(p);
555: this Retained.setPosition(p);
556:
557: int len = orgRetained.getDistanceGainLength();
558: float distance[] = new float[len];
559: float gain[] = new float[len];
560: orgRetained.getDistanceGain(distance, gain);
561: thisRetained.setDistanceGain(distance, gain);
562: }
563:
564: }
|