import { Nullable , Observable , VideoTexture , Vector2 } from "babylonjs" ; import { DedicatedWorker } from "../shared/dedicatedWorker" ; import { IMAGE_TEMPLATE_TRACKER_URL } from "../shared/constants" ; declare var Module ; declare function postMessage ( data ) ; export class ImageTemplateTracker { private _worker : Worker ; private _tracking : boolean ; private _trackingLoop : Promise < void > ; private _videoTexture : VideoTexture ; public onTrackingUpdatedObservable : Observable < Nullable < Vector2 > > ; private constructor ( videoTexture ) { this . _videoTexture = videoTexture ; this . onTrackingUpdatedObservable = new Observable < Nullable < Vector2 > > ( ) ; } private static onInitialized ( ) { postMessage ( { initialized : true } ) ; } private static onMessage ( event ) { const args = event . data ; if ( args . initialize ) { let buf = Module . _malloc ( args . imageData . length * args . imageData . BYTES_PER_ELEMENT ) ; Module . HEAP8 . set ( args . imageData , buf ) ; Module . _initialize ( args . width , args . height , buf , args . x , args . y ) ; Module . _free ( buf ) ; postMessage ( { initialized : true } ) ; } else if ( args . uninitialize ) { Module . _uninitialize ( ) ; postMessage ( { uninitialized : true } ) ; } else if ( args . track ) { let buf = Module . _malloc ( args . imageData . length * args . imageData . BYTES_PER_ELEMENT ) ; Module . HEAP8 . set ( args . imageData , buf ) ; let tracked = false ; let trackedX = - 1 ; let trackedY = - 1 ; Module . _update_template_position = ( x , y ) => { tracked = true ; trackedX = x ; trackedY = y ; } ; Module . _track_template_in_image ( args . width , args . height , buf ) ; Module . _update_template_position = ( ) => { } ; Module . _free ( buf ) ; postMessage ( { tracked : tracked , x : trackedX , y : trackedY } ) ; } } public static CreateAsync ( videoTexture ) { return new Promise < ImageTemplateTracker > ( ( resolve ) => { let tracker = new ImageTemplateTracker ( videoTexture ) ; tracker . _worker = DedicatedWorker . createFromLocation ( IMAGE_TEMPLATE_TRACKER_URL , ImageTemplateTracker . onInitialized , ImageTemplateTracker . onMessage ) ; tracker . _worker . onmessage = ( event ) => { tracker . _worker . onmessage = DedicatedWorker . unexpectedMessageHandler ; resolve ( tracker ) ; } ; } ) ; } public startTracking ( x , y ) { this . _tracking = true ; this . _trackingLoop = new Promise < void > ( async ( resolve ) => { this . _worker . onmessage = ( ) => { var trackedPosition = Vector2 . Zero ( ) ; var loopFunction = async ( data ) => { if ( data . tracked ) { trackedPosition . set ( data . x , data . y ) ; this . onTrackingUpdatedObservable . notifyObservers ( trackedPosition ) ; } else { this . onTrackingUpdatedObservable . notifyObservers ( null ) ; } if ( this . _tracking ) { this . _worker . postMessage ( { track : true , width : this . _videoTexture . getSize ( ) . width , height : this . _videoTexture . getSize ( ) . height , imageData : await this . _videoTexture . readPixels ( ) } ) ; } else { this . _worker . onmessage = ( ) => { this . _worker . onmessage = DedicatedWorker . unexpectedMessageHandler ; resolve ( ) ; } ; this . _worker . postMessage ( { uninitialize : true } ) ; } } ; this . _worker . onmessage = ( result ) => { loopFunction ( result . data ) ; } ; loopFunction ( { tracked : false , x : - 1 , y : - 1 } ) ; } ; this . _worker . postMessage ( { initialize : true , x : x , y : y , width : this . _videoTexture . getSize ( ) . width , height : this . _videoTexture . getSize ( ) . height , imageData : await this . _videoTexture . readPixels ( ) } ) ; } ) ; } public stopTrackingAsync ( ) { this . _tracking = false ; return this . _trackingLoop ; } }