Blitz3D+ Command Reference

PhysicsQueryPlaneOffset# ( query,index )

Parameters

query - owned query handle from CreatePhysicsQuery

index - one-based plane index, up to CountPhysicsQueryHits

Description

Returns the offset of a character query's collision plane.

Returns the native collision-plane offset in metres, relative to movement from the captured capsule origin. The solver constrains Dot(normal, delta) to be at least this offset minus its small linear tolerance. Zero means touching; positive values describe penetration of the capsule radius. This is a movement constraint, not the world-space offset of the surface plane. Read the associated world surface point with PhysicsQueryX/Y/Z.

Character results have PhysicsQueryKind 9. CountPhysicsQueryHits counts copied starting-pose planes, including multiple planes from the same shape. Each hit supplies live body/shape/entity identity, copied tags, a world-space surface point and an outward world normal. It supplies no hit fraction, material, triangle or child metadata. The final cast returns only a movement fraction: it may stop against a new shape absent from the starting planes. Inspect the final pose separately when support classification is needed.

PhysicsQueryFilter and PhysicsQueryTarget apply to both plane gathering and the movement cast. Sensors are excluded by default and disabled bodies are excluded. Planes use deterministic wrapper-shape/geometry ordering. PhysicsQueryLimit defaults to 1024 and can be set up to 65536; all retained and temporary query buffers share a 64 MiB runtime budget. A single native shape producing a full 64-plane batch is conservatively rejected because Box3D may have truncated it. Errors retain the entity position and the entire previous query result.

Results remain available after stepping or entity/body deletion until this query runs successfully again or is freed. Deleted body/shape/entity identities read as zero; copied numerical data and tags remain. Freeing the owning world frees its queries. Getters and clipping require a character result; indices are one-based.

The mover does not simulate a dynamic body, apply gravity, push other bodies, choose a slope limit, climb steps or snap to the ground. Deep overlaps whose capsule centre segment intersects geometry have no useful native plane result; start in a valid pose and use bounded movement. Replay validation covers recorded native operations; wrapper-only entity movement and application support/jump state are not restored by physics replay.

Requires Extended mode.

See also: CreatePhysicsQuery, MovePhysicsCharacter, QueryPhysicsCharacter, ClipPhysicsCharacterVelocity, PhysicsQueryPlanePush, PhysicsQueryFilter.

Example

; PhysicsQueryPlaneOffset Example
; -------------------------------
; Requires Extended mode.

Graphics3D 640,480,0,2
SetBuffer BackBuffer()

Const PHYSICS_STATIC=0
Const PHYSICS_DYNAMIC=2

camera=CreateCamera()
PositionEntity camera,0,5,-10
RotateEntity camera,25,0,0

light=CreateLight()
RotateEntity light,45,-30,0
AmbientLight 60,60,60

; An independent Box3D world with standard gravity
world=CreatePhysicsWorld()

; Blue static floor
ground=CreateCube()
ScaleEntity ground,6,0.5,6
PositionEntity ground,0,-0.5,0
EntityColor ground,80,160,255
ground_body=CreatePhysicsBody(world,ground,PHYSICS_STATIC)
ground_shape=PhysicsBodyBox(ground_body,12,1,12)

; Scenery: a wall, a low step and a ramp
wall=CreateCube()
ScaleEntity wall,0.2,1,2
PositionEntity wall,3,1,0
wall_body=CreatePhysicsBody(world,wall,PHYSICS_STATIC)
wall_shape=PhysicsBodyBox(wall_body,0.4,2,4)
stair=CreateCube()
ScaleEntity stair,1,0.15,1
PositionEntity stair,-2,0.15,2
stair_body=CreatePhysicsBody(world,stair,PHYSICS_STATIC)
stair_shape=PhysicsBodyBox(stair_body,2,0.3,2)
ramp=CreateCube()
ScaleEntity ramp,1.5,0.1,1
RotateEntity ramp,0,0,20
PositionEntity ramp,-2,0.4,-2
ramp_body=CreatePhysicsBody(world,ramp,PHYSICS_STATIC)
ramp_shape=PhysicsBodyBox(ramp_body,3,0.2,2)

; The character is an ordinary entity moved by capsule queries, not a body
character=CreateCylinder(12)
ScaleEntity character,0.3,0.9,0.3
PositionEntity character,0,1,0
EntityColor character,255,230,60
query=CreatePhysicsQuery(world)
vy#=0

While Not KeyDown(1)

    ; A / D / W / S walk, Space jumps when standing on something
    vx#=(KeyDown(32)-KeyDown(30))*3
    vz#=(KeyDown(17)-KeyDown(31))*3
    If KeyHit(57) And Abs(vy)<0.01 Then vy=5
    vy=vy-10.0/60.0

    ; Move a 0.6 m wide, 1.8 m tall capsule; it slides along what it hits
    fraction#=MovePhysicsCharacter(query,character,0.6,1.8,vx/60,vy/60,vz/60)

    ; Remove the part of the velocity that pushes into what it hit,
    ; so landing stops the fall and walls stop the walk
    ClipPhysicsCharacterVelocity query,vx,vy,vz
    vy=PhysicsQueryMoveVelocityY(query)

    StepPhysics world,1.0/60.0,4

    ; Arrow keys move the camera
    If KeyDown(200) Then MoveEntity camera,0,0,0.1
    If KeyDown(208) Then MoveEntity camera,0,0,-0.1
    If KeyDown(203) Then TurnEntity camera,0,1,0
    If KeyDown(205) Then TurnEntity camera,0,-1,0

    RenderWorld

    Text 0,0,"Arrow keys: move camera   A / D / W / S: walk   Space: jump   Esc: exit"

    ; Each hit of a character query is a plane the capsule touched
    For h=1 To CountPhysicsQueryHits(query)
        Text 0,20+(h-1)*20,"Plane "+h+": normal "+PhysicsQueryNX(query,h)+", "+PhysicsQueryNY(query,h)+", "+PhysicsQueryNZ(query,h)+"  offset "+PhysicsQueryPlaneOffset(query,h)+""
    Next

    Flip

Wend

FreePhysicsWorld world
End

Index