Oluşturulan Geometri için Yüzey Normallerini Hesaplama


12

Arama kodundan girişler dayalı bir 3D şekil üreten bir sınıf var. Girdiler uzunluk, derinlik, ark vb. Yandığında, şeklimin hesaplanan yanlış yüzey normallerinden çok tuhaf renklendirme / doku var. Tüm araştırmalarımdan matematiğimin doğru olduğuna inanıyorum, teknik veya yöntemimle ilgili bir sorun var gibi görünüyor.

Yüksek bir seviyede, üretilen bir şekil için yüzey normallerinin programlı olarak hesaplanması nasıl yapılır? Kodum için iOS'ta Swift / SceneKit kullanıyorum, ancak genel bir cevap iyi.

Şeklimi temsil eden iki dizim var. Bunlardan biri, şekli oluşturan köşeleri temsil eden bir 3B nokta dizisidir. Diğer dizi, köşeleri üçgenlerle eşleyen ilk dizinin dizinlerinin listesidir. Bu veri almak ve şekil aydınlatma yardımcı yüzey normalleri bir dizi 3. bir dizi oluşturmak gerekir. ( SCNGeometrySourceSemanticNormalSceneKit`e bakınız )

Köşeler ve dizinler listesi, sınıfa girişlere bağlı olarak her zaman farklıdır, bu yüzden yüzey normallerini önceden hesaplayamaz veya sabit kodlayamam.


Daha fazla içeriğe ihtiyacınız var. Parametrik bir yüzey için analitik normalleri hesaplamaya mı çalışıyorsunuz? Örtük bir yüzey? Yoksa jenerik üçgen örgülerden normalleri hesaplamak ister misiniz? Veya başka bir şey?
Nathan Reed

Teşekkürler, daha fazla ayrıntı ekledim. Sorunuzu cevaplamak için, genel bir üçgen ağdan normalleri hesaplamam gerekiyor. Ağın girdilere bağlı olarak farklı olduğu açık olsa da. Benim şeklim bir 3D ok, burada bir örnek olarak 2 farklı formun (radyal ve doğrusal) bir ekran görüntüsü. Sınıf, örgünün genişliğini, derinliğini, uzunluğunu, yayını ve yarıçapını istendiği gibi değiştirir. cl.ly/image/3O0P3X3N3d1d Bunu çözme konusundaki zayıf girişimlerimle aldığım garip aydınlatmayı görebilirsiniz.
macinjosh

3
Kısa versiyon: her bir tepe noktasını, ona değen tüm üçgenlerin normallerinin normalleştirilmiş toplamı olarak normal olarak hesaplayın. Ancak, bu her şeyi pürüzsüzleştirecektir, bu da bu şekil için istediğiniz şey olmayabilir. Daha sonra tam bir cevaba geçmeye çalışacağım.
Nathan Reed

Benim için düzgün olan bu!
macinjosh

4
Çoğu durumda, tepe konumlarını analitik olarak hesaplarsanız, normalleri analitik olarak da hesaplayabilirsiniz. Parametrik bir yüzey için, normaller iki gradyan vektörünün çapraz ürünüdür. Üçgen normallerin ortalamasını hesaplamak sadece bir yaklaşımdır ve genellikle görsel olarak çok daha düşük kalitede sonuç verir. Bir cevap gönderirim, ancak zaten SO'ya ( stackoverflow.com/questions/27233820/… ) ayrıntılı bir örnek gönderdim ve burada çoğaltılmış içerik isteyip istemediğimizden emin değilim.
Reto Koradi

Yanıtlar:


10

Tamamen pürüzsüz sonuçlar istemezsiniz. Nathan Reed tarafından yorumlanan yöntem: "Her tepe noktasını normal yüze hesaplayın, toplayın, toplamı normalleştirin", genellikle işe yaradığında bazen muhteşem bir şekilde başarısız olur. Ancak burada bir önemi yok, bu yöntemi bir reddetme maddesi ekleyerek kullanabiliriz.

Bu durumda, bazı parçaların diğer parçalara karşı düzeltilmesini istemezsiniz. Seçici sert kenarlar istiyorsunuz. Böylece örneğin düz üst ve alt, her bir düz alanda olduğu gibi yandaki üçgen şeritten ayrıdır.

Biz peşindeyiz resim

Resim 1 : İstediğiniz sonuç.

Aslında sadece kavisli alanın köşelerini ortalamak istersiniz, diğer herkes sadece üçgenlerinden aldıkları normali kullanabilir. Bu yüzden örgüyü, diğerleri olmadan ele alınan 9 ayrı bölge olarak düşünmek daha iyidir.

Mesh ve normaller gösteriliyor]

Resim 2 : Ağ yapısını ve normalleri gösteren resim.

Bunu, normal birincil köşelerden belirli bir açının dışında olan normalleri dahil etmeyerek otomatik olarak çıkarabilirsiniz. pseudocode:

For vertex in faceVertex:
    normal = vertex.normal
    For adjVertex in adjacentVertices:
        if anglebetween(vertex.normal, adjVertex.normal )  < treshold:
            normal += adjVertex.normal
    normal = normalize(normal)

Bu işe yarıyor, ancak yaratım zamanında bunların hepsinden kaçınabilirsiniz, çünkü ayrı uçakların farklı çalıştığını anlıyorsunuz. Bu nedenle, yalnızca kavisli tarafların normal yönde birleştirilmesi gerekir. Ve aslında onları doğrudan altta yatan matematiksel şekilden hesaplayabilirsiniz.


10

Oluşturulan bir şekil için normalleri hesaplamanın üç yolunu görüyorum.

Analitik normaller

Bazı durumlarda, normalleri üretmek için yüzey hakkında yeterli bilgiye sahip olabilirsiniz. Örneğin, bir küre üzerindeki herhangi bir noktanın normal değeri hesaplamak önemsizdir. Basitçe söylemek gerekirse, fonksiyonun türevini bildiğinizde, normali de bilirsiniz.

Durumunuz analitik normalleri kullanmanıza izin verecek kadar darsa, muhtemelen hassasiyet açısından en iyi sonucu verecektir. Yine de teknik çok iyi ölçeklenmiyor: Analitik normalleri kullanamayacağınız vakaları da ele almanız gerekiyorsa, genel durumu ele alan ve analitiği tamamen düşüren tekniği tutmak daha kolay olabilir.

Köşe normalleri

İki vektörün çapraz çarpımı ait oldukları düzleme dik bir vektör verir. Yani bir üçgenin normalini almak basittir:

vec3 computeNormal(vec3 a, vec3 b, vec3 c)
{
    return normalize(crossProduct(b - a, c - a));
}

Ayrıca, yukarıdaki örnekte, çapraz ürünün uzunluğu, abc içindeki alanla orantılıdır . Böylece, birkaç üçgenle paylaşılan bir tepe noktasında düzeltilmiş normal, çapraz ürünlerin toplanması ve son adım olarak normalleştirilmesi, böylece her üçgenin alanı ile ağırlıklandırılmasıyla hesaplanabilir.

vec3 computeNormal(vertex a)
{
    vec3 sum = vec3(0, 0, 0);
    list<vertex> adjacentVertices = getAdjacentVertices(a);
    for (int i = 1; i < adjacentVertices; ++i)
    {
        vec3 b = adjacentVertices[i - 1];
        vec3 c = adjacentVertices[i];
        sum += crossProduct(b - a, c - a);
    }
    if (norm(sum) == 0)
    {
        // Degenerate case
        return sum;
    }
    return normalize(sum);
}

Dörtlülerle çalışıyorsanız, kullanabileceğiniz güzel bir hile vardır: bir dörtlü abcd için kullanın crossProduct(c - a, d - b)ve dörtlü aslında bir üçgen olan güzel durumları ele alacaktır.

: Iñigo QUILEZ konu üzerine birkaç kısa makaleler yazdı zeki bir örgü normalleşmesini ve normal ve n alan poligonları taraflı .

Kısmi türevlerden normaller

Kısmi türevlerden fragman gölgesinde normaller hesaplanabilir. Arkasındaki matematik aynıdır, ancak bu süre ekran alanında yapılır. Angelo Pesce'nin bu makalesi tekniği açıklar: Normalsiz normaller .


1
Dördüncü bir yol var, sanatçı normalleri sağladı;)
joojaa

@joojaa: Sanırım normal haritalardan bahsediyorsun? Başka türlü elle yazılmış normalleri hiç duymadım.
Julien Guertault

1
Hayır, elle yazılmış normaller. Bazen sanatçılarınızın normallerin nasıl davranması gerektiği hakkında programcıların modellerinden daha fazla şey bildikleri görülür. Normalin altında yatan hesaplamalardan kaynaklandığını varsayarsak, hesaplama motorları için bazen biraz sorunlu olabilir. Ama kesinlikle olur ve matematiksel modellemede çok zaman kazanırsınız.
joojaa

1
Bunlara bazen "açık normaller" (3ds max ve maya terminolojisi) denir.
Dusan Bosnjak 'pailhead'
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.