Yeqa uye kokuyinhloko
Izifundo ze-AI

Yakha Izilwane Ezakhiwa Ngohlelo Nezinyakazayo ku-Three.js

Funda ukufaka i-Procedural Animals, ukudala isilwane esine-seed, ukulawula ukunyakaza nezenzo, ukuphatha imicimbi, ukumisa ama-worker, ukulungiselela ama-asethi ukuze alayishe ngokushesha, nokukhetha izilungiselelo zekhwalithi, kusukela ezithombeni eziseduze zesinema kuya ezixukwini ezinkulu.

Yakha Izilwane Ezakhiwa Ngohlelo Nezinyakazayo ku-Three.js

Yini i-three.js Procedural Animals?

three.js Procedural Animals iwumtapo oqukethe izilwane ezingu-24 ezikhiqizwa ngesikhathi sokusebenza ku-three.js. Esikhundleni sokulanda amamodeli, ama-texture, ama-rig noma ama-animation clip, ubiza createAnimal() bese umtapo wakha isilwane esiphelele esigqwayizayo ngekhodi.

Isilwane ngasinye sakhiwe kusetshenziswa ama-signed distance field, senziwa i-mesh, sifakelwe i-rig ne-skin, simbozwe ngoboya, izimpaphe noma izikali, bese sigqwayizwa ngama-gait nezenzo ze-inverse kinematics. Izakhiwo zemizimba ezitholakalayo zihlanganisa izilwane ezinezidladla, ezinezinselo, izinyoni, ababhukudi, izinyoka, izicabucabu nabagxumayo.

Ungahlola zonke izinhlobo, izinguqulo, izenzo nemibukiso yokulungisa iphutha ku-umbukiso obukhoma, noma uhlole ikhodi ku-GitHub repository.

Izici Eziyinhloko

  • Izinhlobo ezingu-24: Izinketho zisuka ezimpisini, emakati, emahhashini nakumvundla ziye ezinyonini, ezinhlanzini, ezinyokeni nasezicabucabwini.
  • Izilwane ezisebenzisa i-seed: I-seed ikhiqiza usayizi, izilinganiso zomzimba, ijazi, ubulili, ubudala nezinguqulo eziphindaphindekayo ngaphandle kokuthi uziguqule.
  • Ukugqwayiza ngesikhathi sokusebenza: Izilwane zikhetha ngokuzenzakalelayo ama-gait afanele futhi zinikeze izenzo ezinjengokuhlala, ukulala, ukudla, ukuhlasela nokugxuma.
  • Amazinga amahlanu ekhwalithi: Khetha phakathi kwe-hero, high, medium, low ne-crowd.
  • Ukwakhiwa okusekelwe kuma-Worker: Ukwakhiwa kwenzeka kuma-Module Web Worker ngokuzenzakalelayo, kube ne-fallback eya ku-thread ebizayo.
  • Ukulungiselela ngaphandle kwesikhathi sokusebenza: Yakha isilwane kusengaphambili sibe yifayela le-.animal ukuze silayishwe cishe ngama-millisecond angu-20.
  • Izilawuli ezigxile emidlalweni: Lawula izilwane, zihambise ezindaweni eziqondiwe, zilandele imizimba ye-physics, zilandele okuqondiwe, dlala izenzo futhi uthole imicimbi yomdlalo.
  • Ukusekelwa kwe-TypeScript: Iphakheji isebenzisa ama-ES module futhi ihlanganisa izincazelo ze-TypeScript.

Ukufakwa

Umtapo udinga i-three.js r160 noma entsha njengokuphela kwe-peer dependency. Faka iphakheji ne-three.js nge-npm:

npm install procedural-animals three

Uma iphakheji ingakatholakali ku-npm, yifake ngqo ku-GitHub:

npm install github:majidmanzarpour/threejs-procedural-animals three

Dala Isilwane Sakho Sokuqala

Qala ngokungenisa i-three.js kanye ne-createAnimal. Umsebenzi awuvumelanisi ngoba ukwakha i-mesh, i-rig, izembozo nedatha ehambisanayo kuthatha isikhathi.

import * as THREE from 'three';
import { createAnimal } from 'procedural-animals';

const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(innerWidth, innerHeight);
renderer.shadowMap.enabled = true;
document.body.appendChild(renderer.domElement);

const scene = new THREE.Scene();
scene.background = new THREE.Color(0xa9c1e0);

const camera = new THREE.PerspectiveCamera(
  40,
  innerWidth / innerHeight,
  0.1,
  500
);
camera.position.set(6, 3, 8);

const sun = new THREE.DirectionalLight(0xfff3e4, 2.7);
sun.position.set(6, 10, 4);
sun.castShadow = true;

scene.add(
  sun,
  new THREE.HemisphereLight(0xdde6f2, 0x5f5a52, 1.15)
);

