Hogyan generáljunk 3D telefonmodellt a böngészőben

Útmutató 3D telefonmodellhez a böngészőben Three.js-szel és CSG-vel: bevel élű ház, gomb- és hangszórókivágások, Web Worker és gyors lyukkivonás.

Két generált 3D telefonmodell, az egyik elölről sötét kijelzővel, a másik hátulról

3D telefonmodellt úgy generálhat a böngészőben, hogy egy lekerekített sarkú téglalapot kihúz a készülék mélységére, majd logikai műveletekkel (CSG) kivágja belőle az előlapot, a gombokat, a hangszórókat és a csatlakozót. Az egész készüléket ezután néhány milliméterben megadott szám írja le, és egy új modell ezeknek a számoknak a módosítását jelenti, nem modellezést egy 3D programban.

Ez mindenhol hasznos, ahol sok hasonló készülékre van szükség, vagy a felhasználónak kell őket módosítania: konfigurátorok, mockupok, termékelőnézetek. Gyakorlati példa az Ecranify, egy eszköz 3D mockupokhoz App Store és Google Play képernyőképekhez, amelyben egyetlen kész 3D modell sincs. Alább lépésről lépésre olvashatja a folyamatot, egy méréssel együtt, amely megmutatja, hol lehet a számításon a legtöbbet spórolni.

Amire szüksége lesz

  • Three.js a jelenethez, kamerákhoz, fényekhez és főleg a geometriához. A geometria a Three.js-ben mesh, vagyis háromszögek halmaza.
  • A three-bvh-csg könyvtár a mesheken végzett logikai műveletekhez. Térbeli indexszel (BVH, bounding volume hierarchy) gyorsítja őket, így nem vet össze minden háromszöget minden másikkal.
  • A készülék leírása adatként, például JSON a ház méreteivel, a sarkok sugarával, a bevel méretével és az oldalakon lévő elemek listájával. Minden pozíciót a készülék közepétől mért milliméterben adjon meg.

1. lépés: Húzza ki a téglalapot 3D-be

Rajzoljon egy lekerekített sarkú 2D téglalapot valós méretben, például 163,4 × 78 mm-eset, és húzza ki (extrudálás) 8,75 mm mélységre. Éles élű lapot kap. Ilyen telefon nincs, ezért a kihúzáskor kapcsolja be a bevelt is, vagyis az él lekerekítését. A Three.js mindkettőt egy lépésben elvégzi.

Csak extrudálásSzögletes lap lekerekített sarkok és élek nélkül
+ sarkok és bevelUgyanaz a lap lekerekített sarkokkal és élekkel
Ugyanaz a forma, két másik szám: a sarok sugara és a bevel mérete.

Egy dologra figyeljen: a bevel kifelé adódik hozzá. Ha pontos külső méretre van szüksége, csökkentse a 2D formát és a mélységet a bevel méretével.

b = min(bevel, mélység / 2)
forma = lekerekített téglalap(szélesség - 2b, magasság - 2b, saroksugár - b)
ház = kihúz(forma, mélység - 2b, bevel b)

Az ívek simaságát (tesszelláció) az határozza meg, hány szegmensre bontjuk az ívet. Több szegmens simább formát és több háromszöget jelent. Ez a szám később az egész számítás sebességét meghatározza, ezért a 7. lépésben visszatérünk rá.

2. lépés: Vágjon mélyedést a kijelzőnek

A CSG (constructive solid geometry) egyszerűbb testekből rak össze testeket három művelettel: unió, különbség és metszet. A különbség úgy működik, mint egy fúró: az egyik test anyagot vesz el a másikból.

A telefon kijelzője nem egy síkban van a kerettel, hanem egy sekély mélyedésben ül. Ehhez készítsen a házról egy második, 1,4 mm-rel kisebb másolatot, hagyja meg belőle csak a 0,7 mm vastag elülső részt (metszet egy nagy téglatesttel), és vonja ki ezt a részt a házból. A keletkezett mélyedésbe ezután tegyen egy sötét kijelzőfelületet.

