Castle Game EngineIntroduction Units Class Hierarchy Classes, Interfaces, Objects and Records Types Variables Constants Functions and Procedures Identifiers |
Class TCastleSceneCore
Unit
CastleSceneCore
Declaration
type TCastleSceneCore = class(TX3DEventsEngine)
Description
3D scene, 3D model handling (except rendering, for which see TCastleScene). Provides a lot of useful functionality. Simple loading of the scene (Load method), calculating various things (like BoundingBox method).
The Shapes tree provides a simple processed scene information, alternative to traversing the complicated VRML/X3D nodes graph. The basic idea is to have at the same time full VRML/X3D graph of the scene (in RootNode) and a simple view of the same scene (in Shapes).
VRML scene also takes care of initiating and managing VRML events and routes mechanism (see ProcessEvents).
The actual VRML/X3D nodes graph is stored in the RootNode property. Remember that if you directly change the fields/nodes within the RootNode, this scene object must be notified about this. The simplest way to do this is to use only TX3DField.Send to change the fields' values. Or you can call TX3DField.Changed after each change. Or you will have to call ChangedField or ChangedAll method of this class. If the scene is changed by VRML events, all changes are automagically acted upon, so you don't have to do anything.
For more-or-less static scenes, many things are cached and work very quickly. E.g. methods BoundingBox, VerticesCount, TrianglesCount, Shapes cache their results so after the first call to TrianglesCount next calls to the same method will return instantly (assuming that scene did not change much).
Hierarchy
Overview
Fields
Methods
 |
function CreateShape(AGeometry: TAbstractGeometryNode; AState: TX3DGraphTraverseState; ParentInfo: PTraversingInfo): TShape; virtual; |
 |
procedure UpdateHeadlightOnFromNavigationInfo; |
 |
procedure InvalidateBackground; virtual; |
 |
procedure DoPointingDeviceSensorsChange; virtual; |
 |
procedure ExecuteCompiledScript(const HandlerName: string; ReceivedValue: TX3DField); override; |
 |
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; |
 |
procedure Load(ARootNode: TX3DRootNode; AOwnsRootNode: boolean; const AResetTime: boolean = true); |
 |
procedure Load(const AURL: string; AllowStdIn: boolean = false; const AResetTime: boolean = true); |
 |
destructor Destroy; override; |
 |
function ShapesActiveCount: Cardinal; |
 |
function ShapesActiveVisibleCount: Cardinal; |
 |
function BoundingBox: TBox3D; override; |
 |
function VerticesCount(OverTriangulate: boolean): Cardinal; |
 |
function TrianglesCount(OverTriangulate: boolean): Cardinal; |
 |
function ViewpointsCount: Cardinal; |
 |
function GetViewpointName(Idx: integer): string; |
 |
procedure MoveToViewpoint(Idx: integer; Animated: boolean = true); |
 |
procedure AddViewpointFromCamera(ACamera: TCamera; AName: string); |
 |
procedure BeforeNodesFree(const InternalChangedAll: boolean = false); override; |
 |
procedure NodeFreeRemovingFromAllParents(Node: TX3DNode); |
 |
procedure RemoveShape(Shape: TShape); |
 |
procedure ChangedAll; override; |
 |
procedure ChangedField(Field: TX3DField); override; |
 |
procedure DoGeometryChanged(const Change: TGeometryChange; LocalGeometryShape: TShape); virtual; |
 |
procedure DoViewpointsChanged; |
 |
procedure DoBoundViewpointVectorsChanged; |
 |
procedure DoBoundNavigationInfoFieldsChanged; virtual; |
 |
procedure ScheduleChangedAll; |
 |
procedure BeginChangesSchedule; |
 |
procedure EndChangesSchedule; |
 |
function Info( ATriangleVerticesCounts, ABoundingBox, AManifoldAndBorderEdges: boolean): string; |
 |
function InfoTriangleVerticesCounts: string; |
 |
function InfoBoundingBox: string; |
 |
function InfoManifoldAndBorderEdges: string; |
 |
function OctreeRendering: TShapeOctree; |
 |
function OctreeDynamicCollisions: TShapeOctree; |
 |
function OctreeVisibleTriangles: TTriangleOctree; |
 |
function OctreeCollidableTriangles: TTriangleOctree; |
 |
function OctreeCollisions: TBaseTrianglesOctree; |
 |
function TriangleOctreeLimits: POctreeLimits; |
 |
function ShapeOctreeLimits: POctreeLimits; |
 |
