Arazi üretimi için bir Octree oluşturmak


9

Daha önce bir IsoSurface oluşturmak için yürüyen küpler / tetrahedra kullandım. İşe yaradı ( YouTube ), ancak görüntüleme mesafesine göre değişken Ayrıntı Düzeyi uygulamak için hiç uğraşmadığım için performans çok kötüydü (hatta eski, uzaktaki parçaları kaldırıyordu).

Bu sefer başka bir gidip düzgün yapmaya karar verdim. Ben ne zaman Build()denir aşağıdaki gibi çalışan bir OctreeNode oluşturarak başladım .

  • Öbek yapılamayacak kadar küçükse, hemen geri dönün.
  • Yüzey bu yığının hacminden geçerse çalışın.
  • Öyleyse, LOD'u yükseltmek isteyip istemediğimize karar verin (kamera yakın olduğu için)
  • Eğer öyleyse, 8 çocuk doğurun ve aynı süreci onlara çağırın
  • Değilse, geçerli düğümün boyutlarını kullanarak ağı oluşturun

Bazı PseudoCode:

OctNode Build() {
    if(this.ChunkSize < minChunkSize) {
        return null;
    }
    densityRange = densitySource¹.GetDensityRange(this.bounds);
    if(densityRange.min < surface < densityRange.max) {
        if(loDProvider.DesiredLod(bounds > currentLoD) {
            for(i 1 to 8) {
                if(children[i] == null) {
                    children[i] = new OctNode(...)
                }
                children[i] = children[i].Build();
            }
        } else {
            BuildMesh();
        }
        return this;
    }
}

¹ Yoğunluk kaynağı bir noktadaki geri dönüş yoğunluğunun yanı sıra belirli bir hacim için olası yoğunluk aralığını belirleyebilir.

² LoD sağlayıcı bir sınırlayıcı kutu alır ve kamera konumu / frustum, kullanıcı ayarları vb.

Yani ... Tüm bunlar gayet iyi çalışıyor. Yoğunluk kaynağı olarak basit bir küre kullanma ve tüm düğümleri gösterme:

Tam Octree

Ve sadece yapraklar:

Sadece yaprakları gösteren Octree

Ancak, birkaç sorun var:

  • İlk sınırlama hacmini tanımlamam gerekiyor (ve ne kadar büyükse, daha fazla işlem yapmam gerekir)
  • Ağacın kökünde, yaprakların ne kadar derin olacağı hakkında hiçbir fikrim yok, bu yüzden LoD numaralandırmam en düşük kalitede (kök) başlar ve parçalar küçüldükçe artar. LoD artık başlangıç ​​hacmine göreli olduğundan, belirli boyutlarda / niteliklerde bir şeyler yapmak istediğimde çok fazla kullanılmıyor.

Birkaç seçenek düşündüm ama her ikisi de kusurlu görünüyor:

  • Octrees koleksiyonunu koruyun ve mesafeye bağlı olarak ekleyin / kaldırın. Güzelce nasıl birbirine geçeceğimi göremiyorum¹, ayrıca özellikle boş 3D yüzeyler istiyorsanız (boş hacimleri tekrar tekrar hesaplamaktan kaçınmak için) bilinen boş düğümlerin bir listesine ihtiyacım var
  • Geçerli köke bir üst Düğüm ekleyin, ardından orijinal düğüm için yedi kardeş ekleyin. Bu işe yarayacak ve talep üzerine olacaktı, ancak oyuncu manzara boyunca hareket ettikçe mantıklı bir şekilde küçülmek karmaşık görünüyor. Ayrıca LoD sayılarını daha az anlamlı hale getirecektir.

¹ [Aşağıdaki Q'ya açıklık olarak] Şu anda, ağaçtaki fiziksel olarak bitişik 2 düğüm farklı LOD'larda ise, kafesler oluşturulduğunda dikiş olmadığı için vertsleri zorlamak için bazı kodlarım var. Bunu çevreleyen düğümlerin çoğunun yoğunluğunu bilerek yapabilirim. Yan yana 2 bağımsız oktuğum olduğu bir senaryoda, bu bilgileri almanın kolay bir yolu olmaz ve dikişlerle sonuçlanır.

Buna yaklaşmanın en uygun yolu nedir?

Yanıtlar:


1

Soruyu tam olarak cevapladığımdan emin değilim, bu yüzden segmentlerde cevap vereceğim ve belirli bir sorunun ayrıntıları hakkında bir yanlış anlama varsa yorumlarda cevap vermekten çekinmeyin.

İlk sınırlama hacmini tanımlamam gerekiyor (ve ne kadar büyükse, daha fazla işlem yapmam gerekir)

Durum böyle olmalı. Octree granülerlik katlanarak katlanarak arttığından, en üste birkaç seviye eklemek performans vuruşunda çok küçük bir net artış olmalıdır.

Ağacın kökünde, yaprakların ne kadar derin olacağı hakkında hiçbir fikrim yok, bu yüzden LoD numaralandırmam en düşük kalitede (kök) başlar ve parçalar küçüldükçe artar. LoD artık başlangıç ​​hacmine göreli olduğundan, belirli boyutlarda / niteliklerde bir şeyler yapmak istediğimde çok fazla kullanılmıyor.

Kök oktree'nizi "yeterince büyük bir değere" sabitlerseniz, "başlangıç ​​hacmine göre LoD" bir sorun olmamalıdır. Yukarıda da belirtildiği gibi, üstte ekstra seviyeye sahip olmanın genel performansı etkileyeceğini düşünmüyorum.

Octrees koleksiyonunu koruyun ve mesafeye bağlı olarak ekleyin / kaldırın. Güzelce nasıl birbirine geçeceğimi göremiyorum, ayrıca özellikle boş 3D yüzeyler istiyorsanız (boş hacimleri tekrar tekrar hesaplamaktan kaçınmak için) bilinen boş düğümlerin bir listesine ihtiyacım var

Anladığım kadarıyla, bu önerilen çözüm daha önce ayrıntılı bir alandan uzaklaşırken LoD'yi düşürmekle ilgilidir. Ben "artan LoD" kod yoluna çok benzer görünmesi gerektiğini anlıyorum:

if (loDProvider.DesiredLod(bounds) <(is a lot less than)< currentLoD) { 
    for(i = 1 to 8) { 
        children[i].Destroy();
    }
    BuildMesh();
}

Daha sonra, uzaktaki düğümleri kontrol etmek için çok fazla zaman harcamıyorsunuz çünkü uzaktaki tüm yüksek çözünürlüklü düğümlerin kaldırılacağı için çok fazla "aktif" düğüm bulunmadığına güvenebilirsiniz.


Küçük düğümlerin kaya ölçeği olduğunu varsayarsak, bu bir kıta boyunca seyahat ederken yüzlerce seviye olmasa bile onlarca potansiyel anlamına gelir

Bence octree'nin logaritmik ölçeği onu hala uygulanabilir kılıyor. En üst düzey 1,000,0000,000 m genişliğinde ise (bu gerçek Dünya'ya göre 25 kat daha geniş olurdu ve 625x yüzey alanı ile birlikte) ve en düşük düzey bit olduğu octree, 32 seviyeleri olduğunu, karşısında 10cm olan muhtemelen yeterince yönetilebilir. Dünya'dan 100 kat daha geniş (ve 10000 kat daha fazla yüzey alanına sahip) bir gezegen istiyorsanız, bu oktree'nizde sadece 3-4 seviye daha. Bu noktada bir oyuncunun dünyanın dört bir yanından yürümesi yüzlerce yıl alacaktır ve saf kayan nokta matematiğini kullanırsanız dünya hassas hatalar biriktirecektir.

Octrees koleksiyonunu koruyun ve mesafeye bağlı olarak ekleyin / kaldırın. Güzelce nasıl birbirine geçeceğimi göremiyorum¹, ayrıca özellikle boş 3D yüzeyler istiyorsanız (boş hacimleri tekrar tekrar hesaplamaktan kaçınmak için) bilinen boş düğümlerin bir listesine ihtiyacım var

Bu temelde milyar km genişliğinde bir oktüre sahip olmak, ancak her 1 km'lik bloğa işaretçiler listesi tutmakla eşdeğer değil mi? Sonra "ağ örgüsü" sadece 2 km büyüklüğündeki düğümlere dayanır. Her bir orta düzey "büyük blok" a yerel referans tutmak, "muhtemelen düzinelerce ek oktree seviyesi" hakkında endişeleniyorsanız, üst düzey düğümleri tekrarlamanıza da engel olur.


Cevabın için teşekkür ederim. Arazim sonsuz olduğu için sadece büyük bir başlangıç ​​hacmi seçemiyorum (bu benim amacım). Bir fikir edinmek için videoyu izleyin. Bu nedenle, düğüm ağacım daha da yükselecekti. Küçük düğümlerin kaya ölçeği olduğunu varsayarsak, bu bir kıta boyunca seyahat ederken yüzlerce seviye olmasa bile onlarca potansiyel anlamına gelir. Ynt: Öbür tarafa geçelim, soruya biraz daha ayrıntı ekleyeyim [Tamamlandı]
Basic

oyuncu söz konusu olduğunda, "milyar mil" oldukça "sonsuz" a yakındır. Sabit bir başlangıç ​​birimi için daha fazla argüman cevaplandı.
Jimmy

Hala ikna olmadım. Neden 30'dan fazla bilinen bilinen işleme katmanı var? Verimli değil, zarif değil. Karşıdan karşıya geçmek için zaman ayırmaya çalışıyorum, ama biz sadece arazi üretimi hakkında konuşuyoruz. Başlangıç ​​noktasında ortalamam gerektiğini ya da yüksek hızda uçmanın imkansız olduğunu söyleyen hiçbir şey yok (bu hızda ağ oluşturmamasına rağmen!). FWIW Bu hassas problemi önlemek için dahili olarak iki kat kullanıyorum.
Temel
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.