8.1 Pregled projekta
Ovo je aplikacija VebXR Augmented Realiti za Meta Kuest 3 koja kombinuje:
- Passthrough AR — stvarna soba je vidljiva kroz kamere za slušalice
- Interakcija hit-test — virtuelni kursor koji se pričvršćuje na površine u stvarnom svetu
- AI detekcija objekata — TensorFlow.js prepoznaje objekte u feedu kamere i prikazuje oznake u 3D prostoru
- Razumevanje scene — WebXR Plane Detection vizualizuje otkrivene površine (pod, zidovi, sto)
URL uživo: http://92.113.18.92/
Pojedinačna datoteka:
index.html

8.2 Arhitektura projekta
📄 index.html (sve-u-jednom)
│
├── HTML → platno + dugme UI + skriveni video element
├── CSS → transparentna pozadina, preklapanje UI
└── JavaScript
├── Three.js → 3D rendering engine (scena, kamera, materijali)
├── VebXR API → AR sesija, hit-test, detekcija aviona
└── TF.js → AI zaključivanje (coco-ssd model)
Zašto čista Three.js (bez A-okvira)?
Tokom razvoja otkriveno je da A-Frame ima svoju unutrašnju petlju za renderovanje koja je u sukobu sa eksplicitnom imerzivnom-ar VebXR sesijom. A-Frame započinje immersive-vr sesiju (neprozirno, bez prolaza) umesto immersive-ar. Prelazak na čistu Three.js nam je dao direktnu kontrolu i nad tipom sesije i petljom rendera.
8.3 Tehnologija Stack
|
Tehnologija |
Verzija |
Uloge |
|
Three.js |
0.157.0 |
3D rendering, geometrija, materijali |
|
VebXR API uređaja |
Izvorni pretraživač |
AR sesija, hit-test, detekcija aviona |
|
TensorFlow.js |
4.15.0 |
Mehanizam za zaključivanje ML-a u pretraživaču |
|
COCO-SSD |
2.2.3 |
Unapred obučeni model detekcije objekata |
|
getUserMedia API |
Izvorni pretraživač |
Tok kamere za analizu TF.js |
8.4 Protok aplikacije
Učitavanje stranica
→ TF.js model (coco-SSD) se opterećuje asinhrono (~ 6MB)
→ Proverite: navigator.xr.isSessionSupported('immersive-ar')
→ "Unesite AR" dugme postaje aktivno
Korisnik klikne na "Enter AR"
→ Zahtev: navigator.xr.requestSession('immersive-ar', {...})
→ Kuest omogućava prolaz (kamera vidljiva preko slušalica)
→ Istovremeno: getUserMedia () → tok kamere za TF.js
→ renderer.setAnimationLoop () počinje (KSR render petlja)
Svaki kadar (~ 72fps na Kuest 3)
o scene.background = null (obezbeđuje transparentnost)
o Hit-test → ažurira poziciju kursora
o Avion Detekcija → ažurira vizuelizaciju površine
o Svakih KSNUMKSs → runDetection() → AI zaključivanje
o renderer.render(scena, kamera)
8.5 Detaljno objašnjenje koda
1. HTML Struktura (linije 1–78)
Skriveni element <video> koji prima potok getUserMedia(). TensorFlow.js ga koristi kao ulaz za zaključivanje — nikada se ne prikazuje korisniku, već se samo analizira.