function GetViewpoint( out ProjectionType: TProjectionType; out CamPos, CamDir, CamUp, GravityUp: TVector3Single; const ViewpointDescription: string = ''): TAbstractViewpointNode; |
 |
function GetPerspectiveViewpoint( out CamPos, CamDir, CamUp, GravityUp: TVector3Single; const ViewpointDescription: string = ''): TAbstractViewpointNode; |
 |
function TrianglesListShadowCasters: TTrianglesShadowCastersList; |
 |
function ManifoldEdges: TManifoldEdgeList; |
 |
function BorderEdges: TBorderEdgeList; |
 |
procedure ShareManifoldAndBorderEdges( ManifoldShared: TManifoldEdgeList; BorderShared: TBorderEdgeList); |
 |
procedure FreeResources(Resources: TSceneFreeResources); virtual; |
 |
procedure UnregisterScene(Node: TX3DNode); |
 |
function Press(const Event: TInputPressRelease): boolean; override; |
 |
function Release(const Event: TInputPressRelease): boolean; override; |
 |
function PointingDeviceActivate(const Active: boolean; const Distance: Single): boolean; override; |
 |
function PointingDeviceMove(const Pick: TRayCollisionNode; const Distance: Single): boolean; override; |
 |
function PointingDeviceSensors: TPointingDeviceSensorList; |
 |
procedure PointingDeviceClear; |
 |
procedure Update(const SecondsPassed: Single; var RemoveMe: TRemoveType); override; |
 |
procedure SetTime(const NewValue: TFloatTime); |
 |
procedure IncreaseTime(const TimeIncrease: TFloatTime); |
 |
procedure IncreaseTimeTick; override; |
 |
function GetTime: TX3DTime; override; |
 |
procedure ResetTime(const NewValue: TFloatTime); |
 |
procedure ResetTimeAtLoad; |
 |
function GetBackgroundStack: TX3DBindableStackBasic; override; |
 |
function GetFogStack: TX3DBindableStackBasic; override; |
 |
function GetNavigationInfoStack: TX3DBindableStackBasic; override; |
 |
function GetViewpointStack: TX3DBindableStackBasic; override; |
 |
procedure CameraChanged(ACamera: TCamera; const Changes: TVisibleChanges); |
 |
procedure RegisterCompiledScript(const HandlerName: string; Handler: TCompiledScriptHandler); |
 |
procedure CameraFromNavigationInfo(Camera: TCamera; const Box: TBox3D; const ForceNavigationType: string = ''; const ForceRadius: Single = 0); |
 |
procedure CameraFromViewpoint(ACamera: TCamera; const RelativeCameraTransform: boolean = false; const AllowTransitionAnimate: boolean = true); |
 |
function CreateCamera(AOwner: TComponent; const Box: TBox3D; const ForceNavigationType: string = ''): TUniversalCamera; |
 |
function CreateCamera(AOwner: TComponent; const ForceNavigationType: string = ''): TUniversalCamera; deprecated; |
 |
procedure CameraTransition(Camera: TCamera; const Position, Direction, Up: TVector3Single); |
 |
procedure CameraTransition(Camera: TCamera; const Position, Direction, Up, GravityUp: TVector3Single); |
 |
function MainLightForShadows( out AMainLightPosition: TVector4Single): boolean; |
 |
function CustomHeadlight: TAbstractLightNode; |
 |
procedure ViewChangedSuddenly; virtual; |
 |
procedure PrepareResources(Options: TPrepareResourcesOptions; ProgressStep: boolean; BaseLights: TAbstractLightInstancesList); override; |
 |
function Dragging: boolean; override; |
 |
function Caption: string; |
 |
function Node(const NodeName: string): TX3DNode; |
 |
function Field(const NodeName, FieldName: string): TX3DField; |
 |
function Event(const NodeName, EventName: string): TX3DEvent; |
Properties
Description
Fields
 |
GeneratedTextures: TGeneratedTextureList; |
|
 |
Dirty: Cardinal; |
Nonzero value prevents rendering of this scene, and generally means that our state isn't complete. This is useful if we're in the middle of some operation (like ChangedAll call or octree creation).
Some callbacks *may* be called during such time: namely, the progress call (e.g. done during constructing octrees). As these callbacks may try to e.g. render our scene (which should not be done on the dirty state), we have to protect ourselves using this variable (e.g. Render routines will exit immediately when Dirty <> 0).
|
 |
internal const DefaultShadowMapsDefaultSize = 256; |
|
Methods
 |
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.
|
 |
