From 98fb31dad2c3d3ab984f53df7c1fb3078415738a Mon Sep 17 00:00:00 2001 From: albjeremias Date: Thu, 21 May 2020 13:15:43 +0100 Subject: [PATCH] add threejs + wasm worker + gltf model --- .../threejs_wasm_worker_gltf.html | 141 ++++++++++ .../threejs_wasm_worker_gltf.js | 241 ++++++++++++++++++ 2 files changed, 382 insertions(+) create mode 100644 examples/nft_improved_worker/threejs_wasm_worker_gltf.html create mode 100644 examples/nft_improved_worker/threejs_wasm_worker_gltf.js diff --git a/examples/nft_improved_worker/threejs_wasm_worker_gltf.html b/examples/nft_improved_worker/threejs_wasm_worker_gltf.html new file mode 100644 index 00000000..6de213de --- /dev/null +++ b/examples/nft_improved_worker/threejs_wasm_worker_gltf.html @@ -0,0 +1,141 @@ + + + + + NFT marker example with a WebWorker, WASM and with Three.js + + + + +
+ + Loading, please wait +
+ + +
+ +
+

+ Main +

+
+ +
+

+ Worker +

+
+ +
+ + + +
+ + + +
+ + + 🖼 Marker Image + + + + + + + + + + diff --git a/examples/nft_improved_worker/threejs_wasm_worker_gltf.js b/examples/nft_improved_worker/threejs_wasm_worker_gltf.js new file mode 100644 index 00000000..7551949b --- /dev/null +++ b/examples/nft_improved_worker/threejs_wasm_worker_gltf.js @@ -0,0 +1,241 @@ +var model; +var clock = new THREE.Clock(); +var mixers = []; + +function isMobile() { + return /Android|mobile|iPad|iPhone/i.test(navigator.userAgent); +} + +var interpolationFactor = 24; + +var trackedMatrix = { + // for interpolation + delta: [ + 0,0,0,0, + 0,0,0,0, + 0,0,0,0, + 0,0,0,0 + ], + interpolated: [ + 0,0,0,0, + 0,0,0,0, + 0,0,0,0, + 0,0,0,0 + ] +} + +var markers = { + "pinball": { + width: 1637, + height: 2048, + dpi: 250, + url: "../DataNFT/pinball", + }, +}; + +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); + } +}; + +//var worker; +function start(container, marker, video, input_width, input_height, canvas_draw, render_update, track_update) { + worker = new Worker('wasm_worker/artoolkit.wasm_worker.js'); + worker.onmessage = function(ev) { + start2(container, marker, video, input_width, input_height, canvas_draw, render_update, track_update); + } +} + +function start2(container, marker, video, input_width, input_height, canvas_draw, render_update, track_update) { + var vw, vh; + var sw, sh; + var pscale, sscale; + var w, h; + var pw, ph; + var ox, oy; + var camera_para = './../../Data/camera_para-iPhone 5 rear 640x480 1.0m.dat' + + var canvas_process = document.createElement('canvas'); + var context_process = canvas_process.getContext('2d'); + + var renderer = new THREE.WebGLRenderer({canvas: canvas_draw, alpha: true, antialias: true}); + renderer.setPixelRatio(window.devicePixelRatio); + + var scene = new THREE.Scene(); + + var camera = new THREE.Camera(); + camera.matrixAutoUpdate = false; + + scene.add(camera); + + var light = new THREE.AmbientLight(0xffffff); + scene.add(light); + + var root = new THREE.Object3D(); + scene.add(root); + + root.matrixAutoUpdate = false; + /* Load Model */ + var threeGLTFLoader = new THREE.GLTFLoader(); + + threeGLTFLoader.load("../Data/models/Flamingo.glb", function (gltf) { + model = gltf.scene.children[0]; + model.position.z = 0; + model.position.x = 100; + model.position.y = 100; + + var animation = gltf.animations[0]; + var mixer = new THREE.AnimationMixer(model); + mixers.push(mixer); + var action = mixer.clipAction(animation); + action.play(); + + root.matrixAutoUpdate = false; + root.add(model); + } + ); + + var load = function() { + vw = input_width; + vh = input_height; + + pscale = 320 / Math.max(vw, vh / 3 * 4); + sscale = isMobile() ? window.outerWidth / input_width : 1; + + sw = vw * sscale; + sh = vh * sscale; + video.style.width = sw + "px"; + video.style.height = sh + "px"; + container.style.width = sw + "px"; + container.style.height = sh + "px"; + canvas_draw.style.clientWidth = sw + "px"; + canvas_draw.style.clientHeight = sh + "px"; + canvas_draw.width = sw; + canvas_draw.height = sh; + w = vw * pscale; + h = vh * pscale; + pw = Math.max(w, h / 3 * 4); + ph = Math.max(h, w / 4 * 3); + ox = (pw - w) / 2; + oy = (ph - h) / 2; + canvas_process.style.clientWidth = pw + "px"; + canvas_process.style.clientHeight = ph + "px"; + canvas_process.width = pw; + canvas_process.height = ph; + + renderer.setSize(sw, sh); + + worker.postMessage({type: "load", pw: pw, ph: ph, camera_para: camera_para, marker: '../' + marker.url}); + + worker.onmessage = function(ev) { + var msg = ev.data; + switch (msg.type) { + case "loaded": { + var proj = JSON.parse(msg.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); + break; + } + + case "endLoading": { + if (msg.end == true) + // removing loader page if present + document.body.classList.remove("loading"); + document.getElementById("loading").remove(); + break; + } + + case "found": { + found(msg); + break; + } + + case "not found": { + found(null); + break; + } + } + + track_update(); + process(); + }; + }; + + var world; + + var found = function(msg) { + if (!msg) { + world = null; + } else { + world = JSON.parse(msg.matrixGL_RH); + } + }; + + var lasttime = Date.now(); + var time = 0; + + var draw = function() { + render_update(); + var now = Date.now(); + var dt = now - lasttime; + time += dt; + lasttime = now; + + if (!world) { + root.visible = false; + } else { + root.visible = true; + // interpolate matrix + for (var i = 0; i < 16; i++) { + trackedMatrix.delta[i] = world[i] - trackedMatrix.interpolated[i]; + trackedMatrix.interpolated[i] = + trackedMatrix.interpolated[i] + + trackedMatrix.delta[i] / interpolationFactor; + } + + // set matrix of 'root' by detected 'world' matrix + setMatrix(root.matrix, trackedMatrix.interpolated); + } + renderer.render(scene, camera); + }; + + function process() { + context_process.fillStyle = "black"; + context_process.fillRect(0, 0, pw, ph); + context_process.drawImage(video, 0, 0, vw, vh, ox, oy, w, h); + + var imageData = context_process.getImageData(0, 0, pw, ph); + worker.postMessage({ type: "process", imagedata: imageData }, [ + imageData.data.buffer + ]); + } + var tick = function() { + draw(); + requestAnimationFrame(tick); + if (mixers.length > 0) { + for (var i = 0; i < mixers.length; i++) { + mixers[i].update(clock.getDelta()); + } + } + }; + + load(); + tick(); + process(); +}