VágótestTelefonház kék, áttetsző vágótesttel az előlapon
Kivonás utánHáz kivágott mélyedéssel és benne sötét kijelzővel
A kék test az, amit kivonunk. Jobbra a kijelző már a mélyedésben ül.

Két gyakorlati részlet:

  • A metszethez használt téglatestnek tényleg nagynak kell lennie. Elég, ha a mélységet vágja, de szélességben és magasságban túl kell nyúlnia az egész készüléken. Ne a mélységből számolja: például a mélység 20-szorosa egy vékony, magas telefonnál kisebb, mint a magassága, és fent meg lent vágatlan keret marad.
  • Nagyítsa meg a vágótestet néhány ezrelékkel. Ha két testnek pontosan azonos lapja van, a CSG nem tudja eldönteni, melyik oldal van belül. Az 1,002-es lépték ezt megelőzi, és szemmel nem látszik.

3. lépés: Készítse elő az oldalsó elemeket fúróként

Minden oldalsó elem ugyanaz a recept más fúróval. Egy gomb például három testből áll: egy a gombnál kicsit mélyebb lekerekített téglalapot kivonunk a keretből, a nyílás széle kis letörést kap, a nyílásba pedig egy valamivel kisebb test kerül, amely kissé kiáll a keretből.

FúrókTelefon oldala két kék gombvágó testtel
Kivágás és gombTelefon oldala kivágott nyílásokkal és behelyezett gombokkal
Két gomb a jobb oldalon kivonás előtt és után.

A hangszórók kis hengerek sorai, a csatlakozó egy lekerekített téglalap. Minden nyílásba tegyen valami sötétet: vékony korongot a rácsba, lapkát a csatlakozóba. Egy üres lyuk a vékony héjban hibának tűnik, a sötét kitöltésű lyuk hardvernek.

Telefon alsó éle két sor hangszórólyukkal és középen csatlakozóval
Hangszórólyukak és csatlakozó. Mind kivont hengerek és lekerekített téglalapok.
az oldalsó elemek listájának minden elemére:
    fúró = az elem formája (henger, lekerekített téglalap, ...)
    helyezd a fúrót az élre a mm-ben megadott pozíció szerint
    add hozzá a fúrót a vágások listájához
    ha az elemnek van kitöltése: add hozzá a kitöltést a jelenethez

Egy gomb hozzáadása így csak egy új bejegyzés az adatokban. Az elemek gyorsan szaporodnak: egy iPad Pro 13″ 58 hangszórólyukkal, 4 gombbal, 2 antennával és egy csatlakozóval rendelkezik, ez több mint 60 kivonás egyetlen házból.

4. lépés: Az előlap részleteit ne fúrja

A kamera kivágása, a kijelző tetején lévő sziget és a kezdőképernyő-jelző lapos. Geometriát vágni hozzájuk felesleges munka. Helyezze fel őket decalként, vagyis felületre vetített képként. Vetítse egy rejtett síkra, amely az egész előlapot lefedi, és a pozíciót ugyanabban a milliméterben adja meg, mint minden mást. Kivétel a régebbi iPhone-ok kerek kezdőgombja. Ennek valódi mélysége van, ami oldalról látszik, ezért CSG-n megy keresztül.

5. lépés: Tegye át a számítást Web Workerbe

A böngészőben a JavaScript egyetlen szálon fut. Ugyanez a szál számol, rajzolja az oldalt és reagál a kattintásokra. Amíg a CSG fut, az oldal megáll, és egy spinner sem segít, mert annak is ugyanez a szál kell.

Ezért az egész készülék összeállítását futtassa Web Workerben, vagyis egy külön háttérszálon. A worker megkapja a készülék leírását, kész csúcstömböket ad vissza, és az oldal folyamatos marad. Ha egy paraméter megváltozik, állítsa le a régi workert, és indítson újat, hogy ne számoljon végig egy elavult állapotot.

