Class TCastleSceneCore

Unit

Declaration

type TCastleSceneCore = class(TX3DEventsEngine)

Description

Loading and processing of a scene. Almost everything visible in your game will be an instance of TCastleScene, which is a descendant of this class that adds rendering capabilities.

This class provides a lot of functionality, like loading of the scene (Load method), animating it, performing collisions with the scene, and calculating things (like LocalBoundingBox).

The actual scene information (visible and collidable things) is inside X3D nodes graph contained within the RootNode. During the lifetime of the scene, this X3D graph can change (e.g. because of animations), and you can always change it by code too. E.g. you can freely change TTransformNode.Translation or add children by RootNode.AddChildren. The X3D nodes graph works like a DOM tree for rendering HTML documents: it's typically initialized from a file (3D model), but during the game execution it is dynamic, always changing.

This class takes care of performing the X3D events and routes mechanism (if ProcessEvents is True). This is what allows X3D graph to be animated, or even be interactive (respond to user actions). For a simple way to play animations, use the PlayAnimation method.

This class maintains a Shapes tree is always synchronized with the X3D nodes tree in RootNode. The Shapes tree provides a little simple view at the scene, sometimes easier (or faster) to iterate over.

Many results are cached, so querying them multiple times is fast, if the scene does not change (in a significant way) between each query. So you can query information like LocalBoundingBox, BoundingBox, VerticesCount... as often as you want to.

Hierarchy

Overview

Fields

Protected ScreenEffectNodes: TX3DNodeList;
Protected IsVisibleNow: boolean;
Protected GeneratedTextures: TGeneratedTextureList;
Public nested const DefaultShadowMapsDefaultSize = 256;

Methods

Protected function CreateShape(AGeometry: TAbstractGeometryNode; AState: TX3DGraphTraverseState; ParentInfo: PTraversingInfo): TShape; virtual;
Protected procedure UpdateHeadlightOnFromNavigationInfo;
Protected procedure InvalidateBackground; virtual;
Protected procedure ChangedTransform; override;
Protected procedure ChangeWorld(const Value: TSceneManagerWorld); override;
Protected procedure DoPointingDeviceSensorsChange; virtual;
Protected procedure ExecuteCompiledScript(const HandlerName: string; ReceivedValue: TX3DField); override;
Protected function LocalHeightCollision(const APosition, GravityUp: TVector3; const TrianglesToIgnoreFunc: TTriangleIgnoreFunc; out AboveHeight: Single; out AboveGround: PTriangle): boolean; override;
Protected function LocalMoveCollision( const OldPos, ProposedNewPos: TVector3; out NewPos: TVector3; const IsRadius: boolean; const Radius: Single; const OldBox, NewBox: TBox3D; const TrianglesToIgnoreFunc: TTriangleIgnoreFunc): boolean; override;
Protected function LocalMoveCollision( const OldPos, NewPos: TVector3; const IsRadius: boolean; const Radius: Single; const OldBox, NewBox: TBox3D; const TrianglesToIgnoreFunc: TTriangleIgnoreFunc): boolean; override;
Protected function LocalSegmentCollision(const Pos1, Pos2: TVector3; const TrianglesToIgnoreFunc: TTriangleIgnoreFunc; const ALineOfSight: boolean): boolean; override;
Protected function LocalSphereCollision(const Pos: TVector3; const Radius: Single; const TrianglesToIgnoreFunc: TTriangleIgnoreFunc): boolean; override;
Protected function LocalSphereCollision2D(const Pos: TVector2; const Radius: Single; const TrianglesToIgnoreFunc: TTriangleIgnoreFunc; const Details: TCollisionDetails): boolean; override;
Protected function LocalPointCollision2D(const Point: TVector2; const TrianglesToIgnoreFunc: TTriangleIgnoreFunc): boolean; override;
Protected function LocalBoxCollision(const Box: TBox3D; const TrianglesToIgnoreFunc: TTriangleIgnoreFunc): boolean; override;
Protected function LocalRayCollision(const RayOrigin, RayDirection: TVector3; const TrianglesToIgnoreFunc: TTriangleIgnoreFunc): TRayCollision; override;
Protected procedure LocalRender(const Params: TRenderParams); override;
Public constructor Create(AOwner: TComponent); override;
Public procedure Load(ARootNode: TX3DRootNode; AOwnsRootNode: boolean; const AResetTime: boolean = true);
Public procedure Load(const AURL: string; AllowStdIn: boolean = false; const AResetTime: boolean = true);
Public procedure Save(const AURL: string);
Public destructor Destroy; override;
Public function ShapesActiveCount: Cardinal;
Public function ShapesActiveVisibleCount: Cardinal;
Public function VerticesCount(OverTriangulate: boolean): Cardinal;
Public function TrianglesCount(OverTriangulate: boolean): Cardinal;
Public function ViewpointsCount: Cardinal;
Public function GetViewpointName(Idx: integer): string;
Public procedure MoveToViewpoint(Idx: integer; Animated: boolean = true);
Public procedure AddViewpointFromCamera(ACamera: TCamera; AName: string);
Public procedure BeforeNodesFree(const InternalChangedAll: boolean = false); override;
Public procedure NodeFreeRemovingFromAllParents(Node: TX3DNode);
Public procedure RemoveShape(Shape: TShape);
Public procedure ChangedAll; override;
Public procedure DoGeometryChanged(const Change: TGeometryChange; LocalGeometryShape: TShape); virtual;
Public procedure DoViewpointsChanged;
Public procedure DoBoundViewpointVectorsChanged;
Public procedure DoBoundNavigationInfoFieldsChanged; virtual;
Public procedure ScheduleChangedAll;
Public procedure BeginChangesSchedule;
Public procedure EndChangesSchedule;
Public function Info( ATriangleVerticesCounts, ABoundingBox: boolean; AManifoldAndBorderEdges: boolean): string; deprecated 'do not use this, better to construct a summary string yourself';
Public function InfoTriangleVerticesCounts: string; deprecated 'better to construct a string yourself, use TrianglesCount, VerticesCount';
Public function InfoBoundingBox: string; deprecated 'better to construct a string yourself, use BoundingBox.ToString';
Public function InfoManifoldAndBorderEdges: string; deprecated 'better to construct a string yourself, use EdgesCount';
Public procedure EdgesCount(out ManifoldEdges, BorderEdges: Cardinal);
Public function InternalOctreeRendering: TShapeOctree;
Public function InternalOctreeDynamicCollisions: TShapeOctree;
Public function InternalOctreeVisibleTriangles: TTriangleOctree;
Public function InternalOctreeStaticCollisions: TTriangleOctree;
Public function InternalOctreeCollisions: TBaseTrianglesOctree;
Public function UseInternalOctreeCollisions: boolean;
Public function GetViewpoint( out ProjectionType: TProjectionType; out CamPos, CamDir, CamUp, GravityUp: TVector3; const ViewpointDescription: string = ''): TAbstractViewpointNode;
Public function GetPerspectiveViewpoint( out CamPos, CamDir, CamUp, GravityUp: TVector3; const ViewpointDescription: string = ''): TAbstractViewpointNode;
Public procedure FreeResources(Resources: TSceneFreeResources); virtual;
Public procedure UnregisterScene(Node: TX3DNode);
Public function Press(const Event: TInputPressRelease): boolean; override;
Public function Release(const Event: TInputPressRelease): boolean; override;
Public function PointingDeviceActivate(const Active: boolean; const Distance: Single; const CancelAction: boolean = false): boolean; override;
Public function PointingDeviceMove(const Pick: TRayCollisionNode; const Distance: Single): boolean; override;
Public function PointingDeviceSensors: TPointingDeviceSensorList;
Public procedure PointingDeviceClear;
Public function LocalBoundingBox: TBox3D; override;
Public procedure Update(const SecondsPassed: Single; var RemoveMe: TRemoveType); override;
Public procedure SetTime(const NewValue: TFloatTime);
Public procedure IncreaseTime(const TimeIncrease: TFloatTime);
Public procedure IncreaseTimeTick; deprecated 'it should not be necessary to call this, ever; using TX3DEvent.Send(...) or TX3DEvent.Send(..., NextEventTime) will automatically behave Ok.';
Public function Time: TFloatTime; override;
Public function NextEventTime: TX3DTime; override;
Public procedure ResetTime(const NewValue: TFloatTime);
Public procedure ResetTimeAtLoad;
Public function GetBackgroundStack: TX3DBindableStackBasic; override;
Public function GetFogStack: TX3DBindableStackBasic; override;
Public function GetNavigationInfoStack: TX3DBindableStackBasic; override;
Public function GetViewpointStack: TX3DBindableStackBasic; override;
Public function CameraPosition: TVector3; deprecated 'do not access camera properties this way, instead use e.g. SceneManager.Camera.Position';
Public function CameraDirection: TVector3; deprecated 'do not access camera properties this way, instead use e.g. SceneManager.Camera.GetView';
Public function CameraUp: TVector3; deprecated 'do not access camera properties this way, instead use e.g. SceneManager.Camera.GetView';
Public function CameraViewKnown: boolean; deprecated 'do not access camera properties this way, instead use e.g. SceneManager.Camera';
Public procedure CameraChanged(ACamera: TCamera); override;
Public procedure RegisterCompiledScript(const HandlerName: string; Handler: TCompiledScriptHandler);
Public function NavigationTypeFromNavigationInfo: TNavigationType;
Public procedure CameraFromNavigationInfo(Camera: TCamera; const WorldBox: TBox3D);
Public procedure CameraFromViewpoint(ACamera: TCamera; const RelativeCameraTransform: boolean = false; const AllowTransitionAnimate: boolean = true);
Public procedure CameraTransition(Camera: TCamera; const APosition, ADirection, AUp: TVector3);
Public procedure CameraTransition(Camera: TCamera; const APosition, ADirection, AUp, GravityUp: TVector3);
Public function MainLightForShadows( out AMainLightPosition: TVector4): boolean;
Public function CustomHeadlight: TAbstractLightNode;
Public procedure ViewChangedSuddenly; virtual;
Public procedure PrepareResources(const Options: TPrepareResourcesOptions; const ProgressStep: boolean; const Params: TPrepareParams); override;
Public function Dragging: boolean; override;
Public function Caption: string;
Public function Node(const NodeName: string): TX3DNode;
Public function Field(const NodeName, FieldName: string): TX3DField;
Public function Event(const NodeName, EventName: string): TX3DEvent;
Public function HasAnimation(const AnimationName: string): boolean;
Public function AnimationTimeSensor(const AnimationName: string): TTimeSensorNode;
Public function AnimationTimeSensor(const Index: Integer): TTimeSensorNode;
Public function Animations: TStringList; deprecated 'use AnimationsList (and do not free it''s result)';
Public function ForceAnimationPose(const AnimationName: string; const TimeInAnimation: TFloatTime; const Loop: boolean; const Forward: boolean = true): boolean; overload;
Public function ForceAnimationPose(const AnimationName: string; const TimeInAnimation: TFloatTime; const Looping: TPlayAnimationLooping; const Forward: boolean = true): boolean; overload; deprecated 'use ForceAnimationPose overload with "Loop: boolean" parameter';
Public function PlayAnimation(const Parameters: TPlayAnimationParameters): boolean; overload;
Public function PlayAnimation(const AnimationName: string; const Loop: boolean; const Forward: boolean = true): boolean; overload;
Public function PlayAnimation(const AnimationName: string; const Looping: TPlayAnimationLooping; const Forward: boolean = true): boolean; overload; deprecated 'use another overloaded version of PlayAnimation, like simple PlayAnimation(AnimationName: string, Loop: boolean)';
Public procedure ForceInitialAnimationPose;
Public function AnimationDuration(const AnimationName: string): TFloatTime;
Public procedure FontChanged;
Public function Clone(const AOwner: TComponent): TCastleSceneCore;

