White lines are bullet debug lines.
Red arrow is where the forward dir is supposed to be.
Red lines is where the front of the object is supposed to be.
Green arrow is where the forward dir really is, at least in this direction the object is going to.
Ogre mesh has inverted rotation so it faces the right direction.
Some code:
Code: Select all
Ogre::Entity* ent = pSceneMgr->createEntity("SinbadBody", "Sinbad.mesh");
Ogre::SceneNode* sphereNode = pSceneMgr->getRootSceneNode()->createChildSceneNode();
sphereNode->attachObject(ent);
Ogre::Vector3 halfsize = ent->getBoundingBox().getHalfSize();
ent->setCastShadows(true);
sphereNode->setPosition(0,20,0);
btConvexShape* capsule = new btBoxShape(ToBullet(halfsize));
characterBody = pBullet->addGhostObject(sphereNode->getPosition(), capsule, sphereNode);
btScalar stepHeight = btScalar(0.35);
Character = new btKinematicCharacterController(characterBody,capsule,stepHeight);
Character->setJumpSpeed(15);
pBullet->getWorld()->addCollisionObject(characterBody,btBroadphaseProxy::CharacterFilter, btBroadphaseProxy::StaticFilter|btBroadphaseProxy::DefaultFilter);
pBullet->getWorld()->addAction(Character);
Code: Select all
//character
Ogre::SceneNode* characterNode = (Ogre::SceneNode*)(characterBody->getUserPointer());
bool forward = false, backward = false, left = false, right = false, jump = false;
if(pKeyboard->isKeyDown(OIS::KC_A))
{
left = true;
}
else if(pKeyboard->isKeyDown(OIS::KC_D))
{
right = true;
}
if(pKeyboard->isKeyDown(OIS::KC_W))
{
forward = true;
}
else if(pKeyboard->isKeyDown(OIS::KC_S))
{
backward = true;
}
if(pKeyboard->isKeyDown(OIS::KC_SPACE))
{
jump = true;
}
btTransform xform;
xform = characterBody->getWorldTransform();
btVector3 forwardDir = xform.getBasis()[2];
btVector3 upDir = xform.getBasis()[1];
btVector3 strafeDir = xform.getBasis()[1];
forwardDir.normalized();
upDir.normalized();
strafeDir.normalized();
btVector3 walkDirection(0,0,0);
btScalar walkVelocity(1.1*8.0);// 4 km/h -> 1.1 m/s
btScalar walkSpeed(walkVelocity*(DeltaTime/1000.0f));
Ogre::SceneNode* node = static_cast<Ogre::SceneNode*>(characterBody->getUserPointer());
if(left)
{
turnAngle -= DeltaTime * 0.003f;
}
if(right)
{
turnAngle += DeltaTime * 0.003f;
}
xform.setRotation(btQuaternion (btVector3(0.0, 1.0, 0.0), turnAngle));
characterBody->setWorldTransform (xform);
//here is inverted(?) turnAngle of ogre mesh, so it faces the right direction that the bullet kinematic character is going to
node->setOrientation(Ogre::Quaternion(-(Ogre::Radian)turnAngle, Ogre::Vector3(0.0, 1.0, 0.0)));
if(forward)
{
walkDirection += forwardDir;
}
if(backward)
{
walkDirection -= forwardDir;
}
if(jump && Character->canJump())
{
Character->jump();
}
Character->setWalkDirection(walkDirection * walkSpeed);
Code: Select all
World->stepSimulation(Delta, 60);
for(list<btRigidBody*>::iterator It = Objects.begin(); It != Objects.end(); ++It)
{
Ogre::SceneNode* node = static_cast<Ogre::SceneNode*>((*It)->getUserPointer());
btVector3 Point = (*It)->getCenterOfMassPosition();
node->setPosition(Ogre::Vector3((float)Point[0], (float)Point[1], (float)Point[2]));
btQuaternion btq = (*It)->getOrientation();
Ogre::Quaternion quart = Ogre::Quaternion(btq.w(),btq.x(),btq.y(),btq.z());
node->setOrientation(quart);
}
for(list<btPairCachingGhostObject*>::iterator it = GhostObjects.begin(); it != GhostObjects.end(); ++it)
{
Ogre::SceneNode* node = static_cast<Ogre::SceneNode*>((*it)->getUserPointer());
btVector3 Point = (*it)->getWorldTransform().getOrigin();
node->setPosition(Ogre::Vector3(Point[0], Point[1], Point[2]));
}
World->debugDrawWorld();
I did some more tests and here is the code that works perfectly, but i get forward dir not from bullet but from ogre, so maybe i did something wrong with bullet or the forward dir from bullet is wrong:
Code: Select all
btTransform xform;
xform = characterBody->getWorldTransform();
btVector3 walkDirection(0,0,0);
btScalar walkVelocity(1.1*8.0);// 4 km/h -> 1.1 m/s
btScalar walkSpeed(walkVelocity*(DeltaTime/1000.0f));
Ogre::SceneNode* node = static_cast<Ogre::SceneNode*>(characterBody->getUserPointer());
btVector3 forwardDir = ToBullet(node->getOrientation() * Ogre::Vector3(0, 0, 1));
forwardDir.normalized();
if(left)
{
turnAngle += DeltaTime * 0.003f;
}
if(right)
{
turnAngle -= DeltaTime * 0.003f;
}
xform.setRotation(btQuaternion (btVector3(0.0, 1.0, 0.0), turnAngle));
characterBody->setWorldTransform (xform);
if(forward)
{
walkDirection = forwardDir;
}
if(backward)
{
walkDirection = -forwardDir;
}
if(jump && Character->canJump())
{
Character->jump();
}
Character->setWalkDirection(walkDirection * walkSpeed);
Code: Select all
for(list<btPairCachingGhostObject*>::iterator it = GhostObjects.begin(); it != GhostObjects.end(); ++it)
{
Ogre::SceneNode* node = static_cast<Ogre::SceneNode*>((*it)->getUserPointer());
btVector3 Point = (*it)->getWorldTransform().getOrigin();
node->setPosition(Ogre::Vector3(Point.getX(), Point.getY(), Point.getZ()));
btQuaternion btq = (*it)->getWorldTransform().getRotation();
Ogre::Quaternion quart = Ogre::Quaternion(btq.w(),btq.x(),btq.y(),btq.z());
node->setOrientation(quart);
}