立方体を大量に描画するとなると mqoファイルと MV1LoadModel などの3Dモデル関数を使用するより
以下の関数
CreateVertexBuffer
DeleteVertexBuffer
SetVertexBufferData
CreateIndexBuffer
DeleteIndexBuffer
SetIndexBufferData
DrawPolygonIndexed3D_UseVertexBuffer
を使用して立方体の配置情報から自前でポリゴン座標を計算して描画するほうが圧倒的に高速に描画できると思います
( 一回の DrawPolygonIndexed3D_UseVertexBuffer で複数の立方体を一度に描画するので、
一個一個 MV1DrawModel するより速くなります )
また、どうしても計算誤差の関係で立方体の隙間にある影部分は消せないと思いますので、
自前でポリゴン座標を算出する際は
・見えないポリゴンは省く
ようにすることで、描画するポリゴンも減らすことができ、且つ隣接する立方体の隙間部分にある
影も消すことができます
処理の流れは
>> 初期化パート
1.立方体の配置情報を読み込む( 立方体に貼るテクスチャも読み込む )
2.立方体群の見える面を洗い出す( 見えない面は省く )
3.見える面( ポリゴン )を描画するのに必要な頂点数の頂点バッファ、インデックス数のインデックスバッファを
CreateVertexBuffer, CreateIndexBuffer を使用して作成する
4.頂点データ、インデックスデータを SetVertexBufferData, SetIndexBufferData でセットする
( 頂点座標はワールド座標 )
>> ループパート
5.ループでは用意した頂点データ、インデックスデータを使用して DrawPolygonIndexed3D_UseVertexBuffer で描画する
というような感じです
DrawPolygonIndexed3D_UseVertexBuffer を使用して画面に2個ポリゴンを描画するサンプルプログラムが
ありましたので、よろしければご覧ください
#include "DxLib.h"
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
VERTEX3D Vertex[ 4 ] ;
WORD Index[ 6 ] ;
int VertexBufHandle ;
int IndexBufHandle ;
// DXライブラリの初期化
ChangeWindowMode( TRUE ) ;
if( DxLib_Init() < 0 )
{
// エラーが発生したら直ちに終了
return -1 ;
}
// 4頂点分の頂点バッファを作成
VertexBufHandle = CreateVertexBuffer( 4, DX_VERTEX_TYPE_NORMAL_3D ) ;
// 6個分のインデックスバッファを作成
IndexBufHandle = CreateIndexBuffer( 6, DX_INDEX_TYPE_16BIT ) ;
// 4頂点分のデータをセット
Vertex[ 0 ].pos = VGet( 100.0f, 100.0f, 0.0f ) ;
Vertex[ 0 ].norm = VGet( 0.0f, 0.0f, -1.0f ) ;
Vertex[ 0 ].dif = GetColorU8( 255,255,255,255 ) ;
Vertex[ 0 ].spc = GetColorU8( 0, 0, 0, 0 ) ;
Vertex[ 0 ].u = 0.0f ;
Vertex[ 0 ].v = 0.0f ;
Vertex[ 0 ].su = 0.0f ;
Vertex[ 0 ].sv = 0.0f ;
Vertex[ 1 ].pos = VGet( 250.0f, 100.0f, 0.0f ) ;
Vertex[ 1 ].norm = VGet( 0.0f, 0.0f, -1.0f ) ;
Vertex[ 1 ].dif = GetColorU8( 255, 0,255,255 ) ;
Vertex[ 1 ].spc = GetColorU8( 0, 0, 0, 0 ) ;
Vertex[ 1 ].u = 0.0f ;
Vertex[ 1 ].v = 0.0f ;
Vertex[ 1 ].su = 0.0f ;
Vertex[ 1 ].sv = 0.0f ;
Vertex[ 2 ].pos = VGet( 100.0f, 300.0f, 0.0f ) ;
Vertex[ 2 ].norm = VGet( 0.0f, 0.0f, -1.0f ) ;
Vertex[ 2 ].dif = GetColorU8( 0,255,255,255 ) ;
Vertex[ 2 ].spc = GetColorU8( 0, 0, 0, 0 ) ;
Vertex[ 2 ].u = 0.0f ;
Vertex[ 2 ].v = 0.0f ;
Vertex[ 2 ].su = 0.0f ;
Vertex[ 2 ].sv = 0.0f ;
Vertex[ 3 ].pos = VGet( 400.0f, 200.0f, 0.0f ) ;
Vertex[ 3 ].norm = VGet( 0.0f, 0.0f, -1.0f ) ;
Vertex[ 3 ].dif = GetColorU8( 0,255,255,255 ) ;
Vertex[ 3 ].spc = GetColorU8( 0, 0, 0, 0 ) ;
Vertex[ 3 ].u = 0.0f ;
Vertex[ 3 ].v = 0.0f ;
Vertex[ 3 ].su = 0.0f ;
Vertex[ 3 ].sv = 0.0f ;
// 2ポリゴン分のインデックスデータをセット
Index[ 0 ] = 0 ;
Index[ 1 ] = 1 ;
Index[ 2 ] = 2 ;
Index[ 3 ] = 3 ;
Index[ 4 ] = 2 ;
Index[ 5 ] = 1 ;
// 頂点データを頂点バッファに転送
SetVertexBufferData( 0, Vertex, 4, VertexBufHandle ) ;
// インデックスデータをインデックスバッファに転送
SetIndexBufferData( 0, Index, 6, IndexBufHandle ) ;
// 頂点バッファとインデックスバッファを使用した2ポリゴンの描画
DrawPolygonIndexed3D_UseVertexBuffer( VertexBufHandle, IndexBufHandle, DX_NONE_GRAPH, FALSE ) ;
// キー入力待ちをする
WaitKey() ;
// DXライブラリの後始末
DxLib_End() ;
// ソフトの終了
return 0 ;
}
ただ、この方法には以下のような面倒な点があります
・一度の DrawPolygonIndexed3D_UseVertexBuffer で使用できるテクスチャは一つなので、
何種類もある立方体のテクスチャを一つのテクスチャに纏める必要がある
・一度に描画できるインデックスデータの数、頂点データの数の最大数は 65536個 なので
一度に描画できるポリゴンの数は最大 65536 / 3 = 21845個、
128 * 128 の立方体を全面描画するのに必要なポリゴン数は 12 * 128 * 128 = 196608個( 立方体一つ12ポリ )
なので、見えない部分を省いても 21845個を超える場合があるので複数の頂点バッファ、インデックスバッファを
使用する必要がある
・頂点バッファ、インデックスバッファを使用する立方体描画は立方体が動かないことを前提に最適化された
処理なので、仮に動く立方体が存在する場合は扱いを別にする必要がある
( 動く立方体だけ MV1DrawModel を使用するなど )
DrawPolygonIndexed3D_UseVertexBuffer などの扱いで不明な点がありましたらお訊ねください
と、ここまでご説明したところでもう一つ方法を思いつきました
速度面では DrawPolygonIndexed3D_UseVertexBuffer を使用する場合より大幅に遅くなりますが、
3Dサンプルプログラムの迷路
http://homepage2.nifty.com/natupaji/DxLib/program/dxprogram_3Dmeiro.html
と同じ方法で立方体の各面をそれぞれフレームに分けて、見えない面を非表示にして描画することで
件の問題の影部分の面がちらちら見える現象は防げると思います
DrawPolygonIndexed3D_UseVertexBuffer を使用する場合よりかなり遅くなるので実用的な速度が得られるかは
分かりませんが、実装難度はかなり低くなると思います