Sloj prekrivača korisničkog interfejsa koji lebdi iznad Three.js platna. pointer-events: none on the container but pointer-events: all on the button only — so the overlay doesn't block 3D interactions.
2. Three.js Inicijalizacija (linije 84–109)
alpha: true kreira WebGL platno sa transparentnim alfa kanalom — ovo je preduslov za prolaz. kstr.enabled = true aktivira ugrađenu VebXR integraciju Three.js-a.
Kamera se dodaje na scenu. Ovo je važno jer objekti vezani za kameru (potomci entiteti) moraju biti u hijerarhiji scene.
Geometrija prstena se rotira -90 ° na Ks osi tako da leži ravno horizontalno na otkrivenim površinama. Bez ove rotacije stajao bi vertikalno.
3. makeLabel() — Text Sprite (linije 113–138)
TRI. Sprajt je objekat koji je uvek okrenut prema kameri (bilbord) — idealan za etikete u 3D prostoru. Nacrtan je na HTML platnu, pretvoren u CanvasTexture i primenjen na SpriteMaterial.
depthTest: false osigurava da je oznaka uvek vidljiva čak i ako je geometrijski "iza" drugog 3D objekta.
4. detectionTo3D() — 2D → 3D projekcija (linije 140–163)
Ovo je matematičko jezgro AI-AR integracije.
Primer: Ako AI otkrije stolicu u levoj trećini video zapisa, nk ≈ -0.17. Ovo se pretvara u negativan ugao (levo od ose pogleda). Oznaka je postavljena 1,8 m ispred kamere u tom pravcu.
5. makeBox3D() i bbox2dSize3D() — 3D Bounding Boxes (linije 165–182)
EdgesGeometry + LineSegments renderuje samo ivice kutije — efekat tanke žičane granice bez ispunjene površine.
TotalW formula je standardna perspektivna projekcija: na udaljenosti d, vidljiva širina zavisi od FOV. Iz ovoga izvodimo koliko metara odgovara pikselima graničnog okvira.
6. runDetection() — AI Inference Pipeline (linije 205–247)
cocoModel.detect(tfVideo) prihvata element <video> direktno — TF.js interno čita podatke piksela iz trenutnog video okvira.
pred.bbok format: [k, i, širina, visina] u pikselima.
Svaka detekcija stvara JS (sprite, kutija) par koji živi 4 sekunde.
7. WebXR Session — Ključni detalji (linije 274–285)

Zašto imerzivno-ar, a ne imerzivno-vr?
- Immersive-VR = neprozirna crna pozadina (VR iskustvo sa kacigom)
- Immersive-AR = prolazna kamera + virtuelni sadržaj prekriven na vrhu
lokalni referentni prostor popravlja koordinatni sistem na podu prostorije — y=0 je na nivou poda.
Hit-Test i Plane-Detection su opcioni jer nisu podržani na svim uređajima i verzijama pretraživača — proglašavanje ih kao opcionih sprečava neuspeh sesije ako nisu dostupni
8. Render Loop (linije 335–395)
Zašto setAnimationLoop i ne requestAnimationFrame?
Three.js XR render petlja mora biti integrisana sa povratnim pozivom VebXR okvira. renderer.setAnimationLoop () automatski se vezuje za KSR sesiju kada renderer.kr.enabled = true. Alternativa (ručno pozivanje session.requestAnimationFrame()) zahteva ručno pozivanje renderer.render(), ali rizikuje da nedostaju ispravne matrice XR prikaza koje se Three.js primenjuju interno.
scene.background = null mora biti pozvan svaki frejm, jer Three.js može interno resetovati ovu vrednost tokom određenih operacija.
9. Detekcija aviona (linije 355–378)
plane.planeSpace je KSRSpace koji prati fizičku površinu. frame.getPose() vraća svoju pozu u izabranom referentnom prostoru.
OtkrivenaMapa aviona (Map<XRPlane, TRI. Mesh>) sprečava stvaranje duplih mreža za istu površinu preko okvira.
8.6 Poznata ograničenja
|
Ograničenje |
Obrazloženje |
|
AI oznake nisu savršeno poravnate sa objektom |
Kuest prolazne kamere i getUserMedia isporučuju različite tokove sa različitim FOV i optičkom kalibracijom |
|
Detekcija aviona zahteva da se završi podešavanje sobe za potragu |
Slušalice moraju prethodno skenirati sobu |
|
getUserMedia može biti odbijen na nekim uređajima |
Zavisi od dozvola pretraživača |
|
AI zaključak nije u realnom vremenu (radi svakih 2s) |
Coco-SSD je relativno težak model; lakši alternative (MobileNet SSD) će dati veću propusnost |
8.7 Izvorni kod
https://github.com/bciric1/ARVR