Properties

Protected property VisibilitySensors: TVisibilitySensors read FVisibilitySensors;
Public property Shapes: TShapeTree read FShapes;
Public property OnGeometryChanged: TSceneGeometryChanged read FOnGeometryChanged write FOnGeometryChanged;
Public property OnViewpointsChanged: TSceneNotification read FOnViewpointsChanged write FOnViewpointsChanged;
Public property OnBoundViewpointVectorsChanged: TSceneNotification read FOnBoundViewpointVectorsChanged write FOnBoundViewpointVectorsChanged;
Public property OnBoundNavigationInfoFieldsChanged: TSceneNotification read FOnBoundNavigationInfoFieldsChanged write FOnBoundNavigationInfoFieldsChanged;
Public property RootNode: TX3DRootNode read FRootNode write SetRootNode;
Public property OwnsRootNode: boolean read FOwnsRootNode write FOwnsRootNode default true;
Public property TriangleOctreeProgressTitle: string read FTriangleOctreeProgressTitle write FTriangleOctreeProgressTitle;
Public property ShapeOctreeProgressTitle: string read FShapeOctreeProgressTitle write FShapeOctreeProgressTitle;
Public property PointingDeviceOverItem: PTriangle read FPointingDeviceOverItem write FPointingDeviceOverItem;
Public property PointingDeviceOverPoint: TVector3 read FPointingDeviceOverPoint write FPointingDeviceOverPoint;
Public property PointingDeviceActiveSensors: TX3DNodeList read FPointingDeviceActiveSensors;
Public property PointingDeviceActive: boolean read FPointingDeviceActive default false;
Public property OnPointingDeviceSensorsChange: TNotifyEvent read FOnPointingDeviceSensorsChange write FOnPointingDeviceSensorsChange;
Public property TimeAtLoad: TFloatTime read FTimeAtLoad;
Public property BackgroundStack: TBackgroundStack read FBackgroundStack;
Public property FogStack: TFogStack read FFogStack;
Public property NavigationInfoStack: TNavigationInfoStack read FNavigationInfoStack;
Public property ViewpointStack: TViewpointStack read FViewpointStack;
Public property CompiledScriptHandlers: TCompiledScriptHandlerInfoList read FCompiledScriptHandlers;
Public property HeadlightOn: boolean read FHeadlightOn write SetHeadlightOn;
Public property OnHeadlightOnChanged: TNotifyEvent read FOnHeadlightOnChanged write FOnHeadlightOnChanged;
Public property Static: boolean read FStatic write SetStatic default false; deprecated 'do not use this; optimization done by this is really negligible; leave ProcessEvents=false for static scenes';
Public property GlobalLights: TLightInstancesList read FGlobalLights;
Public property AnimationsList: TStrings read FAnimationsList;
Public property AnimationPrefix: string read FAnimationPrefix write FAnimationPrefix;
Public property CurrentAnimation: TTimeSensorNode read FCurrentAnimation;
Public property FileName: string read FURL write SetURL; deprecated;
Published property TimePlaying: boolean read FTimePlaying write FTimePlaying default true;
Published property TimePlayingSpeed: Single read FTimePlayingSpeed write FTimePlayingSpeed default 1.0;
Published property Spatial: TSceneSpatialStructures read FSpatial write SetSpatial default [];
Published property ProcessEvents: boolean read FProcessEvents write SetProcessEvents default false;
Published property URL: string read FURL write SetURL;
Published property ShadowMaps: boolean read FShadowMaps write SetShadowMaps default true;
Published property ShadowMapsDefaultSize: Cardinal read FShadowMapsDefaultSize write SetShadowMapsDefaultSize default DefaultShadowMapsDefaultSize;
Published property InitialViewpointIndex: Cardinal read FInitialViewpointIndex write FInitialViewpointIndex default 0;
Published property InitialViewpointName: string read FInitialViewpointName write FInitialViewpointName;
Published property AnimateOnlyWhenVisible: boolean read FAnimateOnlyWhenVisible write FAnimateOnlyWhenVisible default false;
Published property AnimateSkipTicks: Cardinal read FAnimateSkipTicks write SetAnimateSkipTicks default 0;
Published property PrimitiveGeometry: TPrimitiveGeometry read FPrimitiveGeometry write SetPrimitiveGeometry default pgNone;

Description

Fields

Protected ScreenEffectNodes: TX3DNodeList;

List of TScreenEffectNode nodes, collected by ChangedAll.

Protected IsVisibleNow: boolean;

Is the scene visible currently. Descendants may set this to True during TCastleTransform.LocalRender.

Protected GeneratedTextures: TGeneratedTextureList;
 
Public nested const DefaultShadowMapsDefaultSize = 256;
 

Methods

Protected function CreateShape(AGeometry: TAbstractGeometryNode; AState: TX3DGraphTraverseState; ParentInfo: PTraversingInfo): TShape; virtual;

Create TShape (or descendant) instance suitable for this TCastleSceneCore descendant. In this class, this simply creates new TShape instance. If you make a descendant of TCastleSceneCore, you may need to store some per-shape information, and then it may be useful to have your own TShape descendant to carry this information. So you can override this to create your own descendant, and then you're sure that all leafs within Shapes tree are created using this.

Example: TCastleScene uses this to create TGLShape.

Protected procedure UpdateHeadlightOnFromNavigationInfo;
 
Protected procedure InvalidateBackground; virtual;
 
Protected procedure ChangedTransform; override;
 
Protected procedure ChangeWorld(const Value: TSceneManagerWorld); override;
 
Protected procedure DoPointingDeviceSensorsChange; virtual;

Called after PointingDeviceSensors or PointingDeviceActiveSensors lists (possibly) changed.

In this class, DoPointingDeviceSensorsChange updates Cursor and calls OnPointingDeviceSensorsChange.

Protected procedure ExecuteCompiledScript(const HandlerName: string; ReceivedValue: TX3DField); override;
 
