ODEでXファイルからポリゴンを表示する
Xファイルは、DirectXの3Dフォーマットのようです。
多くの3Dモデリングツールがサポートしています。
たとえば、BlenderやMetasequoiaといったもの。
多くの3Dモデリングツールがサポートしています。
たとえば、BlenderやMetasequoiaといったもの。
ここでは、Xファイル(アスキー形式)を読み込むためのクラスを作ってみました。
デバッグはそこそこしかしてません。
バグったらごめんなさい。
デバッグはそこそこしかしてません。
バグったらごめんなさい。
とりあえず、BleanderとMetasequoiaのXファイルは読めました。
BlenderでXファイルのエクスポート時、"Flip z"が有効になっているとポリゴンの表裏が反転してしまうので注意してください。

Metasequoia(無料版)の基本図形の1つ(立方体)を読み込んで表示したところ。
2つ生成して重ねています。
2つ生成して重ねています。

以前作成したSTL用のものとAPIを合わせて作っています。
使い方
- ヘッダ
#include "XReader.h"
namespaceは、ode_utilsです。(using namespace ode_utils;)
- クラス
ode_util::XReader<V_TYPE,IDX_TYPE>
V_TYPEは、頂点座標の型(floatもしくはdouble)
IDX_TYPEは、頂点座標番号の型(intもしくはdTriIndex)
IDX_TYPEは、頂点座標番号の型(intもしくはdTriIndex)
- API
XReader( const char* file_name ) | コンストラクタ、file_nameは、読み込むX(アスキー)ファイル名 |
bool isCompleted() | Xファイルが正常に読み込まれるとtrueを返す |
const char* message() | ファイル処理時の完了/エラーメッセージを返す |
const vertex_type* getVertices() | 頂点座標配列の先頭ポインタを返す |
const index_type* getIndices() | 頂点座標番号配列の先頭ポインタを返す |
int getVertexCount() | 頂点座標の数を返す。 |
int getIndexCount() | 頂点座標番号の数を返す。 |
vertex_typeはV_TYPEで与えたもの。
index_typeはODX_TYPEで与えたもの。
index_typeはODX_TYPEで与えたもの。
- XReaderの仕様
Xファイル内で、
Mesh { ・・・ }
のvertex数、頂点データ、index数、頂点インデックスのみを取得します。
template{}はすべて無視します。
MeshMaterialList、Material、Normalといったものもすべて無視です。
template{}はすべて無視します。
MeshMaterialList、Material、Normalといったものもすべて無視です。
頂点インデックスは、3つ(三角形)もくしは4つ(四角形)の番号がセットになる場合があります。ODEのTriMeshは4つには対応していないので、4つセットのものは3つに分割しています。
字句解析には、無駄にre2cを使っています。(勉強がてら)
なのでクラスの中は一部人には読めないものになっています。
なのでクラスの中は一部人には読めないものになっています。
ODE記述
#include "XReader.h"
static dBodyID body1, body2;
static dGeomID geom1, geom2;
ode_utils::XReader<float,dTriIndex> *mesh;
mesh = new ode_utils::XReader<float,dTriIndex>("cube2.x");
if (!mesh->isCompleted()) {
printf( "mesh error\n");
printf( "msg : \n%s", mesh->message() );
printf("vertexCount=%d\n", mesh->getVertexCount());
printf("getIndexCount=%d\n", mesh->getIndexCount());
printf("vertices pointer=%d\n", mesh->getVertices());
printf("indices pointer=%d\n", mesh->getIndices());
exit(1);
}
body = dBodyCreate( world );
dTriMeshDataID data;
data = dGeomTriMeshDataCreate();
dGeomTriMeshDataBuildSingle(data, mesh->getVertices(), 3*sizeof(float), mesh->getVertexCount(),
mesh->getIndices(), mesh->getIndexCount(), 3*sizeof(dTriIndex));
geom = dCreateTriMesh(space, data, 0, 0, 0);
dGeomSetData( geom, data );
dMass m;
dMassSetTrimesh( &m, mass, geom );
dGeomSetPosition( geom, -m.c[0], -m.c[1], -m.c[2] );
dMassTranslate( &m, -m.c[0], -m.c[1], -m.c[2] );
dBodySetMass( body, &m );
dGeomSetBody( geom, body );
drawstuff記述例
dsSetColor( 1, 1, 0 );
{
const dReal* pos = dGeomGetPosition(geom1);
const dReal* rot = dGeomGetRotation(geom1);
const dTriIndex *index = mesh->getIndices();
for (int ii = 0; ii < mesh->getIndexCount()/3; ii++) {
const dReal v[9] = {
mesh->getVertices()[index[ii*3+0]*3 + 0],
mesh->getVertices()[index[ii*3+0]*3 + 1],
mesh->getVertices()[index[ii*3+0]*3 + 2],
mesh->getVertices()[index[ii*3+1]*3 + 0],
mesh->getVertices()[index[ii*3+1]*3 + 1],
mesh->getVertices()[index[ii*3+1]*3 + 2],
mesh->getVertices()[index[ii*3+2]*3 + 0],
mesh->getVertices()[index[ii*3+2]*3 + 1],
mesh->getVertices()[index[ii*3+2]*3 + 2]
};
dsDrawTriangle( pos, rot, &v[0], &v[3], &v[6], 1 );
}
}
添付ファイル