const floor = new THREE.Mesh(
  new THREE.PlaneGeometry(200, 200).rotateX(-Math.PI / 2),
  new THREE.MeshStandardMaterial({ color: 0x77736a })
);
floor.receiveShadow = true;
scene.add(floor);

async function main() {
  const wolf = await createAnimal('wolf', {
    seed: 3,
    quality: 'high'
  });

  scene.add(wolf.object);

  let last = performance.now();

  renderer.setAnimationLoop((now) => {
    const dt = (now - last) / 1000;
    last = now;

    wolf.move({
      speed: wolf.gears.walk,
      heading: now / 1000 * 0.3
    });

    wolf.update(dt);
    camera.lookAt(wolf.position);
    renderer.render(scene, camera);
  });
}

main();

Kunemithetho eminingana ebalulekile kulesi sibonelo:

  1. Dala isilwane ngaphakathi komsebenzi we-async bese ulinda umphumela nge-await.
  2. Engeza i-animal.object esigcawini, kodwa ugcine i-transform yaleyo object iku-identity. Isilwane sizilawula sona ukunyakaza kwaso.
  3. Sebenzisa izindlela ezifana ne-move(), moveTo() noma follow() ukuze usiqondise.
  4. Biza i-update(dt) kanye kuphela ku-frame ngayinye, lapho i-dt ikalwa ngemizuzwana.
  5. Sebenzisa izivinini ezivela ku-animal.gears ngoba amagama e-gear atholakalayo angahluka kuye ngohlobo lwesilwane.

Gwema i-await esezingeni eliphezulu kumodule yokuqala. Ngokwemibhalo yephrojekthi, ingavala ukwakhiwa kwe-Vite production.

Ukunyakaza Nokuzulazula

Ukuqondisa Okuqondile

Indlela ye-move() ithatha isivinini ngamamitha ngomzuzwana kanye ne-heading ngama-radian. I-heading engu-0 ibheka ku-eksisi engu-positive Z.

wolf.move({
  speed: wolf.gears.walk,
  heading: Math.PI / 2
});

Biza i-stop() lapho isilwane kufanele siyeke ukunyakaza:

wolf.stop();

Hambisa Esendaweni Eqondiwe

Sebenzisa i-moveTo() ukuthumela isilwane endaweni esesikhaleni somhlaba. Ithumela umcimbi we-arrive ngemva kokufika lapho siya khona.

wolf.moveTo(
  new THREE.Vector3(10, 0, 4),
  { speed: 3 }
);

wolf.on('arrive', () => {
  console.log('The wolf arrived.');
});

Landela Umzimba We-Physics

Uma olunye uhlelo lulawula umzimba, dlulisela indawo yawo yamanje nesivinini ku-follow() ku-frame ngayinye:

wolf.follow(body.position, body.velocity);

Landelela Okuqondiwe

Yenza isilwane siphendulele ikhanda laso kokuthile okuqondiwe nge-lookAt(). Dlulisa u-null ukuze siyeke ukulandelela.

wolf.lookAt(player.position);

// Later:
wolf.lookAt(null);

Izenzo Zokudlala

Uhlobo ngalunye lusekela izenzo ezivamile ezithi jump, sit, lie, sleep, eat, drink, attack, hit, death, kanye ne-stand. Izinhlobo zingaphinde zinikeze izenzo ezikhethekile. Isibonelo, izinyoka zingazigoqa futhi zihlasele, izinyoni zingasuka phansi futhi zehle, kanti onogwaja bangagxuma futhi bashaye phansi ngezinyawo.

Indlela ye-play() ibuyisa i-Promise umphumela wayo ongaba done, interrupted, stopped, noma refused.

const result = await wolf.play('attack');
console.log(result);

Hlola animal.actions esikhundleni sokucabanga ukuthi uhlobo oluthile luyasisekela isenzo esikhethekile. Ungamisa isenzo esiqanjwe ngegama usebenzisa i-stopAction():

wolf.stopAction('attack');

Phendula Imicimbi Yezilwane

I-API yemicimbi ivumela amasistimu omdlalo ukuthi aphendule ekugqwayizeni nasekunyakazeni. Imicimbi etholakalayo ihlanganisa footstep, attackHit, actionStart, actionEnd, arrive, takeoff, land, death, vocalize, kanye ne-wingbeat.

const onFootstep = (event) => {
  sfx.play('step', event.position, event.strength);
};

wolf.on('footstep', onFootstep);

wolf.on('attackHit', (event) => {
  damage(event.position, event.direction);
});

// Remove a listener when it is no longer needed.
wolf.off('footstep', onFootstep);

Hlela Indawo Namanzi

Inketho ye-ground ingumsebenzi obuyisa ukuphakama kwendawo ngezixhumanisi zika-X no-Z. Izixhumanisi zawo kufanele zibe sendaweni ka-animal.object.parent, futhi ukuphakama okubuyiswayo kufanele kuhambisane nendawo eboniswa esigcawini.

const deer = await createAnimal('deer', {
  ground: (x, z) => terrainHeightAt(x, z),
  position: new THREE.Vector3(4, 0, 8),
  heading: Math.PI
});

Izilwane ezibhukudayo zidinga umsebenzi we-water kanye nendawo yokuqala engaphansi kobuso bamanzi. Umsebenzi ubuyisa ukuphakama kobuso bamanzi noma null lapho kungekho manzi.

const fish = await createAnimal('fish', {
  water: (x, z) => 2,
  position: new THREE.Vector3(0, 1, 0)
});

scene.add(fish.object);

Izilwane zasemhlabeni nazo zingasebenzisa incazelo yamanzi ukuze ziphuze futhi zihambe emanzini angajulile. Izinyoni zingamukela uhlu lwe-perches oluqukethe amaphuzu e-THREE.Vector3 ezingandizela kuwo.

Khetha Uhlobo, Izinhlobonhlobo Nabantu Ngabanye

Ilabhulali ihlanganisa izimpisi, izinja, izimpungushe, amakati, amabhubesi, izingulule, amabhere, amagundane, onogwaja, amahhashi, izinyamazane, izinkomo, izingulube, izimvu, izimbuzi, izingulube zasendle, amaxoxo, izinkukhu, amagwababa, izinkozi, izinhlanzi, oshaka, izinyoka, kanye nezicabucabu.

Sebenzisa i-seed ukuze udale isilwane esifanayo njalo. Ungaphinda ukhethe ngokuqondile uhlobo lwaso, ubulili, noma ubudala:

const cat = await createAnimal('cat', {
  seed: 12,
  quality: 'high',
  variant: 'tuxedo',
  sex: 'female',
  age: 'adult'
});

Izihlonzi zezinhlobo eziyizintambo zilayishwa kuphela lapho zidingeka. Uma uhlelo ludinga uhlobo olulodwa kuphela, ngenisa lolo hlobo ngokuqondile ukuze ugcine i-bundle igxile:

import wolfSpecies from 'procedural-animals/species/wolf';
import { createAnimal } from 'procedural-animals';

const wolf = await createAnimal(wolfSpecies, {
  seed: 3
});

Khetha Izinga Lekhwalithi Elifanele

  • hero: Cishe ama-vertices angu-110,000 kuya ku-130,000 ezithombe eziseduze zesinema.
  • high: Cishe ama-vertices angu-65,000 kuya ku-80,000 esilwaneni somdlali. Leli izinga elizenzakalelayo.
  • medium: Cishe ama-vertices angu-25,000 kuya ku-32,000 ekubukweni kwebanga eliphakathi nakumafoni.
  • low: Cishe ama-vertices angu-11,000 kuya ku-15,000 emihlambini yezilwane ezingaba ngu-10 kuya ku-20.
  • crowd: Cishe ama-vertices angu-5,000 kuya ku-8,000 ezixukwini zezilwane ezingaba ngu-100, kusetshenziswa i-draw call eyodwa.

Ungashintsha imininingwane yoboya noma yesikhumba ku-mesh ekhona usebenzisa i-setQuality(). Ezixukwini ezinkulu, hlanganisa izinga le-crowd ne-setLod(2) ukuze unciphise imininingwane yokunyakaza:

const sheep = await createAnimal('sheep', {
  seed: 5,
  quality: 'crowd'
});

sheep.setLod(2);

Imiphumela yokwakha igcinwa ngokuya ngohlobo, i-seed, ikhwalithi, kanye ne-variant. Ngakho umhlambi wezilwane ezingu-100 osebenzisa ama-seed ayisithupha udinga kuphela ukwakhiwa okuyisithupha okuhlukile. Izindleko ze-CPU ezibhaliwe zingama-millisecond angu-0.1 cishe ngesilwane ngasinye ku-frame ngayinye.

Hlela Ama-Web Worker

Ukwakhiwa kwezilwane kuthatha cishe imizuzwana engu-0.4 kuya kwengu-6. Ngokuzenzakalelayo, ukwakha kwenziwa kuma-Web Worker angamamojuli. Uma i-Worker ingatholakali, ilabhulali ibuyela ku-thread ebizayo.

Ukucushwa kwe-Vite

// vite.config.js
export default {
  worker: { format: 'es' },
  build: { target: 'es2022' },
  optimizeDeps: {
    exclude: ['procedural-animals']
  }
};

i-webpack 5 ne-Parcel 2 akudingi ukucushwa okwengeziwe kwama-worker.

Amanye Ama-Bundler

Kwenye i-bundler, hlanganisa i-worker mathupha:

npx esbuild node_modules/procedural-animals/src/worker.js --bundle --format=iife --minify --outfile=public/animal-worker.js

Bese ubhalisa i-factory edala i-worker:

import { setWorkerFactory } from 'procedural-animals';

setWorkerFactory(
  () => new Worker('/animal-worker.js')
);

Ungakhubaza ukwakhiwa kusetshenziswa i-worker ngesilwane esithile, kodwa ukwenza lokho kuvimbela i-thread ebizayo ngesikhathi sonke sokwakha:

const wolf = await createAnimal('wolf', {
  worker: false
});

Lungiselela Izilwane Ukuze Zilayishe Ngokushesha

Kumuntu owaziwayo, yibhake kusenesikhathi ibe yifayela le-.animal. Lokhu kushintsha ukubambezeleka kokwakha ngesikhathi sokusebenza kube ukulayisha, i-README ekulinganisela cishe kuma-millisecond angu-20.

npx procedural-animals-bake wolf --seed 3 --quality high -o public/wolf-3.animal

Landa ifayela elakhiwe njenge-ArrayBuffer bese ulidlulisa ngenketho ethi baked:

const wolf = await createAnimal('wolf', {
  baked: fetch('/wolf-3.animal')
    .then((response) => response.arrayBuffer())
});

Isilwane esibhakiwe kufanele sihambisane nohlobo kanye nokucushwa okulungiselelwe umyalo.

Amathiphu Athuthukile

Sebenzisa Isimo Sokunyakaza Esifundeka Kuphela

Funda i-position, heading, speed, velocity, kanye ne-state ukuze uhlanganise amakhamera, umdlalo, noma izixhumi zokusetshenziswa. Ungayiphathi into eyimpande yesilwane ukuze ukhiqize ukunyakaza.

Namathisela Izinto Emaphoyintini Aqanjwe Amagama

Iqoqo le-attachments linikeza amaphoyinti afana ne-mouth, head, kanye ne-back. Izinyoni ziphinde ziveze izinamathiselo zezinyawo, kanti amahhashi anikeza amaphoyinti ahlobene nokugibela, okuhlanganisa i-seat, ama-stirrup, kanye namabhithi. Beka izinto ezingezwayo kulezi zinto zokunamathisela esikhundleni sokulinganisa mathupha izindawo zazo ezinyakazayo.

Sebenzisa Izilawuli Zokulungisa Nezembozo

I-API yesilwane ihlanganisa setDebug(mode, on) enamamodi athi albedo, weights, material, kanye ne-bare. Sebenzisa setCoverings(on) ukuze uguqule amagobolondo oboya avuleke noma avaleke.

wolf.setDebug('weights', true);
wolf.setCoverings(false);

Bala Indlela Ebheke Ephoyintini

Ngenxa yokuthi i-heading engu-zero ibheke ku-Z ephozithivu, sebenzisa Math.atan2(dx, dz) lapho ubala indlela ebheke kulokho okuqondiswe kukho:

const dx = target.x - wolf.position.x;
const dz = target.z - wolf.position.z;
const heading = Math.atan2(dx, dz);

wolf.move({
  speed: wolf.gears.walk,
  heading
});

Hlanza Izinsiza

Biza i-dispose() lapho isilwane sisuswa unomphela. Lokhu kukhulula izinsiza zaso ze-GPU futhi kusisuse esigcawini.

wolf.dispose();

Okukhishwayo Nemibhalo Ewusizo

Iphakheji eyinhloko iphinde ikhiphe i-listSpecies, loadSpecies, setWorkerFactory, clearBuildCache, kanye ne-QUALITY:

import {
  createAnimal,
  listSpecies,
  loadSpecies,
  setWorkerFactory,
  clearBuildCache,
  QUALITY
} from 'procedural-animals';

Ngenketho ngayinye, idatha yomcimbi, inkambu yesimo, kanye neresiphi, bheka ireferensi ephelele kanye izimemezelo ze-TypeScript zekhosombe.

Isiphetho

i-three.js Procedural Animals inikeza indlela egxile kukhodi yokwengeza izilwane zasendle ezihlukahlukene, ezine-rig, nezinyakazayo kuhlelo lwe-three.js. Qala ngo-createAnimal(), engeza into ebuyisiwe esigcawini, yiqondise nge-API yesilwane, bese uyibuyekeza kanye kuhlaka ngalunye. Ama-worker, ukubhaka, ukugcinwa kwesikhashana okusekelwe ku-seed, kanye namazinga amaningi ekhwalithi kwenza ukuhamba komsebenzi okufanayo kusekele kokubili ukubukwa okuningiliziwe eduze nezixuku ezinkulu.