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
- TObject
- TPersistent
- TX3DFileItem
- TX3DNode
- TAbstractNode
- TAbstractChildNode
- TSkinNode
Overview
Fields
![]() |
nested const DefaultAnimationSamplingForBox = 30; |
![]() |
InternalUsesShadersMaxJoints: Cardinal; |
![]() |
AnimationSamplingForBox: Cardinal; |
Methods
![]() |
function DirectEnumerateActive(Func: TEnumerateChildrenFunction): Pointer; override; |
![]() |
procedure BeforeTraverse(StateStack: TX3DGraphTraverseStateStack); override; |
![]() |
procedure AfterTraverse(StateStack: TX3DGraphTraverseStateStack); override; |
![]() |
destructor Destroy; override; |
![]() |
procedure CreateNode; override; |
![]() |
class function ClassX3DType: String; override; |
![]() |
procedure SetJoints(const Value: array of TTransformNode); |
![]() |
procedure SetInverseBindMatrices(const Value: array of TMatrix4); overload; |
![]() |
procedure SetInverseBindMatrices(const Value: TMatrix4List); overload; |
![]() |
procedure SetShapes(const Value: array of TAbstractShapeNode); |
Properties
![]() |
property FdJoints: TMFNode read FFdJoints; |
![]() |
property FdInverseBindMatrices: TMFMatrix4f read FFdInverseBindMatrices; |
![]() |
property FdShapes: TMFNode read FFdShapes; |
![]() |
property FdSkeleton: TSFNode read FFdSkeleton; |
![]() |
property Skeleton: TAbstractGroupingNode read GetSkeleton write SetSkeleton; |
Description
Fields
![]() |
nested const DefaultAnimationSamplingForBox = 30; |
|
This item has no description. | |
![]() |
InternalUsesShadersMaxJoints: Cardinal; |
|
This item has no description. | |
![]() |
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:
E.g. when AnimationSampleForBox = 10, we sample frame 10, 20, 30 etc. (in addition to the first (0) and last frames).
) 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
![]() |
function DirectEnumerateActive(Func: TEnumerateChildrenFunction): Pointer; override; |
|
function ShapeBoundingBoxInInstance(const ShapeIndex: Integer; const Instance: TCastleSceneInstance): TBox3D; | |
![]() |
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 Besides changing StateStack.Top fields, you can do push/pop on the stack. Remember that if you do StateStack.Push in | |
![]() |
procedure AfterTraverse(StateStack: TX3DGraphTraverseStateStack); override; |
|
This item has no description. | |
![]() |
destructor Destroy; override; |
|
This item has no description. | |
![]() |
procedure CreateNode; override; |
|
Create node fields and events. | |
![]() |
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. | |
![]() |
procedure SetJoints(const Value: array of TTransformNode); |
|
When the joints are transformed (moved, rotated, scaled), the skin (meshes listed in FdShapes) is updated accordingly. | |
![]() |
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. | |
![]() |
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. | |
![]() |
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 The geometries within these shapes are affected by this skinned animation. Their 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
![]() |
property FdJoints: TMFNode read FFdJoints; |
|
Internal wrapper for property | |
![]() |
property FdInverseBindMatrices: TMFMatrix4f read FFdInverseBindMatrices; |
|
Internal wrapper for property | |
![]() |
property FdShapes: TMFNode read FFdShapes; |
|
Internal wrapper for property | |
![]() |
property FdSkeleton: TSFNode read FFdSkeleton; |
|
Internal wrapper for property | |
![]() |
property Skeleton: TAbstractGroupingNode read GetSkeleton write SetSkeleton; |
|
Common root of the joints hierarchy. | |
Generated by PasDoc 0.16.0-snapshot.