procedure UpdateHeadlightOnFromNavigationInfo; |
|
 |
procedure InvalidateBackground; virtual; |
|
 |
procedure ExecuteCompiledScript(const HandlerName: string; ReceivedValue: TX3DField); override; |
|
 |
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; |
|
 |
procedure Load(ARootNode: TX3DRootNode; AOwnsRootNode: boolean; const AResetTime: boolean = true); |
Load new 3D model (from VRML node tree). This replaces RootNode with new value.
If AResetTime, we will also do ResetTimeAtLoad, changing Time — this is usually what you want when you really load a new world.
|
 |
procedure Load(const AURL: string; AllowStdIn: boolean = false; const AResetTime: boolean = true); |
Load the 3D model from given URL.
Model is loaded by Load3D, so this supports all 3D model formats that Load3D handles (VRML, X3D, Wavefront OBJ, 3DS, Collada and more).
URL is downloaded using CastleDownload unit. 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.
|
 |
destructor Destroy; override; |
|
 |
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).
|
 |
function BoundingBox: TBox3D; override; |
Calculate bounding box, 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.
|
 |
function VerticesCount(OverTriangulate: boolean): Cardinal; |
|
 |
function TrianglesCount(OverTriangulate: boolean): Cardinal; |
|
 |
function ViewpointsCount: Cardinal; |
Helper functions for accessing viewpoints defined in the scene.
|
 |
function GetViewpointName(Idx: integer): string; |
|
 |
procedure MoveToViewpoint(Idx: integer; Animated: boolean = true); |
|
 |
procedure AddViewpointFromCamera(ACamera: TCamera; AName: string); |
|
 |
procedure BeforeNodesFree(const InternalChangedAll: boolean = false); override; |
Release all internal associations with your VRML 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.
InternalChangedAll is for internal use. This is True when ChangedAll calls it at the beginning of 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.
|
 |
procedure NodeFreeRemovingFromAllParents(Node: TX3DNode); |
Call Node.FreeRemovingFromAllParents, making sure that changes to our VRML 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.
|
 |
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.
|
 |
procedure ChangedAll; override; |
Notify scene that potentially everything changed in the VRML 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.)
ChangedAll causes recalculation of all things dependent on RootNode, so it's very costly to call this. While you have to call some ChangedXxx method after you changed RootNode graph directly, usually you can call something more efficient, like ChangedField.
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).
|
 |
procedure ChangedField(Field: TX3DField); override; |
Notify scene that you changed the value of given field.
This does relatively intelligent discovery what could be possibly affected by this field, and updates / invalidates internal information where needed.
Every change you do directly to the VRML/X3D nodes inside RootNode (using directly the methods of TX3DNode or TX3DField) must be reported to scene by calling this method. This includes changes to the inactive graph part (e.g. in inactive Switch child), because our shapes have to track it also. Changes to TShape.State.LastNodes (these nodes may come from StateDefaultNodes) should also be reported here. In fact, you can even notify this scene about changes to fields that don't belong to our RootNode — nothing bad will happen. We always try to intelligently detect what this change implicates for this VRML scene.
|
 |
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.
|
 |
procedure DoBoundNavigationInfoFieldsChanged; virtual; |
|
 |
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.
|
 |
procedure BeginChangesSchedule; |
|
 |
procedure EndChangesSchedule; |
|
 |
