Пример jBullet
Я пытаюсь узнать, как использовать jBullet в проекте, над которым я работаю, и я рассмотрел демонстрацию, которую предоставляет источник, но я просто не могу понять, как эти демонстрационные объекты получают. У кого-нибудь есть хороший ресурс, на который они могли бы указать мне или предоставить базовый пример, который отображает один или два объекта на экране?
Заранее спасибо, извините, у меня нет кода, чтобы показать, что я могу быстро написать некоторые, если это необходимо, но просто действительно ищу направление, по которому нужно идти.
Спасибо,
Код для куба, который я использую, поэтому я пытаюсь добавить к нему коллизию, но я не уверен, как использовать jbullet:
public void Draw() {
// center point posX, posY, posZ
float radius = size / 2;
//top
glPushMatrix();
glBegin(GL_QUADS);
{
glColor3f(1.0f,0.0f,0.0f); // red
glVertex3f(posX + radius, posY + radius, posZ - radius);
glVertex3f(posX - radius, posY + radius, posZ - radius);
glVertex3f(posX - radius, posY + radius, posZ + radius);
glVertex3f(posX + radius, posY + radius, posZ + radius);
}
glEnd();
glPopMatrix();
//bottom
glPushMatrix();
glBegin(GL_QUADS);
{
glColor3f(1.0f,1.0f,0.0f); // ?? color
glVertex3f(posX + radius, posY - radius, posZ + radius);
glVertex3f(posX - radius, posY - radius, posZ + radius);
glVertex3f(posX - radius, posY - radius, posZ - radius);
glVertex3f(posX + radius, posY - radius, posZ - radius);
}
glEnd();
glPopMatrix();
//right side
glPushMatrix();
glBegin(GL_QUADS);
{
glColor3f(1.0f,0.0f,1.0f); // ?? color
glVertex3f(posX + radius, posY + radius, posZ + radius);
glVertex3f(posX + radius, posY - radius, posZ + radius);
glVertex3f(posX + radius, posY - radius, posZ - radius);
glVertex3f(posX + radius, posY + radius, posZ - radius);
}
glEnd();
glPopMatrix();
//left side
glPushMatrix();
glBegin(GL_QUADS);
{
glColor3f(0.0f,1.0f,1.0f); // ?? color
glVertex3f(posX - radius, posY + radius, posZ - radius);
glVertex3f(posX - radius, posY - radius, posZ - radius);
glVertex3f(posX - radius, posY - radius, posZ + radius);
glVertex3f(posX - radius, posY + radius, posZ + radius);
}
glEnd();
glPopMatrix();
//front side
glPushMatrix();
glBegin(GL_QUADS);
{
glColor3f(0.0f,0.0f,1.0f); //blue
glVertex3f(posX + radius, posY + radius, posZ + radius);
glVertex3f(posX - radius, posY + radius, posZ + radius);
glVertex3f(posX - radius, posY - radius, posZ + radius);
glVertex3f(posX + radius, posY - radius, posZ + radius);
}
glEnd();
glPopMatrix();
//back side
glPushMatrix();
glBegin(GL_QUADS);
{
glColor3f(0.0f,1.0f,0.0f); // green
glVertex3f(posX + radius, posY - radius, posZ - radius);
glVertex3f(posX - radius, posY - radius, posZ - radius);
glVertex3f(posX - radius, posY + radius, posZ - radius);
glVertex3f(posX + radius, posY + radius, posZ - radius);
}
glEnd();
glPopMatrix();
}
Вот мой преобразованный код из тестового кода hello world, все ли это выглядит правильно?:
public static void HelloWorld() {
BroadphaseInterface broadphase = new DbvtBroadphase();
DefaultCollisionConfiguration collisionConfiguration = new DefaultCollisionConfiguration();
CollisionDispatcher dispatcher = new CollisionDispatcher(collisionConfiguration);
SequentialImpulseConstraintSolver solver = new SequentialImpulseConstraintSolver();
DiscreteDynamicsWorld dynamicsWorld = new DiscreteDynamicsWorld(dispatcher, broadphase, solver, collisionConfiguration);
// set the gravity of our world
dynamicsWorld.setGravity(new Vector3f(0, -10, 0));
// setup our collision shapes
CollisionShape groundShape = new StaticPlaneShape(new Vector3f(0, 1, 0), 1);
CollisionShape fallShape = new SphereShape(1);
// setup the motion state
DefaultMotionState groundMotionState = new DefaultMotionState(new Transform(new Matrix4f(new Quat4f(0, 0, 0, 1), new Vector3f(0, -1, 0), 1.0f)));
RigidBodyConstructionInfo groundRigidBodyCI = new RigidBodyConstructionInfo(0, groundMotionState, groundShape, new Vector3f(0,0,0));
RigidBody groundRigidBody = new RigidBody(groundRigidBodyCI);
dynamicsWorld.addRigidBody(groundRigidBody); // add our ground to the dynamic world..
// setup the motion state for the ball
DefaultMotionState fallMotionState = new DefaultMotionState(new Transform(new Matrix4f(new Quat4f(0, 0, 0, 1), new Vector3f(0, 50, 0), 1.0f)));
//This we're going to give mass so it responds to gravity
int mass = 1;
Vector3f fallInertia = new Vector3f(0,0,0);
fallShape.calculateLocalInertia(mass,fallInertia);
RigidBodyConstructionInfo fallRigidBodyCI = new RigidBodyConstructionInfo(mass,fallMotionState,fallShape,fallInertia);
RigidBody fallRigidBody = new RigidBody(fallRigidBodyCI);
//now we add it to our physics simulation
dynamicsWorld.addRigidBody(fallRigidBody);
for (int i=0 ; i<300 ; i++) {
dynamicsWorld.stepSimulation(1/60.f, 10);
Transform trans = new Transform();
fallRigidBody.getMotionState().getWorldTransform(trans);
System.out.println("sphere height: " + trans.origin.y);
}
}
3 ответа
Пример кода для jBullet HelloWorld:
public static void HelloWorld() {
BroadphaseInterface broadphase = new DbvtBroadphase();
DefaultCollisionConfiguration collisionConfiguration = new DefaultCollisionConfiguration();
CollisionDispatcher dispatcher = new CollisionDispatcher(collisionConfiguration);
SequentialImpulseConstraintSolver solver = new SequentialImpulseConstraintSolver();
DiscreteDynamicsWorld dynamicsWorld = new DiscreteDynamicsWorld(dispatcher, broadphase, solver, collisionConfiguration);
// set the gravity of our world
dynamicsWorld.setGravity(new Vector3f(0, -10, 0));
// setup our collision shapes
CollisionShape groundShape = new StaticPlaneShape(new Vector3f(0, 1, 0), 1);
CollisionShape fallShape = new SphereShape(1);
// setup the motion state
DefaultMotionState groundMotionState = new DefaultMotionState(new Transform(new Matrix4f(new Quat4f(0, 0, 0, 1), new Vector3f(0, -1, 0), 1.0f)));
RigidBodyConstructionInfo groundRigidBodyCI = new RigidBodyConstructionInfo(0, groundMotionState, groundShape, new Vector3f(0,0,0));
RigidBody groundRigidBody = new RigidBody(groundRigidBodyCI);
dynamicsWorld.addRigidBody(groundRigidBody); // add our ground to the dynamic world..
// setup the motion state for the ball
DefaultMotionState fallMotionState = new DefaultMotionState(new Transform(new Matrix4f(new Quat4f(0, 0, 0, 1), new Vector3f(0, 50, 0), 1.0f)));
//This we're going to give mass so it responds to gravity
int mass = 1;
Vector3f fallInertia = new Vector3f(0,0,0);
fallShape.calculateLocalInertia(mass,fallInertia);
RigidBodyConstructionInfo fallRigidBodyCI = new RigidBodyConstructionInfo(mass,fallMotionState,fallShape,fallInertia);
RigidBody fallRigidBody = new RigidBody(fallRigidBodyCI);
//now we add it to our physics simulation
dynamicsWorld.addRigidBody(fallRigidBody);
for (int i=0 ; i<300 ; i++) {
dynamicsWorld.stepSimulation(1/60.f, 10);
Transform trans = new Transform();
fallRigidBody.getMotionState().getWorldTransform(trans);
System.out.println("sphere height: " + trans.origin.y);
}
}
Давайте посмотрим на пример кода из учебника, с которым вы работаете. Я добавил комментарии в код, чтобы вы могли лучше узнать, что происходит и как вы должны настроить свой код. Важно отметить, что код ниже на самом деле ничего не показывает. По сути, он просто создает физический объект, землю и позволяет объекту упасть на землю, выводя высоту объекта, когда он проходит через симуляцию.
int main (void)
{
//Set up all the required objects and controllers for simulating the physics
//all this stuff would actually go into whatever initialize function you have
btBroadphaseInterface* broadphase = new btDbvtBroadphase();
btDefaultCollisionConfiguration* collisionConfiguration = new btDefaultCollisionConfiguration();
btCollisionDispatcher* dispatcher = new btCollisionDispatcher(collisionConfiguration);
btSequentialImpulseConstraintSolver* solver = new btSequentialImpulseConstraintSolver;
btDiscreteDynamicsWorld* dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,broadphase,solver,collisionConfiguration);
dynamicsWorld->setGravity(btVector3(0,-10,0));
//Create our physics objects, the planeShape is the ground
btCollisionShape* groundShape = new btStaticPlaneShape(btVector3(0,1,0),1);
//A sphere that will be dropping to the ground,
btCollisionShape* fallShape = new btSphereShape(1);
//Create motion states for our objects
//First the ground object. It will be in the XZ plane at -1 Y
//note that we're not giving it any mass
//zero mass in a physics simulation means it won't move when collided with
//it also means that it won't respond to gravity
btDefaultMotionState* groundMotionState = new btDefaultMotionState(btTransform(btQuaternion(0,0,0,1),btVector3(0,-1,0)));
btRigidBody::btRigidBodyConstructionInfo
groundRigidBodyCI(0,groundMotionState,groundShape,btVector3(0,0,0));
btRigidBody* groundRigidBody = new btRigidBody(groundRigidBodyCI);
//Add the ground to the simulation
dynamicsWorld->addRigidBody(groundRigidBody);
//now set up the motion state for our sphere, we'll put it at 50 Y
btDefaultMotionState* fallMotionState =
new btDefaultMotionState(btTransform(btQuaternion(0,0,0,1),btVector3(0,50,0)));
//This we're going to give mass so it responds to gravity
btScalar mass = 1;
btVector3 fallInertia(0,0,0);
fallShape->calculateLocalInertia(mass,fallInertia);
btRigidBody::btRigidBodyConstructionInfo fallRigidBodyCI(mass,fallMotionState,fallShape,fallInertia);
btRigidBody* fallRigidBody = new btRigidBody(fallRigidBodyCI);
//now we add it to our physics simulation
dynamicsWorld->addRigidBody(fallRigidBody);
//Here's where the magic happens. The physics simulation is stepped.
//for each step, we're going to get the balls current position and write it out.
//Everything inside this for loop would actually go into your *update* loop
//your update loop would step the physics simulation
//after stepping the simulation, you get the positions of your physics bodies
//and make sure your object positions match those.
for (int i=0 ; i<300 ; i++) {
dynamicsWorld->stepSimulation(1/60.f,10);
btTransform trans;
fallRigidBody->getMotionState()->getWorldTransform(trans);
//so you would take `trans` and use it to set the position of your cube
//then your cube position would be updated to the same position as
//this physics object that's representing it.
std::cout << "sphere height: " << trans.getOrigin().getY() << std::endl;
}
//everything else is clean up
dynamicsWorld->removeRigidBody(fallRigidBody);
delete fallRigidBody->getMotionState();
delete fallRigidBody;
dynamicsWorld->removeRigidBody(groundRigidBody);
delete groundRigidBody->getMotionState();
delete groundRigidBody;
delete fallShape;
delete groundShape;
delete dynamicsWorld;
delete solver;
delete collisionConfiguration;
delete dispatcher;
delete broadphase;
return 0;
}
По сути, вы хотите воссоздать свой игровой мир в симуляторе физики. Затем, когда вы переходите к симуляции физики, вы обновляете игровой мир новыми позициями симуляции. Физический симулятор говорит вам, как перемещать игровые объекты так, чтобы они выглядели так, как будто они сталкиваются друг с другом.
Таким образом, для вашей настройки, вы бы переместить материал в for
цикл в вашем цикле обновления. Затем вместо того, чтобы записывать положение сферы на консоль, вы обновляете posX
, posY
, posZ
с положением сферы. Теперь ваш куб движется так же, как сфера в симуляции!
Так что просто последний толчок в точку. Вы создаете два мира. Та, где вы рисуете детальную графику, и та, где у вас есть простые фигуры, представляющие физические фигуры ваших детальных графических объектов. Мир физики моделирует взаимодействия всех ваших объектов, а детали графических объектов просто отражают положение этих простых физических форм.
Надеюсь, это проясняет ситуацию.
Вы проверили демоверсии jMonkeyEngine и пример кода?
Многие из них используют jBullet в качестве физического движка, с которым определенно стоит поиграть.