org.scijava.java3d.Soundscape Maven / Gradle / Ivy
/*
* Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*
*/
package org.scijava.java3d;
/**
* The Soundscape Leaf Node defines the attributes that characterize the
* listener's environment as it pertains to sound. This node defines an
* application region and an associated aural attribute component object
* that controls reverberation and atmospheric properties that affect sound
* source rendering. Multiple Soundscape nodes can be included in a single
* scene graph.
*
* The Soundscape application region, different from a Sound node's scheduling
* region, is used to select which Soundscape (and thus which aural attribute
* object) is to be applied to the sounds being rendered. This selection is
* based on the position of the ViewPlatform (i.e., the listener), not the
* position of the sound.
*
* It will be common that multiple Soundscape regions are contained within a
* scene graph. For example, two Soundscape regions within a single space the
* listener can move about: a region with a large open area on the right, and
* a smaller more constricted, less reverberant area on the left. The rever-
* beration attributes for these two regions could be set to approximate their
* physical differences so that active sounds are rendered differently depending
* on which region the listener is in.
*/
public class Soundscape extends Leaf {
// Constants
//
// These flags, when enabled using the setCapability method, allow an
// application to invoke methods that respectively read and write the
// application region and the aural attributes. These capability flags
// are enforced only when the node is part of a live or compiled scene
// graph.
/**
* For Soundscape component objects, specifies that this object
* allows read access to its application bounds
*/
public static final int
ALLOW_APPLICATION_BOUNDS_READ = CapabilityBits.SOUNDSCAPE_ALLOW_APPLICATION_BOUNDS_READ;
/**
* For Soundscape component objects, specifies that this object
* allows write access to its application bounds
*/
public static final int
ALLOW_APPLICATION_BOUNDS_WRITE = CapabilityBits.SOUNDSCAPE_ALLOW_APPLICATION_BOUNDS_WRITE;
/**
* For Soundscape component objects, specifies that this object
* allows the reading of it's aural attributes information
*/
public static final int
ALLOW_ATTRIBUTES_READ = CapabilityBits.SOUNDSCAPE_ALLOW_ATTRIBUTES_READ;
/**
* For Soundscape component objects, specifies that this object
* allows the writing of it's aural attribute information
*/
public static final int
ALLOW_ATTRIBUTES_WRITE = CapabilityBits.SOUNDSCAPE_ALLOW_ATTRIBUTES_WRITE;
// Array for setting default read capabilities
private static final int[] readCapabilities = {
ALLOW_APPLICATION_BOUNDS_READ,
ALLOW_ATTRIBUTES_READ
};
/**
* Constructs and initializes a new Sound node using following
* defaults:
*
application region: null (no active region)
* aural attributes: null (uses default aural attributes)
*/
public Soundscape() {
// Just use default values
// set default read capabilities
setDefaultReadCapabilities(readCapabilities);
}
/**
* Constructs and initializes a new Sound node using specified
* parameters
* @param region application region
* @param attributes array of aural attribute component objects
*/
public Soundscape(Bounds region,
AuralAttributes attributes) {
// set default read capabilities
setDefaultReadCapabilities(readCapabilities);
((SoundscapeRetained)this.retained).setApplicationBounds(region);
((SoundscapeRetained)this.retained).setAuralAttributes(attributes);
}
/**
* Creates the retained mode SoundscapeRetained object that this
* component object will point to.
*/
@Override
void createRetained() {
this.retained = new SoundscapeRetained();
this.retained.setSource(this);
}
/**
* Set the Soundscape's application region to the specified bounds
* specified in local coordinates of this leaf node. The aural
* attributes associated with this Soundscape are used to render
* the active sounds when this application region intersects the
* ViewPlatform's activation volume. The getApplicationBounds method
* returns a new Bounds object.
* This region is used when the application bounding leaf is null.
* @param region the bounds that contains the Soundscape's new application
* region.
* @exception CapabilityNotSetException if appropriate capability is
* not set and this object is part of live or compiled scene graph
*/
public void setApplicationBounds(Bounds region) {
if (isLiveOrCompiled())
if(!this.getCapability(ALLOW_APPLICATION_BOUNDS_WRITE))
throw new CapabilityNotSetException(J3dI18N.getString("Soundscape0"));
((SoundscapeRetained)this.retained).setApplicationBounds(region);
}
/**
* Retrieves the Soundscape node's application bounds.
* @return this Soundscape's application bounds information
* @exception CapabilityNotSetException if appropriate capability is
* not set and this object is part of live or compiled scene graph
*/
public Bounds getApplicationBounds() {
if (isLiveOrCompiled())
if(!this.getCapability(ALLOW_APPLICATION_BOUNDS_READ))
throw new CapabilityNotSetException(J3dI18N.getString("Soundscape1"));
return ((SoundscapeRetained)this.retained).getApplicationBounds();
}
/**
* Set the Soundscape's application region to the specified bounding leaf.
* When set to a value other than null, this overrides the application
* bounds object.
* @param region the bounding leaf node used to specify the Soundscape
* node's new application region.
* @exception CapabilityNotSetException if appropriate capability is
* not set and this object is part of live or compiled scene graph
*/
public void setApplicationBoundingLeaf(BoundingLeaf region) {
if (isLiveOrCompiled())
if(!this.getCapability(ALLOW_APPLICATION_BOUNDS_WRITE))
throw new CapabilityNotSetException(J3dI18N.getString("Soundscape0"));
((SoundscapeRetained)this.retained).setApplicationBoundingLeaf(region);
}
/**
* Retrieves the Soundscape node's application bounding leaf.
* @return this Soundscape's application bounding leaf information
* @exception CapabilityNotSetException if appropriate capability is
* not set and this object is part of live or compiled scene graph
*/
public BoundingLeaf getApplicationBoundingLeaf() {
if (isLiveOrCompiled())
if(!this.getCapability(ALLOW_APPLICATION_BOUNDS_READ))
throw new CapabilityNotSetException(J3dI18N.getString("Soundscape1"));
return ((SoundscapeRetained)this.retained).getApplicationBoundingLeaf();
}
/**
* Set a set of aural attributes for this Soundscape
* @param attributes aural attributes
* @exception CapabilityNotSetException if appropriate capability is
* not set and this object is part of live or compiled scene graph
*/
public void setAuralAttributes(AuralAttributes attributes) {
if (isLiveOrCompiled())
if(!this.getCapability(ALLOW_ATTRIBUTES_WRITE))
throw new CapabilityNotSetException(J3dI18N.getString("Soundscape4"));
((SoundscapeRetained)this.retained).setAuralAttributes(attributes);
}
/**
* Retrieve reference of Aural Attributes
* @return reference to aural attributes
* @exception CapabilityNotSetException if appropriate capability is
* not set and this object is part of live or compiled scene graph
*/
public AuralAttributes getAuralAttributes() {
if (isLiveOrCompiled())
if(!this.getCapability(ALLOW_ATTRIBUTES_READ))
throw new CapabilityNotSetException(J3dI18N.getString("Soundscape5"));
return ((SoundscapeRetained)this.retained).getAuralAttributes();
}
/**
* Creates a new instance of the node. This routine is called
* by cloneTree
to duplicate the current node.
* @param forceDuplicate when set to true
, causes the
* duplicateOnCloneTree
flag to be ignored. When
* false
, the value of each node's
* duplicateOnCloneTree
variable determines whether
* NodeComponent data is duplicated or copied.
*
* @see Node#cloneTree
* @see Node#cloneNode
* @see Node#duplicateNode
* @see NodeComponent#setDuplicateOnCloneTree
*/
@Override
public Node cloneNode(boolean forceDuplicate) {
Soundscape s = new Soundscape();
s.duplicateNode(this, forceDuplicate);
return s;
}
/**
* Copies all node information from originalNode
into
* the current node. This method is called from the
* cloneNode
method which is, in turn, called by the
* cloneTree
method.
*
* For any NodeComponent
objects
* contained by the object being duplicated, each NodeComponent
* object's duplicateOnCloneTree
value is used to determine
* whether the NodeComponent
should be duplicated in the new node
* or if just a reference to the current node should be placed in the
* new node. This flag can be overridden by setting the
* forceDuplicate
parameter in the cloneTree
* method to true
.
*
* NOTE: Applications should not call this method directly.
* It should only be called by the cloneNode method.
*
* @param originalNode the original node to duplicate.
* @param forceDuplicate when set to true
, causes the
* duplicateOnCloneTree
flag to be ignored. When
* false
, the value of each node's
* duplicateOnCloneTree
variable determines whether
* NodeComponent data is duplicated or copied.
* @exception ClassCastException if originalNode is not an instance of
* Soundscape
*
* @see Node#cloneTree
* @see Node#cloneNode
* @see NodeComponent#setDuplicateOnCloneTree
*/
@Override
public void duplicateNode(Node originalNode, boolean forceDuplicate) {
checkDuplicateNode(originalNode, forceDuplicate);
}
/**
* Copies all Soundscape information from
* originalNode
into
* the current node. This method is called from the
* cloneNode
method which is, in turn, called by the
* cloneTree
method.
*
* @param originalNode the original node to duplicate.
* @param forceDuplicate when set to true
, causes the
* duplicateOnCloneTree
flag to be ignored. When
* false
, the value of each node's
* duplicateOnCloneTree
variable determines whether
* NodeComponent data is duplicated or copied.
*
* @exception RestrictedAccessException if this object is part of a live
* or compiled scenegraph.
*
* @see Node#duplicateNode
* @see Node#cloneTree
* @see NodeComponent#setDuplicateOnCloneTree
*/
@Override
void duplicateAttributes(Node originalNode, boolean forceDuplicate) {
super.duplicateAttributes(originalNode, forceDuplicate);
SoundscapeRetained attr = (SoundscapeRetained) originalNode.retained;
SoundscapeRetained rt = (SoundscapeRetained) retained;
rt.setApplicationBounds(attr.getApplicationBounds());
rt.setAuralAttributes((AuralAttributes) getNodeComponent(
attr.getAuralAttributes(),
forceDuplicate,
originalNode.nodeHashtable));
// the following reference will set correctly in updateNodeReferences
rt.setApplicationBoundingLeaf(attr.getApplicationBoundingLeaf());
}
/**
* Callback used to allow a node to check if any scene graph objects
* referenced
* by that node have been duplicated via a call to cloneTree
.
* This method is called by cloneTree
after all nodes in
* the sub-graph have been duplicated. The cloned Leaf node's method
* will be called and the Leaf node can then look up any object references
* by using the getNewObjectReference
method found in the
* NodeReferenceTable
object. If a match is found, a
* reference to the corresponding object in the newly cloned sub-graph
* is returned. If no corresponding reference is found, either a
* DanglingReferenceException is thrown or a reference to the original
* object is returned depending on the value of the
* allowDanglingReferences
parameter passed in the
* cloneTree
call.
*
* NOTE: Applications should not call this method directly.
* It should only be called by the cloneTree method.
*
* @param referenceTable a NodeReferenceTableObject that contains the
* getNewObjectReference
method needed to search for
* new object instances.
* @see NodeReferenceTable
* @see Node#cloneTree
* @see DanglingReferenceException
*/
@Override
public void updateNodeReferences(NodeReferenceTable referenceTable) {
SoundscapeRetained rt = (SoundscapeRetained) retained;
BoundingLeaf bl = rt.getApplicationBoundingLeaf();
if (bl != null) {
Object o = referenceTable.getNewObjectReference(bl);
rt.setApplicationBoundingLeaf((BoundingLeaf) o);
}
}
}