Snapchat-szerű szűrő létrehozása Jeeliz FaceFilter API-jával: 2. rész, felhasználói interakciók és részecskék

A FaceFilter API lehetővé teszi, hogy könnyedén hozzon létre Snapchat-szerű szűrőket a webes alkalmazásaiba. Az arcfelismerő neurális hálózatra építve ötvözi a mély tanulás erejét a WebGL / Three.js sokoldalúságával.

Összefoglalás az előző részről: A sorozat első részében először láttuk, hogyan lehet 3D modellt exportálni a JSON-ba a Blender segítségével. Ezután hozzáadtuk kalapunkat a Three.js jelenethez, és így a Grand Line igazi kalózá váltunk! Nagyon ügyes, mi?

Ebben az oktatóanyagban egy felhasználói interakciót fogunk használni, hogy kiváló csokor hozzáadását indítsuk a szűrőnkbe. Egyidejűleg animált részecskéket adunk hozzá, hogy hűvös megjelenési hatást hozzunk létre. Shazaa!

Előfeltételek: az előző oktatóprogramhoz hasonlóan, jó ismeretekkel kell rendelkeznie a Javascript számára, és jól meg kell ismernie a Three.js alapjait.

Készen állsz egy seggszűrő felépítésére?!

Projektmappa létrehozása

Ugyanazon a ponttal kezdjük, mint a sorozat első bemutatóján. Másoljuk meg a „kocka” mappát, és nevezjük azt „bowtie” -nek.

Megjegyzés: A FaceFilter API futtatásához eszközöket helyi kiszolgálón keresztül kell kiszolgálni. A projekt mappa gyökeréből származó parancssorban indítsa el a httpServer.py parancsfájlt, és látogasson el a localhost: 8455 webhelyre, hogy ellenőrizze a demokat.

Készítsük el a értékesítési objektumot

Oké, ideje elkészíteni a hírt. Először keresünk egy 3D-s modellt az interneten, majd a Blender segítségével exportáljuk azt a JSON-ba. Ha még nem nézte meg a sorozat első cikkét, akkor a teljes folyamat itt található.

Csodálatos értékesünk, amelyet a Blenderben láthatunk

Rendben, most, hogy megvan a megfelelő formátumú modellünk, kezdjük bele a kódolásba. A demo.js-ben létrehozunk egy függvényt, az initListeners () -et, amelybe az összes kódot belehelyezzük a felhasználói interakciókhoz - ebben az esetben a „kattintás” vagy a „érintés” -be a mobilon.

// itt minden hallgatót inicializálunk a felhasználói interakciókhoz
initListeners () függvény {
  // a kódod ide megy!
}

Ezután elkészítjük az értékesítési hálót, feltöltve a modellünket, létrehozva egy anyagot, majd mindkettőt hálóba keverve:

