Skip to content

Commit 96ddbd9

Browse files
committed
multi nft wasm example
1 parent 373e009 commit 96ddbd9

16 files changed

+589
-0
lines changed

Diff for: examples/Data/chalk_multi.jpg

112 KB
Loading

Diff for: examples/Data/kuva.jpg

73.5 KB
Loading

Diff for: examples/Data/logo.gif

15.4 KB
Loading

Diff for: examples/DataNFT/chalk_multi.fset

3.72 KB
Binary file not shown.

Diff for: examples/DataNFT/chalk_multi.fset3

343 KB
Binary file not shown.

Diff for: examples/DataNFT/chalk_multi.iset

47.5 KB
Binary file not shown.

Diff for: examples/DataNFT/kuva.fset

4.52 KB
Binary file not shown.

Diff for: examples/DataNFT/kuva.fset3

343 KB
Binary file not shown.

Diff for: examples/DataNFT/kuva.iset

46.9 KB
Binary file not shown.

Diff for: examples/build/artoolkit_wasm.js

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

Diff for: examples/build/artoolkit_wasm.wasm

541 KB
Binary file not shown.

Diff for: 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+
}

Diff for: 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>

Diff for: 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+
}

0 commit comments

Comments
 (0)