Sebagai permulaan, izinkan saya mengeluh bahwa "greeble" adalah kata yang mengerikan untuk dibuang dari kamus.
Nah, menghilangkan batu dari jiwa, kita beralih ke penjelasannya. Greeble adalah detail kecil berulang yang ditambahkan ke model untuk memberikan rasa skala dan estetika tertentu. Jamur telah menjadi populer berkat film-film fiksi ilmiah klasik, di mana patung fisik sering menjadi "model":
Jika Anda sudah tahu dari
tutorial ekstrusi saya cara mengusir jerat prosedural, maka Anda mengerti cara menambahkan jamur. Menambahkan
jamur sederhana ke jala dapat dilakukan dengan
mengekstrusi semua poligon jala ke
panjang acak .
Namun, Anda mungkin telah memperhatikan bahwa tutorial di atas hanya melihat mengekstrusi segitiga, sedangkan gambar di awal artikel adalah jamur persegi. Saya harus menyesuaikan mesh sehingga dibagi menjadi empat persegi, dan banyak jerat sering terdiri dari poligon dengan lebih dari tiga indeks. Oleh karena itu, dalam tutorial ini kita akan belajar cara
mengekstraksi poligon dengan indeks n dan menerapkan algoritma ini ke seluruh jala untuk membuat jamur. Kami juga belajar beberapa cara untuk membuat variasi dalam algoritma menjamur untuk mendapatkan hasil yang kurang seragam.
Permukaan normal
Pertama, mari kita cari tahu bagaimana normal suatu poligon dengan indeks n sembarang dihitung. Jika kita dapat berasumsi bahwa poligon ini adalah
planar , yaitu, semua simpulnya berada pada bidang yang sama, maka prosesnya tidak berbeda dengan menghitung normal poligon dengan tiga indeks.
Permukaan normal adalah tegak lurus terhadap permukaan poligon, yang dapat dihitung dengan mengambil
produk vektor dari dua vektor yang menunjuk di sepanjang tepi poligon .
Kemudian kita
menormalkan vektor ini sehingga panjangnya adalah 1, karena dari normal ke permukaan kita hanya perlu arah, bukan panjang.
function getFaceNormal (mesh, poly)
Vec3 v1 = mesh: getVertex (poli [1])
Vec3 v2 = jala: getVertex (poli [2])
Vec3 v3 = jala: getVertex (poli [3])
Vec3 e1 = v2 - v1
Vec3 e2 = v3 - v2
Vec3 normal = e1: cross (e2)
kembali normal: menormalkan ()
akhir
Jika kita tidak dapat dengan yakin berasumsi bahwa poligon adalah planar, maka algoritma yang disajikan di atas lebih memilih bidang di mana dua indeks pertama berada. Untuk representasi yang lebih akurat dari arah titik poligon, kita dapat mengambil
rata -
rata semua produk vektor tepian :
function getFaceNormal (mesh, poly)
Vec3 n = Vec3 (0, 0, 0)
untuk i = 1, #poly -2 do
Vec3 v1 = mesh: getVertex (poli [1])
Vec3 v2 = jala: getVertex (poli [1+ i])
Vec3 v3 = jala: getVertex (poli [2+ i])
n: add ((v2 - v1): cross (v3 - v1))
akhir
return n: normalize ()
akhir
Contoh yang menunjukkan ekstrusi quadrangle planar.Mengekstrusi
Sekarang kami memiliki informasi tentang permukaan normal, kami siap untuk mengusir poligon ke arah normal. Sederhananya, untuk mengekstraksi poligon, kami membuat simpul baru dengan menggerakkan simpul lama ke arah permukaan normal.
Lebih detail:
- Buat puncak baru "di atas" yang lama ke arah normal.
Simpul baru dapat dihitung sebagai berikut:
(posisi puncak lama) + (arah normal)
Ini "menggeser" posisi lama ke arah permukaan normal.
Sebagai contoh, lihat gambar di atas, di atasnya v1 bergerak ke arah normal ke v5. - Buat quadrangles untuk menghubungkan simpul baru dan lama.
Perlu dicatat bahwa untuk setiap indeks dalam poligon baru, satu segiempat baru dibuat.
Sebagai contoh, lihat quad yang dibuat dari v8, v7, v3 dan v4 . - Ganti poligon lama dengan poligon baru yang dibuat oleh simpul baru. Sebagai contoh, lihat quad yang dibuat dari v5, v6, v7 dan v8.
fungsi extrudePoly (mesh, polyIndex, panjang)
int [] poly = mesh.polys [polyIndex]
int [] newPoly = []
Vec3 n = getFaceNormal (mesh, poly)
- (1) Buat verdi diekstrusi
untuk j = 1, #poly do
p = mesh lokal: getVertex (poli [j])
newPoly [#newPoly + 1] = # mesh.verts
- panjang menentukan panjang ekstrusi
mesh: addVertex (p + (n * panjang))
akhir
- (2) Jahit sisi ekstrusi dengan paha depan
untuk j0 = 1, #poly do
j1 lokal = j0% #poly + 1
jala: addQuad (
poli [j0],
poli [j1],
newPoly [j1],
baruPoly [j0]
)
akhir
- (3) Pindahkan wajah yang ada ke vertikal yang diekstrusi
untuk j = 1, #poly do
mesh.polys [pi] [j] = newPoly [j]
akhir
akhir
Jamur seragam.Semua jamur menjamur
Sekarang kita memiliki fungsi getSurfaceNormal () dan fungsi mengusir (), menjamur sangat mudah! Kami cukup
menerapkan fungsi extrude () untuk setiap poligon mesh . Kami menggunakan ekstrusi dengan
panjang acak sehingga setiap poligon yang diekstrusi memiliki ukuran yang sedikit berbeda, yang menciptakan perasaan tekstur. Algoritma yang ditunjukkan di bawah ini diterapkan pada kubus yang disajikan di atas, yang seluruhnya terdiri dari segi empat.
fungsi greeble (jala)
untuk i = 1, # mesh.poli lakukan
- nilai acak ini arbitrer: p
panjang float = acak: getUniformRange (0.1, 1.0)
extrudePoly (jala, i, panjang)
akhir
kembali jala
akhir
Selamat, menjamur kami. Tapi kita bisa berbuat lebih banyak! Sekarang jamur cukup seragam. Berikut adalah dua contoh modifikasi agar lebih menarik.
Modifikasi 1: keberadaan fungling tergantung pada kesempatan
Ini cukup sederhana: hanya menggulung dadu untuk menentukan apakah jamur harus diterapkan pada setiap poligon. Berkat ini, menjamur menjadi kurang seragam. Algoritma yang ditunjukkan di bawah ini diterapkan pada kubus di atas.
untuk i = 1, # mesh.poli lakukan
<strong> jika acak: kebetulan (0,33) maka </strong>
panjang float = acak (0,1, 1,0)
extrudePoly (jala, i, panjang)
akhir
akhir
kembali jala
akhir
Modifikasi 2: Tambahkan Skala Ekstrusi
Ini membutuhkan perubahan algoritma ekstrusi. Ketika kita membuat simpul dari poligon yang diekstrusi, kita dapat
menguranginya ke pusat poligon dengan jumlah acak untuk membuat objek terlihat lebih menarik.
Untuk memulainya, fungsi extrude () kami harus menerima parameter tambahan yang menentukan jumlah penyempitan poligon baru. Kami akan mendefinisikannya sebagai
scale
disebut Vec3. Untuk memindahkan titik menuju pusat, kami
menginterpolasi posisi titik antara
posisi aslinya dan
pusat poligon dengan nilai
scale
.
(Jika Anda perlu mengetahui algoritma untuk menemukan pusat poligon, saya sarankan untuk segera beralih ke
tutorial tentang triangulasi dan membaca tentang triangulasi centroid.)
- temukan pusat poli
Vec3 c = mesh: getFaceCentroid (poli)
untuk j = 1, #poly do
p = mesh lokal: getVertex (poli [j])
newPoly [#newPoly + 1] = # mesh.verts
diri: addVertex (
math.lerp (cx, px, scale.x) + panjang nx *,
math.lerp (cy, py, scale.y) + ny * panjang,
math.lerp (cz, pz, scale.z) + nz * panjangnya
)
mesh: addVertex (p + (n * panjang))
akhir
Sekarang Anda dapat menggunakannya dalam algoritma menjamur dengan penskalaan dengan nilai acak untuk setiap poligon. Jadi kita mendapatkan gambar yang ditunjukkan di atas.
fungsi greeble (jala)
untuk i = 1, # mesh.poli lakukan
panjang float = acak: getUniformRange (0.1, 1.0)
Skala Vec3 = (acak: getUniformRange (0.1, 1.0),
acak: getUniformRange (0,1, 1,0),
acak: getUniformRange (0.1, 1.0))
extrudePoly (mesh, i, panjang, skala)
akhir
kembali jala
akhir
Akhirnya
Bagus, kita sampai akhir! Saya harap tutorial ini bermanfaat bagi Anda.