// itt minden hallgatót inicializálunk a felhasználói interakciókhoz
initListeners () függvény {
  // létrehozjuk a betöltőt
  const loader = new THREE.BufferGeometryLoader ()
  // majd betölti a modellünket
  loader.load (
    „Modellek / bowtie.json”
    függvény (geometria) {
      // majd a betöltőnk visszahívásában először anyagot készítünk
      // választunk egy MeshPhongMaterial, amely lehetővé teszi számunkra, hogy reálisabb
      // eredmény (lásd: https://threejs.org/docs/#api/materials/MeshPhongMaterial)
      const anyag = új THREE.MeshPhongMaterial ({
      // itt egy textúrát töltünk be a modellünkhöz
        térkép: új THREE.TextureLoader (). betöltés ('modellek / texture.jpg'),
        fényesség: 3,
        spekuláris: 0xffffff
      });
      // itt létrehozjuk a hálót az újonnan betöltött geometriával és az éppen létrehozott anyaggal
     const bowtieMesh = új THREE.Mesh (geometria, mat);
   )
}

A részecskék létrehozása

A következő lépés a részecskék objektum létrehozása. Kattintás után a részecskéket véletlenszerű irányban terjesztjük, hogy hűvös varázslatos megjelenési hatást érjünk el. Kódunk egy részét ebből a three.js példából kapjuk meg.

Összességében ezekre a példákra vagy az arra való felkeresésemre, amikor valahol beragadtam egy three.js projektbe, mivel az alapok nagy része és még bonyolultabb funkciói le vannak fedve.

Ilyen részecskéket hozunk létre:

Gyönyörű, nem? Merüljünk bele!

// létrehozunk egy üres tömböt, ahol tiszteletben tartjuk a részecskéinket
// a későbbi animáció érdekében
const RÉSZEK = [];
// a 3D részecske-objektumot pillanatok alatt állítjuk, és a „látható” tulajdonságot hamis értékre állítjuk
// ezt a tulajdonságot arra használjuk, hogy elrejtse ezt az objektumot, az animáción keresztül szükségünk volt
const PARTICLESOBJ3D = új THREE.Object3D ();
PARTICLESOBJ3D.visible = false;
// adjuk hozzá az objektumot a 3D objektumunkhoz
THREEFACEOBJ3D.add (PARTICLESOBJ3D);
// anyag létrehozása
// a generspritert a threejs példából vett helper módszerrel fogjuk használni
const particleMaterial = új THREE.SpriteMaterial ({
  térkép: új THREE.CanvasTexture (generatorSprite ()),
  keverés: THREE.AdditiveBlending
});
// ezután 200 részecskét állítunk elő, amelyeket kattintással mutatunk meg
mert (legyen i = 0; i <= 200; i ++) {
  részecske = új HÉT.Kapsz (részecske anyag);
  PARTICLES.push (részecske);
  PARTICLESOBJ3D.add (részecske);
}

Kicsit adaptáltam a generSprite () metódust, a three.js példából vettük:

function geneSprite () {
  var canvas = document.createElement ('vászon');
  vászon szélesség = 8;
  vászonmagasság = 8;
  var context = canvas.getContext ('2d');
  var gradient = context.createRadialGradient (vászon szélesség / 2, vászon magasság / 2, 0, vászon szélesség / 2, vászon magasság / 2, vászon szélesség / 2);
  gradiens.addColorStop (0, 'rgba (255,255,255,0,5)');
  gradiens.addColorStop (0,2, 'rgba (255,255,255,0,5)');
  gradient.addColorStop (1, 'rgba (0,0,0,0,5)');
  context.fillStyle = gradiens;
  context.fillRect (0, 0, vászon szélesség, vászon magasság);
  visszavászon;
}

Az eseményhallgató létrehozása

Azt szeretnénk észlelni, amikor a felhasználó rákattint a vászonra; akkor hozzáadjuk az értékesítést az egér helyzetéhez, amikor a felhasználó rákattint, és elindítja a részecske-animációt. Kezdjük egy eseményfigyelő létrehozásával.

Rakodó visszahívásunkban:

// Hivatkozást készítünk a vászonra, és hozzáadjuk az esemény-hallgatókat
const vászon = document.getElementById ('jeeFaceFilterCanvas');
canvas.addEventListener ('kattintás', (esemény) => {
  // a hálót a setPosition helper funkcióval pozicionáljuk
  bowtieMesh = setPosition (bowtieMesh, esemény);
  // beállítottuk a .frustumCoble hamis értékre, hogy olyan elemek jelenjenek meg, amelyeknek a testrésze van
  // a frusztrumból
  bowtieMesh.frustumCulled = false;
  // állítsa a renderOrder magasra, hogy rétegezzük a bowtie-t a videó textúráján
  bowtieMesh.renderOrder = 100000;
  // létrehozunk egy html objektumot 3D-vel, és hozzáadjuk a hálót
  const BOWTIE = új HÁROM.objekt3D ();
  BOWTIE.add (bowtieMesh);
  // ezután beállítjuk a részecske object3D látható tulajdonságát "true" -ra, hogy ez megjelenjen, és a setPosition segítőnk segítségével állítsa be az objektumot
  PARTICLESOBJ3D.visible = igaz;
  setPosition (PARTICLESOBJ3D, esemény);
  // ezután hívjuk az animateParticle metódust, amelyet azonnal létrehozunk, a PARTICLES tömbünk minden elemére.
  // ez a módszer kezeli a részecskék animációját
  PARTICLES.forEach ((részecske, index) => {
    animateParticle (részecske, 50 * index);
  });
  // hozzáadunk egy setTimeout-ot a részecske-objektum látható tulajdonságának beállításához
  // hamis az animáció vége után
  setTimeout (function () {
     PARTICLESOBJ3D.visible = false;
  }, 50 * RÉSZEK (hossz);
  // végül hozzáadjuk az értékesítési objektumot
  THREEFACEOBJ3D.add (Bowtie);
});

Pfuj! Nagyon nagy volt, de itt már majdnem kész vagyunk! Még hozzá kell adnunk a setPosition () és az animateParticles () segítő módszereinket.

A setPosition segítőnk létrehozása

Csak a setPosition-t illesztem be, mivel nem kell megértenie a mögöttes fogalmakat. De ha hajlandó megérteni egy kicsit jobban, hogyan működik, felkérem Önt, hogy tegye meg a következő útmutatót a WebGLAcademy.com webhelyen.

Itt van a funkciónk:

hagyjuk, hogy a MOUSEVECTOR = új HÉT.Vektor3 () legyen a DIRECTIONVECTOR = új HÁROM.Vektor3 () legyen a VIEWPORTVECTOR = új HÁT.Vektor3 () // ez a funkció a bowtie hálóját a THREEFACEOBJ3D funkciókészletre állítja, amely setBowtiePosition (háló, esemény) {// we kiszámítja az egér helyzetét a vászon belsejében
// előfordulhat, hogy ezekkel hegedül, attól függően, hogy a vászon abszolút / normál helyzetben van-e. var x = - (2 * (event.clientX - canvas.offsetLeft + canvas.offsetWidth / 2) / canvas.offsetWidth - 1); var y = - (2 * (esemény.klientY - canvas.offsetTop + canvas.offsetHeight / 2) / canvas.offsetHeight - 1);
// ez arra a pontra található, ahová a hálót hozzá kell adni a MOUSEVECTOR.set (x, y) kattintásra; VIEWPORTVECTOR.set (x, y, 1);
  DIRECTIONVECTOR.copy (VIEWPORTVECTOR);
  DIRECTIONVECTOR.unproject (THREECAMERA);
  DIRECTIONVECTOR.sub (THREECAMERA.position);
  DIRECTIONVECTOR.normalize ();
  // kiszámoljuk azt az együtthatót, amely lehetővé teszi nekünk a háló helyzetének megállapítását const k = _headCenterZ / DIRECTIONVECTOR.z;
mesh.position.copy (DIRECTIONVECTOR) .multiplyScalar (k); mesh.position.sub (THREEFACEOBJ3D.position); }

Animáljuk részecskéinket az animált részecskével

Tökéletes. Most bármilyen hozzáadott elemet elhelyezhetünk kattintással az egér helyzetében. Készítsük el az animateParticle módszerünket. Ez a módszer két érvelést igényel:

  1. Az a részecskeméret, amelyet animálni akarunk
  2. A késleltetési érték, amely az animáció befejezéséig eltelt idő

A Tween.js-t használjuk a részecskék animálására. Ismét nem magyarázom meg az animáció matematikai logikáját, a legjobb módja annak, hogy jobban megértsük, mi folyik, az, ha a paraméterekkel játsszuk és nézzük meg az általuk kifejtett hatást.

funkció animateParticle (részecske, késleltetés) {
  // Tween pozíció:
  var sugárEnd = 100;
  particle.position.set (0,0,0)
var theta = Math.random () * 2 * Math.PI; // szög az XY síkban
var phi = (Math.random () * 2–1) * Math.PI / 4 // szög az XY sík és a részecske között. 0-> az XY síkban
  új TWEEN.Tween (részecske.pozíció)
  .to ({x: 0,008 * sugárEnd * Math.cos (theta) * Math.cos (phi),
    y: 0,008 * sugárEnd * Math.sin (theta) * Math.cos (phi),
  }, késés)
  .Rajt();
  // tween skála:
  particle.scale.x = particle.scale.y = Math.random () * 0.15
  új TWEEN.Tween (részecske.skála)
  .to ({x: 0.0001, y: 0.0001}, késleltetés)
  .Rajt();
}

Az utolsó lépés egy kódsor hozzáadása a render hurokba, hogy idővel frissítsük a tweeneinket. A fő () függvényben, a callbackTrack-ben:

if (ISDETECTED) {
  ...
  // hozzáadjuk a kódot az ISDETECTED-hez, ha blokk
  TWEEN.update ()
}

És ott van! Mesés csokornyakkendőt adunk hozzá minden alkalommal, amikor a felhasználó az egér helyzetében rákattint a vászonra, és hozzáad egy hűvös megjelenési hatást, amelyet a részecskék animációja hoz létre. Mennyire nagyszerű?!

Feladatok:

  1. Játsszon még egy kicsit a részecskékkel: próbálkozzon úgy, hogy esik az égből, mint eső, vagy változtassa meg a színeket az idő múlásával, változtassa meg a mozgást
  2. Válassza ki és adja hozzá a projekthez más 3D-s modelleket, amelyek alkalmasak lehetnek a virtuális kipróbálásra: fülbevalók, pólók…

Összegezni:

A sorozat Snapchat-szerű szûrõk létrehozásáról szóló második része elkészült! Yeaay!

Az oktatóanyag teljes részében láttuk, hogyan lehet hozzáadni egy 3D-s objektumot a felhasználói interakcióhoz. Láttuk azt is, hogyan lehet részecskéket létrehozni és animálni a gyönyörű hatás elérése érdekében!

A következő részben vizuális deformációkat hozunk létre a felhasználó arcán. Ez vidám lesz, garantálom; plusz lehetővé teszi számunkra, hogy mélyebben belemerüljünk a Three.js-be és bonyolultabb 3D technikákat tanulmányozzunk. Tehát maradj velünk az izgalmas epizódon!