Havok plugin - raycast doesn't update the result if there's no Hit

It’ll only update the result object if there’s more than one hit, so if you re-use your result objects as recommended in the doc and they’ve had a hit already, hasHit will always be true even if there’s no hit.

havokPlugin.js

    raycast(from, to, result) {
        const queryMembership = ~0;
        const queryCollideWith = ~0;
        const query = [this._bVecToV3(from), this._bVecToV3(to), [queryMembership, queryCollideWith]];
        this._hknp.HP_World_CastRayWithCollector(this.world, this._queryCollector, query);
        if (this._hknp.HP_QueryCollector_GetNumHits(this._queryCollector)[1] > 0) {
            const hitData = this._hknp.HP_QueryCollector_GetCastRayResult(this._queryCollector, 0)[1];
            const hitPos = hitData[1][3];
            const hitNormal = hitData[1][4];
            result.setHitData({ x: hitNormal[0], y: hitNormal[1], z: hitNormal[2] }, { x: hitPos[0], y: hitPos[1], z: hitPos[2] });
            result.calculateHitDistance();
            const hitBody = this._bodies.get(hitData[1][0][0]);
            result.body = hitBody === null || hitBody === void 0 ? void 0 : hitBody.body;
            result.bodyIndex = hitBody === null || hitBody === void 0 ? void 0 : hitBody.index;
        }
    }

Indeed! Good catch!. I’m doing a fix.

2 Likes
4 Likes

@Cedric
Additionally, you need to set result._rayFromWorld to the ‘from’ vector, otherwise the distance calculation will be done between (0,0,0) and hitPointWorld.
By setting _rayFromWorld and _rayToWorld before doing the raycast, you’ll still be able to calculate the distance in case of not hitting anything, which might be useful.

3 Likes

I will provide a fix later today.

2 Likes

What I meant was, that as far as I can tell, the _rayFromWorld vector3 of the PhysicsRaycastResult is not set to that of the from vector3 in case of a hit. This results in the distance calculation being incorrect in any case other than a ray being fired from either (0,0,0) - or the last position used when a miss occurred.

A quick fix would be to reset the result in any case, no matter of a hit or not

public raycast(from: Vector3, to: Vector3, result: PhysicsRaycastResult): void {
        const queryMembership = ~0;
        const queryCollideWith = ~0;

        *******result.reset(from, to);********

        const query = [this._bVecToV3(from), this._bVecToV3(to), [queryMembership, queryCollideWith]];
        this._hknp.HP_World_CastRayWithCollector(this.world, this._queryCollector, query);

        if (this._hknp.HP_QueryCollector_GetNumHits(this._queryCollector)[1] > 0) {
            const hitData = this._hknp.HP_QueryCollector_GetCastRayResult(this._queryCollector, 0)[1];

            const hitPos = hitData[1][3];
            const hitNormal = hitData[1][4];
            result.setHitData({ x: hitNormal[0], y: hitNormal[1], z: hitNormal[2] }, { x: hitPos[0], y: hitPos[1], z: hitPos[2] });
            result.calculateHitDistance();
            const hitBody = this._bodies.get(hitData[1][0][0]);
            result.body = hitBody?.body;
            result.bodyIndex = hitBody?.index;
        }
    }
2 Likes