Protected function LocalHeightCollision(const APosition, GravityUp: TVector3; const TrianglesToIgnoreFunc: TTriangleIgnoreFunc; out AboveHeight: Single; out AboveGround: PTriangle): boolean; override;
 
Protected function LocalMoveCollision( const OldPos, ProposedNewPos: TVector3; out NewPos: TVector3; const IsRadius: boolean; const Radius: Single; const OldBox, NewBox: TBox3D; const TrianglesToIgnoreFunc: TTriangleIgnoreFunc): boolean; override;
 
Protected function LocalMoveCollision( const OldPos, NewPos: TVector3; const IsRadius: boolean; const Radius: Single; const OldBox, NewBox: TBox3D; const TrianglesToIgnoreFunc: TTriangleIgnoreFunc): boolean; override;
 
Protected function LocalSegmentCollision(const Pos1, Pos2: TVector3; const TrianglesToIgnoreFunc: TTriangleIgnoreFunc; const ALineOfSight: boolean): boolean; override;
 
Protected function LocalSphereCollision(const Pos: TVector3; const Radius: Single; const TrianglesToIgnoreFunc: TTriangleIgnoreFunc): boolean; override;
 
Protected function LocalSphereCollision2D(const Pos: TVector2; const Radius: Single; const TrianglesToIgnoreFunc: TTriangleIgnoreFunc; const Details: TCollisionDetails): boolean; override;
 
Protected function LocalPointCollision2D(const Point: TVector2; const TrianglesToIgnoreFunc: TTriangleIgnoreFunc): boolean; override;
 
Protected function LocalBoxCollision(const Box: TBox3D; const TrianglesToIgnoreFunc: TTriangleIgnoreFunc): boolean; override;
 
Protected function LocalRayCollision(const RayOrigin, RayDirection: TVector3; const TrianglesToIgnoreFunc: TTriangleIgnoreFunc): TRayCollision; override;
 
Protected procedure LocalRender(const Params: TRenderParams); override;
 
Public constructor Create(AOwner: TComponent); override;
 
Public procedure Load(ARootNode: TX3DRootNode; AOwnsRootNode: boolean; const AResetTime: boolean = true);

Load the model given as a X3D nodes graph. This replaces RootNode with new value.

Note that you should never load the same TX3DRootNode instance into multiple TCastleScene instances.

// DON'T DO THIS!
Node := Load3D(URL);
Scene1 := TCastleScene.Create(Application);
Scene1.Load(Node, false);
Scene2 := TCastleScene.Create(Application);
Scene2.Load(Node, false);

If you need to load the same model into multiple scenes, it is best to use the Clone method:

SceneTemplate := TCastleScene.Create(Application);
SceneTemplate.Load(URL);
Scene1 := SceneTemplate.Clone(Application);
Scene2 := SceneTemplate.Clone(Application);

Using the Clone makes a copy of the underlying X3D graph, so it is roughly like doing:

Node := Load3D(URL);
Scene1 := TCastleScene.Create(Application);
Scene1.Load(Node.DeepCopy as TX3DRootNode, false);
Scene2 := TCastleScene.Create(Application);
Scene2.Load(Node.DeepCopy as TX3DRootNode, false);

Note that sometimes you don't need to create multiple scenes to show the same model many times. You can simply insert the same TCastleScene instance multiple times to SceneManager.Items. See the manual: https://castle-engine.io/manual_scene.php#section_many_instances

Parameters
ARootNode
The model to load. This will become a new value of our RootNode property.
AOwnsRootNode
Should the scene take care of freeing this root node when it is no longer used. If False, you are expected to free it yourself, but only after the scene using it was freed.
AResetTime
If True then we will reset time at loading (using ResetTimeAtLoad), changing the Time. This is usually what you want when you load a new world.
Public procedure Load(const AURL: string; AllowStdIn: boolean = false; const AResetTime: boolean = true);

Load the 3D model from given URL.

We load a number of 3D model formats (X3D, VRML, Collada, Wavefront OBJ...) and some 2D model formats (Spine JSON). See https://castle-engine.io/creating_data_model_formats.php for the complete list.

URL is downloaded using the CastleDownload unit, so it supports files, http resources and more. See https://castle-engine.io/manual_network.php about supported URL schemes. If you all you care about is loading normal files, then just pass a normal filename (absolute or relative to the current directory) as the URL parameter.

Parameters
AllowStdIn
If AllowStdIn and AURL = '-' then we will load a file from standard input (StdInStream), using current working directory as BaseUrl (to resolve relative URLs from the file). Currently, this limits the file to be VRML/X3D.
Public procedure Save(const AURL: string);

Save the current 3D model (X3D nodes graph) to the given file (URL).

The X3D encoding is automatically guessed from the URL extension. By default it is XML, and we suggest using the .x3d extension. If you specify an extension indicating "classic encoding", we will use such encoding (use .x3dv for X3D in classic encoding, or .wrl for older VRML content).

The file may also be automatically gzip compressed if extension indicates it. Use .x3d.gz to indicated XML compressed with gzip, or use .x3dv.gz or .wrl.gz to indicate classic encoding compressed with gzip.

The URL property is also changed.

Public destructor Destroy; override;
 
Public function ShapesActiveCount: Cardinal;

Number of active shapes in the Shapes tree. This is equivalent to Shapes.ShapesCount(true), except that this is faster (it's cached and reused in this instance, and automatically invalidated only when needed).

Public function ShapesActiveVisibleCount: Cardinal;

Number of active and visible (TShape.Visible) shapes in the Shapes tree.

See also
ShapesActiveCount
Number of active shapes in the Shapes tree.
Public function VerticesCount(OverTriangulate: boolean): Cardinal;

Calculate the number of triangls and vertexes of all shapa states. For detailed specification of what these functions do (and what does OverTriangulate mean) see appropriate TAbstractGeometryNode methods. Here, we just sum their results for all shapes.

Public function TrianglesCount(OverTriangulate: boolean): Cardinal;
 
Public function ViewpointsCount: Cardinal;

Helper functions for accessing viewpoints defined in the scene.

Public function GetViewpointName(Idx: integer): string;
 
Public procedure MoveToViewpoint(Idx: integer; Animated: boolean = true);
 
Public procedure AddViewpointFromCamera(ACamera: TCamera; AName: string);
 
Public procedure BeforeNodesFree(const InternalChangedAll: boolean = false); override;

Release all internal associations with your VRML/X3D nodes. In particular, this will release OpenGL resources connected to your nodes. You should always call this before you (may) free some nodes in RootNode.

You have to call ChangedAll or Load at sometime after BeforeNodesFree, and before you try actual rendering, events etc. Otherwise some stuff may not get recalculated.

The InternalChangedAll parameter is for internal use. It is set to True when ChangedAll calls this method at the beginning of it's work, and means that nothing is freed, and we only require necessary cleanup at the beginning of ChangedAll. This way ChangedAll (when it wasn't preceeded by explicit BeforeNodesFree(false)) produces events from stacks CheckForDeletedNodes.

Public procedure NodeFreeRemovingFromAllParents(Node: TX3DNode);

Call Node.FreeRemovingFromAllParents, making sure that changes to our VRML/X3D node graph are allowed. This makes sure we call BeforeNodesFree befor freeing, and ChangedAll afterwards.

This avoids a common pitfall with relying on TShape or such existence between BeforeNodesFree and ChangedAll. BeforeNodesFree may free all our TShape instances, so if you want to free TX3DNode from our graph — you typically want to get this TX3DNode instance *before* calling BeforeNodesFree. Using this method to free the node ensures this.

Public procedure RemoveShape(Shape: TShape);

Remove the shape node from the scene. In case of VRML 1.0 / Inventor, when the Shape doesn't have a node, we remove the geometry node.

Public procedure ChangedAll; override;

Notify scene that potentially everything changed in the VRML/X3D graph. This includes adding/removal of some nodes within RootNode graph and changing their fields' values. (Before freeing the nodes, remember to also call BeforeNodesFree earlier.)

You usually never need to call this method explicitly. It's called by engine when necesssary. However, you need to call it yourself if you change the X3D graph directly through nodes' FdXxx fields, and you don't want to call for some reason FdXxx.Changed.

ChangedAll causes recalculation of all things dependent on RootNode, so it's very costly to call this. Avoid calling this. When you change a simple field, like by FdXxx.Value := ..., you should rather call FdXxx.Changed, and it may do something much faster than rebuilding the scene.

Descendant implementors notes: ChangedAll is virtual, when overriding it remember that it's called by constructor of this class, so you can put a lot of your initialization there (instead of in the constructor).

ChangedAll calls BeforeNodesFree(true) first, for safety (and TGLShape actually depends on it, see implementation comments).

Public procedure DoGeometryChanged(const Change: TGeometryChange; LocalGeometryShape: TShape); virtual;

