Dalam profiler saya, menemukan koordinat barycentric tampaknya agak macet. Saya ingin membuatnya lebih efisien.
Ini mengikuti metode di shirley , di mana Anda menghitung luas segitiga yang dibentuk dengan menyematkan titik P di dalam segitiga.
Kode:
Vector Triangle::getBarycentricCoordinatesAt( const Vector & P ) const
{
Vector bary ;
// The area of a triangle is
real areaABC = DOT( normal, CROSS( (b - a), (c - a) ) ) ;
real areaPBC = DOT( normal, CROSS( (b - P), (c - P) ) ) ;
real areaPCA = DOT( normal, CROSS( (c - P), (a - P) ) ) ;
bary.x = areaPBC / areaABC ; // alpha
bary.y = areaPCA / areaABC ; // beta
bary.z = 1.0f - bary.x - bary.y ; // gamma
return bary ;
}
Metode ini berhasil, tetapi saya sedang mencari yang lebih efisien!
barycentric-coordinates
bobobobo
sumber
sumber
Jawaban:
Ditranskrip dari Deteksi Tabrakan Real-Time Christer Ericson (yang, kebetulan, adalah buku yang sangat bagus):
Ini adalah aturan Cramer yang efektif untuk menyelesaikan sistem linear. Anda tidak akan mendapatkan jauh lebih efisien daripada ini — jika ini masih merupakan hambatan (dan mungkin saja: itu tidak terlihat seperti jauh lebih baik dari algoritma saat ini), Anda mungkin harus mencari tempat lain untuk mendapatkan speedup.
Perhatikan bahwa sejumlah nilai yang layak di sini tidak bergantung pada p —mereka dapat di-cache dengan segitiga jika perlu.
sumber
p
untuk fungsi ini.Aturan Cramer harus menjadi cara terbaik untuk menyelesaikannya. Saya bukan seorang pria grafis, tetapi saya bertanya-tanya mengapa dalam buku Deteksi Tabrakan Real-Time mereka tidak melakukan hal sederhana berikut ini:
Ini secara langsung memecahkan sistem linier 2x2
sedangkan metode dari buku memecahkan sistem
sumber
.z
dimensi ketiga ( ) (khususnya, bahwa itu tidak ada)?Sedikit lebih cepat: Precompute penyebutnya, dan lipat gantinya dengan membagi. Divisi jauh lebih mahal daripada perkalian.
Dalam implementasi saya, bagaimanapun, saya cache semua variabel independen. Saya pra-kalk berikut di konstruktor:
Jadi kode akhir terlihat seperti ini:
sumber
Saya akan menggunakan solusi yang diposting John, tetapi saya akan menggunakan SSS 4.2 dot intrinsic dan sse rcpss intrinsik untuk membagi, dengan asumsi Anda ok membatasi diri ke Nehalem dan proses yang lebih baru dan presisi terbatas.
Atau Anda bisa menghitung beberapa koordinat barycentric sekaligus menggunakan sse atau avx untuk speedup 4 atau 8x.
sumber
Anda dapat mengubah masalah 3D Anda menjadi masalah 2D dengan memproyeksikan salah satu bidang yang selaras sumbu dan menggunakan metode yang diusulkan oleh user5302. Ini akan menghasilkan koordinat barikentrik yang sama persis selama Anda memastikan segitiga Anda tidak terproyeksi menjadi garis. Yang terbaik adalah memproyeksikan ke bidang sejajar sumbu yang sedekat mungkin dengan orientasi triagle Anda. Ini menghindari masalah co-linearitas dan memastikan akurasi maksimum.
Kedua, Anda dapat melakukan pra-komputasi penyebut dan menyimpannya untuk setiap segitiga. Ini menyimpan perhitungan sesudahnya.
sumber
Saya mencoba untuk menyalin kode @ NielW ke C ++, tetapi saya tidak mendapatkan hasil yang benar.
Lebih mudah untuk membaca https://en.wikipedia.org/wiki/Barycentric_coordinate_system#Barycentric_coordinates_on_triangles dan menghitung lambda1 / 2/3 sebagaimana diberikan di sana (tidak diperlukan fungsi vektor).
Jika p (0..2) adalah Poin dari segitiga dengan x / y / z:
Precalc untuk segitiga:
maka lambda untuk "titik" Point adalah
sumber
Untuk titik tertentu N di dalam segitiga ABC, Anda bisa mendapatkan bobot barikentrik titik C dengan membagi area subtriangle ABN dengan total luas segitiga AB C.
sumber