92 lines
4.2 KiB
HTML
92 lines
4.2 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="utf-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover, maximum-scale=1" />
|
|
<title>Newbury Exhibit — 3D LEGO-head ghost</title>
|
|
<style>
|
|
:root { --red:#f65151; --yellow:#fff35d; --blue:#529eff; --cyan:#51eaf1;
|
|
--ink:#e8eaf2; --dim:#8a93ad; --panel:rgba(10,12,20,0.84); }
|
|
* { box-sizing:border-box; }
|
|
html,body { margin:0; height:100%; background:#05060a; color:var(--ink);
|
|
font-family:'Segoe UI',system-ui,-apple-system,sans-serif; overflow:hidden;
|
|
-webkit-user-select:none; user-select:none; }
|
|
#stage { position:fixed; inset:0; }
|
|
#video,#three { position:absolute; top:50%; left:50%; transform:translate(-50%,-50%); }
|
|
#three { pointer-events:none; }
|
|
|
|
#hud { position:fixed; left:10px; top:calc(10px + env(safe-area-inset-top));
|
|
background:var(--panel); border:1px solid rgba(255,255,255,0.08); border-radius:12px;
|
|
padding:9px 12px; font-size:12.5px; line-height:1.5; backdrop-filter:blur(8px); }
|
|
.tag { padding:1px 8px; border-radius:999px; font-size:11px; font-weight:600; }
|
|
.tag.on { background:rgba(81,234,241,0.16); color:var(--cyan); }
|
|
.tag.off { background:rgba(246,81,81,0.16); color:var(--red); }
|
|
#hud b { color:var(--blue); }
|
|
|
|
/* colour switcher */
|
|
#picker { position:fixed; right:12px; top:calc(10px + env(safe-area-inset-top));
|
|
display:flex; gap:8px; }
|
|
.swatch { width:30px; height:30px; border-radius:50%; border:2px solid rgba(255,255,255,0.25);
|
|
cursor:pointer; }
|
|
.swatch.sel { border-color:#fff; box-shadow:0 0 0 2px rgba(255,255,255,0.3); }
|
|
|
|
#start { position:fixed; inset:0; display:flex; flex-direction:column; align-items:center;
|
|
justify-content:center; gap:18px; text-align:center; padding:24px;
|
|
background:radial-gradient(circle at 50% 38%,#161a2b,#05060a 70%); }
|
|
#start h1 { font-size:24px; margin:0; }
|
|
#start h1 span { background:linear-gradient(90deg,var(--red),var(--yellow),var(--blue));
|
|
-webkit-background-clip:text; background-clip:text; color:transparent; }
|
|
#start p { color:var(--dim); max-width:32ch; margin:0; line-height:1.6; font-size:14px; }
|
|
#go { appearance:none; border:0; cursor:pointer; font-size:16px; font-weight:600; color:#06121f;
|
|
background:linear-gradient(135deg,var(--blue),var(--cyan)); padding:14px 30px; border-radius:999px; }
|
|
#err { color:var(--red); font-size:12.5px; max-width:34ch; }
|
|
.hidden { display:none !important; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div id="stage">
|
|
<video id="video" playsinline muted autoplay></video>
|
|
<canvas id="three"></canvas>
|
|
</div>
|
|
|
|
<div id="hud" class="hidden">
|
|
Ghost <span id="lock" class="tag off">searching…</span><br />
|
|
id <b id="mid">—</b> · dist <b id="dist">—</b>mm · fps <b id="fps">0</b><br />
|
|
<span style="color:var(--dim);font-size:11px">scan:</span>
|
|
<select id="preset" style="background:rgba(255,255,255,0.08);color:var(--ink);border:1px solid rgba(255,255,255,0.15);border-radius:6px;font-size:11px;padding:1px 4px">
|
|
<option value="strict">strict</option>
|
|
<option value="forgiving" selected>forgiving</option>
|
|
<option value="greedy">greedy</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div id="picker" class="hidden">
|
|
<div class="swatch sel" data-c="Blue" style="background:#529eff"></div>
|
|
<div class="swatch" data-c="Red" style="background:#f65151"></div>
|
|
<div class="swatch" data-c="Yellow" style="background:#fff35d"></div>
|
|
</div>
|
|
|
|
<div id="start">
|
|
<h1>Newbury <span>LEGO-head ghost</span></h1>
|
|
<p>Point at a crest. A 3D ghost head locks onto it — walk around and it turns to face you from every side.</p>
|
|
<button id="go">Start camera</button>
|
|
<div id="err"></div>
|
|
</div>
|
|
|
|
<script src="vendor/cv.js"></script>
|
|
<script src="vendor/svd.js"></script>
|
|
<script src="vendor/posit1.js"></script>
|
|
<script src="vendor/aruco.js"></script>
|
|
<script src="vendor/dictionaries/aruco_4x4_1000.js"></script>
|
|
<script type="importmap">
|
|
{
|
|
"imports": {
|
|
"three": "https://cdn.jsdelivr.net/npm/three@0.160.0/build/three.module.js",
|
|
"three/addons/": "https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/"
|
|
}
|
|
}
|
|
</script>
|
|
<script type="module" src="js/ar-head.js"></script>
|
|
</body>
|
|
</html>
|