Called when geometry changed. Does OnGeometryChanged, and does some other stuff necessary (mark some octrees for regenerating at next access).

This is public only for overloading (and for internal TShape access). Do not call this yourself — TShape and TCastleSceneCore implementations know when and how to call this.

Public procedure DoViewpointsChanged;

Call OnViewpointsChanged, if assigned.

Public procedure DoBoundViewpointVectorsChanged;

Call OnBoundViewpointVectorsChanged, if assigned.

Public procedure DoBoundNavigationInfoFieldsChanged; virtual;
 
Public procedure ScheduleChangedAll;

Mechanism to schedule ChangedAll calls.

Since these calls may be costly (traversing the hierarchy), and their results are often not immediately needed by TCastleSceneCore or TX3DNode hierarchy, it's sometimes not desirable to call them immediately when geometry changed / all changed.

So you can use ScheduleChangedAll instead of ChangedAll. All event handlers within TCastleSceneCore already do this.

When you're within Begin/EndChangesSchedule, then ScheduleChangedAll just sets an internal flag and actual ChangedAll will be done only once at EndChangesSchedule. Otherwise (when not within Begin/EndChangesSchedule), ScheduleChangedAll will immediately call ChangedAll.

Public procedure BeginChangesSchedule;
 
Public procedure EndChangesSchedule;
 
Public function Info( ATriangleVerticesCounts, ABoundingBox: boolean; AManifoldAndBorderEdges: boolean): string; deprecated 'do not use this, better to construct a summary string yourself';

Warning: this symbol is deprecated: do not use this, better to construct a summary string yourself

Returns short information about the scene. This consists of a few lines, separated by newlines. Last line also ends with CastleUtils.NL.

Public function InfoTriangleVerticesCounts: string; deprecated 'better to construct a string yourself, use TrianglesCount, VerticesCount';

Warning: this symbol is deprecated: better to construct a string yourself, use TrianglesCount, VerticesCount

 
Public function InfoBoundingBox: string; deprecated 'better to construct a string yourself, use BoundingBox.ToString';

Warning: this symbol is deprecated: better to construct a string yourself, use BoundingBox.ToString

 
Public function InfoManifoldAndBorderEdges: string; deprecated 'better to construct a string yourself, use EdgesCount';

Warning: this symbol is deprecated: better to construct a string yourself, use EdgesCount

 
Public procedure EdgesCount(out ManifoldEdges, BorderEdges: Cardinal);

Edges count in the scene, for information purposes.

Public function InternalOctreeRendering: TShapeOctree;

A spatial structure containing all visible shapes. Add ssRendering to Spatial property, otherwise it's Nil.

You should not usually use this directly. Instead use SceneManager (like TCastleSceneManager or TCastle2DSceneManager) and then use SceneManager.Items.WorldXxxCollision methods like SceneManager.Items.WorldRay or SceneManager.Items.WorldSphereCollision.

Note that when VRML/X3D scene contains Collision nodes, this octree contains the visible (not necessarily collidable) objects.

Public function InternalOctreeDynamicCollisions: TShapeOctree;

A spatial structure containing all collidable shapes. Add ssDynamicCollisions to Spatial property, otherwise it's Nil.

You should not usually use this directly. Instead use SceneManager (like TCastleSceneManager or TCastle2DSceneManager) and then use SceneManager.Items.WorldXxxCollision methods like SceneManager.Items.WorldRay or SceneManager.Items.WorldSphereCollision.

You can use InternalOctreeCollisions to get either InternalOctreeDynamicCollisions or InternalOctreeStaticCollisions, whichever is available.

Note that when VRML/X3D scene contains Collision nodes, this octree contains the collidable (not necessarily rendered) objects.

TODO: Temporarily, this is updated simply by rebuilding.

Public function InternalOctreeVisibleTriangles: TTriangleOctree;

A spatial structure containing all visible triangles, suitable only for scenes that stay static. Add ssVisibleTriangles to Spatial property, otherwise it's Nil.

You should not usually use this directly. Instead use SceneManager (like TCastleSceneManager or TCastle2DSceneManager) and then use SceneManager.Items.WorldXxxCollision methods like SceneManager.Items.WorldRay or SceneManager.Items.WorldSphereCollision.

Note that when VRML/X3D scene contains X3D Collision nodes, this octree contains the visible (not necessarily collidable) objects.

Public function InternalOctreeStaticCollisions: TTriangleOctree;

A spatial structure containing all collidable triangles. Add ssStaticCollisions to Spatial property, otherwise it's Nil.

You should not usually use this directly. Instead use SceneManager (like TCastleSceneManager or TCastle2DSceneManager) and then use SceneManager.Items.WorldXxxCollision methods like SceneManager.Items.WorldRay or SceneManager.Items.WorldSphereCollision.

It is automatically used by the XxxCollision methods in this class, if exists, unless OctreeDynamicCollisions exists.

Note that you can use InternalOctreeCollisions to get either InternalOctreeDynamicCollisions or InternalOctreeStaticCollisions, whichever is available.

Public function InternalOctreeCollisions: TBaseTrianglesOctree;

Octree for collisions. This returns either InternalOctreeStaticCollisions or InternalOctreeDynamicCollisions, whichever is available (or Nil if none). Be sure to add ssDynamicCollisions or ssStaticCollisions to have this available.

You should not usually use this directly. Instead use SceneManager (like TCastleSceneManager or TCastle2DSceneManager) and then use SceneManager.Items.WorldXxxCollision methods like SceneManager.Items.WorldRay or SceneManager.Items.WorldSphereCollision.

Public function UseInternalOctreeCollisions: boolean;
 
Public function GetViewpoint( out ProjectionType: TProjectionType; out CamPos, CamDir, CamUp, GravityUp: TVector3; const ViewpointDescription: string = ''): TAbstractViewpointNode;

Viewpoint defined in the 3D file (or some default camera settings if no viewpoint is found).

GetViewpoint seeks for VRML/X3D nodes like Viewpoint, OrthoViewpoint (actually, any X3DViewpointNode) and VRML 1.0 PerspectiveCamera and OrthographicCamera. GetPerspectiveViewpoint seeks only for perspective viewpoints.

If ViewpointDescription = '', they return the first found viewpoint node. Otherwise, they look for X3DViewpointNode with description field mathing given string.

If camera properties were found in some node, it returns this node. Otherwise it returns nil. This way you can optionally extract some additional info from used viewpoint node, or do something special if default values were used. Often you will just ignore result of this function — after all, the most important feature of this function is that you don't have to care about details of dealing with camera node.

Returned CamDir and CamUp and GravityUp are always normalized — reasons the same as for TAbstractViewpointNode.GetView.

Public function GetPerspectiveViewpoint( out CamPos, CamDir, CamUp, GravityUp: TVector3; const ViewpointDescription: string = ''): TAbstractViewpointNode;
 
Public procedure FreeResources(Resources: TSceneFreeResources); virtual;

Frees some scene resources, to conserve memory. See TSceneFreeResources documentation.

Public procedure UnregisterScene(Node: TX3DNode);

Recursively unset node's TX3DNode.Scene. Useful if you want to remove part of a node graph and put it in some other scene.