A worker eredménye eltart egy ideig, ezért adjon hozzá azonnali előnézetet. A szerkesztett elemet mutassa kék, áttetsző „szellemként”: egyszerű téglatestként vagy hengerként néhány tucat háromszöggel, amely a fő szálon azonnal felépíthető. Amikor a worker végez, a szellem eltűnik.

6. lépés: Vonja ki az összes lyukat egyszerre

A legegyenesebb út az elemek egymás utáni kivonása: az 1. lyukat a házból, aztán a 2.-at az eredményből és így tovább. Minden kivonás azonban újraépíti az egész ház térbeli indexét, ami a számítás legdrágább része. Több tucat elemnél az idő nagyon gyorsan nő.

Jobb, ha előbb összegyűjti az adott test összes fúróját, egyetlen mesh-be egyesíti őket, és egyszer vonja ki.

vágások = []
minden elemre: add hozzá a fúróját a vágásokhoz
egyesített = egyesítsd az összes vágást egy mesh-be
ház = ház mínusz egyesített
ha az egyesítés nem sikerül: vond ki a vágásokat egyenként

Mérés a folyamat egyszerűsített másolatán (Three.js 0.170, three-bvh-csg 0.0.17, Node 22, felhőszerver 2 Intel Xeon 2,1 GHz-es maggal, 5 futás mediánja):

Test Lyukak Egyenként Egyszerre
telefon, 17 676 háromszög 25 2,47 s 0,26 s
tablet, 17 676 háromszög 58 5,55 s 0,89 s
tablet, 68 108 háromszög 58 22,8 s 3,1 s

Egy feltétel: az egyesítés és egyetlen kivonás csak akkor adja ugyanazt az eredményt, mint a fokozatos kivonás, ha a fúrók nem fedik egymást. Az elemek különböző helyeken vannak, így ez általában teljesül. Ha viszont a felhasználó két elemet egymásra tol, az átfedés helyén apró hiba keletkezhet.

7. lépés: A szegmensszámot tartsa paraméterként

A megjelenítéshez elég tesszelláció a CSG-hez gyakran feleslegesen sűrű. Saroknként 64 és a bevelen 32 szegmenssel a ház 68 108 háromszögből áll. A felét (32 és 16) egy 2 mm-es élen nem látni, de a ház így csak 17 676 háromszög, és a táblázat harmadik sora mutatja, mit jelent ez az időben.

64 és 32 szegmensTelefonsarok drótvázas modellje nagyon sűrű háromszöghálóval
32 és 16 szegmensUgyanannak a saroknak a drótvázas modellje fele annyi szegmenssel
A ház sarka felülről. Jobbra a háromszögek negyede.

A legfeljebb 2 mm sugarú kis elemek (hangszórólyukak, csavarok) kapják a szegmensek felét, a galéria előnézetei még kevesebbet. A minőséget ezért ne konstansként írja a kódba, hanem az összeállítás paramétereként adja meg.

Renderelés szerveren videokártya nélkül

Ha ugyanazt a jelenetet szerveren is renderelni kell, például az exportok tartalékaként, az képernyő nélküli (headless) Chrome-ban fut, amely videokártya híján szoftveresen rajzol. Ott minden pazarlás megsokszorozódik. Az Ecranifyban a legnehezebb tablet a fenti módosítások nélkül elérte a 15 perces időkorlátot. Egyesített vágásokkal, kisebb textúrákkal, alacsonyabb tesszellációval és a kész geometria cache-ével, amelynek kulcsa a készülékleírás hashe, egy renderelés nagyjából fél percig tart, egy ismételt pedig körülbelül 5 másodpercig. A részletek interaktív példákkal az ecranify.com angol nyelvű cikkében olvashatók.

Ha hasonló 3D-s problémát old meg a böngészőben, vagy egyedi alkalmazásra van szüksége, írjon nekünk.

← Továbbiak: Ecranify