練習用に LWJGL を使用して Java でボクセル エンジンを作成していますが、チャンク管理システムで行き詰まっています。より具体的には、最適なレンダリングのために、ブロック ID の整数の 3D 配列であるチャンクをオクツリーに変換しようとしています。
これまでのところ、システムは機能していますが、非常に非効率的です。
これは 16*16*16 チャンクのスクリーンショットで、y=8 より下のすべての位置が 1 に設定されています (赤いブロック)。
https://raw.githubusercontent.com/ninthworld/Octree/master/screenshot0.png
OctNode ジェネレーター コードにデバッガーを追加して、チャンク配列へのアクセスに必要な回数を調べたところ、8392704が返されました。
8 つの子ノードを生成するためだけに、チャンク配列に 800 万回以上アクセスしました。
y=4 未満のブロックのみを持つようにチャンク配列を設定すると、プログラムはほぼ 30 秒間黒い画面になり、デバッガーは1623199744の配列アクセスを返します。
68 個の子ノードを生成するためだけに、16 億回を超える配列呼び出し。
明らかに、配列呼び出しの数を減らす必要がありますが、それは確かですが、どうやってそれを行うのかわかりません。ソース コード全体を見たい場合は、プロジェクトの github ページを次に示します。
私のコードの重要な部分は次のとおりです。
Main.java
// Initialize Octree Object
// This is just an extended OctNode object
octree = new Octree(chunk);
octree.generate(lookup);
OctNode.java
public void generate(){
int value = -1;
// Loop through an area an area of width*width*width
for(int x=0; x<width; x++){
for(int y=0; y<width; y++){
for(int z=0; z<width; z++){
// Get the value from the master array based on the node's
// offset + the forloop'd area
int store = array[x+(int)offset.x][y+(int)offset.y][z+(int)offset.z];
// Basically sets the value variable to the value at
// 0, 0, 0 with respect to the offset
if(value < 0)
value = store;
// Then check if the current position's value is the
// same as the first one found (int value), if it's not,
// then this node needs to be subdivided
if(store != value){
// Create 8 children for this node
children = new OctNode[8];
// And for each of the children...
for(int i=0; i<children.length; i++){
// Set their offset equal to this node's offset +
// this node's width/2 all with respect to it's
// individual quadrant (which is related to i)
Vector3f offS = new Vector3f(offset.x + (width/2f)*(i%2), offset.y + (width/2f)*((int)Math.floor(i/2f)%2), offset.z + (width/2f)*((int)Math.floor(i/4f)%2));
// Initialize the new child node
children[i] = new OctNode(array, (int)(width/2f), offS);
// And now do the same thing (recursion), but
// for a smaller area
children[i].generate();
}
}
}
}
}
// This is only called if the node is completely made of one value
if(children == null){
data = value;
}
}
残念ながら、それが私が説明できる最善の方法です。同じことをより簡単かつ迅速に行う方法を指摘できれば、それはすばらしいことです。