You almost never need to call this method — this is done automatically for you when TCastleSceneCore is destroyed. However, if you process RootNode graph and extract some node from it (that is, delete node from our RootNode graph, but instead of freeing it you insert it into some other VRML/X3D graph) you must call it to manually "untie" this node (and all it's children) from this TCastleSceneCore instance.

Public function Press(const Event: TInputPressRelease): boolean; override;
 
Public function Release(const Event: TInputPressRelease): boolean; override;
 
Public function PointingDeviceActivate(const Active: boolean; const Distance: Single; const CancelAction: boolean = false): boolean; override;
 
Public function PointingDeviceMove(const Pick: TRayCollisionNode; const Distance: Single): boolean; override;

Called when pointing device moves. This may generate the continously-generated events like hitPoint_changed, also it updates PointingDeviceOverItem and PointingDeviceOverPoint, thus producing isOver and such events.

To make pointing-device sensors work Ok, make sure you have non-nil OctreeCollisions (e.g. include ssDynamicCollisions in Spatial).

Public function PointingDeviceSensors: TPointingDeviceSensorList;

Pointing-device sensors over which the pointing device is. This is just a shortcut for PointingDeviceOverItemˆ.State.PointingDeviceSensors, returning Nil if PointingDeviceOverItem = Nil.

Public procedure PointingDeviceClear;

Clear any references to OverItem passed previously to PointingDeviceMove. This is sometimes useful, because PointingDeviceMove may save the last passed OverItem, and PointingDeviceActivate may even save some sensors for a longer time.

You could free it by calling PointingDeviceMove with Collision = Nil, but this could cause other X3D events, so it's undesirable to call this when you're going to e.g. release the scene or it's octree. Also, you would have to deactivate sensor first, causing even more events.

So this method clears any references to saved OverItem and PointingDeviceActiveSensors, without calling any VRML/X3D events. Note that this still calls DoPointingDeviceSensorsChange (making OnPointingDeviceSensorsChange event), if PointingDeviceActiveSensors / PointingDeviceSensors possibly changed.

Public function LocalBoundingBox: TBox3D; override;
 
Public procedure Update(const SecondsPassed: Single; var RemoveMe: TRemoveType); override;
 
Public procedure SetTime(const NewValue: TFloatTime);

Change current scene time, setting Time. It is crucial that you call this continously to have some VRML/X3D time-dependent features working, like TimeSensor and MovieTexture. See Time for details what is affected by this.

This is automatically taken care of if you added this scene to TCastleWindowCustom.Controls or TCastleControlCustom.Controls. Then our Update takes care of doing the job, according to TimePlaying and TimePlayingSpeed.

This causes time to be passed to appropriate time-dependent nodes, events will be called etc.

SetTime and IncreaseTime do exactly the same, the difference is only that for IncreaseTime you specify increase in the time (that is, NewTime = Time + TimeIncrease). Use whichever version is more handy.

Following X3D specification, time should only grow. So NewValue should be > Time (or TimeIncrease > 0). Otherwise we ignore this call. For resetting the time (when you don't necessarily want to grow Time) see ResetTime.

If a change of Time will produce some visible change in the VRML/X3D model (for example, MovieTexture will change, or TimeSensor change will be routed by interpolator to coordinates of some visible node) it will be reported by usual method, that is VisibleChangeHere.

Public procedure IncreaseTime(const TimeIncrease: TFloatTime);
 
Public procedure IncreaseTimeTick; deprecated 'it should not be necessary to call this, ever; using TX3DEvent.Send(...) or TX3DEvent.Send(..., NextEventTime) will automatically behave Ok.';

Warning: this symbol is deprecated: it should not be necessary to call this, ever; using TX3DEvent.Send(...) or TX3DEvent.Send(..., NextEventTime) will automatically behave Ok.

 
Public function Time: TFloatTime; override;

The time within this scene, in seconds. Increasing this "drives" the animations (by increasing time of time-dependent nodes like X3D TimeSensor, which in turn drive the rest of the animation).

You can use SetTime or IncreaseTime to move time forward manually. But usually there's no need for it: our Update method takes care of it automatically, you only need to place the scene inside TCastleSceneManager.Items.

You can start/stop time progress by TimePlaying and scale it by TimePlayingSpeed. These properties affect how the time is updated by the Update method (so if you use SetTime or IncreaseTime methods, you're working around these properties).

Default time value is 0.0 (zero). However it will be reset at load to a current time (seconds since Unix epoch — that's what X3D standard says to use, although you can change it by KambiNavigationInfo.timeOriginAtLoad, see https://castle-engine.io/x3d_implementation_navigation_extensions.php#section_ext_time_origin_at_load ). You can perform this "time reset" yourself by ResetTimeAtLoad or ResetTime.

Public function NextEventTime: TX3DTime; override;

Time that should be used for next event. You usually don't need to call this directly, this is automatically used by TX3DEvent.Send when you don't specify explicit time.

Public procedure ResetTime(const NewValue: TFloatTime);

Set Time to arbitrary value.

You should only use this when you loaded new VRML/X3D model.

Unlike SetTime and IncreaseTime, this doesn't require that Time grows. It still does some time-dependent events work, although some time-dependent nodes may be just unconditionally reset by this to starting value (as they keep local time, and so require TimeIncrease notion, without it we can only reset them).

Public procedure ResetTimeAtLoad;

Set Time to suitable initial value after loading a world.

This honours VRML/X3D specification about VRML/X3D time origin, and our extension [https://castle-engine.io/x3d_extensions.php#section_ext_time_origin_at_load].

Public function GetBackgroundStack: TX3DBindableStackBasic; override;
 
Public function GetFogStack: TX3DBindableStackBasic; override;
 
Public function GetNavigationInfoStack: TX3DBindableStackBasic; override;
 
Public function GetViewpointStack: TX3DBindableStackBasic; override;
 
Public function CameraPosition: TVector3; deprecated 'do not access camera properties this way, instead use e.g. SceneManager.Camera.Position';

Warning: this symbol is deprecated: do not access camera properties this way, instead use e.g. SceneManager.Camera.Position

 
Public function CameraDirection: TVector3; deprecated 'do not access camera properties this way, instead use e.g. SceneManager.Camera.GetView';

Warning: this symbol is deprecated: do not access camera properties this way, instead use e.g. SceneManager.Camera.GetView

 
Public function CameraUp: TVector3; deprecated 'do not access camera properties this way, instead use e.g. SceneManager.Camera.GetView';

Warning: this symbol is deprecated: do not access camera properties this way, instead use e.g. SceneManager.Camera.GetView

 
Public function CameraViewKnown: boolean; deprecated 'do not access camera properties this way, instead use e.g. SceneManager.Camera';

Warning: this symbol is deprecated: do not access camera properties this way, instead use e.g. SceneManager.Camera

 
Public procedure CameraChanged(ACamera: TCamera); override;

Call when camera position/dir/up changed, to update things depending on camera settings. This includes sensors like ProximitySensor, LOD nodes, camera settings for next RenderedTexture update and more.

There should be no need to call this method explicitly. The scene is notified about camera changes automatically, by the TCastleSceneManager. This method may be renamed / removed in future releases.

Public procedure RegisterCompiledScript(const HandlerName: string; Handler: TCompiledScriptHandler);

Register compiled script handler, for VRML/X3D Script node with "compiled:" protocol. See [https://castle-engine.io/x3d_extensions.php#section_ext_script_compiled].

Public function NavigationTypeFromNavigationInfo: TNavigationType;

TNavigationType value determined by current NavigationInfo node.

Public procedure CameraFromNavigationInfo(Camera: TCamera; const WorldBox: TBox3D);

Update camera properties based on currently bound NavigationInfo.

Bound NavigationInfo node is taken from NavigationInfoStack.Top. If no NavigationInfo is bound, this is Nil, and we will create camera corresponding to default NavigationInfo values (this is following VRML/X3D spec), so it will have initial type = EXAMINE.

This initializes a lot of camera properties:

Box is the expected bounding box of the whole 3D scene. Usually, it should be SceneManager.Items.BoundingBox. In simple cases (if this scene is the only TCastleScene instance in your world, and it's not transformed) it may be equal to just BoundingBox of this scene.

Public procedure CameraFromViewpoint(ACamera: TCamera; const RelativeCameraTransform: boolean = false; const AllowTransitionAnimate: boolean = true);

Update camera to the currently bound VRML/X3D viewpoint. When no viewpoint is currently bound, we will go to a suitable viewpoint to see the whole scene (based on the Camera.ModelBox, which should be set in CameraFromNavigationInfo to the world bounding box).

The initial camera vectors (TCamera.InitialPosition, TCamera.InitialDirection, TCamera.InitialUp, TWalkCamera.GravityUp) are set to the current viewpoint. This is done regardless of the RelativeCameraTransform value.

How current camera vectors change depends on RelativeCameraTransform:

  • RelativeCameraTransform = False means that we just set current vectors to the initial vectors. In other words, camera jumps to the viewpoint.

    In this case, AllowTransitionAnimate determines if we allow moving camera by a smooth transition. If this is True, and also NavigationInfo allows it (see CameraTransition), then camera will jump smoothy. Otherwise camera will jump to viewpoint immediately.

  • RelativeCameraTransform = True means that we translate/rotate the current camera in the same manner as initial camera changed. This is suitable when you change transformation, position or orientation of the VRML/X3D Viewpoint node: conceptually, there exists a "user" camera transformation that is the child of the viewpoint. When viewpoint is moved, then the current camera moves with it.

Public procedure CameraTransition(Camera: TCamera; const APosition, ADirection, AUp: TVector3);

Make Camera go to the view given by APosition, ADirection, AUp.

Honours current NavigationInfo.transitionType and transitionTime. If transitionType indicates instanteneous transition, then jumps by simple Camera.SetView(APosition, ADirection, AUp). Otherwise makes a smooth animation into new values by Camera.AnimateTo(APosition, ADirection, AUp, TransitionTime).

Will generate NavigationInfo.transitionComplete when transition ends.

Public procedure CameraTransition(Camera: TCamera; const APosition, ADirection, AUp, GravityUp: TVector3);
 
Public function MainLightForShadows( out AMainLightPosition: TVector4): boolean;

Detect position/direction of the main light that produces shadows. This is useful when you want to make shadows on the scene from only a single light, but your scene has many lights.

The main light is simply one with both shadowVolumes and shadowVolumesMain fields set to True. See [https://castle-engine.io/x3d_extensions.php#section_ext_shadows] for more info. If no light with shadowVolumes = shadowVolumesMain = TRUE is present then this function returns False, since AMainLightPosition cannot be calculated.

AMainLightPosition[3] is always set to 1 (positional light) or 0 (indicates that this is a directional light).

See also
TCastleAbstractViewport.MainLightForShadows
Detect position/direction of the main light that produces shadows.
Public function CustomHeadlight: TAbstractLightNode;

Light node that should be used for headlight, or Nil if default directional headlight is suitable.

This never returns Nil. It's not concerned whether the headlight should actually be used — for this, see HeadlightOn.

Public procedure ViewChangedSuddenly; virtual;

Notify the scene that camera position/direction changed a lot. It may be called when you make a sudden change to the camera, like teleporting the player to a completely different scene part.

This may be used as a hint by some optimizations. It tells that what will be visible in the next rendered frame will be probably very different from what was visible in the last frame.

Current implementation notes:

Currently, this is used by TCastleScene if you use Attributes.UseOcclusionQuery. Normally, occlusion query tries to reuse results from previous frame, using the assumption that usually camera changes slowly and objects appear progressively in the view. When you make a sudden camera jump/change, this assumption breaks, so it's better to resign from occlusion query for the very next frame. This method will do exactly that.

Public procedure PrepareResources(const Options: TPrepareResourcesOptions; const ProgressStep: boolean; const Params: TPrepareParams); override;
 
Public function Dragging: boolean; override;
 
Public function Caption: string;

Nice scene caption. Uses the "title" of WorldInfo node inside the VRML/X3D scene. If there is no WorldInfo node (or it has empty title) then result is based on loaded URL.

Public function Node(const NodeName: string): TX3DNode;

Find a named X3D node (and a field or event within this node) in the current node graph. They search all nodes (in active or not) graph parts.

For more flexible and extensive search methods, use RootNode property along with TX3DNode.FindNodeByName, TX3DNode.FindNode and other methods.

Exceptions raised
EX3DNotFound
If given node (or field/event inside this node) could not be found.
Public function Field(const NodeName, FieldName: string): TX3DField;
 
Public function Event(const NodeName, EventName: string): TX3DEvent;
 
Public function HasAnimation(const AnimationName: string): boolean;

Does named animation with given name exist.

See also
AnimationsList
List the names of available animations in this file.
PlayAnimation
Public function AnimationTimeSensor(const AnimationName: string): TTimeSensorNode;

TimeSensor of this animation. Nil if this name not found. See e.g. examples/3d_rendering_processing/listen_on_x3d_events.lpr for an example of using this.

Public function AnimationTimeSensor(const Index: Integer): TTimeSensorNode;

TimeSensor of this animation, by animation index (index on AnimationsList). Nil if this index not found.

Public function Animations: TStringList; deprecated 'use AnimationsList (and do not free it''s result)';

Warning: this symbol is deprecated: use AnimationsList (and do not free it's result)

 
Public function ForceAnimationPose(const AnimationName: string; const TimeInAnimation: TFloatTime; const Loop: boolean; const Forward: boolean = true): boolean; overload;

Forcefully, immediately, set 3D pose from given animation, with given time in animation.

This avoids the normal passage of time in X3D scenes, it ignores the ProcessEvents and AnimateOnlyWhenVisible properties, it ignores the current animation set by PlayAnimation, and forces the current time on TimeSensors by TTimeSensorNode.FakeTime.

Public function ForceAnimationPose(const AnimationName: string; const TimeInAnimation: TFloatTime; const Looping: TPlayAnimationLooping; const Forward: boolean = true): boolean; overload; deprecated 'use ForceAnimationPose overload with "Loop: boolean" parameter';

Warning: this symbol is deprecated: use ForceAnimationPose overload with "Loop: boolean" parameter

 
Public function PlayAnimation(const Parameters: TPlayAnimationParameters): boolean; overload;

Play a named animation. Calling this method also stops previously playing named animation, if any. Returns boolean whether such animation name was found. To get the list of available animations, see AnimationsList.

This is the simplest way to play animations using Castle Game Engine. For a nice overview about using PlayAnimation, see the manual https://castle-engine.io/manual_scene.php , section "Play animation".

Playing an already-playing animation is guaranteed to start it from the beginning.

You can specify whether the animation should loop, whether to play it forward or backward, whether to do animation blending and some other options: see TPlayAnimationParameters.

If you use an overloaded version with the TPlayAnimationParameters, note that you can (and usually should) free the TPlayAnimationParameters instance right after calling this method. We do not keep reference to the TPlayAnimationParameters instance, and we do not free it ourselves.

Some obscure notes (you usually do not need to know the details below):

  • Calling this method does not change the scene immediately. There may be a delay between calling PlayAnimation and actually changing the scene to reflect the state at the beginning of the indicated animation. This delay is usually 1 frame (that is, the scene is updated at the next Update call), but it may be larger if you use the optimization AnimateSkipTicks.

    This is often a desirable optimization. There's often no "rush" to visually change the animation right now, and doing it at the nearest Update call is acceptable. It also means that calling PlayAnimation multiple times before a single Update call is not expensive.

    If you really need to change the scene immediately (for example, because you don't want to show user the initial scene state), simply call ForceInitialAnimationPose right after PlayAnimation.

  • Internally, the animation is performed using TTimeSensorNode that instructs other nodes to change. For exampe, TTimeSensorNode may instruct a TCoordinateInterpolatorNode to update the TIndexedFaceSetNode coordinates, and in effect the animation can deform a mesh. Or TTimeSensorNode may instruct a TPositionInterpolatorNode to update TTransformNode.Translation, and in effect the animation can move something.

    So the animation means that the X3D nodes graph within RootNode is being changed. The exact subset of the nodes inside RootNode that change depends on your animation.

    This means that internally our mechanism is very flexible. E.g. you can have another animation running (another TTimeSensorNode running) in parallel to the animation run by this method. You can also change parts of the node graph by your own code (accessing RootNode) in parallel to the animation by this method, as long as you don't touch the same nodes. Such tricks are possible, but require manually designing a proper X3D file.

    If you load a model from a castle-anim-frames or MD3 format, note that it is animated using a special "node interpolator" algorithm. In this case, you cannot really change the model inside RootNode anymore — any modifications may be overwritten by the "node interpolator" at some point (the exact overwrite moment depends on the "merge nodes" optimization done by the "node interpolator").

Public function PlayAnimation(const AnimationName: string; const Loop: boolean; const Forward: boolean = true): boolean; overload;
 
Public function PlayAnimation(const AnimationName: string; const Looping: TPlayAnimationLooping; const Forward: boolean = true): boolean; overload; deprecated 'use another overloaded version of PlayAnimation, like simple PlayAnimation(AnimationName: string, Loop: boolean)';

Warning: this symbol is deprecated: use another overloaded version of PlayAnimation, like simple PlayAnimation(AnimationName: string, Loop: boolean)

 
Public procedure ForceInitialAnimationPose;

Force the model to look like the initial animation frame now.

Use this after calling PlayAnimation. Calling this is simply ignored if no PlayAnimation was called earlier, of if the model already looks following the animation requested by PlayAnimation.

Without this method, there may be a 1-frame delay between calling PlayAnimation and actually updating the rendered scene look. If during that time a rendering will happen, the user will see a scene in previous pose (not in the first pose of animation you requested by PlayAnimation). To avoid this, simply call this method right after PlayAnimation.

This sets first animation frame, unless you used TPlayAnimationParameters.InitialTime <> 0.

Public function AnimationDuration(const AnimationName: string): TFloatTime;

Duration, in seconds, of the named animation (named animations are detected by AnimationsList method). For a looping animation, this is the duration of a single cycle. 0 if not found.

Public procedure FontChanged;

Force recalculating the text shapes when font changed. For now, we don't detect font changes (when TFontStyleNode.OnFont returns something different) ourselves. This calls TTextNode.FontChanged and TAsciiTextNode_1.FontChanged on all appropriate nodes.

Public function Clone(const AOwner: TComponent): TCastleSceneCore;

Create a scene with the same contents (X3D scene graph) as this one. The created scene has exactly the same class as this one (we use ClassType.Create to call a virtual constructor).

Note that this does not copy other scene attributes, like ProcessEvents or Spatial or rendering attributes in TCastleScene.Attributes. It only copies the scene graph (RootNode) and also sets target URL based on source URL (for logging purposes, e.g. TCastleProfilerTime use this URL to report loading and preparation times).

Properties

Protected property VisibilitySensors: TVisibilitySensors read FVisibilitySensors;
 
Public property Shapes: TShapeTree read FShapes;

Simple (usually very flat) tree of shapes within this VRML/X3D scene.

Contents of this tree are read-only from outside.

Note that the only place where Shapes structure is rebuild in this class is ChangedAll procedure. So e.g. if you want to do something after each change of Shapes tree, you can simply override ChangedAll and do your work after calling "inherited".

Public property OnGeometryChanged: TSceneGeometryChanged read FOnGeometryChanged write FOnGeometryChanged;

Notification when geometry changed. "Geometry changed" means that the positions of triangles changed. This is not send when merely things like material changed.

It is not guaranteed that octrees are already recalculated when this is called. (They may be recalculated only on-demand, that is when you actually access them.) However, it is guaranteed that shape's transformation (like TShape.State.Transform) are already updated.

Public property OnViewpointsChanged: TSceneNotification read FOnViewpointsChanged write FOnViewpointsChanged;

Notification when the list of viewpoints in the scene possibly changed.

Note that this doesn't necessarily mean that the current, bound viewpoint changed (although it could). If you only want to get notified when currently bound viewpoint changes, then what you seek is rather ViewpointStack.OnBoundChanged.

Public property OnBoundViewpointVectorsChanged: TSceneNotification read FOnBoundViewpointVectorsChanged write FOnBoundViewpointVectorsChanged;

Notification when the currently bound viewpoint's vectors (position/orientation and such) changed.

More precisely, this is called whenever values generated by ViewpointStack.Top.GetView changed.

It cannot be called when ViewpointStack.Top = Nil. Note that this also doesn't notify you about changes to currently bound viewpoint, for this you rather want to use ViewpointStack.OnBoundChanged. This is called only when currently bound viewpoint stays the same, only it's vectors change.

Public property OnBoundNavigationInfoFieldsChanged: TSceneNotification read FOnBoundNavigationInfoFieldsChanged write FOnBoundNavigationInfoFieldsChanged;
 
Public property RootNode: TX3DRootNode read FRootNode write SetRootNode;

Actual VRML/X3D graph defining this scene.

It is allowed to change contents of RootNode. Just make sure the scene is notified about these changes. The simplest option is to use simple properties of nodes (not the ones starting with Fd... prefix), when possible. Then everything is notified automatically. If you must use fields through the FdXxx properties, then assign them using TX3DField.Send, or (if you need to assign field values directly, like TSFVec3f.Value := ...) call TX3DField.Changed.

It is also allowed to change the value of RootNode and even to set RootNode to Nil. Changing RootNode allows you to load and unload whole new VRML/X3D graph (for example from some 3D file) whenever you want, and keep the same TCastleSceneCore instance (with the same rendering settings and such).

Public property OwnsRootNode: boolean read FOwnsRootNode write FOwnsRootNode default true;

If True, RootNode will be freed by destructor of this class.

Public property TriangleOctreeProgressTitle: string read FTriangleOctreeProgressTitle write FTriangleOctreeProgressTitle;

Progress title shown during spatial structure creation (through TProgress.Title). Uses only when not empty, and only if progress was not active already (so we avoid starting "progress bar within a progress bar").

Public property ShapeOctreeProgressTitle: string read FShapeOctreeProgressTitle write FShapeOctreeProgressTitle;

Progress title shown during spatial structure creation (through TProgress.Title). Uses only when not empty, and only if progress was not active already (so we avoid starting "progress bar within a progress bar").

Public property PointingDeviceOverItem: PTriangle read FPointingDeviceOverItem write FPointingDeviceOverItem;

Current item over which the pointing device is. Nil if over none. For example, you can investigate it's pointing device sensors (in PointingDeviceOverItemˆ.State.PointingDeviceSensors), although there's a shortcut for just this in PointingDeviceSensors. You can change this by PointingDeviceMove and PointingDeviceClear.

Public property PointingDeviceOverPoint: TVector3 read FPointingDeviceOverPoint write FPointingDeviceOverPoint;

Current 3D point under the pointing device. Only meaningful when PointingDeviceOverItem <> nil, otherwise undefined.

Public property PointingDeviceActiveSensors: TX3DNodeList read FPointingDeviceActiveSensors;

Currently active pointing-device sensors. Only TAbstractPointingDeviceSensorNode instances. Always empty when PointingDeviceActive = False. Read-only from outside of this class.

Note that sensor specified here doesn't have to be one of the sensors of PointingDeviceOverItem. When some sensor is activated, it grabs further events until it's deactivated (e.g. when you set PointingDeviceActive := false, which means that user released mouse button). This means that when user moves the mouse while given sensors are active, he can move mouse over other items, even the ones where the active sensors aren't listed — but the sensors remain active.

Public property PointingDeviceActive: boolean read FPointingDeviceActive default false;

Is pointing device currently active (for example, mouse button is pressed down).

Public property OnPointingDeviceSensorsChange: TNotifyEvent read FOnPointingDeviceSensorsChange write FOnPointingDeviceSensorsChange;

Event called PointingDeviceSensors or PointingDeviceActiveSensors lists (possibly) changed.

Public property TimeAtLoad: TFloatTime read FTimeAtLoad;

Initial world time, set by the last ResetTimeAtLoad call.

Public property BackgroundStack: TBackgroundStack read FBackgroundStack;

Stack of background nodes. The node at the top is the current background. All nodes on this stack must descend from TAbstractBackgroundNode class.

Public property FogStack: TFogStack read FFogStack;

Stack of fog nodes. The node at the top is the current fog. All nodes on this stack must descend from TFogNode class.

Public property NavigationInfoStack: TNavigationInfoStack read FNavigationInfoStack;

Stack of NavigatinInfo nodes. The node at the top is the current NavigatinInfo. All nodes on this stack must descend from TNavigationInfoNode class.

Public property ViewpointStack: TViewpointStack read FViewpointStack;

Stack of viewpoint nodes. The node at the top is the current Viewpoint. All nodes on this stack must descend from TAbstractViewpointNode. Note that this includes also VRML 1.0/Inventor nodes.

Public property CompiledScriptHandlers: TCompiledScriptHandlerInfoList read FCompiledScriptHandlers;

List of handlers for VRML/X3D Script node with "compiled:" protocol. This is read-only, change this only by RegisterCompiledScript.

Public property HeadlightOn: boolean read FHeadlightOn write SetHeadlightOn;

Should we use headlight for this scene. Controls if containing TCastleSceneManager will use a headlight, if this is the main scene.

When you load a new model, this is always updated based on this model's NavigationInfo.headlight. (If no NavigationInfo node, then default is to use the headlight.) When you bind a new NavigationInfo node, this is also updated to follow NavigationInfo.headlight.

You can change the value of this property. If we have a NavigationInfo node, then NavigationInfo.headlight field will be always updated to correspond to this value. (It will be even updated using events mechanism if ProcessEvents, so scripts inside the VRML/X3D "know" when you turn on/off the headlight and may react to it, e.g. spawn a zombie monster when you turn on the flashlight.)

Public property OnHeadlightOnChanged: TNotifyEvent read FOnHeadlightOnChanged write FOnHeadlightOnChanged;
 
Public property Static: boolean read FStatic write SetStatic default false; deprecated 'do not use this; optimization done by this is really negligible; leave ProcessEvents=false for static scenes';

Warning: this symbol is deprecated: do not use this; optimization done by this is really negligible; leave ProcessEvents=false for static scenes

Static scene will not be automatically notified about the changes to the field values. This means that TX3DField.Send and TX3DField.Changed will not notify this scene. This makes a small optimization when you know you will not modify scene's VRML/X3D graph besides loading (or you're prepared to do it by manually calling Scene.InternalChangedField, but this should not be used anymore, it's really dirty).

The behavior of events is undefined when scene is static. This means that you should always have ProcessEvents = False when Static = True. Only when Static = false you're allowed to freely change ProcessEvents to True.

Changing this is expensive when the scene content is already loaded, so it's best to adjust this before Load.

Public property GlobalLights: TLightInstancesList read FGlobalLights;

Global lights of this scene. Read-only. May be useful to render other 3D objects with lights defined inside this scene.

Public property AnimationsList: TStrings read FAnimationsList;

List the names of available animations in this file. Animations are detected in VRML/X3D models as simply TimeSensor nodes (if you set AnimationPrefix property, we additionally filter them to show only the names starting with given prefix). You can even get the time sensor node directly by AnimationTimeSensor.

The resulting TStringList instance is owned by this object, do not free it.

Note that the list of animations may change if you rebuild the underlying X3D nodes graph, for example if you start to delete / add some TimeSensor nodes.

Public property AnimationPrefix: string read FAnimationPrefix write FAnimationPrefix;

The prefix of an X3D TimeSensor node name to treat it as a "named animation". Named animation are used by methods AnimationsList, PlayAnimation, and AnimationDuration, HasAnimation. By default this is empty, which means we consider all TimeSensor nodes a "named animation".

You can set this to something like 'Anim_' or 'Animation_' or whatever your 3D export software produces. Only the TimeSensor nodes with names starting with this prefix will be available on AnimationsList, and this prefix will be stripped from the names you use with methods like PlayAnimation.

Public property CurrentAnimation: TTimeSensorNode read FCurrentAnimation;

Currently played animation by PlayAnimation, or Nil. Note that in X3D world, you can have multiple active animations (TimeSensor nodes) at the same time. This property only describes the animation controlled by the PlayAnimation method.

Note that the animation may be started by PlayAnimation with a 1-frame delay, but this property hides it from you, it is changed immediately by the PlayAnimation call.

Public property FileName: string read FURL write SetURL; deprecated;

Warning: this symbol is deprecated.

Deprecated name for URL.

Published property TimePlaying: boolean read FTimePlaying write FTimePlaying default true;

When TimePlaying is True, the time of our 3D world will keep playing. More precisely, our Update will take care of increasing Time. Our Update is usually automatically called (if you added this scene to TCastleWindowCustom.Controls or TCastleControlCustom.Controls) so you don't have to do anything to make this work.

Published property TimePlayingSpeed: Single read FTimePlayingSpeed write FTimePlayingSpeed default 1.0;

Controls the time speed (if TimePlaying is True): 1.0 means that 1 second of real time equals to 1 unit of world time.

Published property Spatial: TSceneSpatialStructures read FSpatial write SetSpatial default [];

Which spatial structures (octrees) should be created and used.

Using "spatial structures" allows to achieve various things:

  • ssDynamicCollisions or ssStaticCollisions:

    Using one of these two flags allows to resolve collisions with the (collidable) triangles of the model. By default, every X3D Shape is collidable using it's exact mesh. You can use the X3D TCollisionNode to turn collisions off for some shapes, or replace some shapes with simpler objects for the collision-detection purposes.

    If you use neither ssDynamicCollisions nor ssStaticCollisions, then the collisions are resolved using the whole scene bounding box. That is, treating the whole scene as a giant cube.

    You can always toggle Collides to quickly make the scene not collidable. In summary:

    • Collides = False: the scene does not collide.

    • Collides = True and Spatial is empty: the scene collides as it's bounding box. This is the default situation after constructing TCastleScene.

    • Collides = True and Spatial contains ssDynamicCollisions or ssStaticCollisions: the scene collides as a set of triangles. The triangles are derived from information in X3D Shape and Collision nodes.

    The ssStaticCollisions can be used instead of ssDynamicCollisions when the scene is guaranteed to absolutely never change, and only when the speed is absolutely crucial. The collision structure created by ssStaticCollisions is a bit faster (although may use significantly more memory). The practical advice is to almost always use ssDynamicCollisions instead of ssStaticCollisions: the speed gains from ssStaticCollisions are usually impossible to measure, and ssStaticCollisions sometimes uses significantly more memory, and if you by accident modify the model (animate it etc.) with ssStaticCollisions -> then results are undefined, even crashes are possible.

  • ssRendering:

    Using this flag adds an additional optimization during rendering. It allows to use frustum culling with an octree. Whether the frustum culling is actually used depends on TCastleScene.OctreeFrustumCulling value (by default: yes).

    Without this flag, we can still use frustum culling, but it's less effective as it considers each shape separately. Whether the frustum culling is actually used depends in this case on TCastleScene.FrustumCulling value (by default: yes).

    Using frustum culling (preferably with ssRendering flag) is highly adviced if your camera usually only sees only a part of the scene. For example, it a noticeable optimization if you have a camera walking/flying inside a typical game level/location.

  • ssVisibleTriangles:

    Using this flag allows to resolve collisions with visible (not only collidable) triangles quickly.

    This is in practice useful only for ray-tracers, normal applications should not use this. Normal applications should avoid collision detection with the visible version of the model. Normal applications should instead perform collision detection with the collidable version of the model, since this is much better optimized (both by the engine code, and by an artist creating the model, using X3D Collision nodes etc.)

See TSceneSpatialStructure for more details about the possible values. For usual dynamic scenes rendered in real-time, you set this to [ssRendering, ssDynamicCollisions].

By default, the value of this property is empty, which means that no octrees will be created. This has to be the default value, to:

  1. Not create octrees by default (e.g. at construction). Creating them takes time (and memory).

  2. Allow developer to adjust TriangleOctreeLimits before creating the octree.

Published property ProcessEvents: boolean read FProcessEvents write SetProcessEvents default false;

Should the event mechanism (a basic of animations and interactions) work.

If True, then events will be send and received through X3D routes, time dependent nodes (X3DTimeDependentNode, like TimeSensor) will be activated and updated from Time time property, Press, Release and other methods will activate key/mouse sensor nodes, scripts will be initialized and work, etc.

In other words, this makes the scene fully animated and interacting with the user.

If False, this all doesn't work, which makes the scene static.

Published property URL: string read FURL write SetURL;

Currently loaded scene URL. Set this to load a 3D scene from the given URL, we can load from any known 3D format (VRML, X3D, Collada, 3ds, Wavefront, etc.).

Works just like the Load method (the overloaded version that takes AURL: string parameter). And, in fact, using directly the Load method will also change this URL property.

The only difference of Scene.URL := 'blah.x3d' vs Scene.Load('blah.x3d') is that setting the URL will not reload the scene if you set it to the same value. That is, Scene.URL := Scene.URL; will not reload the scene (you have to use explicit Load for this.).

Published property ShadowMaps: boolean read FShadowMaps write SetShadowMaps default true;

At loading, process the scene to support shadow maps. This happens at the Load method call, and it makes "receiveShadows" field automatically handled.

Note that this is not the only way to make shadow maps. VRML/X3D author can always make shadow maps by using lower-level nodes, see [https://castle-engine.io/x3d_extensions.php#section_ext_shadow_maps]. When using these lower-level nodes, this property does not matter This property (and related ones like ShadowMapsDefaultSize) is relevant only for handling shadows by the "receiveShadows" field.

Published property ShadowMapsDefaultSize: Cardinal read FShadowMapsDefaultSize write SetShadowMapsDefaultSize default DefaultShadowMapsDefaultSize;

Default shadow map texture size.

Affects how shadow maps are handled for the "receiveShadows" field. This is taken into account at the scene Load time, and only if ShadowMaps is True.

VRML/X3D author can always override this by placing a GeneratedShadowMap node inside light's defaultShadowMap field. In this case, GeneratedShadowMap.size determines shadow map size.

Published property InitialViewpointIndex: Cardinal read FInitialViewpointIndex write FInitialViewpointIndex default 0;

When loading new model, use this viewpoint index to initialize camera. VRML/X3D specification says to use the first (index = 0) viewpoint, you can change this property to bind 2nd, 3rd and so on viewpoints.

This is applied only at loading (actually, at ChangedAll). If you later want to bind another viewpoint, just send set_bind := true to it.

Published property InitialViewpointName: string read FInitialViewpointName write FInitialViewpointName;

When loading new model and looking for initial viewpoint, consider only viewpoints with this node name. Relevant only if non-empty.

This may cooperate with InitialViewpointIndex: InitialViewpointIndex specifies the index of viewpoint node that satisfies also InitialViewpointName condition. For example:

  • InitialViewpointIndex = 0 and InitialViewpointName = '' means to use the first viewpoint, ignoring nodes' names. This is the default behavior, also following VRML/X3D specification.

  • InitialViewpointIndex = 1 and InitialViewpointName = '' means to use the 2nd viewpoint. Node name doesn't matter.

  • InitialViewpointIndex = 1 and InitialViewpointName = 'blah' means to use the first viewpoint named 'blah'. That is, we are only counting nodes named 'blah' for this.

Published property AnimateOnlyWhenVisible: boolean read FAnimateOnlyWhenVisible write FAnimateOnlyWhenVisible default false;

When True, we animate (more precisely: process time pass in Update) only when the model is visible. This is a powerful optimization, but be careful if you depend on your animations for something else than just visual effect.

Published property AnimateSkipTicks: Cardinal read FAnimateSkipTicks write SetAnimateSkipTicks default 0;

Non-zero values optimize the animation processing, by not updating the animation every frame. After updating the animation in one Update call, the next AnimateSkipTicks number of Update calls will go very quickly, as they will not actually change the scene at all.

This is an effective optimization if the scene is usually not large on the screen.

  • The animation is less smooth. For example, if AnimateSkipTicks = 1, then every other Update call does not change the scene. For example, if you have 60 FPS, and Update is called 60 times per second, then we will actually change the scene only 30 times per second.

    The "skip" within every scene has a little random shift, to avoid synchronizing this skip across many created scenes. This makes this a little harder to notice.

  • In exchange, the speedup is substantial. For example, if AnimateSkipTicks = 1, then the animation on CPU effectively costs 2x less. In general, AnimateSkipTicks = N means that the cost drops to 1 / (1 + N).

Published property PrimitiveGeometry: TPrimitiveGeometry read FPrimitiveGeometry write SetPrimitiveGeometry default pgNone;

Easily turn the scene into a simple primitive, like sphere or box or plane. Changing this to something else than pgNone reloads the scene (calls Load with a new X3D graph).


Generated by PasDoc 0.15.0.