SceneObject
Properties
name(string)id(string) — Unique IdclusterMemberCount(integer) — How many members are in this object's overlap cluster this frame (seedrawable(Drawable)type(SceneObjectType)negDistanceFromCamera(float) — The negative distance from the camera, used for depth sorting. Measured fromworldPosition(dynamic)depthPosition(dynamic) — This object's position as used for depth classification (BGE.BSP's dynamic-itemtransformationMatrix(dynamic) — The Current Transformation MatrixlastFrameWasCulled(boolean) — Whether the last frame's draw was skipped because the frustum rejected this object,lastFrameDidDraw(boolean) — Whether the last frame's draw actually happened. Distinct from lastFrameWasCulledhasValidWorldPosition(boolean)hasValidCanvasPosition(boolean)wasEnabledLastFrame(boolean)isFirstFrameSinceEnabled(boolean)isLowEndDevice(boolean)lastGeometryVersion(integer) — The drawable'sgeometryVersionas of the last completed draw - see geometryChanged()lastQualityVersion(integer) — The renderer'squalityVersionas of the last drawqualityChangedThisDraw(boolean) — True during a draw whose renderer quality settings changed since this object'slastDrawMode(integer) — The draw mode this object last drew in - see drawModeChanged()lastProjectionVersion(integer) — The camera'sprojectionVersionas of the last draw - see projectionChanged()depthChangedThisFrame(boolean) — True for exactly the frame this object's negDistanceFromCamera was recomputed -stableSortKey(float) — What Renderer actually sorts by - negDistanceFromCamera quantized intoisStatic(boolean) — Set by Renderer when this object's owning entity is marked GameEntity.isStatic andstaticGeometryMovedThisFrame(boolean) — True for exactly the frame Renderer.updateSceneObjects() should mark the staticstaticCheckArmed(boolean) — Whether update() has completed at least one prior frame for this object - guardsstaticWarningLogged(boolean) — Whether the one-time misuse warning has already been logged for this object -staticDrawModeWarningLogged(boolean) — Whether the one-time "static but not in an oriented draw mode" warning haswasStaticEnabledState(boolean) — This object's isEnabled() as of the last checkStaticEnabledStateChanged() call -
Constructor
new SceneObject(
name: string,
drawableObj: Drawable,
objType: SceneObjectType,
): SceneObjectParameters
name(string)drawableObj(Drawable)objType(SceneObjectType)
Instance Methods
setId(id: string): void
Parameters
id(string)
Returns
void
setLastSortIndex(index: integer): void
Parameters
index(integer)
Returns
void
getLastSortIndex(): integer
Returns
integer
update(cameraObj: Camera): void
Update the scene object for the current frame. Updates the world position and checks if the object should be drawn. Updates negDistanceFromCamera for depth sorting. Do not override this function.
Parameters
cameraObj(Camera)
Returns
void
getDepthPosition(): BGE.Math.Vector
This object's cached depth-classification position - see depthPosition's own doc comment. Exposed for Renderer's static-geometry BSP path (drawStaticAndDynamicSceneObjects()), which needs the same anchor point used for depth sorting, not the raw worldPosition.
Returns
BGE.Math.Vector
getPositionForCameraDistance(
drawMode: SceneObjectDrawMode,
): BGE.Math.Vector
Get the position of the object for the camera distance calculation Override this function in subclasses to provide specific behavior
Parameters
drawMode(SceneObjectDrawMode) — Current draw mode
Returns
BGE.Math.Vector
isEnabled(): boolean
Check if the object is enabled
Returns
boolean— true if this sceneObject should be drawn or updated
updateWorldPosition(drawMode: SceneObjectDrawMode): boolean
Parameters
drawMode(SceneObjectDrawMode)
Returns
boolean
draw(rendererObj: Renderer): void
Draw the object with the current renderer Calculates if the object is on screen and if it should be drawn. Do not override this function!
Parameters
rendererObj(Renderer)
Returns
void
drawModeChanged(drawMode: SceneObjectDrawMode): boolean
Parameters
drawMode(SceneObjectDrawMode)
Returns
boolean
geometryChanged(): boolean
Returns
boolean
projectionChanged(cameraObj: Camera): boolean
Parameters
cameraObj(Camera)
Returns
boolean
findCanvasPosition(
rendererObj: Renderer,
drawMode: SceneObjectDrawMode,
): boolean
Parameters
rendererObj(Renderer)drawMode(SceneObjectDrawMode)
Returns
boolean
performDraw(
rendererObj: Renderer,
drawMode: SceneObjectDrawMode,
): boolean
Parameters
rendererObj(Renderer)drawMode(SceneObjectDrawMode)
Returns
boolean
getPrimitiveCount(): integer
How many separately-orderable draw primitives this object currently has. The base-class default (1) is correct for every billboard-family SceneObject - a quad/circle/text/etc. is always drawn as one piece regardless of draw mode. SceneObjectModel overrides this to return its actual per-face count, which does vary with draw mode (backface-culled modes only count front-facing faces; the DrawBackFace variants count both).
Returns
integer
getPrimitiveDepth(index: integer): float
The depth to sort primitive index by, within a multi-member cluster's combined primitive list. The base-class default (this object's own overall depth) is correct for the single-primitive case.
Contract: the returned value must be on the same convention as negDistanceFromCamera - negative in front of the camera, and ascending sort = farthest-first (matching the main scene's own painter's-algorithm sort convention). Every override (e.g. SceneObjectModel's per-face depth) must convert to this same convention, or primitives from different SceneObject subtypes will sort against each other backwards within a shared cluster.
Parameters
index(integer)
Returns
float
drawPrimitive(rendererObj: Renderer, index: integer): boolean
Draws primitive index now. The base-class default delegates to this object's normal whole-object draw path (performDraw, with its normal caching behavior intact) - correct for the single-primitive case, where "draw primitive 0" and "draw the whole object" are the same operation. SceneObjectModel overrides this to draw one face directly (bypassing its whole-model temp-bitmap cache, which can't represent cross-object interleaving).
Parameters
rendererObj(Renderer)index(integer)
Returns
boolean— whether this primitive actually drew something
afterDraw(): void
Returns
void
objMovedInRelationToCamera(cameraObj: Camera): boolean
Parameters
cameraObj(Camera)
Returns
boolean
isPotentiallyOnScreen(cameraObj: Camera): boolean
Parameters
cameraObj(Camera)
Returns
boolean
getPositionsForFrustumCheck(
drawMode: SceneObjectDrawMode,
): Array.<BGE.Math.Vector>
Parameters
drawMode(SceneObjectDrawMode)
Returns
Array.<BGE.Math.Vector>
getBoundingPoints(cameraObj: Camera): Array.<BGE.Math.Vector>
Public wrapper around getPositionsForFrustumCheck(), for cross-object callers (e.g. BGE.DepthSort's overlap detection) that need this object's own bounding points but aren't a SceneObject subclass themselves.
Parameters
cameraObj(Camera)
Returns
Array.<BGE.Math.Vector>
participatesInOverlapDetection(): boolean
Whether this object is worth including in overlap-cluster detection (BGE.DepthSort/Renderer.getOverlapClusters()) at all. The base-class default (true) is correct for anything with real area/volume, which the narrow phase (BGE.DepthSort.hullsOverlap) can actually test via a >=3-point convex hull. SceneObjectLine overrides this to false: a line's own bounding points (getPositionsForFrustumCheck) are always exactly 2 (its two endpoints), so its projected hull can never reach MIN_VALID_HULL_POINTS - hullsOverlap() already rejects it via isValidHull() unconditionally, meaning a line could never actually be unioned into a real cluster with anything, before or after this method existed. This isn't tolerating a small visual error - the scenario ("two lines clustered in the wrong order") is structurally impossible under the current hull-based narrow phase. What this method actually buys is skipping the broad-phase setup cost (screen-bounds projection, hull construction, sort/sweep entries) for objects that were always going to fail the narrow phase anyway - this matters in practice for a scene built from many line segments (e.g. examples/3d's TreesScene, each tree a bundle of DrawableLine branches), which would otherwise dominate the cluster-candidate count for zero possible benefit.
A static object (isStatic - see GameEntity.isStatic/Renderer.markStatic()) also returns false here regardless of type: the static geometry BSP tree already gives it correct draw order against every dynamic object, so clustering it too would be redundant at best - and at worst, a cluster with clusterMemberCount > 1 defers the object to Renderer.drawPendingClusterPrimitives(), which runs after the entire BSP pass and would silently discard that ordering for it.
Returns
boolean
isEligibleForStaticBsp(): boolean
Whether this concrete SceneObject type's geometry can be represented as a single flat quad usable by the static geometry BSP tree (see BGE.BSP and Renderer.buildStaticGeometryTree()). False by default - override true only for a type whose getWorldPoints() exactly matches its drawn fill geometry (currently SceneObjectImage and SceneObjectRectangle; not SceneObjectModel/SceneObjectCircle/ SceneObjectPolygon/SceneObjectText, whose world corners are a bounding proxy, not their actual silhouette).
Returns
boolean
isReadyForStaticBspBuild(cam: Camera): boolean
Whether this object should actually be included in this build of the static geometry BSP tree (see Renderer.buildStaticGeometryTree()) - combines isEligibleForStaticBsp() (concrete type support) with a runtime check that the object is actually in a draw mode that can define a plane. A static entity left in a screen-aligned draw mode (matchCamera/directToCamera/directScaled - see isScreenAlignedDrawMode()) never populates worldPoints (see SceneObjectBillboard.updateWorldPosition()'s screen-aligned branch), so getWorldPoints() would still be the constructor's all-zero CornerPoints - building a plane from that classifies every dynamic object to the same side, silently collapsing draw order. Note this is NOT simply "not isOrientedDrawMode()" - isOrientedDrawMode() is defined as not isDirectDrawMode(), which incorrectly counts directScaled as oriented even though it's screen-aligned and just as incapable of populating worldPoints as matchCamera/directToCamera (see isScreenAlignedDrawMode()'s own doc comment). Warns once (matching the staticWarningLogged misuse-detection pattern) and returns false instead, so the tree itself excludes this object - but it is NOT dropped: Renderer. drawStaticAndDynamicSceneObjects() still classifies it every frame as a dynamic item against the tree's real planes (e.g. a screen-aligned tree billboard ordered correctly against a real static wall), same as a genuinely moving object.
Parameters
cam(Camera)
Returns
boolean
checkStaticEnabledStateChanged(): boolean
Detects a static object's enabled/disabled transition even on a frame update() itself never runs (a disabled object never reaches update() - see Renderer.updateSceneObjects()). Called once per frame for every SceneObject (cheap; a no-op state update for a non-static object) so Renderer can mark the static geometry tree dirty exactly once per transition, in either direction, instead of drawing a disabled object from a stale tree or never re-drawing one that was disabled when the tree was last built.
Returns
boolean— true exactly on the frame this object's (isStatic and) enabled state changed since the last call
getWorldPoints(): BGE.Math.CornerPoints
This object's world-space quad corners, if it has any - invalid for a type that isn't built from a single flat quad. Overridden on SceneObjectBillboard (the shared base for every quad-shaped SceneObject) to return its computed worldPoints.
Returns
BGE.Math.CornerPoints
isDeterministicDrawFailure(
rendererObj: Renderer,
drawMode: SceneObjectDrawMode,
): boolean
Parameters
rendererObj(Renderer)drawMode(SceneObjectDrawMode)
Returns
boolean
isCulled(): boolean
Whether this object was culled (skipped entirely) on the last frame drawn - either by the camera frustum, or by a deterministic draw failure (see isDeterministicDrawFailure()) that's being treated the same way. Game code can use this (e.g. via GameEntity.isOnScreen()/Drawable.isOnScreen()) to skip its own expensive per-frame work for an entity that isn't currently visible - see issue #75.
Returns
boolean