Skip to content

Commit 771b3bc

Browse files
committedDec 21, 2020
multi nft wasm example
1 parent 68196b8 commit 771b3bc

16 files changed

+589
-0
lines changed
 

‎examples/Data/chalk_multi.jpg

112 KB
Loading

‎examples/Data/kuva.jpg

73.5 KB
Loading

‎examples/Data/logo.gif

15.4 KB
Loading

‎examples/DataNFT/chalk_multi.fset

3.72 KB
Binary file not shown.

‎examples/DataNFT/chalk_multi.fset3

343 KB
Binary file not shown.

‎examples/DataNFT/chalk_multi.iset

47.5 KB
Binary file not shown.

‎examples/DataNFT/kuva.fset

4.52 KB
Binary file not shown.

‎examples/DataNFT/kuva.fset3

343 KB
Binary file not shown.

‎examples/DataNFT/kuva.iset

46.9 KB
Binary file not shown.

‎examples/build/artoolkit_wasm.js

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎examples/build/artoolkit_wasm.wasm

541 KB
Binary file not shown.

‎examples/css/video-style.css

+112
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
html,
2+
body {
3+
margin: 0;
4+
overflow: hidden;
5+
}
6+
7+
html {
8+
font-family: sans-serif;
9+
}
10+
11+
#loading {
12+
width: 100%;
13+
position: absolute;
14+
display: flex;
15+
flex-direction: column;
16+
justify-content: center;
17+
align-items: center;
18+
width: 100%;
19+
height: 100%;
20+
background-color: rgba(0, 0, 0, 0.45);
21+
z-index: 9999999;
22+
}
23+
24+
#loading img {
25+
height: 5em;
26+
}
27+
28+
#loading span{
29+
color: black;
30+
font-weight: bold;
31+
}
32+
33+
.ui {
34+
position: fixed;
35+
36+
margin: 0.5rem;
37+
38+
background-color: rgba( 255,255,255,0.6 );
39+
border-radius: 6px;
40+
}
41+
42+
.stats {
43+
top: 0;
44+
left: 0;
45+
z-index: 200;
46+
margin: 0.5rem;
47+
padding: 0.5rem 0.5rem 0;
48+
}
49+
50+
.stats-item {
51+
margin: 0 0 0.5rem;
52+
53+
}
54+
55+
.stats-item-title {
56+
margin: 0 0 0.25rem;
57+
58+
font-size: 0.75rem;
59+
}
60+
61+
#stats div {
62+
position: relative !important;
63+
}
64+
65+
.marker {
66+
right: 0;
67+
bottom: 0;
68+
z-index: 200;
69+
margin: 0.5rem;
70+
padding: 0.25rem 0.5rem;
71+
72+
font-size: 0.75rem;
73+
color: inherit;
74+
text-decoration: none;
75+
}
76+
77+
#app {
78+
position: fixed;
79+
top: 0;
80+
left: 0;
81+
82+
width: 100%;
83+
height: 100%;
84+
}
85+
86+
#video {
87+
position: absolute;
88+
top: 0;
89+
left: 0;
90+
91+
display: block;
92+
width: 100% !important;
93+
height: 100% !important;
94+
object-fit: cover;
95+
}
96+
97+
#canvas {
98+
position: absolute;
99+
left: 0;
100+
top: 0;
101+
z-index: 100;
102+
103+
display: block;
104+
width: 100% !important;
105+
height: 100% !important;
106+
object-fit: cover;
107+
}
108+
109+
110+
#arvideo {
111+
display: none;
112+
}

‎examples/index.html

+4
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,7 @@
1313
<a href="/examples/arNFT_example.html"><h2>ARnft example with NFT tracking</h2></a>
1414
<p>A simple example that display a red cube. You need the <a href="/examples/Data/pinball.jpg">Pinball image</a>
1515
</div>
16+
<div class='box'>
17+
<a href="/examples/multi_wasm_nft.html"><h2>Multi NFT WASM example with jsartoolkit5</h2></a>
18+
<p>A simple example that display three different 3d models. You need the <a href="/examples/Data/pinball.jpg">Pinball image</a>, <a href="/examples/Data/chalk_multi.jpg">chalk_multi image</a> and <a href="/examples/Data/kuva.jpg">Kuva image</a>
19+
</div>

‎examples/multi_nft_wasm_worker.js

