Castle Game EngineIntroduction Units Class Hierarchy Classes, Interfaces, Objects and Records Types Variables Constants Functions and Procedures Identifiers
|
Class TCastleTransform
Unit
CastleTransform
Declaration
type TCastleTransform = class(TComponent)
Description
Group and transform (move, rotate, scale) children objects.
Add and remove children using the Add, Remove and similar methods. A child can be any TCastleTransform instance, in particular it can be a TCastleScene instance (which allows to load and render any 3D or 2D model).
Control the transformation using these properties:
Move using Translation.
Rotate using Rotation. The rotation is performed around the Center point. The rotation may be alternatively controlled using the Direction and Up vectors.
Change size using Scale. Scale is done around Center and with orientation given by ScaleOrientation.
This class is the base object that is managed by the TCastleSceneManager. You insert instances of this class into TCastleSceneManager.Items, which is actually an instance of TCastleTransform too.
This class implements also optional gravity and physics. See the Gravity property for a simple unrealistic gravity model. See the RigidBody for a proper rigid-bidy simulation, with correct gravity model and collisions with other rigid bodies.
Hierarchy
- TComponent
- TCastleTransform
Overview
Fields
 |
internal const DefaultMiddleHeight = 0.5; |
 |
internal const DefaultDirection: array [TOrientationType] of TVector3 = (
(Data: (0, 0, -1)),
(Data: (0, -1, 0)),
(Data: (1, 0, 0))
); |
 |
internal const DefaultUp: array [TOrientationType] of TVector3 = (
(Data: (0, 1, 0)),
(Data: (0, 0, 1)),
(Data: (0, 0, 1))
); |
 |
var DefaultOrientation: TOrientationType; static; |
Methods
 |
procedure AddToWorld(const Value: TSceneManagerWorld); |
 |
procedure RemoveFromWorld(const Value: TSceneManagerWorld); |
 |
procedure ChangeWorld(const Value: TSceneManagerWorld); virtual; |
 |
procedure Notification(AComponent: TComponent; Operation: TOperation); override; |
 |
function HeightCollision(const APosition, GravityUp: TVector3; const TrianglesToIgnoreFunc: TTriangleIgnoreFunc; out AboveHeight: Single; out AboveGround: PTriangle): boolean; |
 |
function MoveCollision( const OldPos, ProposedNewPos: TVector3; out NewPos: TVector3; const IsRadius: boolean; const Radius: Single; const OldBox, NewBox: TBox3D; const TrianglesToIgnoreFunc: TTriangleIgnoreFunc): boolean; overload; |
 |
function MoveCollision( const OldPos, NewPos: TVector3; const IsRadius: boolean; const Radius: Single; const OldBox, NewBox: TBox3D; const TrianglesToIgnoreFunc: TTriangleIgnoreFunc): boolean; overload; |
 |
function SegmentCollision(const Pos1, Pos2: TVector3; const TrianglesToIgnoreFunc: TTriangleIgnoreFunc; const ALineOfSight: boolean): boolean; |
 |
function SphereCollision(const Pos: TVector3; const Radius: Single; const TrianglesToIgnoreFunc: TTriangleIgnoreFunc): boolean; |
 |
function SphereCollision2D(const Pos: TVector2; const Radius: Single; const TrianglesToIgnoreFunc: TTriangleIgnoreFunc; const Details: TCollisionDetails = nil): boolean; |
 |
function PointCollision2D(const Point: TVector2; const TrianglesToIgnoreFunc: TTriangleIgnoreFunc): boolean; |
 |
function BoxCollision(const Box: TBox3D; const TrianglesToIgnoreFunc: TTriangleIgnoreFunc): boolean; |
 |
function RayCollision(const RayOrigin, RayDirection: TVector3; const TrianglesToIgnoreFunc: TTriangleIgnoreFunc): TRayCollision; |
 |
function LocalHeightCollision(const APosition, GravityUp: TVector3; const TrianglesToIgnoreFunc: TTriangleIgnoreFunc; out AboveHeight: Single; out AboveGround: PTriangle): boolean; virtual; |
 |
function LocalMoveCollision( const OldPos, ProposedNewPos: TVector3; out NewPos: TVector3; const IsRadius: boolean; const Radius: Single; const OldBox, NewBox: TBox3D; const TrianglesToIgnoreFunc: TTriangleIgnoreFunc): boolean; virtual; |
 |
function LocalMoveCollision( const OldPos, NewPos: TVector3; const IsRadius: boolean; const Radius: Single; const OldBox, NewBox: TBox3D; const TrianglesToIgnoreFunc: TTriangleIgnoreFunc): boolean; virtual; |
 |
function LocalSegmentCollision(const Pos1, Pos2: TVector3; const TrianglesToIgnoreFunc: TTriangleIgnoreFunc; const ALineOfSight: boolean): boolean; virtual; |
 |
function LocalSphereCollision(const Pos: TVector3; const Radius: Single; const TrianglesToIgnoreFunc: TTriangleIgnoreFunc): boolean; virtual; |
 |
function LocalSphereCollision2D(const Pos: TVector2; const Radius: Single; const TrianglesToIgnoreFunc: TTriangleIgnoreFunc; const Details: TCollisionDetails = nil): boolean; virtual; |
 |
function LocalPointCollision2D(const Point: TVector2; const TrianglesToIgnoreFunc: TTriangleIgnoreFunc): boolean; virtual; |
 |
function LocalBoxCollision(const Box: TBox3D; const TrianglesToIgnoreFunc: TTriangleIgnoreFunc): boolean; virtual; |
 |
function LocalRayCollision(const RayOrigin, RayDirection: TVector3; const TrianglesToIgnoreFunc: TTriangleIgnoreFunc): TRayCollision; virtual; |
 |
procedure LocalRender(const Params: TRenderParams); virtual; |
 |
procedure LocalRenderShadowVolume( ShadowVolumeRenderer: TBaseShadowVolumeRenderer; const ParentTransformIsIdentity: boolean; const ParentTransform: TMatrix4); virtual; |
 |
function Translation2D: TVector2; |
 |
procedure TransformMatricesMult(var M, MInverse: TMatrix4); deprecated 'do not use this directly, instead use Transform and InverseTransform methods'; |
 |
procedure TransformMatrices(out M, MInverse: TMatrix4); deprecated 'do not use this directly, instead use Transform and InverseTransform methods'; |
 |
function AverageScale: Single; |
 |
function AverageScale2D: Single; |
 |
procedure Fall(const FallHeight: Single); virtual; |
 |
procedure ChangedTransform; virtual; |
 |
constructor Create(AOwner: TComponent); override; |
 |
destructor Destroy; override; |
 |
