オフトピック
わかる方がいらっしゃったら教えていただきたい
PhysX2.8.0 Sampleを改造して人の形を作りたいのですが、ジョイントに制限をかける際のパラメータ値をどのようにしたらいいのかわかりません
ジョイントの選定はサンプルをすべて実行し確認しました。
その結果、以下のジョイントが人の形には適しているのかと思いました。
- SampleArticulateTruckのジョイントか
- SampleD6Joint のジョイントか
- NxSphericalJointDesc クラスhttp://maverickproj.web.fc2.com/PhysX_R ... tDesc.html
ジョイントの制限は以下のリンクのNxJointLimitDesc クラスを確認したしました
http://maverickproj.web.fc2.com/PhysX_R ... tDesc.html
座標の場合とラジアンの場合がさっぱりですラジアン角の場合:( -PI ~ PI )
座標の場合:( -inf ~ inf )
ラジアンで1なのか座標で1なのか判別できないのでは?と少し疑問です
以下のようにコードを書いたのですが、角度の制限も動いている雰囲気もありません
くっついてる状態ですここで何をしたらいいのかわからなくなっています
#include <stdio.h>
#include <GL\glut.h>
#include <stdlib.h>
#include "NxPhysics.h"
#include "ErrorStream.h"
#include "DebugRenderer.h"
#include "Utilities.h"
#include "DrawObjects.h"
#include "../../v2.8.0/Samples/SampleCommonCode/src/Actors.h"
// 関数のプロトタイプ宣言
void InitGlut(int argc, char **argv);
bool InitNx();
// Physics
NxPhysicsSDK* gPhysicsSDK = NULL;
NxScene* gScene = NULL;
static DebugRenderer gDebugRenderer;
static void CreateCombo(
const NxVec3& pos, // **初期位置情報
const NxVec3* initialVelocity=NULL, //**初期速度情報
const NxVec3* fors=NULL//
);
// Rendering
static NxVec3 gEye(10.0f, 10.0f, 10.0f);
static NxVec3 gDir(-0.6f,-0.2f,-0.7f);
static NxVec3 gViewY;
static int gMouseX = 0;
static int gMouseY = 0;
bool debug = false;
NxActor *rodPivot;
// ユーザーデータの定義
class myData
{
public:
double a[3];
char color;
int size;
};
// キーボードの処理
static void KeyboardCallback(unsigned char key, int x, int y)
{
NxQuat quatbuf(rodPivot->getGlobalOrientationQuat());
NxMat33 nowbuf;
NxF32 buf[3][3];
nowbuf = rodPivot->getGlobalOrientation();
nowbuf.getRowMajor(buf);
puts("mat");
for(int i=0;i<3;i++){
for(int j=0;j<3;j++)
printf("%5.3f,",buf[i][j]);
puts("");
}
NxReal quat[4];
quatbuf.getXYZW(quat);
for(int i=0;i<4;i++)
printf("%5.3f,",quat[i]);
switch(key)
{
case 27:
exit(0);
break;
case ' ':
for(int i=0;i<3;i++){
for(int j=0;j<3;j++)
scanf("%f,",&buf[i][j]);
puts("");
}
nowbuf.setRowMajor(buf);
break;
case '1':
rodPivot->setAngularVelocity(NxVec3(0.9,0.0,0.0));
break;
case '2':
rodPivot->setAngularVelocity(NxVec3(0.0,0.9,0.0));
break;
case '3':
rodPivot->setAngularVelocity(NxVec3(0.0,0.0,0.9));
break;
case 'v':
case 'V':
debug = !debug;
break;
case 'x':
case 'X':
{
NxActor** actors = gScene->getActors();
if(gScene->getNbActors() > 1){
gScene->releaseActor(*actors[gScene->getNbActors()-1]);
}
}
break;
case 'q':
CreateCombo(NxVec3(0.0,20.0,0.0));///2000.0cm==20m
break;
case GLUT_KEY_UP:
gEye += gDir*2.0f;
break;
case GLUT_KEY_DOWN:
gEye -= gDir*2.0f;
break;
case GLUT_KEY_LEFT:
gEye -= gViewY*2.0f;
break;
case GLUT_KEY_RIGHT:
gEye += gViewY*2.0f;
break;
}
}
NxD6Joint* CreateD6Joint(NxActor* a0, NxActor* a1
,const NxVec3& globalAnchor, const NxVec3& globalAxis
)
{
NxReal gLinearLimit = 1.0f;
NxReal gSwing1Limit = NxPiF32 / 180.0f * 30.0f;
NxReal gSwing2Limit = NxPiF32 / 180.0f * 70.0f;
NxReal gTwistLowLimit = NxPiF32 / 180.0f * -90.0f;
NxReal gTwistHighLimit = NxPiF32 / 180.0f * 45.0f;
NxD6JointDesc d6Desc;
d6Desc.actor[0] = a0;
d6Desc.actor[1] = a1;
d6Desc.setGlobalAnchor(globalAnchor);
d6Desc.setGlobalAxis(globalAxis);
d6Desc.twistMotion = NX_D6JOINT_MOTION_LOCKED;
d6Desc.swing1Motion = NX_D6JOINT_MOTION_LOCKED;
d6Desc.swing2Motion = NX_D6JOINT_MOTION_LOCKED;
d6Desc.xMotion = NX_D6JOINT_MOTION_LOCKED;
d6Desc.yMotion = NX_D6JOINT_MOTION_LOCKED;
d6Desc.zMotion = NX_D6JOINT_MOTION_LOCKED;
d6Desc.linearLimit.value = gLinearLimit;
d6Desc.swing1Limit.value = gSwing1Limit;
d6Desc.swing2Limit.value = gSwing2Limit;
d6Desc.twistLimit.low.value = gTwistLowLimit;
d6Desc.twistLimit.high.value = gTwistHighLimit;
// d6Desc.projectionMode = NX_JPM_NONE;
d6Desc.projectionMode = NX_JPM_POINT_MINDIST;
// d6Desc.jointFlags |= NX_JF_COLLISION_ENABLED;
NxJoint* d6Joint = gScene->createJoint(d6Desc);
return (NxD6Joint*)d6Joint->is(NX_JOINT_D6);
}
// 複合シェープ人の生成
static void CreateComboHuman(
const NxVec3& pos, // **初期位置情報
const NxVec3* initialVelocity=NULL, //**初期速度情報
const NxVec3* fors=NULL// **初期化速度
){
if(gScene == NULL) return;
NxActor *migiasi = CreateBox(NxVec3(1,0,0), NxVec3(1,0.5,2.7),985);
NxActor *hidariasi= CreateBox(NxVec3(-1,0,0), NxVec3(1,0.5,2.7),985);
NxActor *migisune = CreateCapsule(NxVec3(1,0,3),3.7,0.557,985);
NxD6Joint *j1 = CreateD6Joint(migiasi,migisune,NxVec3(0,0,0),NxVec3(0,0,0));
}
// 複合シェープの生成
static void CreateCombo(
const NxVec3& pos, // **初期位置情報
const NxVec3* initialVelocity, //**初期速度情報
const NxVec3* fors//
)
{
if(gScene == NULL) return;
// アクターのパラメータ設定
NxBodyDesc bodyDesc;
// 回転運動減衰係数
bodyDesc.angularDamping = 0.01f;
// 線形減衰係数
bodyDesc.linearDamping = 0.01f;
// 初期速度情報
if(initialVelocity) bodyDesc.linearVelocity = *initialVelocity;
// Boxシェープの作成
NxBoxShapeDesc boxDesc1;
// Dimentions 寸法
boxDesc1.dimensions = NxVec3(1,4,1);
NxBoxShapeDesc boxDesc2;
boxDesc2.dimensions = NxVec3(4,1,1);
NxBoxShapeDesc boxDesc3;
boxDesc3.dimensions = NxVec3(1,1,4);
// シェープを保持してアクターを構成します
NxActorDesc actorDesc;
actorDesc.shapes.pushBack(&boxDesc1);
actorDesc.shapes.pushBack(&boxDesc2);
actorDesc.shapes.pushBack(&boxDesc3);
// アクターのパラメータを受け継ぐ
actorDesc.body = &bodyDesc;
// 密度の指定
actorDesc.density = 1000.0f;
// アクターの位置情報
actorDesc.globalPose.t = pos;
rodPivot = gScene->createActor(actorDesc);
}
// 囲いシェープ
static void RoundedBox(
const double takasa=3,
const double x_kyori=50,
const double z_kyori=50,
const double atusa=1
)
{
if(gScene == NULL) return;
NxBodyDesc bodyDesc;
bodyDesc.angularDamping = 0.5f;
NxBoxShapeDesc boxDesc1;
boxDesc1.dimensions = NxVec3(atusa,takasa,z_kyori);
boxDesc1.localPose.t= NxVec3(-x_kyori+atusa,takasa,0);
NxBoxShapeDesc boxDesc2;
boxDesc2.dimensions = NxVec3(atusa,takasa,z_kyori);
boxDesc2.localPose.t= NxVec3(x_kyori-atusa,takasa,0);
NxBoxShapeDesc boxDesc3;
boxDesc3.dimensions = NxVec3(x_kyori,takasa,atusa);
boxDesc3.localPose.t= NxVec3(0,takasa,-z_kyori+atusa);
NxBoxShapeDesc boxDesc4;
boxDesc4.dimensions = NxVec3(x_kyori,takasa,atusa);
boxDesc4.localPose.t= NxVec3(0,takasa,z_kyori-atusa);
NxActorDesc actorDesc;
actorDesc.shapes.pushBack(&boxDesc1);
actorDesc.shapes.pushBack(&boxDesc2);
actorDesc.shapes.pushBack(&boxDesc3);
actorDesc.shapes.pushBack(&boxDesc4);
actorDesc.body = &bodyDesc;
actorDesc.density = 1000000.0f;
actorDesc.globalPose.t = NxVec3(0.0,1,0.0);
gScene->createActor(actorDesc);
}
////
///
////
///
////
///
////
///
////
// メイン関数
int main(int argc, char** argv)
{
printf("スペースキーはキューブを生成します\n");
printf("1は複合シェープを生成します\n");
printf("2は机を生成します\n");
printf("Bはボックスを生成します\n");
printf("Cはカプセルを生成します\n");
printf("Sは球を生成します\n");
printf("Vキーはデバッグ画面を切り替えます\n");
printf("Xキーはアクターを削除します\n");
// glutの初期化
InitGlut(argc, argv);
// PhysXの初期化
if (InitNx()){
CreateCombo(NxVec3(0.0,2000.0,0.0));///2000.0cm==20m
CreateComboHuman(NxVec3(0.0,100.0,0.0));
RoundedBox();
glutMainLoop();
}
return 0;
}
// 画面の描画
static void RenderCallback()
{
if(gScene == NULL) return;
gScene->simulate(1.0f/60.0f);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
// 射影マトリックス
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0f, (float)glutGet(GLUT_WINDOW_WIDTH)/(float)glutGet(GLUT_WINDOW_HEIGHT), 1.0f, 10000.0f);
gluLookAt(gEye.x, gEye.y, gEye.z, gEye.x + gDir.x, gEye.y + gDir.y, gEye.z + gDir.z, 0.0f, 1.0f, 0.0f);
// ビューマトリックス
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
int nbActors = gScene->getNbActors();
gScene->fetchResults(NX_RIGID_BODY_FINISHED, true);
if (debug)
{
gDebugRenderer.renderData(*gScene->getDebugRenderable());
}
else
{
NxActor** actors = gScene->getActors();
while(nbActors--)
{
NxActor* actor= *actors;
if(actor->userData){
myData *mydata =(myData*)(actor)->userData;
// NxVec3 set(mydata->a[0],mydata->a[1],mydata->a[2]);
// NxVec3 set(0.0,rand()%1000,0.0);
// actor->addForce(set);
}
DrawActor(*actors++);
}
gScene->flushStream();
}
glutSwapBuffers();
}
// PhysXの初期化
static bool InitNx()
{
// PhysX SDKの生成
NxPhysicsSDKDesc desc;
NxSDKCreateError errorCode = NXCE_NO_ERROR;
gPhysicsSDK = NxCreatePhysicsSDK(NX_PHYSICS_SDK_VERSION, NULL, new ErrorStream(), desc, &errorCode);
if(gPhysicsSDK == NULL)
{
printf("\nSDKの生成に失敗\n");
return false;
}
gPhysicsSDK->setParameter(NX_SKIN_WIDTH, 0.05f);
gPhysicsSDK->setParameter(NX_VISUALIZE_COLLISION_SHAPES, 1);
gPhysicsSDK->setParameter(NX_VISUALIZATION_SCALE, 10.0f);
// シーンの生成
NxSceneDesc sceneDesc;
sceneDesc.gravity = NxVec3(0.0f, -1.0f, 0.0f);
gScene = gPhysicsSDK->createScene(sceneDesc);
if(gScene == NULL)
{
printf("\nシーンの生成に失敗\n");
return false;
}
// デフォルトのマテリアル
NxMaterial* defaultMaterial = gScene->getMaterialFromIndex(0);
defaultMaterial->setRestitution(0.0f);
defaultMaterial->setStaticFriction(0.5f);
defaultMaterial->setDynamicFriction(0.5f);
// 地面の生成
NxPlaneShapeDesc planeDesc;
NxActorDesc actorDesc;
actorDesc.shapes.pushBack(&planeDesc);
gScene->createActor(actorDesc);
return true;
}
// PhysXの終了処理
static void ExitNx()
{
if(gPhysicsSDK != NULL)
{
if(gScene != NULL) gPhysicsSDK->releaseScene(*gScene);
gScene = NULL;
NxReleasePhysicsSDK(gPhysicsSDK);
gPhysicsSDK = NULL;
}
}
// 矢印キーの処理
static void ArrowKeyCallback(int key, int x, int y)
{
KeyboardCallback(key,x,y);
}
// マウスの処理
static void MouseCallback(int button, int state, int x, int y)
{
gMouseX = x;
gMouseY = y;
}
// マウスのドラッグの処理
static void MotionCallback(int x, int y)
{
int dx = gMouseX - x;
int dy = gMouseY - y;
gDir.normalize();
gViewY.cross(gDir, NxVec3(0,1,0));
NxQuat qx(NxPiF32 * dx * 20/ 180.0f, NxVec3(0,1,0));
qx.rotate(gDir);
NxQuat qy(NxPiF32 * dy * 20/ 180.0f, gViewY);
qy.rotate(gDir);
gMouseX = x;
gMouseY = y;
}
// ウインドウのサイズの変更
static void ReshapeCallback(int width, int height)
{
glViewport(0, 0, width, height);
}
// アイドリングの処理
static void IdleCallback()
{
glutPostRedisplay();
}
// glutの初期化
void InitGlut(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitWindowSize(512, 512);
glutInitDisplayMode(GLUT_RGB|GLUT_DOUBLE|GLUT_DEPTH);
int mainHandle = glutCreateWindow("Sample");
glutSetWindow(mainHandle);
glutDisplayFunc(RenderCallback);
glutReshapeFunc(ReshapeCallback);
glutIdleFunc(IdleCallback);
glutKeyboardFunc(KeyboardCallback);
glutSpecialFunc(ArrowKeyCallback);
glutMouseFunc(MouseCallback);
glutMotionFunc(MotionCallback);
MotionCallback(0,0);
atexit(ExitNx);
// デフォルトの描画パラメータ
glClearColor(0.3f, 0.4f, 0.5f, 1.0);
glEnable(GL_DEPTH_TEST);
glEnable(GL_COLOR_MATERIAL);
// 光源の設定
glEnable(GL_LIGHTING);
float ambientColor[] = { 0.0f, 0.1f, 0.2f, 0.0f };
float diffuseColor[] = { 1.0f, 1.0f, 1.0f, 0.0f };
float specularColor[] = { 0.0f, 0.0f, 0.0f, 0.0f };
float position[] = { 100.0f, 100.0f, 400.0f, 1.0f };
glLightfv(GL_LIGHT0, GL_AMBIENT, ambientColor);
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseColor);
glLightfv(GL_LIGHT0, GL_SPECULAR, specularColor);
glLightfv(GL_LIGHT0, GL_POSITION, position);
glEnable(GL_LIGHT0);
}
まとめると質問は3つです
- ラジアンの範囲内の座標はどうなってしまうのか?
- 単位系はどうなっているのか?
- どうして、完全にくっついているのか?