| <!DOCTYPE html> |
| <html> |
| <head> |
| <meta charset="utf-8"> |
| <meta name="viewport" content='width=device-width, height=device-height, initial-scale=1.0, minimum-scale=1.0, user-scalable=no, shrink-to-fit=yes'> |
| <title>ClothAd</title> |
| <link rel="stylesheet" href="TemplateData/style.css"> |
| <link rel="icon" href="TemplateData/favicon.ico"> |
| <style> |
| html{ |
| height: -webkit-fill-available; |
| } |
| body { |
| margin: 0; |
| padding: 0; |
| min-height: 100vh; |
| min-height: -webkit-fill-available; |
| width: 100vw; |
| overflow: hidden; |
| background: #1a1a1a; |
| } |
| .ctaDiv { |
| display: flex; |
| flex-direction: column; |
| align-items: center; |
| justify-content: center; |
| position: absolute; |
| left: 0; |
| right: 0; |
| top: 0; |
| bottom: 0; |
| background: #fffa; |
| background: rgba(0, 0, 0, 0.8); |
| z-index: 99; |
| } |
| .ctaDiv p { |
| text-align: center; |
| width: 60vw; |
| color: #ffffff; |
| font-family: 'Arial', sans-serif; |
| font-size: 1.2em; |
| margin-bottom: 20px; |
| } |
| .ctaDiv select { |
| background: #000000; |
| color: #ffffff; |
| border: 2px solid #ffffff; |
| padding: 10px; |
| font-size: 1em; |
| border-radius: 5px; |
| transition: background 0.3s ease; |
| margin-bottom: 20px; |
| } |
| .ctaDiv select:hover { |
| background: #333333; |
| } |
| .ctaDiv button { |
| background: #000000; |
| color: #ffffff; |
| border: 2px solid #ffffff; |
| padding: 10px 20px; |
| font-size: 1em; |
| border-radius: 5px; |
| cursor: pointer; |
| transition: background 0.3s ease; |
| } |
| .ctaDiv button:hover { |
| background: #333333; |
| } |
| </style> |
| </head> |
| <body> |
| |
| <imagetarget id='ClothAd' src='targets/ClothAd.png'></imagetarget> |
|
|
| <video id="webcam-video" muted autoplay playsinline style="width:1px;position:absolute"></video> |
| |
| <canvas id="video-canvas" style="width:100%; height:100%; object-fit:cover; position:absolute"></canvas> |
| <div id="startARDiv" class="ctaDiv"> |
| <select id="chooseCamSel" style="display: none;" onchange="SelectCam()"></select> |
| <p>Welcome to ClothAd! To dive into this immersive AR experience, we need access to your device's camera.</p> |
| <button id="startARButton" onclick="StartAR()" style="display:none">ALLOW ACCESS</button> |
| </div> |
| <div id="screenshotDiv" style="display: none;" class="ctaDiv"> |
| <div style="position:relative; background-color:white; padding:10px; box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.3), 0 6px 20px 0 rgba(0, 0, 0, 0.25);"> |
| <img id="screenshotImg" src="" alt="screenshot" style="width:80vw; height:80vh"> |
| <button onclick="document.getElementById('screenshotDiv').style.display = 'none';" style="position:absolute; transform:translateY(-100%); right:0; top:0">Close</button> |
| </div> |
| </div> |
| <div id="confirmUrlDiv" style="display: none;" class="ctaDiv"> |
| <div style="position:relative; background-color:white; padding:10px; box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.3), 0 6px 20px 0 rgba(0, 0, 0, 0.25); width: 80vw; display:flex; flex-direction: column; align-items: center;"> |
| <p id="confirmUrlText" style="text-align: center; width:80%; overflow: hidden; text-overflow: ellipsis;">Are you sure you want to visit url.com?</p> |
| <div> |
| <button onclick="window.open(newUrlString, '_blank').focus(); document.getElementById('confirmUrlDiv').style.display = 'none'">VISIT SITE</button> |
| <button onclick="document.getElementById('confirmUrlDiv').style.display = 'none'">GO BACK</button> |
| </div> |
| </div> |
| </div> |
| <div id="errorDiv" class="ctaDiv" style="display: none; background:#aaa"> |
| <p id="errorText" style="text-align: center; width:60vw; color:white"></p> |
| </div> |
| <div id="unity-container" class="unity-mobile"> |
| <canvas id="unity-canvas" style="width: 100%; height: 100%; background: #0000; z-index: -99"></canvas> |
| <div id="unity-loading-bar"> |
| <div id="unity-logo"></div> |
| <div id="unity-progress-bar-empty"> |
| <div id="unity-progress-bar-full"></div> |
| </div> |
| </div> |
| <canvas id="video-canvas"></canvas> |
| </div> |
| <script src="arcamera.js" type="text/javascript"></script> |
| <script src="itracker.js" type="text/javascript"></script> |
| <script src="Build/Build.loader.js"></script> |
| <script> |
| var initialize = async() =>{ |
| var unityCanvas = document.querySelector("#unity-canvas"); |
| var videoCanvas = document.querySelector("#video-canvas"); |
| window.arCamera = new ARCamera(unityCanvas, videoCanvas); |
| window.iTracker = new ImageTracker(arCamera); |
| try{ |
| await window.iTracker.initialize(); |
| console.log("ImageTracker initialized!"); |
| } |
| catch{ |
| console.error("Failed to initialize ImageTracker. Are you missing opencv.js? " + error); |
| ShowError("Failed to initialize the experience."); |
| return; |
| } |
| |
| try { |
| const permissionStatus = await navigator.permissions.query({ name: 'camera' }); |
| if (permissionStatus.state === 'granted') { |
| |
| await LoadWebcams(); |
| StartAR(); |
| } else { |
| |
| await LoadWebcams(); |
| document.getElementById("startARButton").style.display = "block"; |
| } |
| } catch (err) { |
| console.error("Error checking camera permission: ", err); |
| |
| await LoadWebcams(); |
| document.getElementById("startARButton").style.display = "block"; |
| } |
| } |
| initialize(); |
| var container = document.querySelector("#unity-container"); |
| var canvas = document.querySelector("#unity-canvas"); |
| var loadingBar = document.querySelector("#unity-loading-bar"); |
| var progressBarFull = document.querySelector("#unity-progress-bar-full"); |
| function StartAR() { |
| canvas.style.width = window.innerWidth + "px"; |
| canvas.style.height = window.innerHeight + "px"; |
| |
| document.getElementById("startARDiv").style.display = "none"; |
| createUnityInstance(document.querySelector("#unity-canvas"), { |
| dataUrl: "Build/Build.data", |
| frameworkUrl: "Build/Build.framework.js", |
| codeUrl: "Build/Build.wasm", |
| streamingAssetsUrl: "StreamingAssets", |
| companyName: "BlackFlash", |
| productName: "ClothAd", |
| productVersion: "0.1", |
| |
| |
| |
| }, |
| (progress) => { |
| progressBarFull.style.width = 100 * progress + "%"; |
| } |
| ).then((unityInstance) => { |
| window.unityInstance = unityInstance; |
| RequestWebcam(); |
| loadingBar.style.display = "none"; |
| }); |
| loadingBar.style.display = "block"; |
| } |
| |
| window.unityFacingMode = "environment" |
| window.WEBCAM_SETTINGS = { |
| video: { |
| facingMode: unityFacingMode, |
| }, |
| audio: false |
| }; |
| window.requestingForPermissions = false; |
| async function RequestWebcam(){ |
| window.requestingForPermissions = true; |
| try{ |
| window.webcamStream = await navigator.mediaDevices.getUserMedia(window.WEBCAM_SETTINGS); |
| console.log("Webcam access granted"); |
| requestingForPermissions = false; |
| } |
| catch (err) { |
| |
| console.error("getUserMedia error - " , err); |
| ShowError("Failed to start the experience. Camera permission was denied"); |
| window.requestingForPermissions = false; |
| } |
| } |
| async function StartWebcam(){ |
| console.log("StartWebcam") |
| while (window.requestingForPermissions) { |
| |
| console.log("Waiting for permissions..."); |
| await new Promise(resolve => setTimeout(resolve, 100)); |
| } |
| console.log("Got Permissions"); |
| if(window.webcamStream) |
| { |
| const video = document.querySelector("#webcam-video"); |
| video.srcObject = webcamStream; |
| try { |
| await arCamera.startWebcam(video); |
| console.log("Webcam started successfully"); |
| window.unityInstance.SendMessage('ARCamera', 'OnStartWebcamSuccess'); |
| } |
| catch(err){ |
| console.error("Webcam failed to start - ", err); |
| window.unityInstance.SendMessage('ARCamera', 'OnStartWebcamFail'); |
| } |
| } |
| else{ |
| console.error("Webcam failed to start - permission not yet granted"); |
| window.unityInstance.SendMessage('ARCamera', 'OnStartWebcamFail'); |
| } |
| } |
| async function LoadWebcams(){ |
| let camDevices = []; |
| |
| let devices = await navigator.mediaDevices.enumerateDevices(); |
| var ctr = 0; |
| devices.forEach(mediaDevice => { |
| if (mediaDevice.kind === 'videoinput') { |
| if(window.unityFacingMode == 'environment' && !mediaDevice.label.includes('facing front')){ |
| |
| camDevices.push(mediaDevice); |
| } |
| else if(window.unityFacingMode == 'user' && mediaDevice.label.includes('facing front')){ |
| |
| camDevices.push(mediaDevice); |
| } |
| else{ |
| |
| camDevices.push(mediaDevice); |
| } |
| |
| ctr++; |
| } |
| }); |
| var select = document.getElementById("chooseCamSel"); |
| select.style.display = "block"; |
| var count = 0; |
| |
| |
| camDevices = camDevices.reverse(); |
| camDevices.forEach(mediaDevice => { |
| const option = document.createElement('option'); |
| option.value = mediaDevice.deviceId; |
| let label = `Camera ${count}`; |
| if (mediaDevice.label) { |
| label = mediaDevice.label |
| } |
| const textNode = document.createTextNode(label); |
| option.appendChild(textNode); |
| select.appendChild(option); |
| count++; |
| }); |
| iTracker.WEBCAM_NAME = select.options[select.selectedIndex].innerHTML; |
| } |
| function SelectCam(){ |
| var select = document.getElementById("chooseCamSel"); |
| window.deviceId = select.value; |
| window.WEBCAM_SETTINGS.video['deviceId'] = deviceId; |
| |
| iTracker.WEBCAM_NAME = select.options[select.selectedIndex].innerHTML; |
| } |
| async function FlipCam(){ |
| arCamera.stopWebcam(); |
| window.WEBCAM_SETTINGS.video.deviceId = ''; |
| if(window.WEBCAM_SETTINGS.video.facingMode == 'user'){ |
| window.WEBCAM_SETTINGS.video.facingMode = 'environment'; |
| arCamera.setFlipped(false); |
| } |
| else{ |
| window.WEBCAM_SETTINGS.video.facingMode = 'user'; |
| arCamera.setFlipped(true); |
| } |
| window.webcamStream = await navigator.mediaDevices.getUserMedia(window.WEBCAM_SETTINGS); |
| const video = document.querySelector("#webcam-video"); |
| video.srcObject = webcamStream; |
| await arCamera.startWebcam(video); |
| } |
| function ShowError(error){ |
| document.getElementById("errorDiv").style.display = "flex"; |
| document.getElementById("errorText").innerHTML = error; |
| } |
| function ShowScreenshot(dataUrl){ |
| document.getElementById("screenshotDiv").style.display = "flex"; |
| document.getElementById("screenshotImg").src = dataUrl; |
| document.getElementById("screenshotImg").style.width = "80vw"; |
| document.getElementById("screenshotImg").style.height = 80 / window.innerWidth * window.innerHeight + "vw"; |
| } |
| function ShowConfirmUrl(url){ |
| document.getElementById("confirmUrlDiv").style.display = "flex"; |
| window.newUrlString = url; |
| document.getElementById("confirmUrlText").innerText = "Are you sure you want to visit " + url; |
| } |
| window.ITRACKER_GLOBALS = { |
| |
| INTERNAL_SMOOTHFACTOR_POS: .075, |
| } |
| |
| </script> |
| </body> |
| </html> |
|
|