ObjectMeshSkinned Class
Skinned meshes are used for bone-based animation.
Intersections and collisions with skinned meshes are not as fast as with static meshes, so the following workaround is possible: create a simple surface roughly resembling the main model, make it hidden and enable collisions and intersections with it, disabling them for the main model.
Creating and Playing Animation
As there can be several animations describing motion of different parts of the mesh, there are several animation layers available, each of which should be set up separately. Usually, you will need to do the following:
- Set the number of animation layers with the setNumLayers() method. By default, there is always one layer.
- Choose a layer by calling the setLayer() method and change layer properties: set its weight for blending (setWeight()), load animation (setAnimation()).
- Choose another layer, set its properties, etc.
- Animation is played by sequential calls of the setFrame() method.
Updating Bone Transformations
Some of the methods require to update the animation data before the renderer makes its obligatory update and actually draws the skinned mesh. Such intermediate update allows to get the correct result of blending between the frames and layers. All class methods can be divided into the following groups:
- Methods that do not require the update and do not call it. These methods can be called at any time.
- Methods that set a flag indicating that the update of animation data is required. These methods should be called before the methods from the 3rd group.
- addLayer()
- removeLayer()
- setNumLayers()
- setBuffer() in case bone transformations are applied to one specific layer
- setFrame()
- setFrameBoneTransform()
- Methods that call for update. Animation data will be recalculated during the update only if the corresponding flag was previously set by a function from the 2nd group.
- getBuffer() in case bone transformations are grabbed from one specific layer
- setBoneTransform()
- setBoneChildsTransform()
- getBoneTransform()
For example, if we call setFrameBoneTransform() (sets the flag), getBoneTransform() (updates data), and setFrameBoneTransform() again, only transformations set during the last call will be rendered, while the first setFrameBoneTransform() call will we discarded.
Instancing
Surfaces of identical skinned meshes which have the same materials assigned to them and the same number of bones attached to their vertices are automatically instanced and drawn in one DIP call. The instancing flag is enabled by default (see corresponding console commands).
The data buffers for instanced objects that store bones transformations are limited in size; therefore, if skinned meshes have many bones, only a few meshes can populate the instance data buffer to be drawn in one draw call.
For example, in DirectX 9 the buffer with bones transformations is limited to 96 bones and a buffer with skinned mesh surfaces transformations is limited to 8 surfaces. When any of these buffers overflow, skinned meshes that fit in are drawn as one instance.
It means that if a skinned mesh has 50 bones (even it has only one or two surfaces), it will not be instanced at all.
ObjectMeshSkinned Class
This class inherits from ObjectMembers
ObjectMeshSkinned (string name, int dynamic = 0)
Constructor. Creates a new skinned mesh object from a given file. Set Dynamic flag to 1 if vertices of the mesh are going to be modified in run-time. (However, you can modify it only once, when init() or update() is over, it is sent to the GPU and cannot be changed any more.)Arguments
- string name - Path to the skinned mesh file.
- int dynamic = 0 - Dynamic flag for meshes that are going to be modified. This is an optional argument.
int addBone (string name, int parent)
Appends a new bone.Arguments
- string name - Name of the bone.
- int parent - Number of the parent bone.
Return value
Bone number.int addBuffer ()
Adds an animation buffer.Return value
ID of the created buffer.int addEmptySurface (string name, int num_vertex, int num_indices)
Appends a new surface to the mesh.Arguments
- string name - A name of the new surface.
- int num_vertex - Number of vertices.
- int num_indices - Number of indices.
Return value
Mesh surface number.void addFrame (int frame)
Appends a new frame.Arguments
- int frame - Frame pointer.
int addLayer ()
Adds an animation layer.Return value
ID of the added (the last) layer.int addMeshFrame (ObjectMeshSkinned mesh, int frame)
Copies per-frame transformations from a donor skinned mesh to the current one. Transformations from the specified frame are applied to identical bones found by name.Arguments
- ObjectMeshSkinned mesh - Skinned mesh to copy a frame from.
- int frame - Frame number.
Return value
Number of the added frame.void addMeshSurface (variable variable, ObjectMeshSkinned mesh, int surface)
Adds geometry (a surface) from a donor mesh to the existing surface of the current mesh or into its new surface.Arguments
- variable variable - Variable to control to what surface geometry is added:
- If int, it is a destination surface number. Geometry is added to the existing mesh surface.
- If string, it is a new surface name. Geometry is added to the new mesh surface.
- ObjectMeshSkinned mesh - Mesh to copy geometry (a surface) from.
- int surface - Number of the surface to copy geometry from.
void clearBuffer (int num)
Clears a given animation buffer.Arguments
- int num - Number of the buffer in range from 0 to the total number of animation buffers.
void clearFrame ()
Clears the frame of the current animation layer. This function clears animation transformations of all bones to the bind pose.void copyBuffer (int dst, int src)
Copies transformations of source bones to the destination buffer (if the destination buffer has more bones than the source one, those bones will have old transformations; if the source buffer has more bones than destination one, those bones will be added to the destination buffer).Arguments
- int dst - Destination buffer.
- int src - Source buffer.
int findBone (string name)
Searches for a bone with a given name.Arguments
- string name - Name of the bone.
Return value
Bone number.int getAnimationID ()
Gets the ID of the animation loaded for the current layer. This ID can be used when calling setAnimationID().Return value
Animation ID.string getAnimation ()
Returns the name of the animation used in the current layer.Return value
Path to the animation file (absolute or relative to the data directory, as it was set).int getBoneChild (int bone, int child)
Returns the number of a child of a given node.Arguments
- int bone - Bone number.
- int child - Child number.
Return value
Number of the child in the collection of all bones.string getBoneName (int bone)
Returns the name of a given bone.Arguments
- int bone - Bone number.
Return value
Bone name.int getBoneParent (int bone)
Returns the number of the parent bone of a given one.Arguments
- int bone - Bone, for which the parent will be returned.
Return value
Parent bone number.mat4 getBoneTransform (int bone)
Returns a transformation matrix of a given bone relatively to the parent object (not considering transformations of the node itself).Arguments
- int bone - Bone number.
Return value
Transformation matrix.ivec4 getBones (int num, int surface)
Returns bones that are attached to a given vertex of the skinned mesh.Arguments
- int num - Vertex number.
- int surface - Surface number.
Return value
Four vertex bone numbers.mat4 getBufferBoneTransform (int buffer, int bone)
Returns the current transformation matrix of a specified bone from the given animation buffer.Arguments
- int buffer - Buffer ID.
- int bone - Bone number.
Return value
Transformation matrix of a bone.void getBuffer (int buffer, int layer)
Gets bone transformations from a given layer to a given buffer. If layer ID is equal to -1, then data is grabbed from the resulting animation.Arguments
- int buffer - Buffer ID.
- int layer - Layer ID.
int getCoordinateIndex (int num, int surface)
Returns a vertex number pointed by the index that is set after applying animation.Arguments
- int num - Index in the index buffer.
- int surface - Surface number.
Return value
Vertex number.vec3 getCoordinateVertex (int num, int surface)
Returns vertex coordinates that are set after applying animation.Arguments
- int num - Number of the vertex.
- int surface - Surface number.
Return value
Vertex coordinates.mat4 getFrameBoneTransform (int bone)
Returns a transformation matrix of a given bone relatively to the parent object. The difference from getBoneTransform() is that this method takes into account only the transformation in the current animation layer (no blending is done).Arguments
- int bone - Bone number.
Return value
Transformation matrix.int getFrameFrom ()
Returns the start frame passed to the last setFrame() call.Return value
Start frame.float getFrameTime ()
Returns the time value passed to the last setFrame() call.Return value
Time value.int getFrameTo ()
Returns the end frame passed to the last setFrame() call.Return value
End frame.void getFrame ()
Creates a frame out of transformations that were set to skinned mesh bones. After that, for example, physical transformations can be interpolated with animation.int getIndex (int num, int surface)
Returns an index of a vertex from the index buffer.Arguments
- int num - Index number in the index buffer.
- int surface - Surface number.
Return value
Index number.int getLayer ()
Returns the current animation layer.Return value
Current animation layer.int getLoop ()
Gets a value indicating if the animation is looped.Return value
Loop flag.string getMeshName ()
Returns the name of the original mesh file.Return value
Name of the mesh file.vec3 getNormal (int num, int surface)
Returns a normal vector of a vertex in the given skinned mesh surface.Arguments
- int num - Number of the vertex.
- int surface - Surface number.
Return value
The vertex normal vector.int getNumAnimations ()
Returns the number of all animations.Return value
Number of animations.int getNumBoneChilds (int bone)
Returns the number of children for the specified bone.Arguments
- int bone - Bone number.
Return value
Number of child bones.int getNumBones ()
Returns the number of all bones taking part in animation.Return value
Number of bones in the bind pose.int getNumBuffers ()
Returns the number of animation buffers.Return value
Number of animation buffers.int getNumCoordinateVertex (int surface)
Returns the number of vertices in a given surface that are set after applying animation.Arguments
- int surface - Surface number.
Return value
Number of vertices.int getNumFrames ()
Returns the number of animation frames in the current layer.Return value
Number of frames.int getNumIndices (int surface)
Returns the number of vertex indices used in the given skinned mesh surface.Arguments
- int surface - Surface number.
Return value
Number of indices.int getNumLayers ()
Returns the number of animation layers set for blending.Return value
Number of animation layers.int getNumVertex (int surface)
Returns the total number of vertices in the given skinned mesh surface.Arguments
- int surface - Surface number.
Return value
Number of vertices.int getNumWeights (int num, int surface)
Returns the number of bones that control a specified vertex (up to 4 bones per vertex are supported).Arguments
- int num - Number of the vertex.
- int surface - Number of the surface to which a vertex belongs.
Return value
The number of bone weights used.mat4 getOffsetTransform (int bone)
Returns an offset transformation matrix.Arguments
- int bone - Bone number.
Return value
Offset transformation matrix.float getSpeed ()
Returns multiplier for animation playback speed. This time is measured in animation frames per second. Negative value determines reverse playback.Return value
Multiplier for animation playback speed.vec4 getTangent (int num, int surface)
Returns a tangent vector of a vertex in the given skinned mesh surface.Arguments
- int num - Number of the vertex.
- int surface - Surface number.
Return value
The vertex tangent vector.vec4 getTexCoord (int num, int surface)
Returns texture coordinates of a vertex in the given skinned mesh surface.Arguments
- int num - Number of the vertex.
- int surface - Surface number.
Return value
Coordinate pairs for both texture channels.float getTime ()
Returns the current time of animation set via setTime(). This time is measured in animation frames. When the time is between frames, animation is blended.Return value
Animation time.vec3 getVertex (int num, int surface)
Returns coordinates of a given vertex in the given skinned mesh surface.Arguments
- int num - Number of the vertex.
- int surface - Surface number.
Return value
Coordinates in the skinned mesh system of coordinates.float getWeight ()
Returns the current blending weight of the current animation layer.Return value
Blending weight.vec4 getWeights (int num, int surface)
Returns animation weights that are used for a given vertex of the skinned mesh.Arguments
- int num - Vertex number.
- int surface - Surface number.
Return value
Four vertex weights.mat4 getWorldBoneTransform (int bone)
Returns the current transformation matrix applied to the bone in the world coordinate space (considering node transformations).Arguments
- int bone - Bone number.
Return value
Transformation matrix in the world space.void inverseBuffer (int dst, int src)
Copies inverse transformations of bones from the source buffer to the destination one. Please note that the destination buffer isn't cleared before writing to it.Arguments
- int dst - Destination buffer.
- int src - Source buffer.
int isBufferBoneTransform (int buffer, int bone)
Returns a value indication if a transformation matrix has been previously set for the specified bone from the given animation buffer.Arguments
- int buffer - Buffer ID.
- int bone - Bone number.
Return value
1 if the bone has been transformed; otherwise, 0.int isControlled ()
Gets a value indicating if the animation should be controlled by a parent ObjectMeshSkinned (useful for attaching clothes to a character body).Return value
Control flag.int isFrameBoneTransform (int bone)
Returns a value indicating if the bone transformation is applied only to the current animation layer (no blending is done).Arguments
- int bone - Bone number.
Return value
1 if the bone transformation is applied only to the current animation layer; otherwise, 0.int isPlaying ()
Returns playback status.Return value
1 if animation is playing, 0 if it isn't.int isStopped ()
Returns stop status.Return value
1 if animation is stopped, 0 if it isn't.void lerpBuffer (int dst, int src0, int src1, float weight)
Copies interpolated bone transformations from source0 and source1 buffers (with a given weight) to the destination buffer. If there is no bone in a source buffer, the bone transformation from another one will be copied to the destination buffer without interpolation.Arguments
- int dst - Number of the destination buffer in range from 0 to the total number of animation buffers.
- int src0 - Number of the first source buffer in range from 0 to the total number of animation buffers.
- int src1 - Number of the second source buffer in range from 0 to the total number of animation buffers.
- float weight - Interpolation weight.
void mulBuffer (int dst, int src0, int src1, float weight)
Fills the destination buffer by the following formulas:
dst_pos = src0_pos + src1_pos * weight;
dst_rot = slerp(src0_rot,src0_rot * src1_rot,weight);
dst_scale = slerp(src0_scale,src0_scale * src1_scale,weight);
Arguments
- int dst - Destination buffer.
- int src0 - Source0 buffer.
- int src1 - Source1 buffer.
- float weight - Interpolation weight.
void play ()
Continues playback of the animation, if it was paused, or starts playback if it was stopped.void removeBuffer (int num)
Removes an animation buffer.Arguments
- int num - Buffer ID.
void removeLayer (int num)
Removes an animation layer.Arguments
- int num - Layer ID.
int save (string name)
Saves a mesh into a specified *.smesh or *.sanim file.Arguments
- string name - Path to the skinned mesh file.
Return value
1 if the skinned mesh is successfully saved; otherwise, 0.void setAnimationID (int id)
Sets the previously loaded animation to the current layer. This variant is faster than setAnimation(), but works only after animation was set once. The ID of the animation is get via getAnimationID().Arguments
- int id - Animation ID.
Examples
skinned_mesh.setNumLayers(2);
skinned_mesh.setLayer(0);
skinned_mesh.setAnimation("animations/agent_walk.sanim");
int id = skinned_mesh.getAnimationID();
skinned_mesh.setLayer(1);
skinned_mesh.setAnimationID(id);
int setAnimation (string filename)
Loads the animation and sets it for the current layer.- When setting the animation for the first time, the function loads it from the external file and requires the full path to the file (absolute or relative to the data folder).
- After loading once, it checks the list of loaded animations and if the name matches, uses the cached one. You can pass only the animation file name without the path when setting the previously loaded animation.
Arguments
- string filename - Path to the animation file.
Return value
Positive value if animation was successfully set, 0 otherwise.void setBoneChildsTransform (int bone, mat4 transform)
Sets transformation for the bone and all of its children (without considering node transformations). Take notice that bones can be scaled only uniformly.Arguments
- int bone - Bone number.
- mat4 transform - Transformation matrix.
void setBoneTransform (int bone, mat4 transform)
Sets a transformation matrix for a given bone (without considering node transformations). Take notice that a bone can be scaled only uniformly.Arguments
- int bone - Bone number.
- mat4 transform - Transformation matrix.
void setBones (int num, ivec4 bones, int surface)
Sets four bones used for control a specified vertex (up to 4 bones per vertex are supported).Arguments
- int num - Number of the vertex.
- ivec4 bones - Numbers of four bones.
- int surface - Number of the surface to which a vertex belongs.
void setBufferBoneTransformEnabled (int buffer, int bone, int enable)
Sets a buffer transformation enabled flag for a given bone.Arguments
- int buffer - Buffer number.
- int bone - Bone number.
- int enable - Enabled flag.
void setBufferBoneTransform (int buffer, int bone, mat4 transform)
Sets a transformation matrix for a specified bone from the given animation buffer. Take notice that a bone can be scaled only uniformly.Arguments
- int buffer - Buffer ID.
- int bone - Bone number.
- mat4 transform - Transformation matrix for a bone.
void setBuffer (int buffer, int layer)
Applies bone transformations from a given buffer to a given layer. If layer ID is equal to -1, then buffer is applied to the resulting animation.Arguments
- int buffer - Buffer ID.
- int layer - Layer ID.
void setControlled (int c)
Sets a value indicating if the animation should be controlled by a parent ObjectMeshSkinned (useful for attaching clothes to a character body).Arguments
- int c - Control flag (0 by default).
void setFrameBoneTransformEnabled (int bone, int enabled)
Sets a frame transformation enabled flag for a given bone.Arguments
- int bone - Bone number.
- int enabled - Enabled flag.
void setFrameBoneTransform (int bone, mat4 transform)
Sets a transformation matrix for a given bone. The difference from setBoneTransform() is that this method takes into account only the transformation in the current animation layer (no blending is done). Take notice that a bone can be scaled only uniformly.Arguments
- int bone - Bone number.
- mat4 transform - Transformation matrix.
float setFrame (float time, int from, int to)
Sets a frame of the current animation layer. If needed, interpolation between two frames will be done.Arguments
- float time - The number of the frame in the "from-to" interval. If float argument is passed, animation is interpolated between nearby frames. 0 means the from frame. From larger values a residue of a modulo (from-to) is calculated. If a negative value is provided, interpolation will be done from the current frame to the from frame.
- int from - Start frame. -1 means the initial frame of animation (0, bind pose).
- int to - End frame. -1 means the last frame of animation.
Return value
Frame number.void setIndex (int num, int index, int surface)
Updates a vertex index by its number.Arguments
- int num - Index number in the index buffer.
- int index - New vertex index.
- int surface - Surface number.
void setLayer (int layer)
Sets the current animation layer. This method should be called when you want to change properties of some layer: set weight and animation.Arguments
- int layer - Layer number.
void setLoop (int mode)
Sets a value indicating if the animation should be looped.Arguments
- int mode - Positive number to loop the animation, 0 to play it only once (0 by default).
void setNormal (int num, vec3 normal, int surface)
Updates a normal vector for a given vertex.Arguments
- int num - Number of the vertex.
- vec3 normal - Normal vector.
- int surface - Number of the surface to which a vertex belongs.
void setNumBuffers (int num)
Allocates a given number of animation buffers.Arguments
- int num - Number of buffers to be allocated.
void setNumLayers (int layers)
Sets the number of animation layers for blending.Arguments
- int layers - Number of animation layers.
void setNumWeights (int num, int num_weights, int surface)
Sets the number of bones that control a specified vertex (up to 4 bones per vertex are supported).Arguments
- int num - Number of the vertex.
- int num_weights - The number of bone weights to use (up to 4).
- int surface - Number of the surface to which a vertex belongs.
void setSpeed (float speed)
Updates multiplier for animation playback speed. This time is measured in animation frames per second. The default is 1.0.Arguments
- float speed - New multiplier for animation playback speed (1.0 by default). Negative value determines reverse playback.
void setSurfaceTransform (mat4 transform, int surface)
Transformation of the mesh surface.Arguments
- mat4 transform - Transformation matrix.
- int surface - The surface number.
void setTangent (int num, vec4 tangent, int surface)
Updates a tangent vector for a given vertex.Arguments
- int num - Number of the vertex.
- vec4 tangent - Tangent vector. The vector's w component is set to 0.
- int surface - Number of the surface to which a vertex belongs.
void setTexCoord (int num, vec4 texcoord, int surface)
Updates texture coordinates for a given vertex.Arguments
- int num - Number of the vertex.
- vec4 texcoord - Texture coordinates (for 2 UV sets).
- int surface - Number of the surface to which a vertex belongs.
void setTime (float time)
Sets the time for animation. This time is measured in animation frames. When the time is set to be between frames, animation is blended. If the time is set outside the animation frame range, the animation is looped.Arguments
- float time - Animation time.
void setVertex (int num, vec3 xyz, int surface)
Updates coordinates of a given vertex.Arguments
- int num - Number of the vertex.
- vec3 xyz - Position coordinates of the vertex.
- int surface - Number of the surface to which a vertex belongs.
void setWeight (float weight)
Sets a weight for the current animation layer.Arguments
- float weight - Blending weight. Note that this weight may be more than 1, however, it is recommended to use values from the range [0; 1] only.
void setWeights (int num, vec4 weights, int surface)
Sets four bone weights used for control a specified vertex (up to 4 bones per vertex are supported).Arguments
- int num - Number of the vertex.
- vec4 weights - Four bone weights.
- int surface - Number of the surface to which a vertex belongs.
void setWorldBoneChildsTransform (int bone, mat4 transform)
Sets transformation for the bone and all of its children in the world coordinate space (considering node transformations). Take notice that bones can be scaled only uniformly.Arguments
- int bone - Bone number.
- mat4 transform - Transformation matrix.
void setWorldBoneTransform (int bone, mat4 transform)
Applies transformation to a bone in the world coordinate space. Take notice that a bone can be scaled only uniformly.Arguments
- int bone - Bone number.
- mat4 transform - Transformation matrix in the world space.