Generasi Geometri Prosedural

10

Saya baru-baru ini mencari di SceneKit untuk OS X dan memperhatikan bahwa ada beberapa metode pabrik untuk membuat bentuk geometris seperti:

Kotak, Kapsul, Kerucut, Silinder, Pesawat, Piramida, Bola, Torus dan Tabung.

Saya tertarik untuk menambahkan bentuk-bentuk primitif seperti itu kepada penyaji saya, tetapi saya berjuang untuk menemukan sumber yang masuk akal dari mana saya dapat mengumpulkan pemahaman tentang generasi prosedural. Ada beberapa sumber yang merinci teorinya, tetapi tidak memiliki kode sumber yang sesuai untuk mendukungnya.

SceneKit menyediakan metode pabrik yang memungkinkan untuk secara dinamis mengatur atribut dari bentuk-bentuk tersebut. Dalam hal Kotak, Anda dapat memberikan nilai integer untuk jumlah segmen lebar, tinggi dan kedalaman yang harus dibagi oleh setiap wajah.

Saya mengerti teori tetapi tidak memiliki pengetahuan untuk mulai membagi wajah geometri untuk mencapai efek yang diinginkan.

Verteks untuk setiap bentuk kemungkinan besar cukup mudah untuk dibuat dalam loop sederhana. Yang membuat saya bingung adalah mengetahui cara membuat wajah, atau lebih tepatnya koordinat tekstur yang sesuai untuk setiap wajah. Normalnya dapat dihitung per wajah jadi saya cukup yakin saya bisa mencapai apa yang saya inginkan, itu hanya tahu harus mulai dari mana.

Adakah yang bisa memberikan rincian tentang geometri prosedural? Yang benar-benar saya butuhkan adalah beberapa kode sumber untuk mendapatkan beberapa informasi dari. Saya telah mencari tinggi dan rendah untuk tutorial tetapi sejauh ini hanya muncul dengan beberapa situs atau blog yang masuk akal. Buku, tutorial, blog, atau makalah penelitian yang bagus akan dihargai.

Edit berdasarkan komentar

Saya seharusnya mengklarifikasi bahwa saya tahu cara membuat simpul untuk bentuk dasar, sebagian besar mungkin dapat dicapai dengan loop sederhana. Apa yang tidak saya pahami adalah bagaimana membuat wajah dari array simpul yang dihasilkan. Bagaimana cara membuat strip segitiga, atau segitiga, dari berbagai simpul yang tampaknya tidak berurutan?

Saya berasumsi bahwa setelah saya melewati titik ini, saya dapat membuat normals dari setiap wajah. Sementara saya belum menyelidiki ini, saya telah melihat banyak referensi untuk ini dan saya yakin itu akan cukup mudah untuk diterapkan.

Idealnya, saya ingin dapat menghasilkan geometri dari sekumpulan properti tertentu seperti cara yang disediakan SceneKit. Mengingat SceneKit telah melakukannya, dan Anda dapat melakukan hal serupa di Blender dan Maya dll, saya berasumsi saya tidak mencoba mengimplementasikan yang tidak mungkin.

Aspek terakhir akan menerapkan tekstur. Sekali lagi, ini bukan sesuatu yang telah saya terapkan tetapi telah membaca dan mengetahui persyaratannya.

Masalah utama di sini adalah bahwa saya tahu apa yang ingin saya capai tetapi saya sedang berjuang untuk menguraikan bagaimana menerapkan untuk primitif tersebut di atas. Saya berharap bahwa saya akan dapat menemukan beberapa kesamaan pengetahuan melalui kode sumber tapi saya benar-benar belum menemukan sesuatu yang cocok sejauh ini.

KaptenRedmuff
sumber
Anda mengatakan bahwa masalah Anda adalah membagi geometri, tetapi kemudian Anda mengatakan membuat simpul seharusnya mudah, dan kemudian Anda mengatakan masalah Anda adalah bagaimana membuat wajah, dan kemudian Anda mengatakan bahwa masalah Anda adalah pemetaan tekstur. Apa masalahmu? Bisakah Anda menghasilkan posisi titik? Bisakah Anda menghasilkan tepi dan wajah? Juga, koordinat tekstur tergantung pada tekstur Anda dan apa yang ingin Anda capai dengan itu, jadi pertanyaan tentang koordinat tekstur bukanlah yang baik. Akhirnya, generasi primitif hanyalah tentang geometri dan orang-orang jarang menyebutnya "prosedural geometri" meskipun itulah yang sebenarnya.
jrsala
Saya mengerti bagaimana membuat geometri untuk bentuk-bentuk sederhana seperti kubus atau bidang, dengan penciptaan wajah yang tidak saya pahami. Bagaimana cara membuat wajah dari sekelompok simpul? Merencanakan poin untuk bentuk yang lebih kompleks adalah bagian dari masalah walaupun saya memiliki pemahaman dasar. Merekatkan mereka menjadi satu strip segitiga atau segitiga adalah apa yang aku berjuang untuk membungkus kepalaku.
CaptainRedmuff
OK, terima kasih untuk detailnya. Anda mungkin ingin mengedit pertanyaan Anda untuk menjelaskan. Menjawab waktu!
jrsala

