Blitz3D+ Command Reference

QueryPhysicsShapeDistance ( query,shape_a,shape_b )

Parameters

query - owned query handle

shape_a - shape handle

shape_b - shape handle

Description

Measures the distance between the surfaces of two convex shapes.

Computes the non-negative surface separation of two supported convex shapes, in metres, and returns 2. Stores a kind-6 snapshot with hit 1 belonging to shape_a and hit 2 to shape_b, preserving caller order even for the same shape. Both radii are included. PhysicsQueryDistance reads the copied separation. At positive distance, each entry has its own world-space closest witness point and the same unit normal pointing from A toward B. At zero distance (touching/overlapping), neither entry exposes point/normal fields: the native distance solver does not supply penetration witnesses, depth or a contact manifold. Use PhysicsQueryHasPoint/HasNormal before reading geometry. There is no fraction or material metadata.

PhysicsQueryLimit must be at least 2. Allocation/limit failure preserves the prior snapshot and distance. These are direct measurements of explicitly supplied geometry, so PhysicsQueryFilter and PhysicsQueryTarget settings, sensors, collision rules and disabled-body broadphase membership do not exclude the requested objects. All supplied objects must belong to the query world. Geometry uses the current native body pose and authored local offsets; visual mesh edits do not recook it. Supported proximity geometry is sphere, capsule and convex hull/box. Mesh, terrain and compound shapes are rejected before native proxy construction; body queries reject a body containing any unsupported shape.

Results are copied and survive StepPhysics, other queries and deletion of referenced objects until this query runs successfully again or is freed. Live identity getters return zero for deleted objects while tags, available geometry and distance remain readable. A failed operation preserves the entire previous snapshot. Freeing the world frees its queries. Invalid handles, indices or unavailable fields raise runtime errors.

Requires Extended mode.

See also: CreatePhysicsQuery, QueryPhysicsBodyClosestPoint, PhysicsQueryDistance, PhysicsQueryHasPoint.

Example

; QueryPhysicsShapeDistance Example
; ---------------------------------
; Requires Extended mode.

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

Const PHYSICS_STATIC=0
Const PHYSICS_DYNAMIC=2

camera=CreateCamera()
PositionEntity camera,0,7,-8
RotateEntity camera,40,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)

; Crates scattered over the floor
Dim crates(9)
Dim crate_bodies(9)
For i=0 To 9
    crates(i)=CreateCube()
    ScaleEntity crates(i),0.4,0.4,0.4
    PositionEntity crates(i),Rnd(-4,4),0.4,Rnd(-4,4)
    crate_bodies(i)=CreatePhysicsBody(world,crates(i),PHYSICS_DYNAMIC)
    crate_shape=PhysicsBodyBox(crate_bodies(i),0.8,0.8,0.8)
Next

; A query object runs searches and keeps a copy of their results
; It ignores the floor body, so only crates are found
query=CreatePhysicsQuery(world)
PhysicsQueryFilter query,-1,-1,ground_body

; A see-through yellow probe shows the search volume
; The probe is a kinematic body whose own shape does the searching
probe=CreateSphere(16)
PositionEntity probe,0,0.5,0
probe_body=CreatePhysicsBody(world,probe,1)
probe_shape=PhysicsBodySphere(probe_body,2)

; Mask 0: the probe collides with nothing, so it never pushes the crates
PhysicsShapeFilter probe_shape,1,0
EntityColor probe,255,230,60
EntityAlpha probe,0.4

While Not KeyDown(1)

    ; A, D, W and S move the probe over the floor
    If KeyDown(30) Then MoveEntity probe,-0.05,0,0
    If KeyDown(32) Then MoveEntity probe,0.05,0,0
    If KeyDown(17) Then MoveEntity probe,0,0,0.05
    If KeyDown(31) Then MoveEntity probe,0,0,-0.05
    px#=EntityX(probe)
    pz#=EntityZ(probe)

    StepPhysics world,1.0/60.0,4

    ; Measure the gap between the probe's sphere and crate 0's box
    hits=QueryPhysicsShapeDistance(query,probe_shape,PhysicsBodyShape(crate_bodies(0),1))

    ; Crates found by the search turn yellow
    For i=0 To 9
        EntityColor crates(i),255,120,70
    Next
    For h=1 To hits
        found=PhysicsQueryEntity(query,h)
        If found<>ground Then EntityColor found,255,230,60
    Next

    ; 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

    ; Draw the shortest gap between the two shapes
    If PhysicsQueryDistance(query)>0
        CameraProject camera,PhysicsQueryX(query,1),PhysicsQueryY(query,1),PhysicsQueryZ(query,1)
        gap_x=ProjectedX()
        gap_y=ProjectedY()
        CameraProject camera,PhysicsQueryX(query,2),PhysicsQueryY(query,2),PhysicsQueryZ(query,2)
        Line gap_x,gap_y,ProjectedX(),ProjectedY()
    EndIf

    Text 0,0,"Arrow keys: move camera   A / D / W / S: move the probe   Esc: exit"
    Text 0,20,"Gap between the probe and crate 0: "+PhysicsQueryDistance(query)+" m"

    Flip

Wend

FreePhysicsWorld world
End

Index