- November 1, 2007
ODE講座22:ODEでポリゴンを簡単に表示する方法
Archive3D.netからダウンロードした3DSフォーマットの「うさちゃん」。lib3dsライブラリを使うことでODE付属のdrawstuffで表示できました。
早いものでもう11月ですね。卒業研究や修士研究に取り組んでいる方はお尻に火か着くころではないでしょうか。
さて、ODE (Open Dynamics Engine)講座の22回目です。ODEに付属している3次元グラフィクスライブラリdrawstuffでは3Dモデルのファイルを読み込みません。ひびきのさんはXファイル(あの謎が謎を呼ぶTV番組ではありません。最も最近はPrison Breakに夢中ですが...)を読み込むX File Loaderを公開しています。 ここではもう一つの標準的な3Dファイルである3DSを読み込むサンプルプログラムをテスト公開します。
3dsファイルを読み込むライブラリとしてlib3dsを使います。これはJan Eric Kyprianidisさんが開発したものでLGPLで公開されています。lib3dsのウェブサイトはここです。
まず、lib3dsをインストールしましょう。方法はODEと同じで 以下の要領です。MSYS+MinGW+Windows Vista環境で問題なくできました。
- ./configure
- make
- make install
後は、このode3dsloader-0.0.tgzファイルを次のリンクからダウンロードして、
- 3DS Loader for Open Dynamics Engine 0.0(2007-11-1)
今までのサンプルプログラムと同じように展開し、make、実行してください。ただし、このプログラムは完全ではなく、複数の部品で構成されるモデルを表示しようとするとエラーになります。また、テクスチャも表示できません。そのためにはdrawstuffのソースを変更しなければなりません。今後の宿題とします。
なお、3dsファイルを表示するためには、そのファイルが必要になります。上図のうさちゃんはArchive3D.netのここからダウンロードしました。
以下にソースコードの主要部分を掲載します。3dsファイルを読み込む関数がload3dsModel()です。読み込みが終わると頂点配列Vertices[]とインデックス配列Indices[]にデータが格納されるので、後はODE付属のdemoプログラムdemo_moving_trimesh.cppと同じようにプログラムするとポリゴンデータを扱うことができます。
つまり、一般ユーザはload3dsModel()を一行入れるだけで3dsファイルを読み込むことができます。簡単ですね。
まだ、テスト公開中で不完全です。複数のオブジェクトで構成される3dsデータを表示できなければなりません。コメント頂ければありがたいです。
// main.cppから抜粋 by Kosei Demura 2007-11-1
//
#include <ode/ode.h>
#include <drawstuff/drawstuff.h>
#include "ode3dsloader.h"
extern int MeshCount; // オブジェクト数
void makeModel()
{
static dReal weight = 10.0;
dReal x0 = 0, y0 = 0, z0 = 1.0;
dMass m;
// 3dsファイルをロードする関数。引数は3dsファイル名
load3dsModel("../models/rabbit.3DS");
TriData = (dTriMeshDataID *) malloc(MeshCount * sizeof(dTriMeshDataID));
model = (MyObject *) malloc (MeshCount * sizeof(MyObject));
for (int i = 0; i < MeshCount; i++) {
// rigid body
model[i].body = dBodyCreate(world);
dBodySetPosition(model[i].body, x0, y0, z0);
// for a trimesh object
TriData[i] = dGeomTriMeshDataCreate();
dGeomTriMeshDataBuildSingle(TriData[i], trimesh[i].vertices, 3 * sizeof(float), trimesh[i].vertexCount, trimesh[i].indices, trimesh[i].indexCount * 3, 3 * sizeof(int));
model[i].geom = dCreateTriMesh(space, TriData[i], 0, 0, 0);
// remember the mesh's dTriMeshDataID on its userdata for convenience.
dGeomSetData(model[i].geom, TriData[i]);
dMassSetTrimeshTotal(&m, weight, model[i].geom);
dGeomSetPosition(model[i].geom, -m.c[0], -m.c[1], -m.c[2]);
dMassTranslate(&m, -m.c[0], -m.c[1], -m.c[2]);
dGeomSetBody(model[i].geom, model[i].body);
dBodySetMass(model[i].body, &m);
dMatrix3 Rotation;
dRFromAxisAndAngle(Rotation, 0, 0, 1, -M_PI/4);
dBodySetRotation(model[i].body, Rotation);
}
}
// ode3dsloader.cpp by Kosei Demura 2007-11-01
// 3dsフォーマットで作られたオブジェクトを読み込むプログラム
// このファイルでload3dsModel()関数を実装している。
// Todo:1つの3Dモデルが複数のオブジェクトで構成されているとエラーになる。
// lib3dsライブラリが必要http://lib3ds.sourceforge.net/
#include "ode3dsloader.h"
#define BASE_LENGTH 1.0 // メッシュモデルのバウンディングボックスの最大長さ[m]
#define MAX_OBJECTS 1000 // オブジェクトの数
typedef struct
{
float *vertices;
unsigned int vertexCount;
int *indices;
unsigned int indexCount;
} MyTrimesh;
extern MyTrimesh *trimesh;
dReal MIN_X = dInfinity, MAX_X = - dInfinity;
dReal MIN_Y = dInfinity, MAX_Y = - dInfinity;
dReal MIN_Z = dInfinity, MAX_Z = - dInfinity;
dReal ADJUST;
Lib3dsFile *file=0;
int MeshCount = 0;
int vCount[MAX_OBJECTS], iCount[MAX_OBJECTS];
void calModel(Lib3dsMesh *mesh, int *points, int *faces)
{
*points = mesh->points;
*faces = mesh->faces;
}
int meshDump(int no, Lib3dsMesh *mesh)
{
if (mesh->points == 0) return 0;
for (int i=0; i< (int) mesh->points; i++) {
trimesh[no].vertices[3*i] = mesh->pointL[i].pos[0];
trimesh[no].vertices[3*i+1] = mesh->pointL[i].pos[1];
trimesh[no].vertices[3*i+2] = mesh->pointL[i].pos[2];
if (MIN_X > mesh->pointL[i].pos[0]) MIN_X = mesh->pointL[i].pos[0];
if (MIN_Y > mesh->pointL[i].pos[1]) MIN_Y = mesh->pointL[i].pos[1];
if (MIN_Z > mesh->pointL[i].pos[2]) MIN_Z = mesh->pointL[i].pos[2];
if (MAX_X < mesh->pointL[i].pos[0]) MAX_X = mesh->pointL[i].pos[0];
if (MAX_Y < mesh->pointL[i].pos[1]) MAX_Y = mesh->pointL[i].pos[1];
if (MAX_Z < mesh->pointL[i].pos[2]) MAX_Z = mesh->pointL[i].pos[2];
}
for (int i=0; i< (int) mesh->faces; i++) {
trimesh[no].indices[3*i] = mesh->faceL[i].points[0];
trimesh[no].indices[3*i+1] = mesh->faceL[i].points[1];
trimesh[no].indices[3*i+2] = mesh->faceL[i].points[2];
}
return 1;
}
// トライメッシュデータのサイズ変更
int normalize(int no, Lib3dsMesh *mesh)
{
if (mesh->points == 0) return 0;
for (int i=0; i< (int) mesh->points; i++) {
trimesh[no].vertices[3*i] *= (dReal) ADJUST;
trimesh[no].vertices[3*i+1] *= (dReal) ADJUST;
trimesh[no].vertices[3*i+2] *= (dReal) ADJUST;
}
return 1;
}
void load3dsModel(const char *filename)
{
int points, faces, no;
Lib3dsMesh *p;
file = lib3ds_file_load(filename);
if (!file) {
puts("3dsplayer: Error: Loading 3DS file failed.\n");
exit(1);
}
for (p=file->meshes; p!=0; p=p->next) {
calModel(p, &points, &faces);
if (points == 0) continue;
MeshCount++;
}
trimesh = (MyTrimesh *) malloc(MeshCount * sizeof(MyTrimesh));
no = 0;
for (p=file->meshes; p!=0; p=p->next) {
calModel(p, &points, &faces);
if (points == 0) continue;
vCount[no] = points;
iCount[no] = faces;
trimesh[no].vertices = (float *) malloc(vCount[no] * sizeof(float) * 3);
trimesh[no].indices = (int *) malloc(iCount[no] * sizeof(int) * 3);
trimesh[no].vertexCount = vCount[no];
trimesh[no].indexCount = iCount[no];
no++;
}
no = 0;
for (p=file->meshes; p!=0; p=p->next) {
if (meshDump(no, p)) no++;
}
dReal maxLength;
if (MAX_X - MIN_X >= MAX_Y - MIN_Y) {
if (MAX_X - MIN_X >= MAX_Z - MIN_Z) maxLength = MAX_X - MIN_X;
else maxLength = MAX_Z - MIN_Z;
}
else {
if (MAX_Y - MIN_Y >= MAX_Z - MIN_Z) maxLength = MAX_Y - MIN_Y;
else maxLength = MAX_Z - MIN_Z;
}
no = 0;
for (p=file->meshes; p!=0; p=p->next) {
if (normalize(no, p)) no++;
}
}
// ode3dsloader.h
#include <ode/ode.h>
#include <drawstuff/drawstuff.h>
// for lib3ds
#include <lib3ds/chunk.h>
#include <lib3ds/file.h>
#include <lib3ds/camera.h>
#include <lib3ds/mesh.h>
#include <lib3ds/node.h>
#include <lib3ds/material.h>
#include <lib3ds/matrix.h>
#include <lib3ds/vector.h>
#include <lib3ds/light.h>
void load3dsModel(const char *filename);
- Previous Page: ODE講座21:テクスチャを切り替えよう!(画像ライブラリ)
- Next Page: ODE講座23:関節中心点の取得とスケルトン表示

