Class TSkinNode

Unit

Declaration

type TSkinNode = class(TAbstractChildNode)

Description

Defines how a set of joints influences meshes, thus enabling skinned animation in a way that is simple, efficient and perfectly aligned with glTF. See skinned animation documentation for usage details.

Hierarchy

Overview

Fields

Public nested const DefaultAnimationSamplingForBox = 30;
Public InternalUsesShadersMaxJoints: Cardinal;
Public AnimationSamplingForBox: Cardinal;

Methods

Protected function DirectEnumerateActive(Func: TEnumerateChildrenFunction): Pointer; override;
Protected procedure BeforeTraverse(StateStack: TX3DGraphTraverseStateStack); override;
Protected procedure AfterTraverse(StateStack: TX3DGraphTraverseStateStack); override;
Public destructor Destroy; override;
Public procedure CreateNode; override;
Public class function ClassX3DType: String; override;
Public procedure SetJoints(const Value: array of TTransformNode);
Public procedure SetInverseBindMatrices(const Value: array of TMatrix4); overload;
Public procedure SetInverseBindMatrices(const Value: TMatrix4List); overload;
Public procedure SetShapes(const Value: array of TAbstractShapeNode);

Properties

Public property FdJoints: TMFNode read FFdJoints;
Public property FdInverseBindMatrices: TMFMatrix4f read FFdInverseBindMatrices;
Public property FdShapes: TMFNode read FFdShapes;
Public property FdSkeleton: TSFNode read FFdSkeleton;
Public property Skeleton: TAbstractGroupingNode read GetSkeleton write SetSkeleton;

Description

Fields

Public nested const DefaultAnimationSamplingForBox = 30;

This item has no description.

Public InternalUsesShadersMaxJoints: Cardinal;

This item has no description.

Public AnimationSamplingForBox: Cardinal;

Which animation frames to sample when calculating bounding box of the animation.

In order to have correct frustum culling, we need to know the bounding box of the animation. See https://castle-engine.io/skin#_you_need_to_assign_proper_bounding_box_explicitly . Also we don't want to spend too much time calculating it.

Solution: For each animation, we calculate the bounding box of:

  • first frame

  • last frame

  • every AnimationSamplingForBox frame.

E.g. when AnimationSampleForBox = 10, we sample frame 10, 20, 30 etc. (in addition to the first (0) and last frames).

  • Set this to 1 to sample every frame, which is most correct, but also the slowest.

  • Set this to some large number to sample less frames.

  • As a special case, set this to 0 to sample no frames at all, not even the first and last frame.

    This means that if the skin animation will be done by shaders (GPU), then the "T-pose" of the animation determines the object bounding box for the purpose of frustum culling.

    This is fastest, but also incorrect for many real models and animations.

)

Currently this is used only when creating TSkinNode from glTF animation. TODO: But we plan to support this always, regardless of how the skin node was created.

By default this is DefaultAnimationSamplingForBox.

Methods

Protected function DirectEnumerateActive(Func: TEnumerateChildrenFunction): Pointer; override;

function ShapeBoundingBoxInInstance(const ShapeIndex: Integer; const Instance: TCastleSceneInstance): TBox3D;

Protected procedure BeforeTraverse(StateStack: TX3DGraphTraverseStateStack); override;

This item has no description. Showing description inherited from TX3DNode.BeforeTraverse.

Override these methods to determine what happens when given node is traversed during Traverse call. The main use of this is to operate on TX3DGraphTraverseStateStack.

Remember to always call inherited when overriding. In BeforeTraverse and MiddleTraverse you should call inherited at the beginning, in AfterTraverse inherited should be called at the end.

Besides changing StateStack.Top fields, you can do push/pop on the stack. Remember that if you do StateStack.Push in BeforeTraverse, and then you must call StateStack.Pop in AfterTraverse.

Protected procedure AfterTraverse(StateStack: TX3DGraphTraverseStateStack); override;

This item has no description.

Public destructor Destroy; override;

This item has no description.

Public procedure CreateNode; override;

Create node fields and events.

Public class function ClassX3DType: String; override;

This item has no description. Showing description inherited from TX3DNode.ClassX3DType.

