M3G 1.1 -- Jun 22, 2005

javax.microedition.m3g
Class MorphingMesh

java.lang.Object
  extended byjavax.microedition.m3g.Object3D
      extended byjavax.microedition.m3g.Transformable
          extended byjavax.microedition.m3g.Node
              extended byjavax.microedition.m3g.Mesh
                  extended byjavax.microedition.m3g.MorphingMesh

public class MorphingMesh
extends Mesh

A scene graph node that represents a vertex morphing polygon mesh.

MorphingMesh is equivalent to an ordinary Mesh, except that the vertices that are rendered are computed as a weighted linear combination of the base VertexBuffer and a number of morph target VertexBuffers. The resultant mesh is only used for rendering, and is not exposed to the application. The structure of a MorphingMesh object is shown in the figure below.

Morph targets

All morph targets must have the same properties: The same types of arrays, the same number of vertices in each array, the same number of components per vertex, and the same component size. For example, it is prohibited for one morph target to contain vertex coordinates and texture coordinates, if some other target only contains vertex coordinates. Similarly, having 2D texture coordinates in one morph target and 3D texture coordinates in another is not allowed.

The base mesh must be a "superset" of the morph targets. If an array with certain type and dimensions exists in the morph targets, a similar array must also exist in the base mesh, but not vice versa. It is illegal, for example, for the morph targets to have per-vertex colors and 8-bit coordinates if the base mesh has 16-bit coordinates and/or no colors.

Only the VertexBuffer default color and the arrays that are present in the morph targets are actually morphed. The other arrays, as well as the scale and bias values, are copied from the base mesh. Scale and bias values of the morph targets are ignored.

Morphing equation

Denoting the base mesh with B, the morph targets with Ti, and the weights corresponding to the morph targets with wi, the resultant mesh R is computed as follows:

Any values for the weights wi are accepted, including negative values. The sum of the weights is similarly unconstrained. This allows having, for example, a model of a face with a neutral expression as the base mesh, and two morph targets where one is the base mesh but with a smiling mouth and the other with raised eyebrows. Now, setting the first weight to 1.0 makes the face smile, -0.5 could make it frown, and so on, while the eyebrow raising and lowering can be driven independent of the mouth movements.

Setting up the morph weights such that the individual weights as well as their sum are between [0, 1] ensures that the resultant mesh never grows beyond the convex hull of the base mesh and the targets. That, on the other hand, guarantees that no arithmetic overflows will occur and the results are as expected.

If the application chooses to set up the weights such that they or their sum is not in the [0, 1] interval, it should by some other means ensure that the morphed attributes of the resultant mesh will fit into the original numeric range, that is, in the same number of bits that are used in the base mesh and the morph targets. The available range for the results can be either [0, 255] or [0, 65535], for 8-bit and 16-bit components respectively. If the values do not, however, fit in that range, the results are undefined when rendering or picking.

Any intermediate values produced during morphing are subject to the dynamic range constraints that are specified in the package description. In other words, individual weights can be very large or small, as long as the resultant mesh fits in the 8/16-bit range.

The VertexBuffer scale and bias for the resultant mesh are taken from the base mesh as such, without interpolation, because correct interpolation between (integer) values that are in different (floating point) scales would require the interpolants to be first multiplied with the scale factor, and only then interpolated. This involves several floating point operations per vertex attribute, which would make morphing of anything but the most trivial meshes prohibitively expensive on current mobile hardware, for very little benefit. Note also that interpolating the scale terms separately from the values would not produce the correct results.

Deferred exceptions

Any special cases and exceptions that are defined for Mesh also apply for MorphingMesh. An extra exception case is introduced due to the requirement that morph targets must be "subsets" of the base mesh, and that they must all have the same set of vertex attributes with the same dimensions, as specified above. This requirement cannot be enforced until when the morphing is actually done, that is, when rendering or picking.

See Also:
Binary format

Field Summary
 
Fields inherited from class javax.microedition.m3g.Node
NONE, ORIGIN, X_AXIS, Y_AXIS, Z_AXIS
 
Constructor Summary
MorphingMesh(VertexBuffer base, VertexBuffer[] targets, IndexBuffer[] submeshes, Appearance[] appearances)
          Constructs a new MorphingMesh with the given base mesh and morph targets.
