UNPKG

@webarkit/nft-marker-creator-app

Version:

NFt Marker Creator based on WebARKitLib, ported thanks to Emscripten

1,702 lines 6.12 MB
var Module = typeof Module !== "undefined" ? Module : {}; (function () { "use strict"; var scope; if (typeof window !== "undefined") { scope = window; } else { scope = self; } if (scope.artoolkit_wasm_url) { var downloadWasm = function (url) { return new Promise(function (resolve, reject) { var wasmXHR = new XMLHttpRequest(); wasmXHR.open("GET", url, true); wasmXHR.responseType = "arraybuffer"; wasmXHR.onload = function () { resolve(wasmXHR.response); }; wasmXHR.onerror = function () { reject("error " + wasmXHR.status); }; wasmXHR.send(null); }); }; var wasm = downloadWasm(scope.artoolkit_wasm_url); Module.instantiateWasm = function (imports, successCallback) { console.log("instantiateWasm: instantiating synchronously"); wasm.then(function (wasmBinary) { console.log("wasm download finished, begin instantiating"); var wasmInstantiate = WebAssembly.instantiate( new Uint8Array(wasmBinary), imports ) .then(function (output) { console.log("wasm instantiation succeeded"); successCallback(output.instance); }) .catch(function (e) { console.log("wasm instantiation failed! " + e); }); }); return {}; }; } var ARController = function (width, height, cameraPara) { this.id = undefined; var w = width, h = height; this.orientation = "landscape"; this.listeners = {}; if (typeof width !== "number") { var image = width; cameraPara = height; w = image.videoWidth || image.width; h = image.videoHeight || image.height; this.image = image; } this.width = w; this.height = h; this.nftMarkerCount = 0; this.defaultMarkerWidth = 1; this.patternMarkers = {}; this.barcodeMarkers = {}; this.nftMarkers = {}; this.transform_mat = new Float32Array(16); this.transformGL_RH = new Float64Array(16); if (typeof document !== "undefined") { this.canvas = document.createElement("canvas"); this.canvas.width = w; this.canvas.height = h; this.ctx = this.canvas.getContext("2d"); } this.videoWidth = w; this.videoHeight = h; this.videoSize = this.videoWidth * this.videoHeight; this.framepointer = null; this.framesize = null; this.dataHeap = null; this.videoLuma = null; this.camera_mat = null; this.marker_transform_mat = null; this.videoLumaPointer = null; this._bwpointer = undefined; this._lumaCtx = undefined; if (typeof cameraPara === "string") { this.cameraParam = new ARCameraParam( cameraPara, function () { this._initialize(); }.bind(this), function (err) { console.error("ARController: Failed to load ARCameraParam", err); this.onload(err); }.bind(this) ); } else { this.cameraParam = cameraPara; this._initialize(); } }; ARController.prototype.dispose = function () { if (this.id > -1) { artoolkit.teardown(this.id); } if (this.image && this.image.srcObject) { ARController._teardownVideo(this.image); } for (var t in this) { this[t] = null; } }; ARController.prototype.process = function (image) { var result = this.detectMarker(image); if (result != 0) { console.error("detectMarker error: " + result); } var markerNum = this.getMarkerNum(); var k, o; for (k in this.patternMarkers) { o = this.patternMarkers[k]; o.inPrevious = o.inCurrent; o.inCurrent = false; } for (k in this.barcodeMarkers) { o = this.barcodeMarkers[k]; o.inPrevious = o.inCurrent; o.inCurrent = false; } for (k in this.nftMarkers) { o = this.nftMarkers[k]; o.inPrevious = o.inCurrent; o.inCurrent = false; } for (var i = 0; i < markerNum; i++) { var markerInfo = this.getMarker(i); var markerType = artoolkit.UNKNOWN_MARKER; var visible = this.trackPatternMarkerId(-1); if ( markerInfo.idPatt > -1 && (markerInfo.id === markerInfo.idPatt || markerInfo.idMatrix === -1) ) { visible = this.trackPatternMarkerId(markerInfo.idPatt); markerType = artoolkit.PATTERN_MARKER; if (markerInfo.dir !== markerInfo.dirPatt) { this.setMarkerInfoDir(i, markerInfo.dirPatt); } } else if (markerInfo.idMatrix > -1) { visible = this.trackBarcodeMarkerId(markerInfo.idMatrix); markerType = artoolkit.BARCODE_MARKER; if (markerInfo.dir !== markerInfo.dirMatrix) { this.setMarkerInfoDir(i, markerInfo.dirMatrix); } } if (markerType !== artoolkit.UNKNOWN_MARKER && visible.inPrevious) { this.getTransMatSquareCont( i, visible.markerWidth, visible.matrix, visible.matrix ); } else { this.getTransMatSquare(i, visible.markerWidth, visible.matrix); } visible.inCurrent = true; this.transMatToGLMat(visible.matrix, this.transform_mat); this.transformGL_RH = this.arglCameraViewRHf(this.transform_mat); this.dispatchEvent({ name: "getMarker", target: this, data: { index: i, type: markerType, marker: markerInfo, matrix: this.transform_mat, matrixGL_RH: this.transformGL_RH, }, }); } var nftMarkerCount = this.nftMarkerCount; this.detectNFTMarker(); var MARKER_LOST_TIME = 200; for (var i = 0; i < nftMarkerCount; i++) { var nftMarkerInfo = this.getNFTMarker(i); var markerType = artoolkit.NFT_MARKER; if (nftMarkerInfo.found) { self.markerFound = i; self.markerFoundTime = Date.now(); var visible = this.trackNFTMarkerId(i); visible.matrix.set(nftMarkerInfo.pose); visible.inCurrent = true; this.transMatToGLMat(visible.matrix, this.transform_mat); this.transformGL_RH = this.arglCameraViewRHf(this.transform_mat); this.dispatchEvent({ name: "getNFTMarker", target: this, data: { index: i, type: markerType, marker: nftMarkerInfo, matrix: this.transform_mat, matrixGL_RH: this.transformGL_RH, }, }); } else if (self.markerFound === i) { if (Date.now() - self.markerFoundTime <= MARKER_LOST_TIME) { return; } delete self.markerFound; this.dispatchEvent({ name: "lostNFTMarker", target: this, data: { index: i, type: markerType, marker: nftMarkerInfo, matrix: this.transform_mat, matrixGL_RH: this.transformGL_RH, }, }); } } var multiMarkerCount = this.getMultiMarkerCount(); for (var i = 0; i < multiMarkerCount; i++) { var subMarkerCount = this.getMultiMarkerPatternCount(i); var visible = false; artoolkit.getTransMatMultiSquareRobust(this.id, i); this.transMatToGLMat(this.marker_transform_mat, this.transform_mat); this.transformGL_RH = this.arglCameraViewRHf(this.transform_mat); for (var j = 0; j < subMarkerCount; j++) { var multiEachMarkerInfo = this.getMultiEachMarker(i, j); if (multiEachMarkerInfo.visible >= 0) { visible = true; this.dispatchEvent({ name: "getMultiMarker", target: this, data: { multiMarkerId: i, matrix: this.transform_mat, matrixGL_RH: this.transformGL_RH, }, }); break; } } if (visible) { for (var j = 0; j < subMarkerCount; j++) { var multiEachMarkerInfo = this.getMultiEachMarker(i, j); this.transMatToGLMat(this.marker_transform_mat, this.transform_mat); this.transformGL_RH = this.arglCameraViewRHf(this.transform_mat); this.dispatchEvent({ name: "getMultiMarkerSub", target: this, data: { multiMarkerId: i, markerIndex: j, marker: multiEachMarkerInfo, matrix: this.transform_mat, matrixGL_RH: this.transformGL_RH, }, }); } } } if (this._bwpointer) { this.debugDraw(); } }; ARController.prototype.detectNFTMarker = function () { artoolkit.detectNFTMarker(this.id); }; ARController.prototype.trackPatternMarkerId = function (id, markerWidth) { var obj = this.patternMarkers[id]; if (!obj) { this.patternMarkers[id] = obj = { inPrevious: false, inCurrent: false, matrix: new Float64Array(12), matrixGL_RH: new Float64Array(12), markerWidth: markerWidth || this.defaultMarkerWidth, }; } if (markerWidth) { obj.markerWidth = markerWidth; } return obj; }; ARController.prototype.trackBarcodeMarkerId = function (id, markerWidth) { var obj = this.barcodeMarkers[id]; if (!obj) { this.barcodeMarkers[id] = obj = { inPrevious: false, inCurrent: false, matrix: new Float64Array(12), matrixGL_RH: new Float64Array(12), markerWidth: markerWidth || this.defaultMarkerWidth, }; } if (markerWidth) { obj.markerWidth = markerWidth; } return obj; }; ARController.prototype.trackNFTMarkerId = function (id, markerWidth) { var obj = this.nftMarkers[id]; if (!obj) { this.nftMarkers[id] = obj = { inPrevious: false, inCurrent: false, matrix: new Float64Array(12), matrixGL_RH: new Float64Array(12), markerWidth: markerWidth || this.defaultMarkerWidth, }; } if (markerWidth) { obj.markerWidth = markerWidth; } return obj; }; ARController.prototype.getMultiMarkerCount = function () { return artoolkit.getMultiMarkerCount(this.id); }; ARController.prototype.getMultiMarkerPatternCount = function (multiMarkerId) { return artoolkit.getMultiMarkerNum(this.id, multiMarkerId); }; ARController.prototype.addEventListener = function (name, callback) { if (!this.listeners[name]) { this.listeners[name] = []; } this.listeners[name].push(callback); }; ARController.prototype.removeEventListener = function (name, callback) { if (this.listeners[name]) { var index = this.listeners[name].indexOf(callback); if (index > -1) { this.listeners[name].splice(index, 1); } } }; ARController.prototype.dispatchEvent = function (event) { var listeners = this.listeners[event.name]; if (listeners) { for (var i = 0; i < listeners.length; i++) { listeners[i].call(this, event); } } }; ARController.prototype.debugSetup = function () { document.body.appendChild(this.canvas); var lumaCanvas = document.createElement("canvas"); lumaCanvas.width = this.canvas.width; lumaCanvas.height = this.canvas.height; this._lumaCtx = lumaCanvas.getContext("2d"); document.body.appendChild(lumaCanvas); this.setDebugMode(true); this._bwpointer = this.getProcessingImage(); }; ARController.prototype.loadMarker = function (markerURL, onSuccess, onError) { if (markerURL) { artoolkit.addMarker(this.id, markerURL, onSuccess, onError); } else { if (onError) { onError("Marker URL needs to be defined and not equal empty string!"); } else { console.error( "Marker URL needs to be defined and not equal empty string!" ); } } }; ARController.prototype.loadNFTMarker = function ( markerURL, onSuccess, onError ) { var self = this; if (markerURL) { return artoolkit.addNFTMarker( this.id, markerURL, function (id) { self.nftMarkerCount = id + 1; onSuccess(id); }, onError ); } else { if (onError) { onError("Marker URL needs to be defined and not equal empty string!"); } else { console.error( "Marker URL needs to be defined and not equal empty string!" ); } } }; ARController.prototype.loadMultiMarker = function ( markerURL, onSuccess, onError ) { return artoolkit.addMultiMarker(this.id, markerURL, onSuccess, onError); }; ARController.prototype.getTransMatSquare = function ( markerUID, markerWidth, dst ) { artoolkit.getTransMatSquare(this.id, markerUID, markerWidth); dst.set(this.marker_transform_mat); return dst; }; ARController.prototype.getTransMatSquareCont = function ( markerUID, markerWidth, previousMarkerTransform, dst ) { this.marker_transform_mat.set(previousMarkerTransform); artoolkit.getTransMatSquareCont(this.id, markerUID, markerWidth); dst.set(this.marker_transform_mat); return dst; }; ARController.prototype.getTransMatMultiSquare = function (markerUID, dst) { artoolkit.getTransMatMultiSquare(this.id, markerUID); dst.set(this.marker_transform_mat); return dst; }; ARController.prototype.getTransMatMultiSquareRobust = function ( markerUID, dst ) { artoolkit.getTransMatMultiSquare(this.id, markerUID); dst.set(this.marker_transform_mat); return dst; }; ARController.prototype.transMatToGLMat = function (transMat, glMat, scale) { if (glMat == undefined) { glMat = new Float64Array(16); } glMat[0 + 0 * 4] = transMat[0]; glMat[0 + 1 * 4] = transMat[1]; glMat[0 + 2 * 4] = transMat[2]; glMat[0 + 3 * 4] = transMat[3]; glMat[1 + 0 * 4] = transMat[4]; glMat[1 + 1 * 4] = transMat[5]; glMat[1 + 2 * 4] = transMat[6]; glMat[1 + 3 * 4] = transMat[7]; glMat[2 + 0 * 4] = transMat[8]; glMat[2 + 1 * 4] = transMat[9]; glMat[2 + 2 * 4] = transMat[10]; glMat[2 + 3 * 4] = transMat[11]; glMat[3 + 0 * 4] = 0; glMat[3 + 1 * 4] = 0; glMat[3 + 2 * 4] = 0; glMat[3 + 3 * 4] = 1; if (scale != undefined && scale !== 0) { glMat[12] *= scale; glMat[13] *= scale; glMat[14] *= scale; } return glMat; }; ARController.prototype.arglCameraViewRHf = function ( glMatrix, glRhMatrix, scale ) { var m_modelview; if (glRhMatrix == undefined) m_modelview = new Float64Array(16); else m_modelview = glRhMatrix; m_modelview[0] = glMatrix[0]; m_modelview[4] = glMatrix[4]; m_modelview[8] = glMatrix[8]; m_modelview[12] = glMatrix[12]; m_modelview[1] = -glMatrix[1]; m_modelview[5] = -glMatrix[5]; m_modelview[9] = -glMatrix[9]; m_modelview[13] = -glMatrix[13]; m_modelview[2] = -glMatrix[2]; m_modelview[6] = -glMatrix[6]; m_modelview[10] = -glMatrix[10]; m_modelview[14] = -glMatrix[14]; m_modelview[3] = 0; m_modelview[7] = 0; m_modelview[11] = 0; m_modelview[15] = 1; if (scale != undefined && scale !== 0) { m_modelview[12] *= scale; m_modelview[13] *= scale; m_modelview[14] *= scale; } glRhMatrix = m_modelview; return glRhMatrix; }; ARController.prototype.detectMarker = function (image) { if (this._copyImageToHeap(image)) { return artoolkit.detectMarker(this.id); } return -99; }; ARController.prototype.getMarkerNum = function () { return artoolkit.getMarkerNum(this.id); }; ARController.prototype.getMarker = function (markerIndex) { if (0 === artoolkit.getMarker(this.id, markerIndex)) { return artoolkit.markerInfo; } }; ARController.prototype.getNFTMarker = function (markerIndex) { if (0 === artoolkit.getNFTMarker(this.id, markerIndex)) { return artoolkit.NFTMarkerInfo; } }; ARController.prototype.setMarkerInfoVertex = function ( markerIndex, vertexData ) { for (var i = 0; i < vertexData.length; i++) { this.marker_transform_mat[i * 2 + 0] = vertexData[i][0]; this.marker_transform_mat[i * 2 + 1] = vertexData[i][1]; } return artoolkit.setMarkerInfoVertex(this.id, markerIndex); }; ARController.prototype.cloneMarkerInfo = function (markerInfo) { return JSON.parse(JSON.stringify(markerInfo)); }; ARController.prototype.getMultiEachMarker = function ( multiMarkerId, markerIndex ) { if ( 0 === artoolkit.getMultiEachMarker(this.id, multiMarkerId, markerIndex) ) { return artoolkit.multiEachMarkerInfo; } }; ARController.prototype.getTransformationMatrix = function () { return this.transform_mat; }; ARController.prototype.getCameraMatrix = function () { return this.camera_mat; }; ARController.prototype.getMarkerTransformationMatrix = function () { return this.marker_transform_mat; }; ARController.prototype.setDebugMode = function (mode) { return artoolkit.setDebugMode(this.id, mode); }; ARController.prototype.getDebugMode = function () { return artoolkit.getDebugMode(this.id); }; ARController.prototype.getProcessingImage = function () { return artoolkit.getProcessingImage(this.id); }; ARController.prototype.setLogLevel = function (mode) { return artoolkit.setLogLevel(mode); }; ARController.prototype.getLogLevel = function () { return artoolkit.getLogLevel(); }; ARController.prototype.setMarkerInfoDir = function (markerIndex, dir) { return artoolkit.setMarkerInfoDir(this.id, markerIndex, dir); }; ARController.prototype.setProjectionNearPlane = function (value) { return artoolkit.setProjectionNearPlane(this.id, value); }; ARController.prototype.getProjectionNearPlane = function () { return artoolkit.getProjectionNearPlane(this.id); }; ARController.prototype.setProjectionFarPlane = function (value) { return artoolkit.setProjectionFarPlane(this.id, value); }; ARController.prototype.getProjectionFarPlane = function () { return artoolkit.getProjectionFarPlane(this.id); }; ARController.prototype.setThresholdMode = function (mode) { return artoolkit.setThresholdMode(this.id, mode); }; ARController.prototype.getThresholdMode = function () { return artoolkit.getThresholdMode(this.id); }; ARController.prototype.setThreshold = function (threshold) { return artoolkit.setThreshold(this.id, threshold); }; ARController.prototype.getThreshold = function () { return artoolkit.getThreshold(this.id); }; ARController.prototype.setPatternDetectionMode = function (mode) { return artoolkit.setPatternDetectionMode(this.id, mode); }; ARController.prototype.getPatternDetectionMode = function () { return artoolkit.getPatternDetectionMode(this.id); }; ARController.prototype.setMatrixCodeType = function (type) { return artoolkit.setMatrixCodeType(this.id, type); }; ARController.prototype.getMatrixCodeType = function () { return artoolkit.getMatrixCodeType(this.id); }; ARController.prototype.setLabelingMode = function (mode) { return artoolkit.setLabelingMode(this.id, mode); }; ARController.prototype.getLabelingMode = function () { return artoolkit.getLabelingMode(this.id); }; ARController.prototype.setPattRatio = function (pattRatio) { return artoolkit.setPattRatio(this.id, pattRatio); }; ARController.prototype.getPattRatio = function () { return artoolkit.getPattRatio(this.id); }; ARController.prototype.setImageProcMode = function (mode) { return artoolkit.setImageProcMode(this.id, mode); }; ARController.prototype.getImageProcMode = function () { return artoolkit.getImageProcMode(this.id); }; ARController.prototype.debugDraw = function () { var debugBuffer = new Uint8ClampedArray( Module.HEAPU8.buffer, this._bwpointer, this.framesize ); var id = new ImageData( new Uint8ClampedArray(this.canvas.width * this.canvas.height * 4), this.canvas.width, this.canvas.height ); for (var i = 0, j = 0; i < debugBuffer.length; i++, j += 4) { var v = debugBuffer[i]; id.data[j + 0] = v; id.data[j + 1] = v; id.data[j + 2] = v; id.data[j + 3] = 255; } this.ctx.putImageData(id, 0, 0); var lumaBuffer = new Uint8ClampedArray(this.framesize); lumaBuffer.set(this.videoLuma); var lumaImageData = new ImageData( lumaBuffer, this.videoWidth, this.videoHeight ); this._lumaCtx.putImageData(lumaImageData, 0, 0); var marker_num = this.getMarkerNum(); for (var i = 0; i < marker_num; i++) { this._debugMarker(this.getMarker(i)); } if (this.transform_mat && this.transformGL_RH) { console.log("GL 4x4 Matrix: " + this.transform_mat); console.log("GL_RH 4x4 Mat: " + this.transformGL_RH); } }; ARController.prototype._initialize = function () { this.id = artoolkit.setup(this.width, this.height, this.cameraParam.id); this._initNFT(); var params = artoolkit.frameMalloc; this.framepointer = params.framepointer; this.framesize = params.framesize; this.videoLumaPointer = params.videoLumaPointer; this.dataHeap = new Uint8Array( Module.HEAPU8.buffer, this.framepointer, this.framesize ); this.videoLuma = new Uint8Array( Module.HEAPU8.buffer, this.videoLumaPointer, this.framesize / 4 ); this.camera_mat = new Float64Array(Module.HEAPU8.buffer, params.camera, 16); this.marker_transform_mat = new Float64Array( Module.HEAPU8.buffer, params.transform, 12 ); this.setProjectionNearPlane(0.1); this.setProjectionFarPlane(1e3); setTimeout( function () { if (this.onload) { this.onload(); } this.dispatchEvent({ name: "load", target: this }); }.bind(this), 1 ); }; ARController.prototype._initNFT = function () { artoolkit.setupAR2(this.id); }; ARController.prototype._copyImageToHeap = function (image) { if (!image) { image = this.image; } if (image.data) { var imageData = image; } else { this.ctx.save(); if (this.orientation === "portrait") { this.ctx.translate(this.canvas.width, 0); this.ctx.rotate(Math.PI / 2); this.ctx.drawImage(image, 0, 0, this.canvas.height, this.canvas.width); } else { this.ctx.drawImage(image, 0, 0, this.canvas.width, this.canvas.height); } this.ctx.restore(); var imageData = this.ctx.getImageData( 0, 0, this.canvas.width, this.canvas.height ); } var data = imageData.data; if (this.videoLuma) { var q = 0; for (var p = 0; p < this.videoSize; p++) { var r = data[q + 0], g = data[q + 1], b = data[q + 2]; this.videoLuma[p] = (r + r + r + b + g + g + g + g) >> 3; q += 4; } } if (this.dataHeap) { this.dataHeap.set(data); return true; } return false; }; ARController.prototype._debugMarker = function (marker) { var vertex, pos; vertex = marker.vertex; var ctx = this.ctx; ctx.strokeStyle = "red"; ctx.beginPath(); ctx.moveTo(vertex[0][0], vertex[0][1]); ctx.lineTo(vertex[1][0], vertex[1][1]); ctx.stroke(); ctx.beginPath(); ctx.moveTo(vertex[2][0], vertex[2][1]); ctx.lineTo(vertex[3][0], vertex[3][1]); ctx.stroke(); ctx.strokeStyle = "green"; ctx.beginPath(); ctx.lineTo(vertex[1][0], vertex[1][1]); ctx.lineTo(vertex[2][0], vertex[2][1]); ctx.stroke(); ctx.beginPath(); ctx.moveTo(vertex[3][0], vertex[3][1]); ctx.lineTo(vertex[0][0], vertex[0][1]); ctx.stroke(); pos = marker.pos; ctx.beginPath(); ctx.arc(pos[0], pos[1], 8, 0, Math.PI * 2); ctx.fillStyle = "red"; ctx.fill(); }; ARController.getUserMedia = function (configuration) { var facing = configuration.facingMode || "environment"; var onSuccess = configuration.onSuccess; var onError = configuration.onError || function (err) { console.error("ARController.getUserMedia", err); }; var video = document.createElement("video"); var readyToPlay = false; var eventNames = [ "touchstart", "touchend", "touchmove", "touchcancel", "click", "mousedown", "mouseup", "mousemove", "keydown", "keyup", "keypress", "scroll", ]; var play = function () { if (readyToPlay) { video .play() .then(function () { onSuccess(video); }) .catch(function (error) { onError(error); ARController._teardownVideo(video); }); if (!video.paused) { eventNames.forEach(function (eventName) { window.removeEventListener(eventName, play, true); }); } } }; eventNames.forEach(function (eventName) { window.addEventListener(eventName, play, true); }); var success = function (stream) { if (window.URL.createObjectURL) { try { video.srcObject = stream; } catch (ex) {} } video.srcObject = stream; readyToPlay = true; video.autoplay = true; video.playsInline = true; play(); }; var constraints = {}; var mediaDevicesConstraints = {}; if (configuration.width) { mediaDevicesConstraints.width = configuration.width; if (typeof configuration.width === "object") { if (configuration.width.max) { constraints.maxWidth = configuration.width.max; } if (configuration.width.min) { constraints.minWidth = configuration.width.min; } } else { constraints.maxWidth = configuration.width; } } if (configuration.height) { mediaDevicesConstraints.height = configuration.height; if (typeof configuration.height === "object") { if (configuration.height.max) { constraints.maxHeight = configuration.height.max; } if (configuration.height.min) { constraints.minHeight = configuration.height.min; } } else { constraints.maxHeight = configuration.height; } } mediaDevicesConstraints.facingMode = facing; mediaDevicesConstraints.deviceId = configuration.deviceId; navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia; var hdConstraints = { audio: false, video: constraints }; if (navigator.mediaDevices || window.MediaStreamTrack.getSources) { if (navigator.mediaDevices) { navigator.mediaDevices .getUserMedia({ audio: false, video: mediaDevicesConstraints }) .then(success, onError); } else { window.MediaStreamTrack.getSources(function (sources) { var facingDir = mediaDevicesConstraints.facingMode; if (facing && facing.exact) { facingDir = facing.exact; } for (var i = 0; i < sources.length; i++) { if ( sources[i].kind === "video" && sources[i].facing === facingDir ) { hdConstraints.video.mandatory.sourceId = sources[i].id; break; } } if ( facing && facing.exact && !hdConstraints.video.mandatory.sourceId ) { onError("Failed to get camera facing the wanted direction"); } else { if (navigator.getUserMedia) { navigator.getUserMedia(hdConstraints, success, onError); } else { onError( "navigator.getUserMedia is not supported on your browser" ); } } }); } } else { if (navigator.getUserMedia) { navigator.getUserMedia(hdConstraints, success, onError); } else { onError("navigator.getUserMedia is not supported on your browser"); } } return video; }; ARController.getUserMediaARController = function (configuration) { var obj = {}; for (var i in configuration) { obj[i] = configuration[i]; } var onSuccess = configuration.onSuccess; var cameraParamURL = configuration.cameraParam; var onError = configuration.onError || function (err) { console.error("ARController: Failed to load ARCameraParam", err); }; obj.onSuccess = function () { new ARCameraParam( cameraParamURL, function () { var arCameraParam = this; var maxSize = configuration.maxARVideoSize || Math.max(video.videoWidth, video.videoHeight); var f = maxSize / Math.max(video.videoWidth, video.videoHeight); var w = f * video.videoWidth; var h = f * video.videoHeight; if (video.videoWidth < video.videoHeight) { var tmp = w; w = h; h = tmp; } var arController = new ARController(w, h, arCameraParam); arController.image = video; if (video.videoWidth < video.videoHeight) { arController.orientation = "portrait"; arController.videoWidth = video.videoHeight; arController.videoHeight = video.videoWidth; } else { arController.orientation = "landscape"; arController.videoWidth = video.videoWidth; arController.videoHeight = video.videoHeight; } onSuccess(arController, arCameraParam); }, function (err) { ARController._teardownVideo(video); onError(err); } ); }; var video = ARController.getUserMedia(obj); return video; }; ARController._teardownVideo = function (video) { video.srcObject.getVideoTracks()[0].stop(); video.srcObject = null; video.src = null; }; var ARCameraParam = function (src, onload, onerror) { this.id = -1; this._src = ""; this.complete = false; if (!onload) { this.onload = function () { console.log("Successfully loaded"); }; console.warn("onload callback should be defined"); } else { this.onload = onload; } if (!onerror) { this.onerror = function (err) { console.error("Error: " + err); }; console.warn("onerror callback should be defined"); } else { this.onerror = onerror; } if (src) { this.load(src); } else { console.warn( "No camera parameter file defined! It should be defined in constructor or in ARCameraParam.load(url)" ); } }; ARCameraParam.prototype.load = function (src) { if (this._src !== "") { throw "ARCameraParam: Trying to load camera parameters twice."; } this._src = src; if (src) { artoolkit.loadCamera( src, function (id) { this.id = id; this.complete = true; this.onload(); }.bind(this), function (err) { this.onerror(err); }.bind(this) ); } }; Object.defineProperty(ARCameraParam.prototype, "src", { set: function (src) { this.load(src); }, get: function () { return this._src; }, }); ARCameraParam.prototype.dispose = function () { if (this.id !== -1) { artoolkit.deleteCamera(this.id); } this.id = -1; this._src = ""; this.complete = false; }; var artoolkit = { UNKNOWN_MARKER: -1, PATTERN_MARKER: 0, BARCODE_MARKER: 1, NFT_MARKER: 2, loadCamera: loadCamera, addMarker: addMarker, addMultiMarker: addMultiMarker, addNFTMarker: addNFTMarker, }; var FUNCTIONS = [ "setup", "teardown", "setupAR2", "setLogLevel", "getLogLevel", "setDebugMode", "getDebugMode", "getProcessingImage", "setMarkerInfoDir", "setMarkerInfoVertex", "getTransMatSquare", "getTransMatSquareCont", "getTransMatMultiSquare", "getTransMatMultiSquareRobust", "getMultiMarkerNum", "getMultiMarkerCount", "detectMarker", "getMarkerNum", "detectNFTMarker", "getNFTMarker", "getMarker", "getMultiEachMarker", "setProjectionNearPlane", "getProjectionNearPlane", "setProjectionFarPlane", "getProjectionFarPlane", "setThresholdMode", "getThresholdMode", "setThreshold", "getThreshold", "setPatternDetectionMode", "getPatternDetectionMode", "setMatrixCodeType", "getMatrixCodeType", "setLabelingMode", "getLabelingMode", "setPattRatio", "getPattRatio", "setImageProcMode", "getImageProcMode", ]; function runWhenLoaded() { FUNCTIONS.forEach(function (n) { artoolkit[n] = Module[n]; }); for (var m in Module) { if (m.match(/^AR/)) artoolkit[m] = Module[m]; } } var marker_count = 0; function addMarker(arId, url, callback, onError) { var filename = "/marker_" + marker_count++; ajax( url, filename, function () { var id = Module._addMarker(arId, filename); if (callback) callback(id); }, function (errorNumber) { if (onError) onError(errorNumber); } ); } function addNFTMarker(arId, url, callback, onError) { var mId = marker_count++; var prefix = "/markerNFT_" + mId; var filename1 = prefix + ".fset"; var filename2 = prefix + ".iset"; var filename3 = prefix + ".fset3"; ajax( url + ".fset", filename1, function () { ajax( url + ".iset", filename2, function () { ajax( url + ".fset3", filename3, function () { var id = Module._addNFTMarker(arId, prefix); if (callback) callback(id); }, function (errorNumber) { if (onError) onError(errorNumber); } ); }, function (errorNumber) { if (onError) onError(errorNumber); } ); }, function (errorNumber) { if (onError) onError(errorNumber); } ); } function bytesToString(array) { return String.fromCharCode.apply(String, array); } function parseMultiFile(bytes) { var str = bytesToString(bytes); var lines = str.split("\n"); var files = []; var state = 0; var markers = 0; lines.forEach(function (line) { line = line.trim(); if (!line || line.startsWith("#")) return; switch (state) { case 0: markers = +line; state = 1; return; case 1: if (!line.match(/^\d+$/)) { files.push(line); } case 2: case 3: case 4: state++; return; case 5: state = 1; return; } }); return files; } var multi_marker_count = 0; function addMultiMarker(arId, url, callback, onError) { var filename = "/multi_marker_" + multi_marker_count++; ajax( url, filename, function (bytes) { var files = parseMultiFile(bytes); function ok() { var markerID = Module._addMultiMarker(arId, filename); var markerNum = Module.getMultiMarkerNum(arId, markerID); if (callback) callback(markerID, markerNum); } if (!files.length) return ok(); var path = url.split("/").slice(0, -1).join("/"); files = files.map(function (file) { return [path + "/" + file, file]; }); ajaxDependencies(files, ok); }, function (error) { if (onError) onError(error); } ); } var camera_count = 0; function loadCamera(url, callback, errorCallback) { var filename = "/camera_param_" + camera_count++; var writeCallback = function (errorCode) { if (!Module._loadCamera) { if (callback) callback(id); setTimeout(writeCallback, 10); } else { var id = Module._loadCamera(filename); if (callback) callback(id); } }; if (typeof url === "object") { writeByteArrayToFS(filename, url, writeCallback); } else if (url.indexOf("\n") > -1) { writeStringToFS(filename, url, writeCallback); } else { ajax(url, filename, writeCallback, errorCallback); } } function writeStringToFS(target, string, callback) { var byteArray = new Uint8Array(string.length); for (var i = 0; i < byteArray.length; i++) { byteArray[i] = string.charCodeAt(i) & 255; } writeByteArrayToFS(target, byteArray, callback); } function writeByteArrayToFS(target, byteArray, callback) { FS.writeFile(target, byteArray, { encoding: "binary" }); callback(byteArray); } function ajax(url, target, callback, errorCallback) { var oReq = new XMLHttpRequest(); oReq.open("GET", url, true); oReq.responseType = "arraybuffer"; oReq.onload = function () { if (this.status == 200) { var arrayBuffer = oReq.response; var byteArray = new Uint8Array(arrayBuffer); writeByteArrayToFS(target, byteArray, callback); } else { errorCallback(this.status); } }; oReq.send(); } function ajaxDependencies(files, callback) { var next = files.pop(); if (next) { ajax(next[0], next[1], function () { ajaxDependencies(files, callback); }); } else { callback(); } } scope.artoolkit = artoolkit; scope.ARController = ARController; scope.ARCameraParam = ARCameraParam; if (scope.artoolkit_wasm_url) { scope.Module = Module; } if (scope.Module) { scope.Module.onRuntimeInitialized = function () { runWhenLoaded(); var event = new Event("artoolkit-loaded"); scope.dispatchEvent(event); }; } else { scope.Module = { onRuntimeInitialized: function () { runWhenLoaded(); }, }; } })(); var moduleOverrides = {}; var key; for (key in Module) { if (Module.hasOwnProperty(key)) { moduleOverrides[key] = Module[key]; } } var arguments_ = []; var thisProgram = "./this.program"; var quit_ = function (status, toThrow) { throw toThrow; }; var ENVIRONMENT_IS_WEB = false; var ENVIRONMENT_IS_WORKER = false; var ENVIRONMENT_IS_NODE = false; var ENVIRONMENT_HAS_NODE = false; var ENVIRONMENT_IS_SHELL = false; ENVIRONMENT_IS_WEB = typeof window === "object"; ENVIRONMENT_IS_WORKER = typeof importScripts === "function"; ENVIRONMENT_HAS_NODE = typeof process === "object" && typeof process.versions === "object" && typeof process.versions.node === "string"; ENVIRONMENT_IS_NODE = ENVIRONMENT_HAS_NODE && !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_WORKER; ENVIRONMENT_IS_SHELL = !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIRONMENT_IS_WORKER; var scriptDirectory = ""; function locateFile(path) { if (Module["locateFile"]) { return Module["locateFile"](path, scriptDirectory); } return scriptDirectory + path; } var read_, readAsync, readBinary, setWindowTitle; var nodeFS; var nodePath; if (ENVIRONMENT_IS_NODE) { scriptDirectory = __dirname + "/"; read_ = function shell_read(filename, binary) { var ret = tryParseAsDataURI(filename); if (ret) { return binary ? ret : ret.toString(); } if (!nodeFS) nodeFS = require("fs"); if (!nodePath) nodePath = require("path"); filename = nodePath["normalize"](filename); return nodeFS["readFileSync"](filename, binary ? null : "utf8"); }; readBinary = function readBinary(filename) { var ret = read_(filename, true); if (!ret.buffer) { ret = new Uint8Array(ret); } assert(ret.buffer); return ret; }; if (process["argv"].length > 1) { thisProgram = process["argv"][1].replace(/\\/g, "/"); } arguments_ = process["argv"].slice(2); if (typeof module !== "undefined") { module["exports"] = Module; } process["on"]("uncaughtException", function (ex) { if (!(ex instanceof ExitStatus)) { throw ex; } }); process["on"]("unhandledRejection", abort); quit_ = function (status) { process["exit"](status); }; Module["inspect"] = function () { return "[Emscripten Module object]"; }; } else if (ENVIRONMENT_IS_SHELL) { if (typeof read != "undefined") { read_ = function shell_read(f) { var data = tryParseAsDataURI(f); if (data) { return intArrayToString(data); } return read(f); }; } readBinary = function readBinary(f) { var data; data = tryParseAsDataURI(f); if (data) { return data; } if (typeof readbuffer === "function") { return new Uint8Array(readbuffer(f)); } data = read(f, "binary"); assert(typeof data === "object"); return data; }; if (typeof scriptArgs != "undefined") { arguments_ = scriptArgs; } else if (typeof arguments != "undefined") { arguments_ = arguments; } if (typeof quit === "function") { quit_ = function (status) { quit(status); }; } if (typeof print !== "undefined") { if (typeof console === "undefined") console = {}; console.log = print; console.warn = console.error = typeof printErr !== "undefined" ? printErr : print; } } else if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) { if (ENVIRONMENT_IS_WORKER) { scriptDirectory = self.location.href; } else if (document.currentScript) { scriptDirectory = document.currentScript.src; } if (scriptDirectory.indexOf("blob:") !== 0) { scriptDirectory = scriptDirectory.substr( 0, scriptDirectory.lastIndexOf("/") + 1 ); } else { scriptDirectory = ""; } { read_ = function shell_read(url) { try { var xhr = new XMLHttpRequest(); xhr.open("GET", url, false); xhr.send(null); return xhr.responseText; } catch (err) { var data = tryParseAsDataURI(url); if (data) { return intArrayToString(data); } throw err; } }; if (ENVIRONMENT_IS_WORKER) { readBinary = function readBinary(url) { try { var xhr = new XMLHttpRequest(); xhr.open("GET", url, false); xhr.responseType = "arraybuffer"; xhr.send(null); return new Uint8Array(xhr.response); } catch (err) { var data = tryParseAsDataURI(url); if (data) { return data; } throw err; } }; } readAsync = function readAsync(url, onload, onerror) { var xhr = new XMLHttpRequest(); xhr.open("GET", url, true); xhr.responseType = "arraybuffer"; xhr.onload = function xhr_onload() { if (xhr.status == 200 || (xhr.status == 0 && xhr.response)) { onload(xhr.response); return; } var data = tryParseAsDataURI(url); if (data) { onload(data.buffer); return; } onerror(); }; xhr.onerror = onerror; xhr.send(null); }; } setWindowTitle = function (title) { document.title = title; }; } else { } var out = Module["print"] || console.log.bind(console); var err = Module["printErr"] || console.warn.bind(console); for (key in moduleOverrides) { if (moduleOverrides.hasOwnProperty(key)) { Module[key] = moduleOverrides[key]; } } moduleOverrides = null; if (Module["arguments"]) arguments_ = Module["arguments"]; if (Module["thisProgram"]) thisProgram = Module["thisProgram"]; if (Module["quit"]) quit_ = Module["quit"]; var STACK_ALIGN = 16; function dynamicAlloc(size) { var ret = HEAP32[DYNAMICTOP_PTR >> 2]; var end = (ret + size + 15) & -16; if (end > _emscripten_get_heap_size()) { abort(); } HEAP32[DYNAMICTOP_PTR >> 2] = end; return ret; } function getNativeTypeSize(type) { switch (type) { case "i1": case "i8": return 1; case "i16": return 2; case "i32": return 4; case "i64": return 8; case "float": return 4; case "double": return 8; default: { if (type[type.length - 1] === "*") { return 4; } else if (type[0] === "i") { var bits = parseInt(type.substr(1)); assert( bits % 8 === 0, "getNativeTypeSize invalid bits " + bits + ", type " + type ); return bits / 8; } else { return 0; } } } } function warnOnce(text) { if (!warnOnce.shown) warnOnce.shown = {}; if (!warnOnce.shown[text]) { warnOnce.shown[text] = 1; err(text); } } var jsCallStartIndex = 1; var functionPointers = new Array(0); var funcWrappers = {}; function dynCall(sig, ptr, args) { if (args && args.length) { return Module["dynCall_" + sig].apply(null, [ptr].concat(args)); } else { return Module["dynCall_" + sig].call(null, ptr); } } var tempRet0 = 0; var setTempRet0 = function (value) { tempRet0 = value; }; var getTempRet0 = function () { return tempRet0; }; var GLOBAL_BASE = 8; var wasmBinary; if (Module["wasmBinary"]) wasmBinary = Module["wasmBinary"]; var noExitRuntime; if (Module["noExitRuntime"]) noExitRuntime = Module["noExitRuntime"]; function setValue(ptr, value, type, noSafe) { type = type || "i8"; if (type.charAt(type.length - 1) === "*") type = "i32"; switch (type) { case "i1": HEAP8[ptr >> 0] = value; break; case "i8": HEAP8[ptr >> 0] = value; break; case "i16": HEAP16[ptr >> 1] = value; break; case "i32": HEAP32[ptr >> 2] = value; break; case "i64": (tempI64 = [ value >>> 0, ((tempDouble = value), +Math_abs(tempDouble) >= +1 ? tempDouble > +0 ? (Math_min(+Math_floor(tempDouble / +4294967296), +4294967295) | 0) >>> 0 : ~~+Math_ceil( (tempDouble - +(~~tempDouble >>> 0)) / +4294967296 ) >>> 0 : 0), ]), (HEAP32[ptr >> 2] = tempI64[0]), (HEAP32[(ptr + 4) >> 2] = tempI64[1]); break; case "float": HEAPF32[ptr >> 2] = value; break; case "double": HEAPF64[ptr >> 3] = value; break; default: abort("invalid type for setValue: " + type); } } var ABORT = false; var EXITSTATUS = 0; function assert(condition, text) { if (!condition) { abort("Assertion failed: " + text); } } function getCFunc(ident) { var func = Module["_" + ident]; assert( func, "Cannot call unknown function " + ident + ", make sure it is exported" ); return func; } function ccall(ident, returnType, argTypes, args, opts) { var toC = { string: function (str) { var ret = 0; if (str !== null && str !== undefined && str !== 0) { var len = (str.length << 2) + 1; ret = stackAlloc(len); stringToUTF8(str, ret, len); } return ret; }, array: function (arr) { var ret = stackAlloc(arr.length); writeArrayToMemory(arr, ret); return ret; }, }; function convertReturnValue(ret) { if (returnType === "string") return UTF8ToString(ret); if (returnType === "boolean") return Boolean(ret); return ret; } var func = getCFunc(ident); var cArgs = []; var stack = 0; if (args) { for (var i = 0; i < args.length; i++) { var converter = toC[argTypes[i]]; if (converter) { if (stack === 0) stack = stackSave(); cArgs[i] = converter(args[i]); } else { cArgs[i] = args[i]; } } } var ret = func.apply(null, cArgs); ret = convertReturnValue(ret); if (stack !== 0) stackRestore(stack); return ret; } var ALLOC_NORMAL = 0; var ALLOC_NONE = 3; function allocate(slab, types, allocator, ptr) { var zeroinit, size; if (typeof slab === "number") { zeroinit = true; size = slab; } else { zeroinit = false; size = slab.length; } var singleType = typeof types === "string" ? types : null; var ret; if (allocator == ALLOC_NONE) { ret = ptr; } else { ret = [_malloc, stackAlloc, dynamicAlloc][allocator]( Math.max(size, singleType ? 1 : types.length) ); } if (zeroinit) { var stop; ptr = ret; assert((ret & 3) == 0); stop = ret + (size & ~3); for (; ptr < stop; ptr += 4) { HEAP32[ptr >> 2] = 0; } stop = ret + size; while (ptr < stop) { HEAP8[ptr++ >> 0] = 0; } return ret; } if (singleType === "i8") { if (slab.subarray || slab.slice) { HEAPU8.set(slab, ret); } else { HEAPU8.set(new Uint8Array(slab), ret); } return ret; } var i = 0, type, typeSize, previousType; while (i < size) { var curr = slab[i]; type = singleType || types[i]; if (type === 0) { i++; continue; } if (type == "i64") type = "i32"; setValue(ret + i, curr, type); if (previousType !== type) { typeSize = getNativeTypeSize(type); previousType = type; } i += typeSize; } return ret; } function getMemory(size) { if (!runtimeInitialized) return dynamicAlloc(size); return _malloc(size); } var UTF8Decoder = typeof TextDecoder !== "undefined" ? new TextDecoder("utf8") : undefined; function UTF8ArrayToString(u8Array, idx, maxBytesToRead) { var endIdx = idx + maxBytesToRead; var endPtr = idx; while (u8Array[endPtr] && !(endPtr >= endIdx)) ++endPtr; if (endPtr - idx > 16 && u8Array.subarray && UTF8Decoder) { return UTF8Decoder.decode(u8Array.sub