Node type name in VRML/X3D, for this class. Normal VRML/X3D node classes should override this to return something non-empty, and then X3DType automatically will return the same value.

Empty for classes that don't have a hardcoded VRML/X3D node name, like a special TX3DUnknownNode. Such special classes should override then X3DType to return actual non-empty name there.

You usually should call X3DType. The only use of this method is that it works on classes (it's "class function"), without needing at actual instance.

Public procedure SetJoints(const Value: array of TTransformNode);

When the joints are transformed (moved, rotated, scaled), the skin (meshes listed in FdShapes) is updated accordingly.

Public procedure SetInverseBindMatrices(const Value: array of TMatrix4); overload;

For each joint, an "inverse bind matrix" may be specified, which transforms the mesh into the local space of the joint.

The precise mathematical meaning of this follows the glTF 2.0 specification. The glTF 2.0 API Reference Guide also contains a great explanation of how this is used.

Either this array must be empty (equivalent to all values being identity matrix) or the count of this array must be equal to the count of FdJoints.

Public procedure SetInverseBindMatrices(const Value: TMatrix4List); overload;

For each joint, an "inverse bind matrix" may be specified, which transforms the mesh into the local space of the joint.

The precise mathematical meaning of this follows the glTF 2.0 specification. The glTF 2.0 API Reference Guide also contains a great explanation of how this is used.

Either this array must be empty (equivalent to all values being identity matrix) or the count of this array must be equal to the count of FdJoints.

Public procedure SetShapes(const Value: array of TAbstractShapeNode);

Shapes whose geometries are affected by the skinned animation, that is: their vertexes move to follow the joints that are associated with them.

Only shapes with geometries that have SkinWeights0 and SkinJoints0 fields are allowed here. This means these geometry nodes: TAbstractComposedGeometryNode (with its numerous descendants, all "meshes" that are composed of triangles, quads, faces...), TIndexedLineSetNode, TLineSetNode and TPointSetNode.

The geometries within these shapes are affected by this skinned animation. Their SkinJoints0 indexes refer to our FdJoints.

Note that you can place here only shape nodes, not groups or hierarchies of them (e.g. TGroupNode or TTransformNode). This is a deliberate constraint to make working of this node obvious.

This also matches the glTF usage, where the meshes affected by one skin are always within one and the same transformation. glTF specification says "Only the joint transforms are applied to the skinned mesh; the transform of the skinned mesh node MUST be ignored." which in practice forces treating all skinned shapes as if they were direct children alongside the skeleton root.

We make it more explicit in our design: the FdShapes are explicitly direct children of the TSkinNode. So the shapes are affected by the transformations of the TSkinNode. Any further transformation of shapes has to happen through the skinned animation (joints affecting shapes vertexes according to weights).

Note that you can also place TShapeNode instances within the Skeleton hierarchy. Such shapes are not affected by the skinned animation, they are just rigid 3D shapes attached to the joints (like a sword may be attached to the avatar's hand).

Properties

Public property FdJoints: TMFNode read FFdJoints;

Internal wrapper for property Joints. This wrapper API may change, we advise to access simpler Joints instead, if it is defined (TODO: for now, some field types do not have a simpler counterpart).

Public property FdInverseBindMatrices: TMFMatrix4f read FFdInverseBindMatrices;

Internal wrapper for property InverseBindMatrices. This wrapper API may change, we advise to access simpler InverseBindMatrices instead, if it is defined (TODO: for now, some field types do not have a simpler counterpart).

Public property FdShapes: TMFNode read FFdShapes;

Internal wrapper for property Shapes. This wrapper API may change, we advise to access simpler Shapes instead, if it is defined (TODO: for now, some field types do not have a simpler counterpart).

Public property FdSkeleton: TSFNode read FFdSkeleton;

Internal wrapper for property Skeleton. This wrapper API may change, we advise to access simpler Skeleton instead, if it is defined (TODO: for now, some field types do not have a simpler counterpart).

Public property Skeleton: TAbstractGroupingNode read GetSkeleton write SetSkeleton;

Common root of the joints hierarchy.


Generated by PasDoc 0.16.0-snapshot.