+249
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,249 @@
1+
function isMobile() {
2+
return /Android|mobile|iPad|iPhone/i.test(navigator.userAgent);
3+
}
4+
5+
var interpolationFactor = 24;
6+
7+
var trackedMatrix = {
8+
// for interpolation
9+
delta: [
10+
0,0,0,0,
11+
0,0,0,0,
12+
0,0,0,0,
13+
0,0,0,0
14+
],
15+
interpolated: [
16+
0,0,0,0,
17+
0,0,0,0,
18+
0,0,0,0,
19+
0,0,0,0
20+
]
21+
}
22+
23+
var setMatrix = function (matrix, value) {
24+
var array = [];
25+
for (var key in value) {
26+
array[key] = value[key];
27+
}
28+
if (typeof matrix.elements.set === "function") {
29+
matrix.elements.set(array);
30+
} else {
31+
matrix.elements = [].slice.call(array);
32+
}
33+
};
34+
35+
//var worker;
36+
function start(markerUrls, video, input_width, input_height, canvas_draw, render_update, track_update) {
37+
worker = new Worker('wasm_worker/artoolkit.wasm_multi_worker.js');
38+
worker.onmessage = function(ev) {
39+
start2(markerUrls, video, input_width, input_height, canvas_draw, render_update, track_update);
40+
}
41+
}
42+
43+
function start2(markerUrls, video, input_width, input_height, canvas_draw, render_update, track_update) {
44+
var vw, vh;
45+
var sw, sh;
46+
var pscale, sscale;
47+
var w, h;
48+
var pw, ph;
49+
var ox, oy;
50+
var camera_para = './../Data/camera_para.dat'
51+
52+
var canvas_process = document.createElement('canvas');
53+
var context_process = canvas_process.getContext('2d');
54+
55+
var renderer = new THREE.WebGLRenderer({ canvas: canvas_draw, alpha: true, antialias: true });
56+
renderer.setPixelRatio(window.devicePixelRatio);
57+
58+
var scene = new THREE.Scene();
59+
60+
var camera = new THREE.Camera();
61+
camera.matrixAutoUpdate = false;
62+
63+
scene.add(camera);
64+
65+
var sphere = new THREE.Mesh(
66+
new THREE.SphereGeometry(0.5, 8, 8),
67+
new THREE.MeshNormalMaterial()
68+
);
69+
70+
var cube = new THREE.Mesh(
71+
new THREE.BoxGeometry(0.5),
72+
new THREE.MeshNormalMaterial()
73+
);
74+
75+
var cone = new THREE.Mesh(
76+
new THREE.ConeGeometry( 0.5, 1, 32 ),
77+
new THREE.MeshNormalMaterial()
78+
);
79+
80+
var root = new THREE.Object3D();
81+
scene.add(root);
82+
83+
sphere.material.flatShading;
84+
sphere.position.z = 0;
85+
sphere.position.x = 100;
86+
sphere.position.y = 100;
87+
sphere.scale.set(200, 200, 200);
88+
89+
cube.material.flatShading;
90+
cube.position.z = 0;
91+
cube.position.x = 100;
92+
cube.position.y = 100;
93+
cube.scale.set(200, 200, 200);
94+
95+
cone.material.flatShading;
96+
cone.rotation.x = 90;
97+
cone.position.z = 0;
98+
cone.position.x = 100;
99+
cone.position.y = 100;
100+
cone.scale.set(200, 200, 200);
101+
102+
root.matrixAutoUpdate = false;
103+
root.add(sphere);
104+
root.add(cube);
105+
root.add(cone);
106+
107+
var load = function() {
108+
vw = input_width;
109+
vh = input_height;
110+
111+
pscale = 320 / Math.max(vw, vh / 3 * 4);
112+
sscale = isMobile() ? window.outerWidth / input_width : 1;
113+
114+
sw = vw * sscale;
115+
sh = vh * sscale;
116+
117+
w = vw * pscale;
118+
h = vh * pscale;
119+
pw = Math.max(w, h / 3 * 4);
120+
ph = Math.max(h, w / 4 * 3);
121+
ox = (pw - w) / 2;
122+
oy = (ph - h) / 2;
123+
canvas_process.style.clientWidth = pw + "px";
124+
canvas_process.style.clientHeight = ph + "px";
125+
canvas_process.width = pw;
126+
canvas_process.height = ph;
127+
128+
renderer.setSize(sw, sh);
129+
130+
131+
worker.postMessage({ type: "load", pw: pw, ph: ph, camera_para: camera_para, markerUrls: markerUrls });
132+
133+
worker.onmessage = function(ev) {
134+
var msg = ev.data;
135+
switch (msg.type) {
136+
case "loaded": {
137+
var proj = JSON.parse(msg.proj);
138+
var ratioW = pw / w;
139+
var ratioH = ph / h;
140+
proj[0] *= ratioW;
141+
proj[4] *= ratioW;
142+
proj[8] *= ratioW;
143+
proj[12] *= ratioW;
144+
proj[1] *= ratioH;
145+
proj[5] *= ratioH;
146+
proj[9] *= ratioH;
147+
proj[13] *= ratioH;
148+
setMatrix(camera.projectionMatrix, proj);
149+
break;
150+
}
151+
case "endLoading": {
152+
if (msg.end == true) {
153+
// removing loader page if present
154+
var loader = document.getElementById('loading');
155+
if (loader) {
156+
loader.querySelector('.loading-text').innerText = 'Start the tracking!';
157+
setTimeout(function(){
158+
loader.parentElement.removeChild(loader);
159+
}, 2000);
160+
}
161+
}
162+
break;
163+
}
164+
case "found": {
165+
found(msg);
166+
break;
167+
}
168+
case "not found": {
169+
found(null);
170+
break;
171+
}
172+
}
173+
track_update();
174+
process();
175+
};
176+
};
177+
178+
var world, index;
179+
180+
var found = function(msg) {
181+
if (!msg) {
182+
world = null;
183+
} else {
184+
world = JSON.parse(msg.matrixGL_RH);
185+
index = JSON.parse(msg.index);
186+
}
187+
};
188+
189+
var lasttime = Date.now();
190+
var time = 0;
191+
192+
var draw = function() {
193+
render_update();
194+
var now = Date.now();
195+
var dt = now - lasttime;
196+
time += dt;
197+
lasttime = now;
198+
199+
if (!world) {
200+
sphere.visible = false;
201+
cube.visible = false;
202+
cone.visible = false;
203+
} else {
204+
if (index == 0) {
205+
sphere.visible = true;
206+
cube.visible = false;
207+
cone.visible = false;
208+
}
209+
else if(index == 1) {
210+
sphere.visible = false;
211+
cube.visible = true;
212+
cone.visible = false;
213+
}
214+
else if(index == 2) {
215+
sphere.visible = false;
216+
cube.visible = false;
217+
cone.visible = true;
218+
}
219+
// interpolate matrix
220+
for (var i = 0; i < 16; i++) {
221+
trackedMatrix.delta[i] = world[i] - trackedMatrix.interpolated[i];
222+
trackedMatrix.interpolated[i] =
223+
trackedMatrix.interpolated[i] +
224+
trackedMatrix.delta[i] / interpolationFactor;
225+
}
226+
227+
// set matrix of 'root' by detected 'world' matrix
228+
setMatrix(root.matrix, trackedMatrix.interpolated);
229+
}
230+
renderer.render(scene, camera);
231+
};
232+
233+
function process() {
234+
context_process.fillStyle = "black";
235+
context_process.fillRect(0, 0, pw, ph);
236+
context_process.drawImage(video, 0, 0, vw, vh, ox, oy, w, h);
237+
238+
var imageData = context_process.getImageData(0, 0, pw, ph);
239+
worker.postMessage({ type: "process", imagedata: imageData }, [imageData.data.buffer]);
240+
}
241+
var tick = function() {
242+
draw();
243+
requestAnimationFrame(tick);
244+
};
245+
246+
load();
247+
tick();
248+
process();
249+
}

