right way to move a body?

Adriano
Posts: 6
Joined: Fri Mar 08, 2013 9:53 am

right way to move a body?

Post by Adriano »

Hi,
I tried in the last weeks to move an object with a mouse and interact with other bodies.

I have a compound object (2 walls) and it is kinematic, so I can move this body with the mouse.

Image

After setting setCcdMotionThreshold, I am able to set a infinity force to a ball and this ball will bounce on a wall/kinematic object (even if the wall is really thin).

I can also move the walls and the balls are moved. But if I move the walls too fast, I can move the walls through the balls.

So my question is:
- what is the right way to move the walls, without this effect?

I tried to set a sliderconstraint, so I move the kinematic object and on the slider I attach a rigid body. It was better, but I don't know if this is the right way.

The wiki says it is a one way collision. So a solid body can collide with a kinematic object but a kinematic object hasn't a collision detection with the dynamic objects? I read a lot of threads and I always see that it is possible to move kinematic objects for a direct interaction with the world.

I can upload the exe file if this can help (it is a dx10/9 executable).

I don't know if this can help, but here the code for the creation of the objects (I use the btCollisionObject::CF_KINEMATIC_OBJECT flag):

Code: Select all

double dWallDim = 0.2;
		double dWallH = 2.0;
		btCollisionShape* colShape1 = new btBoxShape(btVector3(dWallDim, dWallH*0.5, 2.5)); // |
		btCollisionShape* colShape2 = new btBoxShape(btVector3(dWallDim, dWallH*0.5, 2.5)); //    |
		
		btCompoundShape* colCompoundShape = new btCompoundShape();

		btTransform localTrans1;
		localTrans1.setIdentity();
		localTrans1.setOrigin(btVector3(-0.85 - dWallDim, dWallH*0.5, 0.0));

		btTransform localTrans2;
		localTrans2.setIdentity();
		localTrans2.setOrigin(btVector3(0.85 + dWallDim, dWallH*0.5, 0.0));

		colCompoundShape->addChildShape(localTrans1, colShape1);
		colCompoundShape->addChildShape(localTrans2, colShape2);

		collisionShapes.push_back(colCompoundShape);
		
		/// Create Dynamic Objects
		btTransform startTransform;
		startTransform.setIdentity();

		btScalar	mass(0.f);
		
		//rigidbody is dynamic if and only if mass is non zero, otherwise static
		bool isDynamic = (mass != 0.f);
		
		btVector3 localInertia(0,0,0);
		if (isDynamic)
			colCompoundShape->calculateLocalInertia(mass,localInertia);
		
		startTransform.setOrigin(btVector3(0.0, -0.5, 0.0));				

		g_myMotionState = new btDefaultMotionState(startTransform);
		btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,g_myMotionState,colCompoundShape,localInertia);
		g_slider = new btRigidBody(rbInfo);

		g_slider->setCollisionFlags( g_slider->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); 
		g_slider->setActivationState(DISABLE_DEACTIVATION); 
		
		g_slider->setContactProcessingThreshold(btScalar(0.02));
		g_slider->setCcdMotionThreshold(btScalar(0.00001));
		g_slider->setCcdSweptSphereRadius(btScalar(0.01));

		g_pDynamicsWorld->addRigidBody(g_slider);
and some balls:

Code: Select all

btCollisionShape* colShape = new btSphereShape(btScalar(g_ballDim));
		collisionShapes.push_back(colShape);

		/// Create Dynamic Objects
		btTransform startTransform;
		startTransform.setIdentity();

		btScalar	mass(1.7f);

		//rigidbody is dynamic if and only if mass is non zero, otherwise static
		bool isDynamic = (mass != 0.f);

		btVector3 localInertia(0,0,0);
		if (isDynamic)
			colShape->calculateLocalInertia(mass,localInertia);

		startTransform.setOrigin(btVector3(-7.5 + i * 2.5,5.0,0.0));
		
		//using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects
		btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform);
		btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,colShape,localInertia);
		g_ball[i] = new btRigidBody(rbInfo);
		
		g_ball[i]->setFriction(btScalar(0.005));
		g_ball[i]->setRestitution(btScalar(0.8));
		g_ball[i]->setDamping(btScalar(0.0), btScalar(0.0));
		g_ball[i]->setHitFraction(btScalar(2.0));
		g_ball[i]->setRollingFriction(btScalar(0.001));
		
		g_ball[i]->setContactProcessingThreshold(btScalar(0.04));
		g_ball[i]->setCcdMotionThreshold(btScalar(0.0001));
		g_ball[i]->setActivationState(DISABLE_DEACTIVATION);
		

		g_pDynamicsWorld->addRigidBody(g_ball[i]);
The code for each frame and to update the world:

Code: Select all

double dMove;
		btTransform slTr;

		slTr = g_slider->getWorldTransform();
		dMove = iMoveTo * 0.015625 * 0.022 * (325.0/240.0); // convert mouse/joystick position to a position
		dMove = (dMove - slTr.getOrigin().x());

		slTr.setOrigin(slTr.getOrigin() + btVector3(dMove,0,0));
		g_slider->setWorldTransform(slTr); // set slider (2 walls) position
		//g_slider->setInterpolationWorldTransform(slTr);
		//g_pDynamicsWorld->updateSingleAabb(g_slider);
				
		g_myMotionState->getWorldTransform(slTr);
		slTr.setOrigin(slTr.getOrigin() + btVector3(dMove,0,0));
		g_myMotionState->setWorldTransform(slTr);
		
		g_pDynamicsWorld->stepSimulation(fDelayInSeconds, 20);
You do not have the required permissions to view the files attached to this post.
Adriano
Posts: 6
Joined: Fri Mar 08, 2013 9:53 am

Re: right way to move a body?

Post by Adriano »

I can reproduce this effect also with the demos.

If I move an object with the mouse really fast, I can penetrate through other objects.

I think the only way with bullet is with ray casting and move the objects manually (has nothing to do with physics engine, but if the physic engine fails, this is probably the best way).
STTrife
Posts: 109
Joined: Tue May 01, 2012 10:42 am

Re: right way to move a body?

Post by STTrife »

Probably not the best solution: but if you detect that you move the walls very far within a single frame, you could start making substeps, where the walls move a maximum amount of distance, so that the ball cannot escape the walls.. So basically depending how far you need to move the walls according to the mouse, increase the framerate of bullet, and in the tick-callback move the walls only part of the distance that you actually need to move it according to the mouse movement.

But there might be more elegant solutions.. not sure