Jawaban:

11

Cara untuk menghasilkan tepi dan wajah dari bentuk primitif seperti kotak, kerucut dan semua yang Anda kutip adalah untuk menghasilkan mereka pada saat yang sama saat Anda membuat simpul. Bahkan, Anda harus membuat simpul dengan cara logis yang membuatnya mudah untuk menghitung tepi dan wajah sesuai.

Ada algoritma yang mengambil sebagai input satu set titik dalam ruang dan menghitung apa yang disebut " set triangulasi titik " di atasnya, tetapi masalah triangulasi titik set adalah NP-lengkap , sehingga lebih cepat untuk membuat tepi dan wajah saat Anda pergi daripada hanya menghitung simpul dan biarkan algoritma melakukan pekerjaan. Hanya memberi tahu Anda bahwa solusi ini ada.

Terlepas dari solusi yang tidak efisien ini, saya rasa Anda hanya dapat memperlakukan primitif berdasarkan kasus per kasus, seperti pada contoh berikut.

Jala adalah simpul dan wajah . Tepinya terkandung dalam deskripsi wajah kecuali jala Anda berisi garis-garis yang tidak membentuk wajah. Verteks adalah tupel dari 3 koordinat floating-point. Tepi hanyalah pasangan referensi ke simpul, tetapi sekali lagi Anda pasti tidak akan membutuhkannya. Katakan misalnya bahwa simpul Anda dalam array yang diindeks. Nah tepi Anda kemudian bisa menjadi pasangan indeks array itu. Wajah adalah kembar tiga referensi untuk simpul atau kembar tiga indeks dalam kasus array yang diindeks .

Anda harus dapat menghitung simpul, tepi dan wajah yang membentuk masing-masing bentuk primitif ini karena dapat menghitungnya berarti memahami sifat-sifat objek yang membantu Anda merancang metode yang akan Anda buat, menggunakan loop dan alat lain seperti yang akan kita lihat.

Kerucut

Untuk kerucut dengan simpul n + 2 , tepi 3n dan wajah 2n :

  1. Buat dua simpul terpisah.
  2. Buat lingkaran di sekitar salah satu simpul (simpul dasar), yang berada di dalam bidang yang tegak lurus ke segmen antara dua simpul pertama. Semoga Anda bisa membuat lingkaran menggunakan trigonometri, bukan? Itu sudah semua simpul kerucut. Itu juga sepertiga dari semua tepi (ada n tepi dalam lingkaran dan total 3n ).
  3. Buat n tepi dari simpul dasar ke n simpul dalam lingkaran. Anda dapat membuat satu setengah dari wajah (itu n wajah) saat Anda melakukannya.
  4. Membuat n tepi dari ujung vertex ke n simpul dalam lingkaran. Anda dapat membuat separuh wajah lainnya (yaitu n wajah) saat Anda melakukannya.

1) Dua simpul 2) dan sebuah lingkaran
3) dan wajah
4) dan wajah
Hasil akhir:hasil

Anda juga dapat membuat tepi dan wajah saat Anda menjalankan lingkaran yang membuat lingkaran. Kompleksitas yang sama, hal yang sama. Buat satu simpul pada lingkaran, simpan ke dalam array simpul Anda, tambahkan tepi yang sesuai (sepasang indeks) ke array pasang indeks jika Anda mau, dan akhirnya tambahkan wajah yang sesuai ke array kembar tiga indeks Anda. . Pindah ke simpul berikutnya.

Silinder dan tabung: tidak melakukan pekerjaan yang sama dua kali, dan paha depan

Sekali lagi, untuk tabung dimulai dengan simpul dan lingkaran yang akan menjadi pusat cakram atas atau bawah silinder:

  1. Buat simpul.
  2. Buat lingkaran di sekitar simpul. Tambahkan tepi (jika Anda ingin tepi) antara simpul lingkaran berturut-turut dan antara simpul tengah dan setiap simpul lingkaran. Tambahkan wajah antara setiap triplet simpul yang terbuat dari simpul tengah dan dua simpul berturut-turut pada lingkaran.
  3. Gandakan semua itu, terjemahkan salinan ke arah tegak lurus ke dasar yang baru saja Anda buat, dengan panjang silinder yang diinginkan.
  4. Tautkan bagian atas dan bawah.