‎examples/multi_wasm_nft.html

+134
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8">
5+
<title>Jsartoolkit5 NFT marker example with a WebWorker and Three.js | WebAR Kit org.</title>
6+
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=0.5, maximum-scale=1">
7+
<link rel="stylesheet" href="./css/video-style.css">
8+
</head>
9+
<body>
10+
<div id="loading" >
11+
<img src="./Data/logo.gif"/>
12+
<span class="loading-text">Loading, please wait</span>
13+
</div>
14+
<!--
15+
==================
16+
STATS
17+
==================
18+
-->
19+
20+
<div id="stats" class="ui stats">
21+
22+
<div id="stats1" class="stats-item">
23+
<p class="stats-item-title">
24+
Main
25+
</p>
26+
</div>
27+
28+
<div id="stats2" class="stats-item">
29+
<p class="stats-item-title">
30+
Worker
31+
</p>
32+
</div>
33+
34+
</div>
35+
36+
<!--
37+
==================
38+
CAMERA VIDEO & CANVAS
39+
==================
40+
-->
41+
42+
<div id="app">
43+
<video
44+
loop
45+
autoplay
46+
muted
47+
playsinline
48+
id="video">
49+
</video>
50+
51+
<canvas id="canvas"></canvas>
52+
</div>
53+
54+
<script src="./Data/js/third_party/three.js/stats.min.js"></script>
55+
<script src="./Data/js/third_party/three.js/three.min.js"></script>
56+
<script src="multi_nft_wasm_worker.js"></script>
57+
58+
<script>
59+
60+
/**
61+
* STATS
62+
*/
63+
var statsMain = new Stats();
64+
statsMain.showPanel( 0 ); // 0: fps, 1: ms, 2: mb, 3+: custom
65+
document.getElementById( 'stats1' ).appendChild( statsMain.dom );
66+
67+
var statsWorker = new Stats();
68+
statsWorker.showPanel( 0 ); // 0: fps, 1: ms, 2: mb, 3+: custom
69+
document.getElementById( 'stats2' ).appendChild( statsWorker.dom );
70+
71+
/**
72+
* APP / ELEMENTS
73+
*/
74+
var container = document.getElementById( 'app' );
75+
var video = document.getElementById( 'video' );
76+
var canvas = document.getElementById( 'canvas' );
77+
78+
/**
79+
* APP / VIDEO STREAM
80+
*/
81+
82+
if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
83+
var hint = {
84+
audio: false,
85+
video: true
86+
};
87+
if( window.innerWidth < 800 ) {
88+
var width = ( window.innerWidth < window.innerHeight ) ? 240 : 360;
89+
var height = ( window.innerWidth < window.innerHeight ) ? 360 : 240;
90+
91+
var aspectRatio = window.innerWidth / window.innerHeight;
92+
93+
console.log( width, height );
94+
95+
hint = {
96+
audio: false,
97+
video: {
98+
facingMode: 'environment',
99+
width: { min: width, max: width }
100+
},
101+
};
102+
103+
console.log( hint );
104+
}
105+
106+
navigator.mediaDevices.getUserMedia( hint ).then( function( stream ) {
107+
video.srcObject = stream;
108+
video.addEventListener( 'loadedmetadata', function() {
109+
video.play();
110+
111+
console.log( 'video', video, video.videoWidth, video.videoHeight );
112+
113+
var markerUrls = [ "./../DataNFT/pinball", "./../DataNFT/chalk_multi", "./../DataNFT/kuva" ]
114+
115+
start(
116+
markerUrls,
117+
video,
118+
video.videoWidth,
119+
video.videoHeight,
120+
canvas,
121+
function() {
122+
statsMain.update()
123+
},
124+
function() {
125+
statsWorker.update();
126+
}
127+
);
128+
} );
129+
} );
130+
}
131+
</script>
132+
</body>
133+
134+
</html>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
window = {};
2+
window.artoolkit_wasm_url = '../build/artoolkit_wasm.wasm';
3+
window.listeners = {};
4+
window.addEventListener = function (name, callback) {
5+
if (!window.listeners[name]) {
6+
window.listeners[name] = [];
7+
}
8+
window.listeners[name].push(callback);
9+
};
10+
window.removeEventListener = function (name, callback) {
11+
if (window.listeners[name]) {
12+
var index = window.listeners[name].indexOf(callback);
13+
if (index > -1) {
14+
window.listeners[name].splice(index, 1);
15+
}
16+
}
17+
};
18+
window.dispatchEvent = function (event) {
19+
var listeners = window.listeners[event.type];
20+
if (listeners) {
21+
for (var i = 0; i < listeners.length; i++) {
22+
listeners[i].call(window, event);
23+
}
24+
}
25+
};
26+
27+
importScripts('../../examples/build/artoolkit_wasm.js');
28+
self.onmessage = function(e) {
29+
var msg = e.data;
30+
switch (msg.type) {
31+
case "load": {
32+
load(msg);
33+
return;
34+
}
35+
case "process": {
36+
next = msg.imagedata;
37+
process();
38+
return;
39+
}
40+
}
41+
};
42+
43+
var next = null;
44+
45+
var ar = null;
46+
var markerResult = null;
47+
48+
function load(msg) {
49+
var param = new ARCameraParam(msg.camera_para);
50+
param.onload = function () {
51+
ar = new ARController(msg.pw, msg.ph, param);
52+
var cameraMatrix = ar.getCameraMatrix();
53+
54+
ar.addEventListener('getNFTMarker', function (ev) {
55+
markerResult = {type: "found", index: JSON.stringify(ev.data.index), matrixGL_RH: JSON.stringify(ev.data.matrixGL_RH), proj: JSON.stringify(cameraMatrix)};
56+
});
57+
58+
ar.loadNFTMarkers(msg.markerUrls, function (markerIds) {
59+
ar.trackNFTMarkerId(markerIds, 2);
60+
console.log("loadNFTMarker -> ", markerIds);
61+
postMessage({type: "endLoading", end: true})
62+
});
63+
64+
postMessage({type: "loaded", proj: JSON.stringify(cameraMatrix)});
65+
};
66+
}
67+
68+
function process() {
69+
70+
markerResult = null;
71+
72+
if (ar) {
73+
ar.process(next);
74+
}
75+
76+
if (markerResult) {
77+
postMessage(markerResult);
78+
} else {
79+
postMessage({type: "not found"});
80+
}
81+
82+
next = null;
83+
}
84+
85+
window.addEventListener('artoolkit-loaded', function() {
86+
console.log('artoolkit-loaded');
87+
Object.assign(self, window);
88+
postMessage({type: "wasm"});
89+
});

0 commit comments

Comments
 (0)
Please sign in to comment.