function GetExists: boolean; virtual; |
 |
function GetCollides: boolean; virtual; |
 |
function GetPickable: boolean; virtual; |
 |
function GetVisible: boolean; virtual; |
 |
procedure Disable; |
 |
procedure Enable; |
 |
procedure Add(const Item: TCastleTransform); |
 |
procedure Insert(const Index: Integer; const Item: TCastleTransform); |
 |
procedure Remove(const Item: TCastleTransform); |
 |
function Count: Integer; |
 |
procedure Clear; |
 |
procedure Exchange(const Index1, Index2: Integer); |
 |
procedure SortBackToFront(const BlendingSort: TBlendingSort; const CameraPosition: TVector3); |
 |
procedure SortBackToFront2D; |
 |
function BoundingBox: TBox3D; |
 |
function LocalBoundingBox: TBox3D; virtual; |
 |
procedure Render(const Params: TRenderParams); overload; |
 |
procedure Render(const Frustum: TFrustum; const Params: TRenderParams); overload; deprecated 'use Render method without an explicit Frustum parameter, it is in Params.Frustum now'; |
 |
procedure RenderShadowVolume( ShadowVolumeRenderer: TBaseShadowVolumeRenderer; const ParentTransformIsIdentity: boolean; const ParentTransform: TMatrix4); |
 |
procedure PrepareResources(const Options: TPrepareResourcesOptions; const ProgressStep: boolean; const Params: TPrepareParams); virtual; |
 |
function PrepareResourcesSteps: Cardinal; virtual; |
 |
function Press(const Event: TInputPressRelease): boolean; virtual; |
 |
function Release(const Event: TInputPressRelease): boolean; virtual; |
 |
function PointingDeviceActivate(const Active: boolean; const Distance: Single; const CancelAction: boolean = false): boolean; virtual; |
 |
function PointingDeviceMove(const Pick: TRayCollisionNode; const Distance: Single): boolean; virtual; |
 |
procedure Update(const SecondsPassed: Single; var RemoveMe: TRemoveType); virtual; |
 |
procedure VisibleChangeHere(const Changes: TVisibleChanges); virtual; |
 |
procedure VisibleChangeNotification(const Changes: TVisibleChanges); virtual; |
 |
procedure CameraChanged(ACamera: TCamera); virtual; |
 |
procedure GLContextClose; virtual; |
 |
procedure UpdateGeneratedTextures( const RenderFunc: TRenderFromViewFunction; const ProjectionNear, ProjectionFar: Single; const OriginalViewport: TRectangle); virtual; |
 |
function Dragging: boolean; virtual; |
 |
function Middle: TVector3; virtual; |
 |
function Sector: TSector; |
 |
function Sphere(out Radius: Single): boolean; virtual; |
 |
function Height(const MyPosition: TVector3; out AboveHeight: Single): boolean; overload; |
 |
function Height(const MyPosition: TVector3; out AboveHeight: Single; out AboveGround: PTriangle): boolean; overload; |
 |
function LineOfSight(const Pos1, Pos2: TVector3): boolean; |
 |
function MoveAllowed(const OldPos, ProposedNewPos: TVector3; out NewPos: TVector3; const BecauseOfGravity: boolean): boolean; overload; |
 |
function MoveAllowed(const OldPos, NewPos: TVector3; const BecauseOfGravity: boolean): boolean; overload; |
 |
function Ray(const RayOrigin, RayDirection: TVector3): TRayCollision; |
 |
function OutsideToLocal(const Pos: TVector3): TVector3; |
 |
function LocalToOutside(const Pos: TVector3): TVector3; |
 |
function PreferredHeight: Single; virtual; |
 |
function Transform: TMatrix4; |
 |
function InverseTransform: TMatrix4; |
 |
function HasWorldTransform: boolean; |
 |
function WorldTransform: TMatrix4; |
 |
function WorldInverseTransform: TMatrix4; |
 |
procedure Translate(const T: TVector3); |
 |
function Move(const ATranslation: TVector3; const BecauseOfGravity: boolean; const EnableWallSliding: boolean = true): boolean; |
 |
function GetTranslation: TVector3; deprecated 'use Translation'; |
 |
procedure Identity; |
 |
procedure GetView(out APos, ADir, AUp: TVector3); |
 |
procedure SetView(const APos, ADir, AUp: TVector3; const AdjustUp: boolean = true); overload; |
 |
procedure SetView(const ADir, AUp: TVector3; const AdjustUp: boolean = true); overload; |
 |
procedure UpPrefer(const AUp: TVector3); |
Properties
Description
Fields
 |
internal const DefaultMiddleHeight = 0.5; |
|
 |
internal const DefaultDirection: array [TOrientationType] of TVector3 = (
(Data: (0, 0, -1)),
(Data: (0, -1, 0)),
(Data: (1, 0, 0))
); |
|
 |
internal const DefaultUp: array [TOrientationType] of TVector3 = (
(Data: (0, 1, 0)),
(Data: (0, 0, 1)),
(Data: (0, 0, 1))
); |
|
Methods
 |
procedure AddToWorld(const Value: TSceneManagerWorld); |
Change to new world, or (if not needed) just increase FWorldReferences. Value must not be Nil .
|
 |
procedure RemoveFromWorld(const Value: TSceneManagerWorld); |
Decrease FWorldReferences, then (if needed) change world to Nil . Value must not be Nil .
|
 |
procedure ChangeWorld(const Value: TSceneManagerWorld); virtual; |
Called when the current 3D world (which corresponds to the current TCastleSceneManager) of this 3D object changes. This can be ignored (not care about FWorldReferences) when Value = FWorld.
Each 3D object can only be part of one TSceneManagerWorld at a time. The object may be present many times within the world (counted by FWorldReferences, which is always set to 1 by this procedure for non-nil Value, and 0 for nil Value). Always remove 3D object from previous world (scene manager) before adding it to new one.
|
 |
procedure Notification(AComponent: TComponent; Operation: TOperation); override; |
|
 |
function HeightCollision(const APosition, GravityUp: TVector3; const TrianglesToIgnoreFunc: TTriangleIgnoreFunc; out AboveHeight: Single; out AboveGround: PTriangle): boolean; |
Height of a point above the 3D model. This checks ray collision, from APosition along the negated GravityUp vector. Measures distance to the nearest scene item (called "ground" here).
Parameters
- AboveHeight
- Height above the ground. One height unit equals one GravityUp vector. Always use normalized GravityUp vector if you expect to receive here a normal distance.
AboveHeight is always set to MaxSingle when returned result is False (this guarantee simplifies some code).
- AboveGround
- Pointer to PTriangle representing the ground. Must be
Nil if returned result is False . May be Nil even if we returned True (not all 3D objects may be able to generate PTriangle information about collision).
This may be useful for example to make a footsteps sound dependent on texture of the ground. Or to decrease player life points for walking on hot lava. See "The Castle" game for examples.
Returns
If the 3D scene is hit. False means that APosition floats above an empty space. That is, if you turn gravity on, it will fall down forever, as far as this 3D scene is concerned. |
 |
function MoveCollision( const OldPos, ProposedNewPos: TVector3; out NewPos: TVector3; const IsRadius: boolean; const Radius: Single; const OldBox, NewBox: TBox3D; const TrianglesToIgnoreFunc: TTriangleIgnoreFunc): boolean; overload; |
Can other 3D object (maybe a player) move without colliding with this object.
If IsRadius, then you should prefer to perform exact collision with sphere of given radius (must be > 0). At the very least, this checks that the line segment between OldPos and NewPos doesn't collide, and that sphere with given Radius centered around NewPos doesn't collide.
If not IsRadius, or if checking for collisions with sphere is not possible for some reasons, then you can check for collisions with boxes. OldBox should usually be ignored (it can be useful when collision-checking has to be approximate in some corner cases, see TCreature.MoveCollision). NewBox plays the same role as "sphere centered around NewPos" in paragraph above.
Overloaded version with separate ProposedNewPos and NewPos parameters allows you to accept the move, but for NewPos (that should be some slightly modified version of ProposedNewPos). This allows to implement wall-sliding: when camera tries to walk into the wall, we will change movement to move alongside the wall (instead of just completely blocking the move). When this version returns False , it's undefined what is the NewPos.
|
 |
function MoveCollision( const OldPos, NewPos: TVector3; const IsRadius: boolean; const Radius: Single; const OldBox, NewBox: TBox3D; const TrianglesToIgnoreFunc: TTriangleIgnoreFunc): boolean; overload; |
|
 |
function SegmentCollision(const Pos1, Pos2: TVector3; const TrianglesToIgnoreFunc: TTriangleIgnoreFunc; const ALineOfSight: boolean): boolean; |
|
 |
function SphereCollision2D(const Pos: TVector2; const Radius: Single; const TrianglesToIgnoreFunc: TTriangleIgnoreFunc; const Details: TCollisionDetails = nil): boolean; |
Check collision with a sphere in 2D (a circle, extruded to infinity along the Z axis).
Note that PointCollision2D and SphereCollision2D do not work reliably on objects that have 3D rotations. See PointCollision2D for details.
Parameters
- Details
- If non-nil, these are automatically filled with the details about the collision. If the result is
False , the Details contents are untouched. If the result is True , the Details contents are set to describe the 3D objects hierarchy that caused this collision.
|
 |
function PointCollision2D(const Point: TVector2; const TrianglesToIgnoreFunc: TTriangleIgnoreFunc): boolean; |
Check collision with a point in 2D (which is an infinite line along the Z axis in 3D).
Note that PointCollision2D and SphereCollision2D do not work reliably on objects that have 3D rotations, that is: rotations that change the direction of Z axis! This applies to all ways of rotating – using the TCastleTransform or using the X3D node TTransformNode (within a TCastleSce).
The reason: we transform the point (or sphere center) to the local coordinates, and we should also transform the Z axis to the local coordinates, to be always correct. Right now, we don't do the latter.
And we don't want to do it (at least not in all cases)! The simple 2D point collision check would then actually perform a 3D line collision check, thus PointCollision2D would lose all the speed benefits over LineCollision. PointCollision2D would become a simple shortcut to perform LineCollision with a line parallel to Z axis.
And in case of 2D games, or mostly 2D games, this speed loss would not be justified. Often you know that your objects have no 3D rotations, for example if your animations are done in Spine.
In the future, we may overcome this limitation. To do this, we will detect whether the transformation is "only 2D" (actually this part is easy, you can detect it by looking at the matrix even, so check whether appropriate numbers are zero). And then PointCollision2D will change to LineCollision, and SphereCollision2D will change to something like ExtrudedCircleCollision, only when necessary.
|
 |
function RayCollision(const RayOrigin, RayDirection: TVector3; const TrianglesToIgnoreFunc: TTriangleIgnoreFunc): TRayCollision; |
Check collision with a ray, building a TRayCollision result. Returns a collision as TRayCollision instance, or Nil if no collision. Caller is responsible for freeing the returned TRayCollision instance.
Contrary to other collision routines, this should ignore the Collides property. The Collides property specifies whether item collides with camera. And this method is used for picking (pointing) 3D stuff — everything visible can be picked, collidable or not. Instead, this looks at Pickable property (actually, at GetPickable method result).
This always returns the first collision with the 3D world, that is the one with smallest TRayCollision.Distance. For example, when implemented in TCastleTransform, this checks collisions for all list items, and chooses the closest one.
|
 |
function LocalHeightCollision(const APosition, GravityUp: TVector3; const TrianglesToIgnoreFunc: TTriangleIgnoreFunc; out AboveHeight: Single; out AboveGround: PTriangle): boolean; virtual; |
|
 |
function LocalMoveCollision( const OldPos, ProposedNewPos: TVector3; out NewPos: TVector3; const IsRadius: boolean; const Radius: Single; const OldBox, NewBox: TBox3D; const TrianglesToIgnoreFunc: TTriangleIgnoreFunc): boolean; virtual; |
|
 |
function LocalMoveCollision( const OldPos, NewPos: TVector3; const IsRadius: boolean; const Radius: Single; const OldBox, NewBox: TBox3D; const TrianglesToIgnoreFunc: TTriangleIgnoreFunc): boolean; virtual; |
|
 |
function LocalSegmentCollision(const Pos1, Pos2: TVector3; const TrianglesToIgnoreFunc: TTriangleIgnoreFunc; const ALineOfSight: boolean): boolean; virtual; |
|
 |
function LocalSphereCollision(const Pos: TVector3; const Radius: Single; const TrianglesToIgnoreFunc: TTriangleIgnoreFunc): boolean; virtual; |
|
 |
procedure LocalRender(const Params: TRenderParams); virtual; |
Render with given Params (includes a full transformation of this scene).
This is mostly an internal method. You should not need to override it during normal engine usage. Instead, you should render everything using TCastleScene, which allows to load or build (by code) nodes to display meshes, light and everything else. But overriding this may be useful for special customized rendering.
|
 |
procedure LocalRenderShadowVolume( ShadowVolumeRenderer: TBaseShadowVolumeRenderer; const ParentTransformIsIdentity: boolean; const ParentTransform: TMatrix4); virtual; |
Render shadow volumes (with a full transformation of this scene).
This is mostly an internal method. You should not need to override it during normal engine usage. If you render everything using TCastleScene, then rendering shadow volumes is also automatically handled by TCastleScene.
|
 |
procedure TransformMatricesMult(var M, MInverse: TMatrix4); deprecated 'do not use this directly, instead use Transform and InverseTransform methods'; |
Warning: this symbol is deprecated: do not use this directly, instead use Transform and InverseTransform methods
Transformation matrices, like Transform and InverseTransform.
|
 |
procedure TransformMatrices(out M, MInverse: TMatrix4); deprecated 'do not use this directly, instead use Transform and InverseTransform methods'; |
Warning: this symbol is deprecated: do not use this directly, instead use Transform and InverseTransform methods |
 |
function AverageScale: Single; |
Average value of 3D scale in Scale. It is not calculated as a simple average, it's a little smarter to prevent from weird results sometimes, see Approximate3DScale.
|
 |
function AverageScale2D: Single; |
Average value of 2D scale, from XY components of Scale. It is not calculated as a simple average, it's a little smarter to prevent from weird results sometimes, see Approximate2DScale.
|
 |
procedure Fall(const FallHeight: Single); virtual; |
Called when fall ended. You can use FallHeight to decrease creature life or such.
|
 |
procedure ChangedTransform; virtual; |
Override this to be notified about every transformation change. By default, this calls VisibleChangeHere, which causes the window to redraw.
|
 |
constructor Create(AOwner: TComponent); override; |
|
 |
destructor Destroy; override; |
|
 |
function GetExists: boolean; virtual; |
Does item really exist, see Exists and Enable, Disable. It TCastleTransform class, returns True if Exists and not disabled. May be modified in subclasses, to return something more complicated.
|
 |
function GetCollides: boolean; virtual; |
Does item really collide, see Collides. It TCastleTransform class, returns Collides and GetExists. May be modified in subclasses, to return something more complicated.
|
 |
function GetPickable: boolean; virtual; |
Is item really pickable, see Pickable. It TCastleTransform class, returns Pickable and GetExists. May be modified in subclasses, to return something more complicated.
|
 |
function GetVisible: boolean; virtual; |
Is item really visible, see Visible. It v class, returns Visible and GetExists. May be modified in subclasses, to return something more complicated.
|
 |
procedure Disable; |
Items that are at least once disabled are treated like not existing. Every Disable call should always be paired with Enable call (usually using try ... finally .... end block). Internally, we keep a counter of how many times the object is disabled, and if this counter is <> 0 then GetExists returns False . Using this is useful for taming collisions, especially to avoid self-collisions (when a creature moves, it checks for collision with other creatures, but it doesn't want to check for collisions with it's own bounding volume).
|
 |
procedure Enable; |
|
 |
procedure Add(const Item: TCastleTransform); |
Operate on 3D objects contained in the list. You can also operate directly on List instance.
|
 |
function Count: Integer; |
|
 |
procedure Clear; |
|
 |
procedure Exchange(const Index1, Index2: Integer); |
|
 |
procedure SortBackToFront(const BlendingSort: TBlendingSort; const CameraPosition: TVector3); |
Sort objects back-to-front right now following one of the blending sorting algorithms. Only the immediate list items are reordered, looking at their bounding boxes.
Calling this method makes sense if you have a list of objects, and some of them are partially-transparent and may be visible at the same place on the screen. It may even make sense to call this method every frame (like in every TCastleWindowCustom.OnUpdate), if you move or otherwise change the objects (changing their bounding boxes), or if the CameraPosition may change (note that CameraPosition is only relevant if BlendingSort = bs3D).
Sorting partially-transparent objects avoids artifacts when rendering.
Note that this doesn't take care of sorting the shapes within the scenes. For this, you should set Scene.Attributes.BlendingSort to a value like bs3D, to keep it sorted. It is actually the default now.
See the TBlendingSort documentation for the exact specification of sorting algorithms. Using BlendingSort = bsNone does nothing.
|
 |
procedure SortBackToFront2D; |
Sort objects back-to-front right now following the 2D blending sorting algorithm. See SortBackToFront for documentation, this method is only a shortcut for SortBackToFront(bs2D, TVector3.Zero) .
|
 |
function BoundingBox: TBox3D; |
Bounding box of the 3D object.
Should take into account both collidable and visible objects. For example, invisible walls (not visible) and fake walls (not collidable) should all be accounted here.
It's a bounding volume, it should be as large as necessary to include the object inside. At the same time, it should be as "tight" as it can, to make various optimizations work best.
|
 |
function LocalBoundingBox: TBox3D; virtual; |
Bounding box assuming that the scene is not transformed.
|
 |
procedure Render(const Frustum: TFrustum; const Params: TRenderParams); overload; deprecated 'use Render method without an explicit Frustum parameter, it is in Params.Frustum now'; |
Warning: this symbol is deprecated: use Render method without an explicit Frustum parameter, it is in Params.Frustum now |
 |
procedure RenderShadowVolume( ShadowVolumeRenderer: TBaseShadowVolumeRenderer; const ParentTransformIsIdentity: boolean; const ParentTransform: TMatrix4); |
Render shadow quads for all the things rendered by Render. This is done only if Exists and CastShadowVolumes.
It does shadow volumes culling inside (so ShadowVolumeRenderer should have FrustumCullingInit already initialized).
ParentTransform and ParentTransformIsIdentity describe the transformation of this object in the 3D world. TCastleTransform objects may be organized in a hierarchy when parent transforms it's children. When ParentTransformIsIdentity, ParentTransform must be TMatrix4.Identity (it's not guaranteed that when ParentTransformIsIdentity = True , Transform value will be ignored !).
|
 |
procedure PrepareResources(const Options: TPrepareResourcesOptions; const ProgressStep: boolean; const Params: TPrepareParams); virtual; |
Prepare resources, making various methods (like rendering and such) to execute fast.
It is usually simpler to call TCastleSceneManager.PrepareResources then this method. Calling SceneManager.PrepareResources(MyScene) will automatically call MyScene.PrepareResources(...) underneath, with proper parameters.
It is best to call this after the rendering context is initailized, which means: at Application.OnInitialize, or Window.OnOpen or later. Calling this method earlier will omit some preparations, thus reducing the effectiveness of them.
This makes sure that appropriate methods execute as fast as possible. It's never required to call this method — everything will be prepared "as needed" anyway. But if you allow everything to be prepared "as needed", then e.g. the first Render call may take a long time because it may have to prepare resources that will be reused in next Render calls. This is bad, as your program will seem very slow at the beginning (when rendering resources are being prepared, so at first frame, or a couple of first animation frames). To avoid this, call this method, showing the user something like "now we're preparing the resources — please wait".
For OpenGL rendered objects, this method ties this object to the current OpenGL context. But it doesn't change any OpenGL state or buffers contents (at most, it allocates some texture and display list names).
Parameters
- Options
- What features should be prepared to execute fast. See TPrepareResourcesOption, the names should be self-explanatory (they refer to appropriate methods of TCastleTransform, TCastleSceneCore or TCastleScene).
- ProgressStep
- Says that we should make this many Progress.Step calls during preparation. Useful to show progress bar to the user during long preparation.
TODO: for now, do not include prSpatial if you use ProgressStep. Reason: octree preparations have a separate mechanism that may want to show progress.
- Params
- Rendering parameters to prepare for. It is used only if Options contains prRender.
|
 |
function Press(const Event: TInputPressRelease): boolean; virtual; |
Press and release events of key and mouse. Return True if you handled them. See also TUIControl analogous events.
|
 |
function PointingDeviceActivate(const Active: boolean; const Distance: Single; const CancelAction: boolean = false): boolean; virtual; |
Pointing device (usually mouse) events. Return True if you handled the event.
PointingDeviceActivate signals that the picking button (usually, left mouse button) is pressed or released (depending on Active parameter).
Note that the exact key or mouse responsible for this is configurable in our engine by Input_Interact. By default it's the left mouse button, as is usual for VRML/X3D browsers. But it can be configured to be other mouse button or a key, for example most 3D games use "e" key to interact.
In case of Active = False (which means that pointing device is no longer pressed), an extra parameter CancelAction indicates whether this pointing device "press and release" sequence may be considered a "click". When CancelAction = True , then you should not make a "click" event (e.g. TouchSensor should not send touchTime event etc.).
In case of Active = True , CancelAction is always False .
PointingDeviceMove signals that pointer moves over this 3D object.
PointingDeviceMove receives Pick information about what exactly is hit by the 3D ray corresponding to the current mouse position. It contains the detailed information about 3D point, triangle and ray (all in local coordinate system) that are indicated by the mouse. PointingDeviceActivate does not receive this information now (because it may happen in obscure situations when ray direction is not known; this is all related to our "fallback to MainScene" mechanism).
They also receive Distance to the collision, in world coordinates. See TRayCollision.Distance.
The pointing device event (activation, deactivation or move) is send first to the innermost 3D object. That is, we first send this event to the first item on TRayCollision list corresponding to the current ray. This way, the innermost ("most local") 3D object has the chance to handle this event first. If the event is not handled, it is passed to other 3D objects (we simply iterate over the TRayCollision list). If nothing on TRayCollision list handled the item, it is eventually passed to main 3D scene (TCastleSceneManager.MainScene), if it wasn't already present on TRayCollision list.
Note that when passing this event to TCastleSceneManager.MainScene, it is possible that 3D ray simply didn't hit anything (mouse pointer is over the background). In this case, TRayCollisionNode.Point is undefined, TRayCollisionNode.Triangle is Nil and Distance is MaxSingle.
This event should be handled only if GetExists. Usually, 3D objects with GetExists = False will not be returned by RayCollision, so they will not receive this event anyway. However, if 3D object may be equal to TCastleSceneManager.MainScene, then it should be secured and check for GetExists inside PointingDeviceActivate and PointingDeviceMove.
|
 |
function PointingDeviceMove(const Pick: TRayCollisionNode; const Distance: Single): boolean; virtual; |
|
 |
procedure Update(const SecondsPassed: Single; var RemoveMe: TRemoveType); virtual; |
Continously occuring event, for various tasks.
Parameters
- RemoveMe
- Set this to rtRemove or rtRemoveAndFree to remove this item from 3D world (parent list) after Update finished. rtRemoveAndFree additionally will free this item. Initially it's rtNone when this method is called.
|
 |
procedure VisibleChangeHere(const Changes: TVisibleChanges); virtual; |
Something visible changed inside this 3D object. This is usually called by implementation of this 3D object, to notify others that it changed.
Changes is a set describing what changes occurred. See TVisibleChange docs for more information. It must specify all things that possibly changed.
Changes can be [], meaning "something tells us to redraw, but no visible change happened yet, maybe something will happen during a redraw" (this is used when e.g. possibly LOD level changed). We still broadcast VisibleChangeNotification, even when Changes=[].
The information about visibility changed is passed upward, to the Parent, and eventually to the TCastleSceneManager, that broadcasts this to all 3D objects by VisibleChangeNotification. If you want to react to visibility changes, you should override VisibleChangeNotification, not this method.
Be careful when handling this, various changes may cause this, so be prepared to handle this at every time.
|
 |
procedure VisibleChangeNotification(const Changes: TVisibleChanges); virtual; |
Something visible changed in the world. This is usually called by our container (like TCastleSceneManager), to allow this object to react (e.g. by regenerating mirror textures) to changes in the world (not necessarily in this object, maybe in some other TCastleScene instance).
If you want to react to visibility changes, you should override this.
|
 |
procedure CameraChanged(ACamera: TCamera); virtual; |
Main camera observing this 3D object changed. This is usually called by our container (like TCastleSceneManager) to notify that camera changed.
|
 |
procedure GLContextClose; virtual; |
Called when OpenGL context of the window is destroyed. This will be also automatically called from destructor.
Control should clear here any resources that are tied to the GL context.
|
 |
procedure UpdateGeneratedTextures( const RenderFunc: TRenderFromViewFunction; const ProjectionNear, ProjectionFar: Single; const OriginalViewport: TRectangle); virtual; |
|
 |
function Dragging: boolean; virtual; |
Are we in the middle of dragging something by moving the mouse.
This should be set to True to disable camera navigation methods that also use mouse move. In practice, to disable TExamineCamera view rotation/movement by moving the mouse, as it makes (comfortable) dragging practically impossible (at each mouse move, view changes...).
In particular, when you operate on active X3D pointing-device sensors (like drag sensors, e.g. PlaneSensor, but also TouchSensor may use it).
|
 |
function Middle: TVector3; virtual; |
Middle point, usually "eye point", of the 3D model. This is used for sphere center (if overriden Sphere returns True ) and is the central point from which collisions of this object are checked (Move, MoveAllowed, Height, LineOfSight). For 3D things like level scene this is mostly useless (as you will leave Sphere at default False then, and the scene itself doesn't move), but it's crucial for dynamic 3D things like player and moving creatures.
In short, it's usually most comfortable to think about this as a position of the eye, or the middle of the creature's head.
In an ideal situation, it should not be based on anything dynamic. For example, when this is based on the current bounding box of the animation, there is a risk that a large and sudden change in animation box could make the Middle point to jump to the other side of the wall (breaking collisions, as it changes Middle without a chance to check for collisions by MoveAllowed). Ideally, it should remain constant even when the shape of the object changes, and be possible to change only when MoveAllowed is checked (so only when TCastleTransform.Translation can change).
In this class this returns something sensible above the bottom of the box. See TCastleTransform.MiddleHeight.
|
 |
function Sector: TSector; |
Sector where the middle of this 3D object is. Used for AI. Nil if none (maybe because we're not part of any world, maybe because sectors of the world were not initialized, or maybe simply because we're outside of all sectors).
|
 |
function Sphere(out Radius: Single): boolean; virtual; |
Can the approximate sphere (around Middle point) be used for some collision-detection tasks. If True then Radius (and Middle point) determine the approximate sphere surrounding the 3D object (it does not have to be a perfect bounding sphere around the object), and it may be used for some collisions instead of BoundingBox. See CollidesWithMoving and MoveAllowed for when it may happen.
Must return False when not GetExists (because we can't express "empty sphere" by Sphere method for now, but BoundingBox can express TBox3D.Empty).
By default, in TCastleTransform class, this always returns False and Sphere is undefined.
The advantages of using a sphere, that does not have to be a perfect bounding sphere (it may be smaller than necessary, and only account e.g. for upper body part of the creature), are:
It can have constant radius, even though the actual creature animates. This allows us to perfectly, reliably guarantee that sphere absolutely never collides with level and such.
In case of a tight bounding volume (box or sphere) that animates, this guarantee is not really possible. Simply increasing time changes the animation to the next frame, which may be slightly larger in one dimension because e.g. creature moves a hand in this direction. This means that simply increasing time may change the non-collidable creature into a collidable one, if creature stands close to a wall/other creature and such. And we cannot simply stop/reverse an arbitrary animation at an arbitrary time (to avoid collision), this would look weird for some animations and would require some additional work at preparing animations and designing AI (as then "every action can be interrupted").
Also using a bounding volume large enough to account for all possible positions is not doable, as it would be too large. Consider that for humanoid creatures, walking animation usually has tall and thin bounding box (creature stands) but dead/lying animation usually has flat and wide bounding box.
So, only a bounding volume (like a sphere) that may be smaller than bounding volume can remain constant and easily guarantee the assertion "it never collides".
This means that using such sphere results in simpler collision detection routines, as they may assume that collision doesn't occur. In contrast, detection routines looking at our (possibly animated) BoundingBox must take into account that collision may already be happening, and they must incorporate code to allow creatures/players to "get unstruck".
Using smaller sphere also allows to naturally ascend the stairs and upward slopes. Sphere can move forward slightly, and then creature may raise up, to reach it's preferred height. Then sphere can move further forward, and so on. This alllows to allow stair climbing for creatures without any extra effort in the code.
The downside is that creature legs will temporarily "sink into the floor" when climbing up the stairs. But it's not noticeable if "growing up" mechanism works fast enough.
Sphere disadvantage:
Sphere is far from perfect as a bounding volume — it's too small, sometimes also too large, sometimes both at the same time...
Since the Sphere radius remains always the same, it must be good for many creature animation frames. In cases where the sphere isn't suitable, and you don't need advantages above — you can make Sphere return False . E.g. a dead creature may be stuck in a wall, and it doesn't have to climb stairs. So you don't really need sphere advantages listed above, and Sphere may return False when creature is in dying state.
But still it may be a problem sometimes, if some creature states have entirely different animations and bounding boxes. Then you will be forced to choose one universal Radius for all creature states. And you need constant radius to keep the advantage above of "guarantee".
1. Obviously you can't set radius too small, because if it's much smaller than actual creature's geometry then the creature will noticeably collide with level geometry and other creatures.
2. On the other hand, you can't set radius too large (or move sphere center, Middle, much lower). This would block stair climbing.
|
 |
function Height(const MyPosition: TVector3; out AboveHeight: Single): boolean; overload; |
Get height of my point above the rest of the 3D world.
This ignores the geometry of this 3D object (to not accidentaly collide with your own geometry), and checks collisions with the rest of the world.
|
 |
function Height(const MyPosition: TVector3; out AboveHeight: Single; out AboveGround: PTriangle): boolean; overload; |
|
 |
function LineOfSight(const Pos1, Pos2: TVector3): boolean; |
|
 |
function MoveAllowed(const OldPos, ProposedNewPos: TVector3; out NewPos: TVector3; const BecauseOfGravity: boolean): boolean; overload; |
Is the move from OldPos to ProposedNewPos possible for me. Returns true and sets NewPos if some move is allowed. Overloaded version without ProposedNewPos doesn't do wall-sliding, and only answers if exactly this move is allowed.
If this 3D object allows to use sphere as the bounding volume, if will be used (see Sphere).
This ignores the geometry of this 3D object (to not accidentaly collide with your own geometry), and checks collisions with the rest of the world.
|
 |
function MoveAllowed(const OldPos, NewPos: TVector3; const BecauseOfGravity: boolean): boolean; overload; |
|
 |
function Ray(const RayOrigin, RayDirection: TVector3): TRayCollision; |
Cast a ray from myself to the world, see what is hit.
This ignores the geometry of this 3D object (to not accidentaly collide with your own geometry), and checks collisions with the rest of the world.
|
 |
function OutsideToLocal(const Pos: TVector3): TVector3; |
Convert position between local and outside coordinate system. This is called OutsideToLocal , not WorldToLocal, because it only handles transformation defined in this item — it does not recursively apply all transform on the way to root .
|
 |
function PreferredHeight: Single; virtual; |
The preferred height of the object Middle above the ground, when the object is standing on the ground firmly. This is used by objects affected by gravity (like non-flying creatures and items) to know how far they should fall down or grow up.
The default implementation in this class looks at MiddleHeight property, see the algorithm described there. This may be dynamic (may change during creature lifetime, so you can make the creature duck or grow if you want).
|
 |
function InverseTransform: TMatrix4; |
Inverse transformation as a matrix, thus transforming from outside to local coordinate system. This is an inverse of Transform.
|
 |
procedure Translate(const T: TVector3); |
Unconditionally move this 3D object by given vector. You usually don't want to use this directly, instead use Move method to move checking collisions (and with optional wall sliding).
|
 |
function Move(const ATranslation: TVector3; const BecauseOfGravity: boolean; const EnableWallSliding: boolean = true): boolean; |
Move, if possible (no collisions). This is the simplest way to move a 3D object, and a basic building block for artificial intelligence of creatures.
Checks move possibility by MoveAllowed, using Middle point. Actual move is done using Translate.
|
 |
function GetTranslation: TVector3; deprecated 'use Translation'; |
Warning: this symbol is deprecated: use Translation |
 |
procedure GetView(out APos, ADir, AUp: TVector3); |
Get at once vectors: position, direction, up.
|
 |
procedure SetView(const APos, ADir, AUp: TVector3; const AdjustUp: boolean = true); overload; |
Set at once vectors: position, direction, up.
ADir and AUp given here do not have to be normalized (they will be normalized if needed). They will be automatically fixed to be orthogonal, if necessary: when AdjustUp = True (the default) we will adjust the up vector (preserving the given direction value), otherwise we will adjust the direction (preserving the given up value).
|
 |
procedure SetView(const ADir, AUp: TVector3; const AdjustUp: boolean = true); overload; |
|
 |
procedure UpPrefer(const AUp: TVector3); |
Change up vector, keeping the direction unchanged. If necessary, the up vector provided here will be fixed to be orthogonal to direction.
This is similar to assigning Up vector using it's property setter, but different behavior happens when we need to fix vectors to have direction orthogonal to up (which must be always true). In case of assigning Up by property setter, the Direction vector is changed (if necessary, to be orthogonal to up). In case of this method, the up vector is changed (if necessary, to be orthogonal to direction).
It's good to use this if you have a preferred up vector for creatures, but still preserving the direction vector has the highest priority.
|
Properties
 |
property Exists: boolean read FExists write FExists default true; |
Is this object visible and colliding.
Setting this to False pretty much turns everything of this 3D object to "off". This is useful for objects that disappear completely from the level when something happens. You could just as well remove this object from TCastleSceneManager.Items tree, but sometimes it's more comfortable to simply turn this property to False .
Descendants may also override GetExists method.
|
 |
property Collides: boolean read FCollides write FCollides default true; |
Should this 3D object participate in collision detection. You can turn this off, useful to make e.g. "fake" walls (to some secret places on level).
This describes collision resolution with almost everything — camera, player (in third-person perspective, camera may differ from player), other creatures. That is because everything resolves collisions through our methods MoveCollision and HeightCollision (high-level) or SegmentCollision, SphereCollision, SphereCollision2D, PointCollision2D, BoxCollision (low-level).
(Note that RayCollision is excluded from this, it exceptionally ignores Collides value, as it's primarily used for picking. Same for SegmentCollision with LineOfSight=true.)
The only exception are the collisions with T3DMoving instances (movable world parts like elevators and doors) that have their own detection routines and look at CollidesWithMoving property of other objects. That is, the T3DMoving instance itself must still have Collides = True , but it interacts with other objects if and only if they have CollidesWithMoving = True (ignoring their Collides value). This allows items to be moved by elevators, but still player and creatures can pass through them.
Note that if not Exists then this doesn't matter (not existing objects never participate in collision detection).
Descendants may also override GetCollides method. Sometimes it's more comfortable than changing the property value.
|
 |
property Pickable: boolean read FPickable write FPickable default true; |
Is item pickable by RayCollision method. Note that if not Exists then this doesn't matter (not existing objects are never pickable). This is independent from Collides, as RayCollision does not look at Collides, it only looks at Pickable.
Descendants may also override GetPickable method. Sometimes it's more comfortable than changing the property value.
|
 |
property Visible: boolean read FVisible write FVisible default true; |
Is item visible. Note that if not Exists then this doesn't matter (not existing objects are never visible). This is independent from Collides or Pickable.
Descendants may also override GetVisible method. Sometimes it's more comfortable than changing the property value.
|
 |
property CastShadowVolumes: boolean
read FCastShadowVolumes write FCastShadowVolumes default true; |
Does the 3D object cast shadows by shadow volumes. See also TCastleScene.ReceiveShadowVolumes.
|
 |
property Cursor: TMouseCursor read FCursor write SetCursor default mcDefault; |
Mouse cursor over this object.
|
 |
property CollidesWithMoving: boolean read FCollidesWithMoving write FCollidesWithMoving default false; |
Can this object be pushed by (or block movement of) doors, elevators and other moving level parts (T3DMoving instances).
Some 3D moving objects may try to avoid crushing this item. Like an automatic door that stops it's closing animation to not crush things standing in the doorway.
Some other 3D moving objects may push this object. Like elevators (vertical, or horizontal moving platforms). We may use sphere (see TCastleTransform.Sphere) for checking collisions, or bounding box (TCastleTransform.BoundingBox), depending on need.
|
 |
property InternalExcludeFromParentBoundingVolume: boolean
read FInternalExcludeFromParentBoundingVolume
write FInternalExcludeFromParentBoundingVolume; |
Is this object's bounding volume (BoundingBox) included in parent bounding volume. This should be always True for non-debug scenes. Violating this may cause rendering artifacts, things could disappear when they should not. Using this is reasonable only if you attach a debug geometry to your scene, and you don't want to enlarge your bounding volume (e.g. because this debug geometry visualizes something determined by the bounding volume, and it would create a "feedback loop" if the visualization itself would enlarge the bounding box).
|
 |
property Gravity: boolean read FGravity write FGravity default false; |
Gravity may make this object fall down (see FallSpeed) or grow up (see GrowSpeed). See also PreferredHeight.
Special notes for TPlayer: player doesn't use this (TPlayer.Gravity should remain False ), instead player relies on TPlayer.Camera.Gravity = True , that does a similar thing (with some extras, to make camera effects). This will change in the future, to merge these two gravity implementations. Although the TPlayer.Fall method still works as expected (it's linked to TWalkCamera.OnFall in this case).
TODO: In CGE 6.6 this will be deprecated, and you will be adviced to always use physics, through TCastleTransform.RigidBody, to have realistic gravity.
|
 |
property FallSpeed: Single read FFallSpeed write FFallSpeed default 0; |
Falling speed, in units per second, for Gravity.
This is relevant only if Gravity and PreferredHeight <> 0. 0 means no falling.
TODO: In CGE 6.6 this will be deprecated, and you will be adviced to always use physics, through TCastleTransform.RigidBody, to have realistic gravity.
|
 |
property GrowSpeed: Single read FGrowSpeed write FGrowSpeed default 0; |
Growing (raising from crouching to normal standing position) speed, in units per second. This is used by non-flying creatures when climbing up stairs, in which case Translation ("legs positon") may be sometimes under the ground while Middle ("eyes position") will be always above the ground and will try to grow to be at PreferredHeight above the ground.
This is relevant only if Gravity and PreferredHeight <> 0. 0 means no growing.
|
 |
property MiddleHeight: Single read FMiddleHeight write FMiddleHeight
default DefaultMiddleHeight; |
How high are creature eyes in the model. Value 0 means that eyes are at the bottom of the model, 0.5 means the middle, 1 means top.
The top is always considered to be at the top of the bounding box.
Definition of bottom depends on Gravity:
When Gravity is True , then the bottom is considered to be the plane where World.GravityCoordinate (like Z or Y axis) is zero. The actual bottom (lowest point) of the bounding box doesn't matter. This means that things placed below zero plane (like a creature tentacle or leg) will sink into the ground, instead of causing whole creature to move up. It also means that the creature can easily float above the ground, just model it a little above the zero plane.
In other words, this allows you to model the creature with respect to the ground (zero plane), which is comfortable.
Note that setting MiddleHeight to exact 0 means that gravity will not work, as it means that the PreferredHeight above the ground is to be stuck right at the ground level.
For gravity to work right, the MiddleHeight should be large enough to cause PreferredHeight to be > Sphere radius, for all possible animation states (for all possible bounding box values).
When Gravity is False , then the bottom is considered at the bottom of the bounding box.
This way it works regardless of where (0,0,0) is in your model (regardless if (0,0,0) represents legs, or middle of your creature), since we adjust to the BoundingBox position.
This property determines how the TCastleTransform handles the Middle implementation (this is the point used for various collision detection routines) and PreferredHeight (this is the preferred height of Middle above the ground). You can override these two methods to use a different approach, and then ignore MiddleHeight completely.
|
 |
property Translation: TVector3 read FTranslation write SetTranslation; |
Translation (move) the children. Zero by default.
|
 |
property Center: TVector3 read FCenter write SetCenter; |
Center point around which the Rotation and Scale is performed.
|
 |
property Rotation: TVector4 read FRotation write SetRotation; |
Rotation in 3D, around a specified axis. Rotation is expressed as a 4D vector, in which the first 3 components specify the rotation axis (does not need to be normalized, but must be non-zero), and the last component is the rotation angle in radians.
Rotation is done around Center.
|
 |
property Scale: TVector3 read FScale write SetScale; |
Scale in 3D. Scaling is done around Center and with orientation given by ScaleOrientation.
We do the best we can to work with any scale value, even negative or zero. But usually, it's best to keep the scale positive. More information:
If you can, keep the scale uniform, that is scale equal amount in X, Y and Z. For example set scale = (3.0, 3.0, 3.0) to scale 3x times, and avoid scale like (3.0, 1.0, 1.0) that scales more in one direction.
Non-uniform scale works, but some collisions are not perfectly calculated then. (For example, an ideal sphere is no longer a sphere when scaled in non-uniform fashion, and not everywhere do we account for that.) Although it works Ok on meshes. ScaleOrientation matters in case of non-uniform scale.
All scale components should > 0 if you want 3D lighting to work corrrectly. That is, avoid negative scale, that flips the orientation of faces (CCW becomes CW), or standard lighting may not work Ok.
For unlit stuff, or custom lighting, negative scale may be Ok. For many 2D games that use no lighting/custom lighting, negative scale is Ok.
At least, keep all scale components non-zero. Otherwise the scaling operation is not invertible, and generally collisions will not work correctly.
If you really need to set zero scale, at least consider using Collides = False .
|
 |
property ScaleOrientation: TVector4 read FScaleOrientation write SetScaleOrientation; |
Orientation in which 3D Scale is performed.
|
 |
property RigidBody: TRigidBody read FRigidBody write SetRigidBody; |
Participate in rigid body physics simulation. This makes this object collidable with other rigid bodies (if Collides) and it allows to move and rotate because of gravity or because of collisions with other objects (if TRigidBody.Dynamic is True ).
Setting this property makes this 3D object a single rigid body for the physics engine.
If this property is assigned and the TRigidBody.Dynamic is True (and TRigidBody.Dynamic is True by default) then this object is moved and rotated using the physics engine. It will move because of gravity (if TRigidBody.Gravity, also True by default), and because of collisions with other objects.
The TRigidBody.Collider property must be initialized before assigning the TRigidBody instance here. So you must create a TCollider descendant, specyfying the given TRigidBody as a parent. A rigid body without a collider would in theory not collide with anything, and (if TRigidBody.Dynamic) would simply fall down because of gravity. In practice, a rigid body without a collider is simply not allowed. If you really need this, assign anything to TRigidBody.Collider and just set Collides to False .
Our engine (for now) also has an internal, simple physics simulation, used to perform collisions with player, creatures, and optional (unrealistic) gravity. So we have two independent physics systems, but they try to not get into each others way (they each perform a different task). In the future there will be an option to use the full-featured physics engine for all simulations, also for player and creatures, at which point our "internal physics simulation" will become deprecated. For now, be aware of these:
Note that an object can only be present once in the World to be a rigid body. Breaking this rule will cause the EMultipleReferencesInWorld exception at an undefined time.
|
 |
property Position: TVector3 read FTranslation write SetTranslation; deprecated 'use Translation'; |
Warning: this symbol is deprecated: use Translation |
 |
property Direction: TVector3 read GetDirection write SetDirection; |
Direction the creature is facing, and up vector. These properties provide an alternative way to get and set the Rotation of the transformation. Thinking in terms of "direction" and "up" is often more natural when transforming creatures and player.
The Orientation determines what is your default direction and up (when the Rotation is zero). By default we follow X3D standard vectors suitable for gravity along the Y axis. So direction is -Z (DefaultCameraDirection), up is +Y (DefaultCameraUp).
The Direction and Up vectors should always be normalized (have length 1). When setting them by these properties, we will normalize them automatically.
They must also always be orthogonal. When setting Direction, Up will always be automatically adjusted to be orthogonal to Direction. And vice versa — when setting Up, Direction will be adjusted.
|
 |
property Up: TVector3 read GetUp write SetUp; |
|
 |
property Orientation: TOrientationType read FOrientation write FOrientation; |
How the direction and up vectors determine transformation. See TOrientationType for values documentation.
The default value of this is determined by static variable DefaultOrientation, this is usually comfortable (because almost always you use the same Orientation throughout your game). By default it's otUpYDirectionMinusZ (matching default cameras of OpenGL and VRML/X3D).
This value determines how you should model your 3D models, like the creatures, the items, and the player weapons. Generally, it applies to every 3D model that is used as a child of this TCastleTransform instance.
|
 |
property List: TCastleTransformList read FList; |
3D objects inside. Freeing these items automatically removes them from this list.
|
 |
property ExcludeFromStatistics: boolean
read FExcludeFromStatistics write FExcludeFromStatistics default false; |
Exclude from rendering statistics in TCastleAbstractViewport.Statistics.
|
Generated by PasDoc 0.15.0.
|