Untuk menghubungkan bagian atas dan bawah, Anda harus membuat paha depan antara pasangan pasang simpul yang saling berhadapan. Jadi pikirkan dulu dan mengapa tidak menjadikan diri Anda fungsi yang membuat dua wajah segitiga dari empat simpul?

Selesai Perhatikan bahwa kali ini kami menggunakan fakta bahwa struktur yang sama (lingkaran + pusat) muncul dua kali dalam sebuah silinder untuk mengambil jalan pintas. Kita tidak harus membuat semua simpul, tepi dan wajah dengan tangan, bertentangan dengan kerucut di mana itu diperlukan.

Mengikuti prinsip kemalasan ini, dimungkinkan juga untuk hanya membuat seperempat lingkaran dan menduplikasinya, dan sekali lagi, untuk membuat lingkaran penuh dengan transformasi yang sangat sederhana (berlaku dengan lingkaran apa pun dengan kerucut juga), tapi itu benar-benar berlebihan untuk sebuah bentuknya tidak begitu rumit.

Anda harus selalu menggunakan properti geometris dari objek yang Anda buat untuk menyederhanakan pembuatannya . Yakni, simetri dan invarian mereka .

Untuk sebuah silinder, jangan membuat simpul dasar, buat lingkaran, duplikat, terjemahkan salinan, buat paha depan, selesai.

Bola dan kapsul: menambah kompleksitas, masih belum berfungsi sama dua kali

Untuk membuat kapsul, kami ingin membuat bola UV, membaginya menjadi dua bagian, menerjemahkan bagian pertama dan kemudian menghubungkan keduanya dengan sisi kapsul.

Sekali lagi dimungkinkan untuk membuat hanya seperdelapan (!!) bola, lalu menduplikasi dan membalikkannya, dan kemudian menggandakan dan membalikkan hasilnya kecuali di sepanjang sumbu lain, dll, untuk mendapatkan bola penuh, dalam 4 langkah (buat kedelapan , duplikat dan balikkan tiga kali). Mungkin berlebihan, tetapi kurang dari pada kasus lingkaran.

Bola UV sederhana:
bola

Kami sebenarnya hanya membuat setengahnya (misalnya), menduplikasi setengahnya, membalikkan salinannya dan menerjemahkannya dengan panjang kapsul:
bagian

Kami menautkan bagian atas dan bawah:
kapsul

Kerja keras (agak) nyata berasal dari trigonometri yang digunakan untuk membuat bola. Himpunan semua simpul yang dimiliki bola UV dapat digambarkan sebagai himpunan semua titik bentuk:

poin

di mana R adalah jari-jari bola dan, untuk N bilangan bulat positif tertentu , kita memiliki konstanta

θ = × π / N ,

k dan n adalah bilangan bulat dengan k bervariasi dari 0 hingga 2N-1 dan n bervariasi dari -N / 2 hingga + N / 2 .

Untuk membuat setengah bola atau sepersepuluh bola, Anda harus membatasi sekumpulan nilai yang diambil oleh k dan n .

Jika k adalah bilangan real dan bukan hanya bilangan integer, Anda akan mendapatkan seluruh bidang, bukan hanya simpul pada permukaannya. Jadi apa yang kami lakukan di sini adalah merasterisasi persamaan permukaan primitif .

Torus yang menakutkan : mudah setelah semua yang kita lihat!

Sekali lagi, lebih banyak trigonometri, lebih banyak simpul, lebih banyak paha depan, lebih banyak simetri, lebih banyak invarian ... lebih banyak geometri! Cari tahu persamaan untuk permukaan torus, "rasterize it" dengan benar, sederhanakan masalah menggunakan simetri torus (yang jelas) dan, akhirnya, loop melalui set simpul yang baru saja Anda tetapkan dan jadikan tepi dan wajah seperti yang Anda inginkan. Pergilah!

Lihat? Benar-benar mudah.

jrsala
sumber
Wow. Terima kasih atas tanggapan terperinci dan untuk banyak contoh. Saya belum mempertimbangkan ide hanya menghasilkan setengah dari bola dan mencerminkan elemen simetris. Terima kasih banyak telah meluangkan waktu untuk menulis ini dengan cara yang saya dapat dengan mudah mengerti dan mudah-mudahan dipraktikkan dengan mudah.
CaptainRedmuff
Sama-sama! Maaf, tidak ada kode.
jrsala
Garis besar metode lebih dari apa yang saya butuhkan sebenarnya. Saya bisa mulai menyusun rencana aksi setidaknya dari sana:] Saya kira Anda tidak memiliki informasi tentang Boxes / Cubes dengan tepi yang dilingkari? docs.autodesk.com/3DSMAX/15/ENU/3ds-Max-Help/images/…
CaptainRedmuff