Castle Game Engine: Castle3D: Class T3D

# Class T3D
Description | Hierarchy | Fields | Methods | Properties
## Unit Castle3D ## Declaration `type T3D = class(TComponent)` ## Description Base 3D object, that can be managed by TCastleSceneManager. All 3D objects should descend from this, this way we can easily insert them into the TCastleSceneManager. Default implementations of collision methods in this class work with our BoundingBox: Wall-sliding MoveCollision version simply calls non-wall-sliding version (without separate ProposedNewPos and NewPos). Non-wall-sliding MoveCollision version, SegmentCollision, SphereCollision, BoxCollision and RayCollision and HeightCollision check for collisions with our BoundingBox, using TBox3D methods: TBox3D.TryRayClosestIntersection, TBox3D.TryRayEntrance, TBox3D.SegmentCollision, TBox3D.SphereCollision and TBox3D.Collision. The idea is that by default everything simply uses BoundingBox, and that is the only method that you really have to override. You do not have to (in fact, usually you should not) call "inherited" when overriding collision methods mentioned above. ## Hierarchy TComponent T3D ## Overview ### Methods
| `procedure CursorChange; virtual;`
| `function HeightCollision(const Position, GravityUp: TVector3Single; const TrianglesToIgnoreFunc: T3DTriangleIgnoreFunc; out AboveHeight: Single; out AboveGround: P3DTriangle): boolean; virtual;`
| `function MoveCollision( const OldPos, ProposedNewPos: TVector3Single; out NewPos: TVector3Single; const IsRadius: boolean; const Radius: Single; const OldBox, NewBox: TBox3D; const TrianglesToIgnoreFunc: T3DTriangleIgnoreFunc): boolean; virtual;`
| `function MoveCollision( const OldPos, NewPos: TVector3Single; const IsRadius: boolean; const Radius: Single; const OldBox, NewBox: TBox3D; const TrianglesToIgnoreFunc: T3DTriangleIgnoreFunc): boolean; virtual;`
| `function SegmentCollision(const Pos1, Pos2: TVector3Single; const TrianglesToIgnoreFunc: T3DTriangleIgnoreFunc; const ALineOfSight: boolean): boolean; virtual;`
| `function SphereCollision(const Pos: TVector3Single; const Radius: Single; const TrianglesToIgnoreFunc: T3DTriangleIgnoreFunc): boolean; virtual;`
| `function BoxCollision(const Box: TBox3D; const TrianglesToIgnoreFunc: T3DTriangleIgnoreFunc): boolean; virtual;`
| `function RayCollision(const RayOrigin, RayDirection: TVector3Single; const TrianglesToIgnoreFunc: T3DTriangleIgnoreFunc): TRayCollision; virtual;`
| `constructor Create(AOwner: TComponent); override;`
| `destructor Destroy; override;`
| `function GetExists: boolean; virtual;`
| `function GetCollides: boolean; virtual;`
| `function GetPickable: boolean; virtual;`
| `procedure Disable;`
| `procedure Enable;`
| `function BoundingBox: TBox3D; virtual; abstract;`
| `procedure Render(const Frustum: TFrustum; const Params: TRenderParams); virtual;`
| `procedure RenderShadowVolume( ShadowVolumeRenderer: TBaseShadowVolumeRenderer; const ParentTransformIsIdentity: boolean; const ParentTransform: TMatrix4Single); virtual;`
| `procedure PrepareResources( Options: TPrepareResourcesOptions; ProgressStep: boolean; BaseLights: TAbstractLightInstancesList); 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): 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;`
| `function World: T3DWorld; virtual;`
| `procedure VisibleChangeNotification(const Changes: TVisibleChanges); virtual;`
| `procedure GLContextClose; virtual;`
| `procedure UpdateGeneratedTextures( const RenderFunc: TRenderFromViewFunction; const ProjectionNear, ProjectionFar: Single; const OriginalViewport: TRectangle); virtual;`
| `function Dragging: boolean; virtual;`
| `procedure Translate(const T: TVector3Single); virtual;`
| `function Middle: TVector3Single; virtual;`
| `function Sector: TSector;`
| `function Sphere(out Radius: Single): boolean; virtual;`
| `function Height(const MyPosition: TVector3Single; out AboveHeight: Single): boolean;`
| `function Height(const MyPosition: TVector3Single; out AboveHeight: Single; out AboveGround: P3DTriangle): boolean;`
| `function LineOfSight(const Pos1, Pos2: TVector3Single): boolean;`
| `function MoveAllowed(const OldPos, ProposedNewPos: TVector3Single; out NewPos: TVector3Single; const BecauseOfGravity: boolean): boolean;`
| `function MoveAllowed(const OldPos, NewPos: TVector3Single; const BecauseOfGravity: boolean): boolean;`
| `function Move(const Translation: TVector3Single; const BecauseOfGravity: boolean; const EnableWallSliding: boolean = true): boolean;`
| `function Ray(const RayOrigin, RayDirection: TVector3Single): TRayCollision;`
| `function Shared: T3D; virtual;`
### Properties
| `property Exists: boolean read FExists write FExists default true;`
| `property Collides: boolean read FCollides write FCollides default true;`
| `property Pickable: boolean read FPickable write FPickable default true;`
| `property CastShadowVolumes: boolean read FCastShadowVolumes write FCastShadowVolumes default true;`
| `property Parent: T3DList read FParent;`
| `property Cursor: TMouseCursor read FCursor write SetCursor default mcDefault;`
| `property CollidesWithMoving: boolean read FCollidesWithMoving write FCollidesWithMoving default false;`
| `property ExcludeFromGlobalLights: boolean read FExcludeFromGlobalLights write FExcludeFromGlobalLights default false;`
## Description ### Methods
| `procedure CursorChange; virtual;`
In T3D class, just calls Parent.CursorChange.
| `function HeightCollision(const Position, GravityUp: TVector3Single; const TrianglesToIgnoreFunc: T3DTriangleIgnoreFunc; out AboveHeight: Single; out AboveGround: P3DTriangle): boolean; virtual;`
Height of a point above the 3D model. This checks ray collision, from Position 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 P3DTriangle 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 P3DTriangle 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 Position 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: TVector3Single; out NewPos: TVector3Single; const IsRadius: boolean; const Radius: Single; const OldBox, NewBox: TBox3D; const TrianglesToIgnoreFunc: T3DTriangleIgnoreFunc): boolean; virtual;`
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: TVector3Single; const IsRadius: boolean; const Radius: Single; const OldBox, NewBox: TBox3D; const TrianglesToIgnoreFunc: T3DTriangleIgnoreFunc): boolean; virtual;`
| `function SegmentCollision(const Pos1, Pos2: TVector3Single; const TrianglesToIgnoreFunc: T3DTriangleIgnoreFunc; const ALineOfSight: boolean): boolean; virtual;`
| `function SphereCollision(const Pos: TVector3Single; const Radius: Single; const TrianglesToIgnoreFunc: T3DTriangleIgnoreFunc): boolean; virtual;`
| `function BoxCollision(const Box: TBox3D; const TrianglesToIgnoreFunc: T3DTriangleIgnoreFunc): boolean; virtual;`
| `function RayCollision(const RayOrigin, RayDirection: TVector3Single; const TrianglesToIgnoreFunc: T3DTriangleIgnoreFunc): TRayCollision; virtual;`
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 T3DList, this checks collisions for all list items, and chooses the closest one.
| `constructor Create(AOwner: TComponent); override;`
| `destructor Destroy; override;`
| `function GetExists: boolean; virtual;`
Does item really exist, see Exists and Enable, Disable. It T3D 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 T3D 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 T3D class, returns Pickable 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 doesn't want to collide with other creatures, but obviously it doesn't collide with it's own bounding volume).
| `procedure Enable;`
| `function BoundingBox: TBox3D; virtual; abstract;`
Bounding box of the 3D object. Should take into account both collidable and visible objects. For examples, invisible walls (not visible) and fake walls (not collidable) should all be accounted here. As it's a bounding volume, it may naturally be slightly too large (although, for the same of various optimizations, you should try to make it as tight as reasonably possible.) For now, it's also OK to make it a little too small (nothing bad will happen). Although all currently implemented descendants (TCastleSceneCore, TCastlePrecalculatedAnimationCore, more) guarantee it's never too small.
| `procedure Render(const Frustum: TFrustum; const Params: TRenderParams); virtual;`
Render given object. Should check and immediately exit when Exists is `False`. Should render only parts with matching Params.Transparency and Params.ShadowVolumesReceivers values (it may be called more than once to render frame). ###### Parameters Frustum May be used to optimize rendering, to not render the parts outside the Frustum. Params Other parameters helpful for rendering.
| `procedure RenderShadowVolume( ShadowVolumeRenderer: TBaseShadowVolumeRenderer; const ParentTransformIsIdentity: boolean; const ParentTransform: TMatrix4Single); virtual;`
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. T3D objects may be organized in a hierarchy when parent transforms it's children. When ParentTransformIsIdentity, ParentTransform must be IdentityMatrix4Single (it's not guaranteed that when ParentTransformIsIdentity = `True`, Transform value will be ignored !). Implementation note: In Render, it is usually possible to implement ParentTransform* by glPush/PopMatrix and Frustum.Move tricks. But `RenderShadowVolume` needs actual transformation explicitly: ShadowMaybeVisible needs actual box position in world coordinates, so bounding box has to be transformed by ParentTransform. And TCastleScene.RenderShadowVolumeCore needs explicit ParentTransform to correctly detect front/back sides (for silhouette edges and volume capping).
| `procedure PrepareResources( Options: TPrepareResourcesOptions; ProgressStep: boolean; BaseLights: TAbstractLightInstancesList); virtual;`
Prepare resources, making various methods (like rendering and such) to execute fast. This requires OpenGL to be initailized for most 3D objects. If not, some parts of preparations will be aborted. 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 prepared, so a first frame, or a couple of first frames, if it's something like a precalculated animation). 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 T3D, 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. BaseLights Used if Options contains prRender. A list of base lights (always TLightInstancesList, although cannot be declated as such) used for rendering. May be `Nil` (equivalent to empty).
| `function PrepareResourcesSteps: Cardinal; virtual;`
How many times PrepareResources will call Progress.Step. Useful only if you want to pass ProgressStep = `True` to PrepareResources. In the base class T3D this just returns 0.
| `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 Release(const Event: TInputPressRelease): boolean; virtual;`
| `function PointingDeviceActivate(const Active: boolean; const Distance: Single): 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. 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. It can be [], meaning "something else", we'll still broadcast VisibleChangeNotification then. See TVisibleChange docs for possible values. It must specify all things that possibly changed. 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.
| `function World: T3DWorld; virtual;`
World containing this 3D object. In other words, the root of 3D objects tree containing this object. `Nil` if we are not part of a hierarchy rooted in T3DWorld.
| `procedure VisibleChangeNotification(const Changes: TVisibleChanges); virtual;`
Something visible changed in the 3D world. This is usually called by our container (like TCastleSceneManager), to allow this 3D object to react (e.g. by regenerating mirror textures) to changes in the 3D world (not necessarily in this 3D object, maybe in some other T3D instance). If you want to react to visibility changes, you should override this.
| `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).
| `procedure Translate(const T: TVector3Single); virtual;`
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). By default, in T3D class, this does nothing, because the bare T3D class doesn't know how to move itself. But descendants like T3DTransform and T3DOrient (and their descendants like TPlayer, TCreature, TItemOnWorld) override this and can be moved using this.
| `function Middle: TVector3Single; 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 T3DOrient.Position or T3DTransform.Translation can change). In this class this is simply zero. In the descendant T3DCustomTransform (ancestor of T3DTransform, T3DOrient that in turn are ancestors of normal creatures, items etc.) this is overriden to return something sensible above the bottom of the box. See T3DCustomTransform.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 EmptyBox3D). By default, in T3D 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: TVector3Single; out AboveHeight: Single): boolean;`
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: TVector3Single; out AboveHeight: Single; out AboveGround: P3DTriangle): boolean;`
| `function LineOfSight(const Pos1, Pos2: TVector3Single): boolean;`
| `function MoveAllowed(const OldPos, ProposedNewPos: TVector3Single; out NewPos: TVector3Single; const BecauseOfGravity: boolean): boolean;`
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 (see Sphere), then this sphere must be centered around OldPos, not some other point. That is, we assume that Sphere returns Center that is equal to OldPos. 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: TVector3Single; const BecauseOfGravity: boolean): boolean;`
| `function Move(const Translation: TVector3Single; 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 Ray(const RayOrigin, RayDirection: TVector3Single): 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 Shared: T3D; virtual;`
In case this scene shares lights with other scenes, this is the source scene. In usual circumstances, this method simply returns `Self`, which means "no sharing". In case of scenes that are children of TCastlePrecalculatedAnimation, their `Shared` methods all point to the 1st animation scene.
### 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, 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 CastShadowVolumes: boolean read FCastShadowVolumes write FCastShadowVolumes default true;`
Does the 3D object cast shadows by shadow volumes. See also TCastleScene.ReceiveShadowVolumes.
| `property Parent: T3DList read FParent;`
Containing 3D list.
| `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 T3D.Sphere) for checking collisions, or bounding box (T3D.BoundingBox), depending on need. The item is moved using T3D.Translate, so make sure it actually does something (for example, by descending from T3DTransform, that provides natural T3D.Translate implementation).
| `property ExcludeFromGlobalLights: boolean read FExcludeFromGlobalLights write FExcludeFromGlobalLights default false;`
If this 3D object is rendered as part of TCastleSceneManager, and TCastleSceneManager.UseGlobalLights is `True`, then this property allows to make an exception for this 3D object: even though TCastleSceneManager.UseGlobalLights is `True`, do not use global lights for this 3D object. Note that this is not applied recursively. Instead, it is checked at each T3D instance that checks TRenderParams.BaseLights. In practice, it is only checked at TCastleScene, unless you do custom rendering on your own.
Generated by PasDoc 0.13.0 on 2015-06-15 04:43:07