|
JSR-184 Public Review Draft - Apr. 30, 2003. | ||||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |
java.lang.Object | +--javax.microedition.m3d.Object3D | +--javax.microedition.m3d.Node | +--javax.microedition.m3d.Mesh | +--javax.microedition.m3d.SkinnedMesh
A skeletally animated mesh. Vertex positions in a SkinnedMesh can be associated with multiple separately transforming Nodes, with a weight factor specified for each. This enables groups of vertices to transform independently of each other while still smoothly deforming the polygon mesh "skin" with the vertices. This style of animation is highly efficient for animated characters. Also, using ordinary Nodes in place of more specialized "bone" nodes allows rigid-body attachments on skinned objects, such as weapons on a game character.
The structure of a SkinnedMesh is shown in the figure below.
Each vertex is transformed once for each Node affecting it, as if it was defined in the coordinate system of that node. The results are then blended together according to the weight factors of each node. Let us denote the set of nodes associated with a vertex by {N1, N2, ..., NN}. Let us also denote by Mi the transformation from the local coordinate system of node Ni to a reference coordinate system. The choice of the reference coordinate system is not critical; depending on the implementation, good choices may include the world coordinate system, the coordinate system of the SkinnedMesh node, or the coordinate system of the current camera. Finally, let us denote the weight associated with node Ni as Wi. The blended position of a vertex in the reference coordinate system is then:
v' = w1M1v + w2M2v + ... + wNMNv
where v is the original vertex position in the source vertex buffer, and wi = Wi / (W1 + ... + WN). When computing the normalized weights wi, 0 / 0 = 0. Finally, the blended vertex position is transformed from the chosen reference coordinate system to camera space as usual.
If a vertex v has no transformations associated with it, as is the case for all vertices in a newly constructed SkinnedMesh, the vertex is taken to be in the coordinate system of the SkinnedMesh node itself. That is, a SkinnedMesh in its initial state is equivalent to an ordinary Mesh.
The transformation of vertices is illustrated in the figure below.
Any special cases and exceptions that are defined for Mesh also apply
for SkinnedMesh. An extra exception case is introduced due to the vertex
indices set by addTransform
. The indices cannot be validated
until when they are actually needed, that is, when rendering or picking.
This is because the application may change the length of the associated
VertexBuffer, and consequently make the indices invalid or valid, at any
time.
Another extra exception case is introduced due to the requirement that
all transform reference nodes of a SkinnedMesh must be descendants of that
SkinnedMesh. This condition cannot be enforced by addTransform
,
because again the application may attach and detach the reference nodes at
will. Their validity is therefore checked only when the transformations are
actually done, that is, when rendering or picking.
Field Summary |
Fields inherited from class javax.microedition.m3d.Node |
NONE, ORIGIN, X_AXIS, Y_AXIS, Z_AXIS |
Fields inherited from class javax.microedition.m3d.Object3D |
userObject |
Constructor Summary | |
SkinnedMesh(VertexBuffer vertices,
IndexBuffer[] triangles,
Appearance[] appearances)
Constructs a new SkinnedMesh with the given VertexBuffer and submeshes. |
|
SkinnedMesh(VertexBuffer vertices,
IndexBuffer triangles,
Appearance appearance)
Constructs a new SkinnedMesh consisting of only one submesh. |
Method Summary | |
void |
addTransform(Node transform,
int weight,
int firstVertex,
int lastVertex)
Sets a weighted transformation on a range of vertices in the VertexBuffer associated with this SkinnedMesh. |
Group |
getSkeleton()
Returns the skeleton Group of this SkinnedMesh. |
void |
setSkeleton(Group skeleton)
Sets the Group to use as the skeleton of this SkinnedMesh. |
Methods inherited from class javax.microedition.m3d.Mesh |
getAppearance, getIndexBuffer, getSubmeshCount, getVertexBuffer, setAppearance |
Methods inherited from class javax.microedition.m3d.Node |
getAlphaFactor, getOrientation, getParent, getScale, getScopeID, getTransform, getTransformTo, getTranslation, isEnabled, setAlignment, setAlphaFactor, setEnable, setOrientation, setScale, setScopeID, setTransform, setTranslation |
Methods inherited from class javax.microedition.m3d.Object3D |
addAnimationTrack, animate, clone, find, getAnimationTrack, getAnimationTrackCount, getReferences, getUserID, removeAnimationTrack, setUserID |
Methods inherited from class java.lang.Object |
equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
Constructor Detail |
public SkinnedMesh(VertexBuffer vertices, IndexBuffer triangles, Appearance appearance)
Constructs a new SkinnedMesh consisting of only one submesh. All transform references are initialized to null, and all weights to zero. This means that the mesh is not rendered at all, because all vertices will be mapped to the zero vector (see the transformation equation in the class description above).
vertices
- a VertexBuffer to use for this meshtriangles
- an IndexBuffer defining the triangle strips to drawappearance
- an Appearance to use for this mesh, or nullpublic SkinnedMesh(VertexBuffer vertices, IndexBuffer[] triangles, Appearance[] appearances)
Constructs a new SkinnedMesh with the given VertexBuffer and submeshes.
The number of submeshes is set equal to the length of triangles
.
The appearances
array is parallel to that, and must have at
least as many elements. Alternatively, it may be null, in which case all
the Appearances are initialized to null.
All transform references are initialized to null, and all weights to zero. This means that the mesh is not rendered at all, because all vertices will be mapped to the zero vector (see the transformation equation in the class description above).
vertices
- a VertexBuffer to use for all submeshes in this meshtriangles
- an IndexBuffer array defining the triangle strips to drawappearances
- an Appearance array parallel to triangles
;
a null element disables rendering of that submesh, and a null array
initializes all appearances to null
java.lang.IllegalArgumentException
- if triangles
is empty
java.lang.IllegalArgumentException
- if appearances.length < triangles.length
Method Detail |
public void addTransform(Node transform, int weight, int firstVertex, int lastVertex)
Sets a weighted transformation on a range of vertices in the VertexBuffer associated with this SkinnedMesh. When applying a transformation on a vertex, its weight is normalized by dividing it with the sum of all weights pertaining to that vertex. See the class description for a more formal definition. Due to the normalization, the weights are integers instead of floating point values between [0, 1]. The implementation does not need to check the validity of the incoming weights, because all values are equally valid.
Note that for the SkinnedMesh to be valid, each Node used to transform
vertices must be in the skeleton Group set by setSkeleton
. However,
this check is postponed until rendering or picking; see the class description
for more information.
transform
- node transformation to apply on the specified range of verticesweight
- weight of transform
; all values are acceptedfirstVertex
- index of the first vertex to be affected by transform
lastVertex
- index of the last vertex to be affected by transform
java.lang.IllegalArgumentException
- if firstVertex
is greater than
lastVertex
public void setSkeleton(Group skeleton)
Sets the Group to use as the skeleton of this SkinnedMesh. Every Node used to transform vertices of this mesh must be in the given skeleton Group; not immediately, but at the latest when the transformations are actually done, that is, when rendering or picking. Note that the skeleton group may also contain an arbitrary number of nodes that are not referenced by this mesh; those are treated as usual when rendering or picking.
A SkinnedMesh node is a parent in the scene graph for its skeleton Group.
In other words, this.getSkeleton().getParent() == this
.
skeleton
- the Group containing the Nodes used in transforming this SkinnedMesh
java.lang.IllegalArgumentException
- if skeleton
is a World node
java.lang.IllegalArgumentException
- if skeleton
already has a parent
java.lang.IllegalArgumentException
- if skeleton
is an ancestor of this nodeaddTransform
,
getSkeleton
public Group getSkeleton()
Returns the skeleton Group of this SkinnedMesh.
setSkeleton
|
JSR-184 Public Review Draft - Apr. 30, 2003. | ||||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |