hai saya seorang pemula yang lengkap di bidang computergraphics, mohon maaf jika ini jawaban yang bodoh. Saya mencoba membuat mesin 3d sederhana dari awal, lebih untuk tujuan pendidikan daripada untuk penggunaan nyata.
untuk saat ini saya hanya menghitung wajah normal. lewat sini:
saya punya objek Permukaan dengan di dalam daftar Segitiga. saya menghitung normals di dalam kelas Triangle, dengan cara ini:
triangle.computeFaceNormals() {
Vec3D u = v1.sub(v3)
Vec3D v = v1.sub(v2)
Vec3D normal = Vec3D.cross(u,v)
normal.normalized()
this.n1 = this.n2 = this.n3 = normal
}
dan saat membangun permukaan:
t = new Triangle(v1,v2,v3)
t.computeFaceNormals()
surface.addTriangle(t)
dan saya pikir ini adalah cara terbaik untuk melakukan itu .. bukan?
sekarang .. ini berhasil, ok. tapi cahaya itu tidak dihaluskan. Saya mencoba menghitung juga vertex normals. (Saya sedang menguji mesin saya dengan permukaan tubolar jadi saya memiliki hampir semua titik dibagi dengan lebih dari satu segitiga)
Saya telah menemukan algoritma sederhana ini: flipcode vertex normal tapi .. hei algoritma ini memiliki .. kompleksitas eksponensial? (Jika ingatan saya tidak gagal latar belakang ilmu komputer saya ..) (bytheway .. itu memiliki 3 loop bersarang .. saya tidak berpikir itu cara terbaik untuk melakukannya ..)
ada saran?
t
adalah hasilcomputeFaceNormals
(yang tidak mengembalikan apa-apa), bukan segitiga.Jawaban:
"Best" sangat subyektif - ini akan melibatkan penimbangan apa yang Anda butuhkan dari algoritma versus inputnya, kompleksitas runtime, dan properti lainnya.
Oleh karena itu, baik pendekatan Anda maupun pendekatan FlipCode yang masuk akal dalam hal menghasilkan hasil yang dapat digunakan (Anda dapat dengan mudah menyalin 'wajah normals' Anda ke setiap titik, jika Anda tidak berbagi contoh titik sebenarnya antara segitiga, yang saya tidak jelas aktif dari kode Anda). Teknik-teknik lain termasuk bobot kontribusi masing-masing wajah normal dengan ukuran sudut yang dibuat dengan masing-masing wajah dibagi oleh vertex.
Anda benar karena pendekatan FlipCode tampak suboptimal seperti yang tertulis, tetapi bisa saja tidak ditentukan dengan baik: sedikit tidak jelas apakah ini bermaksud menyarankan loop kedua melintasi semua wajah dalam model, dibandingkan beberapa wajah yang berbagi simpul yang dimaksud. Jika Anda memiliki informasi adjacency untuk mengurangi ruang pencarian dari loop kedua, itu menjadi kurang menjadi perhatian. Tentu saja Anda mungkin tidak memiliki informasi kedekatan itu - ini adalah apa yang saya maksudkan dengan mempertimbangkan input apa yang Anda miliki untuk algoritma Anda.
Jika Anda tidak hanya ingin menyalin wajah normal ke dalam simpul, atau Anda berbagi simpul dan tidak ingin membaginya, Anda dapat:
Ini mengasumsikan bahwa setiap segitiga sebenarnya mereferensikan masing-masing titik daripada menyimpan salinannya - saya tidak tahu bahasa apa yang Anda gunakan jadi saya tidak tahu apakah itu masalahnya atau tidak.
sumber
Josh Petrie benar. Jika Anda ingin menghitung normals verteks, Anda harus mempertimbangkan kontribusi segitiga dengan sudut. Tetapi Anda dapat menggunakan solusi naif dan hanya menjumlahkan semua normals dari semua wajah di sekitar vertex.
Jadi, Anda hanya menghitung semua wajah normal dan menormalkannya. Kemudian atur semua vertex normals ke nol. Kemudian untuk setiap wajah (segitiga) tambahkan normalnya ke semua simpulnya. Kemudian normalisasikan semua vertex normals. Dan sudah selesai.
Itu tidak terlalu benar tetapi itu bisa cukup.
Dan perhitungan normal wajah Anda di atas - itu benar tetapi Anda harus sadar, di mana kepala normal. Itu bisa naik atau turun. Itu tergantung pada produk silang - AxB tidak sama dengan BxA - itu memberi Anda vektor yang berlawanan.
sumber
Mari kita asumsikan bahwa kita memiliki kubus yang terbuat dari 6 persegi panjang. Kita sudah tahu bahwa vertex normal untuk sebuah kubus bukan jumlah normal dari koneksi karena tepi yang tajam. Jika Anda membangun peta nilai titik dan itu normals vertex yang berbeda untuk sebuah kubus Anda berakhir dengan 3 normals untuk setiap titik.
Mempertahankan poin di atas dalam pikiran ini adalah bagaimana saya menghitung vertex normals (Saya telah mengujinya dan saya menggunakannya).
Setiap wajah melacak vertex normals untuk digunakan karena dua wajah mungkin berbagi verteks tidak berarti vertex normal akan sama untuk setiap wajah.
Mari kita asumsikan kita sedang mencoba menghitung titik normal untuk vert ketika rendering face2 .
vert dibagi oleh face0 , face1 , face2 , face3 dan face4 . Semua wajah di atas adalah tetangga dalam rangka dan face0 dan face4 connect untuk membentuk lingkaran.
Vertex normal untuk vert adalah jumlah dari semua rantai tetangga yang terhubung untuk menghadapi 2 dinormalisasi. Rantai berhenti jika sudut antara dua wajah bertetangga lebih dari 0,8 radian (sudut == arccos (crossProduct (faceA.surface_normal, faceB.surface_normal))).
jika sudut antara face0 dan face1 lebih dari 0,8 radian dan sudut antara face3 dan face4 lebih dari 0,8 radian dari titik normal untuk vert saat rendering face2 adalah menormalkan ( surfnormal1 + surfnormal2 + surfnormal3 ).
sumber