NewtonGameDynamicsってあんまり日本では使ってる人を見ませんね。
でも、僕は好きです。
Newtonをビルド
おもむろにNewtonの最新版をチェックアウト。
core_Library200/projects/mac/OS10_xcode3.2.5/newton.xcodeproj
を開く。
ターゲットの設定から、BaseSDKをiOSに設定。しかし、このままではビルドが通らない。
なぜかプロジェクトに追加されていないソースファイルがあったので、
core_Library200/source/physics/dgMeshEffect2.cpp
core_Library200/source/physics/dgMeshEffect3.cpp
core_Library200/source/physics/dgMeshEffectSolidTree.cpp
あたりを追加。
さらに、core_Library200/source/newton/Newton.hの中からNewtonSceneCollisionCreateProxy()が宣言されている行を探し、これをコメントアウトする。
自分の環境では、LLVM GCC4.2でビルドするとうまく動かなかった。LLVM 3.1でビルドした。
XcodeのSchemeを編集し、iPhone/iPad実機用と、iOS Simulator用に別々にビルドする。
終わったら、ターミナルでビルドディレクトリを開き、armv7とi386のユニバーサルバイナリを作成する。
lipo -create -output libnewton.a release-iphoneos/libnewton.a release-iossimulator/libnewton.a
Cocos3Dで使う
先ほどビルドしたバイナリを、Cocos3Dプロジェクトに追加する。
core_Library200/source/newton にパスを通す。
core_Library200/projects/mac/iPhoneTranslator/iNewton.h に、Objective-CのNewtonラッパが置いてある。
だがこいつは使えない子。
大人しくNewton.hをインクルードして、通常のCのライブラリとして呼ぶことにする。
CC3Worldを継承したクラスのメンバに、NewtonWorld* newtonを追加して、こんな感じの関数を書く。
@implementation MyWorld
- (void)initializeWorld {
newton = NewtonCreate();
NewtonSetSolverModel(newton, 1);
}
- (void)dealloc {
NewtonDestroyAllBodies(newton);
NewtonDestroy(newton);
[super dealloc];
}
- (void)updateBeforeTransform:(CC3NodeUpdatingVisitor*)visitor {
NewtonUpdate(newton, visitor.deltaTime);
}
@end
CC3Nodeを継承したクラスのメンバに、NewtonBody* bodyを追加して、こんな感じの関数を書く。
static void NewtonGravityCallback(const NewtonBody* body, float timestep, int thredindex) {
const float GRAVITY = -9.8f;
float Ixx, Iyy, Izz, mass;
NewtonBodyGetMassMatrix(body, &mass, &Ixx, &Iyy, &Izz);
float vector[] = {
0.0f, GRAVITY * mass, 0.0f
};
NewtonBodySetForce(body, vector);
}
static void NewtonTransformCallback(const NewtonBody* body, const float* const matrix, int thredindex) {
MyNode* node = (MyNode*)NewtonBodyGetUserData(body);
float matrix[16];
NewtonBodyGetMatrix(body, matrix);
float quaternion[4];
NewtonBodyGetRotation(body, quaternion);
node.location = CC3VectorMake(matrix[12], matrix[13], matrix[14]);
node.quaternion = CC3Vector4Make(quaternion[3], quaternion[0], quaternion[1], quaternion[2]);
// ほんとは行列を直接代入したかったけど、やりかたがよくわからんかった
}
@implementation MyNode
- (void)setupPhysics:(NewtonWorld*)world {
NewtonCollision* col = NewtonCreateBox(world, 1.0f, 1.0f, 1.0f, 0, NULL);
body = NewtonCreateBody(world, col, self.transformMatrix.glMatrix);
NewtonReleaseCollision(world, col);
NewtonBodySetUserData(body, self);
NewtonBodySetMassMatrix(body, 1.0f, 1.0f, 1.0f, 1.0f);
NewtonBodySetForceAndTorqueCallback(body, &NewtonGravityCallback);
NewtonBodySetTransformCallback(body, &NewtonTransformCallback);
}
@end
できたー!
まとめ
NewtonのMac/iOS対応は適当なので、自分でがんばろう!
追記
Quaternionを使う場合は、どこかで回転方向を逆にしないとうまく動かないかも。