Interpolation in the physical world

I see that various physics engines are wrapped and not used by the engine to their full potential. When experimenting with Box2D - I wrote my own interpolation logic with autoSimulation turned off, but now I’m testing 3d (CannonJS) and even in the physics engine that has interpolation logic under the hood - it is not used because it is wrapped in its own accumulators for calling .step(…) and synchronizes bodies accordingly through position and not interpolatedPosition. And it seems like it will be more difficult to modify without breaking other functionality of the wrapper.

My target devices are weak TVs, so reducing the load by increasing the fixedTimeStep and restoring smoothness by interpolation is mandatory.

Are there any plans to update the approach to using physics engines?

This is working for me so far, but needs more testing. !!! cannon.js !!!

import { _decorator, PhysicsSystem, Component, director, DirectorEvent, Vec3, ERigidBodyType, Quat } from 'cc';
const { ccclass } = _decorator;

@ccclass('PhysicsManager')
export class PhysicsManager extends Component {
    public static instance: PhysicsManager;

    start() {
        PhysicsManager.instance = this;

        const physicsSystem = PhysicsSystem.instance;
        if(physicsSystem.autoSimulation) {
            console.log('[!!!] Disable auto physics simulation in project settings.');
            physicsSystem.autoSimulation = false;
        }
        
        const cannonWorld = physicsSystem.physicsWorld as any;
        cannonWorld._world.addEventListener('preStep', this.preStep.bind(this));
        cannonWorld._world.addEventListener('postStep', this.postStep.bind(this));
    }

    preStep(){
        //console.log('preStep');
        const physicsSystem = PhysicsSystem.instance;
        physicsSystem.physicsWorld.syncSceneToPhysics();
        director.emit(DirectorEvent.BEFORE_PHYSICS);
    }
    postStep(){
        //console.log('postStep');
        const physicsSystem = PhysicsSystem.instance;
        physicsSystem.physicsWorld.emitEvents();
        director.emit(DirectorEvent.AFTER_PHYSICS);
    }

    update (deltaTime: number) {
        const physicsSystem = PhysicsSystem.instance;

        const cannonWorld = physicsSystem.physicsWorld as any;
        cannonWorld._world.step(physicsSystem.fixedTimeStep, deltaTime, physicsSystem.maxSubSteps);
        
        for (let i = 0; i < cannonWorld.bodies.length; i++) {
            const sharedBody = cannonWorld.bodies[i];
            const node = sharedBody.node;
            const body = sharedBody.body;
            if (body.type === ERigidBodyType.DYNAMIC) {
                if (!body.isSleeping()) {
                    Vec3.copy(node.worldPosition, body.interpolatedPosition);
                    node.worldPosition = node.worldPosition;
                    Quat.copy(node.worldRotation, body.interpolatedQuaternion);
                    node.worldRotation = node.worldRotation;
                }
            }
        }
    }
}
import { _decorator, CCFloat, Component, RigidBody, input, KeyCode, Vec3, Input, DirectorEvent, director, PhysicsSystem } from 'cc';
const { ccclass, property } = _decorator;

@ccclass('BallController')
export class BallController extends Component {
    @property(CCFloat)
    speed: number = 10;

    body: RigidBody;

    private pressedKeys: Set<KeyCode> = new Set();

    start() {
        this.body = this.getComponent(RigidBody);
        
    }
    onEnable() {
        input.on(Input.EventType.KEY_DOWN, this.onKeyDown, this);
        input.on(Input.EventType.KEY_UP, this.onKeyUp, this);
        director.on(DirectorEvent.BEFORE_PHYSICS, this.fixedUpdate, this);
    }
    onDisable() {
        input.off(Input.EventType.KEY_DOWN, this.onKeyDown, this);
        input.off(Input.EventType.KEY_UP, this.onKeyUp, this);
        director.off(DirectorEvent.BEFORE_PHYSICS, this.fixedUpdate, this);
    }

    onKeyDown(event: any) {
        this.pressedKeys.add(event.keyCode);
    }

    onKeyUp(event: any) {
        this.pressedKeys.delete(event.keyCode);
    }

    fixedUpdate() {
        //console.log('fixedUpdate');
        const torque = new Vec3(0, 0, 0);
        
        if (this.pressedKeys.has(KeyCode.ARROW_LEFT)) {
            torque.z += 1;
        }
        else if (this.pressedKeys.has(KeyCode.ARROW_RIGHT)) {
            torque.z -= 1;
        }
        if (this.pressedKeys.has(KeyCode.ARROW_UP)) {
            torque.x -= 1;
        }
        else if (this.pressedKeys.has(KeyCode.ARROW_DOWN)) {
            torque.x += 1;
        }
        
        if (torque.x !== 0 || torque.y !== 0 || torque.z !== 0) {
            torque.normalize();
            this.body.applyTorque(torque.multiplyScalar(this.speed));
        }
    }
}