Physics Simulation Forum

 

All times are UTC




Post new topic Reply to topic  [ 8 posts ] 
Author Message
PostPosted: Wed Feb 01, 2012 8:30 am 
Offline

Joined: Mon Jul 18, 2005 7:16 am
Posts: 13
Hi all,

I'm currently using Bullet (in combination with my 3D engine Crystal Space) and I would like to have realistic grabbing of objects. I don't know if any of you are aware of the games Penumbra or Amnesia: The Dark Descent? In that game you have a first person camera and you can grab objects by clicking on them. This is done in a realistic way. For example, to open a door you simply grab the door and then move backwards or forwards. The door will open or close depending on the speed with which you move your mouse. Same for drawers. You can pull out a drawer just the way that you would expect. You can start pulling and stop halfway and then continue or go back. And so on. Same for levers, turning wheels and so on. It all feels very realistic and very nice to use.

So I'm trying to achieve the same. I got a very similar result by creating a pivot joint using btPoint2PointConstraint and dynamicWorld->addConstraint(). This works great.

However there is a small problem in combination with btGeneric6DofConstraint. When the player grabs an object that is connected to such a 6DOF constraint then I guess bullet doesn't know which constraint to fully honor. The problem is that the 6DOF constraint is slightly violated (and so is the pivot joint) because the player is dragging a bit too far. So if you have such a constraint to simulate a door then the player can slightly rotate the door in wrong directions. I guess the problem is that bullet doesn't know which of the two constraints (6dof and pivot) to honor completely so it probably decides to honor both a bit.

I would like the 6DOF constraints to be strict. The player should not be able to pull the door out of its hinges. How can I achieve that? Is there a way I can create a more loosely coupled pivot joint?

In addition, a related problem (I think) is how to make grabbing weight dependend. A heavier object should be harder to grab and if it is very heavy then the player should only be able to drag it on the floor but not lift it in the air. With the pivot joint there is no such restriction. The player can lift anything.

Any advice here?

Thanks!


Top
 Profile  
 
PostPosted: Thu Feb 02, 2012 12:36 am 
Offline
Site Admin
User avatar

Joined: Sun Jun 26, 2005 6:43 pm
Posts: 3895
Location: California, USA
You can set a maximum impulse applied by the btPoint2PointConstraint, it might deal with both cases.

Code:
p2p->m_setting.m_impulseClamp = 30.f;
p2p->m_setting.m_tau = 0.001f;


Can you try it (and tweak the values)?


Top
 Profile  
 
PostPosted: Thu Feb 02, 2012 5:27 am 
Offline

Joined: Mon Jul 18, 2005 7:16 am
Posts: 13
Hmm it seems these settings do improve matters however not fully. No matter what parameters I set it is still possible to slightly get the door out of its hinges and if you pull long enough you will eventually get bigger problems. I'm thinking this might fundamentally not be the right way to handle this. I would like the door hinges to be strict. There should be no way that the door gets wrongly positioned. No matter how hard one is pulling at the door.

So any other things I could try?

Thanks!


Top
 Profile  
 
PostPosted: Fri Feb 10, 2012 1:47 pm 
Offline

Joined: Fri Feb 10, 2012 1:28 pm
Posts: 3
@jorrit

I'm currently doing the same thing you are, and I have some question regarding how you did the p2p-constraint, as my way of doing it give some... funny results? :) I'm attaching the "lift" object to a static collisionObject in (0,0,0), and setting the static's object pivot-point to be shortly in front of the player. This was the best solution, as the player-body is dynamic, so for instance smashing a crate hard into the ground would send the player skywards.

Anyway, this method makes object at times intersect with walls, floors and other objects giving very jaggy, ugly and unrealistic results. Could you give me some info on how you did this? :)

Pimms


Top
 Profile  
 
PostPosted: Fri Feb 10, 2012 2:06 pm 
Offline

Joined: Mon Jul 18, 2005 7:16 am
Posts: 13
Pimms wrote:
@jorrit

I'm currently doing the same thing you are, and I have some question regarding how you did the p2p-constraint, as my way of doing it give some... funny results? :) I'm attaching the "lift" object to a static collisionObject in (0,0,0), and setting the static's object pivot-point to be shortly in front of the player. This was the best solution, as the player-body is dynamic, so for instance smashing a crate hard into the ground would send the player skywards.

