Castle Game EngineIntroduction Units Class Hierarchy Classes, Interfaces, Objects and Records Types Variables Constants Functions and Procedures Identifiers |
Class TCastlePrecalculatedAnimation
Unit
CastlePrecalculatedAnimation
Declaration
type TCastlePrecalculatedAnimation = class(TCastlePrecalculatedAnimationCore)
Description
A "precalculated" animation done by interpolating between a number of 3D model states.
After constructing an object of this class, you must actually load it's animation by calling Load or LoadFromFile or LoadFromEvents etc.
When loading you must provide one or more X3D models with their associated times. Animation will show a transition from the first model to the last. If models are "structurally equal" then the transition between two successive models will be smooth, otherwise a sudden change will be shown. "Structurally equal" means the same nodes hierarchy, the same names of nodes, the same values of all fields (with the exception of fields that are floating-point based and so can be interpolated, for example SFFloat, SFVec3f and equivalent MFXxx fields). For multi-valued fields (MFXxx) that can be interpolated: note that values of items may differ, but still the counts of items must be equal.
This creates a list of Scenes such that
the first scene on the list is exactly the 1st object
the last scene on the list is exactly the last object
intermediate scenes are accordingly interpolated between the two surrounding "predefined" by you scenes
For example, first object may be a small sphere with blue color, the other object may be a larger sphere with white color, and the simplest times are 0.0 for the 1st scene and 1.0 for the 2nd scene. The animation will show the blue sphere growing larger and fading into the white color. Of course, any kind of models is allowed — e.g. it can be a walking man at various stages, so in effect you get an animation of walking man.
A special case when you pass only one scene to this class is allowed (it may be handy in some situations). This will obviously produce just a still result, i.e. resulting TCastlePrecalculatedAnimation will be just a wrapper around single TCastleScene instance.
For more information see our engine documentation on [http://castle-engine.sourceforge.net/engine_doc.php]. Specifically the section "Non-interactive precalculated animation: TCastlePrecalculatedAnimation ", [http://castle-engine.sourceforge.net/vrml_engine_doc/output/xsl/html/section.animation_precalculated.html].
Hierarchy
Overview
Methods
 |
procedure LoadCore( GetRootNodeWithTime: TGetRootNodeWithTime; RootNodesCount: Cardinal; AOwnsFirstRootNode: boolean; ScenesPerTime: Cardinal; const EqualityEpsilon: Single); |
 |
function HeightCollision(const Position, GravityUp: TVector3Single; const TrianglesToIgnoreFunc: T3DTriangleIgnoreFunc; out AboveHeight: Single; out AboveGround: P3DTriangle): boolean; override; |
 |
function MoveCollision( const OldPos, ProposedNewPos: TVector3Single; out NewPos: TVector3Single; const IsRadius: boolean; const Radius: Single; const OldBox, NewBox: TBox3D; const TrianglesToIgnoreFunc: T3DTriangleIgnoreFunc): boolean; override; |
 |
function MoveCollision( const OldPos, NewPos: TVector3Single; const IsRadius: boolean; const Radius: Single; const OldBox, NewBox: TBox3D; const TrianglesToIgnoreFunc: T3DTriangleIgnoreFunc): boolean; override; |
 |
function SegmentCollision(const Pos1, Pos2: TVector3Single; const TrianglesToIgnoreFunc: T3DTriangleIgnoreFunc; const ALineOfSight: boolean): boolean; override; |
 |
function SphereCollision(const Pos: TVector3Single; const Radius: Single; const TrianglesToIgnoreFunc: T3DTriangleIgnoreFunc): boolean; override; |
 |
function BoxCollision(const Box: TBox3D; const TrianglesToIgnoreFunc: T3DTriangleIgnoreFunc): boolean; override; |
 |
function RayCollision(const RayOrigin, RayDirection: TVector3Single; const TrianglesToIgnoreFunc: T3DTriangleIgnoreFunc): TRayCollision; override; |
 |
constructor Create(AOwner: TComponent); override; |
 |
constructor CreateCustomCache(AOwner: TComponent; ACache: TGLRendererContextCache); |
 |
destructor Destroy; override; |
 |
procedure Load( RootNodes: TX3DNodeList; AOwnsFirstRootNode: boolean; ATimes: TSingleList; ScenesPerTime: Cardinal; const EqualityEpsilon: Single); |
 |
procedure LoadFromEvents( RootNode: TX3DRootNode; AOwnsRootNode: boolean; const ATimeBegin, ATimeEnd: Single; ScenesPerTime: Cardinal; const EqualityEpsilon: Single; const ProgressTitle: string); |
 |
procedure LoadStatic(RootNode: TX3DNode; AOwnsRootNode: boolean); |
 |
procedure LoadFromFile(const URL: string; const AllowStdIn: boolean; const LoadTime: boolean; const Smoothness: Float); |
 |
procedure LoadFromFile(const URL: string; const AllowStdIn: boolean; const LoadTime: boolean); |
 |
procedure Close; |
 |
function ScenesCount: Integer; |
 |
function FirstScene: TCastleScene; |
 |
function LastScene: TCastleScene; |
 |
procedure PrepareResources(Options: TPrepareResourcesOptions; ProgressStep: boolean; BaseLights: TAbstractLightInstancesList); override; |
 |
function PrepareResourcesSteps: Cardinal; override; |
 |
procedure FreeResources(Resources: TSceneFreeResources); |
 |
procedure GLContextClose; override; |
 |
function TimeDuration: Single; |
 |
function TimeDurationWithBack: Single; |
 |
function Scene(const Time: Single): TCastleScene; |
 |
function Scene(const Time: Single; const Loop: boolean): TCastleScene; |
 |
function CurrentScene: TCastleScene; |
 |
function Attributes: TSceneRenderingAttributes; |
 |
function BoundingBox: TBox3D; override; |
 |
procedure BeforeNodesFree; |
 |
procedure ChangedAll; |
 |
function Info( ATriangleVerticesCounts, ABoundingBox, AManifoldAndBorderEdges: boolean): string; |
 |
function Press(const Event: TInputPressRelease): boolean; override; |
 |
function Release(const Event: TInputPressRelease): boolean; override; |
 |
procedure Update(const SecondsPassed: Single; var RemoveMe: TRemoveType); override; |
 |
procedure ResetTimeAtLoad(const ForceTimeOrigin: boolean = false); |
 |
procedure ResetTime(const NewValue: TFloatTime); |
 |
procedure Render(const Frustum: TFrustum; const Params: TRenderParams); override; |
 |
procedure RenderShadowVolume( ShadowVolumeRenderer: TBaseShadowVolumeRenderer; const ParentTransformIsIdentity: boolean; const ParentTransform: TMatrix4Single); override; |
 |
procedure UpdateGeneratedTextures( const RenderFunc: TRenderFromViewFunction; const ProjectionNear, ProjectionFar: Single; const OriginalViewport: TRectangle); override; |
 |
procedure VisibleChangeNotification(const Changes: TVisibleChanges); override; |
 |
function Dragging: boolean; override; |
Properties
Description
Methods
 |
procedure LoadCore( GetRootNodeWithTime: TGetRootNodeWithTime; RootNodesCount: Cardinal; AOwnsFirstRootNode: boolean; ScenesPerTime: Cardinal; const EqualityEpsilon: Single); |
Internal version of Load routines, feasible to load from both ready RootNodes array and to automatically generate RootNodes on the fly.
GetRootNodeWithTime will be called with indexes from 0 to RootNodesCount - 1. It's guaranteed that it will be called in this order (from 0 upwards to RootNodesCount - 1) and will be called exactly once for each index. So it's safe to e.g. create RootNode with some costly operation there.
Note that RootNode passed to GetRootNodeWithTime becomes owned by this class. Well, you can get control over only the first one, by AOwnsFirstRootNode, but you cannot free it anyway while this is loaded.
See Load for more information, including the meaning of EqualityEpsilon.
|
 |
function MoveCollision( const OldPos, NewPos: TVector3Single; const IsRadius: boolean; const Radius: Single; const OldBox, NewBox: TBox3D; const TrianglesToIgnoreFunc: T3DTriangleIgnoreFunc): boolean; override; |
|
 |
constructor Create(AOwner: TComponent); override; |
|
 |
constructor CreateCustomCache(AOwner: TComponent; ACache: TGLRendererContextCache); |
Constructor that allows you to pass your own Cache instance.
|
 |
destructor Destroy; override; |
|
 |
procedure Load( RootNodes: TX3DNodeList; AOwnsFirstRootNode: boolean; ATimes: TSingleList; ScenesPerTime: Cardinal; const EqualityEpsilon: Single); |
Load the animation scenes. Must be called (this or some other loading routine like LoadFromFile) before you do almost anything with this object. Loaded changes to True after calling this.
Parameters
- RootNodes
- Models describing the "predefined" frames of animation. They must descend from TX3DRootNode.
For all nodes except the first: They are always owned by this class — that's needed, because actually we may do some operations on these models when building animation (including even freeing some RootNodes, if we will find that they are equivalent to some other RootNodes). They all must point to different objects.
You must supply at least one item here (you cannot make an animation from 0 items).
- Times
- Array specifying the point of time for each "predefined" frame. Length of this array must equal to length of RootNodes array.
- ScenesPerTime
- This says how many scenes will be used for period of time equal to 1.0. This will determine Scenes.Count. RootNodes[0] always takes Scenes[0] and RootNodes[High(RootNodes)] always takes Scenes[Scenes.High].
Note that if we will find that some nodes along the way are exactly equal, we may drop scenes count between — because if they are both equal, we can simply render the same scene for some period of time. This is an optimization, and you shouldn't notice it at all, since rendeting will be the same (but less memory-consuming).
Special value ScenesPerTime = 0 means that you want to have only the RootNodes you explicitly passed in the scene, not more. No more intermediate scenes will ever be created. This creates a trivial animation that suddenly jumps from one RootNode to the next at specified times. It may be useful if you already have generated a lot of RootNodes, densely distributed over time, and you don't need TCastlePrecalculatedAnimation to insert any more scenes.
- EqualityEpsilon
- This will be used for comparing fields, to decide if two fields (and, consequently, nodes) are equal. It will be simply passed to TX3DField.Equals.
You can pass here 0 to use exact comparison, but it's advised to use here something > 0. Otherwise we could waste display list memory (and loading time) for many frames of the same node that are in fact equal.
|
 |
procedure LoadFromEvents( RootNode: TX3DRootNode; AOwnsRootNode: boolean; const ATimeBegin, ATimeEnd: Single; ScenesPerTime: Cardinal; const EqualityEpsilon: Single; const ProgressTitle: string); |
Load precalculated animation by playing a single VRML/X3D file with events (interpolators, TimeSensor and such working). Conceptually, this "records" interactive animation stored in VRML/X3D file into TCastlePrecalculatedAnimation precalculated animation.
ATimeBegin, ATimeEnd tell what time slice should be recorded. They will also set TimeBegin and TimeEnd properties.
Parameters
- ScenesPerTime
- tells with what density should the animation be recorded. See Load for ScenesPerTime, EqualityEpsilon precise documentation. Note that special value ScenesPerTime = 0 is interpreted here as "record only one, initial frame".
- ProgressTitle
- When <> '' we will use Progress.Init, Step, Fini to display nice progress of operation.
|
 |
procedure LoadStatic(RootNode: TX3DNode; AOwnsRootNode: boolean); |
Load a dumb animation that consists of only one frame (so actually there's no animation, everything is static).
This just calls Load with parameters such that
RootNodes list contains one specified node
Times contain only one item 0.0
ScenesPerTime and EqualityEpsilon have some unimportant values — they are not meaningfull when you have only one scene
This is usefull when you know that you have a static scene, but still you want to treat it as TCastlePrecalculatedAnimation.
|
 |
procedure LoadFromFile(const URL: string; const AllowStdIn: boolean; const LoadTime: boolean; const Smoothness: Float); |
Load animation parameters (models to use, times to use and such) from given file.
Various file formats are possible, everything that can be handled by Load3DSequence, in particular simple 3D model files, MD3, kanim (described on [http://castle-engine.sourceforge.net/kanim_format.php]).
If you need more control over loading, for example you want to change some parameters at loading (for example, ScenesPerTime and EqualityEpsilon of kanim files), you should use more flexible (and less comfortable to use) LoadFromFileToVars class procedure (specialized for kanim files) or Load3DSequence (if you want to handle any files).
Loaded property changes to True after calling this.
Parameters
- AllowStdIn
- If
True , then URL = '-' is understood as "standard input".
- LoadTime
- If
True then loading changes current TimeLoop and TimeBackwards properties. Sometimes this is sensible (you want to allow control over them from the file), sometimes not (e.g. you set suitable values for them by code).
Note that, independent of this, you can always change TimeLoop and TimeBackwards properties later, since these properties are writeable at any time.
- Smoothness
- Scales the number of scenes created per second. Values > 1 make better quality but also use more memory. If this parameter isn't given, we use global AnimationSmoothness (which is by default 1, but may be globally changed).
|
 |
procedure LoadFromFile(const URL: string; const AllowStdIn: boolean; const LoadTime: boolean); |
|
 |
procedure Close; |
This releases all resources allocared by Load (or LoadFromFile). Loaded property changes to False after calling this.
It's safe to call this even if Loaded is already False — then this will do nothing.
|
 |
function ScenesCount: Integer; |
|
 |
function FirstScene: TCastleScene; |
Just a shortcut for Scenes[0].
|
 |
procedure PrepareResources(Options: TPrepareResourcesOptions; ProgressStep: boolean; BaseLights: TAbstractLightInstancesList); override; |
Prepare all scenes for rendering. Basically, this calls PrepareResources (...) for all Scenes.
There's also a special memory (and prepare time) optimization used for prManifoldAndBorderEdges: we use the fact that animation scenes are "structurally equal", and so prepare and share one manifold edges information for all scenes.
ProgressStep = True is especially useful with this: we'll call Progress.Step then after preparing each scene. For portability, always check PrepareResourcesSteps, but for now this is just always equal ScenesCount.
|
 |
function PrepareResourcesSteps: Cardinal; override; |
|
 |
procedure FreeResources(Resources: TSceneFreeResources); |
Free resources for all scenes, it's useful if you know that you will not need some allocated resources anymore and you want to conserve memory use.
See TCastleSceneCore.FreeResource documentation for a description of what are possible resources to free.
|
 |
procedure GLContextClose; override; |
Close anything associated with current OpenGL context in this class. This calls GLContextClose on every Scenes[], and additionally may close some other internal things here.
|
 |
function TimeDurationWithBack: Single; |
This is TimeDuration * 2 if TimeBackwards, otherwise it's just TimeDuration. In other words, this is the time of the one "full" (forward + backward) animation.
|
 |
function Scene(const Time: Single): TCastleScene; |
Appropriate scene from Scenes based on given Time. If Time is between given TimeBegin and TimeEnd, then this will be appropriate scene in the middle.
For Time outside the range TimeBegin .. TimeEnd behavior depends on TimeLoop and TimeBackwards properties:
Overloaded version with explicit Loop parameter ignores the TimeLoop property. This way you can force looping (or force not looping), regardless of the TimeLoop property, so also regardless of loop setting in kanim file.
|
 |
function Scene(const Time: Single; const Loop: boolean): TCastleScene; |
|
 |
function CurrentScene: TCastleScene; |
Appropriate scene from Scenes based on current Time. This is just a shortcut for Scene(Time), useful if you track animation time in our Time property.
|
 |
function Attributes: TSceneRenderingAttributes; |
Attributes controlling rendering. See TSceneRenderingAttributes and TRenderingAttributes for documentation of properties.
You can change properties of this object at any time, but beware that some changes may force time-consuming regeneration of some things (like OpenGL display lists) in the nearest Render of the scenes. So explicitly calling PrepareResources may be useful after changing these Attributes.
Note that Attributes may be accessed and even changed when the scene is not loaded (e.g. before calling Load / LoadFromFile). Also, Attributes are preserved between various animations loaded.
|
 |
function BoundingBox: TBox3D; override; |
The sum of bounding boxes of all animation frames.
Result of this function is cached, which means that it usually returns very fast. But you have to call ChangedAll when you changed something inside Scenes[] using some direct Scenes[].RootNode operations, to force recalculation of this box.
|
 |
procedure BeforeNodesFree; |
Call this before directly freeing some VRML nodes in animation scenes.
|
 |
procedure ChangedAll; |
Call this when you changed something inside Scenes[] using some direct Scenes[].RootNode operations. This calls TCastleScene.ChangedAll on all Scenes[] and invalidates some cached things inside this class.
|
 |
function Info( ATriangleVerticesCounts, ABoundingBox, AManifoldAndBorderEdges: boolean): string; |
Returns some textual info about this animation. Similar to TCastleScene.Info.
|
 |
function Press(const Event: TInputPressRelease): boolean; override; |
Handling key and mouse events.
We pass key and mouse events only if there's exactly one scene (ScenesCount = 1), as there's no sensible way of activating VRML/X3D events when TCastlePrecalculatedAnimation contains more than one scene. (Precalculated animation of this class, and interactive animation by TCastleSceneCore.ProcessEvents do not mix sensibly.)
So when ScenesCount = 1, we simply pass key and mouse events to the only Scene[0]. Be sure to turn on Scene[0].ProcessEvents := true if you want to make actual use of it.
|
 |
procedure Update(const SecondsPassed: Single; var RemoveMe: TRemoveType); override; |
|
 |
procedure ResetTimeAtLoad(const ForceTimeOrigin: boolean = false); |
Set Time to initial value after loading a world.
|
 |
procedure ResetTime(const NewValue: TFloatTime); |
Set Time to arbitrary value.
|
 |
procedure UpdateGeneratedTextures( const RenderFunc: TRenderFromViewFunction; const ProjectionNear, ProjectionFar: Single; const OriginalViewport: TRectangle); override; |
|
 |
procedure VisibleChangeNotification(const Changes: TVisibleChanges); override; |
|
 |
function Dragging: boolean; override; |
|
Properties
 |
property Loaded: boolean read FLoaded; |
|
 |
property OwnsFirstRootNode: boolean
read FOwnsFirstRootNode write SetOwnsFirstRootNode; |
Is the RootNode in first scene owned by this TCastlePrecalculatedAnimation instance? If yes, it will be freed at closing the animation. Otherwise, you are responsible for freeing it yourself (but you cannot do this while animation is loaded, anyway).
|
 |
property TimeBegin: Single read FTimeBegin; |
First and last time that you passed to Load (or that were read from file by LoadFromFile). In other words, Times[0] and Times[High(Times)].
|
 |
property TimeEnd: Single read FTimeEnd; |
|
 |
property Time: TFloatTime read FTime; |
Current time of the animation. Although you do not have to use it: you can always acccess any point in time of the animation by Scene. But sometimes tracking the current time here is most natural and comfortable.
When we have exactly one scene in Scenes, our methods (ResetTime, ResetTimeAtLoad and Update) will synchronize Scenes[0].Time always to the same value as our own Time. This makes time-dependent nodes (like TimeSensor, MovieTexture etc.) inside this scene work Ok.
|
 |
property TryFirstSceneDynamic: boolean
read FTryFirstSceneDynamic write FTryFirstSceneDynamic default false; |
Turn this on to treat specially the case when a single scene (Scenes.Count = 1) is loaded: we will set this scene's Static = False . This allows you to enable VRML/X3D events and dynamically change the scene in this very special case. The normal behavior, when we load many scenes (or when this property is False ), is to set all children scenes Static = True .
Practically, this is useful only for tools like view3dscene, that want to have full VRML/X3D events when possible, and at the same time they want to load everything as TCastlePrecalculatedAnimation, for ease of coding.
To put it simply, just don't use this in normal programs – it's a hack.
Although Static can be later changed, but changing it (after loading) to False is expensive (needs ChangedAll, that also recalculates shape tree, forces shape octree and other recalculations). That's why this property is needed, it sets Static correctly before loading the contents.
|
 |
property TimePlayingSpeed: Single read FTimePlayingSpeed write FTimePlayingSpeed default 1.0; |
|
 |
property TimeLoop: boolean read FTimeLoop write FTimeLoop default true; |
See Scene for precise description what this property does.
|
 |
property TimeBackwards: boolean
read FTimeBackwards write FTimeBackwards default false; |
See Scene for precise description what this property does.
|
 |
property CollisionUseLastScene: boolean
read FCollisionUseLastScene
write FCollisionUseLastScene default false; |
Should collision checking check also last animation frame.
Regardless of this value, we always check collision with the first animation frame (FirstScene), of course only when FirstScene.OctreeCollisions is initialized, and only if GetCollides (which includes GetExists).
When CollisionUseLastScene is True , we will also check collision with the last animation frame's octree, i.e. LastScene.OctreeCollisions. (Of course, only if it's initialized, e.g. by adding ssDynamicCollisions to the LastScene.Spatial property.) So when CollisionUseLastScene , collision checking sees the animation as a sum of first and last frames geometry. CollisionUseLastScene is useful if the object is moving, but the move is very slight, so that the sum of first and last scenes geometry is good enough approximation of the whole geometry at any point of the animation.
Although it seems like a totally dumb way to check for collisions, it's suitable for many purposes (see e.g. uses on "castle hall" level), it's simple and not memory-consuming, and you don't have to take any action when animation frame changes (because Time changes don't change the colliding geometry, so the animation is static from the point of view of collision checking routines).
TODO: In the future other collision methods may be available. First of all, checking with sum of all bounding boxes, or with particular scene time box, should be available.
|
 |
property ShadowMaps: boolean read FShadowMaps write SetShadowMaps default true; |
At loading, process the animation to support shadow maps. See TCastleSceneCore.ShadowMaps and related properties for documentation.
|
 |
property InitialViewpointIndex: Cardinal
read FInitialViewpointIndex write FInitialViewpointIndex; |
|
 |
property InitialViewpointName: string
read FInitialViewpointName write FInitialViewpointName; |
|
Generated by PasDoc 0.14.0.
|