M3G 1.1 -- Jun 22, 2005

javax.microedition.m3g
Class Group

java.lang.Object
  extended byjavax.microedition.m3g.Object3D
      extended byjavax.microedition.m3g.Transformable
          extended byjavax.microedition.m3g.Node
              extended byjavax.microedition.m3g.Group
Direct Known Subclasses:
World

public class Group
extends Node

A scene graph node that stores an unordered set of nodes as its children.

The parent-child relationship is bidirectional in the sense that if node A is a child of node B, then B is the (one and only) parent of A. In particular, the getParent method of A will return B. Besides Group nodes, this also concerns SkinnedMesh nodes: the skeleton group is the one and only child of a SkinnedMesh.

A node can have at most one parent at a time, and cycles are prohibited. Furthermore, a World node cannot be a child of any node. These rules are enforced by the addChild method in this class, as well as the constructor of SkinnedMesh.

See Also:
Binary format

Field Summary
 
Fields inherited from class javax.microedition.m3g.Node
NONE, ORIGIN, X_AXIS, Y_AXIS, Z_AXIS
 
Constructor Summary
Group()
          Constructs a new Group node and initializes it with an empty list of children.
 
Method Summary
 void addChild(Node child)
          Adds the given node to this Group, potentially changing the order and indices of the previously added children.
 Node getChild(int index)
          Gets a child by index.
 int getChildCount()
          Gets the number of children in this Group.
 boolean pick(int scope, float x, float y, Camera camera, RayIntersection ri)
          Picks the first Mesh or scaled Sprite3D in this Group that is enabled for picking, is intercepted by the given pick ray, and is in the specified scope.
 boolean pick(int scope, float ox, float oy, float oz, float dx, float dy, float dz, RayIntersection ri)
          Picks the first Mesh in this Group that is intercepted by the given pick ray and is in the specified scope.
 void removeChild(Node child)
          Removes the given node from this Group, potentially changing the order and indices of the remaining children.
 
Methods inherited from class javax.microedition.m3g.Node
align, getAlignmentReference, getAlignmentTarget, getAlphaFactor, getParent, getScope, getTransformTo, isPickingEnabled, isRenderingEnabled, setAlignment, setAlphaFactor, setPickingEnable, setRenderingEnable, setScope
 
Methods inherited from class javax.microedition.m3g.Transformable
getCompositeTransform, getOrientation, getScale, getTransform, getTranslation, postRotate, preRotate, scale, setOrientation, setScale, setTransform, setTranslation, translate
 
Methods inherited from class javax.microedition.m3g.Object3D
addAnimationTrack, animate, duplicate, find, getAnimationTrack, getAnimationTrackCount, getReferences, getUserID, getUserObject, removeAnimationTrack, setUserID, setUserObject
   

Constructor Detail

Group

public Group()

Constructs a new Group node and initializes it with an empty list of children. Properties inherited from Object3D and Node will have the default values as specified in their respective class descriptions.

Method Detail

addChild

public void addChild(Node child)

Adds the given node to this Group, potentially changing the order and indices of the previously added children. The position at which the node is inserted among the existing children is deliberately left undefined. This gives implementations the freedom to select a data structure that best fits their needs, instead of mandating a particular kind of data structure.

Parameters:
child - the node to add; must not form a loop in the scene graph
Throws:
java.lang.NullPointerException - if child is null
java.lang.IllegalArgumentException - if child is this Group
java.lang.IllegalArgumentException - if child is a World node
java.lang.IllegalArgumentException - if child already has a parent other than this Group
java.lang.IllegalArgumentException - if child is an ancestor of this Group

removeChild

public void removeChild(Node child)

Removes the given node from this Group, potentially changing the order and indices of the remaining children. If the given node is not a child of this Group, or is null, the request to remove it is silently ignored.

Parameters:
child - the node to remove
Throws:
java.lang.IllegalArgumentException - if removing child would break a connection between a SkinnedMesh node and one of its transform references

getChildCount

public int getChildCount()

Gets the number of children in this Group.

Returns:
the number of children directly attached to this group

getChild

public Node getChild(int index)

Gets a child by index. Valid indices range from zero up to the number of children minus one. Note that the index of any child may change whenever a node is added to or removed from this Group. See addChild for more information.

Parameters:
index - index of the child node to get
Returns:
the child node at the given index; can not be null
Throws:
java.lang.IndexOutOfBoundsException - if (index < 0) || (index >= getChildCount)

pick

public boolean pick(int scope,
                    float ox,
                    float oy,
                    float oz,
                    float dx,
                    float dy,
                    float dz,
                    RayIntersection ri)

Picks the first Mesh in this Group that is intercepted by the given pick ray and is in the specified scope. Meshes that are disabled or out of scope are ignored. Any ancestors of this Group, including their picking enable flags, are ignored. Winding and culling flags for each Mesh are respected when determining a hit, such that triangles culled based on their facing with respect to the pick ray are ignored.

The pick ray is cast in the given direction from the given location in the coordinate system of this Group. The direction vector of the ray does not need to be unit length; the distance to the picked object is computed relative to the length of the given ray.

