@ar-js-org/artoolkitplus-ts
Version:
Typescript ARToolKitPlus port thanks to Emscripten
210 lines (173 loc) • 7.86 kB
HTML
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>A simple example with artoolkitplus_em and new dist lib</title>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<video id="video" autoplay loop muted playsinline></video>
<canvas id="canvas"></canvas>
<canvas id="canvas_draw"></canvas>
<script src="../dist/ARToolKitPlus.js"></script>
<script src="js/three.min.js"></script>
<script>
var canvas = document.getElementById('canvas');
var canvas_draw = document.getElementById('canvas_draw');
var overlayCanvas = null;
var ctx = canvas.getContext('2d');
var width = 640, height = 480;
var canvasWidth;
var canvasHeight;
var vec, conf;
var renderer, scene, camera, root, mesh;
var vw, vh;
var sw, sh;
var pw, ph;
var w, h;
var pscale, sscale;
var trk;
var glRHMatrix = new Float64Array(16)
var videoSize;
if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
var hint = {
audio: false,
video: true
};
if (window.innerWidth < 800) {
var width = (window.innerWidth < window.innerHeight) ? 240 : 360;
var height = (window.innerWidth < window.innerHeight) ? 360 : 240;
var aspectRatio = window.innerWidth / window.innerHeight;
console.log(width, height);
hint = {
audio: false,
video: {
facingMode: 'environment',
width: { min: width, max: width }
},
};
console.log(hint);
}
navigator.mediaDevices.getUserMedia(hint).then(function (stream) {
video.srcObject = stream;
video.addEventListener('loadedmetadata', function (e) {
video.play();
console.log('video', video, video.videoWidth, video.videoHeight);
videoSize = video.videoWidth * video.videoHeight;
canvasWidth = video.videoWidth;
canvasHeight = video.videoHeight;
canvas.width = canvasWidth;
canvas.height = canvasHeight;
setupThreejs()
if (video) {
ARToolKitPlus.ARToolKitPlus.initAR().then((ar) => {
ARToolKitPlus.TrackerSingleMarker.initTrackerSingleMarker(false, "data/PGR_M12x0.5_2.5mm.cal", width, height, 80).then(
tracker => {
console.log(tracker);
trk = tracker;
// Display the Pixel Format in use, just to test the static variables...
console.log("PIXEL_FORMAT: ", ARToolKitPlus.ARToolKitPlus.PIXEL_FORMAT.PIXEL_FORMAT_LUM);
// here we go, just two calls to find the camera pose
var projMatrix = trk.getProjectionMatrix();
setCameraMatrix(projMatrix);
process();
})
})
}
});
});
var setMatrix = function (matrix, value) {
var array = [];
for (var key in value) {
array[key] = value[key];
}
if (typeof matrix.elements.set === "function") {
matrix.elements.set(array);
} else {
matrix.elements = [].slice.call(array);
}
};
function grayscale(data) {
// Code taken from jsartoolkit5 repository https://github.com/webarkit/jsartoolkit5/blob/master/js/artoolkit.api.js
let out = [];
var q = 0;
// Create luma from video data assuming Pixelformat AR_PIXEL_FORMAT_RGBA (ARToolKitJS.cpp L: 43)
for (var p = 0; p < videoSize; p++) {
var r = data[q + 0], g = data[q + 1], b = data[q + 2];
// videoLuma[p] = (r+r+b+g+g+g)/6; // https://stackoverflow.com/a/596241/5843642
out[p] = (r + r + r + b + g + g + g + g) >> 3;
q += 4;
}
return out;
}
function isMobile() {
return /Android|mobile|iPad|iPhone/i.test(navigator.userAgent);
}
function setCameraMatrix(proj) {
var ratioW = pw / w;
var ratioH = ph / h;
proj[0] *= ratioW;
proj[4] *= ratioW;
proj[8] *= ratioW;
proj[12] *= ratioW;
proj[1] *= ratioH;
proj[5] *= ratioH;
proj[9] *= ratioH;
proj[13] *= ratioH;
setMatrix(camera.projectionMatrix, proj);
}
function setupThreejs() {
vw = video.videoWidth;
vh = video.videoHeight;
pscale = 320 / Math.max(vw, vh / 3 * 4);
sscale = isMobile() ? window.outerWidth / width : 1;
sw = vw * sscale;
sh = vh * sscale;
w = vw * pscale;
h = vh * pscale;
pw = Math.max(w, h / 3 * 4);
ph = Math.max(h, w / 4 * 3);
renderer = new THREE.WebGLRenderer({ canvas: canvas_draw, alpha: true, antialias: true });
renderer.setPixelRatio(window.devicePixelRatio);
camera = new THREE.Camera();
camera.matrixAutoUpdate = false;
scene = new THREE.Scene();
mesh = new THREE.Mesh(
new THREE.SphereGeometry(0.5, 8, 8),
new THREE.MeshNormalMaterial()
);
root = new THREE.Object3D();
scene.add(root);
mesh.material.flatShading;
mesh.scale.set(200, 200, 200);
root.matrixAutoUpdate = false;
root.add(mesh);
renderer.setSize(sw, sh);
}
function process() {
ctx.drawImage(video, 0, 0, width, height);
var image_data = ctx.getImageData(0, 0, width, height);
if (image_data.data) {
vec = trk.update(grayscale(image_data.data));
console.log("Marker found is: ", vec.get(0));
conf = trk.getConfidence();
console.log("Marker confidence is: ", conf * 100, "%");
var matrix = trk.getModelViewMatrix();
console.log("Marker pose matrix is:", matrix);
setMatrix(root.matrix, matrix);
ctx.putImageData(image_data, 0, 0);
}
if (conf > .7) {
mesh.visible = true;
} else {
mesh.visible = false;
}
renderer.render(scene, camera);
requestAnimationFrame(process);
}
}
</script>
</body>
</html>