Return all results with physics v2 shape cast (shapeProximity)

Hello,

Is there any way to get all results with a shapeProximity() call?

I tried to hack a function into havokPlugin but it seems that HP_QueryCollector_GetNumHits() always returns 1 hit even if there are multiple shapes in contact.

 havokPlugin['shapeProximityAllResults'] = function (query: IPhysicsShapeProximityCastQuery): Array<ProximityCastResult> {
            const shapeId = query.shape._pluginData;
            const bodyToIgnore = query.ignoreBody ? [BigInt(query.ignoreBody._pluginData.hpBodyId[0])] : [BigInt(0)];

            const hkQuery = [shapeId, this['_bVecToV3'](query.position), this['_bQuatToV4'](query.rotation), query.maxDistance, query.shouldHitTriggers, bodyToIgnore];
            this._hknp.HP_World_ShapeProximityWithCollector(this.world, this['_queryCollector'], hkQuery);
            const res: Array<ProximityCastResult> = [];
            let nbHits = this._hknp.HP_QueryCollector_GetNumHits(this['_queryCollector'])[1];
            for (let i = 0; i < nbHits; i++) {
                const [distance, hitInputData, hitShapeData] = this._hknp.HP_QueryCollector_GetShapeProximityResult(this['_queryCollector'], i)[1];

                const inputShapeResult = new ProximityCastResult();

                this['_populateHitData'](hitShapeData, inputShapeResult);
                inputShapeResult.setHitDistance(distance);

                res.push(inputShapeResult);
            }
            return res;
        }

Source: Babylon.js/packages/dev/core/src/Physics/v2/Plugins/havokPlugin.ts at master · BabylonJS/Babylon.js · GitHub

this._queryCollector = this._hknp.HP_QueryCollector_Create(1)[1];

If you pass a number higher than 1, I believe you can collect more than 1 hit.

Although I like the default value of 1, I’m unsure if there’s an easy way to pass in a different value. Perhaps you can create another QueryCollector with HP_QueryCollector_Create() and pass it into HP_World_ShapeProximityWithCollector().

Collector is cleared with the proximity query:

Which makes sense: A query for proximity shape will only return 1 result: the closest one.

1 Like

Thanks @regna, that did it: I now get multiple results.
It looks like the collector has a limited capacity upon creation.

 havokPlugin['shapeProximityAllResults'] = function (query: IPhysicsShapeProximityCastQuery): Array<ProximityCastResult> {
            const shapeId = query.shape._pluginData;
            const bodyToIgnore = query.ignoreBody ? [BigInt(query.ignoreBody._pluginData.hpBodyId[0])] : [BigInt(0)];

            const queryCollector = this._hknp.HP_QueryCollector_Create(16)[1];
            const hkQuery = [shapeId, this['_bVecToV3'](query.position), this['_bQuatToV4'](query.rotation), query.maxDistance, query.shouldHitTriggers, bodyToIgnore];
            this._hknp.HP_World_ShapeProximityWithCollector(this.world, queryCollector, hkQuery);
            const res: Array<ProximityCastResult> = [];
            let nbHits = this._hknp.HP_QueryCollector_GetNumHits(queryCollector)[1];
            console.log(nbHits);
            for (let i = 0; i < nbHits; i++) {
                const [distance, hitInputData, hitShapeData] = this._hknp.HP_QueryCollector_GetShapeProximityResult(queryCollector, i)[1];

                const inputShapeResult = new ProximityCastResult();

                this['_populateHitData'](hitShapeData, inputShapeResult); //hitInputData does not return the body
                inputShapeResult.setHitDistance(distance);

                res.push(inputShapeResult);
            }
            this._hknp.HP_QueryCollector_Release(queryCollector);
            return res;
        }

@Cedric what doesn’t make sense is that there’s no way to get all results with a raycast/pointProximity/shapeProximity (while the havok engine obviously supports it).
A typical use case is a bomb blast: you want all shapes in proximity, not only the closest one.
Unity, for example, has Physics.RaycastAll() in addition to Physics.Raycast()

1 Like

cc @eoin

1 Like

@SerialF and @regna are both correct here. The collector passed into the query determines maximum amount of hits, and it’s equal to the capacity provided to HP_QueryCollector_Create. In havokPlugin.ts, we explicitly create a collector with a capacity of 1. That’s just a sane default IMO, since most of the time, the closest hit is the most useful. There shouldn’t be any issue exposing a different interface. It’s permitted to create as many collectors as you like (as long as they get released, eventually!)

1 Like