Anyway, this method makes object at times intersect with walls, floors and other objects giving very jaggy, ugly and unrealistic results. Could you give me some info on how you did this? :)

Pimms


Well that's my problem. I haven't really found a solution to this yet. I could minimize the problem by playing with the impulseClamp values (setting them very low) but I couldn't get the problem to completely disappear yet. I'm still hunting for a good solution here.

Greetings,


Top
 Profile  
 
PostPosted: Fri Feb 10, 2012 4:13 pm 
Offline

Joined: Fri Feb 10, 2012 1:28 pm
Posts: 3
I'm fairly noob at Bullet, but a few points to go by as I've noticed in Penumbra / Amnesia:

- Objects appear to be hung from a rope, thus giving the feeling of weight. Notice how heavier objects especially in P. sort of dangle when being held still.
- This "invisible rope" supports being stretched, thus avoiding awkward jittery motion.

The games are built upon the HPL1/2 engine, which implements ODE. As far as I can tell from the documentation (flame if wrong), there is no native rope-joint in ODE.

It would seem to me that the solution might lay in identifying (i.e., scan the transform each frame) the jittery motion in a constraint of any kind, and upon noticing revert the transform of the body to the last working transform. As mentioned, I have little to no insight in how Bullet works internally, but this makes sense to me.


Top
 Profile  
 
PostPosted: Fri Feb 10, 2012 4:22 pm 
Offline

Joined: Sun Jan 01, 2012 7:37 pm
Posts: 55
HPL 1 / 2 use Newton Dynamics, not ODE.

You may be able to glean how they did it from their sources.
https://github.com/FrictionalGames/HPL1Engine


Top
 Profile  
 
PostPosted: Sat Feb 11, 2012 12:08 pm 
Offline

Joined: Fri Feb 10, 2012 1:28 pm
Posts: 3
Ops, messed up on which engine implements what. Anyways, I looked through the most obvious places to eventually put a "lift"-joint, and I couldn't find anything.

Anyways, using Ogre::Quaternion (for multiplication with vectors), I managed to get a very smooth lifting-system. Goes something like this:

Upon interaction (lifting):
Code:
                        //Calculate the direction vector
                        mConTime = 0;
         Ogre::Vector3 v = mPlayer->camYNode->getOrientation() *
            mPlayer->camXNode->getOrientation() * vp(0,0,1);
                       
         mConBody = (btRigidBody*)mTarget;   
         mConBody->activate();

         //Create an ogre Quaternion (btQuaternion has trouble with vector3 mult)
         btVector3 conRot(   mConBody->getOrientation().getX(),
                        mConBody->getOrientation().getY(),
                        mConBody->getOrientation().getZ());
         Ogre::Quaternion oq(mConBody->getOrientation().getW(), conRot.x(), conRot.y(), conRot.z());

         //Get the local vector in the targetted shape
         Ogre::Vector3 p = btToOg(mTargetPt - mConBody->getWorldTransform().getOrigin());
         //Multiply it with the inverse of the quaternion
         p = oq.Inverse() * p;
         mCon = new btPoint2PointConstraint(*mConBody, *mBaseBody, ogToBt(p), btVector3(0,0,0));

         //Calculate the distance
         Ogre::Vector3 a = btToOg( mTargetPt );
         Ogre::Vector3 b = mPlayer->mainNode->getPosition();
         mConDist = sqrt( pow(b.x-a.x,2) + pow(b.y-a.y,2) + pow(b.z-a.z,2) );
         
         mWorld->addConstraint(mCon);


Called every frame:
Code:
        if (mCon)
   {
      if (!mCon->isEnabled())
      {
         dismiss();
         return;
      }

      Ogre::Vector3 v = mPlayer->camYNode->getOrientation() *
            mPlayer->camXNode->getOrientation() * vp(0,0,1);
      Ogre::Vector3 f = vp(v.x,v.y,v.z)*-mConDist + mPlayer->mainNode->getPosition();

      mConTime += dt;
      if (mConTime > 0.1f)
      {
         mCon->setBreakingImpulseThreshold(1500);
      }

      mCon->setPivotB( ogToBt( f ) );
   }


Hope this is of any help to anyone :)


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 8 posts ] 

All times are UTC


Who is online

Users browsing this forum: Bing [Bot] and 4 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group