function Info( ATriangleVerticesCounts, ABoundingBox, AManifoldAndBorderEdges: boolean): string; |
Returns short information about the scene. This consists of a few lines, separated by CastleUtils.NL. Last line also ends with CastleUtils.NL.
Note that AManifoldAndBorderEdges = True will require calculation of ManifoldEdges and BorderEdges (if they weren't calculated already). If you don't want to actually use them (if you wanted only to report them to user), then you may free them (freeing some memory) with FreeResources([frManifoldAndBorderEdges]) .
|
 |
function InfoTriangleVerticesCounts: string; |
|
 |
function InfoBoundingBox: string; |
|
 |
function InfoManifoldAndBorderEdges: string; |
|
 |
function OctreeRendering: TShapeOctree; |
The dynamic octree containing all visible shapes. It's useful for "frustum culling", it will be automatically used by TCastleScene.RenderFrustum to speed up the rendering.
This octree will be automatically updated on dynamic scenes (when e.g. animation moves some shape by changing it's transformation).
Add ssRendering to Spatial property to have this available, otherwise it's Nil .
Note that when VRML scene contains Collision nodes, this octree contains the visible (not necessarily collidable) objects.
|
 |
function OctreeDynamicCollisions: TShapeOctree; |
The dynamic octree containing all collidable items.
This is actually a hierarchy of octrees: scene is partitioned first into Shapes (each instance of VRML geometry node), and then each Shape has an octree of triangles inside.
This octree is useful for all kinds of collision detection. Compared to OctreeCollidableTriangles, it is (very slightly on typical scenes) less efficient, but it can also be updated very fast. For example, merely transforming some Shape means that only one item needs to be moved in the top-level shape tree. So this is the most important structure for collision detection on dynamic scenes.
You can use OctreeCollisions to get either OctreeDynamicCollisions or OctreeCollidableTriangles, whichever is available.
Add ssDynamicCollisions to Spatial property to have this available, otherwise it's Nil .
Note that when VRML scene contains Collision nodes, this octree contains the collidable (not necessarily rendered) objects.
TODO: Temporarily, this is updated simply by rebuilding. This is a work in progress.
|
 |
function OctreeVisibleTriangles: TTriangleOctree; |
The octree containing all visible triangles. It's mainly useful for ray-tracers. When rendering using OpenGL, this has no use currently.
This octree is not updated on scene changes. In fact, the scene contents cannot change when this octree is created — as this octree keeps pointers to some states that may become invalid in dynamic scenes.
Add ssVisibleTriangles to Spatial property to have this available, otherwise it's Nil .
Note that when VRML scene contains Collision nodes, this octree contains the visible (not necessarily collidable) objects.
|
 |
function OctreeCollidableTriangles: TTriangleOctree; |
The octree containing all collidable triangles. This is pretty much unused for now.
It may be useful if you're absolutely sure that you have a static scene (nothing changes, e.g. because ProcessEvents = False ) and you want to have collision detection with the scene.
For dynamic scenes, using this is a bad idea as this octree is not updated on scene changes. In fact, the scene contents cannot change when this octree is created — as this octree keeps pointers to some states that may become invalid in dynamic scenes. Use OctreeDynamicCollisions for dynamic scenes.
You can use OctreeCollisions to get either OctreeDynamicCollisions or OctreeCollidableTriangles , whichever is available.
Add ssCollidableTriangles to Spatial property to have this available, otherwise it's Nil .
Note that when VRML scene contains Collision nodes, this octree contains the collidable (not necessarily rendered) objects.
|
 |
function GetViewpoint( out ProjectionType: TProjectionType; out CamPos, CamDir, CamUp, GravityUp: TVector3Single; 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.
|
 |
function ManifoldEdges: TManifoldEdgeList; |
ManifoldEdges is a list of edges that have exactly two neighbor triangles, and BorderEdges is a list of edges that have exactly one neighbor triangle. These are crucial for rendering shadows using shadow volumes.
Edges with more than two neighbors are allowed. If an edge has an odd number of neighbors, it will be placed in BorderEdges. Every other pair of neighbors will be "paired" and placed as one manifold edge inside ManifoldEdges . So actually edge with exactly 1 neighbor (odd number, so makes one BorderEdges item) and edge with exactly 2 neighbors (even number, one pair of triangles, makes one item in ManifoldEdges ) — they are just a special case of a general rule, that allows any neighbors number.
Note that vertexes must be consistently ordered in triangles. For two neighboring triangles, if one triangle's edge has order V0, V1, then on the neighbor triangle the order must be reversed (V1, V0). This is true in almost all situations, for example if you have a closed solid object and all outside faces are ordered consistently (all CCW or all CW). Failure to order consistently will result in edges not being "paired", i.e. we will not recognize that some 2 edges are in fact one edge between two neighboring triangles — and this will result in more edges in BorderEdges.
Both of these lists are calculated at once, i.e. when you call ManifoldEdges or BorderEdges for the 1st time, actually both ManifoldEdges and BorderEdges are calculated at once. If all edges are in ManifoldEdges , then the scene is a correct closed manifold, or rather it's composed from any number of closed manifolds.
Results of these functions are cached, and are also owned by this object. So don't modify it, don't free it.
This uses TrianglesListShadowCasters.
|
 |
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 graph) you must call it to manually "untie" this node (and all it's children) from this TCastleSceneCore instance.
|
 |
function PointingDeviceActivate(const Active: boolean; const Distance: Single): boolean; override; |
|
 |
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).
|
 |
procedure Update(const SecondsPassed: Single; var RemoveMe: TRemoveType); override; |
|
 |
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.
|
 |
procedure IncreaseTime(const TimeIncrease: TFloatTime); |
|
 |
procedure IncreaseTimeTick; override; |
Increase Time by some infinitely small value. This simply increments Time.PlusTicks , which may be sometimes useful: this allows events to pass through the ROUTEs without the fear of being rejected as "recursive (cycle) events".
|
 |
procedure ResetTime(const NewValue: TFloatTime); |
Set Time to arbitrary value.
You should only use this when you loaded new VRML 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).
|
 |
procedure CameraChanged(ACamera: TCamera; const Changes: TVisibleChanges); |
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. It automatically does proper VisibleChangeHere (OnVisibleChangeHere).
Parameters
- Changes
- describes changes to the scene caused by camera change. This is needed if some geometry / light follows the player.
We'll automatically add here vcCamera, so not need to specify it.
You should add here vcVisibleNonGeometry if player has a headlight. You should add here vcVisibleGeometry if player has a rendered avatar.
|
 |
procedure CameraFromNavigationInfo(Camera: TCamera; const Box: TBox3D; const ForceNavigationType: string = ''; const ForceRadius: Single = 0); |
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.
You can pass ForceNavigationType = 'EXAMINE', 'WALK', 'FLY', 'NONE' etc. (see X3D specification about NavigationInfo node, type field, on [http://www.web3d.org/x3d/specifications/ISO-IEC-19775-1.2-X3D-AbstractSpecification/Part01/components/navigation.html#NavigationInfo], although not all values are handled by our engine now). This way we will ignore what NavigationInfo.type information inside the scene says.
This initializes a lot of camera properties:
Box is the expected bounding box of the whole 3D scene. Usually, it should be just Scene.BoundingBox, but it may be something larger, if this scene is part of a larger world.
|
 |
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 a scene 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.
|
 |
function CreateCamera(AOwner: TComponent; const Box: TBox3D; const ForceNavigationType: string = ''): TUniversalCamera; |
Create new camera instance, and bind it to current NavigationInfo and Viewpoint. This is only a shortcut for creating TUniversalCamera and then using CameraFromNavigationInfo and CameraFromViewpoint.
CameraFromViewpoint here is called with AllowTransitionAnimate = False , because animating camera in this case would be wrong (user does not want to see the animation from default camera position).
|
 |
function CreateCamera(AOwner: TComponent; const ForceNavigationType: string = ''): TUniversalCamera; deprecated; |
Warning: this symbol is deprecated. |
 |
procedure CameraTransition(Camera: TCamera; const Position, Direction, Up: TVector3Single); |
Make Camera go to the view given by Position, Direction, Up.
Honours current NavigationInfo.transitionType and transitionTime. If transitionType indicates instanteneous transition, then jumps by simple Camera.SetView(Position, Direction, Up) . Otherwise makes a smooth animation into new values by Camera.AnimateTo(Position, Direction, TransitionTime) .
Will generate NavigationInfo.transitionComplete when transition ends.
|
 |
function MainLightForShadows( out AMainLightPosition: TVector4Single): 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 [http://castle-engine.sourceforge.net/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.
|
 |
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.
|
 |
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.
|
 |
function Dragging: boolean; override; |
|
 |
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.
|
 |
function Node(const NodeName: string): TX3DNode; |
Simple methods to find a named X3D node (and a field or event within this node) in a 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.
|
 |
function Field(const NodeName, FieldName: string): TX3DField; |
|
 |
function Event(const NodeName, EventName: string): TX3DEvent; |
|
Properties
 |
property VisibilitySensors: TVisibilitySensors read FVisibilitySensors; |
|
 |
property Shapes: TShapeTree read FShapes; |
Simple (usually very flat) tree of shapes within this VRML 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".
|
 |
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.
|
 |
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.
|
 |
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.
|
 |
property OnBoundNavigationInfoFieldsChanged: TSceneNotification
read FOnBoundNavigationInfoFieldsChanged write FOnBoundNavigationInfoFieldsChanged; |
|
 |
property RootNode: TX3DRootNode read FRootNode write FRootNode; |
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 — you should assign fields using methods like TX3DField.Send or (if you assign field values directly, like TSFVec3f.Value := ... ) call TX3DField.Changed. Eventually, you can call our ChangedField method (but it's usually nicer to use TX3DField.Changed).
It is also allowed to change the value of RootNode and even to set RootNode to Nil . Be sure to call ChangedAll after this. 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).
Note that there is also a trick to conserve memory use. After you've done PrepareResources some things are precalculated here, and RootNode is actually not used, unless you use ProcessEvents. So you can free RootNode (and set it to nil here) without calling ChangedAll and some things will just continue to work, unaware of the fact that the underlying RootNode structure is lost. Note that this is still considered a "dirty trick", and you will have to be extra-careful then about what methods/properties from this class. Generally, use only things that you prepared with PrepareResources. So e.g. calling Render or using BoundingBox. If all your needs are that simple, then you can use this trick to save some memory. This is actually useful when using TCastlePrecalculatedAnimation, as it creates a lot of intermediate node structures and TCastleSceneCore instances.
|
 |
property OwnsRootNode: boolean read FOwnsRootNode write FOwnsRootNode default true; |
If True , RootNode will be freed by destructor of this class.
|
 |
property TriangleOctreeProgressTitle: string
read FTriangleOctreeProgressTitle
write FTriangleOctreeProgressTitle; |
|
 |
property ShapeOctreeProgressTitle: string
read FShapeOctreeProgressTitle
write FShapeOctreeProgressTitle; |
|
 |
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.
|
 |
property PointingDeviceOverPoint: TVector3Single
read FPointingDeviceOverPoint write FPointingDeviceOverPoint; |
Current 3D point under the pointing device. Only meaningful when PointingDeviceOverItem <> nil, otherwise undefined.
|
 |
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.
|
 |
property PointingDeviceActive: boolean
read FPointingDeviceActive default false; |
Is pointing device currently active (for example, mouse button is pressed down).
|
 |
property Time: TX3DTime read FTime; |
This is the scene time, that is passed to time-dependent nodes. See X3D specification "Time" component about time-dependent nodes. In short, this "drives" the time passed to TimeSensor, MovieTexture and AudioClip. See SetTime for changing this.
Default value is 0.0 (zero).
|
 |
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.
|
 |
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.
|
 |
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.
|
 |
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.
|
 |
property CameraPosition: TVector3Single read FCameraPosition; |
Camera position/direction/up known for this scene.
Set by CameraChanged. CameraViewKnown = False means that CameraChanged was never called, and so camera settings are not known, and so other Camera* properties have undefined values.
These are remembered for various reasons, like reacting to changes to ProximitySensor box (center, size) (or it's transform), or changing LOD node children.
|
 |
property CameraViewKnown: boolean read FCameraViewKnown; |
|
 |
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.)
|
 |
property OnHeadlightOnChanged: TNotifyEvent
read FOnHeadlightOnChanged write FOnHeadlightOnChanged; |
|
 |
property Static: boolean read FStatic write SetStatic default false; |
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 graph besides loading (or you're prepared to do it by manually calling Scene.ChangedField etc.).
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.
|
 |
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.
|
 |
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.
|
 |
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.
|
 |
property Spatial: TSceneSpatialStructures read FSpatial write SetSpatial; |
Which spatial structures (octrees, for now) should be created and managed.
You should set this, based on your expected usage of this model. See TSceneSpatialStructure for possible values. For usual dynamic scenes rendered with OpenGL, you want this to be [ssRendering, ssDynamicCollisions].
Before setting any value <> [] you may want to adjust TriangleOctreeLimits, ShapeOctreeLimits. These properties fine-tune how the octrees will be generated (although default values should be Ok for typical cases).
Default value of this property is [], which means that no octrees will be created. This has to be the default value, to 1. get you chance to change TriangleOctreeLimits and such before creating octree 2. otherwise, scenes that not require collision detection would unnecessarily create octrees at construction. Scenes that do not have any spatial structures use default T3D methods for resolving collisions, which means that collisions are checked vs BoundingBox of this scene. (Unless GetCollides is False , in which case collisions are disabled, regardless of Spatial .)
|
 |
property ProcessEvents: boolean
read FProcessEvents write SetProcessEvents default false; |
Should the VRML/X3D event mechanism work.
If True , then events will be send and received through 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.
|
 |
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.).
|
 |
property FileName: string read FURL write SetURL; deprecated; |
Warning: this symbol is deprecated.
Deprecated name for URL.
|
 |
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 author can always make shadow maps by using lower-level nodes, see [http://castle-engine.sourceforge.net/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.
|
 |
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 author can always override this by placing a GeneratedShadowMap node inside light's defaultShadowMap field. In this case, GeneratedShadowMap.size determines shadow map size.
|
 |
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.
|
 |
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.
|
Generated by PasDoc 0.13.0 on 2014-04-30 22:06:44
|