MorphingMesh(VertexBuffer base, VertexBuffer[] targets, IndexBuffer submesh, Appearance appearance)
          Constructs a new MorphingMesh with the given base mesh and morph targets.
 
Method Summary
 VertexBuffer getMorphTarget(int index)
          Returns the morph target VertexBuffer at the given index.
 int getMorphTargetCount()
          Returns the number of morph targets in this MorphingMesh.
 void getWeights(float[] weights)
          Gets the current morph target weights for this mesh.
 void setWeights(float[] weights)
          Sets the weights for all morph targets in this mesh.
 
Methods inherited from class javax.microedition.m3g.Mesh
getAppearance, getIndexBuffer, getSubmeshCount, getVertexBuffer, setAppearance
 
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

MorphingMesh

public MorphingMesh(VertexBuffer base,
                    VertexBuffer[] targets,
                    IndexBuffer submesh,
                    Appearance appearance)

Constructs a new MorphingMesh with the given base mesh and morph targets. Except for the morph targets, the behavior of this constructor is identical to the corresponding constructor in Mesh; refer to that for more information.

The morph target weights are initially set to zero, meaning that the resultant mesh is equal to the base mesh. The behavior of a newly constructed MorphingMesh is therefore equivalent to an ordinary Mesh.

Parameters:
base - a VertexBuffer representing the base mesh
targets - a VertexBuffer array representing the morph targets
submesh - an IndexBuffer defining the triangle strips to draw
appearance - an Appearance to use for this mesh, or null
Throws:
java.lang.NullPointerException - if base is null
java.lang.NullPointerException - if targets is null
java.lang.NullPointerException - if submesh is null
java.lang.NullPointerException - if any element in targets is null
java.lang.IllegalArgumentException - if targets is empty

MorphingMesh

public MorphingMesh(VertexBuffer base,
                    VertexBuffer[] targets,
                    IndexBuffer[] submeshes,
                    Appearance[] appearances)

Constructs a new MorphingMesh with the given base mesh and morph targets. Except for the morph targets, the behavior of this constructor is identical to the corresponding constructor in Mesh; refer to that for more information.

The morph target weights are initially set to zero, meaning that the resultant mesh is equal to the base mesh. The behavior of a newly constructed MorphingMesh is therefore equivalent to an ordinary Mesh.

Parameters:
base - a VertexBuffer representing the base mesh
targets - a VertexBuffer array representing the morph targets
submeshes - an IndexBuffer array defining the submeshes to draw
appearances - an Appearance array parallel to submeshes, or null
Throws:
java.lang.NullPointerException - if base is null
java.lang.NullPointerException - if targets is null
java.lang.NullPointerException - if submeshes is null
java.lang.NullPointerException - if any element in targets is null
java.lang.NullPointerException - if any element in submeshes is null
java.lang.IllegalArgumentException - if targets is empty
java.lang.IllegalArgumentException - if submeshes is empty
java.lang.IllegalArgumentException - if (appearances != null) && (appearances.length < submeshes.length)
Method Detail

getMorphTarget

public VertexBuffer getMorphTarget(int index)

Returns the morph target VertexBuffer at the given index.

Parameters:
index - the index of the morph target to get
Returns:
the VertexBuffer object at index
Throws:
java.lang.IndexOutOfBoundsException - if (index < 0) || (index >= getMorphTargetCount)
See Also:
Mesh.getVertexBuffer

getMorphTargetCount

public int getMorphTargetCount()

Returns the number of morph targets in this MorphingMesh.

Returns:
the number of morph targets

setWeights

public void setWeights(float[] weights)

Sets the weights for all morph targets in this mesh. The number of weights copied in is the number of target vertex buffers, as specified at construction time. The source array must have at least that many elements. See the class description for more information.

Parameters:
weights - weight factors for all morph targets
Throws:
java.lang.NullPointerException - if weights is null
java.lang.IllegalArgumentException - if weights.length < getMorphTargetCount
See Also:
getWeights

getWeights

public void getWeights(float[] weights)

Gets the current morph target weights for this mesh.

Parameters:
weights - array to be populated with the morph target weights
Throws:
java.lang.NullPointerException - if weights is null
java.lang.IllegalArgumentException - if weights.length < getMorphTargetCount
See Also:
setWeights

M3G 1.1 -- Jun 22, 2005

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