/*
* Copyright 1999-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 javax.media.j3d;
import javax.vecmath.Point3f;
import javax.vecmath.Vector3f;
/**
* The OrientedShape3D leaf node is a Shape3D node that is oriented
* along a specified axis or about a specified point. It defines an
* alignment mode and a rotation point or axis. This will cause
* the local +z axis of the object to point at the viewer's eye
* position. This is done regardless of the transforms above this
* OrientedShape3D node in the scene graph. It optionally defines a
* scale value along with a constant scale enable flag that causes
* this node to be scale invariant, subject only to its scale.
*
*
* OrientedShape3D is similar in functionality to the Billboard
* behavior, but OrientedShape3D nodes will orient themselves
* correctly for each view, and they can be used within a SharedGroup.
*
*
* If the alignment mode is ROTATE_ABOUT_AXIS, then the rotation will be
* around the specified axis. If the alignment mode is
* ROTATE_ABOUT_POINT, then the rotation will be about the specified
* point, with an additional rotation to align the +y axis of the
* TransformGroup with the +y axis in the View.
*
*
* If the constant scale enable flag is set, the object will be drawn
* the same size in absolute screen coordinates (meters), regardless
* of the following: any transforms above this OrientedShape3D node in
* the scene graph, the view scale, the window scale, or the effects
* of perspective correction. This is done by scaling the geometry
* about the local origin of this node, such that 1 unit in local
* coordinates is equal to the number of meters specified by this
* node's scale value. If the constant scale enable flag is set to
* false, then the scale is not used. The default scale is 1.0
* meters.
*
*
* OrientedShape3D nodes are ideal for drawing screen-aligned text or
* for drawing roughly-symmetrical objects. A typical use might
* consist of a quadrilateral that contains a texture of a tree.
*
*
* Note that in a multiple View system, picking and interestion test
* is done with the primary View only.
*
* @see Billboard
*
* @since Java 3D 1.2
*/
public class OrientedShape3D extends Shape3D {
/**
* Specifies that rotation should be about the specified axis.
* @see #setAlignmentMode
*/
public static final int ROTATE_ABOUT_AXIS = 0;
/**
* Specifies that rotation should be about the specified point and
* that the children's Y-axis should match the view object's Y-axis.
* @see #setAlignmentMode
*/
public static final int ROTATE_ABOUT_POINT = 1;
/**
* Specifies that no rotation is done. The OrientedShape3D will
* not be aligned to the view.
* @see #setAlignmentMode
*
* @since Java 3D 1.3
*/
public static final int ROTATE_NONE = 2;
/**
* Specifies that this OrientedShape3D node
* allows reading its alignment mode information.
*/
public static final int ALLOW_MODE_READ =
CapabilityBits.ORIENTED_SHAPE3D_ALLOW_MODE_READ;
/**
* Specifies that this OrientedShape3D node
* allows writing its alignment mode information.
*/
public static final int ALLOW_MODE_WRITE =
CapabilityBits.ORIENTED_SHAPE3D_ALLOW_MODE_WRITE;
/**
* Specifies that this OrientedShape3D node
* allows reading its alignment axis information.
*/
public static final int ALLOW_AXIS_READ =
CapabilityBits.ORIENTED_SHAPE3D_ALLOW_AXIS_READ;
/**
* Specifies that this OrientedShape3D node
* allows writing its alignment axis information.
*/
public static final int ALLOW_AXIS_WRITE =
CapabilityBits.ORIENTED_SHAPE3D_ALLOW_AXIS_WRITE;
/**
* Specifies that this OrientedShape3D node
* allows reading its rotation point information.
*/
public static final int ALLOW_POINT_READ =
CapabilityBits.ORIENTED_SHAPE3D_ALLOW_POINT_READ;
/**
* Specifies that this OrientedShape3D node
* allows writing its rotation point information.
*/
public static final int ALLOW_POINT_WRITE =
CapabilityBits.ORIENTED_SHAPE3D_ALLOW_POINT_WRITE;
/**
* Specifies that this OrientedShape3D node
* allows reading its scale and constant scale enable information.
*
* @since Java 3D 1.3
*/
public static final int ALLOW_SCALE_READ =
CapabilityBits.ORIENTED_SHAPE3D_ALLOW_SCALE_READ;
/**
* Specifies that this OrientedShape3D node
* allows writing its scale and constant scale enable information.
*
* @since Java 3D 1.3
*/
public static final int ALLOW_SCALE_WRITE =
CapabilityBits.ORIENTED_SHAPE3D_ALLOW_SCALE_WRITE;
// Array for setting default read capabilities
private static final int[] readCapabilities = {
ALLOW_MODE_READ,
ALLOW_AXIS_READ,
ALLOW_POINT_READ,
ALLOW_SCALE_READ
};
/**
* Constructs an OrientedShape3D node with default parameters.
* The default values are as follows:
*
* alignment mode : ROTATE_ABOUT_AXIS
* alignment axis : Y-axis (0,1,0)
* rotation point : (0,0,1)
* constant scale enable : false
* scale : 1.0
*
*/
public OrientedShape3D() {
super();
// set default read capabilities
setDefaultReadCapabilities(readCapabilities);
}
/**
* Constructs an OrientedShape3D node with the specified geometry
* component, appearance component, mode, and axis.
* The specified axis must not be parallel to the Z
* axis--(0,0,z) for any value of z. It is not
* possible for the +Z axis to point at the viewer's eye
* position by rotating about itself. The target transform will
* be set to the identity if the axis is (0,0,z).
*
* @param geometry the geometry component with which to initialize
* this shape node
* @param appearance the appearance component of the shape node
* @param mode alignment mode, one of: ROTATE_ABOUT_AXIS,
* ROTATE_ABOUT_POINT, or ROTATE_NONE
* @param axis the ray about which the OrientedShape3D rotates
*/
public OrientedShape3D(Geometry geometry,
Appearance appearance,
int mode,
Vector3f axis) {
super(geometry, appearance);
// set default read capabilities
setDefaultReadCapabilities(readCapabilities);
((OrientedShape3DRetained)retained).initAlignmentMode(mode);
((OrientedShape3DRetained)retained).initAlignmentAxis(axis);
}
/**
* Constructs an OrientedShape3D node with the specified geometry
* component, appearance component, mode, and rotation point.
*
* @param geometry the geometry component with which to initialize
* this shape node
* @param appearance the appearance component of the shape node
* @param mode alignment mode, one of: ROTATE_ABOUT_AXIS,
* ROTATE_ABOUT_POINT, or ROTATE_NONE
* @param point the position about which the OrientedShape3D rotates
*/
public OrientedShape3D(Geometry geometry,
Appearance appearance,
int mode,
Point3f point) {
super(geometry, appearance);
// set default read capabilities
setDefaultReadCapabilities(readCapabilities);
((OrientedShape3DRetained)retained).initAlignmentMode(mode);
((OrientedShape3DRetained)retained).initRotationPoint(point);
}
/**
* Constructs an OrientedShape3D node with the specified geometry
* component, appearance component, mode, axis, constant scale
* enable flag, and scale
* The specified axis must not be parallel to the Z
* axis--(0,0,z) for any value of z. It is not
* possible for the +Z axis to point at the viewer's eye
* position by rotating about itself. The target transform will
* be set to the identity if the axis is (0,0,z).
*
* @param geometry the geometry component with which to initialize
* this shape node
* @param appearance the appearance component of the shape node
* @param mode alignment mode, one of: ROTATE_ABOUT_AXIS,
* ROTATE_ABOUT_POINT, or ROTATE_NONE
* @param axis the ray about which the OrientedShape3D rotates
* @param constantScaleEnable a flag indicating whether to enable
* constant scale
* @param scale scale value used when constant scale is enabled
*
* @since Java 3D 1.3
*/
public OrientedShape3D(Geometry geometry,
Appearance appearance,
int mode,
Vector3f axis,
boolean constantScaleEnable,
double scale) {
super(geometry, appearance);
// set default read capabilities
setDefaultReadCapabilities(readCapabilities);
((OrientedShape3DRetained)retained).initAlignmentMode(mode);
((OrientedShape3DRetained)retained).initAlignmentAxis(axis);
((OrientedShape3DRetained)retained).
initConstantScaleEnable(constantScaleEnable);
((OrientedShape3DRetained)retained).initScale(scale);
}
/**
* Constructs an OrientedShape3D node with the specified geometry
* component, appearance component, mode, and rotation point.
*
* @param geometry the geometry component with which to initialize
* this shape node
* @param appearance the appearance component of the shape node
* @param mode alignment mode, one of: ROTATE_ABOUT_AXIS,
* ROTATE_ABOUT_POINT, or ROTATE_NONE
* @param point the position about which the OrientedShape3D rotates
* @param constantScaleEnable a flag indicating whether to enable
* constant scale
* @param scale scale value used when constant scale is enabled
*
* @since Java 3D 1.3
*/
public OrientedShape3D(Geometry geometry,
Appearance appearance,
int mode,
Point3f point,
boolean constantScaleEnable,
double scale) {
super(geometry, appearance);
// set default read capabilities
setDefaultReadCapabilities(readCapabilities);
((OrientedShape3DRetained)retained).initAlignmentMode(mode);
((OrientedShape3DRetained)retained).initRotationPoint(point);
((OrientedShape3DRetained)retained).
initConstantScaleEnable(constantScaleEnable);
((OrientedShape3DRetained)retained).initScale(scale);
}
/**
* Creates the retained mode OrientedShape3DRetained object that this
* OrientedShape3D object will point to.
*/
@Override
void createRetained() {
retained = new OrientedShape3DRetained();
retained.setSource(this);
}
/**
* Sets the alignment mode.
*
* @param mode alignment mode, one of: ROTATE_ABOUT_AXIS,
* ROTATE_ABOUT_POINT, or ROTATE_NONE
*
* @exception CapabilityNotSetException if appropriate capability is
* not set and this object is part of live or compiled scene graph
*/
public void setAlignmentMode(int mode) {
if (isLiveOrCompiled())
if (!this.getCapability(ALLOW_MODE_WRITE))
throw new CapabilityNotSetException(J3dI18N.getString("OrientedShape3D0"));
if (isLive())
((OrientedShape3DRetained)retained).setAlignmentMode(mode);
else
((OrientedShape3DRetained)retained).initAlignmentMode(mode);
}
/**
* Retrieves the alignment mode.
*
* @return one of: ROTATE_ABOUT_AXIS, ROTATE_ABOUT_POINT,
* or ROTATE_NONE
*
* @exception CapabilityNotSetException if appropriate capability is
* not set and this object is part of live or compiled scene graph
*/
public int getAlignmentMode() {
if (isLiveOrCompiled())
if (!this.getCapability(ALLOW_MODE_READ))
throw new CapabilityNotSetException(J3dI18N.getString("OrientedShape3D1"));
return((OrientedShape3DRetained)retained).getAlignmentMode();
}
/**
* Sets the new alignment axis. This is the ray about which this
* OrientedShape3D rotates when the mode is ROTATE_ABOUT_AXIS.
* The specified axis must not be parallel to the Z
* axis--(0,0,z) for any value of z. It is not
* possible for the +Z axis to point at the viewer's eye
* position by rotating about itself. The target transform will
* be set to the identity if the axis is (0,0,z).
*
* @param axis the new alignment axis
*
* @exception CapabilityNotSetException if appropriate capability is
* not set and this object is part of live or compiled scene graph
*/
public void setAlignmentAxis(Vector3f axis) {
if (isLiveOrCompiled())
if (!this.getCapability(ALLOW_AXIS_WRITE))
throw new CapabilityNotSetException(J3dI18N.getString("OrientedShape3D2"));
if (isLive())
((OrientedShape3DRetained)retained).setAlignmentAxis(axis);
else
((OrientedShape3DRetained)retained).initAlignmentAxis(axis);
}
/**
* Sets the new alignment axis. This is the ray about which this
* OrientedShape3D rotates when the mode is ROTATE_ABOUT_AXIS.
* The specified axis must not be parallel to the Z
* axis--(0,0,z) for any value of z. It is not
* possible for the +Z axis to point at the viewer's eye
* position by rotating about itself. The target transform will
* be set to the identity if the axis is (0,0,z).
*
* @param x the x component of the alignment axis
* @param y the y component of the alignment axis
* @param z the z component of the alignment axis
*
* @exception CapabilityNotSetException if appropriate capability is
* not set and this object is part of live or compiled scene graph
*/
public void setAlignmentAxis(float x, float y, float z) {
if (isLiveOrCompiled())
if (!this.getCapability(ALLOW_AXIS_WRITE))
throw new CapabilityNotSetException(J3dI18N.getString("OrientedShape3D2"));
if (isLive())
((OrientedShape3DRetained)retained).setAlignmentAxis(x,y,z);
else
((OrientedShape3DRetained)retained).initAlignmentAxis(x,y,z);
}
/**
* Retrieves the alignment axis of this OrientedShape3D node,
* and copies it into the specified vector.
*
* @param axis the vector that will contain the alignment axis
*
* @exception CapabilityNotSetException if appropriate capability is
* not set and this object is part of live or compiled scene graph
*/
public void getAlignmentAxis(Vector3f axis) {
if (isLiveOrCompiled())
if (!this.getCapability(ALLOW_AXIS_READ))
throw new CapabilityNotSetException(J3dI18N.getString("OrientedShape3D3"));
((OrientedShape3DRetained)retained).getAlignmentAxis(axis);
}
/**
* Sets the new rotation point. This is the point about which the
* OrientedShape3D rotates when the mode is ROTATE_ABOUT_POINT.
*
* @param point the new rotation point
*
* @exception CapabilityNotSetException if appropriate capability is
* not set and this object is part of live or compiled scene graph
*/
public void setRotationPoint(Point3f point) {
if (isLiveOrCompiled())
if (!this.getCapability(ALLOW_POINT_WRITE))
throw new CapabilityNotSetException(J3dI18N.getString("OrientedShape3D4"));
if (isLive())
((OrientedShape3DRetained)retained).setRotationPoint(point);
else
((OrientedShape3DRetained)retained).initRotationPoint(point);
}
/**
* Sets the new rotation point. This is the point about which the
* OrientedShape3D rotates when the mode is ROTATE_ABOUT_POINT.
*
* @param x the x component of the rotation point
* @param y the y component of the rotation point
* @param z the z component of the rotation point
*
* @exception CapabilityNotSetException if appropriate capability is
* not set and this object is part of live or compiled scene graph
*/
public void setRotationPoint(float x, float y, float z) {
if (isLiveOrCompiled())
if (!this.getCapability(ALLOW_POINT_WRITE))
throw new CapabilityNotSetException(J3dI18N.getString("OrientedShape3D4"));
if (isLive())
((OrientedShape3DRetained)retained).setRotationPoint(x,y,z);
else
((OrientedShape3DRetained)retained).initRotationPoint(x,y,z);
}
/**
* Retrieves the rotation point of this OrientedShape3D node,
* and copies it into the specified vector.
*
* @param point the point that will contain the rotation point
*
* @exception CapabilityNotSetException if appropriate capability is
* not set and this object is part of live or compiled scene graph
*/
public void getRotationPoint(Point3f point) {
if (isLiveOrCompiled())
if (!this.getCapability(ALLOW_POINT_READ))
throw new CapabilityNotSetException(J3dI18N.getString("OrientedShape3D5"));
((OrientedShape3DRetained)retained).getRotationPoint(point);
}
/**
* Sets the constant scale enable flag.
*
* @param constantScaleEnable a flag indicating whether to enable
* constant scale
*
* @exception CapabilityNotSetException if appropriate capability is
* not set and this object is part of live or compiled scene graph
*
* @since Java 3D 1.3
*/
public void setConstantScaleEnable(boolean constantScaleEnable) {
if (isLiveOrCompiled())
if (!this.getCapability(ALLOW_SCALE_WRITE))
throw new CapabilityNotSetException(J3dI18N.getString("OrientedShape3D6"));
if (isLive())
((OrientedShape3DRetained)retained).
setConstantScaleEnable(constantScaleEnable);
else
((OrientedShape3DRetained)retained).
initConstantScaleEnable(constantScaleEnable);
}
/**
* Retrieves the constant scale enable flag.
*
* @return the current constant scale enable flag
*
* @exception CapabilityNotSetException if appropriate capability is
* not set and this object is part of live or compiled scene graph
*
* @since Java 3D 1.3
*/
public boolean getConstantScaleEnable() {
if (isLiveOrCompiled())
if (!this.getCapability(ALLOW_SCALE_READ))
throw new CapabilityNotSetException(J3dI18N.getString("OrientedShape3D7"));
return ((OrientedShape3DRetained)retained).getConstantScaleEnable();
}
/**
* Sets the scale for this OrientedShape3D. This scale is used when
* the constant scale enable flag is set to true.
*
* @param scale the scale value
*
* @exception CapabilityNotSetException if appropriate capability is
* not set and this object is part of live or compiled scene graph
*
* @since Java 3D 1.3
*/
public void setScale(double scale) {
if (isLiveOrCompiled())
if (!this.getCapability(ALLOW_SCALE_WRITE))
throw new CapabilityNotSetException(J3dI18N.getString("OrientedShape3D8"));
if (isLive())
((OrientedShape3DRetained)retained).setScale(scale);
else
((OrientedShape3DRetained)retained).initScale(scale);
}
/**
* Retrieves the scale value for this OrientedShape3D.
*
* @return the current scale value
*
* @exception CapabilityNotSetException if appropriate capability is
* not set and this object is part of live or compiled scene graph
*
* @since Java 3D 1.3
*/
public double getScale() {
if (isLiveOrCompiled())
if (!this.getCapability(ALLOW_SCALE_READ))
throw new CapabilityNotSetException(J3dI18N.getString("OrientedShape3D9"));
return ((OrientedShape3DRetained)retained).getScale();
}
/**
* Used to create a new instance of the node. This routine is called
* by cloneTree
to duplicate the current node.
* cloneNode
should be overridden by any user subclassed
* objects. All subclasses must have their cloneNode
* method consist of the following lines:
*
* public Node cloneNode(boolean forceDuplicate) {
* UserSubClass usc = new UserSubClass();
* usc.duplicateNode(this, forceDuplicate);
* return usc;
* }
*
* @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#duplicateNode
* @see NodeComponent#setDuplicateOnCloneTree
*/
@Override
public Node cloneNode(boolean forceDuplicate) {
OrientedShape3D s = new OrientedShape3D();
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
* Shape3D
*
* @see Node#cloneTree
* @see Node#cloneNode
* @see NodeComponent#setDuplicateOnCloneTree
*/
@Override
public void duplicateNode(Node originalNode, boolean forceDuplicate) {
checkDuplicateNode(originalNode, forceDuplicate);
}
/**
* Copies all Shape3D 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);
OrientedShape3DRetained attr = (OrientedShape3DRetained)
originalNode.retained;
OrientedShape3DRetained rt = (OrientedShape3DRetained) retained;
rt.setAlignmentMode(attr.getAlignmentMode());
Vector3f axis = new Vector3f();
attr.getAlignmentAxis(axis);
rt.setAlignmentAxis(axis);
Point3f point = new Point3f();
attr.getRotationPoint(point);
rt.setRotationPoint(point);
}
}