Information about the picked object, if any, is filled in to the given RayIntersection object. If no intersection occurs, the RayIntersection object is left unmodified.

This method ignores all Sprite3D nodes. This is because the camera parameters (that is, the projection matrix) are required in order to compute the size of a sprite (see the Sprite3D class description), and that information is not available to this method. Developers are advised to use the other pick variant if picking of sprites is desired.

The application should ensure that there are no uninvertible node transformations in this Group. Depending on how picking is implemented, singular transformations may or may not trigger an ArithmeticException.

Parameters:
scope - an integer scope specifying which Meshes to test for intersection with the pick ray; "-1" makes the scope as wide as possible
ox - X coordinate of the ray origin
oy - Y coordinate of the ray origin
oz - Z coordinate of the ray origin
dx - X component of the ray direction
dy - Y component of the ray direction
dz - Z component of the ray direction
ri - a RayIntersection object to fill in with information about the intersected Mesh, or null to just find out whether the ray intersected something or not
Returns:
true if the ray intersected a Mesh; false otherwise
Throws:
java.lang.IllegalArgumentException - if dx = dy = dz = 0
java.lang.IllegalStateException - if any Mesh that is tested for intersection violates the constraints defined in Mesh, MorphingMesh, SkinnedMesh, VertexBuffer, or IndexBuffer
java.lang.ArithmeticException - if the inverse of an uninvertible transformation is required by the implementation

pick

public boolean pick(int scope,
                    float x,
                    float y,
                    Camera camera,
                    RayIntersection ri)

Picks the first Mesh or scaled Sprite3D in this Group that is enabled for picking, is intercepted by the given pick ray, and is in the specified scope.

This method behaves identically to the other pick variant, except that the pick ray is specified differently and that scaled sprites can also be picked. Unscaled sprites can not be picked. This is because the size of an unscaled sprite is only defined in screen space (that is, after viewport transformation), and the viewport parameters are not available to this method. See the Sprite3D class description for more information on sprite picking.

The pick ray is cast from the given point p = (x, y) on the near clipping plane towards the corresponding point on the far clipping plane, and then beyond. See the Implementation guidelines below for details.

Note that the origin of the pick ray is not the given Camera, but the point on the near clipping plane. Consequently the distance to the picked object, returned in RayIntersection, is not the distance from the camera, but the distance from the point p.

The point p is specified relative to the viewport such that (0, 0) is the upper left corner and (1, 1) is the lower right corner. However, the (x, y) coordinates are not restricted to that range and may take on any values. In other words, objects that do not lie within the viewport can also be picked.

The given Camera and this Group must be in the same scene graph. Furthermore, the projection matrix of the Camera must be invertible. Depending on how picking is implemented, objects within the Group which have uninvertible modelview matrices may or may not trigger an ArithmeticException.

Implementation guidelines

The pick ray is cast towards infinity from the given point p on the near clipping plane, through a point p' on the far clipping plane. The exact procedure of deriving the pick ray origin and direction from the given point (x, y) and the given projection matrix P is as follows.

In normalized device coordinates (NDC), the viewport spans the range [-1, 1] in each dimension (X, Y and Z). Points that lie on the near plane have a Z coordinate of -1 in NDC; points on the far plane have a Z of 1. The normalized device coordinates of p and p' are, therefore:

Note that the Y coordinate is inverted when going from NDC to viewport or vice versa, as the viewport upper left corner maps to (-1, 1) in NDC (see also the viewport transformation equation in Graphics3D.setViewport). Applying the inverse projection matrix on the pick points, we obtain their positions in camera space:

We then scale the resultant homogeneous points such that their W components are equal to 1; that might not otherwise be the case after the inverse projection. Formally, denoting the W components of the near and far points by w and w', the final camera space coordinates are obtained as follows:

The origin of the pick ray in camera coordinates is then p while its direction vector is p' - p.

Finally, the pick ray is transformed from camera space to the coordinate system of this Group. That ray is used in the actual intersection tests, and is also the one that is returned by the getRay method in RayIntersection.

Parameters:
scope - an integer scope specifying which meshes and sprites to test for intersection with the pick ray; -1 makes the scope as wide as possible
x - X coordinate of the point on the viewport plane through which to cast the ray
y - Y coordinate of the point on the viewport plane through which to cast the ray
camera - a camera based on which the origin and direction of the pick ray are to be computed
ri - a RayIntersection object to fill in with information about the intersected Mesh, or null to just find out whether the ray intersected something or not
Returns:
true if the ray intersected a Mesh or Sprite3D; false otherwise
Throws:
java.lang.NullPointerException - if camera is null
java.lang.IllegalStateException - if any Mesh that is tested for intersection violates the constraints defined in Mesh, MorphingMesh, SkinnedMesh, VertexBuffer, or IndexBuffer
java.lang.IllegalStateException - if there is no scene graph path between camera and this Group
java.lang.ArithmeticException - if the inverse of an uninvertible transformation is required by the implementation

M3G 1.1 -- Jun 22, 2005

Copyright © 2005 Nokia Corporation. See the Copyright Notice for details.