ROBOCUP



lib3ds-examples.tgzを試してみましたが下記のとおりとなってしまいました。msysのトップからのディレクトリ構成と主要ライブラリのメモ書きがあったらメールに添付していただけますでしょうか?
$ make
g++ -Wall -fno-exceptions -fno-rtti -g -DWIN32 -c 3dsplay.c -L/lib -L/usr/lib -L../lib -L../../drawstuff/src -L/usr/local/lib -I/include -I/usr/include -I../include -I. -I../../include -I/usr/local/include
In file included from ../../include/lib3ds/types.h:51,
from ../../include/lib3ds/background.h:27,
from ../../include/lib3ds/file.h:27,
from 3dsplay.c:27:
../include/stdint.h:24:20: stddef.h: No such file or directory
In file included from ../../include/lib3ds/types.h:78,
from ../../include/lib3ds/background.h:27,
from ../../include/lib3ds/file.h:27,
from 3dsplay.c:27:
../include/stdio.h:28:20: stdarg.h: No such file or directory
In file included from ../../include/lib3ds/types.h:78,
from ../../include/lib3ds/background.h:27,
from ../../include/lib3ds/file.h:27,
from 3dsplay.c:27:
../include/stdio.h:191: error: `size_t' has not been declared
../include/stdio.h:191: error: ISO C++ forbids declaration of `parameter' with no type
../include/stdio.h:202: error: `size_t' has not been declared